Commit 2d6dcc6d authored by Dave Chinner's avatar Dave Chinner

Merge branch 'xfs-attr-cleanup' into for-next

Conflicts:
	fs/xfs/xfs_attr.c
parents ff14ee42 6c888af0
...@@ -77,17 +77,26 @@ STATIC int xfs_attr_refillstate(xfs_da_state_t *state); ...@@ -77,17 +77,26 @@ STATIC int xfs_attr_refillstate(xfs_da_state_t *state);
STATIC int STATIC int
xfs_attr_name_to_xname( xfs_attr_args_init(
struct xfs_name *xname, struct xfs_da_args *args,
const unsigned char *aname) struct xfs_inode *dp,
const unsigned char *name,
int flags)
{ {
if (!aname)
if (!name)
return EINVAL; return EINVAL;
xname->name = aname;
xname->len = strlen((char *)aname); memset(args, 0, sizeof(*args));
if (xname->len >= MAXNAMELEN) args->whichfork = XFS_ATTR_FORK;
args->dp = dp;
args->flags = flags;
args->name = name;
args->namelen = strlen((const char *)name);
if (args->namelen >= MAXNAMELEN)
return EFAULT; /* match IRIX behaviour */ return EFAULT; /* match IRIX behaviour */
args->hashval = xfs_da_hashname(args->name, args->namelen);
return 0; return 0;
} }
...@@ -106,79 +115,46 @@ xfs_inode_hasattr( ...@@ -106,79 +115,46 @@ xfs_inode_hasattr(
* Overall external interface routines. * Overall external interface routines.
*========================================================================*/ *========================================================================*/
STATIC int int
xfs_attr_get_int( xfs_attr_get(
struct xfs_inode *ip, struct xfs_inode *ip,
struct xfs_name *name, const unsigned char *name,
unsigned char *value, unsigned char *value,
int *valuelenp, int *valuelenp,
int flags) int flags)
{ {
xfs_da_args_t args; struct xfs_da_args args;
int error; uint lock_mode;
int error;
XFS_STATS_INC(xs_attr_get);
if (XFS_FORCED_SHUTDOWN(ip->i_mount))
return EIO;
if (!xfs_inode_hasattr(ip)) if (!xfs_inode_hasattr(ip))
return ENOATTR; return ENOATTR;
/* error = xfs_attr_args_init(&args, ip, name, flags);
* Fill in the arg structure for this request. if (error)
*/ return error;
memset((char *)&args, 0, sizeof(args));
args.name = name->name;
args.namelen = name->len;
args.value = value; args.value = value;
args.valuelen = *valuelenp; args.valuelen = *valuelenp;
args.flags = flags;
args.hashval = xfs_da_hashname(args.name, args.namelen);
args.dp = ip;
args.whichfork = XFS_ATTR_FORK;
/* lock_mode = xfs_ilock_attr_map_shared(ip);
* Decide on what work routines to call based on the inode size. if (!xfs_inode_hasattr(ip))
*/ error = ENOATTR;
if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) { else if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL)
error = xfs_attr_shortform_getvalue(&args); error = xfs_attr_shortform_getvalue(&args);
} else if (xfs_bmap_one_block(ip, XFS_ATTR_FORK)) { else if (xfs_bmap_one_block(ip, XFS_ATTR_FORK))
error = xfs_attr_leaf_get(&args); error = xfs_attr_leaf_get(&args);
} else { else
error = xfs_attr_node_get(&args); error = xfs_attr_node_get(&args);
} xfs_iunlock(ip, lock_mode);
/*
* Return the number of bytes in the value to the caller.
*/
*valuelenp = args.valuelen; *valuelenp = args.valuelen;
return error == EEXIST ? 0 : error;
if (error == EEXIST)
error = 0;
return(error);
}
int
xfs_attr_get(
xfs_inode_t *ip,
const unsigned char *name,
unsigned char *value,
int *valuelenp,
int flags)
{
int error;
struct xfs_name xname;
uint lock_mode;
XFS_STATS_INC(xs_attr_get);
if (XFS_FORCED_SHUTDOWN(ip->i_mount))
return(EIO);
error = xfs_attr_name_to_xname(&xname, name);
if (error)
return error;
lock_mode = xfs_ilock_attr_map_shared(ip);
error = xfs_attr_get_int(ip, &xname, value, valuelenp, flags);
xfs_iunlock(ip, lock_mode);
return(error);
} }
/* /*
...@@ -186,12 +162,10 @@ xfs_attr_get( ...@@ -186,12 +162,10 @@ xfs_attr_get(
*/ */
STATIC int STATIC int
xfs_attr_calc_size( xfs_attr_calc_size(
struct xfs_inode *ip, struct xfs_da_args *args,
int namelen,
int valuelen,
int *local) int *local)
{ {
struct xfs_mount *mp = ip->i_mount; struct xfs_mount *mp = args->dp->i_mount;
int size; int size;
int nblks; int nblks;
...@@ -199,7 +173,7 @@ xfs_attr_calc_size( ...@@ -199,7 +173,7 @@ xfs_attr_calc_size(
* Determine space new attribute will use, and if it would be * Determine space new attribute will use, and if it would be
* "local" or "remote" (note: local != inline). * "local" or "remote" (note: local != inline).
*/ */
size = xfs_attr_leaf_newentsize(namelen, valuelen, size = xfs_attr_leaf_newentsize(args->namelen, args->valuelen,
mp->m_sb.sb_blocksize, local); mp->m_sb.sb_blocksize, local);
nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK); nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
...@@ -213,7 +187,7 @@ xfs_attr_calc_size( ...@@ -213,7 +187,7 @@ xfs_attr_calc_size(
* Out of line attribute, cannot double split, but * Out of line attribute, cannot double split, but
* make room for the attribute value itself. * make room for the attribute value itself.
*/ */
uint dblocks = xfs_attr3_rmt_blocks(mp, valuelen); uint dblocks = xfs_attr3_rmt_blocks(mp, args->valuelen);
nblks += dblocks; nblks += dblocks;
nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK); nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK);
} }
...@@ -221,26 +195,38 @@ xfs_attr_calc_size( ...@@ -221,26 +195,38 @@ xfs_attr_calc_size(
return nblks; return nblks;
} }
STATIC int int
xfs_attr_set_int( xfs_attr_set(
struct xfs_inode *dp, struct xfs_inode *dp,
struct xfs_name *name, const unsigned char *name,
unsigned char *value, unsigned char *value,
int valuelen, int valuelen,
int flags) int flags)
{ {
xfs_da_args_t args;
xfs_fsblock_t firstblock;
xfs_bmap_free_t flist;
int error, err2, committed;
struct xfs_mount *mp = dp->i_mount; struct xfs_mount *mp = dp->i_mount;
struct xfs_da_args args;
struct xfs_bmap_free flist;
struct xfs_trans_res tres; struct xfs_trans_res tres;
xfs_fsblock_t firstblock;
int rsvd = (flags & ATTR_ROOT) != 0; int rsvd = (flags & ATTR_ROOT) != 0;
int local; int error, err2, committed, local;
XFS_STATS_INC(xs_attr_set);
if (XFS_FORCED_SHUTDOWN(dp->i_mount))
return EIO;
error = xfs_attr_args_init(&args, dp, name, flags);
if (error)
return error;
args.value = value;
args.valuelen = valuelen;
args.firstblock = &firstblock;
args.flist = &flist;
args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
args.total = xfs_attr_calc_size(&args, &local);
/*
* Attach the dquots to the inode.
*/
error = xfs_qm_dqattach(dp, 0); error = xfs_qm_dqattach(dp, 0);
if (error) if (error)
return error; return error;
...@@ -251,31 +237,13 @@ xfs_attr_set_int( ...@@ -251,31 +237,13 @@ xfs_attr_set_int(
*/ */
if (XFS_IFORK_Q(dp) == 0) { if (XFS_IFORK_Q(dp) == 0) {
int sf_size = sizeof(xfs_attr_sf_hdr_t) + int sf_size = sizeof(xfs_attr_sf_hdr_t) +
XFS_ATTR_SF_ENTSIZE_BYNAME(name->len, valuelen); XFS_ATTR_SF_ENTSIZE_BYNAME(args.namelen, valuelen);
if ((error = xfs_bmap_add_attrfork(dp, sf_size, rsvd))) error = xfs_bmap_add_attrfork(dp, sf_size, rsvd);
return(error); if (error)
return error;
} }
/*
* Fill in the arg structure for this request.
*/
memset((char *)&args, 0, sizeof(args));
args.name = name->name;
args.namelen = name->len;
args.value = value;
args.valuelen = valuelen;
args.flags = flags;
args.hashval = xfs_da_hashname(args.name, args.namelen);
args.dp = dp;
args.firstblock = &firstblock;
args.flist = &flist;
args.whichfork = XFS_ATTR_FORK;
args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
/* Size is now blocks for attribute data */
args.total = xfs_attr_calc_size(dp, name->len, valuelen, &local);
/* /*
* Start our first transaction of the day. * Start our first transaction of the day.
* *
...@@ -303,7 +271,7 @@ xfs_attr_set_int( ...@@ -303,7 +271,7 @@ xfs_attr_set_int(
error = xfs_trans_reserve(args.trans, &tres, args.total, 0); error = xfs_trans_reserve(args.trans, &tres, args.total, 0);
if (error) { if (error) {
xfs_trans_cancel(args.trans, 0); xfs_trans_cancel(args.trans, 0);
return(error); return error;
} }
xfs_ilock(dp, XFS_ILOCK_EXCL); xfs_ilock(dp, XFS_ILOCK_EXCL);
...@@ -313,7 +281,7 @@ xfs_attr_set_int( ...@@ -313,7 +281,7 @@ xfs_attr_set_int(
if (error) { if (error) {
xfs_iunlock(dp, XFS_ILOCK_EXCL); xfs_iunlock(dp, XFS_ILOCK_EXCL);
xfs_trans_cancel(args.trans, XFS_TRANS_RELEASE_LOG_RES); xfs_trans_cancel(args.trans, XFS_TRANS_RELEASE_LOG_RES);
return (error); return error;
} }
xfs_trans_ijoin(args.trans, dp, 0); xfs_trans_ijoin(args.trans, dp, 0);
...@@ -322,9 +290,9 @@ xfs_attr_set_int( ...@@ -322,9 +290,9 @@ xfs_attr_set_int(
* If the attribute list is non-existent or a shortform list, * If the attribute list is non-existent or a shortform list,
* upgrade it to a single-leaf-block attribute list. * upgrade it to a single-leaf-block attribute list.
*/ */
if ((dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) || if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL ||
((dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS) && (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
(dp->i_d.di_anextents == 0))) { dp->i_d.di_anextents == 0)) {
/* /*
* Build initial attribute list (if required). * Build initial attribute list (if required).
...@@ -349,9 +317,8 @@ xfs_attr_set_int( ...@@ -349,9 +317,8 @@ xfs_attr_set_int(
* the transaction goes to disk before returning * the transaction goes to disk before returning
* to the user. * to the user.
*/ */
if (mp->m_flags & XFS_MOUNT_WSYNC) { if (mp->m_flags & XFS_MOUNT_WSYNC)
xfs_trans_set_sync(args.trans); xfs_trans_set_sync(args.trans);
}
if (!error && (flags & ATTR_KERNOTIME) == 0) { if (!error && (flags & ATTR_KERNOTIME) == 0) {
xfs_trans_ichgtime(args.trans, dp, xfs_trans_ichgtime(args.trans, dp,
...@@ -361,7 +328,7 @@ xfs_attr_set_int( ...@@ -361,7 +328,7 @@ xfs_attr_set_int(
XFS_TRANS_RELEASE_LOG_RES); XFS_TRANS_RELEASE_LOG_RES);
xfs_iunlock(dp, XFS_ILOCK_EXCL); xfs_iunlock(dp, XFS_ILOCK_EXCL);
return(error == 0 ? err2 : error); return error ? error : err2;
} }
/* /*
...@@ -399,22 +366,19 @@ xfs_attr_set_int( ...@@ -399,22 +366,19 @@ xfs_attr_set_int(
} }
if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) { if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
error = xfs_attr_leaf_addname(&args); error = xfs_attr_leaf_addname(&args);
} else { else
error = xfs_attr_node_addname(&args); error = xfs_attr_node_addname(&args);
} if (error)
if (error) {
goto out; goto out;
}
/* /*
* If this is a synchronous mount, make sure that the * If this is a synchronous mount, make sure that the
* transaction goes to disk before returning to the user. * transaction goes to disk before returning to the user.
*/ */
if (mp->m_flags & XFS_MOUNT_WSYNC) { if (mp->m_flags & XFS_MOUNT_WSYNC)
xfs_trans_set_sync(args.trans); xfs_trans_set_sync(args.trans);
}
if ((flags & ATTR_KERNOTIME) == 0) if ((flags & ATTR_KERNOTIME) == 0)
xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG); xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG);
...@@ -426,65 +390,47 @@ xfs_attr_set_int( ...@@ -426,65 +390,47 @@ xfs_attr_set_int(
error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES); error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES);
xfs_iunlock(dp, XFS_ILOCK_EXCL); xfs_iunlock(dp, XFS_ILOCK_EXCL);
return(error); return error;
out: out:
if (args.trans) if (args.trans) {
xfs_trans_cancel(args.trans, xfs_trans_cancel(args.trans,
XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT); XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
}
xfs_iunlock(dp, XFS_ILOCK_EXCL); xfs_iunlock(dp, XFS_ILOCK_EXCL);
return(error); return error;
} }
/*
* Generic handler routine to remove a name from an attribute list.
* Transitions attribute list from Btree to shortform as necessary.
*/
int int
xfs_attr_set( xfs_attr_remove(
xfs_inode_t *dp, struct xfs_inode *dp,
const unsigned char *name, const unsigned char *name,
unsigned char *value, int flags)
int valuelen,
int flags)
{ {
int error; struct xfs_mount *mp = dp->i_mount;
struct xfs_name xname; struct xfs_da_args args;
struct xfs_bmap_free flist;
xfs_fsblock_t firstblock;
int error;
XFS_STATS_INC(xs_attr_set); XFS_STATS_INC(xs_attr_remove);
if (XFS_FORCED_SHUTDOWN(dp->i_mount)) if (XFS_FORCED_SHUTDOWN(dp->i_mount))
return (EIO); return EIO;
error = xfs_attr_name_to_xname(&xname, name); if (!xfs_inode_hasattr(dp))
return ENOATTR;
error = xfs_attr_args_init(&args, dp, name, flags);
if (error) if (error)
return error; return error;
return xfs_attr_set_int(dp, &xname, value, valuelen, flags);
}
/*
* Generic handler routine to remove a name from an attribute list.
* Transitions attribute list from Btree to shortform as necessary.
*/
STATIC int
xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags)
{
xfs_da_args_t args;
xfs_fsblock_t firstblock;
xfs_bmap_free_t flist;
int error;
xfs_mount_t *mp = dp->i_mount;
/*
* Fill in the arg structure for this request.
*/
memset((char *)&args, 0, sizeof(args));
args.name = name->name;
args.namelen = name->len;
args.flags = flags;
args.hashval = xfs_da_hashname(args.name, args.namelen);
args.dp = dp;
args.firstblock = &firstblock; args.firstblock = &firstblock;
args.flist = &flist; args.flist = &flist;
args.total = 0;
args.whichfork = XFS_ATTR_FORK;
/* /*
* we have no control over the attribute names that userspace passes us * we have no control over the attribute names that userspace passes us
...@@ -493,9 +439,6 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags) ...@@ -493,9 +439,6 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags)
*/ */
args.op_flags = XFS_DA_OP_OKNOENT; args.op_flags = XFS_DA_OP_OKNOENT;
/*
* Attach the dquots to the inode.
*/
error = xfs_qm_dqattach(dp, 0); error = xfs_qm_dqattach(dp, 0);
if (error) if (error)
return error; return error;
...@@ -524,7 +467,7 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags) ...@@ -524,7 +467,7 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags)
XFS_ATTRRM_SPACE_RES(mp), 0); XFS_ATTRRM_SPACE_RES(mp), 0);
if (error) { if (error) {
xfs_trans_cancel(args.trans, 0); xfs_trans_cancel(args.trans, 0);
return(error); return error;
} }
xfs_ilock(dp, XFS_ILOCK_EXCL); xfs_ilock(dp, XFS_ILOCK_EXCL);
...@@ -534,35 +477,26 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags) ...@@ -534,35 +477,26 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags)
*/ */
xfs_trans_ijoin(args.trans, dp, 0); xfs_trans_ijoin(args.trans, dp, 0);
/*
* Decide on what work routines to call based on the inode size.
*/
if (!xfs_inode_hasattr(dp)) { if (!xfs_inode_hasattr(dp)) {
error = XFS_ERROR(ENOATTR); error = XFS_ERROR(ENOATTR);
goto out; } else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
}
if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
ASSERT(dp->i_afp->if_flags & XFS_IFINLINE); ASSERT(dp->i_afp->if_flags & XFS_IFINLINE);
error = xfs_attr_shortform_remove(&args); error = xfs_attr_shortform_remove(&args);
if (error) {
goto out;
}
} else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) { } else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
error = xfs_attr_leaf_removename(&args); error = xfs_attr_leaf_removename(&args);
} else { } else {
error = xfs_attr_node_removename(&args); error = xfs_attr_node_removename(&args);
} }
if (error) {
if (error)
goto out; goto out;
}
/* /*
* If this is a synchronous mount, make sure that the * If this is a synchronous mount, make sure that the
* transaction goes to disk before returning to the user. * transaction goes to disk before returning to the user.
*/ */
if (mp->m_flags & XFS_MOUNT_WSYNC) { if (mp->m_flags & XFS_MOUNT_WSYNC)
xfs_trans_set_sync(args.trans); xfs_trans_set_sync(args.trans);
}
if ((flags & ATTR_KERNOTIME) == 0) if ((flags & ATTR_KERNOTIME) == 0)
xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG); xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG);
...@@ -574,45 +508,17 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags) ...@@ -574,45 +508,17 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags)
error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES); error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES);
xfs_iunlock(dp, XFS_ILOCK_EXCL); xfs_iunlock(dp, XFS_ILOCK_EXCL);
return(error); return error;
out: out:
if (args.trans) if (args.trans) {
xfs_trans_cancel(args.trans, xfs_trans_cancel(args.trans,
XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT); XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
xfs_iunlock(dp, XFS_ILOCK_EXCL);
return(error);
}
int
xfs_attr_remove(
xfs_inode_t *dp,
const unsigned char *name,
int flags)
{
int error;
struct xfs_name xname;
XFS_STATS_INC(xs_attr_remove);
if (XFS_FORCED_SHUTDOWN(dp->i_mount))
return (EIO);
error = xfs_attr_name_to_xname(&xname, name);
if (error)
return error;
xfs_ilock(dp, XFS_ILOCK_SHARED);
if (!xfs_inode_hasattr(dp)) {
xfs_iunlock(dp, XFS_ILOCK_SHARED);
return XFS_ERROR(ENOATTR);
} }
xfs_iunlock(dp, XFS_ILOCK_SHARED); xfs_iunlock(dp, XFS_ILOCK_EXCL);
return error;
return xfs_attr_remove_int(dp, &xname, flags);
} }
/*======================================================================== /*========================================================================
* External routines when attribute list is inside the inode * External routines when attribute list is inside the inode
*========================================================================*/ *========================================================================*/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment