📄 inode.c
字号:
void *data){ struct page *page = __read_cache_page(inode, offset, filler, data); int err; if (IS_ERR(page) || PageUptodate(page)) goto out; wait_on_page(page); if (PageUptodate(page)) goto out; set_bit(PG_locked, &page->flags); err = filler(data, page); if (err < 0) { page_cache_release(page); page = ERR_PTR(err); } out: return page;}#endif /* kernels older than 2.2.18 */STATIC intwrapfs_readpage(file_t *file, page_t *page){ int err = 0; inode_t *inode = file->f_dentry->d_inode; inode_t *hidden_inode = itohi(inode); file_t *hidden_file = ftohf(file); page_t *hidden_page; unsigned long page_data, hidden_page_data; print_entry_location(); /* * readpage is called from generic_file_read and the fault handler. * If your file system uses generic_file_read for the read op, it * must implement readpage. */ ASSERT(hidden_inode->i_op != NULL); atomic_inc(&page->count); set_bit(PG_locked, &page->flags); set_bit(PG_free_after, &page->flags); fist_print_page_flags("READPAGE flags (entry)", page); fist_dprint(6, "READPAGE: f_pos:0x%x inode:0x%x i_size:0x%x hidden_inode:0x%x page->inode:0x%x page->offset:%lu page->count:%d\n", (int) file->f_pos, (int) inode, inode->i_size, (int) hidden_inode, (int) page->inode, page->offset, atomic_read(&page->count)); hidden_page = read_cache_page(hidden_inode, page->offset, (filler_t *)hidden_inode->i_op->readpage, hidden_file); if (IS_ERR(hidden_page)) { err = PTR_ERR(hidden_page); /* XXX: we might have to do some unlocking on this error path */ goto out; } /* * decode hidden_page data onto page */ page_data = page_address(page); hidden_page_data = page_address(hidden_page); wrapfs_decode_block((char *) hidden_page_data, (char *) page_data, PAGE_SIZE, inode, inode->i_sb); /* release our reference to the hidden page */ page_cache_release(hidden_page); /* * adjust flags and wake up processes waiting on the page */ set_bit(PG_uptodate, &page->flags);out: /* * we have to unlock our page, b/c we locked it above */ clear_bit(PG_locked, &page->flags); wake_up(&page->wait); after_unlock_page(page); fist_dprint(6, "READPAGE (exit/page): f_pos:0x%x inode:0x%x i_size:0x%x hidden_inode:0x%x page->inode:0x%x page->offset:%lu page->count:%d\n", (int) file->f_pos, (int) inode, inode->i_size, (int) hidden_inode, (int) page->inode, page->offset, atomic_read(&page->count)); fist_dprint(6, "READPAGE (exit/hidden_page): f_pos:0x%x inode:0x%x i_size:0x%x hidden_inode:0x%x page->inode:0x%x page->offset:%lu page->count:%d\n", (int) file->f_pos, (int) inode, inode->i_size, (int) hidden_inode, (int) hidden_page->inode, hidden_page->offset, atomic_read(&hidden_page->count)); fist_print_page_flags("READPAGE flags (exit)", page); fist_print_page_flags("READPAGE hidden_flags (exit)", hidden_page); print_exit_status(err); return err;}#ifdef NOT_NEEDED#error ARE YOU SURE YOU WANT TO DEFINE WRITEPAGE???/* XXX: the VFS never calls writepage */STATIC intwrapfs_writepage(file_t *file, page_t *page){ int err = -EIO; file_t *hidden_file = ftohf(file); inode_t *hidden_inode = hidden_file->f_dentry->d_inode; print_entry_location(); if (hidden_inode->i_op && hidden_inode->i_op->writepage) { fist_dprint(2, "non-generic writepage\n"); err = hidden_inode->i_op->writepage(hidden_file, page); if (err >= 0) fist_copy_attr_times(file->f_dentry->d_inode, hidden_inode); } print_exit_status(err); return err;}#endif /* NOT_NEEDED */STATIC intwrapfs_bmap(inode_t *inode, int block){ int err = -EINVAL; inode_t *hidden_inode = itohi(inode); print_entry_location(); if (hidden_inode->i_op && hidden_inode->i_op->bmap) err = hidden_inode->i_op->bmap(hidden_inode, block); print_exit_status(err); return err;}STATIC voidwrapfs_truncate(inode_t *inode){ inode_t *hidden_inode = itohi(inode); print_entry_location(); fist_checkinode(inode, "wrapfs_truncate"); if (!hidden_inode->i_op || !hidden_inode->i_op->truncate) goto out; down(&hidden_inode->i_sem); hidden_inode->i_op->truncate(hidden_inode); up(&hidden_inode->i_sem); fist_copy_attr_timesizes(inode, hidden_inode); out: print_exit_location();}STATIC intwrapfs_permission(inode_t *inode, int mask){ inode_t *hidden_inode = itohi(inode); int mode = inode->i_mode; int err; print_entry_location(); if ((mask & S_IWOTH) && IS_RDONLY(inode) && (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) { err = -EROFS; /* Nobody gets write access to a read-only fs */ goto out; } err = permission(hidden_inode, mask); out: print_exit_status(err); return err;}STATIC intwrapfs_smap(inode_t *inode, int block){ int err = -EINVAL; inode_t *hidden_inode = itohi(inode); print_entry_location(); if (hidden_inode->i_op && hidden_inode->i_op->smap) err = hidden_inode->i_op->smap(hidden_inode, block); else err = bmap(hidden_inode, block); print_exit_status(err); return err;}#ifdef NOT_NEEDED/* * We don't need this because we will implement file_write, which will * call the hidden file_write, and the latter, if set to generic_file_write, * will call hidden's update_page (if implemented by lower file system). */STATIC intwrapfs_updatepage(file_t *file, page_t *page, const char *buf, unsigned long offset, unsigned int count, int sync){ int err = -EIO; file_t *hidden_file = ftohf(file); char *hidden_buf, *page_data; mm_segment_t old_fs; loff_t hidden_file_offset = file->f_pos; print_entry_location(); fist_dprint(6, "UPDATEPAGE1: buf[0]=%d, offset=0x%x, count=%d, sync=%d\n", (int) buf[0], (int) offset, count, sync); if (!hidden_file->f_op || !hidden_file->f_op->write) goto out; fist_print_file("Updatepage BEFORE file", file); fist_print_file("Updatepage BEFORE hidden_file", hidden_file); hidden_buf = kmalloc(count, GFP_KERNEL); if (!hidden_buf) { err = -ENOMEM; goto out; } wrapfs_encode_block(buf, hidden_buf, count, page->inode, page->inode->i_sb); old_fs = get_fs(); set_fs(KERNEL_DS); hidden_file->f_pos = file->f_pos; err = hidden_file->f_op->write(hidden_file, hidden_buf, count, &hidden_file_offset); set_fs(old_fs); fist_print_file("Updatepage AFTER file", file); fist_print_file("Updatepage AFTER hidden_file", hidden_file); if (err >= 0) { // file->f_pos = hidden_file_offset; page_data = (char *) page_address(page); memcpy(page_data, buf, count); // file->f_pos = hidden_file->f_pos; } kfree_s(hidden_buf, count); out: print_exit_status(err); return err;}#endif /* NOT_NEEDED */STATIC intwrapfs_inode_revalidate(dentry_t *dentry){ int err = 0; dentry_t *hidden_dentry = wrapfs_hidden_dentry(dentry); inode_t *hidden_inode = hidden_dentry->d_inode; print_entry_location(); // fist_print_dentry("inode_revalidate IN", dentry); if (hidden_inode->i_op && hidden_inode->i_op->revalidate) { err = hidden_inode->i_op->revalidate(hidden_dentry); if (!err) fist_copy_attr_all(dentry->d_inode, hidden_inode); } // fist_print_dentry("inode_revalidate OUT", dentry); print_exit_status(err); return err;}#if 0#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,18)/* * XXX: we may not need this function if not FIST_FILTER_DATA. * XXX: for FIST_FILTER_SCA, get all lower pages and sync them each. */STATIC intwrapfs_sync_page(page_t *page){ int err = 0; inode_t *inode = (inode_t *) page->inode; inode_t *hidden_inode = itohi(inode); page_t *hidden_page; print_entry_location(); /* * find lower page. returns a locked page, and may also return * a newly allocated page. * XXX: if page is allocated, it may not have any data in it. What do * we do then? (What are the exact semantics of ->sync_page? */ hidden_page = get_cached_page(hidden_inode, page->offset, 1); if (!hidden_page) goto out; err = sync_page(hidden_page); UnlockPage(hidden_page); /* b/c get_cached_page locked it */ page_cache_release(hidden_page); /* b/c get_cached_page increased refcnt */out: print_exit_location(); return err;}STATIC intwrapfs_prepare_write(file_t *file, page_t *page, unsigned from, unsigned to){#error need to be ported correctly from 2.4. For now, wrapfs over nfs in 2.2#error will not work.}#endif /* kernel 2.2.18 or newer */#endifstruct inode_operations wrapfs_main_iops ={ default_file_ops: &wrapfs_main_fops, create: wrapfs_create, lookup: wrapfs_lookup, link: wrapfs_link, unlink: wrapfs_unlink, symlink: wrapfs_symlink, mkdir: wrapfs_mkdir, rmdir: wrapfs_rmdir, mknod: wrapfs_mknod, rename: wrapfs_rename, readlink: wrapfs_readlink, follow_link: wrapfs_follow_link, readpage: wrapfs_readpage,#ifdef NOT_NEEDED write_page: wrapfs_writepage,#endif /* NOT_NEEDED */ bmap: wrapfs_bmap, truncate: wrapfs_truncate, permission: wrapfs_permission, smap: wrapfs_smap,#ifdef NOT_NEEDED updatepage: wrapfs_updatepage,#endif /* NOT_NEEDED */ revalidate: wrapfs_inode_revalidate,#if 0#error need proper porting#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,18) prepare_write: wrapfs_prepare_write, sync_page: wrapfs_sync_page,#endif /* kernel 2.2.18 or newer */#endif};struct inode_operations wrapfs_dir_iops ={ default_file_ops: &wrapfs_dir_fops, create: wrapfs_create, lookup: wrapfs_lookup, link: wrapfs_link, unlink: wrapfs_unlink, symlink: wrapfs_symlink, mkdir: wrapfs_mkdir, rmdir: wrapfs_rmdir, mknod: wrapfs_mknod, rename: wrapfs_rename, readlink: wrapfs_readlink, follow_link: wrapfs_follow_link, readpage: wrapfs_readpage,#ifdef NOT_NEEDED write_page: wrapfs_writepage,#endif /* NOT_NEEDED */ bmap: wrapfs_bmap, truncate: wrapfs_truncate, permission: wrapfs_permission, smap: wrapfs_smap,#ifdef NOT_NEEDED updatepage: wrapfs_updatepage,#endif /* NOT_NEEDED */ revalidate: wrapfs_inode_revalidate,#if 0#error need proper porting#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,18) prepare_write: wrapfs_prepare_write, sync_page: wrapfs_sync_page,#endif /* kernel 2.2.18 or newer */#endif};/* * Local variables: * c-basic-offset: 4 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -