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

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

Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs

* 'for-linus' of git://oss.sgi.com/xfs/xfs:
  xfs: xfs_bmap_add_extent_delay_real should init br_startblock
  xfs: fix dquot shaker deadlock
  xfs: handle CIl transaction commit failures correctly
  xfs: limit extsize to size of AGs and/or MAXEXTLEN
  xfs: prevent extsize alignment from exceeding maximum extent size
  xfs: limit extent length for allocation to AG size
  xfs: speculative delayed allocation uses rounddown_power_of_2 badly
  xfs: fix efi item leak on forced shutdown
  xfs: fix log ticket leak on forced shutdown.
parents 2426ec8f 24446fc6
Loading
Loading
Loading
Loading
+18 −2
Original line number Diff line number Diff line
@@ -985,10 +985,22 @@ xfs_ioctl_setattr(

		/*
		 * Extent size must be a multiple of the appropriate block
		 * size, if set at all.
		 * size, if set at all. It must also be smaller than the
		 * maximum extent size supported by the filesystem.
		 *
		 * Also, for non-realtime files, limit the extent size hint to
		 * half the size of the AGs in the filesystem so alignment
		 * doesn't result in extents larger than an AG.
		 */
		if (fa->fsx_extsize != 0) {
			xfs_extlen_t    size;
			xfs_fsblock_t   extsize_fsb;

			extsize_fsb = XFS_B_TO_FSB(mp, fa->fsx_extsize);
			if (extsize_fsb > MAXEXTLEN) {
				code = XFS_ERROR(EINVAL);
				goto error_return;
			}

			if (XFS_IS_REALTIME_INODE(ip) ||
			    ((mask & FSX_XFLAGS) &&
@@ -997,6 +1009,10 @@ xfs_ioctl_setattr(
				       mp->m_sb.sb_blocklog;
			} else {
				size = mp->m_sb.sb_blocksize;
				if (extsize_fsb > mp->m_sb.sb_agblocks / 2) {
					code = XFS_ERROR(EINVAL);
					goto error_return;
				}
			}

			if (fa->fsx_extsize % size) {
+21 −25
Original line number Diff line number Diff line
@@ -1863,12 +1863,14 @@ xfs_qm_dqreclaim_one(void)
	xfs_dquot_t	*dqpout;
	xfs_dquot_t	*dqp;
	int		restarts;
	int		startagain;

	restarts = 0;
	dqpout = NULL;

	/* lockorder: hashchainlock, freelistlock, mplistlock, dqlock, dqflock */
startagain:
again:
	startagain = 0;
	mutex_lock(&xfs_Gqm->qm_dqfrlist_lock);

	list_for_each_entry(dqp, &xfs_Gqm->qm_dqfrlist, q_freelist) {
@@ -1885,13 +1887,10 @@ xfs_qm_dqreclaim_one(void)
			ASSERT(! (dqp->dq_flags & XFS_DQ_INACTIVE));

			trace_xfs_dqreclaim_want(dqp);

			xfs_dqunlock(dqp);
			mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
			if (++restarts >= XFS_QM_RECLAIM_MAX_RESTARTS)
				return NULL;
			XQM_STATS_INC(xqmstats.xs_qm_dqwants);
			goto startagain;
			restarts++;
			startagain = 1;
			goto dqunlock;
		}

		/*
@@ -1906,23 +1905,20 @@ xfs_qm_dqreclaim_one(void)
			ASSERT(list_empty(&dqp->q_mplist));
			list_del_init(&dqp->q_freelist);
			xfs_Gqm->qm_dqfrlist_cnt--;
			xfs_dqunlock(dqp);
			dqpout = dqp;
			XQM_STATS_INC(xqmstats.xs_qm_dqinact_reclaims);
			break;
			goto dqunlock;
		}

		ASSERT(dqp->q_hash);
		ASSERT(!list_empty(&dqp->q_mplist));

		/*
		 * Try to grab the flush lock. If this dquot is in the process of
		 * getting flushed to disk, we don't want to reclaim it.
		 * Try to grab the flush lock. If this dquot is in the process
		 * of getting flushed to disk, we don't want to reclaim it.
		 */
		if (!xfs_dqflock_nowait(dqp)) {
			xfs_dqunlock(dqp);
			continue;
		}
		if (!xfs_dqflock_nowait(dqp))
			goto dqunlock;

		/*
		 * We have the flush lock so we know that this is not in the
@@ -1944,8 +1940,7 @@ xfs_qm_dqreclaim_one(void)
				xfs_fs_cmn_err(CE_WARN, mp,
			"xfs_qm_dqreclaim: dquot %p flush failed", dqp);
			}
			xfs_dqunlock(dqp); /* dqflush unlocks dqflock */
			continue;
			goto dqunlock;
		}

		/*
@@ -1967,13 +1962,8 @@ xfs_qm_dqreclaim_one(void)
		 */
		if (!mutex_trylock(&mp->m_quotainfo->qi_dqlist_lock)) {
			restarts++;
			mutex_unlock(&dqp->q_hash->qh_lock);
			xfs_dqfunlock(dqp);
			xfs_dqunlock(dqp);
			mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
			if (restarts++ >= XFS_QM_RECLAIM_MAX_RESTARTS)
				return NULL;
			goto startagain;
			startagain = 1;
			goto qhunlock;
		}

		ASSERT(dqp->q_nrefs == 0);
@@ -1986,14 +1976,20 @@ xfs_qm_dqreclaim_one(void)
		xfs_Gqm->qm_dqfrlist_cnt--;
		dqpout = dqp;
		mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock);
qhunlock:
		mutex_unlock(&dqp->q_hash->qh_lock);
dqfunlock:
		xfs_dqfunlock(dqp);
dqunlock:
		xfs_dqunlock(dqp);
		if (dqpout)
			break;
		if (restarts >= XFS_QM_RECLAIM_MAX_RESTARTS)
			return NULL;
			break;
		if (startagain) {
			mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
			goto again;
		}
	}
	mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
	return dqpout;
+16 −0
Original line number Diff line number Diff line
@@ -74,6 +74,22 @@ typedef unsigned int xfs_alloctype_t;
 */
#define XFS_ALLOC_SET_ASIDE(mp)  (4 + ((mp)->m_sb.sb_agcount * 4))

/*
 * When deciding how much space to allocate out of an AG, we limit the
 * allocation maximum size to the size the AG. However, we cannot use all the
 * blocks in the AG - some are permanently used by metadata. These
 * blocks are generally:
 *	- the AG superblock, AGF, AGI and AGFL
 *	- the AGF (bno and cnt) and AGI btree root blocks
 *	- 4 blocks on the AGFL according to XFS_ALLOC_SET_ASIDE() limits
 *
 * The AG headers are sector sized, so the amount of space they take up is
 * dependent on filesystem geometry. The others are all single blocks.
 */
#define XFS_ALLOC_AG_MAX_USABLE(mp)	\
	((mp)->m_sb.sb_agblocks - XFS_BB_TO_FSB(mp, XFS_FSS_TO_BB(mp, 4)) - 7)


/*
 * Argument structure for xfs_alloc routines.
 * This is turned into a structure to avoid having 20 arguments passed
+45 −16
Original line number Diff line number Diff line
@@ -1038,17 +1038,34 @@ xfs_bmap_add_extent_delay_real(
		 * Filling in the middle part of a previous delayed allocation.
		 * Contiguity is impossible here.
		 * This case is avoided almost all the time.
		 *
		 * We start with a delayed allocation:
		 *
		 * +ddddddddddddddddddddddddddddddddddddddddddddddddddddddd+
		 *  PREV @ idx
		 *
	         * and we are allocating:
		 *                     +rrrrrrrrrrrrrrrrr+
		 *			      new
		 *
		 * and we set it up for insertion as:
		 * +ddddddddddddddddddd+rrrrrrrrrrrrrrrrr+ddddddddddddddddd+
		 *                            new
		 *  PREV @ idx          LEFT              RIGHT
		 *                      inserted at idx + 1
		 */
		temp = new->br_startoff - PREV.br_startoff;
		trace_xfs_bmap_pre_update(ip, idx, 0, _THIS_IP_);
		xfs_bmbt_set_blockcount(ep, temp);
		r[0] = *new;
		r[1].br_state = PREV.br_state;
		r[1].br_startblock = 0;
		r[1].br_startoff = new_endoff;
		temp2 = PREV.br_startoff + PREV.br_blockcount - new_endoff;
		r[1].br_blockcount = temp2;
		xfs_iext_insert(ip, idx + 1, 2, &r[0], state);
		trace_xfs_bmap_pre_update(ip, idx, 0, _THIS_IP_);
		xfs_bmbt_set_blockcount(ep, temp);	/* truncate PREV */
		LEFT = *new;
		RIGHT.br_state = PREV.br_state;
		RIGHT.br_startblock = nullstartblock(
				(int)xfs_bmap_worst_indlen(ip, temp2));
		RIGHT.br_startoff = new_endoff;
		RIGHT.br_blockcount = temp2;
		/* insert LEFT (r[0]) and RIGHT (r[1]) at the same time */
		xfs_iext_insert(ip, idx + 1, 2, &LEFT, state);
		ip->i_df.if_lastex = idx + 1;
		ip->i_d.di_nextents++;
		if (cur == NULL)
@@ -2430,7 +2447,7 @@ xfs_bmap_btalloc_nullfb(
		startag = ag = 0;

	pag = xfs_perag_get(mp, ag);
	while (*blen < ap->alen) {
	while (*blen < args->maxlen) {
		if (!pag->pagf_init) {
			error = xfs_alloc_pagf_init(mp, args->tp, ag,
						    XFS_ALLOC_FLAG_TRYLOCK);
@@ -2452,7 +2469,7 @@ xfs_bmap_btalloc_nullfb(
			notinit = 1;

		if (xfs_inode_is_filestream(ap->ip)) {
			if (*blen >= ap->alen)
			if (*blen >= args->maxlen)
				break;

			if (ap->userdata) {
@@ -2498,14 +2515,14 @@ xfs_bmap_btalloc_nullfb(
	 * If the best seen length is less than the request
	 * length, use the best as the minimum.
	 */
	else if (*blen < ap->alen)
	else if (*blen < args->maxlen)
		args->minlen = *blen;
	/*
	 * Otherwise we've seen an extent as big as alen,
	 * Otherwise we've seen an extent as big as maxlen,
	 * use that as the minimum.
	 */
	else
		args->minlen = ap->alen;
		args->minlen = args->maxlen;

	/*
	 * set the failure fallback case to look in the selected
@@ -2573,7 +2590,9 @@ xfs_bmap_btalloc(
	args.tp = ap->tp;
	args.mp = mp;
	args.fsbno = ap->rval;
	args.maxlen = MIN(ap->alen, mp->m_sb.sb_agblocks);

	/* Trim the allocation back to the maximum an AG can fit. */
	args.maxlen = MIN(ap->alen, XFS_ALLOC_AG_MAX_USABLE(mp));
	args.firstblock = ap->firstblock;
	blen = 0;
	if (nullfb) {
@@ -2621,7 +2640,7 @@ xfs_bmap_btalloc(
			/*
			 * Adjust for alignment
			 */
			if (blen > args.alignment && blen <= ap->alen)
			if (blen > args.alignment && blen <= args.maxlen)
				args.minlen = blen - args.alignment;
			args.minalignslop = 0;
		} else {
@@ -2640,7 +2659,7 @@ xfs_bmap_btalloc(
			 * of minlen+alignment+slop doesn't go up
			 * between the calls.
			 */
			if (blen > mp->m_dalign && blen <= ap->alen)
			if (blen > mp->m_dalign && blen <= args.maxlen)
				nextminlen = blen - mp->m_dalign;
			else
				nextminlen = args.minlen;
@@ -4485,6 +4504,16 @@ xfs_bmapi(
				/* Figure out the extent size, adjust alen */
				extsz = xfs_get_extsz_hint(ip);
				if (extsz) {
					/*
					 * make sure we don't exceed a single
					 * extent length when we align the
					 * extent by reducing length we are
					 * going to allocate by the maximum
					 * amount extent size aligment may
					 * require.
					 */
					alen = XFS_FILBLKS_MIN(len,
						   MAXEXTLEN - (2 * extsz - 1));
					error = xfs_bmap_extsize_align(mp,
							&got, &prev, extsz,
							rt, eof,
+7 −5
Original line number Diff line number Diff line
@@ -427,12 +427,14 @@ xfs_buf_item_unpin(

		if (remove) {
			/*
			 * We have to remove the log item from the transaction
			 * as we are about to release our reference to the
			 * buffer.  If we don't, the unlock that occurs later
			 * in xfs_trans_uncommit() will ry to reference the
			 * If we are in a transaction context, we have to
			 * remove the log item from the transaction as we are
			 * about to release our reference to the buffer.  If we
			 * don't, the unlock that occurs later in
			 * xfs_trans_uncommit() will try to reference the
			 * buffer which we no longer have a hold on.
			 */
			if (lip->li_desc)
				xfs_trans_del_item(lip);

			/*
Loading