forked from Minki/linux
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:
commit
d102a56edb
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
/*
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 @@ out_dput:
|
||||
dput(dentry);
|
||||
out_unlock_dir:
|
||||
inode_unlock(dir);
|
||||
//out_drop_write:
|
||||
out_drop_write:
|
||||
mnt_drop_write_file(file);
|
||||
out:
|
||||
kfree(vol_args);
|
||||
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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 = {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -448,13 +448,14 @@ out_unlock:
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
12
fs/readdir.c
12
fs/readdir.c
@ -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)) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
10
fs/xattr.c
10
fs/xattr.c
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user