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

Merge tag 'xfs-5.2-merge-4' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux

Pull xfs updates from Darrick Wong:
 "Here's a big pile of new stuff for XFS for 5.2. XFS has grown the
  ability to report metadata health status to userspace after online
  fsck checks the filesystem. The online metadata checking code is (I
  really hope) feature complete with the addition of checks for the
  global fs counters, though it'll remain EXPERIMENTAL for now.

  There are also fixes for thundering herds of writeback completions and
  some other deadlocks, fixes for theoretical integer overflow attacks
  on space accounting, and removal of the long-defunct 'mntpt' option
  which was deprecated in the mid-2000s and (it turns out) totally
  broken since 2011 (and nobody complained...).

  Summary:

   - Fix some more buffer deadlocks when performing an unmount after a
     hard shutdown.

   - Fix some minor space accounting issues.

   - Fix some use after free problems.

   - Make the (undocumented) FITRIM behavior consistent with other
     filesystems.

   - Embiggen the xfs geometry ioctl's data structure.

   - Introduce a new AG geometry ioctl.

   - Introduce a new online health reporting infrastructure and ioctl
     for userspace to query a filesystem's health status.

   - Enhance online scrub and repair to update the health reports.

   - Reduce thundering herd problems when writeback io completes.

   - Fix some transaction reservation type errors.

   - Fix integer overflow problems with delayed alloc reservation
     counters.

   - Fix some problems where we would exit to userspace without
     unlocking.

   - Fix inconsistent behavior when finishing deferred ops fails.

   - Strengthen scrub to check incore data against ondisk metadata.

   - Remove long-broken mntpt mount option.

   - Add an online scrub function for the filesystem summary counters,
     which should make online metadata scrub more or less feature
     complete for now.

   - Various cleanups"

* tag 'xfs-5.2-merge-4' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: (38 commits)
  xfs: change some error-less functions to void types
  xfs: add online scrub for superblock counters
  xfs: don't parse the mtpt mount option
  xfs: always rejoin held resources during defer roll
  xfs: add missing error check in xfs_prepare_shift()
  xfs: scrub should check incore counters against ondisk headers
  xfs: allow scrubbers to pause background reclaim
  xfs: rename the speculative block allocation reclaim toggle functions
  xfs: track delayed allocation reservations across the filesystem
  xfs: fix broken bhold behavior in xrep_roll_ag_trans
  xfs: unlock inode when xfs_ioctl_setattr_get_trans can't get transaction
  xfs: kill the xfs_dqtrx_t typedef
  xfs: widen inode delalloc block counter to 64-bits
  xfs: widen quota block counters to 64-bit integers
  xfs: abort unaligned nowait directio early
  xfs: assert that we don't enter agfl freeing with a non-permanent transaction
  xfs: make tr_growdata a permanent transaction
  xfs: merge adjacent io completions of the same type
  xfs: remove unused m_data_workqueue
  xfs: implement per-inode writeback completion queues
  ...
parents d8456eaf 91083269
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ xfs-y += xfs_aops.o \
				   xfs_fsmap.o \
				   xfs_fsops.o \
				   xfs_globals.o \
				   xfs_health.o \
				   xfs_icache.o \
				   xfs_ioctl.o \
				   xfs_iomap.o \
