Răsfoiți Sursa

Merge branch 'xfs-misc-fixes-3-for-3.16' into for-next

Dave Chinner 11 ani în urmă
părinte
comite
7691283d05

+ 8 - 11
fs/xfs/xfs_alloc.c

@@ -257,16 +257,14 @@ xfs_alloc_fix_len(
 	k = rlen % args->prod;
 	k = rlen % args->prod;
 	if (k == args->mod)
 	if (k == args->mod)
 		return;
 		return;
-	if (k > args->mod) {
-		if ((int)(rlen = rlen - k - args->mod) < (int)args->minlen)
-			return;
-	} else {
-		if ((int)(rlen = rlen - args->prod - (args->mod - k)) <
-		    (int)args->minlen)
-			return;
-	}
-	ASSERT(rlen >= args->minlen);
-	ASSERT(rlen <= args->maxlen);
+	if (k > args->mod)
+		rlen = rlen - (k - args->mod);
+	else
+		rlen = rlen - args->prod + (args->mod - k);
+	if ((int)rlen < (int)args->minlen)
+		return;
+	ASSERT(rlen >= args->minlen && rlen <= args->maxlen);
+	ASSERT(rlen % args->prod == args->mod);
 	args->len = rlen;
 	args->len = rlen;
 }
 }
 
 
@@ -541,7 +539,6 @@ xfs_alloc_read_agfl(
 			XFS_FSS_TO_BB(mp, 1), 0, &bp, &xfs_agfl_buf_ops);
 			XFS_FSS_TO_BB(mp, 1), 0, &bp, &xfs_agfl_buf_ops);
 	if (error)
 	if (error)
 		return error;
 		return error;
-	ASSERT(!xfs_buf_geterror(bp));
 	xfs_buf_set_ref(bp, XFS_AGFL_REF);
 	xfs_buf_set_ref(bp, XFS_AGFL_REF);
 	*bpp = bp;
 	*bpp = bp;
 	return 0;
 	return 0;

+ 3 - 3
fs/xfs/xfs_aops.c

@@ -975,7 +975,7 @@ xfs_vm_writepage(
 	 * Given that we do not allow direct reclaim to call us, we should
 	 * Given that we do not allow direct reclaim to call us, we should
 	 * never be called while in a filesystem transaction.
 	 * never be called while in a filesystem transaction.
 	 */
 	 */
-	if (WARN_ON(current->flags & PF_FSTRANS))
+	if (WARN_ON_ONCE(current->flags & PF_FSTRANS))
 		goto redirty;
 		goto redirty;
 
 
 	/* Is this page beyond the end of the file? */
 	/* Is this page beyond the end of the file? */
@@ -1225,9 +1225,9 @@ xfs_vm_releasepage(
 
 
 	xfs_count_page_state(page, &delalloc, &unwritten);
 	xfs_count_page_state(page, &delalloc, &unwritten);
 
 
-	if (WARN_ON(delalloc))
+	if (WARN_ON_ONCE(delalloc))
 		return 0;
 		return 0;
-	if (WARN_ON(unwritten))
+	if (WARN_ON_ONCE(unwritten))
 		return 0;
 		return 0;
 
 
 	return try_to_free_buffers(page);
 	return try_to_free_buffers(page);

+ 5 - 2
fs/xfs/xfs_bit.h

@@ -66,8 +66,11 @@ static inline int xfs_lowbit64(__uint64_t v)
 		n = ffs(w);
 		n = ffs(w);
 	} else {	/* upper bits */
 	} else {	/* upper bits */
 		w = (__uint32_t)(v >> 32);
 		w = (__uint32_t)(v >> 32);
-		if (w && (n = ffs(w)))
-		n += 32;
+		if (w) {
+			n = ffs(w);
+			if (n)
+				n += 32;
+		}
 	}
 	}
 	return n - 1;
 	return n - 1;
 }
 }

+ 13 - 3
fs/xfs/xfs_bmap_util.c

@@ -258,14 +258,23 @@ xfs_bmapi_allocate_worker(
 	struct xfs_bmalloca	*args = container_of(work,
 	struct xfs_bmalloca	*args = container_of(work,
 						struct xfs_bmalloca, work);
 						struct xfs_bmalloca, work);
 	unsigned long		pflags;
 	unsigned long		pflags;
+	unsigned long		new_pflags = PF_FSTRANS;
 
 
-	/* we are in a transaction context here */
-	current_set_flags_nested(&pflags, PF_FSTRANS);
+	/*
+	 * we are in a transaction context here, but may also be doing work
+	 * in kswapd context, and hence we may need to inherit that state
+	 * temporarily to ensure that we don't block waiting for memory reclaim
+	 * in any way.
+	 */
+	if (args->kswapd)
+		new_pflags |= PF_MEMALLOC | PF_SWAPWRITE | PF_KSWAPD;
+
+	current_set_flags_nested(&pflags, new_pflags);
 
 
 	args->result = __xfs_bmapi_allocate(args);
 	args->result = __xfs_bmapi_allocate(args);
 	complete(args->done);
 	complete(args->done);
 
 
-	current_restore_flags_nested(&pflags, PF_FSTRANS);
+	current_restore_flags_nested(&pflags, new_pflags);
 }
 }
 
 
 /*
 /*
@@ -284,6 +293,7 @@ xfs_bmapi_allocate(
 
 
 
 
 	args->done = &done;
 	args->done = &done;
+	args->kswapd = current_is_kswapd();
 	INIT_WORK_ONSTACK(&args->work, xfs_bmapi_allocate_worker);
 	INIT_WORK_ONSTACK(&args->work, xfs_bmapi_allocate_worker);
 	queue_work(xfs_alloc_wq, &args->work);
 	queue_work(xfs_alloc_wq, &args->work);
 	wait_for_completion(&done);
 	wait_for_completion(&done);

+ 7 - 6
fs/xfs/xfs_bmap_util.h

@@ -50,12 +50,13 @@ struct xfs_bmalloca {
 	xfs_extlen_t		total;	/* total blocks needed for xaction */
 	xfs_extlen_t		total;	/* total blocks needed for xaction */
 	xfs_extlen_t		minlen;	/* minimum allocation size (blocks) */
 	xfs_extlen_t		minlen;	/* minimum allocation size (blocks) */
 	xfs_extlen_t		minleft; /* amount must be left after alloc */
 	xfs_extlen_t		minleft; /* amount must be left after alloc */
-	char			eof;	/* set if allocating past last extent */
-	char			wasdel;	/* replacing a delayed allocation */
-	char			userdata;/* set if is user data */
-	char			aeof;	/* allocated space at eof */
-	char			conv;	/* overwriting unwritten extents */
-	char			stack_switch;
+	bool			eof;	/* set if allocating past last extent */
+	bool			wasdel;	/* replacing a delayed allocation */
+	bool			userdata;/* set if is user data */
+	bool			aeof;	/* allocated space at eof */
+	bool			conv;	/* overwriting unwritten extents */
+	bool			stack_switch;
+	bool			kswapd;	/* allocation in kswapd context */
 	int			flags;
 	int			flags;
 	struct completion	*done;
 	struct completion	*done;
 	struct work_struct	work;
 	struct work_struct	work;

+ 2 - 10
fs/xfs/xfs_btree.c

@@ -553,14 +553,11 @@ xfs_btree_get_bufl(
 	xfs_fsblock_t	fsbno,		/* file system block number */
 	xfs_fsblock_t	fsbno,		/* file system block number */
 	uint		lock)		/* lock flags for get_buf */
 	uint		lock)		/* lock flags for get_buf */
 {
 {
-	xfs_buf_t	*bp;		/* buffer pointer (return value) */
 	xfs_daddr_t		d;		/* real disk block address */
 	xfs_daddr_t		d;		/* real disk block address */
 
 
 	ASSERT(fsbno != NULLFSBLOCK);
 	ASSERT(fsbno != NULLFSBLOCK);
 	d = XFS_FSB_TO_DADDR(mp, fsbno);
 	d = XFS_FSB_TO_DADDR(mp, fsbno);
-	bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock);
-	ASSERT(!xfs_buf_geterror(bp));
-	return bp;
+	return xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock);
 }
 }
 
 
 /*
 /*
@@ -575,15 +572,12 @@ xfs_btree_get_bufs(
 	xfs_agblock_t	agbno,		/* allocation group block number */
 	xfs_agblock_t	agbno,		/* allocation group block number */
 	uint		lock)		/* lock flags for get_buf */
 	uint		lock)		/* lock flags for get_buf */
 {
 {
-	xfs_buf_t	*bp;		/* buffer pointer (return value) */
 	xfs_daddr_t		d;		/* real disk block address */
 	xfs_daddr_t		d;		/* real disk block address */
 
 
 	ASSERT(agno != NULLAGNUMBER);
 	ASSERT(agno != NULLAGNUMBER);
 	ASSERT(agbno != NULLAGBLOCK);
 	ASSERT(agbno != NULLAGBLOCK);
 	d = XFS_AGB_TO_DADDR(mp, agno, agbno);
 	d = XFS_AGB_TO_DADDR(mp, agno, agbno);
-	bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock);
-	ASSERT(!xfs_buf_geterror(bp));
-	return bp;
+	return xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock);
 }
 }
 
 
 /*
 /*
@@ -723,7 +717,6 @@ xfs_btree_read_bufl(
 				   mp->m_bsize, lock, &bp, ops);
 				   mp->m_bsize, lock, &bp, ops);
 	if (error)
 	if (error)
 		return error;
 		return error;
-	ASSERT(!xfs_buf_geterror(bp));
 	if (bp)
 	if (bp)
 		xfs_buf_set_ref(bp, refval);
 		xfs_buf_set_ref(bp, refval);
 	*bpp = bp;
 	*bpp = bp;
@@ -1179,7 +1172,6 @@ xfs_btree_read_buf_block(
 	if (error)
 	if (error)
 		return error;
 		return error;
 
 
-	ASSERT(!xfs_buf_geterror(*bpp));
 	xfs_btree_set_refs(cur, *bpp);
 	xfs_btree_set_refs(cur, *bpp);
 	*block = XFS_BUF_TO_BLOCK(*bpp);
 	*block = XFS_BUF_TO_BLOCK(*bpp);
 	return 0;
 	return 0;

+ 0 - 5
fs/xfs/xfs_buf.h

@@ -298,11 +298,6 @@ extern void xfs_buf_iomove(xfs_buf_t *, size_t, size_t, void *,
 
 
 extern int xfs_bioerror_relse(struct xfs_buf *);
 extern int xfs_bioerror_relse(struct xfs_buf *);
 
 
-static inline int xfs_buf_geterror(xfs_buf_t *bp)
-{
-	return bp ? bp->b_error : ENOMEM;
-}
-
 /* Buffer Utility Routines */
 /* Buffer Utility Routines */
 extern xfs_caddr_t xfs_buf_offset(xfs_buf_t *, size_t);
 extern xfs_caddr_t xfs_buf_offset(xfs_buf_t *, size_t);
 
 

+ 1 - 1
fs/xfs/xfs_buf_item.c

