--- /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