diff options
Diffstat (limited to 'fs/xfs/libxfs/xfs_attr_leaf.c')
| -rw-r--r-- | fs/xfs/libxfs/xfs_attr_leaf.c | 117 | 
1 files changed, 73 insertions, 44 deletions
diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c index 2f7e89e4be3e..8623c815164a 100644 --- a/fs/xfs/libxfs/xfs_attr_leaf.c +++ b/fs/xfs/libxfs/xfs_attr_leaf.c @@ -660,18 +660,65 @@ xfs_attr_shortform_create(  }  /* + * Return -EEXIST if attr is found, or -ENOATTR if not + * args:  args containing attribute name and namelen + * sfep:  If not null, pointer will be set to the last attr entry found on +	  -EEXIST.  On -ENOATTR pointer is left at the last entry in the list + * basep: If not null, pointer is set to the byte offset of the entry in the + *	  list on -EEXIST.  On -ENOATTR, pointer is left at the byte offset of + *	  the last entry in the list + */ +int +xfs_attr_sf_findname( +	struct xfs_da_args	 *args, +	struct xfs_attr_sf_entry **sfep, +	unsigned int		 *basep) +{ +	struct xfs_attr_shortform *sf; +	struct xfs_attr_sf_entry *sfe; +	unsigned int		base = sizeof(struct xfs_attr_sf_hdr); +	int			size = 0; +	int			end; +	int			i; + +	sf = (struct xfs_attr_shortform *)args->dp->i_afp->if_u1.if_data; +	sfe = &sf->list[0]; +	end = sf->hdr.count; +	for (i = 0; i < end; sfe = XFS_ATTR_SF_NEXTENTRY(sfe), +			     base += size, i++) { +		size = XFS_ATTR_SF_ENTSIZE(sfe); +		if (!xfs_attr_match(args, sfe->namelen, sfe->nameval, +				    sfe->flags)) +			continue; +		break; +	} + +	if (sfep != NULL) +		*sfep = sfe; + +	if (basep != NULL) +		*basep = base; + +	if (i == end) +		return -ENOATTR; +	return -EEXIST; +} + +/*   * Add a name/value pair to the shortform attribute list.   * Overflow from the inode has already been checked for.   */  void -xfs_attr_shortform_add(xfs_da_args_t *args, int forkoff) +xfs_attr_shortform_add( +	struct xfs_da_args		*args, +	int				forkoff)  { -	xfs_attr_shortform_t *sf; -	xfs_attr_sf_entry_t *sfe; -	int i, offset, size; -	xfs_mount_t *mp; -	xfs_inode_t *dp; -	struct xfs_ifork *ifp; +	struct xfs_attr_shortform	*sf; +	struct xfs_attr_sf_entry	*sfe; +	int				offset, size; +	struct xfs_mount		*mp; +	struct xfs_inode		*dp; +	struct xfs_ifork		*ifp;  	trace_xfs_attr_sf_add(args); @@ -682,11 +729,8 @@ xfs_attr_shortform_add(xfs_da_args_t *args, int forkoff)  	ifp = dp->i_afp;  	ASSERT(ifp->if_flags & XFS_IFINLINE);  	sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data; -	sfe = &sf->list[0]; -	for (i = 0; i < sf->hdr.count; sfe = XFS_ATTR_SF_NEXTENTRY(sfe), i++) { -		ASSERT(!xfs_attr_match(args, sfe->namelen, sfe->nameval, -			sfe->flags)); -	} +	if (xfs_attr_sf_findname(args, &sfe, NULL) == -EEXIST) +		ASSERT(0);  	offset = (char *)sfe - (char *)sf;  	size = XFS_ATTR_SF_ENTSIZE_BYNAME(args->namelen, args->valuelen); @@ -728,31 +772,27 @@ xfs_attr_fork_remove(   * Remove an attribute from the shortform attribute list structure.   */  int -xfs_attr_shortform_remove(xfs_da_args_t *args) +xfs_attr_shortform_remove( +	struct xfs_da_args		*args)  { -	xfs_attr_shortform_t *sf; -	xfs_attr_sf_entry_t *sfe; -	int base, size=0, end, totsize, i; -	xfs_mount_t *mp; -	xfs_inode_t *dp; +	struct xfs_attr_shortform	*sf; +	struct xfs_attr_sf_entry	*sfe; +	int				size = 0, end, totsize; +	unsigned int			base; +	struct xfs_mount		*mp; +	struct xfs_inode		*dp; +	int				error;  	trace_xfs_attr_sf_remove(args);  	dp = args->dp;  	mp = dp->i_mount; -	base = sizeof(xfs_attr_sf_hdr_t);  	sf = (xfs_attr_shortform_t *)dp->i_afp->if_u1.if_data; -	sfe = &sf->list[0]; -	end = sf->hdr.count; -	for (i = 0; i < end; sfe = XFS_ATTR_SF_NEXTENTRY(sfe), -					base += size, i++) { -		size = XFS_ATTR_SF_ENTSIZE(sfe); -		if (xfs_attr_match(args, sfe->namelen, sfe->nameval, -				sfe->flags)) -			break; -	} -	if (i == end) -		return -ENOATTR; + +	error = xfs_attr_sf_findname(args, &sfe, &base); +	if (error != -EEXIST) +		return error; +	size = XFS_ATTR_SF_ENTSIZE(sfe);  	/*  	 * Fix up the attribute fork data, covering the hole @@ -2742,10 +2782,7 @@ xfs_attr3_leaf_clearflag(  			 XFS_DA_LOGRANGE(leaf, name_rmt, sizeof(*name_rmt)));  	} -	/* -	 * Commit the flag value change and start the next trans in series. -	 */ -	return xfs_trans_roll_inode(&args->trans, args->dp); +	return 0;  }  /* @@ -2793,10 +2830,7 @@ xfs_attr3_leaf_setflag(  			 XFS_DA_LOGRANGE(leaf, name_rmt, sizeof(*name_rmt)));  	} -	/* -	 * Commit the flag value change and start the next trans in series. -	 */ -	return xfs_trans_roll_inode(&args->trans, args->dp); +	return 0;  }  /* @@ -2911,10 +2945,5 @@ xfs_attr3_leaf_flipflags(  			 XFS_DA_LOGRANGE(leaf2, name_rmt, sizeof(*name_rmt)));  	} -	/* -	 * Commit the flag value change and start the next trans in series. -	 */ -	error = xfs_trans_roll_inode(&args->trans, args->dp); - -	return error; +	return 0;  }  |