diff -Naur xen-unstable.hg-pristine/extras/mini-os/blkfront.c xen-unstable.hg/extras/mini-os/blkfront.c --- xen-unstable.hg-pristine/extras/mini-os/blkfront.c 2011-02-25 13:28:13.000000000 -0500 +++ xen-unstable.hg/extras/mini-os/blkfront.c 2011-02-25 13:21:29.000000000 -0500 @@ -546,9 +546,121 @@ #ifdef HAVE_LIBC int blkfront_open(struct blkfront_dev *dev) { + /* Silently prevent multiple opens */ + if(dev->fd != -1) { + return dev->fd; + } dev->fd = alloc_fd(FTYPE_BLK); printk("blk_open(%s) -> %d\n", dev->nodename, dev->fd); files[dev->fd].blk.dev = dev; + files[dev->fd].blk.offset = 0; return dev->fd; } + +int blkfront_posix_rwop(int fd, uint8_t* buf, size_t count, int write) +{ + struct blkfront_dev* dev = files[fd].blk.dev; + off_t offset = files[fd].blk.offset; + struct blkfront_aiocb aiocb; + unsigned long long disksize = dev->info.sectors * dev->info.sector_size; + unsigned int blocksize = dev->info.sector_size; + + int blknum; + int blkoff; + size_t bytes; + int rc = 0; + + /* RW 0 bytes is just a NOP */ + if(count == 0) { + return 0; + } + /* Check for NULL buffer */ + if( buf == NULL ) { + errno = EFAULT; + return -1; + } + /* Write mode checks */ + if(write) { + /*Make sure we have write permission */ + if(dev->info.info & VDISK_READONLY || dev->info.mode != O_RDWR) { + errno = EACCES; + return -1; + } + /*Make sure disk is big enough for this write */ + if(offset + count > disksize) { + errno = ENOSPC; + return -1; + } + } + /* Read mode checks */ + else + { + /*If the requested read is bigger than the disk, just + * read as much as we can until the end */ + if(offset + count > disksize) { + count = offset >= disksize ? 0 : disksize - offset; + } + } + /* Determine which block to start at and which offset inside of it */ + blknum = offset / blocksize; + blkoff = offset % blocksize; + + /* Setup aiocb block object */ + aiocb.aio_dev = dev; + aiocb.aio_buf = _xmalloc(blocksize, dev->info.sector_size); + aiocb.aio_nbytes = blocksize; + aiocb.aio_offset = blknum * blocksize; + aiocb.aio_cb = NULL; + aiocb.data = NULL; + + rc = count; + while(count > 0) { + /* determine how many bytes to read/write from/to the current block buffer */ + bytes = count > (blocksize - blkoff) ? blocksize - blkoff : count; + + /* read operation */ + if(!write) { + aiocb.aio_cb = NULL; + blkfront_read(&aiocb); + memcpy(buf, &aiocb.aio_buf[blkoff], bytes); + } + /* Write operation */ + else { + /* If we're writing a partial block, we need to read the current contents first + * so we don't overwrite the extra bits with garbage */ + if(blkoff != 0 || bytes < blocksize) { + aiocb.aio_cb = NULL; + blkfront_read(&aiocb); + } + aiocb.aio_cb = NULL; + memcpy(&aiocb.aio_buf[blkoff], buf, bytes); + blkfront_write(&aiocb); + } + /* Will start at beginning of all remaining blocks */ + blkoff = 0; + + /* Increment counters and continue */ + count -= bytes; + buf += bytes; + aiocb.aio_offset += blocksize; + } + + free(aiocb.aio_buf); + files[fd].blk.offset += rc; + return rc; + +} + +int blkfront_posix_fstat(int fd, struct stat* buf) +{ + struct blkfront_dev* dev = files[fd].blk.dev; + + buf->st_mode = dev->info.mode; + buf->st_uid = 0; + buf->st_gid = 0; + buf->st_size = dev->info.sectors * dev->info.sector_size; + buf->st_atime = buf->st_mtime = buf->st_ctime = time(NULL); + + return 0; +} #endif diff -Naur xen-unstable.hg-pristine/extras/mini-os/include/blkfront.h xen-unstable.hg/extras/mini-os/include/blkfront.h --- xen-unstable.hg-pristine/extras/mini-os/include/blkfront.h 2011-02-25 13:28:13.000000000 -0500 +++ xen-unstable.hg/extras/mini-os/include/blkfront.h 2011-02-25 13:21:29.000000000 -0500 @@ -28,7 +28,17 @@ }; struct blkfront_dev *init_blkfront(char *nodename, struct blkfront_info *info); #ifdef HAVE_LIBC +#include +/* POSIX IO functions: + * use blkfront_open() to get a file descriptor to the block device + * Don't use the other blkfront posix functions here directly, instead use + * read(), write(), lseek() and fstat() on the file descriptor + */ int blkfront_open(struct blkfront_dev *dev); +int blkfront_posix_rwop(int fd, uint8_t* buf, size_t count, int write); +#define blkfront_posix_write(fd, buf, count) blkfront_posix_rwop(fd, (uint8_t*)buf, count, 1) +#define blkfront_posix_read(fd, buf, count) blkfront_posix_rwop(fd, (uint8_t*)buf, count, 0) +int blkfront_posix_fstat(int fd, struct stat* buf); #endif void blkfront_aio(struct blkfront_aiocb *aiocbp, int write); #define blkfront_aio_read(aiocbp) blkfront_aio(aiocbp, 0) diff -Naur xen-unstable.hg-pristine/extras/mini-os/lib/sys.c xen-unstable.hg/extras/mini-os/lib/sys.c --- xen-unstable.hg-pristine/extras/mini-os/lib/sys.c 2011-02-25 13:28:13.000000000 -0500 +++ xen-unstable.hg/extras/mini-os/lib/sys.c 2011-02-25 13:27:36.000000000 -0500 @@ -270,6 +270,8 @@ } return ret * sizeof(union xenfb_in_event); } + case FTYPE_BLK: + return blkfront_posix_read(fd, buf, nbytes); default: break; } @@ -300,6 +302,8 @@ case FTYPE_TAP: netfront_xmit(files[fd].tap.dev, (void*) buf, nbytes); return nbytes; + case FTYPE_BLK: + return blkfront_posix_write(fd, buf, nbytes); default: break; } @@ -310,8 +314,35 @@ off_t lseek(int fd, off_t offset, int whence) { - errno = ESPIPE; - return (off_t) -1; + switch(files[fd].type) { + case FTYPE_BLK: + switch (whence) { + case SEEK_SET: + files[fd].file.offset = offset; + break; + case SEEK_CUR: + files[fd].file.offset += offset; + break; + case SEEK_END: + { + struct stat st; + int ret; + ret = fstat(fd, &st); + if (ret) + return -1; + files[fd].file.offset = st.st_size + offset; + break; + } + default: + errno = EINVAL; + return -1; + } + return files[fd].file.offset; + break; + default: /* Not implemented on this FTYPE */ + errno = ESPIPE; + return (off_t) -1; + } } int fsync(int fd) { @@ -412,6 +445,8 @@ buf->st_ctime = time(NULL); return 0; } + case FTYPE_BLK: + return blkfront_posix_fstat(fd, buf); default: break; }