diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-09-01 15:33:16 -0700 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-09-01 15:33:16 -0700 | 
| commit | 7d1ce606a37922879cbe40a6122047827105a332 (patch) | |
| tree | 0da4d9a2ef1d0dcca8a6c977267e4f9da13fe375 | |
| parent | 071e31e254e0e0c438eecba3dba1d6e2d0da36c2 (diff) | |
| parent | ea78d80866ce375defb2fdd1c8a3aafec95e0f85 (diff) | |
Merge tag 'xfs-iomap-for-linus-4.8-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/dgc/linux-xfs
Pull xfs and iomap fixes from Dave Chinner:
 "Most of these changes are small regression fixes that address problems
  introduced in the 4.8-rc1 window.  The two fixes that aren't (IO
  completion fix and superblock inprogress check) are fixes for problems
  introduced some time ago and need to be pushed back to stable kernels.
  Changes in this update:
   - iomap FIEMAP_EXTENT_MERGED usage fix
   - additional mount-time feature restrictions
   - rmap btree query fixes
   - freeze/unmount io completion workqueue fix
   - memory corruption fix for deferred operations handling"
* tag 'xfs-iomap-for-linus-4.8-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/dgc/linux-xfs:
  xfs: track log done items directly in the deferred pending work item
  iomap: don't set FIEMAP_EXTENT_MERGED for extent based filesystems
  xfs: prevent dropping ioend completions during buftarg wait
  xfs: fix superblock inprogress check
  xfs: simple btree query range should look right if LE lookup fails
  xfs: fix some key handling problems in _btree_simple_query_range
  xfs: don't log the entire end of the AGF
  xfs: disallow mounting of realtime + rmap filesystems
  xfs: don't perform lookups on zero-height btrees
