Loading fs/xfs/xfs_attr.c +117 −211 Original line number Diff line number Diff line Loading @@ -77,17 +77,26 @@ STATIC int xfs_attr_refillstate(xfs_da_state_t *state); STATIC int xfs_attr_name_to_xname( struct xfs_name *xname, const unsigned char *aname) xfs_attr_args_init( struct xfs_da_args *args, struct xfs_inode *dp, const unsigned char *name, int flags) { if (!aname) if (!name) return EINVAL; xname->name = aname; xname->len = strlen((char *)aname); if (xname->len >= MAXNAMELEN) memset(args, 0, sizeof(*args)); 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 */ args->hashval = xfs_da_hashname(args->name, args->namelen); return 0; } Loading @@ -106,79 +115,46 @@ xfs_inode_hasattr( * Overall external interface routines. *========================================================================*/ STATIC int xfs_attr_get_int( struct xfs_inode *ip, struct xfs_name *name, unsigned char *value, int *valuelenp, int flags) { xfs_da_args_t args; int error; if (!xfs_inode_hasattr(ip)) return ENOATTR; /* * 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 = *valuelenp; args.flags = flags; args.hashval = xfs_da_hashname(args.name, args.namelen); args.dp = ip; args.whichfork = XFS_ATTR_FORK; /* * Decide on what work routines to call based on the inode size. */ if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) { error = xfs_attr_shortform_getvalue(&args); } else if (xfs_bmap_one_block(ip, XFS_ATTR_FORK)) { error = xfs_attr_leaf_get(&args); } else { error = xfs_attr_node_get(&args); } /* * Return the number of bytes in the value to the caller. */ *valuelenp = args.valuelen; if (error == EEXIST) error = 0; return(error); } int xfs_attr_get( xfs_inode_t *ip, struct xfs_inode *ip, const unsigned char *name, unsigned char *value, int *valuelenp, int flags) { int error; struct xfs_name xname; struct xfs_da_args args; uint lock_mode; int error; XFS_STATS_INC(xs_attr_get); if (XFS_FORCED_SHUTDOWN(ip->i_mount)) return(EIO); return EIO; if (!xfs_inode_hasattr(ip)) return ENOATTR; error = xfs_attr_name_to_xname(&xname, name); error = xfs_attr_args_init(&args, ip, name, flags); if (error) return error; args.value = value; args.valuelen = *valuelenp; lock_mode = xfs_ilock_attr_map_shared(ip); error = xfs_attr_get_int(ip, &xname, value, valuelenp, flags); if (!xfs_inode_hasattr(ip)) error = ENOATTR; else if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) error = xfs_attr_shortform_getvalue(&args); else if (xfs_bmap_one_block(ip, XFS_ATTR_FORK)) error = xfs_attr_leaf_get(&args); else error = xfs_attr_node_get(&args); xfs_iunlock(ip, lock_mode); return(error); *valuelenp = args.valuelen; return error == EEXIST ? 0 : error; } /* Loading @@ -186,12 +162,10 @@ xfs_attr_get( */ STATIC int xfs_attr_calc_size( struct xfs_inode *ip, int namelen, int valuelen, struct xfs_da_args *args, int *local) { struct xfs_mount *mp = ip->i_mount; struct xfs_mount *mp = args->dp->i_mount; int size; int nblks; Loading @@ -199,7 +173,7 @@ xfs_attr_calc_size( * Determine space new attribute will use, and if it would be * "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); nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK); Loading @@ -213,7 +187,7 @@ xfs_attr_calc_size( * Out of line attribute, cannot double split, but * 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 += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK); } Loading @@ -221,26 +195,38 @@ xfs_attr_calc_size( return nblks; } STATIC int xfs_attr_set_int( int xfs_attr_set( struct xfs_inode *dp, struct xfs_name *name, const unsigned char *name, unsigned char *value, int valuelen, 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_da_args args; struct xfs_bmap_free flist; struct xfs_trans_res tres; xfs_fsblock_t firstblock; 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); if (error) return error; Loading @@ -251,31 +237,13 @@ xfs_attr_set_int( */ if (XFS_IFORK_Q(dp) == 0) { 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))) return(error); error = xfs_bmap_add_attrfork(dp, sf_size, rsvd); 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. * Loading Loading @@ -303,7 +271,7 @@ xfs_attr_set_int( error = xfs_trans_reserve(args.trans, &tres, args.total, 0); if (error) { xfs_trans_cancel(args.trans, 0); return(error); return error; } xfs_ilock(dp, XFS_ILOCK_EXCL); Loading @@ -313,7 +281,7 @@ xfs_attr_set_int( if (error) { xfs_iunlock(dp, XFS_ILOCK_EXCL); xfs_trans_cancel(args.trans, XFS_TRANS_RELEASE_LOG_RES); return (error); return error; } xfs_trans_ijoin(args.trans, dp, 0); Loading @@ -322,9 +290,9 @@ xfs_attr_set_int( * If the attribute list is non-existent or a shortform list, * upgrade it to a single-leaf-block attribute list. */ if ((dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) || ((dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS) && (dp->i_d.di_anextents == 0))) { if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL || (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS && dp->i_d.di_anextents == 0)) { /* * Build initial attribute list (if required). Loading @@ -349,9 +317,8 @@ xfs_attr_set_int( * the 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); } if (!error && (flags & ATTR_KERNOTIME) == 0) { xfs_trans_ichgtime(args.trans, dp, Loading @@ -361,7 +328,7 @@ xfs_attr_set_int( XFS_TRANS_RELEASE_LOG_RES); xfs_iunlock(dp, XFS_ILOCK_EXCL); return(error == 0 ? err2 : error); return error ? error : err2; } /* Loading Loading @@ -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); } else { else error = xfs_attr_node_addname(&args); } if (error) { if (error) goto out; } /* * If this is a synchronous mount, make sure that the * 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); } if ((flags & ATTR_KERNOTIME) == 0) xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG); Loading @@ -426,65 +390,47 @@ xfs_attr_set_int( error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES); xfs_iunlock(dp, XFS_ILOCK_EXCL); return(error); return error; out: if (args.trans) if (args.trans) { xfs_trans_cancel(args.trans, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT); } 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 xfs_attr_set( xfs_inode_t *dp, xfs_attr_remove( struct xfs_inode *dp, const unsigned char *name, unsigned char *value, int valuelen, int flags) { struct xfs_mount *mp = dp->i_mount; struct xfs_da_args args; struct xfs_bmap_free flist; xfs_fsblock_t firstblock; int error; struct xfs_name xname; XFS_STATS_INC(xs_attr_set); XFS_STATS_INC(xs_attr_remove); 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) 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.flist = &flist; args.total = 0; args.whichfork = XFS_ATTR_FORK; /* * we have no control over the attribute names that userspace passes us Loading @@ -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; /* * Attach the dquots to the inode. */ error = xfs_qm_dqattach(dp, 0); if (error) return error; Loading Loading @@ -524,7 +467,7 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags) XFS_ATTRRM_SPACE_RES(mp), 0); if (error) { xfs_trans_cancel(args.trans, 0); return(error); return error; } xfs_ilock(dp, XFS_ILOCK_EXCL); Loading @@ -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); /* * Decide on what work routines to call based on the inode size. */ if (!xfs_inode_hasattr(dp)) { error = XFS_ERROR(ENOATTR); goto out; } if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) { } else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) { ASSERT(dp->i_afp->if_flags & XFS_IFINLINE); error = xfs_attr_shortform_remove(&args); if (error) { goto out; } } else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) { error = xfs_attr_leaf_removename(&args); } else { error = xfs_attr_node_removename(&args); } if (error) { if (error) goto out; } /* * If this is a synchronous mount, make sure that the * 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); } if ((flags & ATTR_KERNOTIME) == 0) xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG); Loading @@ -574,44 +508,16 @@ 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); xfs_iunlock(dp, XFS_ILOCK_EXCL); return(error); return error; out: if (args.trans) if (args.trans) { xfs_trans_cancel(args.trans, 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) xfs_iunlock(dp, XFS_ILOCK_EXCL); 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); return xfs_attr_remove_int(dp, &xname, flags); } /*======================================================================== * External routines when attribute list is inside the inode Loading Loading
fs/xfs/xfs_attr.c +117 −211 Original line number Diff line number Diff line Loading @@ -77,17 +77,26 @@ STATIC int xfs_attr_refillstate(xfs_da_state_t *state); STATIC int xfs_attr_name_to_xname( struct xfs_name *xname, const unsigned char *aname) xfs_attr_args_init( struct xfs_da_args *args, struct xfs_inode *dp, const unsigned char *name, int flags) { if (!aname) if (!name) return EINVAL; xname->name = aname; xname->len = strlen((char *)aname); if (xname->len >= MAXNAMELEN) memset(args, 0, sizeof(*args)); 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 */ args->hashval = xfs_da_hashname(args->name, args->namelen); return 0; } Loading @@ -106,79 +115,46 @@ xfs_inode_hasattr( * Overall external interface routines. *========================================================================*/ STATIC int xfs_attr_get_int( struct xfs_inode *ip, struct xfs_name *name, unsigned char *value, int *valuelenp, int flags) { xfs_da_args_t args; int error; if (!xfs_inode_hasattr(ip)) return ENOATTR; /* * 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 = *valuelenp; args.flags = flags; args.hashval = xfs_da_hashname(args.name, args.namelen); args.dp = ip; args.whichfork = XFS_ATTR_FORK; /* * Decide on what work routines to call based on the inode size. */ if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) { error = xfs_attr_shortform_getvalue(&args); } else if (xfs_bmap_one_block(ip, XFS_ATTR_FORK)) { error = xfs_attr_leaf_get(&args); } else { error = xfs_attr_node_get(&args); } /* * Return the number of bytes in the value to the caller. */ *valuelenp = args.valuelen; if (error == EEXIST) error = 0; return(error); } int xfs_attr_get( xfs_inode_t *ip, struct xfs_inode *ip, const unsigned char *name, unsigned char *value, int *valuelenp, int flags) { int error; struct xfs_name xname; struct xfs_da_args args; uint lock_mode; int error; XFS_STATS_INC(xs_attr_get); if (XFS_FORCED_SHUTDOWN(ip->i_mount)) return(EIO); return EIO; if (!xfs_inode_hasattr(ip)) return ENOATTR; error = xfs_attr_name_to_xname(&xname, name); error = xfs_attr_args_init(&args, ip, name, flags); if (error) return error; args.value = value; args.valuelen = *valuelenp; lock_mode = xfs_ilock_attr_map_shared(ip); error = xfs_attr_get_int(ip, &xname, value, valuelenp, flags); if (!xfs_inode_hasattr(ip)) error = ENOATTR; else if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) error = xfs_attr_shortform_getvalue(&args); else if (xfs_bmap_one_block(ip, XFS_ATTR_FORK)) error = xfs_attr_leaf_get(&args); else error = xfs_attr_node_get(&args); xfs_iunlock(ip, lock_mode); return(error); *valuelenp = args.valuelen; return error == EEXIST ? 0 : error; } /* Loading @@ -186,12 +162,10 @@ xfs_attr_get( */ STATIC int xfs_attr_calc_size( struct xfs_inode *ip, int namelen, int valuelen, struct xfs_da_args *args, int *local) { struct xfs_mount *mp = ip->i_mount; struct xfs_mount *mp = args->dp->i_mount; int size; int nblks; Loading @@ -199,7 +173,7 @@ xfs_attr_calc_size( * Determine space new attribute will use, and if it would be * "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); nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK); Loading @@ -213,7 +187,7 @@ xfs_attr_calc_size( * Out of line attribute, cannot double split, but * 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 += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK); } Loading @@ -221,26 +195,38 @@ xfs_attr_calc_size( return nblks; } STATIC int xfs_attr_set_int( int xfs_attr_set( struct xfs_inode *dp, struct xfs_name *name, const unsigned char *name, unsigned char *value, int valuelen, 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_da_args args; struct xfs_bmap_free flist; struct xfs_trans_res tres; xfs_fsblock_t firstblock; 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); if (error) return error; Loading @@ -251,31 +237,13 @@ xfs_attr_set_int( */ if (XFS_IFORK_Q(dp) == 0) { 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))) return(error); error = xfs_bmap_add_attrfork(dp, sf_size, rsvd); 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. * Loading Loading @@ -303,7 +271,7 @@ xfs_attr_set_int( error = xfs_trans_reserve(args.trans, &tres, args.total, 0); if (error) { xfs_trans_cancel(args.trans, 0); return(error); return error; } xfs_ilock(dp, XFS_ILOCK_EXCL); Loading @@ -313,7 +281,7 @@ xfs_attr_set_int( if (error) { xfs_iunlock(dp, XFS_ILOCK_EXCL); xfs_trans_cancel(args.trans, XFS_TRANS_RELEASE_LOG_RES); return (error); return error; } xfs_trans_ijoin(args.trans, dp, 0); Loading @@ -322,9 +290,9 @@ xfs_attr_set_int( * If the attribute list is non-existent or a shortform list, * upgrade it to a single-leaf-block attribute list. */ if ((dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) || ((dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS) && (dp->i_d.di_anextents == 0))) { if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL || (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS && dp->i_d.di_anextents == 0)) { /* * Build initial attribute list (if required). Loading @@ -349,9 +317,8 @@ xfs_attr_set_int( * the 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); } if (!error && (flags & ATTR_KERNOTIME) == 0) { xfs_trans_ichgtime(args.trans, dp, Loading @@ -361,7 +328,7 @@ xfs_attr_set_int( XFS_TRANS_RELEASE_LOG_RES); xfs_iunlock(dp, XFS_ILOCK_EXCL); return(error == 0 ? err2 : error); return error ? error : err2; } /* Loading Loading @@ -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); } else { else error = xfs_attr_node_addname(&args); } if (error) { if (error) goto out; } /* * If this is a synchronous mount, make sure that the * 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); } if ((flags & ATTR_KERNOTIME) == 0) xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG); Loading @@ -426,65 +390,47 @@ xfs_attr_set_int( error = xfs_trans_commit(args.trans, XFS_TRANS_RELEASE_LOG_RES); xfs_iunlock(dp, XFS_ILOCK_EXCL); return(error); return error; out: if (args.trans) if (args.trans) { xfs_trans_cancel(args.trans, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT); } 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 xfs_attr_set( xfs_inode_t *dp, xfs_attr_remove( struct xfs_inode *dp, const unsigned char *name, unsigned char *value, int valuelen, int flags) { struct xfs_mount *mp = dp->i_mount; struct xfs_da_args args; struct xfs_bmap_free flist; xfs_fsblock_t firstblock; int error; struct xfs_name xname; XFS_STATS_INC(xs_attr_set); XFS_STATS_INC(xs_attr_remove); 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) 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.flist = &flist; args.total = 0; args.whichfork = XFS_ATTR_FORK; /* * we have no control over the attribute names that userspace passes us Loading @@ -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; /* * Attach the dquots to the inode. */ error = xfs_qm_dqattach(dp, 0); if (error) return error; Loading Loading @@ -524,7 +467,7 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags) XFS_ATTRRM_SPACE_RES(mp), 0); if (error) { xfs_trans_cancel(args.trans, 0); return(error); return error; } xfs_ilock(dp, XFS_ILOCK_EXCL); Loading @@ -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); /* * Decide on what work routines to call based on the inode size. */ if (!xfs_inode_hasattr(dp)) { error = XFS_ERROR(ENOATTR); goto out; } if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) { } else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) { ASSERT(dp->i_afp->if_flags & XFS_IFINLINE); error = xfs_attr_shortform_remove(&args); if (error) { goto out; } } else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) { error = xfs_attr_leaf_removename(&args); } else { error = xfs_attr_node_removename(&args); } if (error) { if (error) goto out; } /* * If this is a synchronous mount, make sure that the * 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); } if ((flags & ATTR_KERNOTIME) == 0) xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG); Loading @@ -574,44 +508,16 @@ 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); xfs_iunlock(dp, XFS_ILOCK_EXCL); return(error); return error; out: if (args.trans) if (args.trans) { xfs_trans_cancel(args.trans, 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) xfs_iunlock(dp, XFS_ILOCK_EXCL); 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); return xfs_attr_remove_int(dp, &xname, flags); } /*======================================================================== * External routines when attribute list is inside the inode Loading