📄 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.53 2002/12/27 20:19:01 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 = wrapfs_hidden_dentry(dentry); dentry_t *hidden_dir_dentry; 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); 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, FMODE_WRITE, 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 = wrapfs_hidden_dentry(dentry->d_parent); dentry_t *hidden_dentry; const char *name = dentry->d_name.name; vnode_t *this_vnode; dentry_t *this_dir;#ifdef FIST_FILTER_NAME unsigned int namelen = dentry->d_name.len; char *encoded_name; unsigned int encoded_namelen;#endif /* FIST_FILTER_NAME */ print_entry_location(); fist_checkinode(dir, "wrapfs_lookup"); this_vnode = dir; this_dir = hidden_dir_dentry; fist_print_dentry("LOOKUP: dentry IN", dentry); fist_print_dentry("LOOKUP: dentry->d_parent IN", dentry->d_parent); fist_print_dentry("LOOKUP: hidden_dir_dentry IN", hidden_dir_dentry); fist_print_inode("LOOKUP: dir IN", dir); if (hidden_dir_dentry->d_inode) fist_print_inode("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 will decrement) */ // THIS IS RIGHT! (don't "fix" it) // NO THIS IS WRONG IN 2.3.99-pre6. lookup_one will NOT decrement // dget(hidden_dir_dentry);#ifndef FIST_FILTER_NAME /* will allocate a new hidden dentry if needed */ hidden_dentry = lookup_one(name, hidden_dir_dentry);#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(encoded_name, hidden_dir_dentry); kfree_s(encoded_name, encoded_namelen);#endif /* FIST_FILTER_NAME */ if (IS_ERR(hidden_dentry)) { 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("lookup hidden", 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(__FUNCTION__ " OUT hidden_dentry", hidden_dentry); fist_print_inode(__FUNCTION__ " 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, FMODE_READ, 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, FMODE_WRITE, 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_s(dtopd(dentry), sizeof(struct wrapfs_dentry_info)); dtopd(dentry) = NULL; /* be safe */ out_dput: dput(hidden_dentry); out: fist_print_dentry("LOOKUP: dentry 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 = wrapfs_hidden_dentry(old_dentry); dentry_t *hidden_new_dentry = wrapfs_hidden_dentry(new_dentry); dentry_t *hidden_dir_dentry; print_entry_location(); 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); err = -ENOENT;#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; if (!check_parent(hidden_dir_dentry, idx_new_dentry)) goto out_lock; err = vfs_link(idx_old_dentry, hidden_dir_dentry->d_inode, idx_new_dentry); if (err) goto out_lock; fist_copy_attr_timesizes(dir, idx_new_dentry->d_inode); }#endif if (!check_parent(hidden_dir_dentry, hidden_new_dentry)) goto out_lock; err = vfs_link(hidden_old_dentry, hidden_dir_dentry->d_inode, hidden_new_dentry); if (err) 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); print_exit_status(err); return err;}STATIC intwrapfs_unlink(inode_t *dir, dentry_t *dentry){ int err = 0; inode_t *hidden_dir = itohi(dir); dentry_t *hidden_dentry = wrapfs_hidden_dentry(dentry); dentry_t *hidden_dir_dentry; print_entry_location(); 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; if (!check_parent(hidden_dir_dentry, idx_dentry)) goto out_index; 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("unlink idx_dentry", idx_dentry); if (idx_dentry->d_inode) fist_print_inode("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 */ if (!check_parent(hidden_dir_dentry, hidden_dentry)) goto out_lock; /* 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 0 if (err && err != -ENOENT) goto out_lock;#endif if (!err) /* dput 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 || err == -ENOENT) d_drop(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 = wrapfs_hidden_dentry(dentry); dentry_t *hidden_dir_dentry;#ifdef FIST_FILTER_NAME char *encoded_symname; unsigned int encoded_symlen;#endif /* FIST_FILTER_NAME */ print_entry_location(); fist_checkinode(dir, "wrapfs_symlink-dir"); dget(hidden_dentry); hidden_dir_dentry = lock_parent(hidden_dentry); err = -ENOENT; if (!check_parent(hidden_dir_dentry, hidden_dentry)) goto out_lock;#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_s(encoded_symname, encoded_symlen);#endif /* FIST_FILTER_NAME */ 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); fist_checkinode(dir, "post wrapfs_symlink-dir"); out_lock: unlock_dir(hidden_dir_dentry); dput(hidden_dentry); print_exit_status(err); return err;}STATIC intwrapfs_mkdir(inode_t *dir, dentry_t *dentry, int mode){ int err; dentry_t *hidden_dentry = wrapfs_hidden_dentry(dentry); dentry_t *hidden_dir_dentry; print_entry_location(); fist_checkinode(dir, "wrapfs_mkdir-dir"); hidden_dir_dentry = lock_parent(hidden_dentry); err = -ENOENT; if (!check_parent(hidden_dir_dentry, hidden_dentry)) goto out; err = vfs_mkdir(hidden_dir_dentry->d_inode, hidden_dentry, mode); if (err) 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); print_exit_status(err); return err;}STATIC intwrapfs_rmdir(inode_t *dir, dentry_t *dentry){ int err = 0; dentry_t *hidden_dentry = wrapfs_hidden_dentry(dentry); dentry_t *hidden_dir_dentry; print_entry_location(); fist_checkinode(dir, "wrapfs_rmdir-dir"); dget(dentry); hidden_dir_dentry = lock_parent(hidden_dentry); if (!check_parent(hidden_dir_dentry, hidden_dentry)) goto out_lock; /* 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 0 if (err && err != -ENOENT) goto out_lock;#endif if (!err) /* dput 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; /* copy nlink (has to be 0) to ours so iput destroys it */ dentry->d_inode->i_nlink = 0; unlock_dir(hidden_dir_dentry); /* * call d_drop so the system "forgets" about us */ if (!err || err == -ENOENT) 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 = wrapfs_hidden_dentry(dentry); dentry_t *hidden_dir_dentry; print_entry_location(); fist_checkinode(dir, "wrapfs_mknod-dir"); hidden_dir_dentry = lock_parent(hidden_dentry); err = -ENOENT;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -