diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-08-14 02:17:49 +0400 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-08-14 02:17:49 +0400 | 
| commit | 9ea319b61613085f501a79cf8d405cb221d084f3 (patch) | |
| tree | 5bf7e1b9f104a0df029d355927fa9eb398db37bb /fs/xfs/xfs_attr.c | |
| parent | 3e11acd4306d558249c31cf6cac09f218f2de52e (diff) | |
| parent | c6a7b0f8a49aa71792dd108efc535435f462bf79 (diff) | |
| download | linux-9ea319b61613085f501a79cf8d405cb221d084f3.tar.xz | |
Merge git://oss.sgi.com:8090/xfs/linux-2.6
* git://oss.sgi.com:8090/xfs/linux-2.6: (45 commits)
  [XFS] Fix use after free in xfs_log_done().
  [XFS] Make xfs_bmap_*_count_leaves void.
  [XFS] Use KM_NOFS for debug trace buffers
  [XFS] use KM_MAYFAIL in xfs_mountfs
  [XFS] refactor xfs_mount_free
  [XFS] don't call xfs_freesb from xfs_unmountfs
  [XFS] xfs_unmountfs should return void
  [XFS] cleanup xfs_mountfs
  [XFS] move root inode IRELE into xfs_unmountfs
  [XFS] stop using file_update_time
  [XFS] optimize xfs_ichgtime
  [XFS] update timestamp in xfs_ialloc manually
  [XFS] remove the sema_t from XFS.
  [XFS] replace dquot flush semaphore with a completion
  [XFS] replace inode flush semaphore with a completion
  [XFS] extend completions to provide XFS object flush requirements
  [XFS] replace the XFS buf iodone semaphore with a completion
  [XFS] clean up stale references to semaphores
  [XFS] use get_unaligned_* helpers
  [XFS] Fix compile failure in xfs_buf_trace()
  ...
