Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull vfs fixes from Al Viro:
 "Followups to the parallel lookup work:

   - update docs

   - restore killability of the places that used to take ->i_mutex
     killably now that we have down_write_killable() merged

   - Additionally, it turns out that I missed a prerequisite for
     security_d_instantiate() stuff - ->getxattr() wasn't the only thing
     that could be called before dentry is attached to inode; with smack
     we needed the same treatment applied to ->setxattr() as well"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  switch ->setxattr() to passing dentry and inode separately
  switch xattr_handler->set() to passing dentry and inode separately
  restore killability of old mutex_lock_killable(&inode->i_mutex) users
  add down_write_killable_nested()
  update D/f/directory-locking
This commit is contained in:
Linus Torvalds 2016-05-27 17:14:05 -07:00
commit d102a56edb
58 changed files with 265 additions and 209 deletions

View file

@ -1,30 +1,37 @@
Locking scheme used for directory operations is based on two
kinds of locks - per-inode (->i_mutex) and per-filesystem
kinds of locks - per-inode (->i_rwsem) and per-filesystem
(->s_vfs_rename_mutex).
When taking the i_mutex on multiple non-directory objects, we
When taking the i_rwsem on multiple non-directory objects, we
always acquire the locks in order by increasing address. We'll call
that "inode pointer" order in the following.
For our purposes all operations fall in 5 classes:
1) read access. Locking rules: caller locks directory we are accessing.
The lock is taken shared.
2) object creation. Locking rules: same as above.
2) object creation. Locking rules: same as above, but the lock is taken
exclusive.
3) object removal. Locking rules: caller locks parent, finds victim,
locks victim and calls the method.
locks victim and calls the method. Locks are exclusive.
4) rename() that is _not_ cross-directory. Locking rules: caller locks
the parent and finds source and target. If target already exists, lock
it. If source is a non-directory, lock it. If that means we need to
lock both, lock them in inode pointer order.
the parent and finds source and target. In case of exchange (with
RENAME_EXCHANGE in rename2() flags argument) lock both. In any case,
if the target already exists, lock it. If the source is a non-directory,
lock it. If we need to lock both, lock them in inode pointer order.
Then call the method. All locks are exclusive.
NB: we might get away with locking the the source (and target in exchange
case) shared.
5) link creation. Locking rules:
* lock parent
* check that source is not a directory
* lock source
* call the method.
All locks are exclusive.
6) cross-directory rename. The trickiest in the whole bunch. Locking
rules:
@ -35,11 +42,12 @@ rules:
fail with -ENOTEMPTY
* if new parent is equal to or is a descendent of source
fail with -ELOOP
* If target exists, lock it. If source is a non-directory, lock
it. In case that means we need to lock both source and target,
do so in inode pointer order.
* If it's an exchange, lock both the source and the target.
* If the target exists, lock it. If the source is a non-directory,
lock it. If we need to lock both, do so in inode pointer order.
* call the method.
All ->i_rwsem are taken exclusive. Again, we might get away with locking
the the source (and target in exchange case) shared.
The rules above obviously guarantee that all directories that are going to be
read, modified or removed by method will be locked by caller.
@ -73,7 +81,7 @@ objects - A < B iff A is an ancestor of B.
attempt to acquire some lock and already holds at least one lock. Let's
consider the set of contended locks. First of all, filesystem lock is
not contended, since any process blocked on it is not holding any locks.
Thus all processes are blocked on ->i_mutex.
Thus all processes are blocked on ->i_rwsem.
By (3), any process holding a non-directory lock can only be
waiting on another non-directory lock with a larger address. Therefore

View file

@ -578,3 +578,10 @@ in your dentry operations instead.
--
[mandatory]
->atomic_open() calls without O_CREAT may happen in parallel.
--
[mandatory]
->setxattr() and xattr_handler.set() get dentry and inode passed separately.
dentry might be yet to be attached to inode, so do _not_ use its ->d_inode
in the instances. Rationale: !@#!@# security_d_instantiate() needs to be
called before we attach dentry to inode and !@#!@##!@$!$#!@#$!@$!@$ smack
->d_instantiate() uses not just ->getxattr() but ->setxattr() as well.

View file

@ -976,8 +976,8 @@ static inline __u64 ll_file_maxbytes(struct inode *inode)
}
/* llite/xattr.c */
int ll_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags);
int ll_setxattr(struct dentry *dentry, struct inode *inode,
const char *name, const void *value, size_t size, int flags);
ssize_t ll_getxattr(struct dentry *dentry, struct inode *inode,
const char *name, void *buffer, size_t size);
ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size);

View file

