xfs: fixes for v7.3-rc5

Signed-off-by: Carlos Maiolino <cem@kernel.org>
 -----BEGIN PGP SIGNATURE-----
 
 iJUEABMJAB0WIQSmtYVZ/MfVMGUq1GNcsMJ8RxYuYwUCarEtCAAKCRBcsMJ8RxYu
 YwmHAX4+ML995OtOeKIN2Cpiu/0RYW/bHPrBBCHsiZN2BFZ3Ap2W7nxm4/OFewA9
 5oB6eKgBgL8Zi2K0ZPsiF+IxAEkWUBkvCgiQtByO3dSS6aMR6KzfrQBj0Pftlcgy
 z+C74fVlyA==
 =USzk
 -----END PGP SIGNATURE-----

Merge tag 'xfs-fixes-7.3-rc5' of gitolite.kernel.org:/pub/scm/fs/xfs/xfs-linux

Pull xfs fixes from Carlos Maiolino:
 "This mostly contain 'random' bugfixes found by LLM tools on different
  xfs subsystems. A few code cleanups and a NULL ptr deref on zoned
  support. Those 'random' bugfixes include possible buf overrus, UAFs,
  block leaks, etc..."

* tag 'xfs-fixes-7.3-rc5' of gitolite.kernel.org:/pub/scm/fs/xfs/xfs-linux: (26 commits)
  xfs: fix wild memcpy access when formatting ondisk rtrefcount btree roots
  xfs: don't let hidden_space go negative in xfs_metafile_resv_init
  xfs: drop dquot flush lock when we can't find a buffer to flush
  xfs: fix cursor and pointer handling when recovering iunlink buckets
  xfs: fix blockgc group quota scanning when usrquota isn't enforced
  xfs: don't merge different file IO error types
  xfs: don't let memory failures leak blocks and kill repairs
  xfs: don't cross reference rmapbt with bitmaps if they're incomplete
  xfs: fix rtgroup repair estimations
  xfs: call xfs_dquot_set_prealloc_limits if we installed default rtb limits
  xfs: fix typos and repeated words in comments
  xfs: remove unused xfs_reflink_remap_range declaration
  xfs: remove duplicate INO1_WRITTEN check
  xfs: don't try to get a reference to a NULL oz in xfs_get_cached_zone
  xfs: check di_forkoff correctly in scrub
  xfs: only flag zero padding for dir3 data blocks, not dir3 block blocks
  xfs: fix integer overflows in xbitmap set functions
  xfs: use the correct reservations for rtrmap/refcount recovery
  xfs: don't call xfs_exchange_range_finish for a dry run
  xfs: check padding field in xfs_ioc_commit_range
  ...
This commit is contained in:
Linus Torvalds 2026-09-21 08:22:53 -07:00
commit f0100363d8
41 changed files with 151 additions and 89 deletions

View File

