diff options
Diffstat (limited to 'fs/xfs/libxfs/xfs_trans_inode.c')
| -rw-r--r-- | fs/xfs/libxfs/xfs_trans_inode.c | 113 | 
1 files changed, 8 insertions, 105 deletions
diff --git a/fs/xfs/libxfs/xfs_trans_inode.c b/fs/xfs/libxfs/xfs_trans_inode.c index 8b5547073379..cb4796b6e693 100644 --- a/fs/xfs/libxfs/xfs_trans_inode.c +++ b/fs/xfs/libxfs/xfs_trans_inode.c @@ -40,9 +40,8 @@ xfs_trans_ijoin(  	iip->ili_lock_flags = lock_flags;  	ASSERT(!xfs_iflags_test(ip, XFS_ISTALE)); -	/* -	 * Get a log_item_desc to point at the new item. -	 */ +	/* Reset the per-tx dirty context and add the item to the tx. */ +	iip->ili_dirty_flags = 0;  	xfs_trans_add_item(tp, &iip->ili_item);  } @@ -76,17 +75,10 @@ xfs_trans_ichgtime(  /*   * This is called to mark the fields indicated in fieldmask as needing to be   * logged when the transaction is committed.  The inode must already be - * associated with the given transaction. - * - * The values for fieldmask are defined in xfs_inode_item.h.  We always log all - * of the core inode if any of it has changed, and we always log all of the - * inline data/extents/b-tree root if any of them has changed. - * - * Grab and pin the cluster buffer associated with this inode to avoid RMW - * cycles at inode writeback time. Avoid the need to add error handling to every - * xfs_trans_log_inode() call by shutting down on read error.  This will cause - * transactions to fail and everything to error out, just like if we return a - * read error in a dirty transaction and cancel it. + * associated with the given transaction. All we do here is record where the + * inode was dirtied and mark the transaction and inode log item dirty; + * everything else is done in the ->precommit log item operation after the + * changes in the transaction have been completed.   */  void  xfs_trans_log_inode( @@ -96,7 +88,6 @@ xfs_trans_log_inode(  {  	struct xfs_inode_log_item *iip = ip->i_itemp;  	struct inode		*inode = VFS_I(ip); -	uint			iversion_flags = 0;  	ASSERT(iip);  	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); @@ -105,18 +96,6 @@ xfs_trans_log_inode(  	tp->t_flags |= XFS_TRANS_DIRTY;  	/* -	 * Don't bother with i_lock for the I_DIRTY_TIME check here, as races -	 * don't matter - we either will need an extra transaction in 24 hours -	 * to log the timestamps, or will clear already cleared fields in the -	 * worst case. -	 */ -	if (inode->i_state & I_DIRTY_TIME) { -		spin_lock(&inode->i_lock); -		inode->i_state &= ~I_DIRTY_TIME; -		spin_unlock(&inode->i_lock); -	} - -	/*  	 * First time we log the inode in a transaction, bump the inode change  	 * counter if it is configured for this to occur. While we have the  	 * inode locked exclusively for metadata modification, we can usually @@ -128,86 +107,10 @@ xfs_trans_log_inode(  	if (!test_and_set_bit(XFS_LI_DIRTY, &iip->ili_item.li_flags)) {  		if (IS_I_VERSION(inode) &&  		    inode_maybe_inc_iversion(inode, flags & XFS_ILOG_CORE)) -			iversion_flags = XFS_ILOG_CORE; -	} - -	/* -	 * If we're updating the inode core or the timestamps and it's possible -	 * to upgrade this inode to bigtime format, do so now. -	 */ -	if ((flags & (XFS_ILOG_CORE | XFS_ILOG_TIMESTAMP)) && -	    xfs_has_bigtime(ip->i_mount) && -	    !xfs_inode_has_bigtime(ip)) { -		ip->i_diflags2 |= XFS_DIFLAG2_BIGTIME; -		flags |= XFS_ILOG_CORE; -	} - -	/* -	 * Inode verifiers do not check that the extent size hint is an integer -	 * multiple of the rt extent size on a directory with both rtinherit -	 * and extszinherit flags set.  If we're logging a directory that is -	 * misconfigured in this way, clear the hint. -	 */ -	if ((ip->i_diflags & XFS_DIFLAG_RTINHERIT) && -	    (ip->i_diflags & XFS_DIFLAG_EXTSZINHERIT) && -	    (ip->i_extsize % ip->i_mount->m_sb.sb_rextsize) > 0) { -		ip->i_diflags &= ~(XFS_DIFLAG_EXTSIZE | -				   XFS_DIFLAG_EXTSZINHERIT); -		ip->i_extsize = 0; -		flags |= XFS_ILOG_CORE; +			flags |= XFS_ILOG_IVERSION;  	} -	/* -	 * Record the specific change for fdatasync optimisation. This allows -	 * fdatasync to skip log forces for inodes that are only timestamp -	 * dirty. -	 */ -	spin_lock(&iip->ili_lock); -	iip->ili_fsync_fields |= flags; - -	if (!iip->ili_item.li_buf) { -		struct xfs_buf	*bp; -		int		error; - -		/* -		 * We hold the ILOCK here, so this inode is not going to be -		 * flushed while we are here. Further, because there is no -		 * buffer attached to the item, we know that there is no IO in -		 * progress, so nothing will clear the ili_fields while we read -		 * in the buffer. Hence we can safely drop the spin lock and -		 * read the buffer knowing that the state will not change from -		 * here. -		 */ -		spin_unlock(&iip->ili_lock); -		error = xfs_imap_to_bp(ip->i_mount, tp, &ip->i_imap, &bp); -		if (error) { -			xfs_force_shutdown(ip->i_mount, SHUTDOWN_META_IO_ERROR); -			return; -		} - -		/* -		 * We need an explicit buffer reference for the log item but -		 * don't want the buffer to remain attached to the transaction. -		 * Hold the buffer but release the transaction reference once -		 * we've attached the inode log item to the buffer log item -		 * list. -		 */ -		xfs_buf_hold(bp); -		spin_lock(&iip->ili_lock); -		iip->ili_item.li_buf = bp; -		bp->b_flags |= _XBF_INODES; -		list_add_tail(&iip->ili_item.li_bio_list, &bp->b_li_list); -		xfs_trans_brelse(tp, bp); -	} - -	/* -	 * Always OR in the bits from the ili_last_fields field.  This is to -	 * coordinate with the xfs_iflush() and xfs_buf_inode_iodone() routines -	 * in the eventual clearing of the ili_fields bits.  See the big comment -	 * in xfs_iflush() for an explanation of this coordination mechanism. -	 */ -	iip->ili_fields |= (flags | iip->ili_last_fields | iversion_flags); -	spin_unlock(&iip->ili_lock); +	iip->ili_dirty_flags |= flags;  }  int  |