| -rw-r--r-- | fs/iomap.c | 5 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_alloc.c | 2 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_btree.c | 14 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_defer.c | 17 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_defer.h | 2 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_format.h | 6 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_sb.c | 3 | ||||
| -rw-r--r-- | fs/xfs/xfs_buf.c | 2 | ||||
| -rw-r--r-- | fs/xfs/xfs_super.c | 9 | ||||
| -rw-r--r-- | fs/xfs/xfs_trace.h | 2 | ||||
| -rw-r--r-- | include/linux/iomap.h | 8 | 
11 files changed, 47 insertions, 23 deletions
| diff --git a/fs/iomap.c b/fs/iomap.c index 0342254646e3..706270f21b35 100644 --- a/fs/iomap.c +++ b/fs/iomap.c @@ -428,9 +428,12 @@ static int iomap_to_fiemap(struct fiemap_extent_info *fi,  		break;  	} +	if (iomap->flags & IOMAP_F_MERGED) +		flags |= FIEMAP_EXTENT_MERGED; +  	return fiemap_fill_next_extent(fi, iomap->offset,  			iomap->blkno != IOMAP_NULL_BLOCK ? iomap->blkno << 9: 0, -			iomap->length, flags | FIEMAP_EXTENT_MERGED); +			iomap->length, flags);  } diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 3dd8f1d54498..05b5243d89f6 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -2278,6 +2278,8 @@ xfs_alloc_log_agf(  		offsetof(xfs_agf_t, agf_btreeblks),  		offsetof(xfs_agf_t, agf_uuid),  		offsetof(xfs_agf_t, agf_rmap_blocks), +		/* needed so that we don't log the whole rest of the structure: */ +		offsetof(xfs_agf_t, agf_spare64),  		sizeof(xfs_agf_t)  	}; diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c index b5c213a051cd..08569792fe20 100644 --- a/fs/xfs/libxfs/xfs_btree.c +++ b/fs/xfs/libxfs/xfs_btree.c @@ -1814,6 +1814,10 @@ xfs_btree_lookup(  	XFS_BTREE_STATS_INC(cur, lookup); +	/* No such thing as a zero-level tree. */ +	if (cur->bc_nlevels == 0) +		return -EFSCORRUPTED; +  	block = NULL;  	keyno = 0; @@ -4554,15 +4558,22 @@ xfs_btree_simple_query_range(  	if (error)  		goto out; +	/* Nothing?  See if there's anything to the right. */ +	if (!stat) { +		error = xfs_btree_increment(cur, 0, &stat); +		if (error) +			goto out; +	} +  	while (stat) {  		/* Find the record. */  		error = xfs_btree_get_rec(cur, &recp, &stat);  		if (error || !stat)  			break; -		cur->bc_ops->init_high_key_from_rec(&rec_key, recp);  		/* Skip if high_key(rec) < low_key. */  		if (firstrec) { +			cur->bc_ops->init_high_key_from_rec(&rec_key, recp);  			firstrec = false;  			diff = cur->bc_ops->diff_two_keys(cur, low_key,  					&rec_key); @@ -4571,6 +4582,7 @@ xfs_btree_simple_query_range(  		}  		/* Stop if high_key < low_key(rec). */ +		cur->bc_ops->init_key_from_rec(&rec_key, recp);  		diff = cur->bc_ops->diff_two_keys(cur, &rec_key, high_key);  		if (diff > 0)  			break; diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index 054a2032fdb3..c221d0ecd52e 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c @@ -194,7 +194,7 @@ xfs_defer_trans_abort(  	/* Abort intent items. */  	list_for_each_entry(dfp, &dop->dop_pending, dfp_list) {  		trace_xfs_defer_pending_abort(tp->t_mountp, dfp); -		if (dfp->dfp_committed) +		if (!dfp->dfp_done)  			dfp->dfp_type->abort_intent(dfp->dfp_intent);  	} @@ -290,7 +290,6 @@ xfs_defer_finish(  	struct xfs_defer_pending	*dfp;  	struct list_head		*li;  	struct list_head		*n; -	void				*done_item = NULL;  	void				*state;  	int				error = 0;  	void				(*cleanup_fn)(struct xfs_trans *, void *, int); @@ -309,19 +308,11 @@ xfs_defer_finish(  		if (error)  			goto out; -		/* Mark all pending intents as committed. */ -		list_for_each_entry_reverse(dfp, &dop->dop_pending, dfp_list) { -			if (dfp->dfp_committed) -				break; -			trace_xfs_defer_pending_commit((*tp)->t_mountp, dfp); -			dfp->dfp_committed = true; -		} -  		/* Log an intent-done item for the first pending item. */  		dfp = list_first_entry(&dop->dop_pending,  				struct xfs_defer_pending, dfp_list);  		trace_xfs_defer_pending_finish((*tp)->t_mountp, dfp); -		done_item = dfp->dfp_type->create_done(*tp, dfp->dfp_intent, +		dfp->dfp_done = dfp->dfp_type->create_done(*tp, dfp->dfp_intent,  				dfp->dfp_count);  		cleanup_fn = dfp->dfp_type->finish_cleanup; @@ -331,7 +322,7 @@ xfs_defer_finish(  			list_del(li);  			dfp->dfp_count--;  			error = dfp->dfp_type->finish_item(*tp, dop, li, -					done_item, &state); +					dfp->dfp_done, &state);  			if (error) {  				/*  				 * Clean up after ourselves and jump out. @@ -428,8 +419,8 @@ xfs_defer_add(  		dfp = kmem_alloc(sizeof(struct xfs_defer_pending),  				KM_SLEEP | KM_NOFS);  		dfp->dfp_type = defer_op_types[type]; -		dfp->dfp_committed = false;  		dfp->dfp_intent = NULL; +		dfp->dfp_done = NULL;  		dfp->dfp_count = 0;  		INIT_LIST_HEAD(&dfp->dfp_work);  		list_add_tail(&dfp->dfp_list, &dop->dop_intake); diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h index cc3981c48296..e96533d178cf 100644 --- a/fs/xfs/libxfs/xfs_defer.h +++ b/fs/xfs/libxfs/xfs_defer.h @@ -30,8 +30,8 @@ struct xfs_defer_op_type;  struct xfs_defer_pending {  	const struct xfs_defer_op_type	*dfp_type;	/* function pointers */  	struct list_head		dfp_list;	/* pending items */ -	bool				dfp_committed;	/* committed trans? */  	void				*dfp_intent;	/* log intent item */ +	void				*dfp_done;	/* log done item */  	struct list_head		dfp_work;	/* work items */  	unsigned int			dfp_count;	/* # extent items */  }; diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index e6a8bea0f7ba..270fb5cf4fa1 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -674,7 +674,8 @@ typedef struct xfs_agf {  #define	XFS_AGF_BTREEBLKS	0x00000800  #define	XFS_AGF_UUID		0x00001000  #define	XFS_AGF_RMAP_BLOCKS	0x00002000 -#define	XFS_AGF_NUM_BITS	14 +#define	XFS_AGF_SPARE64		0x00004000 +#define	XFS_AGF_NUM_BITS	15  #define	XFS_AGF_ALL_BITS	((1 << XFS_AGF_NUM_BITS) - 1)  #define XFS_AGF_FLAGS \ @@ -691,7 +692,8 @@ typedef struct xfs_agf {  	{ XFS_AGF_LONGEST,	"LONGEST" }, \  	{ XFS_AGF_BTREEBLKS,	"BTREEBLKS" }, \  	{ XFS_AGF_UUID,		"UUID" }, \ -	{ XFS_AGF_RMAP_BLOCKS,	"RMAP_BLOCKS" } +	{ XFS_AGF_RMAP_BLOCKS,	"RMAP_BLOCKS" }, \ +	{ XFS_AGF_SPARE64,	"SPARE64" }  /* disk block (xfs_daddr_t) in the AG */  #define XFS_AGF_DADDR(mp)	((xfs_daddr_t)(1 << (mp)->m_sectbb_log)) diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index 0e3d4f5ec33c..4aecc5fefe96 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -583,7 +583,8 @@ xfs_sb_verify(  	 * Only check the in progress field for the primary superblock as  	 * mkfs.xfs doesn't clear it from secondary superblocks.  	 */ -	return xfs_mount_validate_sb(mp, &sb, bp->b_bn == XFS_SB_DADDR, +	return xfs_mount_validate_sb(mp, &sb, +				     bp->b_maps[0].bm_bn == XFS_SB_DADDR,  				     check_version);  } diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index 607cc29bba21..b5b9bffe3520 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -1611,7 +1611,7 @@ xfs_wait_buftarg(  	 */  	while (percpu_counter_sum(&btp->bt_io_count))  		delay(100); -	drain_workqueue(btp->bt_mount->m_buf_workqueue); +	flush_workqueue(btp->bt_mount->m_buf_workqueue);  	/* loop until there is nothing left on the lru list. */  	while (list_lru_count(&btp->bt_lru)) { diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 24ef83ef04de..fd6be45b3a1e 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -1574,9 +1574,16 @@ xfs_fs_fill_super(  		}  	} -	if (xfs_sb_version_hasrmapbt(&mp->m_sb)) +	if (xfs_sb_version_hasrmapbt(&mp->m_sb)) { +		if (mp->m_sb.sb_rblocks) { +			xfs_alert(mp, +	"EXPERIMENTAL reverse mapping btree not compatible with realtime device!"); +			error = -EINVAL; +			goto out_filestream_unmount; +		}  		xfs_alert(mp,  	"EXPERIMENTAL reverse mapping btree feature enabled. Use at your own risk!"); +	}  	error = xfs_mountfs(mp);  	if (error) diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 7e88bec3f359..d303a665dba9 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -2295,7 +2295,7 @@ DECLARE_EVENT_CLASS(xfs_defer_pending_class,  		__entry->dev = mp ? mp->m_super->s_dev : 0;  		__entry->type = dfp->dfp_type->type;  		__entry->intent = dfp->dfp_intent; -		__entry->committed = dfp->dfp_committed; +		__entry->committed = dfp->dfp_done != NULL;  		__entry->nr = dfp->dfp_count;  	),  	TP_printk("dev %d:%d optype %d intent %p committed %d nr %d\n", diff --git a/include/linux/iomap.h b/include/linux/iomap.h index 3267df461012..3d70ece10313 100644 --- a/include/linux/iomap.h +++ b/include/linux/iomap.h @@ -19,6 +19,11 @@ struct vm_fault;  #define IOMAP_UNWRITTEN	0x04	/* blocks allocated @blkno in unwritten state */  /* + * Flags for iomap mappings: + */ +#define IOMAP_F_MERGED	0x01	/* contains multiple blocks/extents */ + +/*   * Magic value for blkno:   */  #define IOMAP_NULL_BLOCK -1LL	/* blkno is not valid */ @@ -27,7 +32,8 @@ struct iomap {  	sector_t		blkno;	/* 1st sector of mapping, 512b units */  	loff_t			offset;	/* file offset of mapping, bytes */  	u64			length;	/* length of mapping, bytes */ -	int			type;	/* type of mapping */ +	u16			type;	/* type of mapping */ +	u16			flags;	/* flags for mapping */  	struct block_device	*bdev;	/* block device for I/O */  }; | 
