xfs: pass an initialized xfs_da_args to xfs_attr_get
Instead of converting from one style of arguments to another in xfs_attr_set, pass the structure from higher up in the call chain. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Chandan Rajendra <chandanrlinux@gmail.com> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
This commit is contained in:
committed by
Darrick J. Wong
parent
a254462243
commit
e5171d7e98
@@ -56,26 +56,6 @@ STATIC int xfs_attr_node_removename(xfs_da_args_t *args);
|
|||||||
STATIC int xfs_attr_fillstate(xfs_da_state_t *state);
|
STATIC int xfs_attr_fillstate(xfs_da_state_t *state);
|
||||||
STATIC int xfs_attr_refillstate(xfs_da_state_t *state);
|
STATIC int xfs_attr_refillstate(xfs_da_state_t *state);
|
||||||
|
|
||||||
|
|
||||||
STATIC int
|
|
||||||
xfs_attr_args_init(
|
|
||||||
struct xfs_da_args *args,
|
|
||||||
struct xfs_inode *dp,
|
|
||||||
const unsigned char *name,
|
|
||||||
size_t namelen,
|
|
||||||
int flags)
|
|
||||||
{
|
|
||||||
memset(args, 0, sizeof(*args));
|
|
||||||
args->geo = dp->i_mount->m_attr_geo;
|
|
||||||
args->whichfork = XFS_ATTR_FORK;
|
|
||||||
args->dp = dp;
|
|
||||||
args->flags = flags;
|
|
||||||
args->name = name;
|
|
||||||
args->namelen = namelen;
|
|
||||||
args->hashval = xfs_da_hashname(args->name, args->namelen);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
xfs_inode_hasattr(
|
xfs_inode_hasattr(
|
||||||
struct xfs_inode *ip)
|
struct xfs_inode *ip)
|
||||||
@@ -115,15 +95,15 @@ xfs_attr_get_ilocked(
|
|||||||
/*
|
/*
|
||||||
* Retrieve an extended attribute by name, and its value if requested.
|
* Retrieve an extended attribute by name, and its value if requested.
|
||||||
*
|
*
|
||||||
* If ATTR_KERNOVAL is set in @flags, then the caller does not want the value,
|
* If ATTR_KERNOVAL is set in args->flags, then the caller does not want the
|
||||||
* just an indication whether the attribute exists and the size of the value if
|
* value, just an indication whether the attribute exists and the size of the
|
||||||
* it exists. The size is returned in @valuelenp,
|
* value if it exists. The size is returned in args.valuelen.
|
||||||
*
|
*
|
||||||
* If the attribute is found, but exceeds the size limit set by the caller in
|
* If the attribute is found, but exceeds the size limit set by the caller in
|
||||||
* @valuelenp, return -ERANGE with the size of the attribute that was found in
|
* args->valuelen, return -ERANGE with the size of the attribute that was found
|
||||||
* @valuelenp.
|
* in args->valuelen.
|
||||||
*
|
*
|
||||||
* If ATTR_ALLOC is set in @flags, allocate the buffer for the value after
|
* If ATTR_ALLOC is set in args->flags, allocate the buffer for the value after
|
||||||
* existence of the attribute has been determined. On success, return that
|
* existence of the attribute has been determined. On success, return that
|
||||||
* buffer to the caller and leave them to free it. On failure, free any
|
* buffer to the caller and leave them to free it. On failure, free any
|
||||||
* allocated buffer and ensure the buffer pointer returned to the caller is
|
* allocated buffer and ensure the buffer pointer returned to the caller is
|
||||||
@@ -131,51 +111,37 @@ xfs_attr_get_ilocked(
|
|||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xfs_attr_get(
|
xfs_attr_get(
|
||||||
struct xfs_inode *ip,
|
struct xfs_da_args *args)
|
||||||
const unsigned char *name,
|
|
||||||
size_t namelen,
|
|
||||||
unsigned char **value,
|
|
||||||
int *valuelenp,
|
|
||||||
int flags)
|
|
||||||
{
|
{
|
||||||
struct xfs_da_args args;
|
|
||||||
uint lock_mode;
|
uint lock_mode;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
ASSERT((flags & (ATTR_ALLOC | ATTR_KERNOVAL)) || *value);
|
ASSERT((args->flags & (ATTR_ALLOC | ATTR_KERNOVAL)) || args->value);
|
||||||
|
|
||||||
XFS_STATS_INC(ip->i_mount, xs_attr_get);
|
XFS_STATS_INC(args->dp->i_mount, xs_attr_get);
|
||||||
|
|
||||||
if (XFS_FORCED_SHUTDOWN(ip->i_mount))
|
if (XFS_FORCED_SHUTDOWN(args->dp->i_mount))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
error = xfs_attr_args_init(&args, ip, name, namelen, flags);
|
args->geo = args->dp->i_mount->m_attr_geo;
|
||||||
if (error)
|
args->whichfork = XFS_ATTR_FORK;
|
||||||
return error;
|
args->hashval = xfs_da_hashname(args->name, args->namelen);
|
||||||
|
|
||||||
/* Entirely possible to look up a name which doesn't exist */
|
/* Entirely possible to look up a name which doesn't exist */
|
||||||
args.op_flags = XFS_DA_OP_OKNOENT;
|
args->op_flags = XFS_DA_OP_OKNOENT;
|
||||||
if (flags & ATTR_ALLOC)
|
if (args->flags & ATTR_ALLOC)
|
||||||
args.op_flags |= XFS_DA_OP_ALLOCVAL;
|
args->op_flags |= XFS_DA_OP_ALLOCVAL;
|
||||||
else
|
|
||||||
args.value = *value;
|
|
||||||
args.valuelen = *valuelenp;
|
|
||||||
|
|
||||||
lock_mode = xfs_ilock_attr_map_shared(ip);
|
lock_mode = xfs_ilock_attr_map_shared(args->dp);
|
||||||
error = xfs_attr_get_ilocked(ip, &args);
|
error = xfs_attr_get_ilocked(args->dp, args);
|
||||||
xfs_iunlock(ip, lock_mode);
|
xfs_iunlock(args->dp, lock_mode);
|
||||||
*valuelenp = args.valuelen;
|
|
||||||
|
|
||||||
/* on error, we have to clean up allocated value buffers */
|
/* on error, we have to clean up allocated value buffers */
|
||||||
if (error) {
|
if (error && (args->flags & ATTR_ALLOC)) {
|
||||||
if (flags & ATTR_ALLOC) {
|
kmem_free(args->value);
|
||||||
kmem_free(args.value);
|
args->value = NULL;
|
||||||
*value = NULL;
|
|
||||||
}
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
*value = args.value;
|
return error;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -146,9 +146,7 @@ int xfs_attr_list_int_ilocked(struct xfs_attr_list_context *);
|
|||||||
int xfs_attr_list_int(struct xfs_attr_list_context *);
|
int xfs_attr_list_int(struct xfs_attr_list_context *);
|
||||||
int xfs_inode_hasattr(struct xfs_inode *ip);
|
int xfs_inode_hasattr(struct xfs_inode *ip);
|
||||||
int xfs_attr_get_ilocked(struct xfs_inode *ip, struct xfs_da_args *args);
|
int xfs_attr_get_ilocked(struct xfs_inode *ip, struct xfs_da_args *args);
|
||||||
int xfs_attr_get(struct xfs_inode *ip, const unsigned char *name,
|
int xfs_attr_get(struct xfs_da_args *args);
|
||||||
size_t namelen, unsigned char **value, int *valuelenp,
|
|
||||||
int flags);
|
|
||||||
int xfs_attr_set(struct xfs_da_args *args);
|
int xfs_attr_set(struct xfs_da_args *args);
|
||||||
int xfs_attr_set_args(struct xfs_da_args *args);
|
int xfs_attr_set_args(struct xfs_da_args *args);
|
||||||
int xfs_attr_remove_args(struct xfs_da_args *args);
|
int xfs_attr_remove_args(struct xfs_da_args *args);
|
||||||
|
|||||||
@@ -126,34 +126,31 @@ xfs_acl_to_disk(struct xfs_acl *aclp, const struct posix_acl *acl)
|
|||||||
struct posix_acl *
|
struct posix_acl *
|
||||||
xfs_get_acl(struct inode *inode, int type)
|
xfs_get_acl(struct inode *inode, int type)
|
||||||
{
|
{
|
||||||
struct xfs_inode *ip = XFS_I(inode);
|
struct xfs_inode *ip = XFS_I(inode);
|
||||||
struct posix_acl *acl = NULL;
|
struct xfs_mount *mp = ip->i_mount;
|
||||||
struct xfs_acl *xfs_acl = NULL;
|
struct posix_acl *acl = NULL;
|
||||||
unsigned char *ea_name;
|
struct xfs_da_args args = {
|
||||||
int error;
|
.dp = ip,
|
||||||
int len;
|
.flags = ATTR_ALLOC | ATTR_ROOT,
|
||||||
|
.valuelen = XFS_ACL_MAX_SIZE(mp),
|
||||||
|
};
|
||||||
|
int error;
|
||||||
|
|
||||||
trace_xfs_get_acl(ip);
|
trace_xfs_get_acl(ip);
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ACL_TYPE_ACCESS:
|
case ACL_TYPE_ACCESS:
|
||||||
ea_name = SGI_ACL_FILE;
|
args.name = SGI_ACL_FILE;
|
||||||
break;
|
break;
|
||||||
case ACL_TYPE_DEFAULT:
|
case ACL_TYPE_DEFAULT:
|
||||||
ea_name = SGI_ACL_DEFAULT;
|
args.name = SGI_ACL_DEFAULT;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
|
args.namelen = strlen(args.name);
|
||||||
|
|
||||||
/*
|
error = xfs_attr_get(&args);
|
||||||
* If we have a cached ACLs value just return it, not need to
|
|
||||||
* go out to the disk.
|
|
||||||
*/
|
|
||||||
len = XFS_ACL_MAX_SIZE(ip->i_mount);
|
|
||||||
error = xfs_attr_get(ip, ea_name, strlen(ea_name),
|
|
||||||
(unsigned char **)&xfs_acl, &len,
|
|
||||||
ATTR_ALLOC | ATTR_ROOT);
|
|
||||||
if (error) {
|
if (error) {
|
||||||
/*
|
/*
|
||||||
* If the attribute doesn't exist make sure we have a negative
|
* If the attribute doesn't exist make sure we have a negative
|
||||||
@@ -162,9 +159,9 @@ xfs_get_acl(struct inode *inode, int type)
|
|||||||
if (error != -ENOATTR)
|
if (error != -ENOATTR)
|
||||||
acl = ERR_PTR(error);
|
acl = ERR_PTR(error);
|
||||||
} else {
|
} else {
|
||||||
acl = xfs_acl_from_disk(ip->i_mount, xfs_acl, len,
|
acl = xfs_acl_from_disk(mp, args.value, args.valuelen,
|
||||||
XFS_ACL_MAX_ENTRIES(ip->i_mount));
|
XFS_ACL_MAX_ENTRIES(mp));
|
||||||
kmem_free(xfs_acl);
|
kmem_free(args.value);
|
||||||
}
|
}
|
||||||
return acl;
|
return acl;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -359,27 +359,32 @@ xfs_attrmulti_attr_get(
|
|||||||
uint32_t *len,
|
uint32_t *len,
|
||||||
uint32_t flags)
|
uint32_t flags)
|
||||||
{
|
{
|
||||||
unsigned char *kbuf;
|
struct xfs_da_args args = {
|
||||||
int error = -EFAULT;
|
.dp = XFS_I(inode),
|
||||||
size_t namelen;
|
.flags = flags,
|
||||||
|
.name = name,
|
||||||
|
.namelen = strlen(name),
|
||||||
|
.valuelen = *len,
|
||||||
|
};
|
||||||
|
int error;
|
||||||
|
|
||||||
if (*len > XFS_XATTR_SIZE_MAX)
|
if (*len > XFS_XATTR_SIZE_MAX)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
kbuf = kmem_zalloc_large(*len, 0);
|
|
||||||
if (!kbuf)
|
args.value = kmem_zalloc_large(*len, 0);
|
||||||
|
if (!args.value)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
namelen = strlen(name);
|
error = xfs_attr_get(&args);
|
||||||
error = xfs_attr_get(XFS_I(inode), name, namelen, &kbuf, (int *)len,
|
|
||||||
flags);
|
|
||||||
if (error)
|
if (error)
|
||||||
goto out_kfree;
|
goto out_kfree;
|
||||||
|
|
||||||
if (copy_to_user(ubuf, kbuf, *len))
|
*len = args.valuelen;
|
||||||
|
if (copy_to_user(ubuf, args.value, args.valuelen))
|
||||||
error = -EFAULT;
|
error = -EFAULT;
|
||||||
|
|
||||||
out_kfree:
|
out_kfree:
|
||||||
kmem_free(kbuf);
|
kmem_free(args.value);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,22 +23,24 @@ static int
|
|||||||
xfs_xattr_get(const struct xattr_handler *handler, struct dentry *unused,
|
xfs_xattr_get(const struct xattr_handler *handler, struct dentry *unused,
|
||||||
struct inode *inode, const char *name, void *value, size_t size)
|
struct inode *inode, const char *name, void *value, size_t size)
|
||||||
{
|
{
|
||||||
int xflags = handler->flags;
|
struct xfs_da_args args = {
|
||||||
struct xfs_inode *ip = XFS_I(inode);
|
.dp = XFS_I(inode),
|
||||||
int error, asize = size;
|
.flags = handler->flags,
|
||||||
size_t namelen = strlen(name);
|
.name = name,
|
||||||
|
.namelen = strlen(name),
|
||||||
|
.value = value,
|
||||||
|
.valuelen = size,
|
||||||
|
};
|
||||||
|
int error;
|
||||||
|
|
||||||
/* Convert Linux syscall to XFS internal ATTR flags */
|
/* Convert Linux syscall to XFS internal ATTR flags */
|
||||||
if (!size) {
|
if (!size)
|
||||||
xflags |= ATTR_KERNOVAL;
|
args.flags |= ATTR_KERNOVAL;
|
||||||
value = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
error = xfs_attr_get(ip, name, namelen, (unsigned char **)&value,
|
error = xfs_attr_get(&args);
|
||||||
&asize, xflags);
|
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
return asize;
|
return args.valuelen;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
Reference in New Issue
Block a user