📄 inode.c
字号:
/* * Copyright (c) 1997-2003 Erez Zadok * Copyright (c) 2001-2003 Stony Brook University * Copyright (c) 1997-2000 Columbia University * * For specific licensing information, see the COPYING file distributed with * this package, or get one from ftp://ftp.filesystems.org/pub/fist/COPYING. * * This Copyright notice must be kept intact and distributed with all * fistgen sources INCLUDING sources generated by fistgen. *//* * $Id: inode.c,v 1.19 2002/12/27 20:19:04 ezk Exp $ */#ifdef HAVE_CONFIG_H# include <config.h>#endif /* HAVE_CONFIG_H */#ifdef FISTGEN# include "fist_wrapfs.h"#endif /* FISTGEN */#include "fist.h"#include "wrapfs.h"STATIC intwrapfs_create(inode_t *dir, dentry_t *dentry, int mode){ int err; dentry_t *hidden_dentry; dentry_t *hidden_dir_dentry; print_entry_location(); hidden_dentry = wrapfs_hidden_dentry(dentry); /* CPW: Moved below print_entry_location */ ASSERT(hidden_dentry != NULL); fist_checkinode(dir, "wrapfs_create"); hidden_dir_dentry = lock_parent(hidden_dentry); err = PTR_ERR(hidden_dir_dentry); if (IS_ERR(hidden_dir_dentry)) goto out; err = vfs_create(hidden_dir_dentry->d_inode, hidden_dentry, mode); /* XXX this could potentially return a negative hidden_dentry! */ if (err) goto out_lock; err = wrapfs_interpose(hidden_dentry, dentry, dir->i_sb, 0); if (err) goto out_lock; fist_copy_attr_timesizes(dir, hidden_dir_dentry->d_inode);#ifdef FIST_FILTER_SCA err = wrapfs_idx_create(hidden_dir_dentry->d_inode, dentry, mode); if (err) { /* * PROBLEM: we created an empty data file at this point. * should we unlink it? maybe. Another solution might be * to change SCA semantics so that a zero-length file need not * have an index file. */ printk("wrapfs_create: couldn't create idx file %s: %d\n", dtopd(dentry)->idx_dentry->d_name.name, err); goto out_lock; } wrapfs_idx_open(dentry, O_WRONLY);#endif /* FIST_FILTER_SCA */ out_lock: unlock_dir(hidden_dir_dentry); out: fist_checkinode(dir, "post wrapfs_create"); print_exit_status(err); return err;}STATIC dentry_t *wrapfs_lookup(inode_t *dir, dentry_t *dentry){ int err = 0; dentry_t *hidden_dir_dentry; dentry_t *hidden_dentry; const char *name; vnode_t *this_vnode; dentry_t *this_dir; unsigned int namelen;#ifdef FIST_FILTER_NAME char *encoded_name; unsigned int encoded_namelen;#endif /* FIST_FILTER_NAME */ print_entry_location(); hidden_dir_dentry = wrapfs_hidden_dentry(dentry->d_parent); /* CPW: Moved below print_entry_location */ name = dentry->d_name.name; namelen = dentry->d_name.len; fist_checkinode(dir, "wrapfs_lookup"); this_vnode = dir; this_dir = hidden_dir_dentry; fist_print_dentry("wrapfs_lookup IN", dentry); fist_print_dentry("wrapfs_lookup: dentry->d_parent IN", dentry->d_parent); fist_print_dentry("wrapfs_lookup: hidden_dir_dentry IN", hidden_dir_dentry); fist_print_inode("wrapfs_lookup: dir IN", dir); if (hidden_dir_dentry->d_inode) fist_print_inode("wrapfs_lookup: hidden_dir_dentry->d_inode", hidden_dir_dentry->d_inode); /* must initialize dentry operations */ dentry->d_op = &wrapfs_dops; FIST_OP_LOOKUP_PRECALL; /* increase refcount of base dentry (lookup_one[_len] will decrement) */ // THIS IS RIGHT! (don't "fix" it) // NO THIS IS WRONG IN 2.3.99-pre6. lookup_one[_len] will NOT decrement // dget(hidden_dir_dentry);#ifndef FIST_FILTER_NAME /* will allocate a new hidden dentry if needed */ hidden_dentry = lookup_one_len(name, hidden_dir_dentry, namelen);#else /* FIST_FILTER_NAME */ encoded_namelen = wrapfs_encode_filename(name, namelen, &encoded_name, SKIP_DOTS, dir, dir->i_sb); /* will allocate a new hidden dentry if needed */ hidden_dentry = lookup_one_len(encoded_name, hidden_dir_dentry, encoded_namelen - 1); kfree(encoded_name);#endif /* FIST_FILTER_NAME */ if (IS_ERR(hidden_dentry)) { /* * this produces an unusual dentry: one that has neither an * inode, nor a private structure attached to it. All cleanup * methods (d_delete, d_release, etc) must be prepared to deal * with such dentries. Ion 09/29/2001 */ printk("ERR from hidden_dentry!!!\n"); err = PTR_ERR(hidden_dentry); goto out; } FIST_OP_LOOKUP_POSTCALL; /* update parent directory's atime */ fist_copy_attr_atime(dir, hidden_dir_dentry->d_inode); /* link the upper and lower dentries */ dtopd(dentry) = (struct wrapfs_dentry_info *) kmalloc(sizeof(struct wrapfs_dentry_info), GFP_KERNEL); if (!dtopd(dentry)) { err = -ENOMEM; goto out_dput; } dtohd(dentry) = hidden_dentry;#ifdef FIST_FILTER_SCA /* * Lookup index file. Note that we create index files only * for real files, but at this point we may not know the type * of the to-be created inode. We release idx_dentry's in d_release. */ if (hidden_dentry->d_inode == NULL || S_ISREG(hidden_dentry->d_inode->i_mode)) { dtopd(dentry)->idx_dentry = wrapfs_idx_lookup(hidden_dentry); if (IS_ERR(dtopd(dentry)->idx_dentry)) { err = PTR_ERR(dtopd(dentry)->idx_dentry); goto out_free; } /* index file exists and data file does not, or viceversa */ if ((dtopd(dentry)->idx_dentry->d_inode == NULL) ^ (hidden_dentry->d_inode == NULL)) { err = -ENOENT; goto out_free; } } else /* no need for index file */ dtopd(dentry)->idx_dentry = NULL;#endif /* FIST_FILTER_SCA */ /* lookup is special: it needs to handle negative dentries */ if (!hidden_dentry->d_inode) { d_add(dentry, NULL); fist_print_dentry("wrapfs_lookup OUT hidden_dentry", hidden_dentry); goto out; } fist_dprint(6, "lookup \"%s\" -> inode %d\n", name, hidden_dentry->d_inode->i_ino); err = wrapfs_interpose(hidden_dentry, dentry, dir->i_sb, 1); if (err) goto out_free; fist_checkinode(dentry->d_inode, "wrapfs_lookup OUT: dentry->d_inode:"); fist_checkinode(dir, "wrapfs_lookup OUT: dir"); fist_print_dentry("wrapfs_lookup OUT hidden_dentry", hidden_dentry); fist_print_inode("wrapfs_lookup OUT hidden_inode", hidden_dentry->d_inode);#ifdef FIST_FILTER_SCA if (S_ISREG(hidden_dentry->d_inode->i_mode)) { err = wrapfs_idx_open(dentry, O_RDONLY); if (err) goto out_free; err = wrapfs_idx_read(dentry->d_inode); wrapfs_idx_release(dentry->d_inode); if (err) goto out_free; wrapfs_idx_open(dentry, O_WRONLY); }#endif /* FIST_FILTER_SCA */ /* All is well */ goto out; out_free: d_drop(dentry); /* so that our bad dentry will get destroyed */#ifdef FIST_FILTER_SCA if (dtopd(dentry)->idx_dentry) dput(dtopd(dentry)->idx_dentry);#endif /* FIST_FILTER_SCA */ kfree(dtopd(dentry)); dtopd(dentry) = NULL; /* be safe */ out_dput: dput(hidden_dentry); out: fist_print_dentry("wrapfs_lookup OUT", dentry); print_exit_status(err); return ERR_PTR(err);}STATIC intwrapfs_link(dentry_t *old_dentry, inode_t *dir, dentry_t *new_dentry){ int err; dentry_t *hidden_old_dentry; dentry_t *hidden_new_dentry; dentry_t *hidden_dir_dentry; print_entry_location(); hidden_old_dentry = wrapfs_hidden_dentry(old_dentry); /* CPW: Moved below print_entry_location */ hidden_new_dentry = wrapfs_hidden_dentry(new_dentry); fist_checkinode(dir, "wrapfs_link-dir"); fist_checkinode(old_dentry->d_inode, "wrapfs_link-oldinode"); dget(hidden_old_dentry); dget(hidden_new_dentry); hidden_dir_dentry = lock_parent(hidden_new_dentry);#ifdef FIST_FILTER_SCA /* Also link the index file */ if (old_dentry->d_inode && S_ISREG(old_dentry->d_inode->i_mode)) { /* These must be in the same directory as the main file */ dentry_t *idx_old_dentry = dtopd(old_dentry)->idx_dentry; dentry_t *idx_new_dentry = dtopd(new_dentry)->idx_dentry; err = vfs_link(idx_old_dentry, hidden_dir_dentry->d_inode, idx_new_dentry); /* XXX this could potentially return a negative dentry! */ if (err) goto out_lock; fist_copy_attr_timesizes(dir, idx_new_dentry->d_inode); }#endif err = vfs_link(hidden_old_dentry, hidden_dir_dentry->d_inode, hidden_new_dentry); if (err || !hidden_new_dentry->d_inode) goto out_lock; err = wrapfs_interpose(hidden_new_dentry, new_dentry, dir->i_sb, 0); if (err) goto out_lock; fist_copy_attr_timesizes(dir, hidden_new_dentry->d_inode); /* propagate number of hard-links */ old_dentry->d_inode->i_nlink = itohi(old_dentry->d_inode)->i_nlink; out_lock: unlock_dir(hidden_dir_dentry); dput(hidden_new_dentry); dput(hidden_old_dentry); if (!new_dentry->d_inode) d_drop(new_dentry); print_exit_status(err); return err;}STATIC intwrapfs_unlink(inode_t *dir, dentry_t *dentry){ int err = 0; inode_t *hidden_dir; dentry_t *hidden_dentry; dentry_t *hidden_dir_dentry; print_entry_location(); hidden_dir = itohi(dir); /* CPW: Moved below print_entry_location */ hidden_dentry = wrapfs_hidden_dentry(dentry); ASSERT(hidden_dentry != NULL); fist_checkinode(dir, "wrapfs_unlink-dir"); dget(dentry); hidden_dir_dentry = lock_parent(hidden_dentry);#ifdef FIST_FILTER_SCA /* first unlink the index file */ if (dentry->d_inode) { if (S_ISREG(dentry->d_inode->i_mode)) { dentry_t *idx_dentry = dtopd(dentry)->idx_dentry; dget(idx_dentry); err = vfs_unlink(hidden_dir, idx_dentry); dput(idx_dentry); if (err) printk("SCA unlink \"%s\" failed with error %d\n", dentry->d_name.name, err); fist_print_dentry("wrapfs_unlink: idx_dentry", idx_dentry); if (idx_dentry->d_inode) fist_print_inode("wrapfs_unlink: idx_inode", idx_dentry->d_inode); } } else { printk("No index file for %s!\n", dentry->d_name.name); } out_index:#endif /* FIST_FILTER_SCA */ /* avoid destroying the hidden inode if the file is in use */ dget(hidden_dentry); err = vfs_unlink(hidden_dir, hidden_dentry); dput(hidden_dentry); if (!err) /* vfs_unlink does that */ d_delete(hidden_dentry); out_lock: fist_copy_attr_times(dir, hidden_dir); /* propagate number of hard-links */ dentry->d_inode->i_nlink = itohi(dentry->d_inode)->i_nlink; unlock_dir(hidden_dir_dentry); /* * call d_drop so the system "forgets" about us */ if (!err) { // fist_print_dentry("wrapfs_unlink: 0", dentry); d_drop(dentry); // fist_print_dentry("wrapfs_unlink: 1", dentry); } dput(dentry); fist_checkinode(dir, "post wrapfs_unlink-dir"); print_exit_status(err); return err;}STATIC intwrapfs_symlink(inode_t *dir, dentry_t *dentry, const char *symname){ int err; dentry_t *hidden_dentry; dentry_t *hidden_dir_dentry;#ifdef FIST_FILTER_NAME char *encoded_symname; unsigned int encoded_symlen;#endif /* FIST_FILTER_NAME */ print_entry_location(); hidden_dentry = wrapfs_hidden_dentry(dentry); /* CPW: Moved below print_entry_location */ fist_checkinode(dir, "wrapfs_symlink-dir"); dget(hidden_dentry); hidden_dir_dentry = lock_parent(hidden_dentry);#ifndef FIST_FILTER_NAME err = vfs_symlink(hidden_dir_dentry->d_inode, hidden_dentry, symname);#else /* FIST_FILTER_NAME */ encoded_symlen = wrapfs_encode_filename(symname, strlen(symname), &encoded_symname, DO_DOTS, dir, dir->i_sb); err = vfs_symlink(hidden_dir_dentry->d_inode, hidden_dentry, encoded_symname); kfree(encoded_symname);#endif /* FIST_FILTER_NAME */ if (err || !hidden_dentry->d_inode) goto out_lock; err = wrapfs_interpose(hidden_dentry, dentry, dir->i_sb, 0); if (err) goto out_lock; fist_copy_attr_timesizes(dir, hidden_dir_dentry->d_inode); fist_checkinode(dir, "post wrapfs_symlink-dir"); out_lock: unlock_dir(hidden_dir_dentry); dput(hidden_dentry); if (!dentry->d_inode) d_drop(dentry); print_exit_status(err); return err;}STATIC intwrapfs_mkdir(inode_t *dir, dentry_t *dentry, int mode){ int err; dentry_t *hidden_dentry; dentry_t *hidden_dir_dentry; print_entry_location(); hidden_dentry = wrapfs_hidden_dentry(dentry); /* CPW: Moved below print_entry_location */ fist_checkinode(dir, "wrapfs_mkdir-dir"); hidden_dir_dentry = lock_parent(hidden_dentry); err = vfs_mkdir(hidden_dir_dentry->d_inode, hidden_dentry, mode); if (err || !hidden_dentry->d_inode) goto out; err = wrapfs_interpose(hidden_dentry, dentry, dir->i_sb, 0); if (err) goto out; fist_copy_attr_timesizes(dir, hidden_dir_dentry->d_inode); /* update number of links on parent directory */ dir->i_nlink = hidden_dir_dentry->d_inode->i_nlink; fist_checkinode(dir, "post wrapfs_mkdir-dir"); out: unlock_dir(hidden_dir_dentry); if (!dentry->d_inode) d_drop(dentry); print_exit_status(err); return err;}STATIC intwrapfs_rmdir(inode_t *dir, dentry_t *dentry){ int err = 0; dentry_t *hidden_dentry; dentry_t *hidden_dir_dentry; print_entry_location(); hidden_dentry = wrapfs_hidden_dentry(dentry); /* CPW: Moved below print_entry_location */ fist_checkinode(dir, "wrapfs_rmdir-dir"); dget(dentry); hidden_dir_dentry = lock_parent(hidden_dentry); /* avoid destroying the hidden inode if the file is in use */ dget(hidden_dentry); err = vfs_rmdir(hidden_dir_dentry->d_inode, hidden_dentry); dput(hidden_dentry); if (!err) /* vfs_rmdir does that */ d_delete(hidden_dentry); out_lock: fist_copy_attr_times(dir, hidden_dir_dentry->d_inode); /* copy the nlink count for our dentry and our parent's dentry */ dir->i_nlink = hidden_dir_dentry->d_inode->i_nlink; unlock_dir(hidden_dir_dentry); /* * call d_drop so the system "forgets" about us */ if (!err) d_drop(dentry); dput(dentry); print_exit_status(err); return err;}STATIC intwrapfs_mknod(inode_t *dir, dentry_t *dentry, int mode, int dev){ int err; dentry_t *hidden_dentry; dentry_t *hidden_dir_dentry; print_entry_location(); hidden_dentry = wrapfs_hidden_dentry(dentry); /* CPW: Moved below print_entry_location */ fist_checkinode(dir, "wrapfs_mknod-dir"); hidden_dir_dentry = lock_parent(hidden_dentry); err = vfs_mknod(hidden_dir_dentry->d_inode, hidden_dentry, mode, dev); if (err || !hidden_dentry->d_inode) goto out; err = wrapfs_interpose(hidden_dentry, dentry, dir->i_sb, 0); if (err) goto out; fist_copy_attr_timesizes(dir, hidden_dir_dentry->d_inode); out: unlock_dir(hidden_dir_dentry); if (!dentry->d_inode) d_drop(dentry); fist_checkinode(dir, "post wrapfs_mknod-dir"); print_exit_status(err); return err;}STATIC intwrapfs_rename(inode_t *old_dir, dentry_t *old_dentry, inode_t *new_dir, dentry_t *new_dentry){ int err; dentry_t *hidden_old_dentry; dentry_t *hidden_new_dentry; dentry_t *hidden_old_dir_dentry;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -