int main(int argc, char** argv) { printf("KEY META TESTS\n"); printf("==================\n\n"); init (argc, argv); test_basic(); test_iterate(); test_size(); test_uid(); test_dup(); test_comment(); test_owner(); test_mode(); test_type(); test_examples(); test_copy(); test_ro(); test_new(); test_copyall(); printf("\ntest_ks RESULTS: %d test(s) done. %d error(s).\n", nbTest, nbError); return nbError; }
/* common functions to regular file and dir */ struct file *hidden_open(struct dentry *dentry, aufs_bindex_t bindex, int flags) { struct dentry *hidden_dentry; struct inode *hidden_inode; struct super_block *sb; struct vfsmount *hidden_mnt; struct file *hidden_file; struct aufs_branch *br; loff_t old_size; int udba; LKTRTrace("%.*s, b%d, flags 0%o\n", DLNPair(dentry), bindex, flags); DEBUG_ON(!dentry); hidden_dentry = au_h_dptr_i(dentry, bindex); DEBUG_ON(!hidden_dentry); hidden_inode = hidden_dentry->d_inode; DEBUG_ON(!hidden_inode); sb = dentry->d_sb; udba = au_flag_test(sb, AuFlag_UDBA_INOTIFY); if (unlikely(udba)) { // test here? } br = stobr(sb, bindex); br_get(br); /* drop flags for writing */ if (test_ro(sb, bindex, dentry->d_inode)) flags = au_file_roflags(flags); flags &= ~O_CREAT; spin_lock(&hidden_inode->i_lock); old_size = i_size_read(hidden_inode); spin_unlock(&hidden_inode->i_lock); //DbgSleep(3); dget(hidden_dentry); hidden_mnt = mntget(br->br_mnt); hidden_file = dentry_open(hidden_dentry, hidden_mnt, flags); //if (LktrCond) {fput(hidden_file); hidden_file = ERR_PTR(-1);} if (!IS_ERR(hidden_file)) { #if 0 // remove this if (/* old_size && */ (flags & O_TRUNC)) { au_direval_dec(dentry); if (!IS_ROOT(dentry)) au_direval_dec(dentry->d_parent); } #endif return hidden_file; } br_put(br); TraceErrPtr(hidden_file); return hidden_file; }
/* returns, * 0: wh is unnecessary * plus: wh is necessary * minus: error */ int wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup, struct dentry *locked) { int need_wh, err; aufs_bindex_t bstart; struct dentry *hidden_dentry; struct super_block *sb; LKTRTrace("%.*s, isdir %d, *bcpup %d, locked %p\n", DLNPair(dentry), isdir, *bcpup, locked); sb = dentry->d_sb; bstart = dbstart(dentry); LKTRTrace("bcpup %d, bstart %d\n", *bcpup, bstart); hidden_dentry = au_h_dptr(dentry); if (*bcpup < 0) { *bcpup = bstart; if (test_ro(sb, bstart, dentry->d_inode)) { *bcpup = err = find_rw_parent_br(dentry, bstart); //*bcpup = err = find_rw_br(sb, bstart); //err = -1; if (unlikely(err < 0)) goto out; } } else DEBUG_ON(bstart < *bcpup || test_ro(sb, *bcpup, dentry->d_inode)); LKTRTrace("bcpup %d, bstart %d\n", *bcpup, bstart); if (*bcpup != bstart) { err = cpup_dirs(dentry, *bcpup, locked); //err = -1; if (unlikely(err)) goto out; need_wh = 1; } else { //struct nameidata nd; aufs_bindex_t old_bend, new_bend, bdiropq = -1; old_bend = dbend(dentry); if (isdir) { bdiropq = dbdiropq(dentry); set_dbdiropq(dentry, -1); } err = need_wh = lkup_dentry(dentry, bstart + 1, /*type*/0); //err = -1; if (isdir) set_dbdiropq(dentry, bdiropq); if (unlikely(err < 0)) goto out; new_bend = dbend(dentry); if (!need_wh && old_bend != new_bend) { set_h_dptr(dentry, new_bend, NULL); set_dbend(dentry, old_bend); #if 0 } else if (!au_h_dptr_i(dentry, new_bend)->d_inode) { LKTRTrace("negative\n"); set_h_dptr(dentry, new_bend, NULL); set_dbend(dentry, old_bend); need_wh = 0; #endif } } LKTRTrace("need_wh %d\n", need_wh); err = need_wh; out: TraceErr(err); return err; }
/* * prepare the @file for writing. */ int au_ready_to_write(struct file *file, loff_t len) { int err; struct dentry *dentry, *parent, *hidden_dentry, *hidden_parent; struct inode *hidden_inode, *hidden_dir, *inode, *dir; struct super_block *sb; aufs_bindex_t bstart, bcpup; dentry = file->f_dentry; LKTRTrace("%.*s, len %Ld\n", DLNPair(dentry), len); FiMustWriteLock(file); sb = dentry->d_sb; bstart = fbstart(file); DEBUG_ON(ftobr(file, bstart) != stobr(sb, bstart)); inode = dentry->d_inode; ii_read_lock_child(inode); LKTRTrace("rdonly %d, bstart %d\n", test_ro(sb, bstart, inode), bstart); err = test_ro(sb, bstart, inode); ii_read_unlock(inode); if (!err && (au_h_fptr(file)->f_mode & FMODE_WRITE)) return 0; /* need to cpup */ parent = dentry->d_parent; // dget_parent() di_write_lock_child(dentry); di_write_lock_parent(parent); bcpup = err = find_rw_parent_br(dentry, bstart); //bcpup = err = find_rw_br(sb, bstart); if (unlikely(err < 0)) goto out_unlock; err = 0; hidden_parent = au_h_dptr_i(parent, bcpup); if (!hidden_parent) { err = cpup_dirs(dentry, bcpup, NULL); //if (LktrCond) err = -1; if (unlikely(err)) goto out_unlock; hidden_parent = au_h_dptr_i(parent, bcpup); } hidden_dir = hidden_parent->d_inode; hidden_dentry = au_h_fptr(file)->f_dentry; hidden_inode = hidden_dentry->d_inode; dir = parent->d_inode; hdir_lock(hidden_dir, dir, bcpup); hi_lock_child(hidden_inode); if (d_unhashed(dentry) || d_unhashed(hidden_dentry) /* || !hidden_inode->i_nlink */) { if (!au_test_perm(hidden_dir, MAY_EXEC | MAY_WRITE, need_dlgt(sb))) err = cpup_wh_file(file, bcpup, len); else { struct cpup_wh_file_args args = { .errp = &err, .file = file, .bdst = bcpup, .len = len }; au_wkq_wait(call_cpup_wh_file, &args, /*dlgt*/0); } //if (LktrCond) err = -1; TraceErr(err); } else { if (!au_h_dptr_i(dentry, bcpup))
int au_do_open(struct inode *inode, struct file *file, int (*open)(struct file *file, int flags)) { int err, coo; struct dentry *dentry; struct super_block *sb; aufs_bindex_t bstart; struct inode *h_dir, *dir; dentry = file->f_dentry; LKTRTrace("i%lu, %.*s\n", inode->i_ino, DLNPair(dentry)); sb = dentry->d_sb; si_read_lock(sb); coo = 0; #if 0 switch (au_flag_test_coo(sb)) { case AuFlag_COO_LEAF: coo = !S_ISDIR(inode->i_mode); break; case AuFlag_COO_ALL: coo = 1; break; } #endif err = au_init_finfo(file); //if (LktrCond) {fi_write_unlock(file); fin_finfo(file); err = -1;} if (unlikely(err)) goto out; if (!coo) { di_read_lock_child(dentry, AUFS_I_RLOCK); bstart = dbstart(dentry); } else { di_write_lock_child(dentry); bstart = dbstart(dentry); if (test_ro(sb, bstart, dentry->d_inode)) { err = do_coo(dentry, bstart); if (err) { di_write_unlock(dentry); goto out_finfo; } bstart = dbstart(dentry); } di_downgrade_lock(dentry, AUFS_I_RLOCK); } // todo: remove this extra locks dir = dentry->d_parent->d_inode; if (!IS_ROOT(dentry)) ii_read_lock_parent(dir); h_dir = au_h_iptr_i(dir, bstart); hdir_lock(h_dir, dir, bstart); err = open(file, file->f_flags); //if (LktrCond) err = -1; hdir_unlock(h_dir, dir, bstart); if (!IS_ROOT(dentry)) ii_read_unlock(dir); di_read_unlock(dentry, AUFS_I_RLOCK); out_finfo: fi_write_unlock(file); if (unlikely(err)) au_fin_finfo(file); //DbgFile(file); out: si_read_unlock(sb); TraceErr(err); return err; }