Skip to content

Commit

Permalink
Merge tag 'xfs-6.8-merge-3' 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 Chandan Babu:
 "New features/functionality:
   - Online repair:
       - Reserve disk space for online repairs
       - Fix misinteraction between the AIL and btree bulkloader because
         of which the bulk load fails to queue a buffer for writeback if
         it happens to be on the AIL list
       - Prevent transaction reservation overflows when reaping blocks
         during online repair
       - Whenever possible, bulkloader now copies multiple records into
         a block
       - Support repairing of
           1. Per-AG free space, inode and refcount btrees
           2. Ondisk inodes
           3. File data and attribute fork mappings
       - Verify the contents of
           1. Inode and data fork of realtime bitmap file
           2. Quota files
   - Introduce MF_MEM_PRE_REMOVE. This will be used to notify tasks
     about a pmem device being removed

  Bug fixes:
   - Fix memory leak of recovered attri intent items
   - Fix UAF during log intent recovery
   - Fix realtime geometry integer overflows
   - Prevent scrub from live locking in xchk_iget
   - Prevent fs shutdown when removing files during low free disk space
   - Prevent transaction reservation overflow when extending an RT
     device
   - Prevent incorrect warning from being printed when extending a
     filesystem
   - Fix an off-by-one error in xreap_agextent_binval
   - Serialize access to perag radix tree during deletion operation
   - Fix perag memory leak during growfs
   - Allow allocation of minlen realtime extent when the maximum sized
     realtime free extent is minlen in size

  Cleanups:
   - Remove duplicate boilerplate code spread across functionality
     associated with different log items
   - Cleanup resblks interfaces
   - Pass defer ops pointer to defer helpers instead of an enum
   - Initialize di_crc in xfs_log_dinode to prevent KMSAN warnings
   - Use static_assert() instead of BUILD_BUG_ON_MSG() to validate size
     of structures and structure member offsets. This is done in order
     to be able to share the code with userspace
   - Move XFS documentation under a new directory specific to XFS
   - Do not invoke deferred ops' ->create_done callback if the deferred
     operation does not have an intent item associated with it
   - Remove duplicate inclusion of header files from scrub/health.c
   - Refactor Realtime code
   - Cleanup attr code"

* tag 'xfs-6.8-merge-3' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: (123 commits)
  xfs: use the op name in trace_xlog_intent_recovery_failed
  xfs: fix a use after free in xfs_defer_finish_recovery
  xfs: turn the XFS_DA_OP_REPLACE checks in xfs_attr_shortform_addname into asserts
  xfs: remove xfs_attr_sf_hdr_t
  xfs: remove struct xfs_attr_shortform
  xfs: use xfs_attr_sf_findname in xfs_attr_shortform_getvalue
  xfs: remove xfs_attr_shortform_lookup
  xfs: simplify xfs_attr_sf_findname
  xfs: move the xfs_attr_sf_lookup tracepoint
  xfs: return if_data from xfs_idata_realloc
  xfs: make if_data a void pointer
  xfs: fold xfs_rtallocate_extent into xfs_bmap_rtalloc
  xfs: simplify and optimize the RT allocation fallback cascade
  xfs: reorder the minlen and prod calculations in xfs_bmap_rtalloc
  xfs: remove XFS_RTMIN/XFS_RTMAX
  xfs: remove rt-wrappers from xfs_format.h
  xfs: factor out a xfs_rtalloc_sumlevel helper
  xfs: tidy up xfs_rtallocate_extent_exact
  xfs: merge the calls to xfs_rtallocate_range in xfs_rtallocate_block
  xfs: reflow the tail end of xfs_rtallocate_extent_block
  ...
  • Loading branch information
torvalds committed Jan 10, 2024
2 parents 32720ac + bcdfae6 commit 12958e9
Show file tree
Hide file tree
Showing 146 changed files with 12,727 additions and 2,943 deletions.
5 changes: 1 addition & 4 deletions Documentation/filesystems/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,5 @@ Documentation for filesystem implementations.
udf
virtiofs
vfat
xfs-delayed-logging-design
xfs-maintainer-entry-profile
xfs-self-describing-metadata
xfs-online-fsck-design
xfs/index
zonefs
14 changes: 14 additions & 0 deletions Documentation/filesystems/xfs/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.. SPDX-License-Identifier: GPL-2.0
============================
XFS Filesystem Documentation
============================

.. toctree::
:maxdepth: 2
:numbered:

