mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 12:44:03 +02:00
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:
commit
f0100363d8
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 &&
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user