/* 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; }
int au_is_subdir(struct dentry *d1, struct dentry *d2) { int err; #ifndef AuUse_ISSUBDIR int i, j; struct au_dcsub_pages dpages; struct au_dpage *dpage; struct dentry **dentries; #endif LKTRTrace("%.*s, %.*s\n", DLNPair(d1), DLNPair(d2)); #ifdef AuUse_ISSUBDIR spin_lock(&dcache_lock); err = is_subdir(d1, d2); spin_unlock(&dcache_lock); #else err = au_dpages_init(&dpages, GFP_KERNEL); if (unlikely(err)) goto out; err = au_dcsub_pages_rev(&dpages, d1, /*do_include*/1, NULL, NULL); if (unlikely(err)) goto out_dpages; for (i = dpages.ndpage - 1; !err && i >= 0; i--) { dpage = dpages.dpages + i; dentries = dpage->dentries; for (j = dpage->ndentry - 1; !err && j >= 0; j--) { struct dentry *d; d = dentries[j]; //Dbg("d %.*s\n", DLNPair(d)); err = (d == d2); } } out_dpages: au_dpages_free(&dpages); out: #endif TraceErr(err); return err; }
int au_reopen_nondir(struct file *file) { int err; struct dentry *dentry; aufs_bindex_t bstart, bindex, bend; struct file *hidden_file, *h_file_tmp; dentry = file->f_dentry; LKTRTrace("%.*s\n", DLNPair(dentry)); DEBUG_ON(S_ISDIR(dentry->d_inode->i_mode) || !au_h_dptr(dentry)->d_inode); bstart = dbstart(dentry); h_file_tmp = NULL; if (fbstart(file) == bstart) { hidden_file = au_h_fptr(file); if (file->f_mode == hidden_file->f_mode) return 0; /* success */ h_file_tmp = hidden_file; get_file(h_file_tmp); set_h_fptr(file, bstart, NULL); } DEBUG_ON(fbstart(file) < bstart || ftofi(file)->fi_hfile[0 + bstart].hf_file); hidden_file = hidden_open(dentry, bstart, file->f_flags & ~O_TRUNC); //if (LktrCond) {fput(hidden_file); br_put(stobr(dentry->d_sb, bstart)); //hidden_file = ERR_PTR(-1);} err = PTR_ERR(hidden_file); if (IS_ERR(hidden_file)) goto out; // close all? err = 0; //cpup_file_flags(hidden_file, file); set_fbstart(file, bstart); set_h_fptr(file, bstart, hidden_file); memcpy(&hidden_file->f_ra, &file->f_ra, sizeof(file->f_ra)); //?? /* close lower files */ bend = fbend(file); for (bindex = bstart + 1; bindex <= bend; bindex++) set_h_fptr(file, bindex, NULL); set_fbend(file, bstart); out: if (h_file_tmp) fput(h_file_tmp); TraceErr(err); return err; }
static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex, struct aufs_nhash *whlist, struct inode *dir) { int rmdir_later, err; struct dentry *hidden_dentry; LKTRTrace("%.*s, b%d\n", DLNPair(dentry), bindex); err = rename_whtmp(dentry, bindex); //err = -1; //todo: bug if (unlikely(err)) { au_direval_inc(dentry->d_parent); return err; } hidden_dentry = au_h_dptr_i(dentry, bindex); if (!au_is_nfs(hidden_dentry->d_sb)) { const int dirwh = stosi(dentry->d_sb)->si_dirwh; rmdir_later = (dirwh <= 1); if (!rmdir_later) rmdir_later = is_longer_wh(whlist, bindex, dirwh); if (rmdir_later) return rmdir_later; } err = rmdir_whtmp(hidden_dentry, whlist, bindex, dir, dentry->d_inode); //err = -1; if (unlikely(err)) { IOErr("rmdir %.*s, b%d failed, %d. ignored\n", DLNPair(hidden_dentry), bindex, err); err = 0; } TraceErr(err); return err; }
static int do_coo(struct dentry *dentry, aufs_bindex_t bstart) { int err; struct dentry *parent, *h_parent, *h_dentry; aufs_bindex_t bcpup; struct inode *h_dir, *h_inode, *dir; LKTRTrace("%.*s\n", DLNPair(dentry)); DEBUG_ON(IS_ROOT(dentry)); DiMustWriteLock(dentry); parent = dentry->d_parent; // dget_parent() di_write_lock_parent(parent); bcpup = err = find_rw_parent_br(dentry, bstart); //bcpup = err = find_rw_br(sb, bstart); if (unlikely(err < 0)) { err = 0; // stop copyup, it is not an error goto out; } err = 0; h_parent = au_h_dptr_i(parent, bcpup); if (!h_parent) { err = cpup_dirs(dentry, bcpup, NULL); if (unlikely(err)) goto out; h_parent = au_h_dptr_i(parent, bcpup); } h_dir = h_parent->d_inode; h_dentry = au_h_dptr_i(dentry, bstart); h_inode = h_dentry->d_inode; dir = parent->d_inode; hdir_lock(h_dir, dir, bcpup); hi_lock_child(h_inode); DEBUG_ON(au_h_dptr_i(dentry, bcpup)); err = sio_cpup_simple(dentry, bcpup, -1, au_flags_cpup(CPUP_DTIME, parent)); TraceErr(err); i_unlock(h_inode); hdir_unlock(h_dir, dir, bcpup); out: di_write_unlock(parent); TraceErr(err); return err; }
static int do_revert(int err, struct dentry *wh_dentry, struct dentry *dentry, aufs_bindex_t bwh, struct dtime *dt, int dlgt) { int rerr; rerr = au_unlink_wh_dentry(wh_dentry->d_parent->d_inode, wh_dentry, dentry, dlgt); //rerr = -1; if (!rerr) { set_dbwh(dentry, bwh); dtime_revert(dt, !CPUP_LOCKED_GHDIR); return 0; } IOErr("%.*s reverting whiteout failed(%d, %d)\n", DLNPair(dentry), err, rerr); return -EIO; }
static struct dentry * lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup, struct dtime *dt) { struct dentry *wh_dentry; int err, need_wh; struct dentry *hidden_parent, *parent; struct inode *dir, *h_dir; struct lkup_args lkup; LKTRTrace("%.*s, isdir %d\n", DLNPair(dentry), isdir); err = need_wh = wr_dir_need_wh(dentry, isdir, bcpup, NULL); //err = -1; wh_dentry = ERR_PTR(err); if (unlikely(err < 0)) goto out; parent = dentry->d_parent; dir = parent->d_inode; hidden_parent = au_h_dptr_i(parent, *bcpup); h_dir = hidden_parent->d_inode; hdir_lock(h_dir, dir, *bcpup); dtime_store(dt, parent, hidden_parent); if (!need_wh) return NULL; /* success, no need to create whiteout */ lkup.nfsmnt = au_nfsmnt(dentry->d_sb, *bcpup); lkup.dlgt = need_dlgt(dentry->d_sb); wh_dentry = simple_create_wh(dentry, *bcpup, hidden_parent, &lkup); //wh_dentry = ERR_PTR(-1); if (!IS_ERR(wh_dentry)) goto out; /* success */ /* returns with the parent is locked and wh_dentry is DGETed */ hdir_unlock(h_dir, dir, *bcpup); out: TraceErrPtr(wh_dentry); return wh_dentry; }
static ssize_t xino_fread(readf_t func, struct file *file, void *buf, size_t size, loff_t *pos) { ssize_t err; mm_segment_t oldfs; LKTRTrace("%.*s, sz %lu, *pos %Ld\n", DLNPair(file->f_dentry), (unsigned long)size, *pos); oldfs = get_fs(); set_fs(KERNEL_DS); do { err = func(file, (char __user*)buf, size, pos); } while (err == -EAGAIN || err == -EINTR); set_fs(oldfs); #if 0 if (err > 0) fsnotify_access(file->f_dentry); #endif TraceErr(err); return err; }
static ssize_t xino_fwrite(writef_t func, struct file *file, void *buf, size_t size, loff_t *pos) { ssize_t err; LKTRTrace("%.*s, sz %lu, *pos %Ld\n", DLNPair(file->f_dentry), (unsigned long)size, *pos); // signal block and no wkq? /* * it breaks RLIMIT_FSIZE and normal user's limit, * users should care about quota and real 'filesystem full.' */ if (!is_aufsd(current)) { struct do_xino_fwrite_args args = { .errp = &err, .func = func, .file = file, .buf = buf, .size = size, .pos = pos }; au_wkq_wait(call_do_xino_fwrite, &args, /*dlgt*/0); } else
static struct dentry *lkup_hash(const char *name, struct dentry *parent, int len, struct lkup_args *lkup) { struct dentry *dentry; char *p; unsigned long hash; struct qstr this; unsigned int c; struct nameidata tmp_nd; dentry = ERR_PTR(-EACCES); this.name = name; this.len = len; if (unlikely(!len)) goto out; p = (void*)name; hash = init_name_hash(); while (len--) { c = *p++; if (unlikely(c == '/' || c == '\0')) goto out; hash = partial_name_hash(c, hash); } this.hash = end_name_hash(hash); memset(&tmp_nd, 0, sizeof(tmp_nd)); tmp_nd.dentry = dget(parent); tmp_nd.mnt = mntget(lkup->nfsmnt); #ifndef CONFIG_AUFS_DLGT dentry = __lookup_hash(&this, parent, &tmp_nd); #else if (!lkup->dlgt) dentry = __lookup_hash(&this, parent, &tmp_nd); else { int wkq_err; struct lookup_hash_args args = { .errp = &dentry, .name = &this, .base = parent, .nd = &tmp_nd }; wkq_err = au_wkq_wait(call_lookup_hash, &args, /*dlgt*/1); if (unlikely(wkq_err)) dentry = ERR_PTR(wkq_err); } #endif path_release(&tmp_nd); out: TraceErrPtr(dentry); return dentry; } #elif defined(CONFIG_AUFS_DLGT) static struct dentry *lkup_hash(const char *name, struct dentry *parent, int len, struct lkup_args *lkup) { return ERR_PTR(-ENOSYS); } #endif #ifdef CONFIG_AUFS_DLGT struct lookup_one_len_args { struct dentry **errp; const char *name; struct dentry *parent; int len; }; static void call_lookup_one_len(void *args) { struct lookup_one_len_args *a = args; *a->errp = lookup_one_len(a->name, a->parent, a->len); } #endif /* CONFIG_AUFS_DLGT */ #if defined(CONFIG_AUFS_LHASH_PATCH) || defined(CONFIG_AUFS_DLGT) /* cf. lookup_one_len() in linux/fs/namei.c */ struct dentry *lkup_one(const char *name, struct dentry *parent, int len, struct lkup_args *lkup) { struct dentry *dentry; LKTRTrace("%.*s/%.*s, lkup{%p, %d}\n", DLNPair(parent), len, name, lkup->nfsmnt, lkup->dlgt); if (!lkup->nfsmnt) { #ifndef CONFIG_AUFS_DLGT dentry = lookup_one_len(name, parent, len); #else if (!lkup->dlgt) dentry = lookup_one_len(name, parent, len); else { int wkq_err; struct lookup_one_len_args args = { .errp = &dentry, .name = name, .parent = parent, .len = len }; wkq_err = au_wkq_wait(call_lookup_one_len, &args, /*dlgt*/1); if (unlikely(wkq_err)) dentry = ERR_PTR(wkq_err); } #endif } else
int aufs_rmdir(struct inode *dir, struct dentry *dentry) { int err, rmdir_later; struct inode *inode, *hidden_dir; struct dentry *parent, *wh_dentry, *hidden_dentry, *hidden_parent; struct dtime dt; aufs_bindex_t bwh, bindex, bstart; struct rmdir_whtmp_arg *arg; struct aufs_nhash *whlist; LKTRTrace("i%lu, %.*s\n", dir->i_ino, DLNPair(dentry)); IMustLock(dir); inode = dentry->d_inode; if (unlikely(!inode)) return -ENOENT; // possible? IMustLock(inode); whlist = nhash_new(GFP_KERNEL); err = PTR_ERR(whlist); if (IS_ERR(whlist)) goto out; err = -ENOMEM; arg = kmalloc(sizeof(*arg), GFP_KERNEL); //arg = NULL; if (unlikely(!arg)) goto out_whlist; aufs_read_lock(dentry, AUFS_D_WLOCK); parent = dentry->d_parent; di_write_lock_parent(parent); err = test_empty(dentry, whlist); //err = -1; if (unlikely(err)) goto out_arg; bstart = dbstart(dentry); bwh = dbwh(dentry); bindex = -1; wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/ 1, &bindex, &dt); //wh_dentry = ERR_PTR(-1); err = PTR_ERR(wh_dentry); if (IS_ERR(wh_dentry)) goto out_arg; hidden_dentry = au_h_dptr(dentry); dget(hidden_dentry); hidden_parent = hidden_dentry->d_parent; hidden_dir = hidden_parent->d_inode; rmdir_later = 0; if (bindex == bstart) { IMustLock(hidden_dir); err = renwh_and_rmdir(dentry, bstart, whlist, dir); //err = -1; if (err > 0) { rmdir_later = err; err = 0; } } else { DEBUG_ON(!wh_dentry); hidden_parent = wh_dentry->d_parent; DEBUG_ON(hidden_parent != au_h_dptr_i(parent, bindex)); hidden_dir = hidden_parent->d_inode; IMustLock(hidden_dir); err = 0; } if (!err) { au_reset_hinotify(inode, /*flags*/0); inode->i_nlink = 0; set_dbdiropq(dentry, -1); epilog(dir, dentry, bindex); if (rmdir_later) { kick_rmdir_whtmp(hidden_dentry, whlist, bstart, dir, inode, arg); arg = NULL; } goto out_unlock; /* success */ } /* revert */ LKTRLabel(revert); if (wh_dentry) { int rerr; rerr = do_revert(err, wh_dentry, dentry, bwh, &dt, need_dlgt(dir->i_sb)); if (rerr) err = rerr; } out_unlock: hdir_unlock(hidden_dir, dir, bindex); dput(wh_dentry); dput(hidden_dentry); out_arg: di_write_unlock(parent); aufs_read_unlock(dentry, AUFS_D_WLOCK); kfree(arg); out_whlist: nhash_del(whlist); out: TraceErr(err); return err; }
/* 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; }
int aufs_unlink(struct inode *dir, struct dentry *dentry) { int err, dlgt; struct inode *inode, *hidden_dir; struct dentry *parent, *wh_dentry, *hidden_dentry, *hidden_parent; struct dtime dt; aufs_bindex_t bwh, bindex, bstart; LKTRTrace("i%lu, %.*s\n", dir->i_ino, DLNPair(dentry)); IMustLock(dir); inode = dentry->d_inode; if (unlikely(!inode)) return -ENOENT; // possible? IMustLock(inode); aufs_read_lock(dentry, AUFS_D_WLOCK); parent = dentry->d_parent; di_write_lock_parent(parent); bstart = dbstart(dentry); bwh = dbwh(dentry); bindex = -1; wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt); //wh_dentry = ERR_PTR(-1); err = PTR_ERR(wh_dentry); if (IS_ERR(wh_dentry)) goto out; dlgt = need_dlgt(dir->i_sb); hidden_dentry = au_h_dptr(dentry); dget(hidden_dentry); hidden_parent = hidden_dentry->d_parent; hidden_dir = hidden_parent->d_inode; if (bindex == bstart) { err = vfsub_unlink(hidden_dir, hidden_dentry, dlgt); //err = -1; } else { DEBUG_ON(!wh_dentry); hidden_parent = wh_dentry->d_parent; DEBUG_ON(hidden_parent != au_h_dptr_i(parent, bindex)); hidden_dir = hidden_parent->d_inode; IMustLock(hidden_dir); err = 0; } if (!err) { inode->i_nlink--; epilog(dir, dentry, bindex); goto out_unlock; /* success */ } /* revert */ if (wh_dentry) { int rerr; rerr = do_revert(err, wh_dentry, dentry, bwh, &dt, dlgt); if (rerr) err = rerr; } out_unlock: hdir_unlock(hidden_dir, dir, bindex); dput(wh_dentry); dput(hidden_dentry); out: di_write_unlock(parent); aufs_read_unlock(dentry, AUFS_D_WLOCK); 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))
/* * copyup the deleted file for writing. */ static int cpup_wh_file(struct file *file, aufs_bindex_t bdst, loff_t len) { int err; struct dentry *dentry, *parent, *hidden_parent, *tmp_dentry; struct dentry *hidden_dentry_bstart, *hidden_dentry_bdst; struct inode *hidden_dir; aufs_bindex_t bstart; struct aufs_dinfo *dinfo; struct dtime dt; struct lkup_args lkup; struct super_block *sb; dentry = file->f_dentry; LKTRTrace("%.*s, bdst %d, len %Lu\n", DLNPair(dentry), bdst, len); DEBUG_ON(S_ISDIR(dentry->d_inode->i_mode) || !(file->f_mode & FMODE_WRITE)); DiMustWriteLock(dentry); parent = dentry->d_parent; IiMustAnyLock(parent->d_inode); hidden_parent = au_h_dptr_i(parent, bdst); DEBUG_ON(!hidden_parent); hidden_dir = hidden_parent->d_inode; DEBUG_ON(!hidden_dir); IMustLock(hidden_dir); sb = parent->d_sb; lkup.nfsmnt = au_nfsmnt(sb, bdst); lkup.dlgt = need_dlgt(sb); tmp_dentry = lkup_whtmp(hidden_parent, &dentry->d_name, &lkup); //if (LktrCond) {dput(tmp_dentry); tmp_dentry = ERR_PTR(-1);} err = PTR_ERR(tmp_dentry); if (IS_ERR(tmp_dentry)) goto out; dtime_store(&dt, parent, hidden_parent); dinfo = dtodi(dentry); bstart = dinfo->di_bstart; hidden_dentry_bdst = dinfo->di_hdentry[0 + bdst].hd_dentry; hidden_dentry_bstart = dinfo->di_hdentry[0 + bstart].hd_dentry; dinfo->di_bstart = bdst; dinfo->di_hdentry[0 + bdst].hd_dentry = tmp_dentry; dinfo->di_hdentry[0 + bstart].hd_dentry = au_h_fptr(file)->f_dentry; err = cpup_single(dentry, bdst, bstart, len, au_flags_cpup(!CPUP_DTIME, parent)); //if (LktrCond) err = -1; if (!err) err = au_reopen_nondir(file); //err = -1; if (unlikely(err)) { dinfo->di_hdentry[0 + bstart].hd_dentry = hidden_dentry_bstart; dinfo->di_hdentry[0 + bdst].hd_dentry = hidden_dentry_bdst; dinfo->di_bstart = bstart; goto out_tmp; } DEBUG_ON(!d_unhashed(dentry)); err = vfsub_unlink(hidden_dir, tmp_dentry, lkup.dlgt); //if (LktrCond) err = -1; if (unlikely(err)) { IOErr("failed remove copied-up tmp file %.*s(%d)\n", DLNPair(tmp_dentry), err); err = -EIO; } dtime_revert(&dt, !CPUP_LOCKED_GHDIR); out_tmp: dput(tmp_dentry); out: TraceErr(err); return err; }
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; }