diff options
Diffstat (limited to 'fs/xfs/xfs_inode.c')
| -rw-r--r-- | fs/xfs/xfs_inode.c | 104 | 
1 files changed, 29 insertions, 75 deletions
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 9de6205fe134..b2879870a17e 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -416,10 +416,12 @@ xfs_lockdep_subclass_ok(   * parent locking. Care must be taken to ensure we don't overrun the subclass   * storage fields in the class mask we build.   */ -static inline int -xfs_lock_inumorder(int lock_mode, int subclass) +static inline uint +xfs_lock_inumorder( +	uint	lock_mode, +	uint	subclass)  { -	int	class = 0; +	uint	class = 0;  	ASSERT(!(lock_mode & (XFS_ILOCK_PARENT | XFS_ILOCK_RTBITMAP |  			      XFS_ILOCK_RTSUM))); @@ -464,7 +466,10 @@ xfs_lock_inodes(  	int			inodes,  	uint			lock_mode)  { -	int			attempts = 0, i, j, try_lock; +	int			attempts = 0; +	uint			i; +	int			j; +	bool			try_lock;  	struct xfs_log_item	*lp;  	/* @@ -489,9 +494,9 @@ xfs_lock_inodes(  	} else if (lock_mode & XFS_MMAPLOCK_EXCL)  		ASSERT(!(lock_mode & XFS_ILOCK_EXCL)); -	try_lock = 0; -	i = 0;  again: +	try_lock = false; +	i = 0;  	for (; i < inodes; i++) {  		ASSERT(ips[i]); @@ -506,7 +511,7 @@ again:  			for (j = (i - 1); j >= 0 && !try_lock; j--) {  				lp = &ips[j]->i_itemp->ili_item;  				if (lp && test_bit(XFS_LI_IN_AIL, &lp->li_flags)) -					try_lock++; +					try_lock = true;  			}  		} @@ -546,8 +551,6 @@ again:  		if ((attempts % 5) == 0) {  			delay(1); /* Don't just spin the CPU */  		} -		i = 0; -		try_lock = 0;  		goto again;  	}  } @@ -1024,11 +1027,6 @@ xfs_create(  	xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);  	unlock_dp_on_error = true; -	error = xfs_iext_count_may_overflow(dp, XFS_DATA_FORK, -			XFS_IEXT_DIR_MANIP_CNT(mp)); -	if (error) -		goto out_trans_cancel; -  	/*  	 * A newly created regular or special file just has one directory  	 * entry pointing to them, but a directory also the "." entry @@ -1242,11 +1240,6 @@ xfs_link(  	if (error)  		goto std_return; -	error = xfs_iext_count_may_overflow(tdp, XFS_DATA_FORK, -			XFS_IEXT_DIR_MANIP_CNT(mp)); -	if (error) -		goto error_return; -  	/*  	 * If we are using project inheritance, we only allow hard link  	 * creation in our tree when the project IDs are the same; else @@ -2594,14 +2587,13 @@ xfs_ifree_cluster(  }  /* - * This is called to return an inode to the inode free list. - * The inode should already be truncated to 0 length and have - * no pages associated with it.  This routine also assumes that - * the inode is already a part of the transaction. + * This is called to return an inode to the inode free list.  The inode should + * already be truncated to 0 length and have no pages associated with it.  This + * routine also assumes that the inode is already a part of the transaction.   * - * The on-disk copy of the inode will have been added to the list - * of unlinked inodes in the AGI. We need to remove the inode from - * that list atomically with respect to freeing it here. + * The on-disk copy of the inode will have been added to the list of unlinked + * inodes in the AGI. We need to remove the inode from that list atomically with + * respect to freeing it here.   */  int  xfs_ifree( @@ -2623,13 +2615,16 @@ xfs_ifree(  	pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));  	/* -	 * Pull the on-disk inode from the AGI unlinked list. +	 * Free the inode first so that we guarantee that the AGI lock is going +	 * to be taken before we remove the inode from the unlinked list. This +	 * makes the AGI lock -> unlinked list modification order the same as +	 * used in O_TMPFILE creation.  	 */ -	error = xfs_iunlink_remove(tp, pag, ip); +	error = xfs_difree(tp, pag, ip->i_ino, &xic);  	if (error) -		goto out; +		return error; -	error = xfs_difree(tp, pag, ip->i_ino, &xic); +	error = xfs_iunlink_remove(tp, pag, ip);  	if (error)  		goto out; @@ -3210,35 +3205,6 @@ retry:  	/*  	 * Check for expected errors before we dirty the transaction  	 * so we can return an error without a transaction abort. -	 * -	 * Extent count overflow check: -	 * -	 * From the perspective of src_dp, a rename operation is essentially a -	 * directory entry remove operation. Hence the only place where we check -	 * for extent count overflow for src_dp is in -	 * xfs_bmap_del_extent_real(). xfs_bmap_del_extent_real() returns -	 * -ENOSPC when it detects a possible extent count overflow and in -	 * response, the higher layers of directory handling code do the -	 * following: -	 * 1. Data/Free blocks: XFS lets these blocks linger until a -	 *    future remove operation removes them. -	 * 2. Dabtree blocks: XFS swaps the blocks with the last block in the -	 *    Leaf space and unmaps the last block. -	 * -	 * For target_dp, there are two cases depending on whether the -	 * destination directory entry exists or not. -	 * -	 * When destination directory entry does not exist (i.e. target_ip == -	 * NULL), extent count overflow check is performed only when transaction -	 * has a non-zero sized space reservation associated with it.  With a -	 * zero-sized space reservation, XFS allows a rename operation to -	 * continue only when the directory has sufficient free space in its -	 * data/leaf/free space blocks to hold the new entry. -	 * -	 * When destination directory entry exists (i.e. target_ip != NULL), all -	 * we need to do is change the inode number associated with the already -	 * existing entry. Hence there is no need to perform an extent count -	 * overflow check.  	 */  	if (target_ip == NULL) {  		/* @@ -3249,12 +3215,6 @@ retry:  			error = xfs_dir_canenter(tp, target_dp, target_name);  			if (error)  				goto out_trans_cancel; -		} else { -			error = xfs_iext_count_may_overflow(target_dp, -					XFS_DATA_FORK, -					XFS_IEXT_DIR_MANIP_CNT(mp)); -			if (error) -				goto out_trans_cancel;  		}  	} else {  		/* @@ -3422,18 +3382,12 @@ retry:  	 * inode number of the whiteout inode rather than removing it  	 * altogether.  	 */ -	if (wip) { +	if (wip)  		error = xfs_dir_replace(tp, src_dp, src_name, wip->i_ino,  					spaceres); -	} else { -		/* -		 * NOTE: We don't need to check for extent count overflow here -		 * because the dir remove name code will leave the dir block in -		 * place if the extent count would overflow. -		 */ +	else  		error = xfs_dir_removename(tp, src_dp, src_name, src_ip->i_ino,  					   spaceres); -	}  	if (error)  		goto out_trans_cancel; @@ -3515,8 +3469,8 @@ xfs_iflush(  	if (XFS_TEST_ERROR(ip->i_df.if_nextents + xfs_ifork_nextents(ip->i_afp) >  				ip->i_nblocks, mp, XFS_ERRTAG_IFLUSH_5)) {  		xfs_alert_tag(mp, XFS_PTAG_IFLUSH, -			"%s: detected corrupt incore inode %Lu, " -			"total extents = %d, nblocks = %Ld, ptr "PTR_FMT, +			"%s: detected corrupt incore inode %llu, " +			"total extents = %llu nblocks = %lld, ptr "PTR_FMT,  			__func__, ip->i_ino,  			ip->i_df.if_nextents + xfs_ifork_nextents(ip->i_afp),  			ip->i_nblocks, ip);  |