@ -211,11 +211,9 @@ int ll_setxattr_common(struct inode *inode, const char *name,
return 0;
}
int ll_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
int ll_setxattr(struct dentry *dentry, struct inode *inode,
const char *name, const void *value, size_t size, int flags)
{
struct inode *inode = d_inode(dentry);
LASSERT(inode);
LASSERT(name);

View file

@ -239,13 +239,13 @@ static int v9fs_xattr_get_acl(const struct xattr_handler *handler,
}
static int v9fs_xattr_set_acl(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
struct dentry *dentry, struct inode *inode,
const char *name, const void *value,
size_t size, int flags)
{
int retval;
struct posix_acl *acl;
struct v9fs_session_info *v9ses;
struct inode *inode = d_inode(dentry);
v9ses = v9fs_dentry2v9ses(dentry);
/*

View file

@ -147,8 +147,9 @@ static int v9fs_xattr_handler_get(const struct xattr_handler *handler,
}
static int v9fs_xattr_handler_set(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
struct dentry *dentry, struct inode *inode,
const char *name, const void *value,
size_t size, int flags)
{
const char *full_name = xattr_full_name(handler, name);

View file

@ -100,8 +100,8 @@ static int bad_inode_setattr(struct dentry *direntry, struct iattr *attrs)
return -EIO;
}
static int bad_inode_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
static int bad_inode_setxattr(struct dentry *dentry, struct inode *inode,
const char *name, const void *value, size_t size, int flags)
{
return -EIO;
}

View file

@ -846,11 +846,9 @@ static noinline int btrfs_mksubvol(struct path *parent,
struct dentry *dentry;
int error;
inode_lock_nested(dir, I_MUTEX_PARENT);
// XXX: should've been
// mutex_lock_killable_nested(&dir->i_mutex, I_MUTEX_PARENT);
// if (error == -EINTR)
// return error;
error = down_write_killable_nested(&dir->i_rwsem, I_MUTEX_PARENT);
if (error == -EINTR)
return error;
dentry = lookup_one_len(name, parent->dentry, namelen);
error = PTR_ERR(dentry);
@ -2377,11 +2375,9 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
goto out;
inode_lock_nested(dir, I_MUTEX_PARENT);
// XXX: should've been
// err = mutex_lock_killable_nested(&dir->i_mutex, I_MUTEX_PARENT);
// if (err == -EINTR)
// goto out_drop_write;
err = down_write_killable_nested(&dir->i_rwsem, I_MUTEX_PARENT);
if (err == -EINTR)
goto out_drop_write;
dentry = lookup_one_len(vol_args->name, parent, namelen);
if (IS_ERR(dentry)) {
err = PTR_ERR(dentry);
@ -2571,7 +2567,7 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
dput(dentry);
out_unlock_dir:
inode_unlock(dir);
//out_drop_write:
out_drop_write:
mnt_drop_write_file(file);
out:
kfree(vol_args);

View file

@ -380,23 +380,21 @@ static int btrfs_xattr_handler_get(const struct xattr_handler *handler,
}
static int btrfs_xattr_handler_set(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *buffer, size_t size,
int flags)
struct dentry *unused, struct inode *inode,
const char *name, const void *buffer,
size_t size, int flags)
{
struct inode *inode = d_inode(dentry);
name = xattr_full_name(handler, name);
return __btrfs_setxattr(NULL, inode, name, buffer, size, flags);
}
static int btrfs_xattr_handler_set_prop(const struct xattr_handler *handler,
struct dentry *dentry,
struct dentry *unused, struct inode *inode,
const char *name, const void *value,
size_t size, int flags)
{
name = xattr_full_name(handler, name);
return btrfs_set_prop(d_inode(dentry), name, value, size, flags);
return btrfs_set_prop(inode, name, value, size, flags);
}
static const struct xattr_handler btrfs_security_xattr_handler = {

View file

@ -1056,12 +1056,13 @@ static int ceph_get_xattr_handler(const struct xattr_handler *handler,
}
static int ceph_set_xattr_handler(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
struct dentry *unused, struct inode *inode,
const char *name, const void *value,
size_t size, int flags)
{
if (!ceph_is_valid_xattr(name))
return -EOPNOTSUPP;
return __ceph_setxattr(d_inode(dentry), name, value, size, flags);
return __ceph_setxattr(inode, name, value, size, flags);
}
const struct xattr_handler ceph_other_xattr_handler = {

View file

@ -39,8 +39,9 @@
enum { XATTR_USER, XATTR_CIFS_ACL, XATTR_ACL_ACCESS, XATTR_ACL_DEFAULT };
static int cifs_xattr_set(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
struct dentry *dentry, struct inode *inode,
const char *name, const void *value,
size_t size, int flags)
{
int rc = -EOPNOTSUPP;
unsigned int xid;
@ -99,12 +100,12 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
if (value &&
pTcon->ses->server->ops->set_acl)
rc = pTcon->ses->server->ops->set_acl(pacl,
size, d_inode(dentry),
size, inode,
full_path, CIFS_ACL_DACL);
else
rc = -EOPNOTSUPP;
if (rc == 0) /* force revalidate of the inode */
CIFS_I(d_inode(dentry))->time = 0;
CIFS_I(inode)->time = 0;
kfree(pacl);
}
#endif /* CONFIG_CIFS_ACL */

View file

@ -1141,12 +1141,13 @@ ecryptfs_write_metadata_to_contents(struct inode *ecryptfs_inode,
static int
ecryptfs_write_metadata_to_xattr(struct dentry *ecryptfs_dentry,
struct inode *ecryptfs_inode,
char *page_virt, size_t size)
{
int rc;
rc = ecryptfs_setxattr(ecryptfs_dentry, ECRYPTFS_XATTR_NAME, page_virt,
size, 0);
rc = ecryptfs_setxattr(ecryptfs_dentry, ecryptfs_inode,
ECRYPTFS_XATTR_NAME, page_virt, size, 0);
return rc;
}
@ -1215,8 +1216,8 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry,
goto out_free;
}
if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
rc = ecryptfs_write_metadata_to_xattr(ecryptfs_dentry, virt,
size);
rc = ecryptfs_write_metadata_to_xattr(ecryptfs_dentry, ecryptfs_inode,
virt, size);
else
rc = ecryptfs_write_metadata_to_contents(ecryptfs_inode, virt,
virt_len);

View file

@ -609,8 +609,8 @@ ssize_t
ecryptfs_getxattr_lower(struct dentry *lower_dentry, struct inode *lower_inode,
const char *name, void *value, size_t size);
int
ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,
size_t size, int flags);
ecryptfs_setxattr(struct dentry *dentry, struct inode *inode, const char *name,
const void *value, size_t size, int flags);
int ecryptfs_read_xattr_region(char *page_virt, struct inode *ecryptfs_inode);
#ifdef CONFIG_ECRYPT_FS_MESSAGING
int ecryptfs_process_response(struct ecryptfs_daemon *daemon,

View file

@ -1001,7 +1001,8 @@ static int ecryptfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
}
int
ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,
ecryptfs_setxattr(struct dentry *dentry, struct inode *inode,
const char *name, const void *value,
size_t size, int flags)
{
int rc = 0;
@ -1014,8 +1015,8 @@ ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,
}
rc = vfs_setxattr(lower_dentry, name, value, size, flags);
if (!rc && d_really_is_positive(dentry))
fsstack_copy_attr_all(d_inode(dentry), d_inode(lower_dentry));
if (!rc && inode)
fsstack_copy_attr_all(inode, d_inode(lower_dentry));
out:
return rc;
}

