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

Commit a601e637 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

Pull xfs bugfixes from Ben Myers:

 - fix for large transactions spanning multiple iclog buffers

 - zero the allocation_args structure on the stack before using it to
   determine whether to use a worker for allocation
 - move allocation stack switch to xfs_bmapi_allocate in order to
   prevent deadlock on AGF buffers

 - growfs no longer reads in garbage for new secondary superblocks

 - silence a build warning

 - ensure that invalid buffers never get written to disk while on free
   list

 - don't vmap inode cluster buffers during free

 - fix buffer shutdown reference count mismatch

 - fix reading of wrapped log data

* tag 'for-linus-v3.7-rc5' of git://oss.sgi.com/xfs/xfs:
  xfs: fix reading of wrapped log data
  xfs: fix buffer shudown reference count mismatch
  xfs: don't vmap inode cluster buffers during free
  xfs: invalidate allocbt blocks moved to the free list
  xfs: silence uninitialised f.file warning.
  xfs: growfs: don't read garbage for new secondary superblocks
  xfs: move allocation stack switch up to xfs_bmapi_allocate
  xfs: introduce XFS_BMAPI_STACK_SWITCH
  xfs: zero allocation_args on the kernel stack
  xfs: only update the last_sync_lsn when a transaction completes
parents 0e4a43ed 6ce377af
Loading
Loading
Loading
Loading
+2 −41
Original line number Diff line number Diff line
@@ -1866,6 +1866,7 @@ xfs_alloc_fix_freelist(
	/*
	 * Initialize the args structure.
	 */
	memset(&targs, 0, sizeof(targs));
	targs.tp = tp;
	targs.mp = mp;
	targs.agbp = agbp;
@@ -2207,7 +2208,7 @@ xfs_alloc_read_agf(
 * group or loop over the allocation groups to find the result.
 */
int				/* error */
__xfs_alloc_vextent(
xfs_alloc_vextent(
	xfs_alloc_arg_t	*args)	/* allocation argument structure */
{
	xfs_agblock_t	agsize;	/* allocation group size */
@@ -2417,46 +2418,6 @@ __xfs_alloc_vextent(
	return error;
}

static void
xfs_alloc_vextent_worker(
	struct work_struct	*work)
{
	struct xfs_alloc_arg	*args = container_of(work,
						struct xfs_alloc_arg, work);
	unsigned long		pflags;

	/* we are in a transaction context here */
	current_set_flags_nested(&pflags, PF_FSTRANS);

	args->result = __xfs_alloc_vextent(args);
	complete(args->done);

	current_restore_flags_nested(&pflags, PF_FSTRANS);
}

/*
 * Data allocation requests often come in with little stack to work on. Push
 * them off to a worker thread so there is lots of stack to use. Metadata
 * requests, OTOH, are generally from low stack usage paths, so avoid the
 * context switch overhead here.
 */
int
xfs_alloc_vextent(
	struct xfs_alloc_arg	*args)
{
	DECLARE_COMPLETION_ONSTACK(done);

	if (!args->userdata)
		return __xfs_alloc_vextent(args);


	args->done = &done;
	INIT_WORK_ONSTACK(&args->work, xfs_alloc_vextent_worker);
	queue_work(xfs_alloc_wq, &args->work);
	wait_for_completion(&done);
	return args->result;
}

/*
 * Free an extent.
 * Just break up the extent address and hand off to xfs_free_ag_extent
+0 −3
Original line number Diff line number Diff line
@@ -120,9 +120,6 @@ typedef struct xfs_alloc_arg {
	char		isfl;		/* set if is freelist blocks - !acctg */
	char		userdata;	/* set if this is user data */
	xfs_fsblock_t	firstblock;	/* io first block allocated */
	struct completion *done;
	struct work_struct work;
	int		result;
} xfs_alloc_arg_t;

/*
+2 −0
Original line number Diff line number Diff line
@@ -121,6 +121,8 @@ xfs_allocbt_free_block(
	xfs_extent_busy_insert(cur->bc_tp, be32_to_cpu(agf->agf_seqno), bno, 1,
			      XFS_EXTENT_BUSY_SKIP_DISCARD);
	xfs_trans_agbtree_delta(cur->bc_tp, -1);

	xfs_trans_binval(cur->bc_tp, bp);
	return 0;
}

+54 −9
Original line number Diff line number Diff line
@@ -2437,6 +2437,7 @@ xfs_bmap_btalloc(
	 * Normal allocation, done through xfs_alloc_vextent.
	 */
	tryagain = isaligned = 0;
	memset(&args, 0, sizeof(args));
	args.tp = ap->tp;
	args.mp = mp;
	args.fsbno = ap->blkno;
@@ -3082,6 +3083,7 @@ xfs_bmap_extents_to_btree(
	 * Convert to a btree with two levels, one record in root.
	 */
	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_BTREE);
	memset(&args, 0, sizeof(args));
	args.tp = tp;
	args.mp = mp;
	args.firstblock = *firstblock;
@@ -3237,6 +3239,7 @@ xfs_bmap_local_to_extents(
		xfs_buf_t	*bp;	/* buffer for extent block */
		xfs_bmbt_rec_host_t *ep;/* extent record pointer */

		memset(&args, 0, sizeof(args));
		args.tp = tp;
		args.mp = ip->i_mount;
		args.firstblock = *firstblock;
@@ -4616,12 +4619,11 @@ xfs_bmapi_delay(


STATIC int
xfs_bmapi_allocate(
	struct xfs_bmalloca	*bma,
	int			flags)
__xfs_bmapi_allocate(
	struct xfs_bmalloca	*bma)
{
	struct xfs_mount	*mp = bma->ip->i_mount;
	int			whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
	int			whichfork = (bma->flags & XFS_BMAPI_ATTRFORK) ?
						XFS_ATTR_FORK : XFS_DATA_FORK;
	struct xfs_ifork	*ifp = XFS_IFORK_PTR(bma->ip, whichfork);
	int			tmp_logflags = 0;
@@ -4654,24 +4656,27 @@ xfs_bmapi_allocate(
	 * Indicate if this is the first user data in the file, or just any
	 * user data.
	 */
	if (!(flags & XFS_BMAPI_METADATA)) {
	if (!(bma->flags & XFS_BMAPI_METADATA)) {
		bma->userdata = (bma->offset == 0) ?
			XFS_ALLOC_INITIAL_USER_DATA : XFS_ALLOC_USERDATA;
	}

	bma->minlen = (flags & XFS_BMAPI_CONTIG) ? bma->length : 1;
	bma->minlen = (bma->flags & XFS_BMAPI_CONTIG) ? bma->length : 1;

	/*
	 * Only want to do the alignment at the eof if it is userdata and
	 * allocation length is larger than a stripe unit.
	 */
	if (mp->m_dalign && bma->length >= mp->m_dalign &&
	    !(flags & XFS_BMAPI_METADATA) && whichfork == XFS_DATA_FORK) {
	    !(bma->flags & XFS_BMAPI_METADATA) && whichfork == XFS_DATA_FORK) {
		error = xfs_bmap_isaeof(bma, whichfork);
		if (error)
			return error;
	}

	if (bma->flags & XFS_BMAPI_STACK_SWITCH)
		bma->stack_switch = 1;

	error = xfs_bmap_alloc(bma);
	if (error)
		return error;
@@ -4706,7 +4711,7 @@ xfs_bmapi_allocate(
	 * A wasdelay extent has been initialized, so shouldn't be flagged
	 * as unwritten.
	 */
	if (!bma->wasdel && (flags & XFS_BMAPI_PREALLOC) &&
	if (!bma->wasdel && (bma->flags & XFS_BMAPI_PREALLOC) &&
	    xfs_sb_version_hasextflgbit(&mp->m_sb))
		bma->got.br_state = XFS_EXT_UNWRITTEN;

@@ -4734,6 +4739,45 @@ xfs_bmapi_allocate(
	return 0;
}

static void
xfs_bmapi_allocate_worker(
	struct work_struct	*work)
{
	struct xfs_bmalloca	*args = container_of(work,
						struct xfs_bmalloca, work);
	unsigned long		pflags;

	/* we are in a transaction context here */
	current_set_flags_nested(&pflags, PF_FSTRANS);

	args->result = __xfs_bmapi_allocate(args);
	complete(args->done);

	current_restore_flags_nested(&pflags, PF_FSTRANS);
}

/*
 * Some allocation requests often come in with little stack to work on. Push
 * them off to a worker thread so there is lots of stack to use. Otherwise just
 * call directly to avoid the context switch overhead here.
 */
int
xfs_bmapi_allocate(
	struct xfs_bmalloca	*args)
{
	DECLARE_COMPLETION_ONSTACK(done);

	if (!args->stack_switch)
		return __xfs_bmapi_allocate(args);


	args->done = &done;
	INIT_WORK_ONSTACK(&args->work, xfs_bmapi_allocate_worker);
	queue_work(xfs_alloc_wq, &args->work);
	wait_for_completion(&done);
	return args->result;
}

STATIC int
xfs_bmapi_convert_unwritten(
	struct xfs_bmalloca	*bma,
@@ -4919,6 +4963,7 @@ xfs_bmapi_write(
			bma.conv = !!(flags & XFS_BMAPI_CONVERT);
			bma.wasdel = wasdelay;
			bma.offset = bno;
			bma.flags = flags;

			/*
			 * There's a 32/64 bit type mismatch between the
@@ -4934,7 +4979,7 @@ xfs_bmapi_write(

			ASSERT(len > 0);
			ASSERT(bma.length > 0);
			error = xfs_bmapi_allocate(&bma, flags);
			error = xfs_bmapi_allocate(&bma);
			if (error)
				goto error0;
			if (bma.blkno == NULLFSBLOCK)
+8 −1
Original line number Diff line number Diff line
@@ -77,6 +77,7 @@ typedef struct xfs_bmap_free
 * from written to unwritten, otherwise convert from unwritten to written.
 */
#define XFS_BMAPI_CONVERT	0x040
#define XFS_BMAPI_STACK_SWITCH	0x080

#define XFS_BMAPI_FLAGS \
	{ XFS_BMAPI_ENTIRE,	"ENTIRE" }, \
@@ -85,7 +86,8 @@ typedef struct xfs_bmap_free
	{ XFS_BMAPI_PREALLOC,	"PREALLOC" }, \
	{ XFS_BMAPI_IGSTATE,	"IGSTATE" }, \
	{ XFS_BMAPI_CONTIG,	"CONTIG" }, \
	{ XFS_BMAPI_CONVERT,	"CONVERT" }
	{ XFS_BMAPI_CONVERT,	"CONVERT" }, \
	{ XFS_BMAPI_STACK_SWITCH, "STACK_SWITCH" }


static inline int xfs_bmapi_aflag(int w)
@@ -133,6 +135,11 @@ typedef struct xfs_bmalloca {
	char			userdata;/* set if is user data */
	char			aeof;	/* allocated space at eof */
	char			conv;	/* overwriting unwritten extents */
	char			stack_switch;
	int			flags;
	struct completion	*done;
	struct work_struct	work;
	int			result;
} xfs_bmalloca_t;

/*
Loading