xfs-delayed-logging-design
xfs-maintainer-entry-profile
xfs-self-describing-metadata
xfs-online-fsck-design
Original file line number Diff line number Diff line change
Expand Up @@ -962,7 +962,7 @@ disk, but these buffer verifiers cannot provide any consistency checking
between metadata structures.

For more information, please see the documentation for
Documentation/filesystems/xfs-self-describing-metadata.rst
Documentation/filesystems/xfs/xfs-self-describing-metadata.rst

Reverse Mapping
---------------
Expand Down
2 changes: 1 addition & 1 deletion Documentation/maintainer/maintainer-entry-profile.rst
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,4 @@ to do something different in the near future.
../driver-api/media/maintainer-entry-profile
../driver-api/vfio-pci-device-specific-driver-acceptance
../nvme/feature-and-quirk-policy
../filesystems/xfs-maintainer-entry-profile
../filesystems/xfs/xfs-maintainer-entry-profile
4 changes: 2 additions & 2 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -23846,10 +23846,10 @@ S: Supported
W: http://xfs.org/
C: irc://irc.oftc.net/xfs
T: git git://git.kernel.org/pub/scm/fs/xfs/xfs-linux.git
P: Documentation/filesystems/xfs-maintainer-entry-profile.rst
P: Documentation/filesystems/xfs/xfs-maintainer-entry-profile.rst
F: Documentation/ABI/testing/sysfs-fs-xfs
F: Documentation/admin-guide/xfs.rst
F: Documentation/filesystems/xfs-*
F: Documentation/filesystems/xfs/*
F: fs/xfs/
F: include/uapi/linux/dqblk_xfs.h
F: include/uapi/linux/fsmap.h
Expand Down
3 changes: 2 additions & 1 deletion drivers/dax/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,8 @@ void kill_dax(struct dax_device *dax_dev)
return;

if (dax_dev->holder_data != NULL)
dax_holder_notify_failure(dax_dev, 0, U64_MAX, 0);
dax_holder_notify_failure(dax_dev, 0, U64_MAX,
MF_MEM_PRE_REMOVE);

clear_bit(DAXDEV_ALIVE, &dax_dev->flags);
synchronize_srcu(&dax_srcu);
Expand Down
21 changes: 20 additions & 1 deletion fs/xfs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ ifeq ($(CONFIG_XFS_ONLINE_SCRUB),y)

xfs-y += $(addprefix scrub/, \
trace.o \
agb_bitmap.o \
agheader.o \
alloc.o \
attr.o \
Expand Down Expand Up @@ -175,14 +176,32 @@ xfs-$(CONFIG_XFS_RT) += $(addprefix scrub/, \
rtsummary.o \
)

xfs-$(CONFIG_XFS_QUOTA) += scrub/quota.o
xfs-$(CONFIG_XFS_QUOTA) += $(addprefix scrub/, \
dqiterate.o \
quota.o \
)

# online repair
ifeq ($(CONFIG_XFS_ONLINE_REPAIR),y)
xfs-y += $(addprefix scrub/, \
agheader_repair.o \
alloc_repair.o \
bmap_repair.o \
cow_repair.o \
ialloc_repair.o \
inode_repair.o \
newbt.o \
reap.o \
refcount_repair.o \
repair.o \
)

xfs-$(CONFIG_XFS_RT) += $(addprefix scrub/, \
rtbitmap_repair.o \
)

xfs-$(CONFIG_XFS_QUOTA) += $(addprefix scrub/, \
quota_repair.o \
)
endif
endif
38 changes: 29 additions & 9 deletions fs/xfs/libxfs/xfs_ag.c
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,31 @@ xfs_agino_range(
return __xfs_agino_range(mp, xfs_ag_block_count(mp, agno), first, last);
}

/*
* Free perag within the specified AG range, it is only used to free unused
* perags under the error handling path.
*/
void
xfs_free_unused_perag_range(
struct xfs_mount *mp,
xfs_agnumber_t agstart,
xfs_agnumber_t agend)
{
struct xfs_perag *pag;
xfs_agnumber_t index;

for (index = agstart; index < agend; index++) {
spin_lock(&mp->m_perag_lock);
pag = radix_tree_delete(&mp->m_perag_tree, index);
spin_unlock(&mp->m_perag_lock);
if (!pag)
break;
xfs_buf_hash_destroy(pag);
xfs_defer_drain_free(&pag->pag_intents_drain);
kmem_free(pag);
}
}

