diff options
Diffstat (limited to 'fs/xfs/xfs_inode.c')
| -rw-r--r-- | fs/xfs/xfs_inode.c | 47 | 
1 files changed, 32 insertions, 15 deletions
| diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 58fb7a5062e1..a4e3cd8971fc 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -42,6 +42,7 @@  #include "xfs_pnfs.h"  #include "xfs_parent.h"  #include "xfs_xattr.h" +#include "xfs_sb.h"  struct kmem_cache *xfs_inode_cache; @@ -870,9 +871,16 @@ xfs_init_new_inode(  	 * this saves us from needing to run a separate transaction to set the  	 * fork offset in the immediate future.  	 */ -	if (init_xattrs && xfs_has_attr(mp)) { +	if (init_xattrs) {  		ip->i_forkoff = xfs_default_attroffset(ip) >> 3;  		xfs_ifork_init_attr(ip, XFS_DINODE_FMT_EXTENTS, 0); + +		if (!xfs_has_attr(mp)) { +			spin_lock(&mp->m_sb_lock); +			xfs_add_attr(mp); +			spin_unlock(&mp->m_sb_lock); +			xfs_log_sb(tp); +		}  	}  	/* @@ -1595,7 +1603,7 @@ xfs_release(  	if (!xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL))  		return 0; -	if (xfs_can_free_eofblocks(ip, false)) { +	if (xfs_can_free_eofblocks(ip)) {  		/*  		 * Check if the inode is being opened, written and closed  		 * frequently and we have delayed allocation blocks outstanding @@ -1856,15 +1864,13 @@ xfs_inode_needs_inactive(  	/*  	 * This file isn't being freed, so check if there are post-eof blocks -	 * to free.  @force is true because we are evicting an inode from the -	 * cache.  Post-eof blocks must be freed, lest we end up with broken -	 * free space accounting. +	 * to free.  	 *  	 * Note: don't bother with iolock here since lockdep complains about  	 * acquiring it in reclaim context. We have the only reference to the  	 * inode at this point anyways.  	 */ -	return xfs_can_free_eofblocks(ip, true); +	return xfs_can_free_eofblocks(ip);  }  /* @@ -1947,15 +1953,11 @@ xfs_inactive(  	if (VFS_I(ip)->i_nlink != 0) {  		/* -		 * force is true because we are evicting an inode from the -		 * cache. Post-eof blocks must be freed, lest we end up with -		 * broken free space accounting. -		 *  		 * Note: don't bother with iolock here since lockdep complains  		 * about acquiring it in reclaim context. We have the only  		 * reference to the inode at this point anyways.  		 */ -		if (xfs_can_free_eofblocks(ip, true)) +		if (xfs_can_free_eofblocks(ip))  			error = xfs_free_eofblocks(ip);  		goto out; @@ -2548,11 +2550,26 @@ xfs_ifree_cluster(  		 * This buffer may not have been correctly initialised as we  		 * didn't read it from disk. That's not important because we are  		 * only using to mark the buffer as stale in the log, and to -		 * attach stale cached inodes on it. That means it will never be -		 * dispatched for IO. If it is, we want to know about it, and we -		 * want it to fail. We can acheive this by adding a write -		 * verifier to the buffer. +		 * attach stale cached inodes on it. +		 * +		 * For the inode that triggered the cluster freeing, this +		 * attachment may occur in xfs_inode_item_precommit() after we +		 * have marked this buffer stale.  If this buffer was not in +		 * memory before xfs_ifree_cluster() started, it will not be +		 * marked XBF_DONE and this will cause problems later in +		 * xfs_inode_item_precommit() when we trip over a (stale, !done) +		 * buffer to attached to the transaction. +		 * +		 * Hence we have to mark the buffer as XFS_DONE here. This is +		 * safe because we are also marking the buffer as XBF_STALE and +		 * XFS_BLI_STALE. That means it will never be dispatched for +		 * IO and it won't be unlocked until the cluster freeing has +		 * been committed to the journal and the buffer unpinned. If it +		 * is written, we want to know about it, and we want it to +		 * fail. We can acheive this by adding a write verifier to the +		 * buffer.  		 */ +		bp->b_flags |= XBF_DONE;  		bp->b_ops = &xfs_inode_buf_ops;  		/* |