View file

@ -442,7 +442,8 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode)
if (size < 0)
size = 8;
put_unaligned_be64(i_size_read(ecryptfs_inode), xattr_virt);
rc = lower_inode->i_op->setxattr(lower_dentry, ECRYPTFS_XATTR_NAME,
rc = lower_inode->i_op->setxattr(lower_dentry, lower_inode,
ECRYPTFS_XATTR_NAME,
xattr_virt, size, 0);
inode_unlock(lower_inode);
if (rc)

View file

@ -18,10 +18,11 @@ ext2_xattr_security_get(const struct xattr_handler *handler,
static int
ext2_xattr_security_set(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
struct dentry *unused, struct inode *inode,
const char *name, const void *value,
size_t size, int flags)
{
return ext2_xattr_set(d_inode(dentry), EXT2_XATTR_INDEX_SECURITY, name,
return ext2_xattr_set(inode, EXT2_XATTR_INDEX_SECURITY, name,
value, size, flags);
}

View file

@ -25,10 +25,11 @@ ext2_xattr_trusted_get(const struct xattr_handler *handler,
static int
ext2_xattr_trusted_set(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
struct dentry *unused, struct inode *inode,
const char *name, const void *value,
size_t size, int flags)
{
return ext2_xattr_set(d_inode(dentry), EXT2_XATTR_INDEX_TRUSTED, name,
return ext2_xattr_set(inode, EXT2_XATTR_INDEX_TRUSTED, name,
value, size, flags);
}

View file

@ -29,13 +29,14 @@ ext2_xattr_user_get(const struct xattr_handler *handler,
static int
ext2_xattr_user_set(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
struct dentry *unused, struct inode *inode,
const char *name, const void *value,
size_t size, int flags)
{
if (!test_opt(dentry->d_sb, XATTR_USER))
if (!test_opt(inode->i_sb, XATTR_USER))
return -EOPNOTSUPP;
return ext2_xattr_set(d_inode(dentry), EXT2_XATTR_INDEX_USER,
return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER,
name, value, size, flags);
}

View file

@ -22,10 +22,11 @@ ext4_xattr_security_get(const struct xattr_handler *handler,
static int
ext4_xattr_security_set(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
struct dentry *unused, struct inode *inode,
const char *name, const void *value,
size_t size, int flags)
{
return ext4_xattr_set(d_inode(dentry), EXT4_XATTR_INDEX_SECURITY,
return ext4_xattr_set(inode, EXT4_XATTR_INDEX_SECURITY,
name, value, size, flags);
}

View file

@ -29,10 +29,11 @@ ext4_xattr_trusted_get(const struct xattr_handler *handler,
static int
ext4_xattr_trusted_set(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
struct dentry *unused, struct inode *inode,
const char *name, const void *value,
size_t size, int flags)
{
return ext4_xattr_set(d_inode(dentry), EXT4_XATTR_INDEX_TRUSTED,
return ext4_xattr_set(inode, EXT4_XATTR_INDEX_TRUSTED,
name, value, size, flags);
}

View file

@ -30,12 +30,13 @@ ext4_xattr_user_get(const struct xattr_handler *handler,
static int
ext4_xattr_user_set(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
struct dentry *unused, struct inode *inode,
const char *name, const void *value,
size_t size, int flags)
{
if (!test_opt(dentry->d_sb, XATTR_USER))
if (!test_opt(inode->i_sb, XATTR_USER))
return -EOPNOTSUPP;
return ext4_xattr_set(d_inode(dentry), EXT4_XATTR_INDEX_USER,
return ext4_xattr_set(inode, EXT4_XATTR_INDEX_USER,
name, value, size, flags);
}

View file

@ -50,10 +50,11 @@ static int f2fs_xattr_generic_get(const struct xattr_handler *handler,
}
static int f2fs_xattr_generic_set(const struct xattr_handler *handler,
struct dentry *dentry, const char *name, const void *value,
struct dentry *unused, struct inode *inode,
const char *name, const void *value,
size_t size, int flags)
{
struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
switch (handler->flags) {
case F2FS_XATTR_INDEX_USER:
@ -69,7 +70,7 @@ static int f2fs_xattr_generic_set(const struct xattr_handler *handler,
default:
return -EINVAL;
}
return f2fs_setxattr(d_inode(dentry), handler->flags, name,
return f2fs_setxattr(inode, handler->flags, name,
value, size, NULL, flags);
}
@ -95,11 +96,10 @@ static int f2fs_xattr_advise_get(const struct xattr_handler *handler,
}
static int f2fs_xattr_advise_set(const struct xattr_handler *handler,
struct dentry *dentry, const char *name, const void *value,
struct dentry *unused, struct inode *inode,
const char *name, const void *value,
size_t size, int flags)
{
struct inode *inode = d_inode(dentry);
if (!inode_owner_or_capable(inode))
return -EPERM;
if (value == NULL)

View file

@ -1719,10 +1719,10 @@ static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
return fuse_update_attributes(inode, stat, NULL, NULL);
}
static int fuse_setxattr(struct dentry *entry, const char *name,
const void *value, size_t size, int flags)
static int fuse_setxattr(struct dentry *unused, struct inode *inode,
const char *name, const void *value,
size_t size, int flags)
{
struct inode *inode = d_inode(entry);
struct fuse_conn *fc = get_fuse_conn(inode);
FUSE_ARGS(args);
struct fuse_setxattr_in inarg;

View file

@ -1251,10 +1251,10 @@ int __gfs2_xattr_set(struct inode *inode, const char *name,
}
static int gfs2_xattr_set(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
struct dentry *unused, struct inode *inode,
const char *name, const void *value,
size_t size, int flags)
{
struct inode *inode = d_inode(dentry);
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_holder gh;
int ret;

View file

@ -13,10 +13,10 @@
#include "hfs_fs.h"
#include "btree.h"
int hfs_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
int hfs_setxattr(struct dentry *unused, struct inode *inode,
const char *name, const void *value,
size_t size, int flags)
{
struct inode *inode = d_inode(dentry);
struct hfs_find_data fd;
hfs_cat_rec rec;
struct hfs_cat_file *file;

View file

@ -212,7 +212,7 @@ extern void hfs_evict_inode(struct inode *);
extern void hfs_delete_inode(struct inode *);
/* attr.c */
extern int hfs_setxattr(struct dentry *dentry, const char *name,
extern int hfs_setxattr(struct dentry *dentry, struct inode *inode, const char *name,
const void *value, size_t size, int flags);
extern ssize_t hfs_getxattr(struct dentry *dentry, struct inode *inode,
const char *name, void *value, size_t size);

View file

@ -424,7 +424,7 @@ static int copy_name(char *buffer, const char *xattr_name, int name_len)
return len;
}
int hfsplus_setxattr(struct dentry *dentry, const char *name,
int hfsplus_setxattr(struct inode *inode, const char *name,
const void *value, size_t size, int flags,
const char *prefix, size_t prefixlen)
{
@ -437,8 +437,7 @@ int hfsplus_setxattr(struct dentry *dentry, const char *name,
return -ENOMEM;
strcpy(xattr_name, prefix);
strcpy(xattr_name + prefixlen, name);
res = __hfsplus_setxattr(d_inode(dentry), xattr_name, value, size,
flags);
res = __hfsplus_setxattr(inode, xattr_name, value, size, flags);
kfree(xattr_name);
return res;
}
@ -864,8 +863,9 @@ static int hfsplus_osx_getxattr(const struct xattr_handler *handler,
}
static int hfsplus_osx_setxattr(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *buffer, size_t size, int flags)
struct dentry *unused, struct inode *inode,
const char *name, const void *buffer,
size_t size, int flags)
{
/*
* Don't allow setting properly prefixed attributes
@ -880,7 +880,7 @@ static int hfsplus_osx_setxattr(const struct xattr_handler *handler,
* creates), so we pass the name through unmodified (after
* ensuring it doesn't conflict with another namespace).
*/
return __hfsplus_setxattr(d_inode(dentry), name, buffer, size, flags);
return __hfsplus_setxattr(inode, name, buffer, size, flags);
}
const struct xattr_handler hfsplus_xattr_osx_handler = {

View file

@ -21,7 +21,7 @@ extern const struct xattr_handler *hfsplus_xattr_handlers[];
int __hfsplus_setxattr(struct inode *inode, const char *name,
const void *value, size_t size, int flags);
int hfsplus_setxattr(struct dentry *dentry, const char *name,
int hfsplus_setxattr(struct inode *inode, const char *name,
const void *value, size_t size, int flags,
const char *prefix, size_t prefixlen);

View file

@ -23,10 +23,11 @@ static int hfsplus_security_getxattr(const struct xattr_handler *handler,
}
static int hfsplus_security_setxattr(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *buffer, size_t size, int flags)
struct dentry *unused, struct inode *inode,
const char *name, const void *buffer,
size_t size, int flags)
{
return hfsplus_setxattr(dentry, name, buffer, size, flags,
return hfsplus_setxattr(inode, name, buffer, size, flags,
XATTR_SECURITY_PREFIX,
XATTR_SECURITY_PREFIX_LEN);
}

View file

@ -21,10 +21,11 @@ static int hfsplus_trusted_getxattr(const struct xattr_handler *handler,
}
static int hfsplus_trusted_setxattr(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *buffer, size_t size, int flags)
struct dentry *unused, struct inode *inode,
const char *name, const void *buffer,
size_t size, int flags)
{
return hfsplus_setxattr(dentry, name, buffer, size, flags,
return hfsplus_setxattr(inode, name, buffer, size, flags,
XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
}

View file

@ -21,10 +21,11 @@ static int hfsplus_user_getxattr(const struct xattr_handler *handler,
}
static int hfsplus_user_setxattr(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *buffer, size_t size, int flags)
struct dentry *unused, struct inode *inode,
const char *name, const void *buffer,
size_t size, int flags)
{
return hfsplus_setxattr(dentry, name, buffer, size, flags,
return hfsplus_setxattr(inode, name, buffer, size, flags,
XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
}

View file

@ -57,10 +57,11 @@ static int jffs2_security_getxattr(const struct xattr_handler *handler,
}
static int jffs2_security_setxattr(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *buffer, size_t size, int flags)
struct dentry *unused, struct inode *inode,
const char *name, const void *buffer,
size_t size, int flags)
{
return do_jffs2_setxattr(d_inode(dentry), JFFS2_XPREFIX_SECURITY,
return do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY,
name, buffer, size, flags);
}

View file

@ -25,10 +25,11 @@ static int jffs2_trusted_getxattr(const struct xattr_handler *handler,
}
static int jffs2_trusted_setxattr(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *buffer, size_t size, int flags)
struct dentry *unused, struct inode *inode,
const char *name, const void *buffer,
size_t size, int flags)
{
return do_jffs2_setxattr(d_inode(dentry), JFFS2_XPREFIX_TRUSTED,
return do_jffs2_setxattr(inode, JFFS2_XPREFIX_TRUSTED,
name, buffer, size, flags);
}

View file

@ -25,10 +25,11 @@ static int jffs2_user_getxattr(const struct xattr_handler *handler,
}
static int jffs2_user_setxattr(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *buffer, size_t size, int flags)
struct dentry *unused, struct inode *inode,
const char *name, const void *buffer,
size_t size, int flags)
{
return do_jffs2_setxattr(d_inode(dentry), JFFS2_XPREFIX_USER,
return do_jffs2_setxattr(inode, JFFS2_XPREFIX_USER,
name, buffer, size, flags);
}

View file

@ -943,11 +943,10 @@ static int jfs_xattr_get(const struct xattr_handler *handler,
}
static int jfs_xattr_set(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
struct dentry *unused, struct inode *inode,
const char *name, const void *value,
size_t size, int flags)
{
struct inode *inode = d_inode(dentry);
name = xattr_full_name(handler, name);
return __jfs_xattr_set(inode, name, value, size, flags);
}
@ -962,11 +961,10 @@ static int jfs_xattr_get_os2(const struct xattr_handler *handler,
}
static int jfs_xattr_set_os2(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
struct dentry *unused, struct inode *inode,
const char *name, const void *value,
size_t size, int flags)
{
struct inode *inode = d_inode(dentry);
if (is_known_namespace(name))
return -EOPNOTSUPP;
return __jfs_xattr_set(inode, name, value, size, flags);

View file

@ -160,10 +160,11 @@ static int kernfs_node_setsecdata(struct kernfs_node *kn, void **secdata,
return 0;
}
int kernfs_iop_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
int kernfs_iop_setxattr(struct dentry *unused, struct inode *inode,
const char *name, const void *value,
size_t size, int flags)
{
struct kernfs_node *kn = dentry->d_fsdata;
struct kernfs_node *kn = inode->i_private;
struct kernfs_iattrs *attrs;
void *secdata;
int error;
@ -175,11 +176,11 @@ int kernfs_iop_setxattr(struct dentry *dentry, const char *name,
if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)) {
const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
error = security_inode_setsecurity(d_inode(dentry), suffix,
error = security_inode_setsecurity(inode, suffix,
value, size, flags);
if (error)
return error;
error = security_inode_getsecctx(d_inode(dentry),
error = security_inode_getsecctx(inode,
&secdata, &secdata_len);
if (error)
return error;

View file

@ -81,7 +81,8 @@ int kernfs_iop_permission(struct inode *inode, int mask);
int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr);
int kernfs_iop_getattr(struct vfsmount *mnt, struct dentry *dentry,
struct kstat *stat);
int kernfs_iop_setxattr(struct dentry *dentry, const char *name, const void *value,
int kernfs_iop_setxattr(struct dentry *dentry, struct inode *inode,
const char *name, const void *value,
size_t size, int flags);
int kernfs_iop_removexattr(struct dentry *dentry, const char *name);
ssize_t kernfs_iop_getxattr(struct dentry *dentry, struct inode *inode,

View file

@ -1118,8 +1118,9 @@ static int empty_dir_setattr(struct dentry *dentry, struct iattr *attr)
return -EPERM;
}
static int empty_dir_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
static int empty_dir_setxattr(struct dentry *dentry, struct inode *inode,
const char *name, const void *value,
size_t size, int flags)
{
return -EOPNOTSUPP;
}

View file

@ -5015,12 +5015,11 @@ static int nfs4_do_set_security_label(struct inode *inode,
}
static int
nfs4_set_security_label(struct dentry *dentry, const void *buf, size_t buflen)
nfs4_set_security_label(struct inode *inode, const void *buf, size_t buflen)
{
struct nfs4_label ilabel, *olabel = NULL;
struct nfs_fattr fattr;
struct rpc_cred *cred;
struct inode *inode = d_inode(dentry);
int status;
if (!nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL))
@ -6281,11 +6280,11 @@ nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_state *lsp)
#define XATTR_NAME_NFSV4_ACL "system.nfs4_acl"
static int nfs4_xattr_set_nfs4_acl(const struct xattr_handler *handler,
struct dentry *dentry, const char *key,
const void *buf, size_t buflen,
int flags)
struct dentry *unused, struct inode *inode,
const char *key, const void *buf,
size_t buflen, int flags)
{
return nfs4_proc_set_acl(d_inode(dentry), buf, buflen);
return nfs4_proc_set_acl(inode, buf, buflen);
}
static int nfs4_xattr_get_nfs4_acl(const struct xattr_handler *handler,
@ -6303,12 +6302,12 @@ static bool nfs4_xattr_list_nfs4_acl(struct dentry *dentry)
#ifdef CONFIG_NFS_V4_SECURITY_LABEL
static int nfs4_xattr_set_nfs4_label(const struct xattr_handler *handler,
struct dentry *dentry, const char *key,
const void *buf, size_t buflen,
int flags)
struct dentry *unused, struct inode *inode,
const char *key, const void *buf,
size_t buflen, int flags)
{
if (security_ismaclabel(key))
return nfs4_set_security_label(dentry, buf, buflen);
return nfs4_set_security_label(inode, buf, buflen);
return -EOPNOTSUPP;
}

View file

@ -7254,10 +7254,11 @@ static int ocfs2_xattr_security_get(const struct xattr_handler *handler,
}
static int ocfs2_xattr_security_set(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
struct dentry *unused, struct inode *inode,
const char *name, const void *value,
size_t size, int flags)
{
return ocfs2_xattr_set(d_inode(dentry), OCFS2_XATTR_INDEX_SECURITY,
return ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_SECURITY,
name, value, size, flags);
}
@ -7325,10 +7326,11 @@ static int ocfs2_xattr_trusted_get(const struct xattr_handler *handler,
}
static int ocfs2_xattr_trusted_set(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
struct dentry *unused, struct inode *inode,
const char *name, const void *value,
size_t size, int flags)
{
return ocfs2_xattr_set(d_inode(dentry), OCFS2_XATTR_INDEX_TRUSTED,
return ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_TRUSTED,
name, value, size, flags);
}
@ -7354,15 +7356,16 @@ static int ocfs2_xattr_user_get(const struct xattr_handler *handler,
}
static int ocfs2_xattr_user_set(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
struct dentry *unused, struct inode *inode,
const char *name, const void *value,
size_t size, int flags)
{
struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR)
return -EOPNOTSUPP;
return ocfs2_xattr_set(d_inode(dentry), OCFS2_XATTR_INDEX_USER,
return ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_USER,
name, value, size, flags);
}

View file

@ -448,13 +448,14 @@ ssize_t orangefs_listxattr(struct dentry *dentry, char *buffer, size_t size)
}
static int orangefs_xattr_set_default(const struct xattr_handler *handler,
struct dentry *dentry,
struct dentry *unused,
struct inode *inode,
const char *name,
const void *buffer,
size_t size,
int flags)
{
return orangefs_inode_setxattr(dentry->d_inode,
return orangefs_inode_setxattr(inode,
ORANGEFS_XATTR_NAME_DEFAULT_PREFIX,
name,
buffer,
@ -478,13 +479,14 @@ static int orangefs_xattr_get_default(const struct xattr_handler *handler,
}
static int orangefs_xattr_set_trusted(const struct xattr_handler *handler,
struct dentry *dentry,
struct dentry *unused,
struct inode *inode,
const char *name,
const void *buffer,
size_t size,
int flags)
{
return orangefs_inode_setxattr(dentry->d_inode,
return orangefs_inode_setxattr(inode,
ORANGEFS_XATTR_NAME_TRUSTED_PREFIX,
name,
buffer,

View file

@ -210,8 +210,9 @@ static bool ovl_is_private_xattr(const char *name)
return strncmp(name, OVL_XATTR_PRE_NAME, OVL_XATTR_PRE_LEN) == 0;
}
int ovl_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
int ovl_setxattr(struct dentry *dentry, struct inode *inode,
const char *name, const void *value,
size_t size, int flags)
{
int err;
struct dentry *upperdentry;

View file

@ -172,8 +172,9 @@ int ovl_check_d_type_supported(struct path *realpath);
/* inode.c */
int ovl_setattr(struct dentry *dentry, struct iattr *attr);
int ovl_permission(struct inode *inode, int mask);
int ovl_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags);
int ovl_setxattr(struct dentry *dentry, struct inode *inode,
const char *name, const void *value,
size_t size, int flags);
ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode,
const char *name, void *value, size_t size);
ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size);

View file

@ -210,9 +210,7 @@ static int ovl_check_whiteouts(struct dentry *dir, struct ovl_readdir_data *rdd)
old_cred = ovl_override_creds(rdd->dentry->d_sb);
inode_lock(dir->d_inode);
err = 0;
// XXX: err = mutex_lock_killable(&dir->d_inode->i_mutex);
err = down_write_killable(&dir->d_inode->i_rwsem);
if (!err) {
while (rdd->first_maybe_whiteout) {
p = rdd->first_maybe_whiteout;

View file

@ -822,10 +822,10 @@ posix_acl_xattr_get(const struct xattr_handler *handler,
static int
posix_acl_xattr_set(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
struct dentry *unused, struct inode *inode,
const char *name, const void *value,
size_t size, int flags)
{
struct inode *inode = d_backing_inode(dentry);
struct posix_acl *acl = NULL;
int ret;

View file

@ -35,13 +35,13 @@ int iterate_dir(struct file *file, struct dir_context *ctx)
if (res)
goto out;
if (shared)
if (shared) {
inode_lock_shared(inode);
else
inode_lock(inode);
// res = mutex_lock_killable(&inode->i_mutex);
// if (res)
// goto out;
} else {
res = down_write_killable(&inode->i_rwsem);
if (res)
goto out;
}
res = -ENOENT;
if (!IS_DEADDIR(inode)) {

View file

@ -20,13 +20,14 @@ security_get(const struct xattr_handler *handler, struct dentry *unused,
}
static int
security_set(const struct xattr_handler *handler, struct dentry *dentry,
const char *name, const void *buffer, size_t size, int flags)
security_set(const struct xattr_handler *handler, struct dentry *unused,
struct inode *inode, const char *name, const void *buffer,
size_t size, int flags)
{
if (IS_PRIVATE(d_inode(dentry)))
if (IS_PRIVATE(inode))
return -EPERM;
return reiserfs_xattr_set(d_inode(dentry),
return reiserfs_xattr_set(inode,
xattr_full_name(handler, name),
buffer, size, flags);
}

View file

@ -19,13 +19,14 @@ trusted_get(const struct xattr_handler *handler, struct dentry *unused,
}
static int
trusted_set(const struct xattr_handler *handler, struct dentry *dentry,
const char *name, const void *buffer, size_t size, int flags)
trusted_set(const struct xattr_handler *handler, struct dentry *unused,
struct inode *inode, const char *name, const void *buffer,
size_t size, int flags)
{
if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(d_inode(dentry)))
if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode))
return -EPERM;
return reiserfs_xattr_set(d_inode(dentry),
return reiserfs_xattr_set(inode,
xattr_full_name(handler, name),
buffer, size, flags);
}

View file

@ -17,12 +17,13 @@ user_get(const struct xattr_handler *handler, struct dentry *unused,
}
static int
user_set(const struct xattr_handler *handler, struct dentry *dentry,
const char *name, const void *buffer, size_t size, int flags)
user_set(const struct xattr_handler *handler, struct dentry *unused,
struct inode *inode, const char *name, const void *buffer,
size_t size, int flags)
{
if (!reiserfs_xattrs_user(dentry->d_sb))
if (!reiserfs_xattrs_user(inode->i_sb))
return -EOPNOTSUPP;
return reiserfs_xattr_set(d_inode(dentry),
return reiserfs_xattr_set(inode,
xattr_full_name(handler, name),
buffer, size, flags);
}

View file

@ -579,11 +579,10 @@ static int ubifs_xattr_get(const struct xattr_handler *handler,
}
static int ubifs_xattr_set(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
struct dentry *dentry, struct inode *inode,
const char *name, const void *value,
size_t size, int flags)
{
struct inode *inode = d_inode(dentry);
dbg_gen("xattr '%s', host ino %lu ('%pd'), size %zd",
name, inode->i_ino, dentry, size);

View file

@ -100,7 +100,7 @@ int __vfs_setxattr_noperm(struct dentry *dentry, const char *name,
if (issec)
inode->i_flags &= ~S_NOSEC;
if (inode->i_op->setxattr) {
error = inode->i_op->setxattr(dentry, name, value, size, flags);
error = inode->i_op->setxattr(dentry, inode, name, value, size, flags);
if (!error) {
fsnotify_xattr(dentry);
security_inode_post_setxattr(dentry, name, value,
@ -745,7 +745,8 @@ generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
* Find the handler for the prefix and dispatch its set() operation.
*/
int
generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags)
generic_setxattr(struct dentry *dentry, struct inode *inode, const char *name,
const void *value, size_t size, int flags)
{
const struct xattr_handler *handler;
@ -754,7 +755,7 @@ generic_setxattr(struct dentry *dentry, const char *name, const void *value, siz
handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
if (IS_ERR(handler))
return PTR_ERR(handler);
return handler->set(handler, dentry, name, value, size, flags);
return handler->set(handler, dentry, inode, name, value, size, flags);
}
/*
@ -769,7 +770,8 @@ generic_removexattr(struct dentry *dentry, const char *name)
handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
if (IS_ERR(handler))
return PTR_ERR(handler);
return handler->set(handler, dentry, name, NULL, 0, XATTR_REPLACE);
return handler->set(handler, dentry, d_inode(dentry), name, NULL,
0, XATTR_REPLACE);
}
EXPORT_SYMBOL(generic_getxattr);

View file

@ -74,11 +74,12 @@ xfs_forget_acl(
}
static int
xfs_xattr_set(const struct xattr_handler *handler, struct dentry *dentry,
const char *name, const void *value, size_t size, int flags)
xfs_xattr_set(const struct xattr_handler *handler, struct dentry *unused,
struct inode *inode, const char *name, const void *value,
size_t size, int flags)
{
int xflags = handler->flags;
struct xfs_inode *ip = XFS_I(d_inode(dentry));
struct xfs_inode *ip = XFS_I(inode);
int error;
/* Convert Linux syscall to XFS internal ATTR flags */
@ -92,7 +93,7 @@ xfs_xattr_set(const struct xattr_handler *handler, struct dentry *dentry,
error = xfs_attr_set(ip, (unsigned char *)name,
(void *)value, size, xflags);
if (!error)
xfs_forget_acl(d_inode(dentry), name, xflags);
xfs_forget_acl(inode, name, xflags);
return error;
}

View file

@ -1729,7 +1729,8 @@ struct inode_operations {
struct inode *, struct dentry *, unsigned int);
int (*setattr) (struct dentry *, struct iattr *);
int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
int (*setxattr) (struct dentry *, struct inode *,
const char *, const void *, size_t, int);
ssize_t (*getxattr) (struct dentry *, struct inode *,
const char *, void *, size_t);
ssize_t (*listxattr) (struct dentry *, char *, size_t);

View file

@ -156,6 +156,7 @@ extern void downgrade_write(struct rw_semaphore *sem);
*/
extern void down_read_nested(struct rw_semaphore *sem, int subclass);
extern void down_write_nested(struct rw_semaphore *sem, int subclass);
extern int down_write_killable_nested(struct rw_semaphore *sem, int subclass);
extern void _down_write_nest_lock(struct rw_semaphore *sem, struct lockdep_map *nest_lock);
# define down_write_nest_lock(sem, nest_lock) \
@ -176,6 +177,7 @@ extern void up_read_non_owner(struct rw_semaphore *sem);
# define down_read_nested(sem, subclass) down_read(sem)
# define down_write_nest_lock(sem, nest_lock) down_write(sem)
# define down_write_nested(sem, subclass) down_write(sem)
# define down_write_killable_nested(sem, subclass) down_write_killable(sem)
# define down_read_non_owner(sem) down_read(sem)
# define up_read_non_owner(sem) up_read(sem)
#endif

View file

@ -33,8 +33,8 @@ struct xattr_handler {
struct inode *inode, const char *name, void *buffer,
size_t size);
int (*set)(const struct xattr_handler *, struct dentry *dentry,
const char *name, const void *buffer, size_t size,
int flags);
struct inode *inode, const char *name, const void *buffer,
size_t size, int flags);
};
const char *xattr_full_name(const struct xattr_handler *, const char *);
@ -54,7 +54,8 @@ int vfs_removexattr(struct dentry *, const char *);
ssize_t generic_getxattr(struct dentry *dentry, struct inode *inode, const char *name, void *buffer, size_t size);
ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
int generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags);
int generic_setxattr(struct dentry *dentry, struct inode *inode,
const char *name, const void *value, size_t size, int flags);
int generic_removexattr(struct dentry *dentry, const char *name);
ssize_t vfs_getxattr_alloc(struct dentry *dentry, const char *name,
char **xattr_value, size_t size, gfp_t flags);

View file

@ -173,6 +173,22 @@ void down_write_nested(struct rw_semaphore *sem, int subclass)
EXPORT_SYMBOL(down_write_nested);
int __sched down_write_killable_nested(struct rw_semaphore *sem, int subclass)
{
might_sleep();
rwsem_acquire(&sem->dep_map, subclass, 0, _RET_IP_);
if (LOCK_CONTENDED_RETURN(sem, __down_write_trylock, __down_write_killable)) {
rwsem_release(&sem->dep_map, 1, _RET_IP_);
return -EINTR;
}
rwsem_set_owner(sem);
return 0;
}
EXPORT_SYMBOL(down_write_killable_nested);
void up_read_non_owner(struct rw_semaphore *sem)
{
__up_read(sem);

View file

@ -2645,10 +2645,11 @@ static int shmem_xattr_handler_get(const struct xattr_handler *handler,
}
static int shmem_xattr_handler_set(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
struct dentry *unused, struct inode *inode,
const char *name, const void *value,
size_t size, int flags)
{
struct shmem_inode_info *info = SHMEM_I(d_inode(dentry));
struct shmem_inode_info *info = SHMEM_I(inode);
name = xattr_full_name(handler, name);
return simple_xattr_set(&info->xattrs, name, value, size, flags);

View file

@ -3514,7 +3514,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
*/
if (isp->smk_flags & SMK_INODE_CHANGED) {
isp->smk_flags &= ~SMK_INODE_CHANGED;
rc = inode->i_op->setxattr(dp,
rc = inode->i_op->setxattr(dp, inode,
XATTR_NAME_SMACKTRANSMUTE,
TRANS_TRUE, TRANS_TRUE_SIZE,
0);