/* * s5fs_dirtypage: * A hook; an attempt is being made to dirty the page * belonging to 'vnode' that contains 'offset'. (If the * underlying fs supports sparse blocks/pages, and the page * containing this offset is currently sparse, this is * where an attempt should be made to allocate a block in * the underlying fs for that block/page). Return zero on * success and nonzero otherwise. * param vnode: the pointer to the vnode object * param offset: the arbitrary offset of that file (bytes offset) * return: the block number or 0; negative number for failure */ static int s5fs_dirtypage(vnode_t *vnode, off_t offset) { dbg(DBG_S5FS, "{\n"); KASSERT(vnode != NULL); int disk_number = 0; int sparse = 0; if ((sparse = s5_seek_to_block(vnode, offset, 0)) < 0) { return sparse; } else if (sparse > 0) { /* find the page */ return 0; } if ((disk_number = s5_seek_to_block(vnode, offset, 1)) < 0) { return disk_number; } /* Dirty the page */ s5_dirty_inode(VNODE_TO_S5FS(vnode), VNODE_TO_S5INODE(vnode)); dbg(DBG_S5FS, "}\n"); return 0; }
/* * s5fs_fillpage: * Read the page of 'vnode' containing 'offset' into the * page-aligned and page-sized buffer pointed to by * 'pagebuf'. * param *vnode: the pointer to the vnode object * param offset: the arbitrary offset of that file (bytes offset) * param pagebuf: the buffer for storing the data you have read * return: number of bytes that have been read, or negative number for errors */ static int s5fs_fillpage(vnode_t *vnode, off_t offset, void *pagebuf) { dbg(DBG_S5FS, "{\n"); KASSERT(vnode != NULL); KASSERT(pagebuf != NULL); int disk_number = 0; if ((disk_number = s5_seek_to_block(vnode, offset, 0)) < 0) { return disk_number; } if (disk_number == 0) { memset(pagebuf, 0, PAGE_SIZE); return 0; } /* If the disk_number is zero, ignore pagebuf */ int ret = VNODE_TO_S5FS(vnode)->s5f_bdev->bd_ops->read_block( VNODE_TO_S5FS(vnode)->s5f_bdev, pagebuf, disk_number, 1); dbg(DBG_S5FS, "}\n"); return ret; }
/* * if this offset is NOT within a sparse region of the file * return 0; * * attempt to make the region containing this offset no longer * sparse * - attempt to allocate a free block * - if no free blocks available, return -ENOSPC * - associate this block with the inode; alter the inode as * appropriate * - dirty the page containing this inode * * Much of this can be done with s5_seek_to_block() */ static int s5fs_dirtypage(vnode_t *vnode, off_t offset) { int blocknum = s5_seek_to_block(vnode, offset, 0); switch (blocknum){ case -EFBIG: case -ENOSPC: return blocknum; default: /* do nothing */; } KASSERT(blocknum >= 0 && "forgot to handle an error case"); return (blocknum == 0) ? s5_seek_to_block(vnode, offset, 1) : 0; }
/* * Like fillpage, but for writing. */ static int s5fs_cleanpage(vnode_t *vnode, off_t offset, void *pagebuf) { int blocknum = s5_seek_to_block(vnode, offset, 1); switch (blocknum){ case -EFBIG: case -ENOSPC: return blocknum; default: /* do nothing */; } KASSERT(blocknum > 0 && "forgot to handle an error case"); blockdev_t *bd = ((s5fs_t *) vnode->vn_fs->fs_i)->s5f_bdev; return bd->bd_ops->write_block(bd, (char *) pagebuf, blocknum, 1/*S5_BLOCK_SIZE*/); }
/* * s5fs_cleanpage: * Write the contents of the page-aligned and page-sized * buffer pointed to by 'pagebuf' to the page of 'vnode' * containing 'offset'. * param *vnode: the pointer to the vnode object * param offset: the arbitrary offset of that file (bytes offset) * param pagebuf: the source buffer * return: number of bytes that have been written, or negative number for errors */ static int s5fs_cleanpage(vnode_t *vnode, off_t offset, void *pagebuf) { dbg(DBG_S5FS, "{\n"); KASSERT(vnode != NULL); KASSERT(pagebuf != NULL); /* Alloc */ int disk_number = 0; if ((disk_number = s5_seek_to_block(vnode, offset, 0)) < 0) { return disk_number;/* error */ } /* If the disk_number is zero, ignore pagebuf */ int ret = VNODE_TO_S5FS(vnode)->s5f_bdev->bd_ops->write_block( VNODE_TO_S5FS(vnode)->s5f_bdev, pagebuf, disk_number, 1); dbg(DBG_S5FS, "}\n"); return ret; }
/* * See the comment in vnode.h for what is expected of this function. * * You'll probably want to use s5_seek_to_block and the device's * read_block function. */ static int s5fs_fillpage(vnode_t *vnode, off_t offset, void *pagebuf) { int blocknum = s5_seek_to_block(vnode, offset, 0); switch (blocknum){ case -EFBIG: case -ENOSPC: return blocknum; default: /* do nothing */; } KASSERT(blocknum >= 0 && "forgot to handle an error case"); if (blocknum == 0){ bytedev_t *bd = bytedev_lookup(MEM_ZERO_DEVID); return bd->cd_ops->read(bd, 0, pagebuf, S5_BLOCK_SIZE); } else { blockdev_t *bd = ((s5fs_t *) vnode->vn_fs->fs_i)->s5f_bdev; return bd->bd_ops->read_block(bd, (char *) pagebuf, blocknum, 1/*S5_BLOCK_SIZE*/); } }