Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 736a4c11 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'for-linus-v3.9-rc1' of git://oss.sgi.com/xfs/xfs

Pull xfs update from Ben Myers:
 "Primarily bugfixes and a few cleanups:

   - fix(es) for compound buffers

   - remove unused XFS_TRANS_DEBUG routines

   - fix for dquot soft timer asserts due to overflow of d_blk_softlimit

   - don't zero allocation args structure members after they are memset(0)

   - fix for regression in dir v2 code introduced in commit 20f7e9f3

   - remove obsolete simple_strto<foo>

   - fix return value when filesystem probe finds no XFS magic, a
     regression introduced in 98021821.

   - remove boolean_t typedef completely

   - fix stack switch in __xfs_bmapi_allocate by moving the check for
     stack switch up into xfs_bmapi_write.

   - fix build error due to incomplete boolean_t removal

   - fix oops in _xfs_buf_find by validating that the requested block is
     within the filesystem bounds.

   - limit speculative preallocation near ENOSPC.

   - fix an unmount hang in xfs_wait_buftarg by freeing the
     xfs_buf_log_item in xfs_buf_item_unlock.

   - fix a possible use after free with AIO.

   - fix xfs_swap_extents after removal of xfs_flushinval_pages, a
     regression introduced in fb595814.

   - replace hardcoded 128 with log header size

   - add memory barrier before wake_up_bit in xfs_ifunlock

   - limit speculative preallocation on sparse files

   - fix xa_lock recursion bug introduced in 90810b9e

   - fix write verifier for symlinks"

Fixed up conflicts in fs/xfs/xfs_buf_item.c (due to bli_format rename in
commit 0f22f9d0 affecting the removed XFS_TRANS_DEBUG routines in
commit ec47eb6b).

* tag 'for-linus-v3.9-rc1' of git://oss.sgi.com/xfs/xfs: (36 commits)
  xfs: xfs_bmap_add_attrfork_local is too generic
  xfs: remove log force from xfs_buf_trylock()
  xfs: recheck buffer pinned status after push trylock failure
  xfs: limit speculative prealloc size on sparse files
  xfs: memory barrier before wake_up_bit()
  xfs: refactor space log reservation for XFS_TRANS_ATTR_SET
  xfs: make use of XFS_SB_LOG_RES() at xfs_fs_log_dummy()
  xfs: make use of XFS_SB_LOG_RES() at xfs_mount_log_sb()
  xfs: make use of XFS_SB_LOG_RES() at xfs_log_sbcount()
  xfs: introduce XFS_SB_LOG_RES() for transactions that modify sb on disk
  xfs: calculate XFS_TRANS_QM_QUOTAOFF_END space log reservation at mount time
  xfs: calculate XFS_TRANS_QM_QUOTAOFF space log reservation at mount time
  xfs: calculate XFS_TRANS_QM_DQALLOC space log reservation at mount time
  xfs: calcuate XFS_TRANS_QM_SETQLIM space log reservation at mount time
  xfs: calculate xfs_qm_write_sb_changes() space log reservation at mount time
  xfs: calculate XFS_TRANS_QM_SBCHANGE space log reservation at mount time
  xfs: make use of xfs_calc_buf_res() in xfs_trans.c
  xfs: add a helper to figure out the space log reservation per item
  xfs: Fix xfs_swap_extents() after removal of xfs_flushinval_pages()
  xfs: Fix possible use-after-free with AIO
  ...