Diffstat (limited to 'fs/xfs/xfs_attr.c')
| -rw-r--r-- | fs/xfs/xfs_attr.c | 110 | 
1 files changed, 68 insertions, 42 deletions
| diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index 78de80e3caa2..f7cdc28aff41 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c @@ -194,6 +194,46 @@ xfs_attr_get(  	return(error);  } +/* + * Calculate how many blocks we need for the new attribute, + */ +int +xfs_attr_calc_size( +	struct xfs_inode 	*ip, +	int			namelen, +	int			valuelen, +	int			*local) +{ +	struct xfs_mount 	*mp = ip->i_mount; +	int			size; +	int			nblks; + +	/* +	 * Determine space new attribute will use, and if it would be +	 * "local" or "remote" (note: local != inline). +	 */ +	size = xfs_attr_leaf_newentsize(namelen, valuelen, +					mp->m_sb.sb_blocksize, local); + +	nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK); +	if (*local) { +		if (size > (mp->m_sb.sb_blocksize >> 1)) { +			/* Double split possible */ +			nblks *= 2; +		} +	} else { +		/* +		 * Out of line attribute, cannot double split, but +		 * make room for the attribute value itself. +		 */ +		uint	dblocks = XFS_B_TO_FSB(mp, valuelen); +		nblks += dblocks; +		nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK); +	} + +	return nblks; +} +  STATIC int  xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name,  		char *value, int valuelen, int flags) @@ -202,10 +242,9 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name,  	xfs_fsblock_t	firstblock;  	xfs_bmap_free_t flist;  	int		error, err2, committed; -	int		local, size; -	uint		nblks;  	xfs_mount_t	*mp = dp->i_mount;  	int             rsvd = (flags & ATTR_ROOT) != 0; +	int		local;  	/*  	 * Attach the dquots to the inode. @@ -241,30 +280,8 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name,  	args.whichfork = XFS_ATTR_FORK;  	args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT; -	/* -	 * Determine space new attribute will use, and if it would be -	 * "local" or "remote" (note: local != inline). -	 */ -	size = xfs_attr_leaf_newentsize(name->len, valuelen, -					mp->m_sb.sb_blocksize, &local); - -	nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK); -	if (local) { -		if (size > (mp->m_sb.sb_blocksize >> 1)) { -			/* Double split possible */ -			nblks <<= 1; -		} -	} else { -		uint	dblocks = XFS_B_TO_FSB(mp, valuelen); -		/* Out of line attribute, cannot double split, but make -		 * room for the attribute value itself. -		 */ -		nblks += dblocks; -		nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK); -	} -  	/* Size is now blocks for attribute data */ -	args.total = nblks; +	args.total = xfs_attr_calc_size(dp, name->len, valuelen, &local);  	/*  	 * Start our first transaction of the day. @@ -286,18 +303,17 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name,  	if (rsvd)  		args.trans->t_flags |= XFS_TRANS_RESERVE; -	if ((error = xfs_trans_reserve(args.trans, (uint) nblks, -				      XFS_ATTRSET_LOG_RES(mp, nblks), -				      0, XFS_TRANS_PERM_LOG_RES, -				      XFS_ATTRSET_LOG_COUNT))) { +	if ((error = xfs_trans_reserve(args.trans, args.total, +			XFS_ATTRSET_LOG_RES(mp, args.total), 0, +			XFS_TRANS_PERM_LOG_RES, XFS_ATTRSET_LOG_COUNT))) {  		xfs_trans_cancel(args.trans, 0);  		return(error);  	}  	xfs_ilock(dp, XFS_ILOCK_EXCL); -	error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, args.trans, dp, nblks, 0, -			 rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES : -				XFS_QMOPT_RES_REGBLKS); +	error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, args.trans, dp, args.total, 0, +				rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES : +				       XFS_QMOPT_RES_REGBLKS);  	if (error) {  		xfs_iunlock(dp, XFS_ILOCK_EXCL);  		xfs_trans_cancel(args.trans, XFS_TRANS_RELEASE_LOG_RES); @@ -384,7 +400,9 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name,  		 * Commit the leaf transformation.  We'll need another (linked)  		 * transaction to add the new attribute to the leaf.  		 */ -		if ((error = xfs_attr_rolltrans(&args.trans, dp))) + +		error = xfs_trans_roll(&args.trans, dp); +		if (error)  			goto out;  	} @@ -964,7 +982,8 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)  		 * Commit the current trans (including the inode) and start  		 * a new one.  		 */ -		if ((error = xfs_attr_rolltrans(&args->trans, dp))) +		error = xfs_trans_roll(&args->trans, dp); +		if (error)  			return (error);  		/* @@ -978,7 +997,8 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)  	 * Commit the transaction that added the attr name so that  	 * later routines can manage their own transactions.  	 */ -	if ((error = xfs_attr_rolltrans(&args->trans, dp))) +	error = xfs_trans_roll(&args->trans, dp); +	if (error)  		return (error);  	/* @@ -1067,7 +1087,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)  		/*  		 * Commit the remove and start the next trans in series.  		 */ -		error = xfs_attr_rolltrans(&args->trans, dp); +		error = xfs_trans_roll(&args->trans, dp);  	} else if (args->rmtblkno > 0) {  		/* @@ -1298,7 +1318,8 @@ restart:  			 * Commit the node conversion and start the next  			 * trans in the chain.  			 */ -			if ((error = xfs_attr_rolltrans(&args->trans, dp))) +			error = xfs_trans_roll(&args->trans, dp); +			if (error)  				goto out;  			goto restart; @@ -1349,7 +1370,8 @@ restart:  	 * Commit the leaf addition or btree split and start the next  	 * trans in the chain.  	 */ -	if ((error = xfs_attr_rolltrans(&args->trans, dp))) +	error = xfs_trans_roll(&args->trans, dp); +	if (error)  		goto out;  	/* @@ -1449,7 +1471,8 @@ restart:  		/*  		 * Commit and start the next trans in the chain.  		 */ -		if ((error = xfs_attr_rolltrans(&args->trans, dp))) +		error = xfs_trans_roll(&args->trans, dp); +		if (error)  			goto out;  	} else if (args->rmtblkno > 0) { @@ -1581,7 +1604,8 @@ xfs_attr_node_removename(xfs_da_args_t *args)  		/*  		 * Commit the Btree join operation and start a new trans.  		 */ -		if ((error = xfs_attr_rolltrans(&args->trans, dp))) +		error = xfs_trans_roll(&args->trans, dp); +		if (error)  			goto out;  	} @@ -2082,7 +2106,8 @@ xfs_attr_rmtval_set(xfs_da_args_t *args)  		/*  		 * Start the next trans in the chain.  		 */ -		if ((error = xfs_attr_rolltrans(&args->trans, dp))) +		error = xfs_trans_roll(&args->trans, dp); +		if (error)  			return (error);  	} @@ -2232,7 +2257,8 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args)  		/*  		 * Close out trans and start the next one in the chain.  		 */ -		if ((error = xfs_attr_rolltrans(&args->trans, args->dp))) +		error = xfs_trans_roll(&args->trans, args->dp); +		if (error)  			return (error);  	}  	return(0); | 
