Skip to content

Commit

Permalink
Merge tag 'xfs-5.2-merge-4' of git://git.kernel.org/pub/scm/fs/xfs/xf…
Browse files Browse the repository at this point in the history
…s-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
  ...
  • Loading branch information
torvalds committed May 7, 2019
2 parents d8456ea + 9108326 commit aa26690
Show file tree
Hide file tree
Showing 59 changed files with 2,085 additions and 313 deletions.
3 changes: 3 additions & 0 deletions fs/xfs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down Expand Up @@ -142,6 +143,8 @@ xfs-y += $(addprefix scrub/, \
common.o \
dabtree.o \
dir.o \
fscounters.o \
health.o \
ialloc.o \
inode.o \
parent.o \
Expand Down
54 changes: 54 additions & 0 deletions fs/xfs/libxfs/xfs_ag.c
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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 changes: 2 additions & 0 deletions fs/xfs/libxfs/xfs_ag.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
13 changes: 11 additions & 2 deletions fs/xfs/libxfs/xfs_alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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)
Expand Down
35 changes: 12 additions & 23 deletions fs/xfs/libxfs/xfs_attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/*
Expand Down Expand Up @@ -255,31 +255,24 @@ 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;

/*
* 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))
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -408,9 +400,6 @@ xfs_attr_set(
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);
Expand Down
2 changes: 1 addition & 1 deletion fs/xfs/libxfs/xfs_attr.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ int xfs_attr_get(struct xfs_inode *ip, const unsigned char *name,
unsigned char *value, int *valuelenp, int flags);
int xfs_attr_set(struct xfs_inode *dp, const unsigned char *name,
unsigned char *value, int valuelen, int flags);
int xfs_attr_set_args(struct xfs_da_args *args, struct xfs_buf **leaf_bp);
int xfs_attr_set_args(struct xfs_da_args *args);
int xfs_attr_remove(struct xfs_inode *dp, const unsigned char *name, int flags);
int xfs_attr_remove_args(struct xfs_da_args *args);
int xfs_attr_list(struct xfs_inode *dp, char *buffer, int bufsize,
Expand Down
17 changes: 14 additions & 3 deletions fs/xfs/libxfs/xfs_bmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -2009,6 +2009,9 @@ xfs_bmap_add_extent_delay_real(
goto done;
}

if (da_new != da_old)
xfs_mod_delalloc(mp, (int64_t)da_new - da_old);

if (bma->cur) {
da_new += bma->cur->bc_private.b.allocated;
bma->cur->bc_private.b.allocated = 0;
Expand Down Expand Up @@ -2640,6 +2643,7 @@ xfs_bmap_add_extent_hole_delay(
/*
* Nothing to do for disk quota accounting here.
*/
xfs_mod_delalloc(ip->i_mount, (int64_t)newlen - oldlen);
}
}

Expand Down Expand Up @@ -3352,8 +3356,10 @@ xfs_bmap_btalloc_accounting(
* already have quota reservation and there's nothing to do
* yet.
*/
if (ap->wasdel)
if (ap->wasdel) {
xfs_mod_delalloc(ap->ip->i_mount, -(int64_t)args->len);
return;
}

/*
* Otherwise, we've allocated blocks in a hole. The transaction
Expand All @@ -3372,8 +3378,10 @@ xfs_bmap_btalloc_accounting(
/* data/attr fork only */
ap->ip->i_d.di_nblocks += args->len;
xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE);
if (ap->wasdel)
if (ap->wasdel) {
ap->ip->i_delayed_blks -= args->len;
xfs_mod_delalloc(ap->ip->i_mount, -(int64_t)args->len);
}
xfs_trans_mod_dquot_byino(ap->tp, ap->ip,
ap->wasdel ? XFS_TRANS_DQ_DELBCOUNT : XFS_TRANS_DQ_BCOUNT,
args->len);
Expand Down Expand Up @@ -3969,6 +3977,7 @@ xfs_bmapi_reserve_delalloc(


ip->i_delayed_blks += alen;
xfs_mod_delalloc(ip->i_mount, alen + indlen);

got->br_startoff = aoff;
got->br_startblock = nullstartblock(indlen);
Expand Down Expand Up @@ -4840,8 +4849,10 @@ xfs_bmap_del_extent_delay(
da_diff = da_old - da_new;
if (!isrt)
da_diff += del->br_blockcount;
if (da_diff)
if (da_diff) {
xfs_mod_fdblocks(mp, da_diff, false);
xfs_mod_delalloc(mp, -da_diff);
}
return error;
}

Expand Down
14 changes: 9 additions & 5 deletions fs/xfs/libxfs/xfs_defer.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,13 +274,15 @@ xfs_defer_trans_roll(

trace_xfs_defer_trans_roll(tp, _RET_IP_);

/* Roll the transaction. */
/*
* Roll the transaction. Rolling always given a new transaction (even
* if committing the old one fails!) to hand back to the caller, so we
* join the held resources to the new transaction so that we always
* return with the held resources joined to @tpp, no matter what
* happened.
*/
error = xfs_trans_roll(tpp);
tp = *tpp;
if (error) {
trace_xfs_defer_trans_roll_error(tp, error);
return error;
}

/* Rejoin the joined inodes. */
for (i = 0; i < ipcount; i++)
Expand All @@ -292,6 +294,8 @@ xfs_defer_trans_roll(
xfs_trans_bhold(tp, bplist[i]);
}

if (error)
trace_xfs_defer_trans_roll_error(tp, error);
return error;
}

Expand Down
4 changes: 1 addition & 3 deletions fs/xfs/libxfs/xfs_dquot_buf.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ xfs_dqblk_verify(
/*
* Do some primitive error checking on ondisk dquot data structures.
*/
int
void
xfs_dqblk_repair(
struct xfs_mount *mp,
struct xfs_dqblk *dqb,
Expand All @@ -133,8 +133,6 @@ xfs_dqblk_repair(
xfs_update_cksum((char *)dqb, sizeof(struct xfs_dqblk),
XFS_DQUOT_CRC_OFF);
}

return 0;
}

STATIC bool
Expand Down
Loading

0 comments on commit aa26690

Please sign in to comment.