parents c4bc705e 1e82379b
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -1925,8 +1925,6 @@ xfs_alloc_fix_freelist(
	targs.mp = mp;
	targs.agbp = agbp;
	targs.agno = args->agno;
	targs.mod = targs.minleft = targs.wasdel = targs.userdata =
		targs.minalignslop = 0;
	targs.alignment = targs.minlen = targs.prod = targs.isfl = 1;
	targs.type = XFS_ALLOCTYPE_THIS_AG;
	targs.pag = pag;
+6 −3
Original line number Diff line number Diff line
@@ -300,9 +300,12 @@ xfs_attr_set_int(
	if (rsvd)
		args.trans->t_flags |= XFS_TRANS_RESERVE;

	if ((error = xfs_trans_reserve(args.trans, args.total,
			XFS_ATTRSET_LOG_RES(mp, args.total), 0,
			XFS_TRANS_PERM_LOG_RES, XFS_ATTRSET_LOG_COUNT))) {
	error = xfs_trans_reserve(args.trans, args.total,
				  XFS_ATTRSETM_LOG_RES(mp) +
				  XFS_ATTRSETRT_LOG_RES(mp) * args.total,
				  0, XFS_TRANS_PERM_LOG_RES,
				  XFS_ATTRSET_LOG_COUNT);
	if (error) {
		xfs_trans_cancel(args.trans, 0);
		return(error);
	}
+93 −25
Original line number Diff line number Diff line
@@ -147,7 +147,10 @@ xfs_bmap_local_to_extents(
	xfs_fsblock_t	*firstblock,	/* first block allocated in xaction */
	xfs_extlen_t	total,		/* total blocks needed by transaction */
	int		*logflagsp,	/* inode logging flags */
	int		whichfork);	/* data or attr fork */
	int		whichfork,	/* data or attr fork */
	void		(*init_fn)(struct xfs_buf *bp,
				   struct xfs_inode *ip,
				   struct xfs_ifork *ifp));

/*
 * Search the extents list for the inode, for the extent containing bno.
@@ -357,7 +360,42 @@ xfs_bmap_add_attrfork_extents(
}

/*
 * Called from xfs_bmap_add_attrfork to handle local format files.
 * Block initialisation functions for local to extent format conversion.
 * As these get more complex, they will be moved to the relevant files,
 * but for now they are too simple to worry about.
 */
STATIC void
xfs_bmap_local_to_extents_init_fn(
	struct xfs_buf		*bp,
	struct xfs_inode	*ip,
	struct xfs_ifork	*ifp)
{
	bp->b_ops = &xfs_bmbt_buf_ops;
	memcpy(bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes);
}

STATIC void
xfs_symlink_local_to_remote(
	struct xfs_buf		*bp,
	struct xfs_inode	*ip,
	struct xfs_ifork	*ifp)
{
	/* remote symlink blocks are not verifiable until CRCs come along */
	bp->b_ops = NULL;
	memcpy(bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes);
}

/*
 * Called from xfs_bmap_add_attrfork to handle local format files. Each
 * different data fork content type needs a different callout to do the
 * conversion. Some are basic and only require special block initialisation
 * callouts for the data formating, others (directories) are so specialised they
 * handle everything themselves.
 *
 * XXX (dgc): investigate whether directory conversion can use the generic
 * formatting callout. It should be possible - it's just a very complex
 * formatter. it would also require passing the transaction through to the init
 * function.
 */
STATIC int					/* error */
xfs_bmap_add_attrfork_local(
@@ -368,25 +406,29 @@ xfs_bmap_add_attrfork_local(
	int			*flags)		/* inode logging flags */
{
	xfs_da_args_t		dargs;		/* args for dir/attr code */
	int			error;		/* error return value */
	xfs_mount_t		*mp;		/* mount structure pointer */

	if (ip->i_df.if_bytes <= XFS_IFORK_DSIZE(ip))
		return 0;

	if (S_ISDIR(ip->i_d.di_mode)) {
		mp = ip->i_mount;
		memset(&dargs, 0, sizeof(dargs));
		dargs.dp = ip;
		dargs.firstblock = firstblock;
		dargs.flist = flist;
		dargs.total = mp->m_dirblkfsbs;
		dargs.total = ip->i_mount->m_dirblkfsbs;
		dargs.whichfork = XFS_DATA_FORK;
		dargs.trans = tp;
		error = xfs_dir2_sf_to_block(&dargs);
	} else
		error = xfs_bmap_local_to_extents(tp, ip, firstblock, 1, flags,
			XFS_DATA_FORK);
	return error;
		return xfs_dir2_sf_to_block(&dargs);
	}

	if (S_ISLNK(ip->i_d.di_mode))
		return xfs_bmap_local_to_extents(tp, ip, firstblock, 1,
						 flags, XFS_DATA_FORK,
						 xfs_symlink_local_to_remote);

	return xfs_bmap_local_to_extents(tp, ip, firstblock, 1, flags,
					 XFS_DATA_FORK,
					 xfs_bmap_local_to_extents_init_fn);
}

/*
@@ -3099,8 +3141,6 @@ xfs_bmap_extents_to_btree(
		args.fsbno = *firstblock;
	}
	args.minlen = args.maxlen = args.prod = 1;
	args.total = args.minleft = args.alignment = args.mod = args.isfl =
		args.minalignslop = 0;
	args.wasdel = wasdel;
	*logflagsp = 0;
	if ((error = xfs_alloc_vextent(&args))) {
@@ -3221,7 +3261,10 @@ xfs_bmap_local_to_extents(
	xfs_fsblock_t	*firstblock,	/* first block allocated in xaction */
	xfs_extlen_t	total,		/* total blocks needed by transaction */
	int		*logflagsp,	/* inode logging flags */
	int		whichfork)	/* data or attr fork */
	int		whichfork,
	void		(*init_fn)(struct xfs_buf *bp,
				   struct xfs_inode *ip,
				   struct xfs_ifork *ifp))
{
	int		error;		/* error return value */
	int		flags;		/* logging flags returned */
@@ -3241,12 +3284,12 @@ xfs_bmap_local_to_extents(
		xfs_buf_t	*bp;	/* buffer for extent block */
		xfs_bmbt_rec_host_t *ep;/* extent record pointer */

		ASSERT((ifp->if_flags &
			(XFS_IFINLINE|XFS_IFEXTENTS|XFS_IFEXTIREC)) == XFS_IFINLINE);
		memset(&args, 0, sizeof(args));
		args.tp = tp;
		args.mp = ip->i_mount;
		args.firstblock = *firstblock;
		ASSERT((ifp->if_flags &
			(XFS_IFINLINE|XFS_IFEXTENTS|XFS_IFEXTIREC)) == XFS_IFINLINE);
		/*
		 * Allocate a block.  We know we need only one, since the
		 * file currently fits in an inode.
@@ -3259,20 +3302,21 @@ xfs_bmap_local_to_extents(
			args.type = XFS_ALLOCTYPE_NEAR_BNO;
		}
		args.total = total;
		args.mod = args.minleft = args.alignment = args.wasdel =
			args.isfl = args.minalignslop = 0;
		args.minlen = args.maxlen = args.prod = 1;
		if ((error = xfs_alloc_vextent(&args)))
		error = xfs_alloc_vextent(&args);
		if (error)
			goto done;
		/*
		 * Can't fail, the space was reserved.
		 */

		/* Can't fail, the space was reserved. */
		ASSERT(args.fsbno != NULLFSBLOCK);
		ASSERT(args.len == 1);
		*firstblock = args.fsbno;
		bp = xfs_btree_get_bufl(args.mp, tp, args.fsbno, 0);
		bp->b_ops = &xfs_bmbt_buf_ops;
		memcpy(bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes);

		/* initialise the block and copy the data */
		init_fn(bp, ip, ifp);

		/* account for the change in fork size and log everything */
		xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1);
		xfs_bmap_forkoff_reset(args.mp, ip, whichfork);
		xfs_idata_realloc(ip, -ifp->if_bytes, whichfork);
@@ -4919,8 +4963,32 @@ xfs_bmapi_write(
	XFS_STATS_INC(xs_blk_mapw);

	if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
		/*
		 * XXX (dgc): This assumes we are only called for inodes that
		 * contain content neutral data in local format. Anything that
		 * contains caller-specific data in local format that needs
		 * transformation to move to a block format needs to do the
		 * conversion to extent format itself.
		 *
		 * Directory data forks and attribute forks handle this
		 * themselves, but with the addition of metadata verifiers every
		 * data fork in local format now contains caller specific data
		 * and as such conversion through this function is likely to be
		 * broken.
		 *
		 * The only likely user of this branch is for remote symlinks,
		 * but we cannot overwrite the data fork contents of the symlink
		 * (EEXIST occurs higher up the stack) and so it will never go
		 * from local format to extent format here. Hence I don't think
		 * this branch is ever executed intentionally and we should
		 * consider removing it and asserting that xfs_bmapi_write()
		 * cannot be called directly on local format forks. i.e. callers
		 * are completely responsible for local to extent format
		 * conversion, not xfs_bmapi_write().
		 */
		error = xfs_bmap_local_to_extents(tp, ip, firstblock, total,
						  &bma.logflags, whichfork);
					&bma.logflags, whichfork,
					xfs_bmap_local_to_extents_init_fn);
		if (error)
			goto error0;
	}
+0 −2
Original line number Diff line number Diff line
@@ -951,8 +951,6 @@ xfs_buf_trylock(
	locked = down_trylock(&bp->b_sema) == 0;
	if (locked)
		XB_SET_OWNER(bp);
	else if (atomic_read(&bp->b_pin_count) && (bp->b_flags & XBF_STALE))
		xfs_log_force(bp->b_target->bt_mount, 0);

	trace_xfs_buf_trylock(bp, _RET_IP_);
	return locked;
+11 −107
Original line number Diff line number Diff line
@@ -37,109 +37,6 @@ static inline struct xfs_buf_log_item *BUF_ITEM(struct xfs_log_item *lip)
	return container_of(lip, struct xfs_buf_log_item, bli_item);
}


#ifdef XFS_TRANS_DEBUG
/*
 * This function uses an alternate strategy for tracking the bytes
 * that the user requests to be logged.  This can then be used
 * in conjunction with the bli_orig array in the buf log item to
 * catch bugs in our callers' code.
 *
 * We also double check the bits set in xfs_buf_item_log using a
 * simple algorithm to check that every byte is accounted for.
 */
STATIC void
xfs_buf_item_log_debug(
	xfs_buf_log_item_t	*bip,
	uint			first,
	uint			last)
{
	uint	x;
	uint	byte;
	uint	nbytes;
	uint	chunk_num;
	uint	word_num;
	uint	bit_num;
	uint	bit_set;
	uint	*wordp;

	ASSERT(bip->bli_logged != NULL);
	byte = first;
	nbytes = last - first + 1;
	bfset(bip->bli_logged, first, nbytes);
	for (x = 0; x < nbytes; x++) {
		chunk_num = byte >> XFS_BLF_SHIFT;
		word_num = chunk_num >> BIT_TO_WORD_SHIFT;
		bit_num = chunk_num & (NBWORD - 1);
		wordp = &(bip->__bli_format.blf_data_map[word_num]);
		bit_set = *wordp & (1 << bit_num);
		ASSERT(bit_set);
		byte++;
	}
}

/*
 * This function is called when we flush something into a buffer without
 * logging it.  This happens for things like inodes which are logged
 * separately from the buffer.
 */
void
xfs_buf_item_flush_log_debug(
	xfs_buf_t	*bp,
	uint		first,
	uint		last)
{
	xfs_buf_log_item_t	*bip = bp->b_fspriv;
	uint			nbytes;

	if (bip == NULL || (bip->bli_item.li_type != XFS_LI_BUF))
		return;

	ASSERT(bip->bli_logged != NULL);
	nbytes = last - first + 1;
	bfset(bip->bli_logged, first, nbytes);
}

/*
 * This function is called to verify that our callers have logged
 * all the bytes that they changed.
 *
 * It does this by comparing the original copy of the buffer stored in
 * the buf log item's bli_orig array to the current copy of the buffer
 * and ensuring that all bytes which mismatch are set in the bli_logged
 * array of the buf log item.
 */
STATIC void
xfs_buf_item_log_check(
	xfs_buf_log_item_t	*bip)
{
	char		*orig;
	char		*buffer;
	int		x;
	xfs_buf_t	*bp;

	ASSERT(bip->bli_orig != NULL);
	ASSERT(bip->bli_logged != NULL);

	bp = bip->bli_buf;
	ASSERT(bp->b_length > 0);
	ASSERT(bp->b_addr != NULL);
	orig = bip->bli_orig;
	buffer = bp->b_addr;
	for (x = 0; x < BBTOB(bp->b_length); x++) {
		if (orig[x] != buffer[x] && !btst(bip->bli_logged, x)) {
			xfs_emerg(bp->b_mount,
				"%s: bip %x buffer %x orig %x index %d",
				__func__, bip, bp, orig, x);
			ASSERT(0);
		}
	}
}
#else
#define		xfs_buf_item_log_debug(x,y,z)
#define		xfs_buf_item_log_check(x)
#endif

STATIC void	xfs_buf_do_callbacks(struct xfs_buf *bp);

/*
@@ -429,7 +326,6 @@ xfs_buf_item_format(
	 * Check to make sure everything is consistent.
	 */
	trace_xfs_buf_item_format(bip);
	xfs_buf_item_log_check(bip);
}

/*
@@ -573,8 +469,18 @@ xfs_buf_item_push(

	if (xfs_buf_ispinned(bp))
		return XFS_ITEM_PINNED;
	if (!xfs_buf_trylock(bp))
	if (!xfs_buf_trylock(bp)) {
		/*
		 * If we have just raced with a buffer being pinned and it has
		 * been marked stale, we could end up stalling until someone else
		 * issues a log force to unpin the stale buffer. Check for the
		 * race condition here so xfsaild recognizes the buffer is pinned
		 * and queues a log force to move it along.
		 */
		if (xfs_buf_ispinned(bp))
			return XFS_ITEM_PINNED;
		return XFS_ITEM_LOCKED;
	}

	ASSERT(!(bip->bli_flags & XFS_BLI_STALE));

@@ -923,8 +829,6 @@ xfs_buf_item_log_segment(
		mask = (1 << end_bit) - 1;
		*wordp |= mask;
	}

	xfs_buf_item_log_debug(bip, first, last);
}

/*
Loading