int
xfs_initialize_perag(
struct xfs_mount *mp,
Expand Down Expand Up @@ -424,19 +449,14 @@ xfs_initialize_perag(

out_remove_pag:
xfs_defer_drain_free(&pag->pag_intents_drain);
spin_lock(&mp->m_perag_lock);
radix_tree_delete(&mp->m_perag_tree, index);
spin_unlock(&mp->m_perag_lock);
out_free_pag:
kmem_free(pag);
out_unwind_new_pags:
/* unwind any prior newly initialized pags */
for (index = first_initialised; index < agcount; index++) {
pag = radix_tree_delete(&mp->m_perag_tree, index);
if (!pag)
break;
xfs_buf_hash_destroy(pag);
xfs_defer_drain_free(&pag->pag_intents_drain);
kmem_free(pag);
}
xfs_free_unused_perag_range(mp, first_initialised, agcount);
return error;
}

Expand Down Expand Up @@ -984,7 +1004,7 @@ xfs_ag_shrink_space(
if (err2 != -ENOSPC)
goto resv_err;

err2 = __xfs_free_extent_later(*tpp, args.fsbno, delta, NULL,
err2 = xfs_free_extent_later(*tpp, args.fsbno, delta, NULL,
XFS_AG_RESV_NONE, true);
if (err2)
goto resv_err;
Expand Down
12 changes: 12 additions & 0 deletions fs/xfs/libxfs/xfs_ag.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,16 @@ struct xfs_perag {
*/
uint16_t pag_checked;
uint16_t pag_sick;

#ifdef CONFIG_XFS_ONLINE_REPAIR
/*
* Alternate btree heights so that online repair won't trip the write
* verifiers while rebuilding the AG btrees.
*/
uint8_t pagf_repair_levels[XFS_BTNUM_AGF];
uint8_t pagf_repair_refcount_level;
#endif

spinlock_t pag_state_lock;

spinlock_t pagb_lock; /* lock for pagb_tree */
Expand Down Expand Up @@ -133,6 +143,8 @@ __XFS_AG_OPSTATE(prefers_metadata, PREFERS_METADATA)
__XFS_AG_OPSTATE(allows_inodes, ALLOWS_INODES)
__XFS_AG_OPSTATE(agfl_needs_reset, AGFL_NEEDS_RESET)

void xfs_free_unused_perag_range(struct xfs_mount *mp, xfs_agnumber_t agstart,
xfs_agnumber_t agend);
int xfs_initialize_perag(struct xfs_mount *mp, xfs_agnumber_t agcount,
xfs_rfsblock_t dcount, xfs_agnumber_t *maxagi);
int xfs_initialize_perag_data(struct xfs_mount *mp, xfs_agnumber_t agno);
Expand Down
2 changes: 2 additions & 0 deletions fs/xfs/libxfs/xfs_ag_resv.c
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,8 @@ xfs_ag_resv_free_extent(
fallthrough;
case XFS_AG_RESV_NONE:
xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, (int64_t)len);
fallthrough;
case XFS_AG_RESV_IGNORE:
return;
}

Expand Down
116 changes: 105 additions & 11 deletions fs/xfs/libxfs/xfs_alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,11 +246,9 @@ xfs_alloc_btrec_to_irec(
/* Simple checks for free space records. */
xfs_failaddr_t
xfs_alloc_check_irec(
struct xfs_btree_cur *cur,
const struct xfs_alloc_rec_incore *irec)
struct xfs_perag *pag,
const struct xfs_alloc_rec_incore *irec)
{
struct xfs_perag *pag = cur->bc_ag.pag;

if (irec->ar_blockcount == 0)
return __this_address;

Expand Down Expand Up @@ -299,7 +297,7 @@ xfs_alloc_get_rec(
return error;

xfs_alloc_btrec_to_irec(rec, &irec);
fa = xfs_alloc_check_irec(cur, &irec);
fa = xfs_alloc_check_irec(cur->bc_ag.pag, &irec);
if (fa)
return xfs_alloc_complain_bad_rec(cur, fa, &irec);

Expand Down Expand Up @@ -2514,22 +2512,23 @@ xfs_defer_agfl_block(
trace_xfs_agfl_free_defer(mp, agno, 0, agbno, 1);

xfs_extent_free_get_group(mp, xefi);
xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_AGFL_FREE, &xefi->xefi_list);
xfs_defer_add(tp, &xefi->xefi_list, &xfs_agfl_free_defer_type);
return 0;
}

/*
* Add the extent to the list of extents to be free at transaction end.
* The list is maintained sorted (by block number).
*/
int
__xfs_free_extent_later(
static int
xfs_defer_extent_free(
struct xfs_trans *tp,
xfs_fsblock_t bno,
xfs_filblks_t len,
const struct xfs_owner_info *oinfo,
enum xfs_ag_resv_type type,
bool skip_discard)
bool skip_discard,
struct xfs_defer_pending **dfpp)
{
struct xfs_extent_free_item *xefi;
struct xfs_mount *mp = tp->t_mountp;
Expand Down Expand Up @@ -2577,10 +2576,105 @@ __xfs_free_extent_later(
XFS_FSB_TO_AGBNO(tp->t_mountp, bno), len);

xfs_extent_free_get_group(mp, xefi);
xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_FREE, &xefi->xefi_list);
*dfpp = xfs_defer_add(tp, &xefi->xefi_list, &xfs_extent_free_defer_type);
return 0;
}

int
xfs_free_extent_later(
struct xfs_trans *tp,
xfs_fsblock_t bno,
xfs_filblks_t len,
const struct xfs_owner_info *oinfo,
enum xfs_ag_resv_type type,
bool skip_discard)
{
struct xfs_defer_pending *dontcare = NULL;

return xfs_defer_extent_free(tp, bno, len, oinfo, type, skip_discard,
&dontcare);
}

/*
* Set up automatic freeing of unwritten space in the filesystem.
*
* This function attached a paused deferred extent free item to the
* transaction. Pausing means that the EFI will be logged in the next
* transaction commit, but the pending EFI will not be finished until the
* pending item is unpaused.
*
* If the system goes down after the EFI has been persisted to the log but
* before the pending item is unpaused, log recovery will find the EFI, fail to
* find the EFD, and free the space.
*
* If the pending item is unpaused, the next transaction commit will log an EFD
* without freeing the space.
*
* Caller must ensure that the tp, fsbno, len, oinfo, and resv flags of the
* @args structure are set to the relevant values.
*/
int
xfs_alloc_schedule_autoreap(
const struct xfs_alloc_arg *args,
bool skip_discard,
struct xfs_alloc_autoreap *aarp)
{
int error;

error = xfs_defer_extent_free(args->tp, args->fsbno, args->len,
&args->oinfo, args->resv, skip_discard, &aarp->dfp);
if (error)
return error;

xfs_defer_item_pause(args->tp, aarp->dfp);
return 0;
}

/*
* Cancel automatic freeing of unwritten space in the filesystem.
*
* Earlier, we created a paused deferred extent free item and attached it to
* this transaction so that we could automatically roll back a new space
* allocation if the system went down. Now we want to cancel the paused work
* item by marking the EFI stale so we don't actually free the space, unpausing
* the pending item and logging an EFD.
*
* The caller generally should have already mapped the space into the ondisk
* filesystem. If the reserved space was partially used, the caller must call
* xfs_free_extent_later to create a new EFI to free the unused space.
*/
void
xfs_alloc_cancel_autoreap(
struct xfs_trans *tp,
struct xfs_alloc_autoreap *aarp)
{
struct xfs_defer_pending *dfp = aarp->dfp;
struct xfs_extent_free_item *xefi;

if (!dfp)
return;

list_for_each_entry(xefi, &dfp->dfp_work, xefi_list)
xefi->xefi_flags |= XFS_EFI_CANCELLED;

xfs_defer_item_unpause(tp, dfp);
}

/*
* Commit automatic freeing of unwritten space in the filesystem.
*
* This unpauses an earlier _schedule_autoreap and commits to freeing the
* allocated space. Call this if none of the reserved space was used.
*/
void
xfs_alloc_commit_autoreap(
struct xfs_trans *tp,
struct xfs_alloc_autoreap *aarp)
{
if (aarp->dfp)
xfs_defer_item_unpause(tp, aarp->dfp);
}

#ifdef DEBUG
/*
* Check if an AGF has a free extent record whose length is equal to
Expand Down Expand Up @@ -3848,7 +3942,7 @@ xfs_alloc_query_range_helper(
xfs_failaddr_t fa;

xfs_alloc_btrec_to_irec(rec, &irec);
fa = xfs_alloc_check_irec(cur, &irec);
fa = xfs_alloc_check_irec(cur->bc_ag.pag, &irec);
if (fa)
return xfs_alloc_complain_bad_rec(cur, fa, &irec);

Expand Down
Loading

0 comments on commit 12958e9

Please sign in to comment.