@@ -142,6 +143,8 @@ xfs-y += $(addprefix scrub/, \
				   common.o \
				   dabtree.o \
				   dir.o \
				   fscounters.o \
				   health.o \
				   ialloc.o \
				   inode.o \
				   parent.o \
+54 −0
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@
#include "xfs_ialloc.h"
#include "xfs_rmap.h"
#include "xfs_ag.h"
#include "xfs_ag_resv.h"
#include "xfs_health.h"

static struct xfs_buf *
xfs_get_aghdr_buf(
@@ -461,3 +463,55 @@ xfs_ag_extend_space(
				len, &XFS_RMAP_OINFO_SKIP_UPDATE,
				XFS_AG_RESV_NONE);
}

/* Retrieve AG geometry. */
int
xfs_ag_get_geometry(
	struct xfs_mount	*mp,
	xfs_agnumber_t		agno,
	struct xfs_ag_geometry	*ageo)
{
	struct xfs_buf		*agi_bp;
	struct xfs_buf		*agf_bp;
	struct xfs_agi		*agi;
	struct xfs_agf		*agf;
	struct xfs_perag	*pag;
	unsigned int		freeblks;
	int			error;

	if (agno >= mp->m_sb.sb_agcount)
		return -EINVAL;

	/* Lock the AG headers. */
	error = xfs_ialloc_read_agi(mp, NULL, agno, &agi_bp);
	if (error)
		return error;
	error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agf_bp);
	if (error)
		goto out_agi;
	pag = xfs_perag_get(mp, agno);

	/* Fill out form. */
	memset(ageo, 0, sizeof(*ageo));
	ageo->ag_number = agno;

	agi = XFS_BUF_TO_AGI(agi_bp);
	ageo->ag_icount = be32_to_cpu(agi->agi_count);
	ageo->ag_ifree = be32_to_cpu(agi->agi_freecount);

	agf = XFS_BUF_TO_AGF(agf_bp);
	ageo->ag_length = be32_to_cpu(agf->agf_length);
	freeblks = pag->pagf_freeblks +
		   pag->pagf_flcount +
		   pag->pagf_btreeblks -
		   xfs_ag_resv_needed(pag, XFS_AG_RESV_NONE);
	ageo->ag_freeblks = freeblks;
	xfs_ag_geom_health(pag, ageo);

	/* Release resources. */
	xfs_perag_put(pag);
	xfs_buf_relse(agf_bp);
out_agi:
	xfs_buf_relse(agi_bp);
	return error;
}
+2 −0
Original line number Diff line number Diff line
@@ -26,5 +26,7 @@ struct aghdr_init_data {
int xfs_ag_init_headers(struct xfs_mount *mp, struct aghdr_init_data *id);
int xfs_ag_extend_space(struct xfs_mount *mp, struct xfs_trans *tp,
			struct aghdr_init_data *id, xfs_extlen_t len);
int xfs_ag_get_geometry(struct xfs_mount *mp, xfs_agnumber_t agno,
			struct xfs_ag_geometry *ageo);

#endif /* __LIBXFS_AG_H */
+11 −2
Original line number Diff line number Diff line
@@ -2042,6 +2042,7 @@ xfs_alloc_space_available(
	xfs_extlen_t		alloc_len, longest;
	xfs_extlen_t		reservation; /* blocks that are still reserved */
	int			available;
	xfs_extlen_t		agflcount;

	if (flags & XFS_ALLOC_FLAG_FREEING)
		return true;
@@ -2054,8 +2055,13 @@ xfs_alloc_space_available(
	if (longest < alloc_len)
		return false;

	/* do we have enough free space remaining for the allocation? */
	available = (int)(pag->pagf_freeblks + pag->pagf_flcount -
	/*
	 * Do we have enough free space remaining for the allocation? Don't
	 * account extra agfl blocks because we are about to defer free them,
	 * making them unavailable until the current transaction commits.
	 */
	agflcount = min_t(xfs_extlen_t, pag->pagf_flcount, min_free);
	available = (int)(pag->pagf_freeblks + agflcount -
			  reservation - min_free - args->minleft);
	if (available < (int)max(args->total, alloc_len))
		return false;
@@ -2237,6 +2243,9 @@ xfs_alloc_fix_freelist(
	xfs_extlen_t		need;	/* total blocks needed in freelist */
	int			error = 0;

	/* deferred ops (AGFL block frees) require permanent transactions */
	ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);

	if (!pag->pagf_init) {
		error = xfs_alloc_read_agf(mp, tp, args->agno, flags, &agbp);
		if (error)
+12 −23
Original line number Diff line number Diff line
@@ -224,10 +224,10 @@ xfs_attr_try_sf_addname(
 */
int
xfs_attr_set_args(
	struct xfs_da_args	*args,
	struct xfs_buf          **leaf_bp)
	struct xfs_da_args	*args)
{
	struct xfs_inode	*dp = args->dp;
	struct xfs_buf          *leaf_bp = NULL;
	int			error;

	/*
@@ -255,7 +255,7 @@ xfs_attr_set_args(
		 * It won't fit in the shortform, transform to a leaf block.
		 * GROT: another possible req'mt for a double-split btree op.
		 */
		error = xfs_attr_shortform_to_leaf(args, leaf_bp);
		error = xfs_attr_shortform_to_leaf(args, &leaf_bp);
		if (error)
			return error;

@@ -263,23 +263,16 @@ xfs_attr_set_args(
		 * Prevent the leaf buffer from being unlocked so that a
		 * concurrent AIL push cannot grab the half-baked leaf
		 * buffer and run into problems with the write verifier.
		 * Once we're done rolling the transaction we can release
		 * the hold and add the attr to the leaf.
		 */
		xfs_trans_bhold(args->trans, *leaf_bp);

		xfs_trans_bhold(args->trans, leaf_bp);
		error = xfs_defer_finish(&args->trans);
		if (error)
			return error;

		/*
		 * Commit the leaf transformation.  We'll need another
		 * (linked) transaction to add the new attribute to the
		 * leaf.
		 */
		error = xfs_trans_roll_inode(&args->trans, dp);
		if (error)
		xfs_trans_bhold_release(args->trans, leaf_bp);
		if (error) {
			xfs_trans_brelse(args->trans, leaf_bp);
			return error;
		xfs_trans_bjoin(args->trans, *leaf_bp);
		*leaf_bp = NULL;
		}
	}

	if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
@@ -322,7 +315,6 @@ xfs_attr_set(
	int			flags)
{
	struct xfs_mount	*mp = dp->i_mount;
	struct xfs_buf		*leaf_bp = NULL;
	struct xfs_da_args	args;
	struct xfs_trans_res	tres;
	int			rsvd = (flags & ATTR_ROOT) != 0;
@@ -381,9 +373,9 @@ xfs_attr_set(
		goto out_trans_cancel;

	xfs_trans_ijoin(args.trans, dp, 0);
	error = xfs_attr_set_args(&args, &leaf_bp);
	error = xfs_attr_set_args(&args);
	if (error)
		goto out_release_leaf;
		goto out_trans_cancel;
	if (!args.trans) {
		/* shortform attribute has already been committed */
		goto out_unlock;
@@ -408,9 +400,6 @@ out_unlock:
	xfs_iunlock(dp, XFS_ILOCK_EXCL);
	return error;

out_release_leaf:
	if (leaf_bp)
		xfs_trans_brelse(args.trans, leaf_bp);
out_trans_cancel:
	if (args.trans)
		xfs_trans_cancel(args.trans);
Loading