mirror of
https://github.com/torvalds/linux.git
synced 2024-11-29 15:41:36 +00:00
New code for 6.3-rc1:
* Eliminate repeated boxing and unboxing of log item parameters.
* Clean up some confusing variable names in the log item code.
* Fix a deadlock when doing unwritten extent conversion that causes a
bmbt split when there are sustained memory shortages and the worker
pool runs out of worker threads.
* Fix the panic_mask debug knob not being able to trigger on verifier
errors.
* Constify kobj_type objects.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
-----BEGIN PGP SIGNATURE-----
iHUEABYKAB0WIQQ2qTKExjcn+O1o2YRKO3ySh0YRpgUCY+Z6BwAKCRBKO3ySh0YR
pkQJAQCjkzXqZuj8WH/g22S01smT51QhmX+1ubLdzMYSvRvrKQD+MlH74EcgurQD
GhgCWJh6dBTx1nICKpCXYgVD9Glvowc=
=J2Xw
-----END PGP SIGNATURE-----
Merge tag 'xfs-6.3-merge-2' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
Pull xfs updates from Darrick Wong:
"There's a couple of bug fixes, some cleanups for inconsistent variable
names and reduction of struct boxing and unboxing in the logging code.
More work is pending, which will begin reworking allocation group
lifetimes and finally replace confusing indirect calls to the
allocator with actual ... function calls. But I want to let that
experience another week of testing.
Summary:
- Eliminate repeated boxing and unboxing of log item parameters
- Clean up some confusing variable names in the log item code
- Fix a deadlock when doing unwritten extent conversion that causes a
bmbt split when there are sustained memory shortages and the worker
pool runs out of worker threads
- Fix the panic_mask debug knob not being able to trigger on verifier
errors
- Constify kobj_type objects"
* tag 'xfs-6.3-merge-2' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux:
xfs: revert commit 8954c44ff4
xfs: make kobj_type structures constant
xfs: allow setting full range of panic tags
xfs: don't use BMBT btree split workers for IO completion
xfs: fix confusing variable names in xfs_refcount_item.c
xfs: pass refcount intent directly through the log intent code
xfs: fix confusing variable names in xfs_rmap_item.c
xfs: pass rmap space mapping directly through the log intent code
xfs: fix confusing xfs_extent_item variable names
xfs: pass xfs_extent_free_item directly through the log intent code
xfs: fix confusing variable names in xfs_bmap_item.c
xfs: pass the xfs_bmbt_irec directly through the log intent code
xfs: use strscpy() to instead of strncpy()
This commit is contained in:
commit
28e335208c
@ -296,7 +296,7 @@ The following sysctls are available for the XFS filesystem:
|
||||
XFS_ERRLEVEL_LOW: 1
|
||||
XFS_ERRLEVEL_HIGH: 5
|
||||
|
||||
fs.xfs.panic_mask (Min: 0 Default: 0 Max: 256)
|
||||
fs.xfs.panic_mask (Min: 0 Default: 0 Max: 511)
|
||||
Causes certain error conditions to call BUG(). Value is a bitmask;
|
||||
OR together the tags which represent errors which should cause panics:
|
||||
|
||||
|
@ -2472,20 +2472,20 @@ xfs_defer_agfl_block(
|
||||
struct xfs_owner_info *oinfo)
|
||||
{
|
||||
struct xfs_mount *mp = tp->t_mountp;
|
||||
struct xfs_extent_free_item *new; /* new element */
|
||||
struct xfs_extent_free_item *xefi;
|
||||
|
||||
ASSERT(xfs_extfree_item_cache != NULL);
|
||||
ASSERT(oinfo != NULL);
|
||||
|
||||
new = kmem_cache_zalloc(xfs_extfree_item_cache,
|
||||
xefi = kmem_cache_zalloc(xfs_extfree_item_cache,
|
||||
GFP_KERNEL | __GFP_NOFAIL);
|
||||
new->xefi_startblock = XFS_AGB_TO_FSB(mp, agno, agbno);
|
||||
new->xefi_blockcount = 1;
|
||||
new->xefi_owner = oinfo->oi_owner;
|
||||
xefi->xefi_startblock = XFS_AGB_TO_FSB(mp, agno, agbno);
|
||||
xefi->xefi_blockcount = 1;
|
||||
xefi->xefi_owner = oinfo->oi_owner;
|
||||
|
||||
trace_xfs_agfl_free_defer(mp, agno, 0, agbno, 1);
|
||||
|
||||
xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_AGFL_FREE, &new->xefi_list);
|
||||
xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_AGFL_FREE, &xefi->xefi_list);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2500,7 +2500,7 @@ __xfs_free_extent_later(
|
||||
const struct xfs_owner_info *oinfo,
|
||||
bool skip_discard)
|
||||
{
|
||||
struct xfs_extent_free_item *new; /* new element */
|
||||
struct xfs_extent_free_item *xefi;
|
||||
#ifdef DEBUG
|
||||
struct xfs_mount *mp = tp->t_mountp;
|
||||
xfs_agnumber_t agno;
|
||||
@ -2519,27 +2519,27 @@ __xfs_free_extent_later(
|
||||
#endif
|
||||
ASSERT(xfs_extfree_item_cache != NULL);
|
||||
|
||||
new = kmem_cache_zalloc(xfs_extfree_item_cache,
|
||||
xefi = kmem_cache_zalloc(xfs_extfree_item_cache,
|
||||
GFP_KERNEL | __GFP_NOFAIL);
|
||||
new->xefi_startblock = bno;
|
||||
new->xefi_blockcount = (xfs_extlen_t)len;
|
||||
xefi->xefi_startblock = bno;
|
||||
xefi->xefi_blockcount = (xfs_extlen_t)len;
|
||||
if (skip_discard)
|
||||
new->xefi_flags |= XFS_EFI_SKIP_DISCARD;
|
||||
xefi->xefi_flags |= XFS_EFI_SKIP_DISCARD;
|
||||
if (oinfo) {
|
||||
ASSERT(oinfo->oi_offset == 0);
|
||||
|
||||
if (oinfo->oi_flags & XFS_OWNER_INFO_ATTR_FORK)
|
||||
new->xefi_flags |= XFS_EFI_ATTR_FORK;
|
||||
xefi->xefi_flags |= XFS_EFI_ATTR_FORK;
|
||||
if (oinfo->oi_flags & XFS_OWNER_INFO_BMBT_BLOCK)
|
||||
new->xefi_flags |= XFS_EFI_BMBT_BLOCK;
|
||||
new->xefi_owner = oinfo->oi_owner;
|
||||
xefi->xefi_flags |= XFS_EFI_BMBT_BLOCK;
|
||||
xefi->xefi_owner = oinfo->oi_owner;
|
||||
} else {
|
||||
new->xefi_owner = XFS_RMAP_OWN_NULL;
|
||||
xefi->xefi_owner = XFS_RMAP_OWN_NULL;
|
||||
}
|
||||
trace_xfs_bmap_free_defer(tp->t_mountp,
|
||||
XFS_FSB_TO_AGNO(tp->t_mountp, bno), 0,
|
||||
XFS_FSB_TO_AGBNO(tp->t_mountp, bno), len);
|
||||
xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_FREE, &new->xefi_list);
|
||||
xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_FREE, &xefi->xefi_list);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -6146,39 +6146,37 @@ xfs_bmap_unmap_extent(
|
||||
int
|
||||
xfs_bmap_finish_one(
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_inode *ip,
|
||||
enum xfs_bmap_intent_type type,
|
||||
int whichfork,
|
||||
xfs_fileoff_t startoff,
|
||||
xfs_fsblock_t startblock,
|
||||
xfs_filblks_t *blockcount,
|
||||
xfs_exntst_t state)
|
||||
struct xfs_bmap_intent *bi)
|
||||
{
|
||||
struct xfs_bmbt_irec *bmap = &bi->bi_bmap;
|
||||
int error = 0;
|
||||
|
||||
ASSERT(tp->t_firstblock == NULLFSBLOCK);
|
||||
|
||||
trace_xfs_bmap_deferred(tp->t_mountp,
|
||||
XFS_FSB_TO_AGNO(tp->t_mountp, startblock), type,
|
||||
XFS_FSB_TO_AGBNO(tp->t_mountp, startblock),
|
||||
ip->i_ino, whichfork, startoff, *blockcount, state);
|
||||
XFS_FSB_TO_AGNO(tp->t_mountp, bmap->br_startblock),
|
||||
bi->bi_type,
|
||||
XFS_FSB_TO_AGBNO(tp->t_mountp, bmap->br_startblock),
|
||||
bi->bi_owner->i_ino, bi->bi_whichfork,
|
||||
bmap->br_startoff, bmap->br_blockcount,
|
||||
bmap->br_state);
|
||||
|
||||
if (WARN_ON_ONCE(whichfork != XFS_DATA_FORK))
|
||||
if (WARN_ON_ONCE(bi->bi_whichfork != XFS_DATA_FORK))
|
||||
return -EFSCORRUPTED;
|
||||
|
||||
if (XFS_TEST_ERROR(false, tp->t_mountp,
|
||||
XFS_ERRTAG_BMAP_FINISH_ONE))
|
||||
return -EIO;
|
||||
|
||||
switch (type) {
|
||||
switch (bi->bi_type) {
|
||||
case XFS_BMAP_MAP:
|
||||
error = xfs_bmapi_remap(tp, ip, startoff, *blockcount,
|
||||
startblock, 0);
|
||||
*blockcount = 0;
|
||||
error = xfs_bmapi_remap(tp, bi->bi_owner, bmap->br_startoff,
|
||||
bmap->br_blockcount, bmap->br_startblock, 0);
|
||||
bmap->br_blockcount = 0;
|
||||
break;
|
||||
case XFS_BMAP_UNMAP:
|
||||
error = __xfs_bunmapi(tp, ip, startoff, blockcount,
|
||||
XFS_BMAPI_REMAP, 1);
|
||||
error = __xfs_bunmapi(tp, bi->bi_owner, bmap->br_startoff,
|
||||
&bmap->br_blockcount, XFS_BMAPI_REMAP, 1);
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
|
@ -234,10 +234,7 @@ struct xfs_bmap_intent {
|
||||
struct xfs_bmbt_irec bi_bmap;
|
||||
};
|
||||
|
||||
int xfs_bmap_finish_one(struct xfs_trans *tp, struct xfs_inode *ip,
|
||||
enum xfs_bmap_intent_type type, int whichfork,
|
||||
xfs_fileoff_t startoff, xfs_fsblock_t startblock,
|
||||
xfs_filblks_t *blockcount, xfs_exntst_t state);
|
||||
int xfs_bmap_finish_one(struct xfs_trans *tp, struct xfs_bmap_intent *bi);
|
||||
void xfs_bmap_map_extent(struct xfs_trans *tp, struct xfs_inode *ip,
|
||||
struct xfs_bmbt_irec *imap);
|
||||
void xfs_bmap_unmap_extent(struct xfs_trans *tp, struct xfs_inode *ip,
|
||||
|
@ -2913,9 +2913,22 @@ xfs_btree_split_worker(
|
||||
}
|
||||
|
||||
/*
|
||||
* BMBT split requests often come in with little stack to work on. Push
|
||||
* BMBT split requests often come in with little stack to work on so we push
|
||||
* them off to a worker thread so there is lots of stack to use. For the other
|
||||
* btree types, just call directly to avoid the context switch overhead here.
|
||||
*
|
||||
* Care must be taken here - the work queue rescuer thread introduces potential
|
||||
* AGF <> worker queue deadlocks if the BMBT block allocation has to lock new
|
||||
* AGFs to allocate blocks. A task being run by the rescuer could attempt to
|
||||
* lock an AGF that is already locked by a task queued to run by the rescuer,
|
||||
* resulting in an ABBA deadlock as the rescuer cannot run the lock holder to
|
||||
* release it until the current thread it is running gains the lock.
|
||||
*
|
||||
* To avoid this issue, we only ever queue BMBT splits that don't have an AGF
|
||||
* already locked to allocate from. The only place that doesn't hold an AGF
|
||||
* locked is unwritten extent conversion at IO completion, but that has already
|
||||
* been offloaded to a worker thread and hence has no stack consumption issues
|
||||
* we have to worry about.
|
||||
*/
|
||||
STATIC int /* error */
|
||||
xfs_btree_split(
|
||||
@ -2929,7 +2942,8 @@ xfs_btree_split(
|
||||
struct xfs_btree_split_args args;
|
||||
DECLARE_COMPLETION_ONSTACK(done);
|
||||
|
||||
if (cur->bc_btnum != XFS_BTNUM_BMAP)
|
||||
if (cur->bc_btnum != XFS_BTNUM_BMAP ||
|
||||
cur->bc_tp->t_firstblock == NULLFSBLOCK)
|
||||
return __xfs_btree_split(cur, level, ptrp, key, curp, stat);
|
||||
|
||||
args.cur = cur;
|
||||
|
@ -1213,37 +1213,33 @@ out_error:
|
||||
STATIC int
|
||||
xfs_refcount_adjust(
|
||||
struct xfs_btree_cur *cur,
|
||||
xfs_agblock_t agbno,
|
||||
xfs_extlen_t aglen,
|
||||
xfs_agblock_t *new_agbno,
|
||||
xfs_extlen_t *new_aglen,
|
||||
xfs_agblock_t *agbno,
|
||||
xfs_extlen_t *aglen,
|
||||
enum xfs_refc_adjust_op adj)
|
||||
{
|
||||
bool shape_changed;
|
||||
int shape_changes = 0;
|
||||
int error;
|
||||
|
||||
*new_agbno = agbno;
|
||||
*new_aglen = aglen;
|
||||
if (adj == XFS_REFCOUNT_ADJUST_INCREASE)
|
||||
trace_xfs_refcount_increase(cur->bc_mp, cur->bc_ag.pag->pag_agno,
|
||||
agbno, aglen);
|
||||
trace_xfs_refcount_increase(cur->bc_mp,
|
||||
cur->bc_ag.pag->pag_agno, *agbno, *aglen);
|
||||
else
|
||||
trace_xfs_refcount_decrease(cur->bc_mp, cur->bc_ag.pag->pag_agno,
|
||||
agbno, aglen);
|
||||
trace_xfs_refcount_decrease(cur->bc_mp,
|
||||
cur->bc_ag.pag->pag_agno, *agbno, *aglen);
|
||||
|
||||
/*
|
||||
* Ensure that no rcextents cross the boundary of the adjustment range.
|
||||
*/
|
||||
error = xfs_refcount_split_extent(cur, XFS_REFC_DOMAIN_SHARED,
|
||||
agbno, &shape_changed);
|
||||
*agbno, &shape_changed);
|
||||
if (error)
|
||||
goto out_error;
|
||||
if (shape_changed)
|
||||
shape_changes++;
|
||||
|
||||
error = xfs_refcount_split_extent(cur, XFS_REFC_DOMAIN_SHARED,
|
||||
agbno + aglen, &shape_changed);
|
||||
*agbno + *aglen, &shape_changed);
|
||||
if (error)
|
||||
goto out_error;
|
||||
if (shape_changed)
|
||||
@ -1253,7 +1249,7 @@ xfs_refcount_adjust(
|
||||
* Try to merge with the left or right extents of the range.
|
||||
*/
|
||||
error = xfs_refcount_merge_extents(cur, XFS_REFC_DOMAIN_SHARED,
|
||||
new_agbno, new_aglen, adj, &shape_changed);
|
||||
agbno, aglen, adj, &shape_changed);
|
||||
if (error)
|
||||
goto out_error;
|
||||
if (shape_changed)
|
||||
@ -1262,7 +1258,7 @@ xfs_refcount_adjust(
|
||||
cur->bc_ag.refc.shape_changes++;
|
||||
|
||||
/* Now that we've taken care of the ends, adjust the middle extents */
|
||||
error = xfs_refcount_adjust_extents(cur, new_agbno, new_aglen, adj);
|
||||
error = xfs_refcount_adjust_extents(cur, agbno, aglen, adj);
|
||||
if (error)
|
||||
goto out_error;
|
||||
|
||||
@ -1298,21 +1294,20 @@ xfs_refcount_finish_one_cleanup(
|
||||
static inline int
|
||||
xfs_refcount_continue_op(
|
||||
struct xfs_btree_cur *cur,
|
||||
xfs_fsblock_t startblock,
|
||||
xfs_agblock_t new_agbno,
|
||||
xfs_extlen_t new_len,
|
||||
xfs_fsblock_t *new_fsbno)
|
||||
struct xfs_refcount_intent *ri,
|
||||
xfs_agblock_t new_agbno)
|
||||
{
|
||||
struct xfs_mount *mp = cur->bc_mp;
|
||||
struct xfs_perag *pag = cur->bc_ag.pag;
|
||||
|
||||
if (XFS_IS_CORRUPT(mp, !xfs_verify_agbext(pag, new_agbno, new_len)))
|
||||
if (XFS_IS_CORRUPT(mp, !xfs_verify_agbext(pag, new_agbno,
|
||||
ri->ri_blockcount)))
|
||||
return -EFSCORRUPTED;
|
||||
|
||||
*new_fsbno = XFS_AGB_TO_FSB(mp, pag->pag_agno, new_agbno);
|
||||
ri->ri_startblock = XFS_AGB_TO_FSB(mp, pag->pag_agno, new_agbno);
|
||||
|
||||
ASSERT(xfs_verify_fsbext(mp, *new_fsbno, new_len));
|
||||
ASSERT(pag->pag_agno == XFS_FSB_TO_AGNO(mp, *new_fsbno));
|
||||
ASSERT(xfs_verify_fsbext(mp, ri->ri_startblock, ri->ri_blockcount));
|
||||
ASSERT(pag->pag_agno == XFS_FSB_TO_AGNO(mp, ri->ri_startblock));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1327,11 +1322,7 @@ xfs_refcount_continue_op(
|
||||
int
|
||||
xfs_refcount_finish_one(
|
||||
struct xfs_trans *tp,
|
||||
enum xfs_refcount_intent_type type,
|
||||
xfs_fsblock_t startblock,
|
||||
xfs_extlen_t blockcount,
|
||||
xfs_fsblock_t *new_fsb,
|
||||
xfs_extlen_t *new_len,
|
||||
struct xfs_refcount_intent *ri,
|
||||
struct xfs_btree_cur **pcur)
|
||||
{
|
||||
struct xfs_mount *mp = tp->t_mountp;
|
||||
@ -1339,17 +1330,16 @@ xfs_refcount_finish_one(
|
||||
struct xfs_buf *agbp = NULL;
|
||||
int error = 0;
|
||||
xfs_agblock_t bno;
|
||||
xfs_agblock_t new_agbno;
|
||||
unsigned long nr_ops = 0;
|
||||
int shape_changes = 0;
|
||||
struct xfs_perag *pag;
|
||||
|
||||
pag = xfs_perag_get(mp, XFS_FSB_TO_AGNO(mp, startblock));
|
||||
bno = XFS_FSB_TO_AGBNO(mp, startblock);
|
||||
pag = xfs_perag_get(mp, XFS_FSB_TO_AGNO(mp, ri->ri_startblock));
|
||||
bno = XFS_FSB_TO_AGBNO(mp, ri->ri_startblock);
|
||||
|
||||
trace_xfs_refcount_deferred(mp, XFS_FSB_TO_AGNO(mp, startblock),
|
||||
type, XFS_FSB_TO_AGBNO(mp, startblock),
|
||||
blockcount);
|
||||
trace_xfs_refcount_deferred(mp, XFS_FSB_TO_AGNO(mp, ri->ri_startblock),
|
||||
ri->ri_type, XFS_FSB_TO_AGBNO(mp, ri->ri_startblock),
|
||||
ri->ri_blockcount);
|
||||
|
||||
if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_REFCOUNT_FINISH_ONE)) {
|
||||
error = -EIO;
|
||||
@ -1380,42 +1370,42 @@ xfs_refcount_finish_one(
|
||||
}
|
||||
*pcur = rcur;
|
||||
|
||||
switch (type) {
|
||||
switch (ri->ri_type) {
|
||||
case XFS_REFCOUNT_INCREASE:
|
||||
error = xfs_refcount_adjust(rcur, bno, blockcount, &new_agbno,
|
||||
new_len, XFS_REFCOUNT_ADJUST_INCREASE);
|
||||
error = xfs_refcount_adjust(rcur, &bno, &ri->ri_blockcount,
|
||||
XFS_REFCOUNT_ADJUST_INCREASE);
|
||||
if (error)
|
||||
goto out_drop;
|
||||
if (*new_len > 0)
|
||||
error = xfs_refcount_continue_op(rcur, startblock,
|
||||
new_agbno, *new_len, new_fsb);
|
||||
if (ri->ri_blockcount > 0)
|
||||
error = xfs_refcount_continue_op(rcur, ri, bno);
|
||||
break;
|
||||
case XFS_REFCOUNT_DECREASE:
|
||||
error = xfs_refcount_adjust(rcur, bno, blockcount, &new_agbno,
|
||||
new_len, XFS_REFCOUNT_ADJUST_DECREASE);
|
||||
error = xfs_refcount_adjust(rcur, &bno, &ri->ri_blockcount,
|
||||
XFS_REFCOUNT_ADJUST_DECREASE);
|
||||
if (error)
|
||||
goto out_drop;
|
||||
if (*new_len > 0)
|
||||
error = xfs_refcount_continue_op(rcur, startblock,
|
||||
new_agbno, *new_len, new_fsb);
|
||||
if (ri->ri_blockcount > 0)
|
||||
error = xfs_refcount_continue_op(rcur, ri, bno);
|
||||
break;
|
||||
case XFS_REFCOUNT_ALLOC_COW:
|
||||
*new_fsb = startblock + blockcount;
|
||||
*new_len = 0;
|
||||
error = __xfs_refcount_cow_alloc(rcur, bno, blockcount);
|
||||
error = __xfs_refcount_cow_alloc(rcur, bno, ri->ri_blockcount);
|
||||
if (error)
|
||||
goto out_drop;
|
||||
ri->ri_blockcount = 0;
|
||||
break;
|
||||
case XFS_REFCOUNT_FREE_COW:
|
||||
*new_fsb = startblock + blockcount;
|
||||
*new_len = 0;
|
||||
error = __xfs_refcount_cow_free(rcur, bno, blockcount);
|
||||
error = __xfs_refcount_cow_free(rcur, bno, ri->ri_blockcount);
|
||||
if (error)
|
||||
goto out_drop;
|
||||
ri->ri_blockcount = 0;
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
error = -EFSCORRUPTED;
|
||||
}
|
||||
if (!error && *new_len > 0)
|
||||
trace_xfs_refcount_finish_one_leftover(mp, pag->pag_agno, type,
|
||||
bno, blockcount, new_agbno, *new_len);
|
||||
if (!error && ri->ri_blockcount > 0)
|
||||
trace_xfs_refcount_finish_one_leftover(mp, pag->pag_agno,
|
||||
ri->ri_type, bno, ri->ri_blockcount);
|
||||
out_drop:
|
||||
xfs_perag_put(pag);
|
||||
return error;
|
||||
|
@ -75,9 +75,7 @@ void xfs_refcount_decrease_extent(struct xfs_trans *tp,
|
||||
extern void xfs_refcount_finish_one_cleanup(struct xfs_trans *tp,
|
||||
struct xfs_btree_cur *rcur, int error);
|
||||
extern int xfs_refcount_finish_one(struct xfs_trans *tp,
|
||||
enum xfs_refcount_intent_type type, xfs_fsblock_t startblock,
|
||||
xfs_extlen_t blockcount, xfs_fsblock_t *new_fsb,
|
||||
xfs_extlen_t *new_len, struct xfs_btree_cur **pcur);
|
||||
struct xfs_refcount_intent *ri, struct xfs_btree_cur **pcur);
|
||||
|
||||
extern int xfs_refcount_find_shared(struct xfs_btree_cur *cur,
|
||||
xfs_agblock_t agbno, xfs_extlen_t aglen, xfs_agblock_t *fbno,
|
||||
|
@ -2390,13 +2390,7 @@ xfs_rmap_finish_one_cleanup(
|
||||
int
|
||||
xfs_rmap_finish_one(
|
||||
struct xfs_trans *tp,
|
||||
enum xfs_rmap_intent_type type,
|
||||
uint64_t owner,
|
||||
int whichfork,
|
||||
xfs_fileoff_t startoff,
|
||||
xfs_fsblock_t startblock,
|
||||
xfs_filblks_t blockcount,
|
||||
xfs_exntst_t state,
|
||||
struct xfs_rmap_intent *ri,
|
||||
struct xfs_btree_cur **pcur)
|
||||
{
|
||||
struct xfs_mount *mp = tp->t_mountp;
|
||||
@ -2408,11 +2402,13 @@ xfs_rmap_finish_one(
|
||||
xfs_agblock_t bno;
|
||||
bool unwritten;
|
||||
|
||||
pag = xfs_perag_get(mp, XFS_FSB_TO_AGNO(mp, startblock));
|
||||
bno = XFS_FSB_TO_AGBNO(mp, startblock);
|
||||
pag = xfs_perag_get(mp, XFS_FSB_TO_AGNO(mp, ri->ri_bmap.br_startblock));
|
||||
bno = XFS_FSB_TO_AGBNO(mp, ri->ri_bmap.br_startblock);
|
||||
|
||||
trace_xfs_rmap_deferred(mp, pag->pag_agno, type, bno, owner, whichfork,
|
||||
startoff, blockcount, state);
|
||||
trace_xfs_rmap_deferred(mp, pag->pag_agno, ri->ri_type, bno,
|
||||
ri->ri_owner, ri->ri_whichfork,
|
||||
ri->ri_bmap.br_startoff, ri->ri_bmap.br_blockcount,
|
||||
ri->ri_bmap.br_state);
|
||||
|
||||
if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_RMAP_FINISH_ONE)) {
|
||||
error = -EIO;
|
||||
@ -2448,35 +2444,37 @@ xfs_rmap_finish_one(
|
||||
}
|
||||
*pcur = rcur;
|
||||
|
||||
xfs_rmap_ino_owner(&oinfo, owner, whichfork, startoff);
|
||||
unwritten = state == XFS_EXT_UNWRITTEN;
|
||||
bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, startblock);
|
||||
xfs_rmap_ino_owner(&oinfo, ri->ri_owner, ri->ri_whichfork,
|
||||
ri->ri_bmap.br_startoff);
|
||||
unwritten = ri->ri_bmap.br_state == XFS_EXT_UNWRITTEN;
|
||||
bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, ri->ri_bmap.br_startblock);
|
||||
|
||||
switch (type) {
|
||||
switch (ri->ri_type) {
|
||||
case XFS_RMAP_ALLOC:
|
||||
case XFS_RMAP_MAP:
|
||||
error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo);
|
||||
error = xfs_rmap_map(rcur, bno, ri->ri_bmap.br_blockcount,
|
||||
unwritten, &oinfo);
|
||||
break;
|
||||
case XFS_RMAP_MAP_SHARED:
|
||||
error = xfs_rmap_map_shared(rcur, bno, blockcount, unwritten,
|
||||
&oinfo);
|
||||
error = xfs_rmap_map_shared(rcur, bno,
|
||||
ri->ri_bmap.br_blockcount, unwritten, &oinfo);
|
||||
break;
|
||||
case XFS_RMAP_FREE:
|
||||
case XFS_RMAP_UNMAP:
|
||||
error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten,
|
||||
&oinfo);
|
||||
error = xfs_rmap_unmap(rcur, bno, ri->ri_bmap.br_blockcount,
|
||||
unwritten, &oinfo);
|
||||
break;
|
||||
case XFS_RMAP_UNMAP_SHARED:
|
||||
error = xfs_rmap_unmap_shared(rcur, bno, blockcount, unwritten,
|
||||
&oinfo);
|
||||
error = xfs_rmap_unmap_shared(rcur, bno,
|
||||
ri->ri_bmap.br_blockcount, unwritten, &oinfo);
|
||||
break;
|
||||
case XFS_RMAP_CONVERT:
|
||||
error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten,
|
||||
&oinfo);
|
||||
error = xfs_rmap_convert(rcur, bno, ri->ri_bmap.br_blockcount,
|
||||
!unwritten, &oinfo);
|
||||
break;
|
||||
case XFS_RMAP_CONVERT_SHARED:
|
||||
error = xfs_rmap_convert_shared(rcur, bno, blockcount,
|
||||
!unwritten, &oinfo);
|
||||
error = xfs_rmap_convert_shared(rcur, bno,
|
||||
ri->ri_bmap.br_blockcount, !unwritten, &oinfo);
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
|
@ -179,10 +179,8 @@ void xfs_rmap_free_extent(struct xfs_trans *tp, xfs_agnumber_t agno,
|
||||
|
||||
void xfs_rmap_finish_one_cleanup(struct xfs_trans *tp,
|
||||
struct xfs_btree_cur *rcur, int error);
|
||||
int xfs_rmap_finish_one(struct xfs_trans *tp, enum xfs_rmap_intent_type type,
|
||||
uint64_t owner, int whichfork, xfs_fileoff_t startoff,
|
||||
xfs_fsblock_t startblock, xfs_filblks_t blockcount,
|
||||
xfs_exntst_t state, struct xfs_btree_cur **pcur);
|
||||
int xfs_rmap_finish_one(struct xfs_trans *tp, struct xfs_rmap_intent *ri,
|
||||
struct xfs_btree_cur **pcur);
|
||||
|
||||
int xfs_rmap_lookup_le_range(struct xfs_btree_cur *cur, xfs_agblock_t bno,
|
||||
uint64_t owner, uint64_t offset, unsigned int flags,
|
||||
|
@ -246,18 +246,11 @@ static int
|
||||
xfs_trans_log_finish_bmap_update(
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_bud_log_item *budp,
|
||||
enum xfs_bmap_intent_type type,
|
||||
struct xfs_inode *ip,
|
||||
int whichfork,
|
||||
xfs_fileoff_t startoff,
|
||||
xfs_fsblock_t startblock,
|
||||
xfs_filblks_t *blockcount,
|
||||
xfs_exntst_t state)
|
||||
struct xfs_bmap_intent *bi)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = xfs_bmap_finish_one(tp, ip, type, whichfork, startoff,
|
||||
startblock, blockcount, state);
|
||||
error = xfs_bmap_finish_one(tp, bi);
|
||||
|
||||
/*
|
||||
* Mark the transaction dirty, even on error. This ensures the
|
||||
@ -290,24 +283,24 @@ xfs_bmap_update_diff_items(
|
||||
/* Set the map extent flags for this mapping. */
|
||||
static void
|
||||
xfs_trans_set_bmap_flags(
|
||||
struct xfs_map_extent *bmap,
|
||||
struct xfs_map_extent *map,
|
||||
enum xfs_bmap_intent_type type,
|
||||
int whichfork,
|
||||
xfs_exntst_t state)
|
||||
{
|
||||
bmap->me_flags = 0;
|
||||
map->me_flags = 0;
|
||||
switch (type) {
|
||||
case XFS_BMAP_MAP:
|
||||
case XFS_BMAP_UNMAP:
|
||||
bmap->me_flags = type;
|
||||
map->me_flags = type;
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
}
|
||||
if (state == XFS_EXT_UNWRITTEN)
|
||||
bmap->me_flags |= XFS_BMAP_EXTENT_UNWRITTEN;
|
||||
map->me_flags |= XFS_BMAP_EXTENT_UNWRITTEN;
|
||||
if (whichfork == XFS_ATTR_FORK)
|
||||
bmap->me_flags |= XFS_BMAP_EXTENT_ATTR_FORK;
|
||||
map->me_flags |= XFS_BMAP_EXTENT_ATTR_FORK;
|
||||
}
|
||||
|
||||
/* Log bmap updates in the intent item. */
|
||||
@ -315,7 +308,7 @@ STATIC void
|
||||
xfs_bmap_update_log_item(
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_bui_log_item *buip,
|
||||
struct xfs_bmap_intent *bmap)
|
||||
struct xfs_bmap_intent *bi)
|
||||
{
|
||||
uint next_extent;
|
||||
struct xfs_map_extent *map;
|
||||
@ -331,12 +324,12 @@ xfs_bmap_update_log_item(
|
||||
next_extent = atomic_inc_return(&buip->bui_next_extent) - 1;
|
||||
ASSERT(next_extent < buip->bui_format.bui_nextents);
|
||||
map = &buip->bui_format.bui_extents[next_extent];
|
||||
map->me_owner = bmap->bi_owner->i_ino;
|
||||
map->me_startblock = bmap->bi_bmap.br_startblock;
|
||||
map->me_startoff = bmap->bi_bmap.br_startoff;
|
||||
map->me_len = bmap->bi_bmap.br_blockcount;
|
||||
xfs_trans_set_bmap_flags(map, bmap->bi_type, bmap->bi_whichfork,
|
||||
bmap->bi_bmap.br_state);
|
||||
map->me_owner = bi->bi_owner->i_ino;
|
||||
map->me_startblock = bi->bi_bmap.br_startblock;
|
||||
map->me_startoff = bi->bi_bmap.br_startoff;
|
||||
map->me_len = bi->bi_bmap.br_blockcount;
|
||||
xfs_trans_set_bmap_flags(map, bi->bi_type, bi->bi_whichfork,
|
||||
bi->bi_bmap.br_state);
|
||||
}
|
||||
|
||||
static struct xfs_log_item *
|
||||
@ -348,15 +341,15 @@ xfs_bmap_update_create_intent(
|
||||
{
|
||||
struct xfs_mount *mp = tp->t_mountp;
|
||||
struct xfs_bui_log_item *buip = xfs_bui_init(mp);
|
||||
struct xfs_bmap_intent *bmap;
|
||||
struct xfs_bmap_intent *bi;
|
||||
|
||||
ASSERT(count == XFS_BUI_MAX_FAST_EXTENTS);
|
||||
|
||||
xfs_trans_add_item(tp, &buip->bui_item);
|
||||
if (sort)
|
||||
list_sort(mp, items, xfs_bmap_update_diff_items);
|
||||
list_for_each_entry(bmap, items, bi_list)
|
||||
xfs_bmap_update_log_item(tp, buip, bmap);
|
||||
list_for_each_entry(bi, items, bi_list)
|
||||
xfs_bmap_update_log_item(tp, buip, bi);
|
||||
return &buip->bui_item;
|
||||
}
|
||||
|
||||
@ -378,25 +371,17 @@ xfs_bmap_update_finish_item(
|
||||
struct list_head *item,
|
||||
struct xfs_btree_cur **state)
|
||||
{
|
||||
struct xfs_bmap_intent *bmap;
|
||||
xfs_filblks_t count;
|
||||
struct xfs_bmap_intent *bi;
|
||||
int error;
|
||||
|
||||
bmap = container_of(item, struct xfs_bmap_intent, bi_list);
|
||||
count = bmap->bi_bmap.br_blockcount;
|
||||
error = xfs_trans_log_finish_bmap_update(tp, BUD_ITEM(done),
|
||||
bmap->bi_type,
|
||||
bmap->bi_owner, bmap->bi_whichfork,
|
||||
bmap->bi_bmap.br_startoff,
|
||||
bmap->bi_bmap.br_startblock,
|
||||
&count,
|
||||
bmap->bi_bmap.br_state);
|
||||
if (!error && count > 0) {
|
||||
ASSERT(bmap->bi_type == XFS_BMAP_UNMAP);
|
||||
bmap->bi_bmap.br_blockcount = count;
|
||||
bi = container_of(item, struct xfs_bmap_intent, bi_list);
|
||||
|
||||
error = xfs_trans_log_finish_bmap_update(tp, BUD_ITEM(done), bi);
|
||||
if (!error && bi->bi_bmap.br_blockcount > 0) {
|
||||
ASSERT(bi->bi_type == XFS_BMAP_UNMAP);
|
||||
return -EAGAIN;
|
||||
}
|
||||
kmem_cache_free(xfs_bmap_intent_cache, bmap);
|
||||
kmem_cache_free(xfs_bmap_intent_cache, bi);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -413,10 +398,10 @@ STATIC void
|
||||
xfs_bmap_update_cancel_item(
|
||||
struct list_head *item)
|
||||
{
|
||||
struct xfs_bmap_intent *bmap;
|
||||
struct xfs_bmap_intent *bi;
|
||||
|
||||
bmap = container_of(item, struct xfs_bmap_intent, bi_list);
|
||||
kmem_cache_free(xfs_bmap_intent_cache, bmap);
|
||||
bi = container_of(item, struct xfs_bmap_intent, bi_list);
|
||||
kmem_cache_free(xfs_bmap_intent_cache, bi);
|
||||
}
|
||||
|
||||
const struct xfs_defer_op_type xfs_bmap_update_defer_type = {
|
||||
@ -434,18 +419,18 @@ xfs_bui_validate(
|
||||
struct xfs_mount *mp,
|
||||
struct xfs_bui_log_item *buip)
|
||||
{
|
||||
struct xfs_map_extent *bmap;
|
||||
struct xfs_map_extent *map;
|
||||
|
||||
/* Only one mapping operation per BUI... */
|
||||
if (buip->bui_format.bui_nextents != XFS_BUI_MAX_FAST_EXTENTS)
|
||||
return false;
|
||||
|
||||
bmap = &buip->bui_format.bui_extents[0];
|
||||
map = &buip->bui_format.bui_extents[0];
|
||||
|
||||
if (bmap->me_flags & ~XFS_BMAP_EXTENT_FLAGS)
|
||||
if (map->me_flags & ~XFS_BMAP_EXTENT_FLAGS)
|
||||
return false;
|
||||
|
||||
switch (bmap->me_flags & XFS_BMAP_EXTENT_TYPE_MASK) {
|
||||
switch (map->me_flags & XFS_BMAP_EXTENT_TYPE_MASK) {
|
||||
case XFS_BMAP_MAP:
|
||||
case XFS_BMAP_UNMAP:
|
||||
break;
|
||||
@ -453,13 +438,13 @@ xfs_bui_validate(
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!xfs_verify_ino(mp, bmap->me_owner))
|
||||
if (!xfs_verify_ino(mp, map->me_owner))
|
||||
return false;
|
||||
|
||||
if (!xfs_verify_fileext(mp, bmap->me_startoff, bmap->me_len))
|
||||
if (!xfs_verify_fileext(mp, map->me_startoff, map->me_len))
|
||||
return false;
|
||||
|
||||
return xfs_verify_fsbext(mp, bmap->me_startblock, bmap->me_len);
|
||||
return xfs_verify_fsbext(mp, map->me_startblock, map->me_len);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -471,17 +456,13 @@ xfs_bui_item_recover(
|
||||
struct xfs_log_item *lip,
|
||||
struct list_head *capture_list)
|
||||
{
|
||||
struct xfs_bmbt_irec irec;
|
||||
struct xfs_bmap_intent fake = { };
|
||||
struct xfs_bui_log_item *buip = BUI_ITEM(lip);
|
||||
struct xfs_trans *tp;
|
||||
struct xfs_inode *ip = NULL;
|
||||
struct xfs_mount *mp = lip->li_log->l_mp;
|
||||
struct xfs_map_extent *bmap;
|
||||
struct xfs_map_extent *map;
|
||||
struct xfs_bud_log_item *budp;
|
||||
xfs_filblks_t count;
|
||||
xfs_exntst_t state;
|
||||
unsigned int bui_type;
|
||||
int whichfork;
|
||||
int iext_delta;
|
||||
int error = 0;
|
||||
|
||||
@ -491,14 +472,12 @@ xfs_bui_item_recover(
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
bmap = &buip->bui_format.bui_extents[0];
|
||||
state = (bmap->me_flags & XFS_BMAP_EXTENT_UNWRITTEN) ?
|
||||
XFS_EXT_UNWRITTEN : XFS_EXT_NORM;
|
||||
whichfork = (bmap->me_flags & XFS_BMAP_EXTENT_ATTR_FORK) ?
|
||||
map = &buip->bui_format.bui_extents[0];
|
||||
fake.bi_whichfork = (map->me_flags & XFS_BMAP_EXTENT_ATTR_FORK) ?
|
||||
XFS_ATTR_FORK : XFS_DATA_FORK;
|
||||
bui_type = bmap->me_flags & XFS_BMAP_EXTENT_TYPE_MASK;
|
||||
fake.bi_type = map->me_flags & XFS_BMAP_EXTENT_TYPE_MASK;
|
||||
|
||||
error = xlog_recover_iget(mp, bmap->me_owner, &ip);
|
||||
error = xlog_recover_iget(mp, map->me_owner, &ip);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@ -512,34 +491,34 @@ xfs_bui_item_recover(
|
||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||
xfs_trans_ijoin(tp, ip, 0);
|
||||
|
||||
if (bui_type == XFS_BMAP_MAP)
|
||||
if (fake.bi_type == XFS_BMAP_MAP)
|
||||
iext_delta = XFS_IEXT_ADD_NOSPLIT_CNT;
|
||||
else
|
||||
iext_delta = XFS_IEXT_PUNCH_HOLE_CNT;
|
||||
|
||||
error = xfs_iext_count_may_overflow(ip, whichfork, iext_delta);
|
||||
error = xfs_iext_count_may_overflow(ip, fake.bi_whichfork, iext_delta);
|
||||
if (error == -EFBIG)
|
||||
error = xfs_iext_count_upgrade(tp, ip, iext_delta);
|
||||
if (error)
|
||||
goto err_cancel;
|
||||
|
||||
count = bmap->me_len;
|
||||
error = xfs_trans_log_finish_bmap_update(tp, budp, bui_type, ip,
|
||||
whichfork, bmap->me_startoff, bmap->me_startblock,
|
||||
&count, state);
|
||||
fake.bi_owner = ip;
|
||||
fake.bi_bmap.br_startblock = map->me_startblock;
|
||||
fake.bi_bmap.br_startoff = map->me_startoff;
|
||||
fake.bi_bmap.br_blockcount = map->me_len;
|
||||
fake.bi_bmap.br_state = (map->me_flags & XFS_BMAP_EXTENT_UNWRITTEN) ?
|
||||
XFS_EXT_UNWRITTEN : XFS_EXT_NORM;
|
||||
|
||||
error = xfs_trans_log_finish_bmap_update(tp, budp, &fake);
|
||||
if (error == -EFSCORRUPTED)
|
||||
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bmap,
|
||||
sizeof(*bmap));
|
||||
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, map,
|
||||
sizeof(*map));
|
||||
if (error)
|
||||
goto err_cancel;
|
||||
|
||||
if (count > 0) {
|
||||
ASSERT(bui_type == XFS_BMAP_UNMAP);
|
||||
irec.br_startblock = bmap->me_startblock;
|
||||
irec.br_blockcount = count;
|
||||
irec.br_startoff = bmap->me_startoff;
|
||||
irec.br_state = state;
|
||||
xfs_bmap_unmap_extent(tp, ip, &irec);
|
||||
if (fake.bi_bmap.br_blockcount > 0) {
|
||||
ASSERT(fake.bi_type == XFS_BMAP_UNMAP);
|
||||
xfs_bmap_unmap_extent(tp, ip, &fake.bi_bmap);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -579,18 +558,18 @@ xfs_bui_item_relog(
|
||||
{
|
||||
struct xfs_bud_log_item *budp;
|
||||
struct xfs_bui_log_item *buip;
|
||||
struct xfs_map_extent *extp;
|
||||
struct xfs_map_extent *map;
|
||||
unsigned int count;
|
||||
|
||||
count = BUI_ITEM(intent)->bui_format.bui_nextents;
|
||||
extp = BUI_ITEM(intent)->bui_format.bui_extents;
|
||||
map = BUI_ITEM(intent)->bui_format.bui_extents;
|
||||
|
||||
tp->t_flags |= XFS_TRANS_DIRTY;
|
||||
budp = xfs_trans_get_bud(tp, BUI_ITEM(intent));
|
||||
set_bit(XFS_LI_DIRTY, &budp->bud_item.li_flags);
|
||||
|
||||
buip = xfs_bui_init(tp->t_mountp);
|
||||
memcpy(buip->bui_format.bui_extents, extp, count * sizeof(*extp));
|
||||
memcpy(buip->bui_format.bui_extents, map, count * sizeof(*map));
|
||||
atomic_set(&buip->bui_next_extent, count);
|
||||
xfs_trans_add_item(tp, &buip->bui_item);
|
||||
set_bit(XFS_LI_DIRTY, &buip->bui_item.li_flags);
|
||||
|
@ -228,7 +228,7 @@ static struct attribute *xfs_errortag_attrs[] = {
|
||||
};
|
||||
ATTRIBUTE_GROUPS(xfs_errortag);
|
||||
|
||||
static struct kobj_type xfs_errortag_ktype = {
|
||||
static const struct kobj_type xfs_errortag_ktype = {
|
||||
.release = xfs_sysfs_release,
|
||||
.sysfs_ops = &xfs_errortag_sysfs_ops,
|
||||
.default_groups = xfs_errortag_groups,
|
||||
|
@ -75,7 +75,7 @@ extern int xfs_errortag_clearall(struct xfs_mount *mp);
|
||||
|
||||
/*
|
||||
* XFS panic tags -- allow a call to xfs_alert_tag() be turned into
|
||||
* a panic by setting xfs_panic_mask in a sysctl.
|
||||
* a panic by setting fs.xfs.panic_mask in a sysctl.
|
||||
*/
|
||||
#define XFS_NO_PTAG 0u
|
||||
#define XFS_PTAG_IFLUSH (1u << 0)
|
||||
@ -88,6 +88,16 @@ extern int xfs_errortag_clearall(struct xfs_mount *mp);
|
||||
#define XFS_PTAG_FSBLOCK_ZERO (1u << 7)
|
||||
#define XFS_PTAG_VERIFIER_ERROR (1u << 8)
|
||||
|
||||
#define XFS_PTAG_MASK (XFS_PTAG_IFLUSH | \
|
||||
XFS_PTAG_LOGRES | \
|
||||
XFS_PTAG_AILDELETE | \
|
||||
XFS_PTAG_ERROR_REPORT | \
|
||||
XFS_PTAG_SHUTDOWN_CORRUPT | \
|
||||
XFS_PTAG_SHUTDOWN_IOERROR | \
|
||||
XFS_PTAG_SHUTDOWN_LOGERROR | \
|
||||
XFS_PTAG_FSBLOCK_ZERO | \
|
||||
XFS_PTAG_VERIFIER_ERROR)
|
||||
|
||||
#define XFS_PTAG_STRINGS \
|
||||
{ XFS_NO_PTAG, "none" }, \
|
||||
{ XFS_PTAG_IFLUSH, "iflush" }, \
|
||||
|
@ -345,23 +345,30 @@ static int
|
||||
xfs_trans_free_extent(
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_efd_log_item *efdp,
|
||||
xfs_fsblock_t start_block,
|
||||
xfs_extlen_t ext_len,
|
||||
const struct xfs_owner_info *oinfo,
|
||||
bool skip_discard)
|
||||
struct xfs_extent_free_item *xefi)
|
||||
{
|
||||
struct xfs_owner_info oinfo = { };
|
||||
struct xfs_mount *mp = tp->t_mountp;
|
||||
struct xfs_extent *extp;
|
||||
uint next_extent;
|
||||
xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, start_block);
|
||||
xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp,
|
||||
xefi->xefi_startblock);
|
||||
xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp,
|
||||
start_block);
|
||||
xefi->xefi_startblock);
|
||||
int error;
|
||||
|
||||
trace_xfs_bmap_free_deferred(tp->t_mountp, agno, 0, agbno, ext_len);
|
||||
oinfo.oi_owner = xefi->xefi_owner;
|
||||
if (xefi->xefi_flags & XFS_EFI_ATTR_FORK)
|
||||
oinfo.oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
|
||||
if (xefi->xefi_flags & XFS_EFI_BMBT_BLOCK)
|
||||
oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;
|
||||
|
||||
error = __xfs_free_extent(tp, start_block, ext_len,
|
||||
oinfo, XFS_AG_RESV_NONE, skip_discard);
|
||||
trace_xfs_bmap_free_deferred(tp->t_mountp, agno, 0, agbno,
|
||||
xefi->xefi_blockcount);
|
||||
|
||||
error = __xfs_free_extent(tp, xefi->xefi_startblock,
|
||||
xefi->xefi_blockcount, &oinfo, XFS_AG_RESV_NONE,
|
||||
xefi->xefi_flags & XFS_EFI_SKIP_DISCARD);
|
||||
/*
|
||||
* Mark the transaction dirty, even on error. This ensures the
|
||||
* transaction is aborted, which:
|
||||
@ -375,8 +382,8 @@ xfs_trans_free_extent(
|
||||
next_extent = efdp->efd_next_extent;
|
||||
ASSERT(next_extent < efdp->efd_format.efd_nextents);
|
||||
extp = &(efdp->efd_format.efd_extents[next_extent]);
|
||||
extp->ext_start = start_block;
|
||||
extp->ext_len = ext_len;
|
||||
extp->ext_start = xefi->xefi_startblock;
|
||||
extp->ext_len = xefi->xefi_blockcount;
|
||||
efdp->efd_next_extent++;
|
||||
|
||||
return error;
|
||||
@ -404,7 +411,7 @@ STATIC void
|
||||
xfs_extent_free_log_item(
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_efi_log_item *efip,
|
||||
struct xfs_extent_free_item *free)
|
||||
struct xfs_extent_free_item *xefi)
|
||||
{
|
||||
uint next_extent;
|
||||
struct xfs_extent *extp;
|
||||
@ -420,8 +427,8 @@ xfs_extent_free_log_item(
|
||||
next_extent = atomic_inc_return(&efip->efi_next_extent) - 1;
|
||||
ASSERT(next_extent < efip->efi_format.efi_nextents);
|
||||
extp = &efip->efi_format.efi_extents[next_extent];
|
||||
extp->ext_start = free->xefi_startblock;
|
||||
extp->ext_len = free->xefi_blockcount;
|
||||
extp->ext_start = xefi->xefi_startblock;
|
||||
extp->ext_len = xefi->xefi_blockcount;
|
||||
}
|
||||
|
||||
static struct xfs_log_item *
|
||||
@ -433,15 +440,15 @@ xfs_extent_free_create_intent(
|
||||
{
|
||||
struct xfs_mount *mp = tp->t_mountp;
|
||||
struct xfs_efi_log_item *efip = xfs_efi_init(mp, count);
|
||||
struct xfs_extent_free_item *free;
|
||||
struct xfs_extent_free_item *xefi;
|
||||
|
||||
ASSERT(count > 0);
|
||||
|
||||
xfs_trans_add_item(tp, &efip->efi_item);
|
||||
if (sort)
|
||||
list_sort(mp, items, xfs_extent_free_diff_items);
|
||||
list_for_each_entry(free, items, xefi_list)
|
||||
xfs_extent_free_log_item(tp, efip, free);
|
||||
list_for_each_entry(xefi, items, xefi_list)
|
||||
xfs_extent_free_log_item(tp, efip, xefi);
|
||||
return &efip->efi_item;
|
||||
}
|
||||
|
||||
@ -463,21 +470,13 @@ xfs_extent_free_finish_item(
|
||||
struct list_head *item,
|
||||
struct xfs_btree_cur **state)
|
||||
{
|
||||
struct xfs_owner_info oinfo = { };
|
||||
struct xfs_extent_free_item *free;
|
||||
struct xfs_extent_free_item *xefi;
|
||||
int error;
|
||||
|
||||
free = container_of(item, struct xfs_extent_free_item, xefi_list);
|
||||
oinfo.oi_owner = free->xefi_owner;
|
||||
if (free->xefi_flags & XFS_EFI_ATTR_FORK)
|
||||
oinfo.oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
|
||||
if (free->xefi_flags & XFS_EFI_BMBT_BLOCK)
|
||||
oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;
|
||||
error = xfs_trans_free_extent(tp, EFD_ITEM(done),
|
||||
free->xefi_startblock,
|
||||
free->xefi_blockcount,
|
||||
&oinfo, free->xefi_flags & XFS_EFI_SKIP_DISCARD);
|
||||
kmem_cache_free(xfs_extfree_item_cache, free);
|
||||
xefi = container_of(item, struct xfs_extent_free_item, xefi_list);
|
||||
|
||||
error = xfs_trans_free_extent(tp, EFD_ITEM(done), xefi);
|
||||
kmem_cache_free(xfs_extfree_item_cache, xefi);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -494,10 +493,10 @@ STATIC void
|
||||
xfs_extent_free_cancel_item(
|
||||
struct list_head *item)
|
||||
{
|
||||
struct xfs_extent_free_item *free;
|
||||
struct xfs_extent_free_item *xefi;
|
||||
|
||||
free = container_of(item, struct xfs_extent_free_item, xefi_list);
|
||||
kmem_cache_free(xfs_extfree_item_cache, free);
|
||||
xefi = container_of(item, struct xfs_extent_free_item, xefi_list);
|
||||
kmem_cache_free(xfs_extfree_item_cache, xefi);
|
||||
}
|
||||
|
||||
const struct xfs_defer_op_type xfs_extent_free_defer_type = {
|
||||
@ -523,7 +522,7 @@ xfs_agfl_free_finish_item(
|
||||
struct xfs_owner_info oinfo = { };
|
||||
struct xfs_mount *mp = tp->t_mountp;
|
||||
struct xfs_efd_log_item *efdp = EFD_ITEM(done);
|
||||
struct xfs_extent_free_item *free;
|
||||
struct xfs_extent_free_item *xefi;
|
||||
struct xfs_extent *extp;
|
||||
struct xfs_buf *agbp;
|
||||
int error;
|
||||
@ -532,13 +531,13 @@ xfs_agfl_free_finish_item(
|
||||
uint next_extent;
|
||||
struct xfs_perag *pag;
|
||||
|
||||
free = container_of(item, struct xfs_extent_free_item, xefi_list);
|
||||
ASSERT(free->xefi_blockcount == 1);
|
||||
agno = XFS_FSB_TO_AGNO(mp, free->xefi_startblock);
|
||||
agbno = XFS_FSB_TO_AGBNO(mp, free->xefi_startblock);
|
||||
oinfo.oi_owner = free->xefi_owner;
|
||||
xefi = container_of(item, struct xfs_extent_free_item, xefi_list);
|
||||
ASSERT(xefi->xefi_blockcount == 1);
|
||||
agno = XFS_FSB_TO_AGNO(mp, xefi->xefi_startblock);
|
||||
agbno = XFS_FSB_TO_AGBNO(mp, xefi->xefi_startblock);
|
||||
oinfo.oi_owner = xefi->xefi_owner;
|
||||
|
||||
trace_xfs_agfl_free_deferred(mp, agno, 0, agbno, free->xefi_blockcount);
|
||||
trace_xfs_agfl_free_deferred(mp, agno, 0, agbno, xefi->xefi_blockcount);
|
||||
|
||||
pag = xfs_perag_get(mp, agno);
|
||||
error = xfs_alloc_read_agf(pag, tp, 0, &agbp);
|
||||
@ -559,11 +558,11 @@ xfs_agfl_free_finish_item(
|
||||
next_extent = efdp->efd_next_extent;
|
||||
ASSERT(next_extent < efdp->efd_format.efd_nextents);
|
||||
extp = &(efdp->efd_format.efd_extents[next_extent]);
|
||||
extp->ext_start = free->xefi_startblock;
|
||||
extp->ext_len = free->xefi_blockcount;
|
||||
extp->ext_start = xefi->xefi_startblock;
|
||||
extp->ext_len = xefi->xefi_blockcount;
|
||||
efdp->efd_next_extent++;
|
||||
|
||||
kmem_cache_free(xfs_extfree_item_cache, free);
|
||||
kmem_cache_free(xfs_extfree_item_cache, xefi);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -599,7 +598,6 @@ xfs_efi_item_recover(
|
||||
struct xfs_mount *mp = lip->li_log->l_mp;
|
||||
struct xfs_efd_log_item *efdp;
|
||||
struct xfs_trans *tp;
|
||||
struct xfs_extent *extp;
|
||||
int i;
|
||||
int error = 0;
|
||||
|
||||
@ -624,10 +622,17 @@ xfs_efi_item_recover(
|
||||
efdp = xfs_trans_get_efd(tp, efip, efip->efi_format.efi_nextents);
|
||||
|
||||
for (i = 0; i < efip->efi_format.efi_nextents; i++) {
|
||||
struct xfs_extent_free_item fake = {
|
||||
.xefi_owner = XFS_RMAP_OWN_UNKNOWN,
|
||||
};
|
||||
struct xfs_extent *extp;
|
||||
|
||||
extp = &efip->efi_format.efi_extents[i];
|
||||
error = xfs_trans_free_extent(tp, efdp, extp->ext_start,
|
||||
extp->ext_len,
|
||||
&XFS_RMAP_OINFO_ANY_OWNER, false);
|
||||
|
||||
fake.xefi_startblock = extp->ext_start;
|
||||
fake.xefi_blockcount = extp->ext_len;
|
||||
|
||||
error = xfs_trans_free_extent(tp, efdp, &fake);
|
||||
if (error == -EFSCORRUPTED)
|
||||
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
|
||||
extp, sizeof(*extp));
|
||||
|
@ -4,6 +4,7 @@
|
||||
* All Rights Reserved.
|
||||
*/
|
||||
#include "xfs.h"
|
||||
#include "xfs_error.h"
|
||||
|
||||
/*
|
||||
* Tunable XFS parameters. xfs_params is required even when CONFIG_SYSCTL=n,
|
||||
@ -15,7 +16,7 @@ xfs_param_t xfs_params = {
|
||||
/* MIN DFLT MAX */
|
||||
.sgid_inherit = { 0, 0, 1 },
|
||||
.symlink_mode = { 0, 0, 1 },
|
||||
.panic_mask = { 0, 0, 256 },
|
||||
.panic_mask = { 0, 0, XFS_PTAG_MASK},
|
||||
.error_level = { 0, 3, 11 },
|
||||
.syncd_timer = { 1*100, 30*100, 7200*100},
|
||||
.stats_clear = { 0, 0, 1 },
|
||||
|
@ -252,17 +252,12 @@ static int
|
||||
xfs_trans_log_finish_refcount_update(
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_cud_log_item *cudp,
|
||||
enum xfs_refcount_intent_type type,
|
||||
xfs_fsblock_t startblock,
|
||||
xfs_extlen_t blockcount,
|
||||
xfs_fsblock_t *new_fsb,
|
||||
xfs_extlen_t *new_len,
|
||||
struct xfs_refcount_intent *ri,
|
||||
struct xfs_btree_cur **pcur)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = xfs_refcount_finish_one(tp, type, startblock,
|
||||
blockcount, new_fsb, new_len, pcur);
|
||||
error = xfs_refcount_finish_one(tp, ri, pcur);
|
||||
|
||||
/*
|
||||
* Mark the transaction dirty, even on error. This ensures the
|
||||
@ -297,16 +292,16 @@ xfs_refcount_update_diff_items(
|
||||
/* Set the phys extent flags for this reverse mapping. */
|
||||
static void
|
||||
xfs_trans_set_refcount_flags(
|
||||
struct xfs_phys_extent *refc,
|
||||
struct xfs_phys_extent *pmap,
|
||||
enum xfs_refcount_intent_type type)
|
||||
{
|
||||
refc->pe_flags = 0;
|
||||
pmap->pe_flags = 0;
|
||||
switch (type) {
|
||||
case XFS_REFCOUNT_INCREASE:
|
||||
case XFS_REFCOUNT_DECREASE:
|
||||
case XFS_REFCOUNT_ALLOC_COW:
|
||||
case XFS_REFCOUNT_FREE_COW:
|
||||
refc->pe_flags |= type;
|
||||
pmap->pe_flags |= type;
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
@ -318,10 +313,10 @@ STATIC void
|
||||
xfs_refcount_update_log_item(
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_cui_log_item *cuip,
|
||||
struct xfs_refcount_intent *refc)
|
||||
struct xfs_refcount_intent *ri)
|
||||
{
|
||||
uint next_extent;
|
||||
struct xfs_phys_extent *ext;
|
||||
struct xfs_phys_extent *pmap;
|
||||
|
||||
tp->t_flags |= XFS_TRANS_DIRTY;
|
||||
set_bit(XFS_LI_DIRTY, &cuip->cui_item.li_flags);
|
||||
@ -333,10 +328,10 @@ xfs_refcount_update_log_item(
|
||||
*/
|
||||
next_extent = atomic_inc_return(&cuip->cui_next_extent) - 1;
|
||||
ASSERT(next_extent < cuip->cui_format.cui_nextents);
|
||||
ext = &cuip->cui_format.cui_extents[next_extent];
|
||||
ext->pe_startblock = refc->ri_startblock;
|
||||
ext->pe_len = refc->ri_blockcount;
|
||||
xfs_trans_set_refcount_flags(ext, refc->ri_type);
|
||||
pmap = &cuip->cui_format.cui_extents[next_extent];
|
||||
pmap->pe_startblock = ri->ri_startblock;
|
||||
pmap->pe_len = ri->ri_blockcount;
|
||||
xfs_trans_set_refcount_flags(pmap, ri->ri_type);
|
||||
}
|
||||
|
||||
static struct xfs_log_item *
|
||||
@ -348,15 +343,15 @@ xfs_refcount_update_create_intent(
|
||||
{
|
||||
struct xfs_mount *mp = tp->t_mountp;
|
||||
struct xfs_cui_log_item *cuip = xfs_cui_init(mp, count);
|
||||
struct xfs_refcount_intent *refc;
|
||||
struct xfs_refcount_intent *ri;
|
||||
|
||||
ASSERT(count > 0);
|
||||
|
||||
xfs_trans_add_item(tp, &cuip->cui_item);
|
||||
if (sort)
|
||||
list_sort(mp, items, xfs_refcount_update_diff_items);
|
||||
list_for_each_entry(refc, items, ri_list)
|
||||
xfs_refcount_update_log_item(tp, cuip, refc);
|
||||
list_for_each_entry(ri, items, ri_list)
|
||||
xfs_refcount_update_log_item(tp, cuip, ri);
|
||||
return &cuip->cui_item;
|
||||
}
|
||||
|
||||
@ -378,25 +373,20 @@ xfs_refcount_update_finish_item(
|
||||
struct list_head *item,
|
||||
struct xfs_btree_cur **state)
|
||||
{
|
||||
struct xfs_refcount_intent *refc;
|
||||
xfs_fsblock_t new_fsb;
|
||||
xfs_extlen_t new_aglen;
|
||||
struct xfs_refcount_intent *ri;
|
||||
int error;
|
||||
|
||||
refc = container_of(item, struct xfs_refcount_intent, ri_list);
|
||||
error = xfs_trans_log_finish_refcount_update(tp, CUD_ITEM(done),
|
||||
refc->ri_type, refc->ri_startblock, refc->ri_blockcount,
|
||||
&new_fsb, &new_aglen, state);
|
||||
ri = container_of(item, struct xfs_refcount_intent, ri_list);
|
||||
error = xfs_trans_log_finish_refcount_update(tp, CUD_ITEM(done), ri,
|
||||
state);
|
||||
|
||||
/* Did we run out of reservation? Requeue what we didn't finish. */
|
||||
if (!error && new_aglen > 0) {
|
||||
ASSERT(refc->ri_type == XFS_REFCOUNT_INCREASE ||
|
||||
refc->ri_type == XFS_REFCOUNT_DECREASE);
|
||||
refc->ri_startblock = new_fsb;
|
||||
refc->ri_blockcount = new_aglen;
|
||||
if (!error && ri->ri_blockcount > 0) {
|
||||
ASSERT(ri->ri_type == XFS_REFCOUNT_INCREASE ||
|
||||
ri->ri_type == XFS_REFCOUNT_DECREASE);
|
||||
return -EAGAIN;
|
||||
}
|
||||
kmem_cache_free(xfs_refcount_intent_cache, refc);
|
||||
kmem_cache_free(xfs_refcount_intent_cache, ri);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -413,10 +403,10 @@ STATIC void
|
||||
xfs_refcount_update_cancel_item(
|
||||
struct list_head *item)
|
||||
{
|
||||
struct xfs_refcount_intent *refc;
|
||||
struct xfs_refcount_intent *ri;
|
||||
|
||||
refc = container_of(item, struct xfs_refcount_intent, ri_list);
|
||||
kmem_cache_free(xfs_refcount_intent_cache, refc);
|
||||
ri = container_of(item, struct xfs_refcount_intent, ri_list);
|
||||
kmem_cache_free(xfs_refcount_intent_cache, ri);
|
||||
}
|
||||
|
||||
const struct xfs_defer_op_type xfs_refcount_update_defer_type = {
|
||||
@ -433,15 +423,15 @@ const struct xfs_defer_op_type xfs_refcount_update_defer_type = {
|
||||
static inline bool
|
||||
xfs_cui_validate_phys(
|
||||
struct xfs_mount *mp,
|
||||
struct xfs_phys_extent *refc)
|
||||
struct xfs_phys_extent *pmap)
|
||||
{
|
||||
if (!xfs_has_reflink(mp))
|
||||
return false;
|
||||
|
||||
if (refc->pe_flags & ~XFS_REFCOUNT_EXTENT_FLAGS)
|
||||
if (pmap->pe_flags & ~XFS_REFCOUNT_EXTENT_FLAGS)
|
||||
return false;
|
||||
|
||||
switch (refc->pe_flags & XFS_REFCOUNT_EXTENT_TYPE_MASK) {
|
||||
switch (pmap->pe_flags & XFS_REFCOUNT_EXTENT_TYPE_MASK) {
|
||||
case XFS_REFCOUNT_INCREASE:
|
||||
case XFS_REFCOUNT_DECREASE:
|
||||
case XFS_REFCOUNT_ALLOC_COW:
|
||||
@ -451,7 +441,7 @@ xfs_cui_validate_phys(
|
||||
return false;
|
||||
}
|
||||
|
||||
return xfs_verify_fsbext(mp, refc->pe_startblock, refc->pe_len);
|
||||
return xfs_verify_fsbext(mp, pmap->pe_startblock, pmap->pe_len);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -463,18 +453,13 @@ xfs_cui_item_recover(
|
||||
struct xfs_log_item *lip,
|
||||
struct list_head *capture_list)
|
||||
{
|
||||
struct xfs_bmbt_irec irec;
|
||||
struct xfs_cui_log_item *cuip = CUI_ITEM(lip);
|
||||
struct xfs_phys_extent *refc;
|
||||
struct xfs_cud_log_item *cudp;
|
||||
struct xfs_trans *tp;
|
||||
struct xfs_btree_cur *rcur = NULL;
|
||||
struct xfs_mount *mp = lip->li_log->l_mp;
|
||||
xfs_fsblock_t new_fsb;
|
||||
xfs_extlen_t new_len;
|
||||
unsigned int refc_type;
|
||||
bool requeue_only = false;
|
||||
enum xfs_refcount_intent_type type;
|
||||
int i;
|
||||
int error = 0;
|
||||
|
||||
@ -513,14 +498,17 @@ xfs_cui_item_recover(
|
||||
cudp = xfs_trans_get_cud(tp, cuip);
|
||||
|
||||
for (i = 0; i < cuip->cui_format.cui_nextents; i++) {
|
||||
refc = &cuip->cui_format.cui_extents[i];
|
||||
refc_type = refc->pe_flags & XFS_REFCOUNT_EXTENT_TYPE_MASK;
|
||||
struct xfs_refcount_intent fake = { };
|
||||
struct xfs_phys_extent *pmap;
|
||||
|
||||
pmap = &cuip->cui_format.cui_extents[i];
|
||||
refc_type = pmap->pe_flags & XFS_REFCOUNT_EXTENT_TYPE_MASK;
|
||||
switch (refc_type) {
|
||||
case XFS_REFCOUNT_INCREASE:
|
||||
case XFS_REFCOUNT_DECREASE:
|
||||
case XFS_REFCOUNT_ALLOC_COW:
|
||||
case XFS_REFCOUNT_FREE_COW:
|
||||
type = refc_type;
|
||||
fake.ri_type = refc_type;
|
||||
break;
|
||||
default:
|
||||
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
|
||||
@ -529,13 +517,12 @@ xfs_cui_item_recover(
|
||||
error = -EFSCORRUPTED;
|
||||
goto abort_error;
|
||||
}
|
||||
if (requeue_only) {
|
||||
new_fsb = refc->pe_startblock;
|
||||
new_len = refc->pe_len;
|
||||
} else
|
||||
|
||||
fake.ri_startblock = pmap->pe_startblock;
|
||||
fake.ri_blockcount = pmap->pe_len;
|
||||
if (!requeue_only)
|
||||
error = xfs_trans_log_finish_refcount_update(tp, cudp,
|
||||
type, refc->pe_startblock, refc->pe_len,
|
||||
&new_fsb, &new_len, &rcur);
|
||||
&fake, &rcur);
|
||||
if (error == -EFSCORRUPTED)
|
||||
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
|
||||
&cuip->cui_format,
|
||||
@ -544,10 +531,13 @@ xfs_cui_item_recover(
|
||||
goto abort_error;
|
||||
|
||||
/* Requeue what we didn't finish. */
|
||||
if (new_len > 0) {
|
||||
irec.br_startblock = new_fsb;
|
||||
irec.br_blockcount = new_len;
|
||||
switch (type) {
|
||||
if (fake.ri_blockcount > 0) {
|
||||
struct xfs_bmbt_irec irec = {
|
||||
.br_startblock = fake.ri_startblock,
|
||||
.br_blockcount = fake.ri_blockcount,
|
||||
};
|
||||
|
||||
switch (fake.ri_type) {
|
||||
case XFS_REFCOUNT_INCREASE:
|
||||
xfs_refcount_increase_extent(tp, &irec);
|
||||
break;
|
||||
@ -596,18 +586,18 @@ xfs_cui_item_relog(
|
||||
{
|
||||
struct xfs_cud_log_item *cudp;
|
||||
struct xfs_cui_log_item *cuip;
|
||||
struct xfs_phys_extent *extp;
|
||||
struct xfs_phys_extent *pmap;
|
||||
unsigned int count;
|
||||
|
||||
count = CUI_ITEM(intent)->cui_format.cui_nextents;
|
||||
extp = CUI_ITEM(intent)->cui_format.cui_extents;
|
||||
pmap = CUI_ITEM(intent)->cui_format.cui_extents;
|
||||
|
||||
tp->t_flags |= XFS_TRANS_DIRTY;
|
||||
cudp = xfs_trans_get_cud(tp, CUI_ITEM(intent));
|
||||
set_bit(XFS_LI_DIRTY, &cudp->cud_item.li_flags);
|
||||
|
||||
cuip = xfs_cui_init(tp->t_mountp, count);
|
||||
memcpy(cuip->cui_format.cui_extents, extp, count * sizeof(*extp));
|
||||
memcpy(cuip->cui_format.cui_extents, pmap, count * sizeof(*pmap));
|
||||
atomic_set(&cuip->cui_next_extent, count);
|
||||
xfs_trans_add_item(tp, &cuip->cui_item);
|
||||
set_bit(XFS_LI_DIRTY, &cuip->cui_item.li_flags);
|
||||
|
@ -244,40 +244,40 @@ xfs_trans_get_rud(
|
||||
/* Set the map extent flags for this reverse mapping. */
|
||||
static void
|
||||
xfs_trans_set_rmap_flags(
|
||||
struct xfs_map_extent *rmap,
|
||||
struct xfs_map_extent *map,
|
||||
enum xfs_rmap_intent_type type,
|
||||
int whichfork,
|
||||
xfs_exntst_t state)
|
||||
{
|
||||
rmap->me_flags = 0;
|
||||
map->me_flags = 0;
|
||||
if (state == XFS_EXT_UNWRITTEN)
|
||||
rmap->me_flags |= XFS_RMAP_EXTENT_UNWRITTEN;
|
||||
map->me_flags |= XFS_RMAP_EXTENT_UNWRITTEN;
|
||||
if (whichfork == XFS_ATTR_FORK)
|
||||
rmap->me_flags |= XFS_RMAP_EXTENT_ATTR_FORK;
|
||||
map->me_flags |= XFS_RMAP_EXTENT_ATTR_FORK;
|
||||
switch (type) {
|
||||
case XFS_RMAP_MAP:
|
||||
rmap->me_flags |= XFS_RMAP_EXTENT_MAP;
|
||||
map->me_flags |= XFS_RMAP_EXTENT_MAP;
|
||||
break;
|
||||
case XFS_RMAP_MAP_SHARED:
|
||||
rmap->me_flags |= XFS_RMAP_EXTENT_MAP_SHARED;
|
||||
map->me_flags |= XFS_RMAP_EXTENT_MAP_SHARED;
|
||||
break;
|
||||
case XFS_RMAP_UNMAP:
|
||||
rmap->me_flags |= XFS_RMAP_EXTENT_UNMAP;
|
||||
map->me_flags |= XFS_RMAP_EXTENT_UNMAP;
|
||||
break;
|
||||
case XFS_RMAP_UNMAP_SHARED:
|
||||
rmap->me_flags |= XFS_RMAP_EXTENT_UNMAP_SHARED;
|
||||
map->me_flags |= XFS_RMAP_EXTENT_UNMAP_SHARED;
|
||||
break;
|
||||
case XFS_RMAP_CONVERT:
|
||||
rmap->me_flags |= XFS_RMAP_EXTENT_CONVERT;
|
||||
map->me_flags |= XFS_RMAP_EXTENT_CONVERT;
|
||||
break;
|
||||
case XFS_RMAP_CONVERT_SHARED:
|
||||
rmap->me_flags |= XFS_RMAP_EXTENT_CONVERT_SHARED;
|
||||
map->me_flags |= XFS_RMAP_EXTENT_CONVERT_SHARED;
|
||||
break;
|
||||
case XFS_RMAP_ALLOC:
|
||||
rmap->me_flags |= XFS_RMAP_EXTENT_ALLOC;
|
||||
map->me_flags |= XFS_RMAP_EXTENT_ALLOC;
|
||||
break;
|
||||
case XFS_RMAP_FREE:
|
||||
rmap->me_flags |= XFS_RMAP_EXTENT_FREE;
|
||||
map->me_flags |= XFS_RMAP_EXTENT_FREE;
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
@ -293,19 +293,12 @@ static int
|
||||
xfs_trans_log_finish_rmap_update(
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_rud_log_item *rudp,
|
||||
enum xfs_rmap_intent_type type,
|
||||
uint64_t owner,
|
||||
int whichfork,
|
||||
xfs_fileoff_t startoff,
|
||||
xfs_fsblock_t startblock,
|
||||
xfs_filblks_t blockcount,
|
||||
xfs_exntst_t state,
|
||||
struct xfs_rmap_intent *ri,
|
||||
struct xfs_btree_cur **pcur)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = xfs_rmap_finish_one(tp, type, owner, whichfork, startoff,
|
||||
startblock, blockcount, state, pcur);
|
||||
error = xfs_rmap_finish_one(tp, ri, pcur);
|
||||
|
||||
/*
|
||||
* Mark the transaction dirty, even on error. This ensures the
|
||||
@ -342,7 +335,7 @@ STATIC void
|
||||
xfs_rmap_update_log_item(
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_rui_log_item *ruip,
|
||||
struct xfs_rmap_intent *rmap)
|
||||
struct xfs_rmap_intent *ri)
|
||||
{
|
||||
uint next_extent;
|
||||
struct xfs_map_extent *map;
|
||||
@ -358,12 +351,12 @@ xfs_rmap_update_log_item(
|
||||
next_extent = atomic_inc_return(&ruip->rui_next_extent) - 1;
|
||||
ASSERT(next_extent < ruip->rui_format.rui_nextents);
|
||||
map = &ruip->rui_format.rui_extents[next_extent];
|
||||
map->me_owner = rmap->ri_owner;
|
||||
map->me_startblock = rmap->ri_bmap.br_startblock;
|
||||
map->me_startoff = rmap->ri_bmap.br_startoff;
|
||||
map->me_len = rmap->ri_bmap.br_blockcount;
|
||||
xfs_trans_set_rmap_flags(map, rmap->ri_type, rmap->ri_whichfork,
|
||||
rmap->ri_bmap.br_state);
|
||||
map->me_owner = ri->ri_owner;
|
||||
map->me_startblock = ri->ri_bmap.br_startblock;
|
||||
map->me_startoff = ri->ri_bmap.br_startoff;
|
||||
map->me_len = ri->ri_bmap.br_blockcount;
|
||||
xfs_trans_set_rmap_flags(map, ri->ri_type, ri->ri_whichfork,
|
||||
ri->ri_bmap.br_state);
|
||||
}
|
||||
|
||||
static struct xfs_log_item *
|
||||
@ -375,15 +368,15 @@ xfs_rmap_update_create_intent(
|
||||
{
|
||||
struct xfs_mount *mp = tp->t_mountp;
|
||||
struct xfs_rui_log_item *ruip = xfs_rui_init(mp, count);
|
||||
struct xfs_rmap_intent *rmap;
|
||||
struct xfs_rmap_intent *ri;
|
||||
|
||||
ASSERT(count > 0);
|
||||
|
||||
xfs_trans_add_item(tp, &ruip->rui_item);
|
||||
if (sort)
|
||||
list_sort(mp, items, xfs_rmap_update_diff_items);
|
||||
list_for_each_entry(rmap, items, ri_list)
|
||||
xfs_rmap_update_log_item(tp, ruip, rmap);
|
||||
list_for_each_entry(ri, items, ri_list)
|
||||
xfs_rmap_update_log_item(tp, ruip, ri);
|
||||
return &ruip->rui_item;
|
||||
}
|
||||
|
||||
@ -405,16 +398,14 @@ xfs_rmap_update_finish_item(
|
||||
struct list_head *item,
|
||||
struct xfs_btree_cur **state)
|
||||
{
|
||||
struct xfs_rmap_intent *rmap;
|
||||
struct xfs_rmap_intent *ri;
|
||||
int error;
|
||||
|
||||
rmap = container_of(item, struct xfs_rmap_intent, ri_list);
|
||||
error = xfs_trans_log_finish_rmap_update(tp, RUD_ITEM(done),
|
||||
rmap->ri_type, rmap->ri_owner, rmap->ri_whichfork,
|
||||
rmap->ri_bmap.br_startoff, rmap->ri_bmap.br_startblock,
|
||||
rmap->ri_bmap.br_blockcount, rmap->ri_bmap.br_state,
|
||||
ri = container_of(item, struct xfs_rmap_intent, ri_list);
|
||||
|
||||
error = xfs_trans_log_finish_rmap_update(tp, RUD_ITEM(done), ri,
|
||||
state);
|
||||
kmem_cache_free(xfs_rmap_intent_cache, rmap);
|
||||
kmem_cache_free(xfs_rmap_intent_cache, ri);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -431,10 +422,10 @@ STATIC void
|
||||
xfs_rmap_update_cancel_item(
|
||||
struct list_head *item)
|
||||
{
|
||||
struct xfs_rmap_intent *rmap;
|
||||
struct xfs_rmap_intent *ri;
|
||||
|
||||
rmap = container_of(item, struct xfs_rmap_intent, ri_list);
|
||||
kmem_cache_free(xfs_rmap_intent_cache, rmap);
|
||||
ri = container_of(item, struct xfs_rmap_intent, ri_list);
|
||||
kmem_cache_free(xfs_rmap_intent_cache, ri);
|
||||
}
|
||||
|
||||
const struct xfs_defer_op_type xfs_rmap_update_defer_type = {
|
||||
@ -451,15 +442,15 @@ const struct xfs_defer_op_type xfs_rmap_update_defer_type = {
|
||||
static inline bool
|
||||
xfs_rui_validate_map(
|
||||
struct xfs_mount *mp,
|
||||
struct xfs_map_extent *rmap)
|
||||
struct xfs_map_extent *map)
|
||||
{
|
||||
if (!xfs_has_rmapbt(mp))
|
||||
return false;
|
||||
|
||||
if (rmap->me_flags & ~XFS_RMAP_EXTENT_FLAGS)
|
||||
if (map->me_flags & ~XFS_RMAP_EXTENT_FLAGS)
|
||||
return false;
|
||||
|
||||
switch (rmap->me_flags & XFS_RMAP_EXTENT_TYPE_MASK) {
|
||||
switch (map->me_flags & XFS_RMAP_EXTENT_TYPE_MASK) {
|
||||
case XFS_RMAP_EXTENT_MAP:
|
||||
case XFS_RMAP_EXTENT_MAP_SHARED:
|
||||
case XFS_RMAP_EXTENT_UNMAP:
|
||||
@ -473,14 +464,14 @@ xfs_rui_validate_map(
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!XFS_RMAP_NON_INODE_OWNER(rmap->me_owner) &&
|
||||
!xfs_verify_ino(mp, rmap->me_owner))
|
||||
if (!XFS_RMAP_NON_INODE_OWNER(map->me_owner) &&
|
||||
!xfs_verify_ino(mp, map->me_owner))
|
||||
return false;
|
||||
|
||||
if (!xfs_verify_fileext(mp, rmap->me_startoff, rmap->me_len))
|
||||
if (!xfs_verify_fileext(mp, map->me_startoff, map->me_len))
|
||||
return false;
|
||||
|
||||
return xfs_verify_fsbext(mp, rmap->me_startblock, rmap->me_len);
|
||||
return xfs_verify_fsbext(mp, map->me_startblock, map->me_len);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -493,15 +484,11 @@ xfs_rui_item_recover(
|
||||
struct list_head *capture_list)
|
||||
{
|
||||
struct xfs_rui_log_item *ruip = RUI_ITEM(lip);
|
||||
struct xfs_map_extent *rmap;
|
||||
struct xfs_rud_log_item *rudp;
|
||||
struct xfs_trans *tp;
|
||||
struct xfs_btree_cur *rcur = NULL;
|
||||
struct xfs_mount *mp = lip->li_log->l_mp;
|
||||
enum xfs_rmap_intent_type type;
|
||||
xfs_exntst_t state;
|
||||
int i;
|
||||
int whichfork;
|
||||
int error = 0;
|
||||
|
||||
/*
|
||||
@ -526,35 +513,34 @@ xfs_rui_item_recover(
|
||||
rudp = xfs_trans_get_rud(tp, ruip);
|
||||
|
||||
for (i = 0; i < ruip->rui_format.rui_nextents; i++) {
|
||||
rmap = &ruip->rui_format.rui_extents[i];
|
||||
state = (rmap->me_flags & XFS_RMAP_EXTENT_UNWRITTEN) ?
|
||||
XFS_EXT_UNWRITTEN : XFS_EXT_NORM;
|
||||
whichfork = (rmap->me_flags & XFS_RMAP_EXTENT_ATTR_FORK) ?
|
||||
XFS_ATTR_FORK : XFS_DATA_FORK;
|
||||
switch (rmap->me_flags & XFS_RMAP_EXTENT_TYPE_MASK) {
|
||||
struct xfs_rmap_intent fake = { };
|
||||
struct xfs_map_extent *map;
|
||||
|
||||
map = &ruip->rui_format.rui_extents[i];
|
||||
switch (map->me_flags & XFS_RMAP_EXTENT_TYPE_MASK) {
|
||||
case XFS_RMAP_EXTENT_MAP:
|
||||
type = XFS_RMAP_MAP;
|
||||
fake.ri_type = XFS_RMAP_MAP;
|
||||
break;
|
||||
case XFS_RMAP_EXTENT_MAP_SHARED:
|
||||
type = XFS_RMAP_MAP_SHARED;
|
||||
fake.ri_type = XFS_RMAP_MAP_SHARED;
|
||||
break;
|
||||
case XFS_RMAP_EXTENT_UNMAP:
|
||||
type = XFS_RMAP_UNMAP;
|
||||
fake.ri_type = XFS_RMAP_UNMAP;
|
||||
break;
|
||||
case XFS_RMAP_EXTENT_UNMAP_SHARED:
|
||||
type = XFS_RMAP_UNMAP_SHARED;
|
||||
fake.ri_type = XFS_RMAP_UNMAP_SHARED;
|
||||
break;
|
||||
case XFS_RMAP_EXTENT_CONVERT:
|
||||
type = XFS_RMAP_CONVERT;
|
||||
fake.ri_type = XFS_RMAP_CONVERT;
|
||||
break;
|
||||
case XFS_RMAP_EXTENT_CONVERT_SHARED:
|
||||
type = XFS_RMAP_CONVERT_SHARED;
|
||||
fake.ri_type = XFS_RMAP_CONVERT_SHARED;
|
||||
break;
|
||||
case XFS_RMAP_EXTENT_ALLOC:
|
||||
type = XFS_RMAP_ALLOC;
|
||||
fake.ri_type = XFS_RMAP_ALLOC;
|
||||
break;
|
||||
case XFS_RMAP_EXTENT_FREE:
|
||||
type = XFS_RMAP_FREE;
|
||||
fake.ri_type = XFS_RMAP_FREE;
|
||||
break;
|
||||
default:
|
||||
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
|
||||
@ -563,13 +549,21 @@ xfs_rui_item_recover(
|
||||
error = -EFSCORRUPTED;
|
||||
goto abort_error;
|
||||
}
|
||||
error = xfs_trans_log_finish_rmap_update(tp, rudp, type,
|
||||
rmap->me_owner, whichfork,
|
||||
rmap->me_startoff, rmap->me_startblock,
|
||||
rmap->me_len, state, &rcur);
|
||||
|
||||
fake.ri_owner = map->me_owner;
|
||||
fake.ri_whichfork = (map->me_flags & XFS_RMAP_EXTENT_ATTR_FORK) ?
|
||||
XFS_ATTR_FORK : XFS_DATA_FORK;
|
||||
fake.ri_bmap.br_startblock = map->me_startblock;
|
||||
fake.ri_bmap.br_startoff = map->me_startoff;
|
||||
fake.ri_bmap.br_blockcount = map->me_len;
|
||||
fake.ri_bmap.br_state = (map->me_flags & XFS_RMAP_EXTENT_UNWRITTEN) ?
|
||||
XFS_EXT_UNWRITTEN : XFS_EXT_NORM;
|
||||
|
||||
error = xfs_trans_log_finish_rmap_update(tp, rudp, &fake,
|
||||
&rcur);
|
||||
if (error == -EFSCORRUPTED)
|
||||
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
|
||||
rmap, sizeof(*rmap));
|
||||
map, sizeof(*map));
|
||||
if (error)
|
||||
goto abort_error;
|
||||
|
||||
@ -600,18 +594,18 @@ xfs_rui_item_relog(
|
||||
{
|
||||
struct xfs_rud_log_item *rudp;
|
||||
struct xfs_rui_log_item *ruip;
|
||||
struct xfs_map_extent *extp;
|
||||
struct xfs_map_extent *map;
|
||||
unsigned int count;
|
||||
|
||||
count = RUI_ITEM(intent)->rui_format.rui_nextents;
|
||||
extp = RUI_ITEM(intent)->rui_format.rui_extents;
|
||||
map = RUI_ITEM(intent)->rui_format.rui_extents;
|
||||
|
||||
tp->t_flags |= XFS_TRANS_DIRTY;
|
||||
rudp = xfs_trans_get_rud(tp, RUI_ITEM(intent));
|
||||
set_bit(XFS_LI_DIRTY, &rudp->rud_item.li_flags);
|
||||
|
||||
ruip = xfs_rui_init(tp->t_mountp, count);
|
||||
memcpy(ruip->rui_format.rui_extents, extp, count * sizeof(*extp));
|
||||
memcpy(ruip->rui_format.rui_extents, map, count * sizeof(*map));
|
||||
atomic_set(&ruip->rui_next_extent, count);
|
||||
xfs_trans_add_item(tp, &ruip->rui_item);
|
||||
set_bit(XFS_LI_DIRTY, &ruip->rui_item.li_flags);
|
||||
|
@ -69,7 +69,7 @@ static struct attribute *xfs_mp_attrs[] = {
|
||||
};
|
||||
ATTRIBUTE_GROUPS(xfs_mp);
|
||||
|
||||
struct kobj_type xfs_mp_ktype = {
|
||||
const struct kobj_type xfs_mp_ktype = {
|
||||
.release = xfs_sysfs_release,
|
||||
.sysfs_ops = &xfs_sysfs_ops,
|
||||
.default_groups = xfs_mp_groups,
|
||||
@ -266,7 +266,7 @@ static struct attribute *xfs_dbg_attrs[] = {
|
||||
};
|
||||
ATTRIBUTE_GROUPS(xfs_dbg);
|
||||
|
||||
struct kobj_type xfs_dbg_ktype = {
|
||||
const struct kobj_type xfs_dbg_ktype = {
|
||||
.release = xfs_sysfs_release,
|
||||
.sysfs_ops = &xfs_sysfs_ops,
|
||||
.default_groups = xfs_dbg_groups,
|
||||
@ -324,7 +324,7 @@ static struct attribute *xfs_stats_attrs[] = {
|
||||
};
|
||||
ATTRIBUTE_GROUPS(xfs_stats);
|
||||
|
||||
struct kobj_type xfs_stats_ktype = {
|
||||
const struct kobj_type xfs_stats_ktype = {
|
||||
.release = xfs_sysfs_release,
|
||||
.sysfs_ops = &xfs_sysfs_ops,
|
||||
.default_groups = xfs_stats_groups,
|
||||
@ -410,7 +410,7 @@ static struct attribute *xfs_log_attrs[] = {
|
||||
};
|
||||
ATTRIBUTE_GROUPS(xfs_log);
|
||||
|
||||
struct kobj_type xfs_log_ktype = {
|
||||
const struct kobj_type xfs_log_ktype = {
|
||||
.release = xfs_sysfs_release,
|
||||
.sysfs_ops = &xfs_sysfs_ops,
|
||||
.default_groups = xfs_log_groups,
|
||||
@ -564,13 +564,13 @@ static struct attribute *xfs_error_attrs[] = {
|
||||
};
|
||||
ATTRIBUTE_GROUPS(xfs_error);
|
||||
|
||||
static struct kobj_type xfs_error_cfg_ktype = {
|
||||
static const struct kobj_type xfs_error_cfg_ktype = {
|
||||
.release = xfs_sysfs_release,
|
||||
.sysfs_ops = &xfs_sysfs_ops,
|
||||
.default_groups = xfs_error_groups,
|
||||
};
|
||||
|
||||
static struct kobj_type xfs_error_ktype = {
|
||||
static const struct kobj_type xfs_error_ktype = {
|
||||
.release = xfs_sysfs_release,
|
||||
.sysfs_ops = &xfs_sysfs_ops,
|
||||
};
|
||||
|
@ -7,10 +7,10 @@
|
||||
#ifndef __XFS_SYSFS_H__
|
||||
#define __XFS_SYSFS_H__
|
||||
|
||||
extern struct kobj_type xfs_mp_ktype; /* xfs_mount */
|
||||
extern struct kobj_type xfs_dbg_ktype; /* debug */
|
||||
extern struct kobj_type xfs_log_ktype; /* xlog */
|
||||
extern struct kobj_type xfs_stats_ktype; /* stats */
|
||||
extern const struct kobj_type xfs_mp_ktype; /* xfs_mount */
|
||||
extern const struct kobj_type xfs_dbg_ktype; /* debug */
|
||||
extern const struct kobj_type xfs_log_ktype; /* xlog */
|
||||
extern const struct kobj_type xfs_stats_ktype; /* stats */
|
||||
|
||||
static inline struct xfs_kobj *
|
||||
to_kobj(struct kobject *kobject)
|
||||
@ -28,7 +28,7 @@ xfs_sysfs_release(struct kobject *kobject)
|
||||
static inline int
|
||||
xfs_sysfs_init(
|
||||
struct xfs_kobj *kobj,
|
||||
struct kobj_type *ktype,
|
||||
const struct kobj_type *ktype,
|
||||
struct xfs_kobj *parent_kobj,
|
||||
const char *name)
|
||||
{
|
||||
|
@ -3207,17 +3207,14 @@ DEFINE_REFCOUNT_DEFERRED_EVENT(xfs_refcount_deferred);
|
||||
|
||||
TRACE_EVENT(xfs_refcount_finish_one_leftover,
|
||||
TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno,
|
||||
int type, xfs_agblock_t agbno, xfs_extlen_t len,
|
||||
xfs_agblock_t new_agbno, xfs_extlen_t new_len),
|
||||
TP_ARGS(mp, agno, type, agbno, len, new_agbno, new_len),
|
||||
int type, xfs_agblock_t agbno, xfs_extlen_t len),
|
||||
TP_ARGS(mp, agno, type, agbno, len),
|
||||
TP_STRUCT__entry(
|
||||
__field(dev_t, dev)
|
||||
__field(xfs_agnumber_t, agno)
|
||||
__field(int, type)
|
||||
__field(xfs_agblock_t, agbno)
|
||||
__field(xfs_extlen_t, len)
|
||||
__field(xfs_agblock_t, new_agbno)
|
||||
__field(xfs_extlen_t, new_len)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->dev = mp->m_super->s_dev;
|
||||
@ -3225,17 +3222,13 @@ TRACE_EVENT(xfs_refcount_finish_one_leftover,
|
||||
__entry->type = type;
|
||||
__entry->agbno = agbno;
|
||||
__entry->len = len;
|
||||
__entry->new_agbno = new_agbno;
|
||||
__entry->new_len = new_len;
|
||||
),
|
||||
TP_printk("dev %d:%d type %d agno 0x%x agbno 0x%x fsbcount 0x%x new_agbno 0x%x new_fsbcount 0x%x",
|
||||
TP_printk("dev %d:%d type %d agno 0x%x agbno 0x%x fsbcount 0x%x",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
__entry->type,
|
||||
__entry->agno,
|
||||
__entry->agbno,
|
||||
__entry->len,
|
||||
__entry->new_agbno,
|
||||
__entry->new_len)
|
||||
__entry->len)
|
||||
);
|
||||
|
||||
/* simple inode-based error/%ip tracepoint class */
|
||||
|
Loading…
Reference in New Issue
Block a user