@ -207,7 +207,7 @@ xfs_perag_next(
}
/*
* Per-ag geometry infomation and validation
* Per-ag geometry information and validation
*/
xfs_agblock_t xfs_ag_block_count(struct xfs_mount *mp, xfs_agnumber_t agno);
void xfs_agino_range(struct xfs_mount *mp, xfs_agnumber_t agno,

View File

@ -3487,7 +3487,7 @@ xfs_alloc_read_agf(
}
/*
* Pre-proces allocation arguments to set initial state that we don't require
* Pre-process allocation arguments to set initial state that we don't require
* callers to set up correctly, as well as bounds check the allocation args
* that are set up.
*/
@ -3608,7 +3608,7 @@ xfs_alloc_vextent_finish(
* ABBA AGF deadlocks because a future allocation attempt in this
* transaction may attempt to lock a lower number AGF.
*
* We can't release the AGF until the transaction is commited, so at
* We can't release the AGF until the transaction is committed, so at
* this point we must update the "first allocation" tracker to point at
* this AG if the tracker is empty or points to a lower AG. This allows
* the next allocation attempt to be modified appropriately to avoid

View File

@ -1715,7 +1715,7 @@ xfs_attr3_leaf_add_work(
/*
* This freemap entry starts at the old end of the
* leaf entry array, so we need to adjust its base
* upward to accomodate the larger array.
* upward to accommodate the larger array.
*/
diff = sizeof(struct xfs_attr_leaf_entry);
} else if (ichdr->freemap[i].size > 0 &&

View File

@ -83,7 +83,7 @@
#define XFS_RANDOM_DEFAULT 100
/*
* Table of errror injection knobs. The parameters to the XFS_ERRTAG macro are:
* Table of error injection knobs. The parameters to the XFS_ERRTAG macro are:
* 1. The XFS_ERRTAG_ flag but without the prefix;
* 2. The name of the sysfs knob; and
* 3. The default value for the knob.

View File

@ -395,7 +395,7 @@ xfs_exchmaps_one_step(
/*
* Re-add both mappings. We exchange the file offsets between the two
* maps and add the opposite map, which has the effect of filling the
* logical offsets we just unmapped, but with with the physical mapping
* logical offsets we just unmapped, but with the physical mapping
* information exchanged.
*/
swap(irec1->br_startoff, irec2->br_startoff);
@ -959,16 +959,6 @@ xmi_can_exchange_reflink_flags(
{
struct xfs_mount *mp = req->ip1->i_mount;
/*
* The INO1_WRITTEN optimization can skip exchanging hole and
* unwritten mappings, which means we cannot guarantee that all
* shared extents actually moved to the other file. Clearing the
* reflink flag of an inode that still holds shared extents breaks
* the CoW write path, so refuse to exchange the flags in that case.
*/
if (req->flags & XFS_EXCHMAPS_INO1_WRITTEN)
return false;
/*
* The INO1_WRITTEN optimization can skip exchanging hole and
* unwritten mappings, which means we cannot guarantee that all

View File

@ -1051,7 +1051,7 @@ enum xfs_dinode_fmt {
* block is 1KB in size.
*
* With XFS_MAX_EXTCNT_DATA_FORK_SMALL representing maximum extent count and
* with 1KB sized blocks, a file can reach upto,
* with 1KB sized blocks, a file can reach up to,
* 1KB * (2^31) = 2TB
*
* This is much larger than the theoretical maximum size of a directory

View File

@ -626,7 +626,7 @@ xfs_dinode_verify(
* have di_nlink track the link count, even if the actual filesystem
* only supported V1 inodes (i.e. di_onlink). When writing out the
* ondisk inode, it would set both the ondisk di_nlink and di_onlink to
* the the incore di_nlink value, which is why we cannot check for
* the incore di_nlink value, which is why we cannot check for
* di_nlink==0 on a V1 inode. V2/3 inodes would get written out with
* di_onlink==0, so we can check that.
*/

View File

@ -297,14 +297,14 @@ xfs_metafile_resv_init(
goto out_unlock;
/*
* Space taken by the per-AG metadata btrees are accounted on-disk as
* used space. We therefore only hide the space that is reserved but
* not used by the trees.
* Space taken by metadata btrees are accounted on-disk as used space.
* We therefore only hide the space that is reserved but not used by
* the trees.
*/
if (used > target)
target = used;
else if (target > dblocks_avail)
target = dblocks_avail;
target = max(dblocks_avail, used);
hidden_space = target - used;
error = xfs_dec_fdblocks(mp, hidden_space, true);

View File

@ -617,7 +617,7 @@ xfs_rtrefcountbt_from_disk(
fpp = xfs_rtrefcount_droot_ptr_addr(dblock, 1, maxrecs);
tpp = xfs_rtrefcount_broot_ptr_addr(mp, rblock, 1, rblocklen);
numrecs = be16_to_cpu(dblock->bb_numrecs);
memcpy(tkp, fkp, 2 * sizeof(*fkp) * numrecs);
memcpy(tkp, fkp, sizeof(*fkp) * numrecs);
memcpy(tpp, fpp, sizeof(*fpp) * numrecs);
} else {
frp = xfs_rtrefcount_droot_rec_addr(dblock, 1);
@ -703,7 +703,7 @@ xfs_rtrefcountbt_to_disk(
fpp = xfs_rtrefcount_broot_ptr_addr(mp, rblock, 1, rblocklen);
tpp = xfs_rtrefcount_droot_ptr_addr(dblock, 1, maxrecs);
numrecs = be16_to_cpu(rblock->bb_numrecs);
memcpy(tkp, fkp, 2 * sizeof(*fkp) * numrecs);
memcpy(tkp, fkp, sizeof(*fkp) * numrecs);
memcpy(tpp, fpp, sizeof(*fpp) * numrecs);
} else {
frp = xfs_rtrefcount_rec_addr(rblock, 1);

View File

@ -1369,7 +1369,7 @@ xrep_iunlink_mark_ondisk(
/*
* Walk an iunlink bucket's inode list. For each inode that should be on this
* chain, clear its entry in in iunlink_bmp because it's ok and we don't need
* chain, clear its entry in iunlink_bmp because it's ok and we don't need
* to touch it further.
*/
STATIC int

View File

@ -338,7 +338,7 @@ xrep_cntbt_extent_cmp(
}
/*
* Sort the free extents by length so so that we can put the records into the
* Sort the free extents by length so that we can put the records into the
* cntbt in the correct order. Don't let userspace kill us if we're resorting
* after allocating btree blocks.
*/

View File

@ -122,8 +122,8 @@ xbitmap64_set(
uint64_t start,
uint64_t len)
{
struct xbitmap64_node *left;
struct xbitmap64_node *right;
struct xbitmap64_node *left = NULL;
struct xbitmap64_node *right = NULL;
uint64_t last = start + len - 1;
int error;
@ -131,6 +131,7 @@ xbitmap64_set(
left = xbitmap64_tree_iter_first(&bitmap->xb_root, start, last);
if (left && left->bn_start <= start && left->bn_last >= last)
return 0;
left = NULL;
/* Clear out everything in the range we want to set. */
error = xbitmap64_clear(bitmap, start, len);
@ -138,11 +139,15 @@ xbitmap64_set(
return error;
/* Do we have a left-adjacent extent? */
left = xbitmap64_tree_iter_first(&bitmap->xb_root, start - 1, start - 1);
if (start > 0)
left = xbitmap64_tree_iter_first(&bitmap->xb_root, start - 1,
start - 1);
ASSERT(!left || left->bn_last + 1 == start);
/* Do we have a right-adjacent extent? */
right = xbitmap64_tree_iter_first(&bitmap->xb_root, last + 1, last + 1);
if (last < U64_MAX)
right = xbitmap64_tree_iter_first(&bitmap->xb_root, last + 1,
last + 1);
ASSERT(!right || right->bn_start == last + 1);
if (left && right) {
@ -397,8 +402,8 @@ xbitmap32_set(
uint32_t start,
uint32_t len)
{
struct xbitmap32_node *left;
struct xbitmap32_node *right;
struct xbitmap32_node *left = NULL;
struct xbitmap32_node *right = NULL;
uint32_t last = start + len - 1;
int error;
@ -406,6 +411,7 @@ xbitmap32_set(
left = xbitmap32_tree_iter_first(&bitmap->xb_root, start, last);
if (left && left->bn_start <= start && left->bn_last >= last)
return 0;
left = NULL;
/* Clear out everything in the range we want to set. */
error = xbitmap32_clear(bitmap, start, len);
@ -413,11 +419,15 @@ xbitmap32_set(
return error;
/* Do we have a left-adjacent extent? */
left = xbitmap32_tree_iter_first(&bitmap->xb_root, start - 1, start - 1);
if (start > 0)
left = xbitmap32_tree_iter_first(&bitmap->xb_root, start - 1,
start - 1);
ASSERT(!left || left->bn_last + 1 == start);
/* Do we have a right-adjacent extent? */
right = xbitmap32_tree_iter_first(&bitmap->xb_root, last + 1, last + 1);
if (last < U32_MAX)
right = xbitmap32_tree_iter_first(&bitmap->xb_root, last + 1,
last + 1);
ASSERT(!right || right->bn_start == last + 1);
if (left && right) {

View File

@ -492,7 +492,7 @@ xchk_directory_data_bestfree(
goto out;
xchk_buffer_recheck(sc, bp);
if (xfs_has_crc(sc->mp)) {
if (!is_block && xfs_has_crc(sc->mp)) {
struct xfs_dir3_data_hdr *hdr3 = bp->b_addr;
if (hdr3->pad)

View File

@ -1021,7 +1021,7 @@ xchk_dirtree(
return error;
}
/* Does the directory targetted by this scrub have no parents? */
/* Does the directory targeted by this scrub have no parents? */
bool
xchk_dirtree_parentless(const struct xchk_dirtree *dl)
{

View File

@ -473,6 +473,9 @@ xrep_findparent_from_dcache(
pip = igrab(d_inode(parent));
dput(parent);
if (!pip)
goto out_dput;
if (S_ISDIR(pip->i_mode)) {
ret = pip->i_ino;
trace_xrep_findparent_from_dcache(sc->ip, ret);

View File

@ -202,9 +202,9 @@ xchk_update_health(
* there's no sick flag defined for it, so we branch here ahead of the
* mask check.
*/
if (sc->sm->sm_type == XFS_SCRUB_TYPE_HEALTHY &&
!(sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) {
xchk_mark_all_healthy(sc->mp);
if (sc->sm->sm_type == XFS_SCRUB_TYPE_HEALTHY) {
if (!(sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
xchk_mark_all_healthy(sc->mp);
return;
}

View File

@ -607,7 +607,7 @@ xchk_dinode(
}
/* di_forkoff */
if (XFS_DFORK_BOFF(dip) >= mp->m_sb.sb_inodesize)
if (dip->di_forkoff >= (XFS_LITINO(mp) >> 3))
xchk_ino_set_corrupt(sc, ino);
if (naextents != 0 && dip->di_forkoff == 0)
xchk_ino_set_corrupt(sc, ino);

View File

@ -1702,7 +1702,7 @@ xrep_inode_blockcounts(
&acount);
if (error)
return error;
if (count >= sc->mp->m_sb.sb_dblocks)
if (acount >= sc->mp->m_sb.sb_dblocks)
return -EFSCORRUPTED;
error = xrep_ino_ensure_extent_count(sc, XFS_ATTR_FORK,
nextents);

View File

@ -193,9 +193,11 @@ xrep_newbt_add_blocks(
struct xrep_newbt_resv *resv;
int error;
resv = kmalloc_obj(struct xrep_newbt_resv, XCHK_GFP_FLAGS);
if (!resv)
return -ENOMEM;
/*
* We have no way to clean up the allocated space *and* return an
* ENOMEM if we fail to allocate this control structure.
*/
resv = kmalloc_obj(struct xrep_newbt_resv, GFP_KERNEL | __GFP_NOFAIL);
INIT_LIST_HEAD(&resv->list);
resv->agbno = XFS_FSB_TO_AGBNO(mp, args->fsbno);

View File

@ -192,12 +192,16 @@ xrep_orphanage_create(
/* Make sure the orphanage is owned by root. */
error = xrep_chown_orphanage(sc, XFS_I(orphanage_inode));
if (error)
goto out_dput_orphanage;
goto out_rele_orphanage;
/* Stash the reference for later and bail out. */
sc->orphanage = XFS_I(orphanage_inode);
sc->orphanage_ilock_flags = 0;
orphanage_inode = NULL;
out_rele_orphanage:
if (orphanage_inode)
xchk_irele(sc, XFS_I(orphanage_inode));
out_dput_orphanage:
end_creating(orphanage_dentry);
out_dput_root:

View File

@ -172,7 +172,7 @@ static inline bool xreap_is_dirty(const struct xreap_state *rs)
}
/*
* Decide if we need to roll the transaction to clear out the the log
* Decide if we need to roll the transaction to clear out the log
* reservation that we allocated to buffer invalidations.
*/
static inline bool xreap_want_binval_roll(const struct xreap_state *rs)

View File

@ -399,6 +399,7 @@ xrep_calc_rtgroup_resblks(
struct xfs_mount *mp = sc->mp;
struct xfs_scrub_metadata *sm = sc->sm;
uint64_t usedlen;
xfs_extlen_t refcbt_sz = 0;
xfs_extlen_t rmapbt_sz = 0;
if (!(sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR))
@ -411,13 +412,27 @@ xrep_calc_rtgroup_resblks(
usedlen = xfs_rtbxlen_to_blen(mp, xfs_rtgroup_extents(mp, sm->sm_agno));
ASSERT(usedlen <= XFS_MAX_RGBLOCKS);
if (xfs_has_reflink(mp))
refcbt_sz = xfs_rtrefcountbt_calc_size(mp, usedlen);
if (xfs_has_rmapbt(mp))
rmapbt_sz = xfs_rtrmapbt_calc_size(mp, usedlen);
trace_xrep_calc_rtgroup_resblks_btsize(mp, sm->sm_agno, usedlen,
rmapbt_sz);
/*
* Guess how many blocks we need to rebuild the rmapbt. For
* non-reflink filesystems we can't have more records than used blocks.
* However, with reflink it's possible to have more than one rmap
* record per rtgroup block. We don't know how many rmaps there could
* be in the rtgroup, so we start off with what we hope is an generous
* over-estimation.
*/
if (refcbt_sz > 0 && rmapbt_sz > 0)
rmapbt_sz *= 2;
return rmapbt_sz;
trace_xrep_calc_rtgroup_resblks_btsize(mp, sm->sm_agno, usedlen,
rmapbt_sz, refcbt_sz);
return max(rmapbt_sz, refcbt_sz);
}
#endif /* CONFIG_XFS_RT */

View File

@ -493,11 +493,18 @@ xchk_rmapbt_walk_ag_metadata(
* If there's an error, set XFAIL and disable the bitmap
* cross-referencing checks, but proceed with the scrub anyway.
*/
if (error)
xchk_btree_xref_process_error(sc, sc->sa.rmap_cur,
sc->sa.rmap_cur->bc_nlevels - 1, &error);
else
cr->bitmaps_complete = true;
if (error) {
if (!xchk_btree_xref_process_error(sc, sc->sa.rmap_cur,
sc->sa.rmap_cur->bc_nlevels - 1, &error)) {
/* only set incomplete if we didn't set xfail */
if (error)
xchk_set_incomplete(sc);
}
return 0;
}
cr->bitmaps_complete = true;
return 0;
}
@ -567,7 +574,8 @@ xchk_rmapbt(
if (error)
goto out;
xchk_rmapbt_check_bitmaps(sc, cr);
if (cr->bitmaps_complete)
xchk_rmapbt_check_bitmaps(sc, cr);
out:
xagb_bitmap_destroy(&cr->refcbt_owned);

View File

@ -1109,6 +1109,7 @@ xrep_rmap_try_reserve(
return error;
error = xfs_agfl_walk(sc->mp, agf, agfl_bp, xrep_rmap_walk_agfl, &ra);
xfs_trans_brelse(sc->tp, agfl_bp);
if (error)
return error;

View File

@ -40,7 +40,7 @@ static inline int xchk_maybe_relax(struct xchk_relax *widget)
return 0;
widget->resched_nr = 0;
if (unlikely(widget->next_resched <= jiffies)) {
if (unlikely(time_after_eq(jiffies, widget->next_resched))) {
cond_resched();
widget->next_resched = XCHK_RELAX_NEXT;
}

View File

@ -2376,25 +2376,29 @@ TRACE_EVENT(xrep_calc_ag_resblks_btsize,
#ifdef CONFIG_XFS_RT
TRACE_EVENT(xrep_calc_rtgroup_resblks_btsize,
TP_PROTO(struct xfs_mount *mp, xfs_rgnumber_t rgno,
xfs_rgblock_t usedlen, xfs_rgblock_t rmapbt_sz),
TP_ARGS(mp, rgno, usedlen, rmapbt_sz),
xfs_rgblock_t usedlen, xfs_rgblock_t rmapbt_sz,
xfs_rgblock_t refcbt_sz),
TP_ARGS(mp, rgno, usedlen, rmapbt_sz, refcbt_sz),
TP_STRUCT__entry(
__field(dev_t, dev)
__field(xfs_rgnumber_t, rgno)
__field(xfs_rgblock_t, usedlen)
__field(xfs_rgblock_t, rmapbt_sz)
__field(xfs_rgblock_t, refcbt_sz)
),
TP_fast_assign(
__entry->dev = mp->m_super->s_dev;
__entry->rgno = rgno;
__entry->usedlen = usedlen;
__entry->rmapbt_sz = rmapbt_sz;
__entry->refcbt_sz = refcbt_sz;
),
TP_printk("dev %d:%d rgno 0x%x usedlen %u rmapbt %u",
TP_printk("dev %d:%d rgno 0x%x usedlen %u rmapbt %u refcountbt %u",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->rgno,
__entry->usedlen,
__entry->rmapbt_sz)
__entry->rmapbt_sz,
__entry->refcbt_sz)
);
#endif /* CONFIG_XFS_RT */

View File

@ -339,7 +339,7 @@ xfs_bmap_update_get_group(
/*
* Bump the intent count on behalf of the deferred rmap and refcount
* intent items that that we can queue when we finish this bmap work.
* intent items that we can queue when we finish this bmap work.
* This new intent item will bump the intent count before the bmap
* intent drops the intent count, ensuring that the intent count
* remains nonzero across the transaction roll.

View File

@ -139,10 +139,14 @@ xfs_qm_adjust_dqlimits(
dq->q_ino.softlimit = defq->ino.soft;
if (!dq->q_ino.hardlimit)
dq->q_ino.hardlimit = defq->ino.hard;
if (!dq->q_rtb.softlimit)
if (!dq->q_rtb.softlimit) {
dq->q_rtb.softlimit = defq->rtb.soft;
if (!dq->q_rtb.hardlimit)
prealloc = 1;
}
if (!dq->q_rtb.hardlimit) {
dq->q_rtb.hardlimit = defq->rtb.hard;
prealloc = 1;
}
if (prealloc)
xfs_dquot_set_prealloc_limits(dq);

View File

@ -633,6 +633,9 @@ xfs_exchrange_prep(
if (error)
return error;
if (fxr->flags & XFS_EXCHANGE_RANGE_DRY_RUN)
return 0;
trace_xfs_exchrange_flush(fxr, ip1, ip2);
/* Flush the relevant ranges of both files. */
@ -709,9 +712,11 @@ xfs_exchrange_contents(
* other file write would do. This may involve turning on support for
* logged xattrs if either file has security capabilities.
*/
error = xfs_exchange_range_finish(fxr);
if (error)
goto out_unlock;
if (!(fxr->flags & XFS_EXCHANGE_RANGE_DRY_RUN)) {
error = xfs_exchange_range_finish(fxr);
if (error)
goto out_unlock;
}
out_unlock:
xfs_iunlock2_io_mmap(ip1, ip2);
@ -902,7 +907,7 @@ xfs_ioc_commit_range(
if (copy_from_user(&args, argp, sizeof(args)))
return -EFAULT;
if (args.flags & ~XFS_EXCHANGE_RANGE_ALL_FLAGS)
if (args.pad || (args.flags & ~XFS_EXCHANGE_RANGE_ALL_FLAGS))
return -EINVAL;
if (kern_f->magic != XCR_FRESH_MAGIC)
return -EBUSY;

View File

@ -247,7 +247,9 @@ xfs_healthmon_merge_events(
case XFS_HEALTHMON_DIOWRITE:
case XFS_HEALTHMON_DATALOST:
/* logically adjacent file ranges can merge */
if (existing->fino != new->fino || existing->fgen != new->fgen)
if (existing->fino != new->fino ||
existing->fgen != new->fgen ||
existing->error != new->error)
return false;
if (existing->fpos + existing->flen == new->fpos) {

View File

@ -1653,7 +1653,7 @@ xfs_blockgc_free_dquots(
do_work = true;
}
if (XFS_IS_UQUOTA_ENFORCED(mp) && gdqp && xfs_dquot_lowsp(gdqp)) {
if (XFS_IS_GQUOTA_ENFORCED(mp) && gdqp && xfs_dquot_lowsp(gdqp)) {
icw.icw_gid = make_kgid(mp->m_super->s_user_ns, gdqp->q_id);
icw.icw_flags |= XFS_ICWALK_FLAG_GID;
do_work = true;

View File

@ -2669,7 +2669,7 @@ xfs_irele(
}
/*
* Ensure all commited transactions touching the inode are written to the log.
* Ensure all committed transactions touching the inode are written to the log.
*/
int
xfs_log_force_inode(

View File

@ -1370,7 +1370,7 @@ xlog_cil_cleanup_whiteouts(
* allocation context. However, we do not want to block on memory reclaim
* recursing back into the filesystem because this push may have been triggered
* by memory reclaim itself. Hence we really need to run under full GFP_NOFS
* contraints here.
* constraints here.
*/
static void
xlog_cil_push_work(

View File

@ -2736,12 +2736,13 @@ xlog_recover_iunlink_bucket(
{
struct xfs_mount *mp = pag_mount(pag);
struct xfs_inode *prev_ip = NULL;
struct xfs_inode *ip;
xfs_agino_t prev_agino, agino;
int error = 0;
agino = be32_to_cpu(agi->agi_unlinked[bucket]);
while (agino != NULLAGINO) {
struct xfs_inode *ip;
error = xfs_iget(mp, NULL, xfs_agino_to_ino(pag, agino), 0, 0,
&ip);
if (error)
@ -2750,11 +2751,11 @@ xlog_recover_iunlink_bucket(
ASSERT(VFS_I(ip)->i_nlink == 0);
ASSERT(VFS_I(ip)->i_mode != 0);
xfs_iflags_clear(ip, XFS_IRECOVERY);
agino = ip->i_next_unlinked;
if (prev_ip) {
ip->i_prev_unlinked = prev_agino;
xfs_irele(prev_ip);
prev_ip = NULL;
/*
* Ensure the inode is removed from the unlinked list
@ -2766,18 +2767,20 @@ xlog_recover_iunlink_bucket(
* complete.
*/
error = xfs_inodegc_flush(mp);
if (error)
break;
if (error) {
xfs_irele(ip);
return error;
}
}
prev_agino = agino;
agino = ip->i_next_unlinked;
prev_ip = ip;
}
if (prev_ip) {
int error2;
ip->i_prev_unlinked = prev_agino;
xfs_irele(prev_ip);
error2 = xfs_inodegc_flush(mp);

View File

@ -153,7 +153,7 @@ static inline void delay(long ticks)
/*
* XFS wrapper structure for sysfs support. It depends on external data
* structures and is embedded in various internal data structures to implement
* the XFS sysfs object heirarchy. Define it here for broad access throughout
* the XFS sysfs object hierarchy. Define it here for broad access throughout
* the codebase.
*/
struct xfs_kobj {

View File

@ -1432,16 +1432,22 @@ xfs_qm_flush_one(
error = xfs_dquot_use_attached_buf(dqp, &bp);
if (error)
goto out_unlock;
goto out_dqflock;
if (!bp) {
error = -EFSCORRUPTED;
goto out_unlock;
goto out_dqflock;
}
error = xfs_qm_dqflush(dqp, bp);
if (!error)
xfs_buf_delwri_queue(bp, buffer_list);
xfs_buf_relse(bp);
mutex_unlock(&dqp->q_qlock);
xfs_qm_dqrele(dqp);
return error;
out_dqflock:
xfs_dqfunlock(dqp);
out_unlock:
mutex_unlock(&dqp->q_qlock);
xfs_qm_dqrele(dqp);

View File

@ -508,6 +508,7 @@ xfs_refcount_recover_work(
struct xfs_cui_log_item *cuip = CUI_ITEM(lip);
struct xfs_trans *tp;
struct xfs_mount *mp = lip->li_log->l_mp;
unsigned int dblocks;
bool isrt = xfs_cui_item_isrt(lip);
int i;
int error = 0;
@ -543,8 +544,11 @@ xfs_refcount_recover_work(
* full btree split on either end of the refcount range.
*/
resv = xlog_recover_resv(&M_RES(mp)->tr_itruncate);
error = xfs_trans_alloc(mp, &resv, mp->m_refc_maxlevels * 2, 0,
XFS_TRANS_RESERVE, &tp);
if (isrt)
dblocks = mp->m_rtrefc_maxlevels * 2;
else
dblocks = mp->m_refc_maxlevels * 2;
error = xfs_trans_alloc(mp, &resv, dblocks, 0, XFS_TRANS_RESERVE, &tp);
if (error)
return error;

View File

@ -48,9 +48,6 @@ extern int xfs_reflink_end_cow(struct xfs_inode *ip, xfs_off_t offset,
int xfs_reflink_end_atomic_cow(struct xfs_inode *ip, xfs_off_t offset,
xfs_off_t count);
extern int xfs_reflink_recover_cow(struct xfs_mount *mp);
extern loff_t xfs_reflink_remap_range(struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out, loff_t len,
unsigned int remap_flags);
extern int xfs_reflink_inode_has_shared_extents(struct xfs_trans *tp,
struct xfs_inode *ip, bool *has_shared);
extern int xfs_reflink_clear_inode_flag(struct xfs_inode *ip,

View File

@ -573,6 +573,7 @@ xfs_rmap_recover_work(
struct xfs_rui_log_item *ruip = RUI_ITEM(lip);
struct xfs_trans *tp;
struct xfs_mount *mp = lip->li_log->l_mp;
unsigned int dblocks;
bool isrt = xfs_rui_item_isrt(lip);
int i;
int error = 0;
@ -596,8 +597,11 @@ xfs_rmap_recover_work(
}
resv = xlog_recover_resv(&M_RES(mp)->tr_itruncate);
error = xfs_trans_alloc(mp, &resv, mp->m_rmap_maxlevels, 0,
XFS_TRANS_RESERVE, &tp);
if (isrt)
dblocks = mp->m_rtrmap_maxlevels;
else
dblocks = mp->m_rmap_maxlevels;
error = xfs_trans_alloc(mp, &resv, dblocks, 0, XFS_TRANS_RESERVE, &tp);
if (error)
return error;

View File

@ -820,7 +820,7 @@ xfs_get_cached_zone(
spin_unlock(&ip->i_flags_lock);
}
if (!atomic_inc_not_zero(&oz->oz_ref))
if (oz && !atomic_inc_not_zero(&oz->oz_ref))
oz = NULL;
out_unlock:
rcu_read_unlock();
@ -828,7 +828,7 @@ xfs_get_cached_zone(
}
/*
* Stash our zone in the inode so that is is reused for future allocations.
* Stash our zone in the inode so that it is reused for future allocations.
*
* The open_zone structure will be pinned until either the inode is freed or
* until the cached open zone is replaced with a different one because the

View File

@ -46,7 +46,7 @@
* before remapping.
*
* Once a zone does not contain any valid data, be that through GC or user
* block removal, it is queued for for a zone reset. The reset operation
* block removal, it is queued for a zone reset. The reset operation
* carefully ensures that the RT device cache is flushed and all transactions
* referencing the rmap have been committed to disk.
*/