@@ -1052,7 +1052,7 @@ xfs_buf_iodone_callbacks(
 	static ulong		lasttime;
 	static ulong		lasttime;
 	static xfs_buftarg_t	*lasttarg;
 	static xfs_buftarg_t	*lasttarg;
 
 
-	if (likely(!xfs_buf_geterror(bp)))
+	if (likely(!bp->b_error))
 		goto do_callbacks;
 		goto do_callbacks;
 
 
 	/*
 	/*

+ 3 - 3
fs/xfs/xfs_dquot.c

@@ -353,10 +353,10 @@ xfs_qm_dqalloc(
 			       dqp->q_blkno,
 			       dqp->q_blkno,
 			       mp->m_quotainfo->qi_dqchunklen,
 			       mp->m_quotainfo->qi_dqchunklen,
 			       0);
 			       0);
-
-	error = xfs_buf_geterror(bp);
-	if (error)
+	if (!bp) {
+		error = ENOMEM;
 		goto error1;
 		goto error1;
+	}
 	bp->b_ops = &xfs_dquot_buf_ops;
 	bp->b_ops = &xfs_dquot_buf_ops;
 
 
 	/*
 	/*

+ 0 - 1
fs/xfs/xfs_ialloc.c

@@ -2129,7 +2129,6 @@ xfs_read_agi(
 	if (error)
 	if (error)
 		return error;
 		return error;
 
 
-	ASSERT(!xfs_buf_geterror(*bpp));
 	xfs_buf_set_ref(*bpp, XFS_AGI_REF);
 	xfs_buf_set_ref(*bpp, XFS_AGI_REF);
 	return 0;
 	return 0;
 }
 }

+ 1 - 1
fs/xfs/xfs_log.c

@@ -1165,7 +1165,7 @@ xlog_iodone(xfs_buf_t *bp)
 	/*
 	/*
 	 * Race to shutdown the filesystem if we see an error.
 	 * Race to shutdown the filesystem if we see an error.
 	 */
 	 */
-	if (XFS_TEST_ERROR((xfs_buf_geterror(bp)), l->l_mp,
+	if (XFS_TEST_ERROR(bp->b_error, l->l_mp,
 			XFS_ERRTAG_IODONE_IOERR, XFS_RANDOM_IODONE_IOERR)) {
 			XFS_ERRTAG_IODONE_IOERR, XFS_RANDOM_IODONE_IOERR)) {
 		xfs_buf_ioerror_alert(bp, __func__);
 		xfs_buf_ioerror_alert(bp, __func__);
 		xfs_buf_stale(bp);
 		xfs_buf_stale(bp);

+ 17 - 6
fs/xfs/xfs_mount.c

@@ -323,8 +323,19 @@ reread:
 	/*
 	/*
 	 * Initialize the mount structure from the superblock.
 	 * Initialize the mount structure from the superblock.
 	 */
 	 */
-	xfs_sb_from_disk(&mp->m_sb, XFS_BUF_TO_SBP(bp));
-	xfs_sb_quota_from_disk(&mp->m_sb);
+	xfs_sb_from_disk(sbp, XFS_BUF_TO_SBP(bp));
+	xfs_sb_quota_from_disk(sbp);
+
+	/*
+	 * If we haven't validated the superblock, do so now before we try
+	 * to check the sector size and reread the superblock appropriately.
+	 */
+	if (sbp->sb_magicnum != XFS_SB_MAGIC) {
+		if (loud)
+			xfs_warn(mp, "Invalid superblock magic number");
+		error = EINVAL;
+		goto release_buf;
+	}
 
 
 	/*
 	/*
 	 * We must be able to do sector-sized and sector-aligned IO.
 	 * We must be able to do sector-sized and sector-aligned IO.
@@ -337,11 +348,11 @@ reread:
 		goto release_buf;
 		goto release_buf;
 	}
 	}
 
 
-	/*
-	 * Re-read the superblock so the buffer is correctly sized,
-	 * and properly verified.
-	 */
 	if (buf_ops == NULL) {
 	if (buf_ops == NULL) {
+		/*
+		 * Re-read the superblock so the buffer is correctly sized,
+		 * and properly verified.
+		 */
 		xfs_buf_relse(bp);
 		xfs_buf_relse(bp);
 		sector_size = sbp->sb_sectsize;
 		sector_size = sbp->sb_sectsize;
 		buf_ops = loud ? &xfs_sb_buf_ops : &xfs_sb_quiet_buf_ops;
 		buf_ops = loud ? &xfs_sb_buf_ops : &xfs_sb_quiet_buf_ops;

+ 0 - 1
fs/xfs/xfs_rtbitmap.c

@@ -74,7 +74,6 @@ xfs_rtbuf_get(
 				   mp->m_bsize, 0, &bp, NULL);
 				   mp->m_bsize, 0, &bp, NULL);
 	if (error)
 	if (error)
 		return error;
 		return error;
-	ASSERT(!xfs_buf_geterror(bp));
 	*bpp = bp;
 	*bpp = bp;
 	return 0;
 	return 0;
 }
 }