diff options
Diffstat (limited to 'fs/aufs/f')
-rw-r--r-- | fs/aufs/f | 298 |
1 files changed, 298 insertions, 0 deletions
diff --git a/fs/aufs/f b/fs/aufs/f new file mode 100644 index 000000000000..500a2ab32cb6 --- /dev/null +++ b/fs/aufs/f @@ -0,0 +1,298 @@ +--- /home/bruce/poky/build/tmp/work-shared/qemux86-64/kernel-source/fs/aufs/i_op.c 2017-12-23 23:06:53.241340968 -0500 ++++ i_op.c 2017-12-23 23:14:58.070185032 -0500 +@@ -1,5 +1,5 @@ + /* +- * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +@@ -31,12 +31,15 @@ + int err; + const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND)); + ++ err = -EPERM; ++ if (write_mask && IS_IMMUTABLE(h_inode)) ++ goto out; ++ + err = -EACCES; +- if ((write_mask && IS_IMMUTABLE(h_inode)) +- || ((mask & MAY_EXEC) +- && S_ISREG(h_inode->i_mode) +- && (path_noexec(h_path) +- || !(h_inode->i_mode & S_IXUGO)))) ++ if (((mask & MAY_EXEC) ++ && S_ISREG(h_inode->i_mode) ++ && (path_noexec(h_path) ++ || !(h_inode->i_mode & S_IXUGO)))) + goto out; + + /* +@@ -249,27 +252,28 @@ + /* ---------------------------------------------------------------------- */ + + struct aopen_node { +- struct hlist_node hlist; ++ struct hlist_bl_node hblist; + struct file *file, *h_file; + }; + + static int au_do_aopen(struct inode *inode, struct file *file) + { +- struct au_sphlhead *aopen; ++ struct hlist_bl_head *aopen; ++ struct hlist_bl_node *pos; + struct aopen_node *node; + struct au_do_open_args args = { +- .no_lock = 1, +- .open = au_do_open_nondir ++ .aopen = 1, ++ .open = au_do_open_nondir + }; + + aopen = &au_sbi(inode->i_sb)->si_aopen; +- spin_lock(&aopen->spin); +- hlist_for_each_entry(node, &aopen->head, hlist) ++ hlist_bl_lock(aopen); ++ hlist_bl_for_each_entry(node, pos, aopen, hblist) + if (node->file == file) { + args.h_file = node->h_file; + break; + } +- spin_unlock(&aopen->spin); ++ hlist_bl_unlock(aopen); + /* AuDebugOn(!args.h_file); */ + + return au_do_open(file, &args); +@@ -279,10 +283,10 @@ + struct file *file, unsigned int open_flag, + umode_t create_mode, int *opened) + { +- int err, h_opened = *opened; ++ int err, unlocked, h_opened = *opened; + unsigned int lkup_flags; + struct dentry *parent, *d; +- struct au_sphlhead *aopen; ++ struct hlist_bl_head *aopen; + struct vfsub_aopen_args args = { + .open_flag = open_flag, + .create_mode = create_mode, +@@ -324,6 +328,7 @@ + || !(open_flag & O_CREAT)) + goto out_no_open; + ++ unlocked = 0; + err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN); + if (unlikely(err)) + goto out; +@@ -354,6 +359,9 @@ + put_filp(args.file); + goto out_unlock; + } ++ di_write_unlock(parent); ++ di_write_unlock(dentry); ++ unlocked = 1; + + /* some filesystems don't set FILE_CREATED while succeeded? */ + *opened |= FILE_CREATED; +@@ -364,17 +372,21 @@ + args.file = NULL; + } + aopen = &au_sbi(dir->i_sb)->si_aopen; +- au_sphl_add(&aopen_node.hlist, aopen); ++ au_hbl_add(&aopen_node.hblist, aopen); + err = finish_open(file, dentry, au_do_aopen, opened); +- au_sphl_del(&aopen_node.hlist, aopen); ++ au_hbl_del(&aopen_node.hblist, aopen); + AuTraceErr(err); + AuDbgFile(file); + if (aopen_node.h_file) + fput(aopen_node.h_file); + + out_unlock: +- di_write_unlock(parent); +- aufs_read_unlock(dentry, AuLock_DW); ++ if (unlocked) ++ si_read_unlock(dentry->d_sb); ++ else { ++ di_write_unlock(parent); ++ aufs_read_unlock(dentry, AuLock_DW); ++ } + AuDbgDentry(dentry); + if (unlikely(err < 0)) + goto out; +@@ -420,10 +432,10 @@ + if (!err && add_entry && !au_ftest_wrdir(add_entry, TMPFILE)) { + h_parent = au_h_dptr(parent, bcpup); + h_dir = d_inode(h_parent); +- inode_lock_nested(h_dir, AuLsc_I_PARENT); ++ vfsub_inode_lock_shared_nested(h_dir, AuLsc_I_PARENT); + err = au_lkup_neg(dentry, bcpup, /*wh*/0); + /* todo: no unlock here */ +- inode_unlock(h_dir); ++ inode_unlock_shared(h_dir); + + AuDbg("bcpup %d\n", bcpup); + if (!err) { +@@ -807,10 +819,10 @@ + a->h_path.dentry = au_h_dptr(dentry, btop); + a->h_inode = d_inode(a->h_path.dentry); + if (ia && (ia->ia_valid & ATTR_SIZE)) { +- inode_lock_nested(a->h_inode, AuLsc_I_CHILD); ++ vfsub_inode_lock_shared_nested(a->h_inode, AuLsc_I_CHILD); + if (ia->ia_size < i_size_read(a->h_inode)) + sz = ia->ia_size; +- inode_unlock(a->h_inode); ++ inode_unlock_shared(a->h_inode); + } + + hi_wh = NULL; +@@ -885,6 +897,10 @@ + inode = d_inode(dentry); + IMustLock(inode); + ++ err = setattr_prepare(dentry, ia); ++ if (unlikely(err)) ++ goto out; ++ + err = -ENOMEM; + a = kzalloc(sizeof(*a), GFP_NOFS); + if (unlikely(!a)) +@@ -903,7 +919,8 @@ + /* currently ftruncate(2) only */ + AuDebugOn(!d_is_reg(dentry)); + file = ia->ia_file; +- err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1); ++ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1, ++ /*fi_lsc*/0); + if (unlikely(err)) + goto out_si; + ia->ia_file = au_hf_top(file); +@@ -993,7 +1010,7 @@ + out_si: + si_read_unlock(sb); + out_kfree: +- au_delayed_kfree(a); ++ kfree(a); + out: + AuTraceErr(err); + return err; +@@ -1028,8 +1045,8 @@ + return err; + } + +-ssize_t au_srxattr(struct dentry *dentry, struct inode *inode, +- struct au_srxattr *arg) ++ssize_t au_sxattr(struct dentry *dentry, struct inode *inode, ++ struct au_sxattr *arg) + { + int err; + struct path h_path; +@@ -1063,13 +1080,11 @@ + arg->u.set.name, arg->u.set.value, + arg->u.set.size, arg->u.set.flags); + break; +- case AU_XATTR_REMOVE: +- err = vfsub_removexattr(h_path.dentry, arg->u.remove.name); +- break; + case AU_ACL_SET: + err = -EOPNOTSUPP; + h_inode = d_inode(h_path.dentry); + if (h_inode->i_op->set_acl) ++ /* this will call posix_acl_update_mode */ + err = h_inode->i_op->set_acl(h_inode, + arg->u.acl_set.acl, + arg->u.acl_set.type); +@@ -1086,7 +1101,7 @@ + di_write_unlock(dentry); + si_read_unlock(sb); + out_kfree: +- au_delayed_kfree(a); ++ kfree(a); + out: + AuTraceErr(err); + return err; +@@ -1123,11 +1138,12 @@ + } + + /* +- * common routine for aufs_getattr() and aufs_getxattr(). ++ * common routine for aufs_getattr() and au_getxattr(). + * returns zero or negative (an error). + * @dentry will be read-locked in success. + */ +-int au_h_path_getattr(struct dentry *dentry, int force, struct path *h_path) ++int au_h_path_getattr(struct dentry *dentry, int force, struct path *h_path, ++ int locked) + { + int err; + unsigned int mnt_flags, sigen; +@@ -1144,6 +1160,9 @@ + mnt_flags = au_mntflags(sb); + udba_none = !!au_opt_test(mnt_flags, UDBA_NONE); + ++ if (unlikely(locked)) ++ goto body; /* skip locking dinfo */ ++ + /* support fstat(2) */ + if (!d_unlinked(dentry) && !udba_none) { + sigen = au_sigen(sb); +@@ -1171,6 +1190,7 @@ + } else + di_read_lock_child(dentry, AuLock_IR); + ++body: + inode = d_inode(dentry); + bindex = au_ibtop(inode); + h_path->mnt = au_sbr_mnt(sb, bindex); +@@ -1209,7 +1229,7 @@ + err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); + if (unlikely(err)) + goto out; +- err = au_h_path_getattr(dentry, /*force*/0, &h_path); ++ err = au_h_path_getattr(dentry, /*force*/0, &h_path, /*locked*/0); + if (unlikely(err)) + goto out_si; + if (unlikely(!h_path.dentry)) +@@ -1290,7 +1310,7 @@ + err = 0; + AuDbg("%pf\n", h_inode->i_op->get_link); + AuDbgDentry(h_dentry); +- ret = h_inode->i_op->get_link(h_dentry, h_inode, done); ++ ret = vfs_get_link(h_dentry, done); + dput(h_dentry); + if (IS_ERR(ret)) + err = PTR_ERR(ret); +@@ -1384,10 +1404,7 @@ + .getattr = aufs_getattr, + + #ifdef CONFIG_AUFS_XATTR +- .setxattr = aufs_setxattr, +- .getxattr = aufs_getxattr, + .listxattr = aufs_listxattr, +- .removexattr = aufs_removexattr, + #endif + + .readlink = generic_readlink, +@@ -1416,10 +1433,7 @@ + .getattr = aufs_getattr, + + #ifdef CONFIG_AUFS_XATTR +- .setxattr = aufs_setxattr, +- .getxattr = aufs_getxattr, + .listxattr = aufs_listxattr, +- .removexattr = aufs_removexattr, + #endif + + .update_time = aufs_update_time, +@@ -1437,10 +1451,7 @@ + .getattr = aufs_getattr, + + #ifdef CONFIG_AUFS_XATTR +- .setxattr = aufs_setxattr, +- .getxattr = aufs_getxattr, + .listxattr = aufs_listxattr, +- .removexattr = aufs_removexattr, + #endif + + .update_time = aufs_update_time |