diff options
Diffstat (limited to 'fs/xfs/xfs_inode.c')
| -rw-r--r-- | fs/xfs/xfs_inode.c | 52 | 
1 files changed, 34 insertions, 18 deletions
| diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index ceef77c0416a..5599dda4727a 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -874,7 +874,6 @@ xfs_ialloc(  	case S_IFREG:  	case S_IFDIR:  		if (pip && (pip->i_d.di_flags & XFS_DIFLAG_ANY)) { -			uint64_t	di_flags2 = 0;  			uint		di_flags = 0;  			if (S_ISDIR(mode)) { @@ -911,20 +910,23 @@ xfs_ialloc(  				di_flags |= XFS_DIFLAG_NODEFRAG;  			if (pip->i_d.di_flags & XFS_DIFLAG_FILESTREAM)  				di_flags |= XFS_DIFLAG_FILESTREAM; -			if (pip->i_d.di_flags2 & XFS_DIFLAG2_DAX) -				di_flags2 |= XFS_DIFLAG2_DAX;  			ip->i_d.di_flags |= di_flags; -			ip->i_d.di_flags2 |= di_flags2;  		}  		if (pip &&  		    (pip->i_d.di_flags2 & XFS_DIFLAG2_ANY) &&  		    pip->i_d.di_version == 3 &&  		    ip->i_d.di_version == 3) { +			uint64_t	di_flags2 = 0; +  			if (pip->i_d.di_flags2 & XFS_DIFLAG2_COWEXTSIZE) { -				ip->i_d.di_flags2 |= XFS_DIFLAG2_COWEXTSIZE; +				di_flags2 |= XFS_DIFLAG2_COWEXTSIZE;  				ip->i_d.di_cowextsize = pip->i_d.di_cowextsize;  			} +			if (pip->i_d.di_flags2 & XFS_DIFLAG2_DAX) +				di_flags2 |= XFS_DIFLAG2_DAX; + +			ip->i_d.di_flags2 |= di_flags2;  		}  		/* FALLTHROUGH */  	case S_IFLNK: @@ -1053,7 +1055,7 @@ xfs_dir_ialloc(  			tp->t_flags &= ~(XFS_TRANS_DQ_DIRTY);  		} -		code = xfs_trans_roll(&tp, NULL); +		code = xfs_trans_roll(&tp);  		if (committed != NULL)  			*committed = 1; @@ -1283,7 +1285,7 @@ xfs_create(  	 */  	xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp); -	error = xfs_defer_finish(&tp, &dfops, NULL); +	error = xfs_defer_finish(&tp, &dfops);  	if (error)  		goto out_bmap_cancel; @@ -1511,7 +1513,7 @@ xfs_link(  	if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC))  		xfs_trans_set_sync(tp); -	error = xfs_defer_finish(&tp, &dfops, NULL); +	error = xfs_defer_finish(&tp, &dfops);  	if (error) {  		xfs_defer_cancel(&dfops);  		goto error_return; @@ -1605,11 +1607,12 @@ xfs_itruncate_extents(  		 * Duplicate the transaction that has the permanent  		 * reservation and commit the old transaction.  		 */ -		error = xfs_defer_finish(&tp, &dfops, ip); +		xfs_defer_ijoin(&dfops, ip); +		error = xfs_defer_finish(&tp, &dfops);  		if (error)  			goto out_bmap_cancel; -		error = xfs_trans_roll(&tp, ip); +		error = xfs_trans_roll_inode(&tp, ip);  		if (error)  			goto out;  	} @@ -1853,7 +1856,7 @@ xfs_inactive_ifree(  	 * Just ignore errors at this point.  There is nothing we can do except  	 * to try to keep going. Make sure it's not a silent error.  	 */ -	error = xfs_defer_finish(&tp, &dfops, NULL); +	error = xfs_defer_finish(&tp, &dfops);  	if (error) {  		xfs_notice(mp, "%s: xfs_defer_finish returned error %d",  			__func__, error); @@ -2357,11 +2360,24 @@ retry:  			 * already marked stale. If we can't lock it, back off  			 * and retry.  			 */ -			if (ip != free_ip && -			    !xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) { -				rcu_read_unlock(); -				delay(1); -				goto retry; +			if (ip != free_ip) { +				if (!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) { +					rcu_read_unlock(); +					delay(1); +					goto retry; +				} + +				/* +				 * Check the inode number again in case we're +				 * racing with freeing in xfs_reclaim_inode(). +				 * See the comments in that function for more +				 * information as to why the initial check is +				 * not sufficient. +				 */ +				if (ip->i_ino != inum + i) { +					xfs_iunlock(ip, XFS_ILOCK_EXCL); +					continue; +				}  			}  			rcu_read_unlock(); @@ -2635,7 +2651,7 @@ xfs_remove(  	if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC))  		xfs_trans_set_sync(tp); -	error = xfs_defer_finish(&tp, &dfops, NULL); +	error = xfs_defer_finish(&tp, &dfops);  	if (error)  		goto out_bmap_cancel; @@ -2721,7 +2737,7 @@ xfs_finish_rename(  	if (tp->t_mountp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC))  		xfs_trans_set_sync(tp); -	error = xfs_defer_finish(&tp, dfops, NULL); +	error = xfs_defer_finish(&tp, dfops);  	if (error) {  		xfs_defer_cancel(dfops);  		xfs_trans_cancel(tp); | 
