mirror of
https://github.com/edk2-porting/linux-next.git
synced 2025-01-13 16:14:26 +08:00
XFS changes for 4.21:
- Fix CoW remapping of extremely fragmented file areas - Fix a zero-length symlink verifier error - Constify some of the rmap owner structures for per-AG metadata - Precalculate inode geometry for later use - Fix scrub counting problems - Don't crash when rtsummary inode is null - Fix x32 ioctl operation - Fix enum->string mappings for ftrace output - Cache realtime summary information in memory -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEUzaAxoMeQq6m2jMV+H93GTRKtOsFAlwedm4ACgkQ+H93GTRK tOumSBAAjP9nFAWmI9n/4GEyNI7p6Iz26q42vePiX7FspJY2iWG38gf5PyRarL7X eWzmUhUJVQ3koA4+h+ImGPWwjZAyDUug7r437sPPPkcMvG9WKrj8A2M+kQve39NB kCaXsRJFEvOdFXTMwTzCMrZrHa1b/slqj65eoUyXI7dzT0vwuU8Nj8CX6//zOHD2 4i7yiyGGnZvQ+Ql8ad+ck7LjooeBUzl3XBeOHlFZAO+gDCu6o1TUqO+x8HZPy58N sfBLY/9vqlzEN8EpWjiTdI+GNH0zhO0tJQI5YJlGqa6SpIC78fWElfFF0A9CUXy4 meKc9VmJ5oYi0Rg62S3pKTRZWtkr9FddBjS/C0thvXIpw6CSmHz/ED41P/wrtnI+ vbknTXeiLeCuTTLtnYWJNIW1kvWjS2vXlQQT5jt/rp49ZqzfetM9nuopES0CcnCm a8K++V2LZuYEPzM2fKQgAdd5z02BYeNu8uaEBEHcAWDUnVo/bKInp87dEiQZ5GXx PBfIfOuqVooCppp9w1T7nzshI0R3k+LQj2R4S0d039hfEw8eQmPu39rfvugy6YwI qCZo8uErzWmqF7T4EXMtGu1FS8xIwyLPyiqcsCd8g+zep95iVySSrhha+3DgR/mG 85s4VOE5aWijBrRZixIIqF1bIc+LPE/miBEXIyCsBPRD52+YQcQ= =P0gt -----END PGP SIGNATURE----- Merge tag 'xfs-4.21-merge-2' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux Pull XFS updates from Darrick Wong: - Fix CoW remapping of extremely fragmented file areas - Fix a zero-length symlink verifier error - Constify some of the rmap owner structures for per-AG metadata - Precalculate inode geometry for later use - Fix scrub counting problems - Don't crash when rtsummary inode is null - Fix x32 ioctl operation - Fix enum->string mappings for ftrace output - Cache realtime summary information in memory * tag 'xfs-4.21-merge-2' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: (24 commits) xfs: reallocate realtime summary cache on growfs xfs: stringify scrub types in ftrace output xfs: stringify btree cursor types in ftrace output xfs: move XFS_INODE_FORMAT_STR mappings to libxfs xfs: move XFS_AG_BTREE_CMP_FORMAT_STR mappings to libxfs xfs: fix symbolic enum printing in ftrace output xfs: fix function pointer type in ftrace format xfs: Fix x32 ioctls when cmd numbers differ from ia32. xfs: Fix bulkstat compat ioctls on x32 userspace. xfs: Align compat attrlist_by_handle with native implementation. xfs: require both realtime inodes to mount xfs: cache minimum realtime summary level xfs: count inode blocks correctly in inobt scrub xfs: precalculate cluster alignment in inodes and blocks xfs: precalculate inodes and blocks per inode cluster xfs: add a block to inode count converter xfs: remove xfs_rmap_ag_owner and friends xfs: const-ify xfs_owner_info arguments xfs: streamline defer op type handling xfs: idiotproof defer op type configuration ...
This commit is contained in:
commit
47a43f2f0c
@ -414,7 +414,6 @@ xfs_ag_extend_space(
|
||||
struct aghdr_init_data *id,
|
||||
xfs_extlen_t len)
|
||||
{
|
||||
struct xfs_owner_info oinfo;
|
||||
struct xfs_buf *bp;
|
||||
struct xfs_agi *agi;
|
||||
struct xfs_agf *agf;
|
||||
@ -448,17 +447,17 @@ xfs_ag_extend_space(
|
||||
/*
|
||||
* Free the new space.
|
||||
*
|
||||
* XFS_RMAP_OWN_NULL is used here to tell the rmap btree that
|
||||
* XFS_RMAP_OINFO_SKIP_UPDATE is used here to tell the rmap btree that
|
||||
* this doesn't actually exist in the rmap btree.
|
||||
*/
|
||||
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_NULL);
|
||||
error = xfs_rmap_free(tp, bp, id->agno,
|
||||
be32_to_cpu(agf->agf_length) - len,
|
||||
len, &oinfo);
|
||||
len, &XFS_RMAP_OINFO_SKIP_UPDATE);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return xfs_free_extent(tp, XFS_AGB_TO_FSB(mp, id->agno,
|
||||
be32_to_cpu(agf->agf_length) - len),
|
||||
len, &oinfo, XFS_AG_RESV_NONE);
|
||||
len, &XFS_RMAP_OINFO_SKIP_UPDATE,
|
||||
XFS_AG_RESV_NONE);
|
||||
}
|
||||
|
@ -1594,7 +1594,6 @@ xfs_alloc_ag_vextent_small(
|
||||
xfs_extlen_t *flenp, /* result length */
|
||||
int *stat) /* status: 0-freelist, 1-normal/none */
|
||||
{
|
||||
struct xfs_owner_info oinfo;
|
||||
int error;
|
||||
xfs_agblock_t fbno;
|
||||
xfs_extlen_t flen;
|
||||
@ -1648,9 +1647,8 @@ xfs_alloc_ag_vextent_small(
|
||||
* doesn't live in the free space, we need to clear
|
||||
* out the OWN_AG rmap.
|
||||
*/
|
||||
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_AG);
|
||||
error = xfs_rmap_free(args->tp, args->agbp, args->agno,
|
||||
fbno, 1, &oinfo);
|
||||
fbno, 1, &XFS_RMAP_OINFO_AG);
|
||||
if (error)
|
||||
goto error0;
|
||||
|
||||
@ -1694,28 +1692,28 @@ error0:
|
||||
*/
|
||||
STATIC int
|
||||
xfs_free_ag_extent(
|
||||
xfs_trans_t *tp,
|
||||
xfs_buf_t *agbp,
|
||||
xfs_agnumber_t agno,
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
struct xfs_owner_info *oinfo,
|
||||
enum xfs_ag_resv_type type)
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_buf *agbp,
|
||||
xfs_agnumber_t agno,
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
const struct xfs_owner_info *oinfo,
|
||||
enum xfs_ag_resv_type type)
|
||||
{
|
||||
xfs_btree_cur_t *bno_cur; /* cursor for by-block btree */
|
||||
xfs_btree_cur_t *cnt_cur; /* cursor for by-size btree */
|
||||
int error; /* error return value */
|
||||
xfs_agblock_t gtbno; /* start of right neighbor block */
|
||||
xfs_extlen_t gtlen; /* length of right neighbor block */
|
||||
int haveleft; /* have a left neighbor block */
|
||||
int haveright; /* have a right neighbor block */
|
||||
int i; /* temp, result code */
|
||||
xfs_agblock_t ltbno; /* start of left neighbor block */
|
||||
xfs_extlen_t ltlen; /* length of left neighbor block */
|
||||
xfs_mount_t *mp; /* mount point struct for filesystem */
|
||||
xfs_agblock_t nbno; /* new starting block of freespace */
|
||||
xfs_extlen_t nlen; /* new length of freespace */
|
||||
xfs_perag_t *pag; /* per allocation group data */
|
||||
struct xfs_mount *mp;
|
||||
struct xfs_perag *pag;
|
||||
struct xfs_btree_cur *bno_cur;
|
||||
struct xfs_btree_cur *cnt_cur;
|
||||
xfs_agblock_t gtbno; /* start of right neighbor */
|
||||
xfs_extlen_t gtlen; /* length of right neighbor */
|
||||
xfs_agblock_t ltbno; /* start of left neighbor */
|
||||
xfs_extlen_t ltlen; /* length of left neighbor */
|
||||
xfs_agblock_t nbno; /* new starting block of freesp */
|
||||
xfs_extlen_t nlen; /* new length of freespace */
|
||||
int haveleft; /* have a left neighbor */
|
||||
int haveright; /* have a right neighbor */
|
||||
int i;
|
||||
int error;
|
||||
|
||||
bno_cur = cnt_cur = NULL;
|
||||
mp = tp->t_mountp;
|
||||
@ -2314,10 +2312,11 @@ xfs_alloc_fix_freelist(
|
||||
* repair/rmap.c in xfsprogs for details.
|
||||
*/
|
||||
memset(&targs, 0, sizeof(targs));
|
||||
/* struct copy below */
|
||||
if (flags & XFS_ALLOC_FLAG_NORMAP)
|
||||
xfs_rmap_skip_owner_update(&targs.oinfo);
|
||||
targs.oinfo = XFS_RMAP_OINFO_SKIP_UPDATE;
|
||||
else
|
||||
xfs_rmap_ag_owner(&targs.oinfo, XFS_RMAP_OWN_AG);
|
||||
targs.oinfo = XFS_RMAP_OINFO_AG;
|
||||
while (!(flags & XFS_ALLOC_FLAG_NOSHRINK) && pag->pagf_flcount > need) {
|
||||
error = xfs_alloc_get_freelist(tp, agbp, &bno, 0);
|
||||
if (error)
|
||||
@ -2435,7 +2434,6 @@ xfs_alloc_get_freelist(
|
||||
be32_add_cpu(&agf->agf_flcount, -1);
|
||||
xfs_trans_agflist_delta(tp, -1);
|
||||
pag->pagf_flcount--;
|
||||
xfs_perag_put(pag);
|
||||
|
||||
logflags = XFS_AGF_FLFIRST | XFS_AGF_FLCOUNT;
|
||||
if (btreeblk) {
|
||||
@ -2443,6 +2441,7 @@ xfs_alloc_get_freelist(
|
||||
pag->pagf_btreeblks++;
|
||||
logflags |= XFS_AGF_BTREEBLKS;
|
||||
}
|
||||
xfs_perag_put(pag);
|
||||
|
||||
xfs_alloc_log_agf(tp, agbp, logflags);
|
||||
*bnop = bno;
|
||||
@ -3008,21 +3007,21 @@ out:
|
||||
* Just break up the extent address and hand off to xfs_free_ag_extent
|
||||
* after fixing up the freelist.
|
||||
*/
|
||||
int /* error */
|
||||
int
|
||||
__xfs_free_extent(
|
||||
struct xfs_trans *tp, /* transaction pointer */
|
||||
xfs_fsblock_t bno, /* starting block number of extent */
|
||||
xfs_extlen_t len, /* length of extent */
|
||||
struct xfs_owner_info *oinfo, /* extent owner */
|
||||
enum xfs_ag_resv_type type, /* block reservation type */
|
||||
bool skip_discard)
|
||||
struct xfs_trans *tp,
|
||||
xfs_fsblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
const struct xfs_owner_info *oinfo,
|
||||
enum xfs_ag_resv_type type,
|
||||
bool skip_discard)
|
||||
{
|
||||
struct xfs_mount *mp = tp->t_mountp;
|
||||
struct xfs_buf *agbp;
|
||||
xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, bno);
|
||||
xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp, bno);
|
||||
int error;
|
||||
unsigned int busy_flags = 0;
|
||||
struct xfs_mount *mp = tp->t_mountp;
|
||||
struct xfs_buf *agbp;
|
||||
xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, bno);
|
||||
xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp, bno);
|
||||
int error;
|
||||
unsigned int busy_flags = 0;
|
||||
|
||||
ASSERT(len != 0);
|
||||
ASSERT(type != XFS_AG_RESV_AGFL);
|
||||
|
@ -182,7 +182,7 @@ __xfs_free_extent(
|
||||
struct xfs_trans *tp, /* transaction pointer */
|
||||
xfs_fsblock_t bno, /* starting block number of extent */
|
||||
xfs_extlen_t len, /* length of extent */
|
||||
struct xfs_owner_info *oinfo, /* extent owner */
|
||||
const struct xfs_owner_info *oinfo, /* extent owner */
|
||||
enum xfs_ag_resv_type type, /* block reservation type */
|
||||
bool skip_discard);
|
||||
|
||||
@ -191,7 +191,7 @@ xfs_free_extent(
|
||||
struct xfs_trans *tp,
|
||||
xfs_fsblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
struct xfs_owner_info *oinfo,
|
||||
const struct xfs_owner_info *oinfo,
|
||||
enum xfs_ag_resv_type type)
|
||||
{
|
||||
return __xfs_free_extent(tp, bno, len, oinfo, type, false);
|
||||
|
@ -536,7 +536,7 @@ __xfs_bmap_add_free(
|
||||
struct xfs_trans *tp,
|
||||
xfs_fsblock_t bno,
|
||||
xfs_filblks_t len,
|
||||
struct xfs_owner_info *oinfo,
|
||||
const struct xfs_owner_info *oinfo,
|
||||
bool skip_discard)
|
||||
{
|
||||
struct xfs_extent_free_item *new; /* new element */
|
||||
@ -564,7 +564,7 @@ __xfs_bmap_add_free(
|
||||
if (oinfo)
|
||||
new->xefi_oinfo = *oinfo;
|
||||
else
|
||||
xfs_rmap_skip_owner_update(&new->xefi_oinfo);
|
||||
new->xefi_oinfo = XFS_RMAP_OINFO_SKIP_UPDATE;
|
||||
new->xefi_skip_discard = skip_discard;
|
||||
trace_xfs_bmap_free_defer(tp->t_mountp,
|
||||
XFS_FSB_TO_AGNO(tp->t_mountp, bno), 0,
|
||||
@ -3453,7 +3453,7 @@ xfs_bmap_btalloc(
|
||||
args.tp = ap->tp;
|
||||
args.mp = mp;
|
||||
args.fsbno = ap->blkno;
|
||||
xfs_rmap_skip_owner_update(&args.oinfo);
|
||||
args.oinfo = XFS_RMAP_OINFO_SKIP_UPDATE;
|
||||
|
||||
/* Trim the allocation back to the maximum an AG can fit. */
|
||||
args.maxlen = min(ap->length, mp->m_ag_max_usable);
|
||||
|
@ -186,7 +186,7 @@ int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd);
|
||||
int xfs_bmap_set_attrforkoff(struct xfs_inode *ip, int size, int *version);
|
||||
void xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork);
|
||||
void __xfs_bmap_add_free(struct xfs_trans *tp, xfs_fsblock_t bno,
|
||||
xfs_filblks_t len, struct xfs_owner_info *oinfo,
|
||||
xfs_filblks_t len, const struct xfs_owner_info *oinfo,
|
||||
bool skip_discard);
|
||||
void xfs_bmap_compute_maxlevels(struct xfs_mount *mp, int whichfork);
|
||||
int xfs_bmap_first_unused(struct xfs_trans *tp, struct xfs_inode *ip,
|
||||
@ -234,7 +234,7 @@ xfs_bmap_add_free(
|
||||
struct xfs_trans *tp,
|
||||
xfs_fsblock_t bno,
|
||||
xfs_filblks_t len,
|
||||
struct xfs_owner_info *oinfo)
|
||||
const struct xfs_owner_info *oinfo)
|
||||
{
|
||||
__xfs_bmap_add_free(tp, bno, len, oinfo, false);
|
||||
}
|
||||
|
@ -172,7 +172,13 @@
|
||||
* reoccur.
|
||||
*/
|
||||
|
||||
static const struct xfs_defer_op_type *defer_op_types[XFS_DEFER_OPS_TYPE_MAX];
|
||||
static const struct xfs_defer_op_type *defer_op_types[] = {
|
||||
[XFS_DEFER_OPS_TYPE_BMAP] = &xfs_bmap_update_defer_type,
|
||||
[XFS_DEFER_OPS_TYPE_REFCOUNT] = &xfs_refcount_update_defer_type,
|
||||
[XFS_DEFER_OPS_TYPE_RMAP] = &xfs_rmap_update_defer_type,
|
||||
[XFS_DEFER_OPS_TYPE_FREE] = &xfs_extent_free_defer_type,
|
||||
[XFS_DEFER_OPS_TYPE_AGFL_FREE] = &xfs_agfl_free_defer_type,
|
||||
};
|
||||
|
||||
/*
|
||||
* For each pending item in the intake list, log its intent item and the
|
||||
@ -185,15 +191,15 @@ xfs_defer_create_intents(
|
||||
{
|
||||
struct list_head *li;
|
||||
struct xfs_defer_pending *dfp;
|
||||
const struct xfs_defer_op_type *ops;
|
||||
|
||||
list_for_each_entry(dfp, &tp->t_dfops, dfp_list) {
|
||||
dfp->dfp_intent = dfp->dfp_type->create_intent(tp,
|
||||
dfp->dfp_count);
|
||||
ops = defer_op_types[dfp->dfp_type];
|
||||
dfp->dfp_intent = ops->create_intent(tp, dfp->dfp_count);
|
||||
trace_xfs_defer_create_intent(tp->t_mountp, dfp);
|
||||
list_sort(tp->t_mountp, &dfp->dfp_work,
|
||||
dfp->dfp_type->diff_items);
|
||||
list_sort(tp->t_mountp, &dfp->dfp_work, ops->diff_items);
|
||||
list_for_each(li, &dfp->dfp_work)
|
||||
dfp->dfp_type->log_item(tp, dfp->dfp_intent, li);
|
||||
ops->log_item(tp, dfp->dfp_intent, li);
|
||||
}
|
||||
}
|
||||
|
||||
@ -204,14 +210,16 @@ xfs_defer_trans_abort(
|
||||
struct list_head *dop_pending)
|
||||
{
|
||||
struct xfs_defer_pending *dfp;
|
||||
const struct xfs_defer_op_type *ops;
|
||||
|
||||
trace_xfs_defer_trans_abort(tp, _RET_IP_);
|
||||
|
||||
/* Abort intent items that don't have a done item. */
|
||||
list_for_each_entry(dfp, dop_pending, dfp_list) {
|
||||
ops = defer_op_types[dfp->dfp_type];
|
||||
trace_xfs_defer_pending_abort(tp->t_mountp, dfp);
|
||||
if (dfp->dfp_intent && !dfp->dfp_done) {
|
||||
dfp->dfp_type->abort_intent(dfp->dfp_intent);
|
||||
ops->abort_intent(dfp->dfp_intent);
|
||||
dfp->dfp_intent = NULL;
|
||||
}
|
||||
}
|
||||
@ -315,18 +323,20 @@ xfs_defer_cancel_list(
|
||||
struct xfs_defer_pending *pli;
|
||||
struct list_head *pwi;
|
||||
struct list_head *n;
|
||||
const struct xfs_defer_op_type *ops;
|
||||
|
||||
/*
|
||||
* Free the pending items. Caller should already have arranged
|
||||
* for the intent items to be released.
|
||||
*/
|
||||
list_for_each_entry_safe(dfp, pli, dop_list, dfp_list) {
|
||||
ops = defer_op_types[dfp->dfp_type];
|
||||
trace_xfs_defer_cancel_list(mp, dfp);
|
||||
list_del(&dfp->dfp_list);
|
||||
list_for_each_safe(pwi, n, &dfp->dfp_work) {
|
||||
list_del(pwi);
|
||||
dfp->dfp_count--;
|
||||
dfp->dfp_type->cancel_item(pwi);
|
||||
ops->cancel_item(pwi);
|
||||
}
|
||||
ASSERT(dfp->dfp_count == 0);
|
||||
kmem_free(dfp);
|
||||
@ -350,7 +360,7 @@ xfs_defer_finish_noroll(
|
||||
struct list_head *n;
|
||||
void *state;
|
||||
int error = 0;
|
||||
void (*cleanup_fn)(struct xfs_trans *, void *, int);
|
||||
const struct xfs_defer_op_type *ops;
|
||||
LIST_HEAD(dop_pending);
|
||||
|
||||
ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES);
|
||||
@ -373,18 +383,18 @@ xfs_defer_finish_noroll(
|
||||
/* Log an intent-done item for the first pending item. */
|
||||
dfp = list_first_entry(&dop_pending, struct xfs_defer_pending,
|
||||
dfp_list);
|
||||
ops = defer_op_types[dfp->dfp_type];
|
||||
trace_xfs_defer_pending_finish((*tp)->t_mountp, dfp);
|
||||
dfp->dfp_done = dfp->dfp_type->create_done(*tp, dfp->dfp_intent,
|
||||
dfp->dfp_done = ops->create_done(*tp, dfp->dfp_intent,
|
||||
dfp->dfp_count);
|
||||
cleanup_fn = dfp->dfp_type->finish_cleanup;
|
||||
|
||||
/* Finish the work items. */
|
||||
state = NULL;
|
||||
list_for_each_safe(li, n, &dfp->dfp_work) {
|
||||
list_del(li);
|
||||
dfp->dfp_count--;
|
||||
error = dfp->dfp_type->finish_item(*tp, li,
|
||||
dfp->dfp_done, &state);
|
||||
error = ops->finish_item(*tp, li, dfp->dfp_done,
|
||||
&state);
|
||||
if (error == -EAGAIN) {
|
||||
/*
|
||||
* Caller wants a fresh transaction;
|
||||
@ -400,8 +410,8 @@ xfs_defer_finish_noroll(
|
||||
* xfs_defer_cancel will take care of freeing
|
||||
* all these lists and stuff.
|
||||
*/
|
||||
if (cleanup_fn)
|
||||
cleanup_fn(*tp, state, error);
|
||||
if (ops->finish_cleanup)
|
||||
ops->finish_cleanup(*tp, state, error);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@ -413,20 +423,19 @@ xfs_defer_finish_noroll(
|
||||
* a Fresh Transaction while Finishing
|
||||
* Deferred Work" above.
|
||||
*/
|
||||
dfp->dfp_intent = dfp->dfp_type->create_intent(*tp,
|
||||
dfp->dfp_intent = ops->create_intent(*tp,
|
||||
dfp->dfp_count);
|
||||
dfp->dfp_done = NULL;
|
||||
list_for_each(li, &dfp->dfp_work)
|
||||
dfp->dfp_type->log_item(*tp, dfp->dfp_intent,
|
||||
li);
|
||||
ops->log_item(*tp, dfp->dfp_intent, li);
|
||||
} else {
|
||||
/* Done with the dfp, free it. */
|
||||
list_del(&dfp->dfp_list);
|
||||
kmem_free(dfp);
|
||||
}
|
||||
|
||||
if (cleanup_fn)
|
||||
cleanup_fn(*tp, state, error);
|
||||
if (ops->finish_cleanup)
|
||||
ops->finish_cleanup(*tp, state, error);
|
||||
}
|
||||
|
||||
out:
|
||||
@ -486,8 +495,10 @@ xfs_defer_add(
|
||||
struct list_head *li)
|
||||
{
|
||||
struct xfs_defer_pending *dfp = NULL;
|
||||
const struct xfs_defer_op_type *ops;
|
||||
|
||||
ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
|
||||
BUILD_BUG_ON(ARRAY_SIZE(defer_op_types) != XFS_DEFER_OPS_TYPE_MAX);
|
||||
|
||||
/*
|
||||
* Add the item to a pending item at the end of the intake list.
|
||||
@ -497,15 +508,15 @@ xfs_defer_add(
|
||||
if (!list_empty(&tp->t_dfops)) {
|
||||
dfp = list_last_entry(&tp->t_dfops,
|
||||
struct xfs_defer_pending, dfp_list);
|
||||
if (dfp->dfp_type->type != type ||
|
||||
(dfp->dfp_type->max_items &&
|
||||
dfp->dfp_count >= dfp->dfp_type->max_items))
|
||||
ops = defer_op_types[dfp->dfp_type];
|
||||
if (dfp->dfp_type != type ||
|
||||
(ops->max_items && dfp->dfp_count >= ops->max_items))
|
||||
dfp = NULL;
|
||||
}
|
||||
if (!dfp) {
|
||||
dfp = kmem_alloc(sizeof(struct xfs_defer_pending),
|
||||
KM_SLEEP | KM_NOFS);
|
||||
dfp->dfp_type = defer_op_types[type];
|
||||
dfp->dfp_type = type;
|
||||
dfp->dfp_intent = NULL;
|
||||
dfp->dfp_done = NULL;
|
||||
dfp->dfp_count = 0;
|
||||
@ -517,14 +528,6 @@ xfs_defer_add(
|
||||
dfp->dfp_count++;
|
||||
}
|
||||
|
||||
/* Initialize a deferred operation list. */
|
||||
void
|
||||
xfs_defer_init_op_type(
|
||||
const struct xfs_defer_op_type *type)
|
||||
{
|
||||
defer_op_types[type->type] = type;
|
||||
}
|
||||
|
||||
/*
|
||||
* Move deferred ops from one transaction to another and reset the source to
|
||||
* initial state. This is primarily used to carry state forward across
|
||||
|
@ -8,20 +8,6 @@
|
||||
|
||||
struct xfs_defer_op_type;
|
||||
|
||||
/*
|
||||
* Save a log intent item and a list of extents, so that we can replay
|
||||
* whatever action had to happen to the extent list and file the log done
|
||||
* item.
|
||||
*/
|
||||
struct xfs_defer_pending {
|
||||
const struct xfs_defer_op_type *dfp_type; /* function pointers */
|
||||
struct list_head dfp_list; /* pending items */
|
||||
void *dfp_intent; /* log intent item */
|
||||
void *dfp_done; /* log done item */
|
||||
struct list_head dfp_work; /* work items */
|
||||
unsigned int dfp_count; /* # extent items */
|
||||
};
|
||||
|
||||
/*
|
||||
* Header for deferred operation list.
|
||||
*/
|
||||
@ -34,6 +20,20 @@ enum xfs_defer_ops_type {
|
||||
XFS_DEFER_OPS_TYPE_MAX,
|
||||
};
|
||||
|
||||
/*
|
||||
* Save a log intent item and a list of extents, so that we can replay
|
||||
* whatever action had to happen to the extent list and file the log done
|
||||
* item.
|
||||
*/
|
||||
struct xfs_defer_pending {
|
||||
struct list_head dfp_list; /* pending items */
|
||||
struct list_head dfp_work; /* work items */
|
||||
void *dfp_intent; /* log intent item */
|
||||
void *dfp_done; /* log done item */
|
||||
unsigned int dfp_count; /* # extent items */
|
||||
enum xfs_defer_ops_type dfp_type;
|
||||
};
|
||||
|
||||
void xfs_defer_add(struct xfs_trans *tp, enum xfs_defer_ops_type type,
|
||||
struct list_head *h);
|
||||
int xfs_defer_finish_noroll(struct xfs_trans **tp);
|
||||
@ -43,8 +43,6 @@ void xfs_defer_move(struct xfs_trans *dtp, struct xfs_trans *stp);
|
||||
|
||||
/* Description of a deferred type. */
|
||||
struct xfs_defer_op_type {
|
||||
enum xfs_defer_ops_type type;
|
||||
unsigned int max_items;
|
||||
void (*abort_intent)(void *);
|
||||
void *(*create_done)(struct xfs_trans *, void *, unsigned int);
|
||||
int (*finish_item)(struct xfs_trans *, struct list_head *, void *,
|
||||
@ -54,8 +52,13 @@ struct xfs_defer_op_type {
|
||||
int (*diff_items)(void *, struct list_head *, struct list_head *);
|
||||
void *(*create_intent)(struct xfs_trans *, uint);
|
||||
void (*log_item)(struct xfs_trans *, void *, struct list_head *);
|
||||
unsigned int max_items;
|
||||
};
|
||||
|
||||
void xfs_defer_init_op_type(const struct xfs_defer_op_type *type);
|
||||
extern const struct xfs_defer_op_type xfs_bmap_update_defer_type;
|
||||
extern const struct xfs_defer_op_type xfs_refcount_update_defer_type;
|
||||
extern const struct xfs_defer_op_type xfs_rmap_update_defer_type;
|
||||
extern const struct xfs_defer_op_type xfs_extent_free_defer_type;
|
||||
extern const struct xfs_defer_op_type xfs_agfl_free_defer_type;
|
||||
|
||||
#endif /* __XFS_DEFER_H__ */
|
||||
|
@ -916,6 +916,9 @@ static inline uint xfs_dinode_size(int version)
|
||||
|
||||
/*
|
||||
* Values for di_format
|
||||
*
|
||||
* This enum is used in string mapping in xfs_trace.h; please keep the
|
||||
* TRACE_DEFINE_ENUMs for it up to date.
|
||||
*/
|
||||
typedef enum xfs_dinode_fmt {
|
||||
XFS_DINODE_FMT_DEV, /* xfs_dev_t */
|
||||
@ -925,6 +928,13 @@ typedef enum xfs_dinode_fmt {
|
||||
XFS_DINODE_FMT_UUID /* added long ago, but never used */
|
||||
} xfs_dinode_fmt_t;
|
||||
|
||||
#define XFS_INODE_FORMAT_STR \
|
||||
{ XFS_DINODE_FMT_DEV, "dev" }, \
|
||||
{ XFS_DINODE_FMT_LOCAL, "local" }, \
|
||||
{ XFS_DINODE_FMT_EXTENTS, "extent" }, \
|
||||
{ XFS_DINODE_FMT_BTREE, "btree" }, \
|
||||
{ XFS_DINODE_FMT_UUID, "uuid" }
|
||||
|
||||
/*
|
||||
* Inode minimum and maximum sizes.
|
||||
*/
|
||||
@ -1083,6 +1093,8 @@ static inline void xfs_dinode_put_rdev(struct xfs_dinode *dip, xfs_dev_t rdev)
|
||||
((i) & XFS_INO_MASK(XFS_INO_OFFSET_BITS(mp)))
|
||||
#define XFS_OFFBNO_TO_AGINO(mp,b,o) \
|
||||
((xfs_agino_t)(((b) << XFS_INO_OFFSET_BITS(mp)) | (o)))
|
||||
#define XFS_FSB_TO_INO(mp, b) ((xfs_ino_t)((b) << XFS_INO_OFFSET_BITS(mp)))
|
||||
#define XFS_AGB_TO_AGINO(mp, b) ((xfs_agino_t)((b) << XFS_INO_OFFSET_BITS(mp)))
|
||||
|
||||
#define XFS_MAXINUMBER ((xfs_ino_t)((1ULL << 56) - 1ULL))
|
||||
#define XFS_MAXINUMBER_32 ((xfs_ino_t)((1ULL << 32) - 1ULL))
|
||||
|
@ -288,7 +288,7 @@ xfs_ialloc_inode_init(
|
||||
{
|
||||
struct xfs_buf *fbuf;
|
||||
struct xfs_dinode *free;
|
||||
int nbufs, blks_per_cluster, inodes_per_cluster;
|
||||
int nbufs;
|
||||
int version;
|
||||
int i, j;
|
||||
xfs_daddr_t d;
|
||||
@ -299,9 +299,7 @@ xfs_ialloc_inode_init(
|
||||
* sizes, manipulate the inodes in buffers which are multiples of the
|
||||
* blocks size.
|
||||
*/
|
||||
blks_per_cluster = xfs_icluster_size_fsb(mp);
|
||||
inodes_per_cluster = blks_per_cluster << mp->m_sb.sb_inopblog;
|
||||
nbufs = length / blks_per_cluster;
|
||||
nbufs = length / mp->m_blocks_per_cluster;
|
||||
|
||||
/*
|
||||
* Figure out what version number to use in the inodes we create. If
|
||||
@ -312,7 +310,7 @@ xfs_ialloc_inode_init(
|
||||
*
|
||||
* For v3 inodes, we also need to write the inode number into the inode,
|
||||
* so calculate the first inode number of the chunk here as
|
||||
* XFS_OFFBNO_TO_AGINO() only works within a filesystem block, not
|
||||
* XFS_AGB_TO_AGINO() only works within a filesystem block, not
|
||||
* across multiple filesystem blocks (such as a cluster) and so cannot
|
||||
* be used in the cluster buffer loop below.
|
||||
*
|
||||
@ -324,8 +322,7 @@ xfs_ialloc_inode_init(
|
||||
*/
|
||||
if (xfs_sb_version_hascrc(&mp->m_sb)) {
|
||||
version = 3;
|
||||
ino = XFS_AGINO_TO_INO(mp, agno,
|
||||
XFS_OFFBNO_TO_AGINO(mp, agbno, 0));
|
||||
ino = XFS_AGINO_TO_INO(mp, agno, XFS_AGB_TO_AGINO(mp, agbno));
|
||||
|
||||
/*
|
||||
* log the initialisation that is about to take place as an
|
||||
@ -345,9 +342,10 @@ xfs_ialloc_inode_init(
|
||||
/*
|
||||
* Get the block.
|
||||
*/
|
||||
d = XFS_AGB_TO_DADDR(mp, agno, agbno + (j * blks_per_cluster));
|
||||
d = XFS_AGB_TO_DADDR(mp, agno, agbno +
|
||||
(j * mp->m_blocks_per_cluster));
|
||||
fbuf = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
|
||||
mp->m_bsize * blks_per_cluster,
|
||||
mp->m_bsize * mp->m_blocks_per_cluster,
|
||||
XBF_UNMAPPED);
|
||||
if (!fbuf)
|
||||
return -ENOMEM;
|
||||
@ -355,7 +353,7 @@ xfs_ialloc_inode_init(
|
||||
/* Initialize the inode buffers and log them appropriately. */
|
||||
fbuf->b_ops = &xfs_inode_buf_ops;
|
||||
xfs_buf_zero(fbuf, 0, BBTOB(fbuf->b_length));
|
||||
for (i = 0; i < inodes_per_cluster; i++) {
|
||||
for (i = 0; i < mp->m_inodes_per_cluster; i++) {
|
||||
int ioffset = i << mp->m_sb.sb_inodelog;
|
||||
uint isize = xfs_dinode_size(version);
|
||||
|
||||
@ -445,7 +443,7 @@ xfs_align_sparse_ino(
|
||||
return;
|
||||
|
||||
/* calculate the inode offset and align startino */
|
||||
offset = mod << mp->m_sb.sb_inopblog;
|
||||
offset = XFS_AGB_TO_AGINO(mp, mod);
|
||||
*startino -= offset;
|
||||
|
||||
/*
|
||||
@ -641,7 +639,7 @@ xfs_ialloc_ag_alloc(
|
||||
args.tp = tp;
|
||||
args.mp = tp->t_mountp;
|
||||
args.fsbno = NULLFSBLOCK;
|
||||
xfs_rmap_ag_owner(&args.oinfo, XFS_RMAP_OWN_INODES);
|
||||
args.oinfo = XFS_RMAP_OINFO_INODES;
|
||||
|
||||
#ifdef DEBUG
|
||||
/* randomly do sparse inode allocations */
|
||||
@ -692,7 +690,7 @@ xfs_ialloc_ag_alloc(
|
||||
* but not to use them in the actual exact allocation.
|
||||
*/
|
||||
args.alignment = 1;
|
||||
args.minalignslop = xfs_ialloc_cluster_alignment(args.mp) - 1;
|
||||
args.minalignslop = args.mp->m_cluster_align - 1;
|
||||
|
||||
/* Allow space for the inode btree to split. */
|
||||
args.minleft = args.mp->m_in_maxlevels - 1;
|
||||
@ -727,7 +725,7 @@ xfs_ialloc_ag_alloc(
|
||||
args.alignment = args.mp->m_dalign;
|
||||
isaligned = 1;
|
||||
} else
|
||||
args.alignment = xfs_ialloc_cluster_alignment(args.mp);
|
||||
args.alignment = args.mp->m_cluster_align;
|
||||
/*
|
||||
* Need to figure out where to allocate the inode blocks.
|
||||
* Ideally they should be spaced out through the a.g.
|
||||
@ -756,7 +754,7 @@ xfs_ialloc_ag_alloc(
|
||||
args.type = XFS_ALLOCTYPE_NEAR_BNO;
|
||||
args.agbno = be32_to_cpu(agi->agi_root);
|
||||
args.fsbno = XFS_AGB_TO_FSB(args.mp, agno, args.agbno);
|
||||
args.alignment = xfs_ialloc_cluster_alignment(args.mp);
|
||||
args.alignment = args.mp->m_cluster_align;
|
||||
if ((error = xfs_alloc_vextent(&args)))
|
||||
return error;
|
||||
}
|
||||
@ -797,7 +795,7 @@ sparse_alloc:
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
newlen = args.len << args.mp->m_sb.sb_inopblog;
|
||||
newlen = XFS_AGB_TO_AGINO(args.mp, args.len);
|
||||
ASSERT(newlen <= XFS_INODES_PER_CHUNK);
|
||||
allocmask = (1 << (newlen / XFS_INODES_PER_HOLEMASK_BIT)) - 1;
|
||||
}
|
||||
@ -825,7 +823,7 @@ sparse_alloc:
|
||||
/*
|
||||
* Convert the results.
|
||||
*/
|
||||
newino = XFS_OFFBNO_TO_AGINO(args.mp, args.agbno, 0);
|
||||
newino = XFS_AGB_TO_AGINO(args.mp, args.agbno);
|
||||
|
||||
if (xfs_inobt_issparse(~allocmask)) {
|
||||
/*
|
||||
@ -1019,7 +1017,7 @@ xfs_ialloc_ag_select(
|
||||
*/
|
||||
ineed = mp->m_ialloc_min_blks;
|
||||
if (flags && ineed > 1)
|
||||
ineed += xfs_ialloc_cluster_alignment(mp);
|
||||
ineed += mp->m_cluster_align;
|
||||
longest = pag->pagf_longest;
|
||||
if (!longest)
|
||||
longest = pag->pagf_flcount > 0;
|
||||
@ -1849,14 +1847,12 @@ xfs_difree_inode_chunk(
|
||||
int nextbit;
|
||||
xfs_agblock_t agbno;
|
||||
int contigblk;
|
||||
struct xfs_owner_info oinfo;
|
||||
DECLARE_BITMAP(holemask, XFS_INOBT_HOLEMASK_BITS);
|
||||
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INODES);
|
||||
|
||||
if (!xfs_inobt_issparse(rec->ir_holemask)) {
|
||||
/* not sparse, calculate extent info directly */
|
||||
xfs_bmap_add_free(tp, XFS_AGB_TO_FSB(mp, agno, sagbno),
|
||||
mp->m_ialloc_blks, &oinfo);
|
||||
mp->m_ialloc_blks, &XFS_RMAP_OINFO_INODES);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1900,7 +1896,7 @@ xfs_difree_inode_chunk(
|
||||
ASSERT(agbno % mp->m_sb.sb_spino_align == 0);
|
||||
ASSERT(contigblk % mp->m_sb.sb_spino_align == 0);
|
||||
xfs_bmap_add_free(tp, XFS_AGB_TO_FSB(mp, agno, agbno),
|
||||
contigblk, &oinfo);
|
||||
contigblk, &XFS_RMAP_OINFO_INODES);
|
||||
|
||||
/* reset range to current bit and carry on... */
|
||||
startidx = endidx = nextbit;
|
||||
@ -2292,7 +2288,6 @@ xfs_imap(
|
||||
xfs_agblock_t agbno; /* block number of inode in the alloc group */
|
||||
xfs_agino_t agino; /* inode number within alloc group */
|
||||
xfs_agnumber_t agno; /* allocation group number */
|
||||
int blks_per_cluster; /* num blocks per inode cluster */
|
||||
xfs_agblock_t chunk_agbno; /* first block in inode chunk */
|
||||
xfs_agblock_t cluster_agbno; /* first block in inode cluster */
|
||||
int error; /* error code */
|
||||
@ -2338,8 +2333,6 @@ xfs_imap(
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
blks_per_cluster = xfs_icluster_size_fsb(mp);
|
||||
|
||||
/*
|
||||
* For bulkstat and handle lookups, we have an untrusted inode number
|
||||
* that we have to verify is valid. We cannot do this just by reading
|
||||
@ -2359,7 +2352,7 @@ xfs_imap(
|
||||
* If the inode cluster size is the same as the blocksize or
|
||||
* smaller we get to the buffer by simple arithmetics.
|
||||
*/
|
||||
if (blks_per_cluster == 1) {
|
||||
if (mp->m_blocks_per_cluster == 1) {
|
||||
offset = XFS_INO_TO_OFFSET(mp, ino);
|
||||
ASSERT(offset < mp->m_sb.sb_inopblock);
|
||||
|
||||
@ -2388,12 +2381,13 @@ xfs_imap(
|
||||
out_map:
|
||||
ASSERT(agbno >= chunk_agbno);
|
||||
cluster_agbno = chunk_agbno +
|
||||
((offset_agbno / blks_per_cluster) * blks_per_cluster);
|
||||
((offset_agbno / mp->m_blocks_per_cluster) *
|
||||
mp->m_blocks_per_cluster);
|
||||
offset = ((agbno - cluster_agbno) * mp->m_sb.sb_inopblock) +
|
||||
XFS_INO_TO_OFFSET(mp, ino);
|
||||
|
||||
imap->im_blkno = XFS_AGB_TO_DADDR(mp, agno, cluster_agbno);
|
||||
imap->im_len = XFS_FSB_TO_BB(mp, blks_per_cluster);
|
||||
imap->im_len = XFS_FSB_TO_BB(mp, mp->m_blocks_per_cluster);
|
||||
imap->im_boffset = (unsigned short)(offset << mp->m_sb.sb_inodelog);
|
||||
|
||||
/*
|
||||
@ -2726,8 +2720,8 @@ xfs_ialloc_has_inodes_at_extent(
|
||||
xfs_agino_t low;
|
||||
xfs_agino_t high;
|
||||
|
||||
low = XFS_OFFBNO_TO_AGINO(cur->bc_mp, bno, 0);
|
||||
high = XFS_OFFBNO_TO_AGINO(cur->bc_mp, bno + len, 0) - 1;
|
||||
low = XFS_AGB_TO_AGINO(cur->bc_mp, bno);
|
||||
high = XFS_AGB_TO_AGINO(cur->bc_mp, bno + len) - 1;
|
||||
|
||||
return xfs_ialloc_has_inode_record(cur, low, high, exists);
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ __xfs_inobt_alloc_block(
|
||||
memset(&args, 0, sizeof(args));
|
||||
args.tp = cur->bc_tp;
|
||||
args.mp = cur->bc_mp;
|
||||
xfs_rmap_ag_owner(&args.oinfo, XFS_RMAP_OWN_INOBT);
|
||||
args.oinfo = XFS_RMAP_OINFO_INOBT;
|
||||
args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.a.agno, sbno);
|
||||
args.minlen = 1;
|
||||
args.maxlen = 1;
|
||||
@ -136,12 +136,9 @@ __xfs_inobt_free_block(
|
||||
struct xfs_buf *bp,
|
||||
enum xfs_ag_resv_type resv)
|
||||
{
|
||||
struct xfs_owner_info oinfo;
|
||||
|
||||
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INOBT);
|
||||
return xfs_free_extent(cur->bc_tp,
|
||||
XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(bp)), 1,
|
||||
&oinfo, resv);
|
||||
&XFS_RMAP_OINFO_INOBT, resv);
|
||||
}
|
||||
|
||||
STATIC int
|
||||
|
@ -70,7 +70,7 @@ xfs_refcountbt_alloc_block(
|
||||
args.type = XFS_ALLOCTYPE_NEAR_BNO;
|
||||
args.fsbno = XFS_AGB_TO_FSB(cur->bc_mp, cur->bc_private.a.agno,
|
||||
xfs_refc_block(args.mp));
|
||||
xfs_rmap_ag_owner(&args.oinfo, XFS_RMAP_OWN_REFC);
|
||||
args.oinfo = XFS_RMAP_OINFO_REFC;
|
||||
args.minlen = args.maxlen = args.prod = 1;
|
||||
args.resv = XFS_AG_RESV_METADATA;
|
||||
|
||||
@ -106,15 +106,13 @@ xfs_refcountbt_free_block(
|
||||
struct xfs_buf *agbp = cur->bc_private.a.agbp;
|
||||
struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp);
|
||||
xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(bp));
|
||||
struct xfs_owner_info oinfo;
|
||||
int error;
|
||||
|
||||
trace_xfs_refcountbt_free_block(cur->bc_mp, cur->bc_private.a.agno,
|
||||
XFS_FSB_TO_AGBNO(cur->bc_mp, fsbno), 1);
|
||||
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_REFC);
|
||||
be32_add_cpu(&agf->agf_refcount_blocks, -1);
|
||||
xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_REFCOUNT_BLOCKS);
|
||||
error = xfs_free_extent(cur->bc_tp, fsbno, 1, &oinfo,
|
||||
error = xfs_free_extent(cur->bc_tp, fsbno, 1, &XFS_RMAP_OINFO_REFC,
|
||||
XFS_AG_RESV_METADATA);
|
||||
if (error)
|
||||
return error;
|
||||
|
@ -458,21 +458,21 @@ out:
|
||||
*/
|
||||
STATIC int
|
||||
xfs_rmap_unmap(
|
||||
struct xfs_btree_cur *cur,
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
bool unwritten,
|
||||
struct xfs_owner_info *oinfo)
|
||||
struct xfs_btree_cur *cur,
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
bool unwritten,
|
||||
const struct xfs_owner_info *oinfo)
|
||||
{
|
||||
struct xfs_mount *mp = cur->bc_mp;
|
||||
struct xfs_rmap_irec ltrec;
|
||||
uint64_t ltoff;
|
||||
int error = 0;
|
||||
int i;
|
||||
uint64_t owner;
|
||||
uint64_t offset;
|
||||
unsigned int flags;
|
||||
bool ignore_off;
|
||||
struct xfs_mount *mp = cur->bc_mp;
|
||||
struct xfs_rmap_irec ltrec;
|
||||
uint64_t ltoff;
|
||||
int error = 0;
|
||||
int i;
|
||||
uint64_t owner;
|
||||
uint64_t offset;
|
||||
unsigned int flags;
|
||||
bool ignore_off;
|
||||
|
||||
xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
|
||||
ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
|
||||
@ -653,16 +653,16 @@ out_error:
|
||||
*/
|
||||
int
|
||||
xfs_rmap_free(
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_buf *agbp,
|
||||
xfs_agnumber_t agno,
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
struct xfs_owner_info *oinfo)
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_buf *agbp,
|
||||
xfs_agnumber_t agno,
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
const struct xfs_owner_info *oinfo)
|
||||
{
|
||||
struct xfs_mount *mp = tp->t_mountp;
|
||||
struct xfs_btree_cur *cur;
|
||||
int error;
|
||||
struct xfs_mount *mp = tp->t_mountp;
|
||||
struct xfs_btree_cur *cur;
|
||||
int error;
|
||||
|
||||
if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
|
||||
return 0;
|
||||
@ -710,23 +710,23 @@ xfs_rmap_is_mergeable(
|
||||
*/
|
||||
STATIC int
|
||||
xfs_rmap_map(
|
||||
struct xfs_btree_cur *cur,
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
bool unwritten,
|
||||
struct xfs_owner_info *oinfo)
|
||||
struct xfs_btree_cur *cur,
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
bool unwritten,
|
||||
const struct xfs_owner_info *oinfo)
|
||||
{
|
||||
struct xfs_mount *mp = cur->bc_mp;
|
||||
struct xfs_rmap_irec ltrec;
|
||||
struct xfs_rmap_irec gtrec;
|
||||
int have_gt;
|
||||
int have_lt;
|
||||
int error = 0;
|
||||
int i;
|
||||
uint64_t owner;
|
||||
uint64_t offset;
|
||||
unsigned int flags = 0;
|
||||
bool ignore_off;
|
||||
struct xfs_mount *mp = cur->bc_mp;
|
||||
struct xfs_rmap_irec ltrec;
|
||||
struct xfs_rmap_irec gtrec;
|
||||
int have_gt;
|
||||
int have_lt;
|
||||
int error = 0;
|
||||
int i;
|
||||
uint64_t owner;
|
||||
uint64_t offset;
|
||||
unsigned int flags = 0;
|
||||
bool ignore_off;
|
||||
|
||||
xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
|
||||
ASSERT(owner != 0);
|
||||
@ -890,16 +890,16 @@ out_error:
|
||||
*/
|
||||
int
|
||||
xfs_rmap_alloc(
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_buf *agbp,
|
||||
xfs_agnumber_t agno,
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
struct xfs_owner_info *oinfo)
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_buf *agbp,
|
||||
xfs_agnumber_t agno,
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
const struct xfs_owner_info *oinfo)
|
||||
{
|
||||
struct xfs_mount *mp = tp->t_mountp;
|
||||
struct xfs_btree_cur *cur;
|
||||
int error;
|
||||
struct xfs_mount *mp = tp->t_mountp;
|
||||
struct xfs_btree_cur *cur;
|
||||
int error;
|
||||
|
||||
if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
|
||||
return 0;
|
||||
@ -929,16 +929,16 @@ xfs_rmap_alloc(
|
||||
*/
|
||||
STATIC int
|
||||
xfs_rmap_convert(
|
||||
struct xfs_btree_cur *cur,
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
bool unwritten,
|
||||
struct xfs_owner_info *oinfo)
|
||||
struct xfs_btree_cur *cur,
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
bool unwritten,
|
||||
const struct xfs_owner_info *oinfo)
|
||||
{
|
||||
struct xfs_mount *mp = cur->bc_mp;
|
||||
struct xfs_rmap_irec r[4]; /* neighbor extent entries */
|
||||
/* left is 0, right is 1, prev is 2 */
|
||||
/* new is 3 */
|
||||
struct xfs_mount *mp = cur->bc_mp;
|
||||
struct xfs_rmap_irec r[4]; /* neighbor extent entries */
|
||||
/* left is 0, right is 1, */
|
||||
/* prev is 2, new is 3 */
|
||||
uint64_t owner;
|
||||
uint64_t offset;
|
||||
uint64_t new_endoff;
|
||||
@ -1354,16 +1354,16 @@ done:
|
||||
*/
|
||||
STATIC int
|
||||
xfs_rmap_convert_shared(
|
||||
struct xfs_btree_cur *cur,
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
bool unwritten,
|
||||
struct xfs_owner_info *oinfo)
|
||||
struct xfs_btree_cur *cur,
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
bool unwritten,
|
||||
const struct xfs_owner_info *oinfo)
|
||||
{
|
||||
struct xfs_mount *mp = cur->bc_mp;
|
||||
struct xfs_rmap_irec r[4]; /* neighbor extent entries */
|
||||
/* left is 0, right is 1, prev is 2 */
|
||||
/* new is 3 */
|
||||
struct xfs_mount *mp = cur->bc_mp;
|
||||
struct xfs_rmap_irec r[4]; /* neighbor extent entries */
|
||||
/* left is 0, right is 1, */
|
||||
/* prev is 2, new is 3 */
|
||||
uint64_t owner;
|
||||
uint64_t offset;
|
||||
uint64_t new_endoff;
|
||||
@ -1743,20 +1743,20 @@ done:
|
||||
*/
|
||||
STATIC int
|
||||
xfs_rmap_unmap_shared(
|
||||
struct xfs_btree_cur *cur,
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
bool unwritten,
|
||||
struct xfs_owner_info *oinfo)
|
||||
struct xfs_btree_cur *cur,
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
bool unwritten,
|
||||
const struct xfs_owner_info *oinfo)
|
||||
{
|
||||
struct xfs_mount *mp = cur->bc_mp;
|
||||
struct xfs_rmap_irec ltrec;
|
||||
uint64_t ltoff;
|
||||
int error = 0;
|
||||
int i;
|
||||
uint64_t owner;
|
||||
uint64_t offset;
|
||||
unsigned int flags;
|
||||
struct xfs_mount *mp = cur->bc_mp;
|
||||
struct xfs_rmap_irec ltrec;
|
||||
uint64_t ltoff;
|
||||
int error = 0;
|
||||
int i;
|
||||
uint64_t owner;
|
||||
uint64_t offset;
|
||||
unsigned int flags;
|
||||
|
||||
xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
|
||||
if (unwritten)
|
||||
@ -1905,22 +1905,22 @@ out_error:
|
||||
*/
|
||||
STATIC int
|
||||
xfs_rmap_map_shared(
|
||||
struct xfs_btree_cur *cur,
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
bool unwritten,
|
||||
struct xfs_owner_info *oinfo)
|
||||
struct xfs_btree_cur *cur,
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
bool unwritten,
|
||||
const struct xfs_owner_info *oinfo)
|
||||
{
|
||||
struct xfs_mount *mp = cur->bc_mp;
|
||||
struct xfs_rmap_irec ltrec;
|
||||
struct xfs_rmap_irec gtrec;
|
||||
int have_gt;
|
||||
int have_lt;
|
||||
int error = 0;
|
||||
int i;
|
||||
uint64_t owner;
|
||||
uint64_t offset;
|
||||
unsigned int flags = 0;
|
||||
struct xfs_mount *mp = cur->bc_mp;
|
||||
struct xfs_rmap_irec ltrec;
|
||||
struct xfs_rmap_irec gtrec;
|
||||
int have_gt;
|
||||
int have_lt;
|
||||
int error = 0;
|
||||
int i;
|
||||
uint64_t owner;
|
||||
uint64_t offset;
|
||||
unsigned int flags = 0;
|
||||
|
||||
xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
|
||||
if (unwritten)
|
||||
@ -2459,18 +2459,18 @@ xfs_rmap_has_record(
|
||||
*/
|
||||
int
|
||||
xfs_rmap_record_exists(
|
||||
struct xfs_btree_cur *cur,
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
struct xfs_owner_info *oinfo,
|
||||
bool *has_rmap)
|
||||
struct xfs_btree_cur *cur,
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
const struct xfs_owner_info *oinfo,
|
||||
bool *has_rmap)
|
||||
{
|
||||
uint64_t owner;
|
||||
uint64_t offset;
|
||||
unsigned int flags;
|
||||
int has_record;
|
||||
struct xfs_rmap_irec irec;
|
||||
int error;
|
||||
uint64_t owner;
|
||||
uint64_t offset;
|
||||
unsigned int flags;
|
||||
int has_record;
|
||||
struct xfs_rmap_irec irec;
|
||||
int error;
|
||||
|
||||
xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
|
||||
ASSERT(XFS_RMAP_NON_INODE_OWNER(owner) ||
|
||||
@ -2530,7 +2530,7 @@ xfs_rmap_has_other_keys(
|
||||
struct xfs_btree_cur *cur,
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
struct xfs_owner_info *oinfo,
|
||||
const struct xfs_owner_info *oinfo,
|
||||
bool *has_rmap)
|
||||
{
|
||||
struct xfs_rmap_irec low = {0};
|
||||
@ -2550,3 +2550,31 @@ xfs_rmap_has_other_keys(
|
||||
*has_rmap = rks.has_rmap;
|
||||
return error;
|
||||
}
|
||||
|
||||
const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE = {
|
||||
.oi_owner = XFS_RMAP_OWN_NULL,
|
||||
};
|
||||
const struct xfs_owner_info XFS_RMAP_OINFO_ANY_OWNER = {
|
||||
.oi_owner = XFS_RMAP_OWN_UNKNOWN,
|
||||
};
|
||||
const struct xfs_owner_info XFS_RMAP_OINFO_FS = {
|
||||
.oi_owner = XFS_RMAP_OWN_FS,
|
||||
};
|
||||
const struct xfs_owner_info XFS_RMAP_OINFO_LOG = {
|
||||
.oi_owner = XFS_RMAP_OWN_LOG,
|
||||
};
|
||||
const struct xfs_owner_info XFS_RMAP_OINFO_AG = {
|
||||
.oi_owner = XFS_RMAP_OWN_AG,
|
||||
};
|
||||
const struct xfs_owner_info XFS_RMAP_OINFO_INOBT = {
|
||||
.oi_owner = XFS_RMAP_OWN_INOBT,
|
||||
};
|
||||
const struct xfs_owner_info XFS_RMAP_OINFO_INODES = {
|
||||
.oi_owner = XFS_RMAP_OWN_INODES,
|
||||
};
|
||||
const struct xfs_owner_info XFS_RMAP_OINFO_REFC = {
|
||||
.oi_owner = XFS_RMAP_OWN_REFC,
|
||||
};
|
||||
const struct xfs_owner_info XFS_RMAP_OINFO_COW = {
|
||||
.oi_owner = XFS_RMAP_OWN_COW,
|
||||
};
|
||||
|
@ -6,16 +6,6 @@
|
||||
#ifndef __XFS_RMAP_H__
|
||||
#define __XFS_RMAP_H__
|
||||
|
||||
static inline void
|
||||
xfs_rmap_ag_owner(
|
||||
struct xfs_owner_info *oi,
|
||||
uint64_t owner)
|
||||
{
|
||||
oi->oi_owner = owner;
|
||||
oi->oi_offset = 0;
|
||||
oi->oi_flags = 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
xfs_rmap_ino_bmbt_owner(
|
||||
struct xfs_owner_info *oi,
|
||||
@ -43,27 +33,13 @@ xfs_rmap_ino_owner(
|
||||
oi->oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
|
||||
}
|
||||
|
||||
static inline void
|
||||
xfs_rmap_skip_owner_update(
|
||||
struct xfs_owner_info *oi)
|
||||
{
|
||||
xfs_rmap_ag_owner(oi, XFS_RMAP_OWN_NULL);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
xfs_rmap_should_skip_owner_update(
|
||||
struct xfs_owner_info *oi)
|
||||
const struct xfs_owner_info *oi)
|
||||
{
|
||||
return oi->oi_owner == XFS_RMAP_OWN_NULL;
|
||||
}
|
||||
|
||||
static inline void
|
||||
xfs_rmap_any_owner_update(
|
||||
struct xfs_owner_info *oi)
|
||||
{
|
||||
xfs_rmap_ag_owner(oi, XFS_RMAP_OWN_UNKNOWN);
|
||||
}
|
||||
|
||||
/* Reverse mapping functions. */
|
||||
|
||||
struct xfs_buf;
|
||||
@ -103,12 +79,12 @@ xfs_rmap_irec_offset_unpack(
|
||||
|
||||
static inline void
|
||||
xfs_owner_info_unpack(
|
||||
struct xfs_owner_info *oinfo,
|
||||
uint64_t *owner,
|
||||
uint64_t *offset,
|
||||
unsigned int *flags)
|
||||
const struct xfs_owner_info *oinfo,
|
||||
uint64_t *owner,
|
||||
uint64_t *offset,
|
||||
unsigned int *flags)
|
||||
{
|
||||
unsigned int r = 0;
|
||||
unsigned int r = 0;
|
||||
|
||||
*owner = oinfo->oi_owner;
|
||||
*offset = oinfo->oi_offset;
|
||||
@ -137,10 +113,10 @@ xfs_owner_info_pack(
|
||||
|
||||
int xfs_rmap_alloc(struct xfs_trans *tp, struct xfs_buf *agbp,
|
||||
xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len,
|
||||
struct xfs_owner_info *oinfo);
|
||||
const struct xfs_owner_info *oinfo);
|
||||
int xfs_rmap_free(struct xfs_trans *tp, struct xfs_buf *agbp,
|
||||
xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len,
|
||||
struct xfs_owner_info *oinfo);
|
||||
const struct xfs_owner_info *oinfo);
|
||||
|
||||
int xfs_rmap_lookup_le(struct xfs_btree_cur *cur, xfs_agblock_t bno,
|
||||
xfs_extlen_t len, uint64_t owner, uint64_t offset,
|
||||
@ -218,11 +194,21 @@ int xfs_rmap_btrec_to_irec(union xfs_btree_rec *rec,
|
||||
int xfs_rmap_has_record(struct xfs_btree_cur *cur, xfs_agblock_t bno,
|
||||
xfs_extlen_t len, bool *exists);
|
||||
int xfs_rmap_record_exists(struct xfs_btree_cur *cur, xfs_agblock_t bno,
|
||||
xfs_extlen_t len, struct xfs_owner_info *oinfo,
|
||||
xfs_extlen_t len, const struct xfs_owner_info *oinfo,
|
||||
bool *has_rmap);
|
||||
int xfs_rmap_has_other_keys(struct xfs_btree_cur *cur, xfs_agblock_t bno,
|
||||
xfs_extlen_t len, struct xfs_owner_info *oinfo,
|
||||
xfs_extlen_t len, const struct xfs_owner_info *oinfo,
|
||||
bool *has_rmap);
|
||||
int xfs_rmap_map_raw(struct xfs_btree_cur *cur, struct xfs_rmap_irec *rmap);
|
||||
|
||||
extern const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE;
|
||||
extern const struct xfs_owner_info XFS_RMAP_OINFO_ANY_OWNER;
|
||||
extern const struct xfs_owner_info XFS_RMAP_OINFO_FS;
|
||||
extern const struct xfs_owner_info XFS_RMAP_OINFO_LOG;
|
||||
extern const struct xfs_owner_info XFS_RMAP_OINFO_AG;
|
||||
extern const struct xfs_owner_info XFS_RMAP_OINFO_INOBT;
|
||||
extern const struct xfs_owner_info XFS_RMAP_OINFO_INODES;
|
||||
extern const struct xfs_owner_info XFS_RMAP_OINFO_REFC;
|
||||
extern const struct xfs_owner_info XFS_RMAP_OINFO_COW;
|
||||
|
||||
#endif /* __XFS_RMAP_H__ */
|
||||
|
@ -505,6 +505,12 @@ xfs_rtmodify_summary_int(
|
||||
uint first = (uint)((char *)sp - (char *)bp->b_addr);
|
||||
|
||||
*sp += delta;
|
||||
if (mp->m_rsum_cache) {
|
||||
if (*sp == 0 && log == mp->m_rsum_cache[bbno])
|
||||
mp->m_rsum_cache[bbno]++;
|
||||
if (*sp != 0 && log < mp->m_rsum_cache[bbno])
|
||||
mp->m_rsum_cache[bbno] = log;
|
||||
}
|
||||
xfs_trans_log_buf(tp, bp, first, first + sizeof(*sp) - 1);
|
||||
}
|
||||
if (sum)
|
||||
|
@ -199,7 +199,10 @@ xfs_symlink_local_to_remote(
|
||||
ifp->if_bytes - 1);
|
||||
}
|
||||
|
||||
/* Verify the consistency of an inline symlink. */
|
||||
/*
|
||||
* Verify the in-memory consistency of an inline symlink data fork. This
|
||||
* does not do on-disk format checks.
|
||||
*/
|
||||
xfs_failaddr_t
|
||||
xfs_symlink_shortform_verify(
|
||||
struct xfs_inode *ip)
|
||||
@ -215,9 +218,12 @@ xfs_symlink_shortform_verify(
|
||||
size = ifp->if_bytes;
|
||||
endp = sfp + size;
|
||||
|
||||
/* Zero length symlinks can exist while we're deleting a remote one. */
|
||||
if (size == 0)
|
||||
return NULL;
|
||||
/*
|
||||
* Zero length symlinks should never occur in memory as they are
|
||||
* never alllowed to exist on disk.
|
||||
*/
|
||||
if (!size)
|
||||
return __this_address;
|
||||
|
||||
/* No negative sizes or overly long symlink targets. */
|
||||
if (size < 0 || size > XFS_SYMLINK_MAXLEN)
|
||||
|
@ -87,16 +87,15 @@ xfs_agino_range(
|
||||
* Calculate the first inode, which will be in the first
|
||||
* cluster-aligned block after the AGFL.
|
||||
*/
|
||||
bno = round_up(XFS_AGFL_BLOCK(mp) + 1,
|
||||
xfs_ialloc_cluster_alignment(mp));
|
||||
*first = XFS_OFFBNO_TO_AGINO(mp, bno, 0);
|
||||
bno = round_up(XFS_AGFL_BLOCK(mp) + 1, mp->m_cluster_align);
|
||||
*first = XFS_AGB_TO_AGINO(mp, bno);
|
||||
|
||||
/*
|
||||
* Calculate the last inode, which will be at the end of the
|
||||
* last (aligned) cluster that can be allocated in the AG.
|
||||
*/
|
||||
bno = round_down(eoag, xfs_ialloc_cluster_alignment(mp));
|
||||
*last = XFS_OFFBNO_TO_AGINO(mp, bno, 0) - 1;
|
||||
bno = round_down(eoag, mp->m_cluster_align);
|
||||
*last = XFS_AGB_TO_AGINO(mp, bno) - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -100,15 +100,37 @@ typedef void * xfs_failaddr_t;
|
||||
*/
|
||||
#define MAXNAMELEN 256
|
||||
|
||||
/*
|
||||
* This enum is used in string mapping in xfs_trace.h; please keep the
|
||||
* TRACE_DEFINE_ENUMs for it up to date.
|
||||
*/
|
||||
typedef enum {
|
||||
XFS_LOOKUP_EQi, XFS_LOOKUP_LEi, XFS_LOOKUP_GEi
|
||||
} xfs_lookup_t;
|
||||
|
||||
#define XFS_AG_BTREE_CMP_FORMAT_STR \
|
||||
{ XFS_LOOKUP_EQi, "eq" }, \
|
||||
{ XFS_LOOKUP_LEi, "le" }, \
|
||||
{ XFS_LOOKUP_GEi, "ge" }
|
||||
|
||||
/*
|
||||
* This enum is used in string mapping in xfs_trace.h and scrub/trace.h;
|
||||
* please keep the TRACE_DEFINE_ENUMs for it up to date.
|
||||
*/
|
||||
typedef enum {
|
||||
XFS_BTNUM_BNOi, XFS_BTNUM_CNTi, XFS_BTNUM_RMAPi, XFS_BTNUM_BMAPi,
|
||||
XFS_BTNUM_INOi, XFS_BTNUM_FINOi, XFS_BTNUM_REFCi, XFS_BTNUM_MAX
|
||||
} xfs_btnum_t;
|
||||
|
||||
#define XFS_BTNUM_STRINGS \
|
||||
{ XFS_BTNUM_BNOi, "bnobt" }, \
|
||||
{ XFS_BTNUM_CNTi, "cntbt" }, \
|
||||
{ XFS_BTNUM_RMAPi, "rmapbt" }, \
|
||||
{ XFS_BTNUM_BMAPi, "bmbt" }, \
|
||||
{ XFS_BTNUM_INOi, "inobt" }, \
|
||||
{ XFS_BTNUM_FINOi, "finobt" }, \
|
||||
{ XFS_BTNUM_REFCi, "refcbt" }
|
||||
|
||||
struct xfs_name {
|
||||
const unsigned char *name;
|
||||
int len;
|
||||
|
@ -32,7 +32,6 @@ xchk_superblock_xref(
|
||||
struct xfs_scrub *sc,
|
||||
struct xfs_buf *bp)
|
||||
{
|
||||
struct xfs_owner_info oinfo;
|
||||
struct xfs_mount *mp = sc->mp;
|
||||
xfs_agnumber_t agno = sc->sm->sm_agno;
|
||||
xfs_agblock_t agbno;
|
||||
@ -49,8 +48,7 @@ xchk_superblock_xref(
|
||||
|
||||
xchk_xref_is_used_space(sc, agbno, 1);
|
||||
xchk_xref_is_not_inode_chunk(sc, agbno, 1);
|
||||
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_FS);
|
||||
xchk_xref_is_owned_by(sc, agbno, 1, &oinfo);
|
||||
xchk_xref_is_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS);
|
||||
xchk_xref_is_not_shared(sc, agbno, 1);
|
||||
|
||||
/* scrub teardown will take care of sc->sa for us */
|
||||
@ -484,7 +482,6 @@ STATIC void
|
||||
xchk_agf_xref(
|
||||
struct xfs_scrub *sc)
|
||||
{
|
||||
struct xfs_owner_info oinfo;
|
||||
struct xfs_mount *mp = sc->mp;
|
||||
xfs_agblock_t agbno;
|
||||
int error;
|
||||
@ -502,8 +499,7 @@ xchk_agf_xref(
|
||||
xchk_agf_xref_freeblks(sc);
|
||||
xchk_agf_xref_cntbt(sc);
|
||||
xchk_xref_is_not_inode_chunk(sc, agbno, 1);
|
||||
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_FS);
|
||||
xchk_xref_is_owned_by(sc, agbno, 1, &oinfo);
|
||||
xchk_xref_is_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS);
|
||||
xchk_agf_xref_btreeblks(sc);
|
||||
xchk_xref_is_not_shared(sc, agbno, 1);
|
||||
xchk_agf_xref_refcblks(sc);
|
||||
@ -598,7 +594,6 @@ out:
|
||||
/* AGFL */
|
||||
|
||||
struct xchk_agfl_info {
|
||||
struct xfs_owner_info oinfo;
|
||||
unsigned int sz_entries;
|
||||
unsigned int nr_entries;
|
||||
xfs_agblock_t *entries;
|
||||
@ -609,15 +604,14 @@ struct xchk_agfl_info {
|
||||
STATIC void
|
||||
xchk_agfl_block_xref(
|
||||
struct xfs_scrub *sc,
|
||||
xfs_agblock_t agbno,
|
||||
struct xfs_owner_info *oinfo)
|
||||
xfs_agblock_t agbno)
|
||||
{
|
||||
if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
|
||||
return;
|
||||
|
||||
xchk_xref_is_used_space(sc, agbno, 1);
|
||||
xchk_xref_is_not_inode_chunk(sc, agbno, 1);
|
||||
xchk_xref_is_owned_by(sc, agbno, 1, oinfo);
|
||||
xchk_xref_is_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_AG);
|
||||
xchk_xref_is_not_shared(sc, agbno, 1);
|
||||
}
|
||||
|
||||
@ -638,7 +632,7 @@ xchk_agfl_block(
|
||||
else
|
||||
xchk_block_set_corrupt(sc, sc->sa.agfl_bp);
|
||||
|
||||
xchk_agfl_block_xref(sc, agbno, priv);
|
||||
xchk_agfl_block_xref(sc, agbno);
|
||||
|
||||
if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
|
||||
return XFS_BTREE_QUERY_RANGE_ABORT;
|
||||
@ -662,7 +656,6 @@ STATIC void
|
||||
xchk_agfl_xref(
|
||||
struct xfs_scrub *sc)
|
||||
{
|
||||
struct xfs_owner_info oinfo;
|
||||
struct xfs_mount *mp = sc->mp;
|
||||
xfs_agblock_t agbno;
|
||||
int error;
|
||||
@ -678,8 +671,7 @@ xchk_agfl_xref(
|
||||
|
||||
xchk_xref_is_used_space(sc, agbno, 1);
|
||||
xchk_xref_is_not_inode_chunk(sc, agbno, 1);
|
||||
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_FS);
|
||||
xchk_xref_is_owned_by(sc, agbno, 1, &oinfo);
|
||||
xchk_xref_is_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS);
|
||||
xchk_xref_is_not_shared(sc, agbno, 1);
|
||||
|
||||
/*
|
||||
@ -732,7 +724,6 @@ xchk_agfl(
|
||||
}
|
||||
|
||||
/* Check the blocks in the AGFL. */
|
||||
xfs_rmap_ag_owner(&sai.oinfo, XFS_RMAP_OWN_AG);
|
||||
error = xfs_agfl_walk(sc->mp, XFS_BUF_TO_AGF(sc->sa.agf_bp),
|
||||
sc->sa.agfl_bp, xchk_agfl_block, &sai);
|
||||
if (error == XFS_BTREE_QUERY_RANGE_ABORT) {
|
||||
@ -791,7 +782,6 @@ STATIC void
|
||||
xchk_agi_xref(
|
||||
struct xfs_scrub *sc)
|
||||
{
|
||||
struct xfs_owner_info oinfo;
|
||||
struct xfs_mount *mp = sc->mp;
|
||||
xfs_agblock_t agbno;
|
||||
int error;
|
||||
@ -808,8 +798,7 @@ xchk_agi_xref(
|
||||
xchk_xref_is_used_space(sc, agbno, 1);
|
||||
xchk_xref_is_not_inode_chunk(sc, agbno, 1);
|
||||
xchk_agi_xref_icounts(sc);
|
||||
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_FS);
|
||||
xchk_xref_is_owned_by(sc, agbno, 1, &oinfo);
|
||||
xchk_xref_is_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS);
|
||||
xchk_xref_is_not_shared(sc, agbno, 1);
|
||||
|
||||
/* scrub teardown will take care of sc->sa for us */
|
||||
|
@ -646,7 +646,6 @@ int
|
||||
xrep_agfl(
|
||||
struct xfs_scrub *sc)
|
||||
{
|
||||
struct xfs_owner_info oinfo;
|
||||
struct xfs_bitmap agfl_extents;
|
||||
struct xfs_mount *mp = sc->mp;
|
||||
struct xfs_buf *agf_bp;
|
||||
@ -708,8 +707,8 @@ xrep_agfl(
|
||||
goto err;
|
||||
|
||||
/* Dump any AGFL overflow. */
|
||||
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_AG);
|
||||
return xrep_reap_extents(sc, &agfl_extents, &oinfo, XFS_AG_RESV_AGFL);
|
||||
return xrep_reap_extents(sc, &agfl_extents, &XFS_RMAP_OINFO_AG,
|
||||
XFS_AG_RESV_AGFL);
|
||||
err:
|
||||
xfs_bitmap_destroy(&agfl_extents);
|
||||
return error;
|
||||
|
@ -125,12 +125,10 @@ xchk_allocbt(
|
||||
struct xfs_scrub *sc,
|
||||
xfs_btnum_t which)
|
||||
{
|
||||
struct xfs_owner_info oinfo;
|
||||
struct xfs_btree_cur *cur;
|
||||
|
||||
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_AG);
|
||||
cur = which == XFS_BTNUM_BNO ? sc->sa.bno_cur : sc->sa.cnt_cur;
|
||||
return xchk_btree(sc, cur, xchk_allocbt_rec, &oinfo, NULL);
|
||||
return xchk_btree(sc, cur, xchk_allocbt_rec, &XFS_RMAP_OINFO_AG, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -583,31 +583,32 @@ xchk_btree_block_keys(
|
||||
*/
|
||||
int
|
||||
xchk_btree(
|
||||
struct xfs_scrub *sc,
|
||||
struct xfs_btree_cur *cur,
|
||||
xchk_btree_rec_fn scrub_fn,
|
||||
struct xfs_owner_info *oinfo,
|
||||
void *private)
|
||||
struct xfs_scrub *sc,
|
||||
struct xfs_btree_cur *cur,
|
||||
xchk_btree_rec_fn scrub_fn,
|
||||
const struct xfs_owner_info *oinfo,
|
||||
void *private)
|
||||
{
|
||||
struct xchk_btree bs = { NULL };
|
||||
union xfs_btree_ptr ptr;
|
||||
union xfs_btree_ptr *pp;
|
||||
union xfs_btree_rec *recp;
|
||||
struct xfs_btree_block *block;
|
||||
int level;
|
||||
struct xfs_buf *bp;
|
||||
struct check_owner *co;
|
||||
struct check_owner *n;
|
||||
int i;
|
||||
int error = 0;
|
||||
struct xchk_btree bs = {
|
||||
.cur = cur,
|
||||
.scrub_rec = scrub_fn,
|
||||
.oinfo = oinfo,
|
||||
.firstrec = true,
|
||||
.private = private,
|
||||
.sc = sc,
|
||||
};
|
||||
union xfs_btree_ptr ptr;
|
||||
union xfs_btree_ptr *pp;
|
||||
union xfs_btree_rec *recp;
|
||||
struct xfs_btree_block *block;
|
||||
int level;
|
||||
struct xfs_buf *bp;
|
||||
struct check_owner *co;
|
||||
struct check_owner *n;
|
||||
int i;
|
||||
int error = 0;
|
||||
|
||||
/* Initialize scrub state */
|
||||
bs.cur = cur;
|
||||
bs.scrub_rec = scrub_fn;
|
||||
bs.oinfo = oinfo;
|
||||
bs.firstrec = true;
|
||||
bs.private = private;
|
||||
bs.sc = sc;
|
||||
for (i = 0; i < XFS_BTREE_MAXLEVELS; i++)
|
||||
bs.firstkey[i] = true;
|
||||
INIT_LIST_HEAD(&bs.to_check);
|
||||
|
@ -31,21 +31,21 @@ typedef int (*xchk_btree_rec_fn)(
|
||||
|
||||
struct xchk_btree {
|
||||
/* caller-provided scrub state */
|
||||
struct xfs_scrub *sc;
|
||||
struct xfs_btree_cur *cur;
|
||||
xchk_btree_rec_fn scrub_rec;
|
||||
struct xfs_owner_info *oinfo;
|
||||
void *private;
|
||||
struct xfs_scrub *sc;
|
||||
struct xfs_btree_cur *cur;
|
||||
xchk_btree_rec_fn scrub_rec;
|
||||
const struct xfs_owner_info *oinfo;
|
||||
void *private;
|
||||
|
||||
/* internal scrub state */
|
||||
union xfs_btree_rec lastrec;
|
||||
bool firstrec;
|
||||
union xfs_btree_key lastkey[XFS_BTREE_MAXLEVELS];
|
||||
bool firstkey[XFS_BTREE_MAXLEVELS];
|
||||
struct list_head to_check;
|
||||
union xfs_btree_rec lastrec;
|
||||
bool firstrec;
|
||||
union xfs_btree_key lastkey[XFS_BTREE_MAXLEVELS];
|
||||
bool firstkey[XFS_BTREE_MAXLEVELS];
|
||||
struct list_head to_check;
|
||||
};
|
||||
int xchk_btree(struct xfs_scrub *sc, struct xfs_btree_cur *cur,
|
||||
xchk_btree_rec_fn scrub_fn, struct xfs_owner_info *oinfo,
|
||||
xchk_btree_rec_fn scrub_fn, const struct xfs_owner_info *oinfo,
|
||||
void *private);
|
||||
|
||||
#endif /* __XFS_SCRUB_BTREE_H__ */
|
||||
|
@ -313,8 +313,8 @@ xchk_set_incomplete(
|
||||
*/
|
||||
|
||||
struct xchk_rmap_ownedby_info {
|
||||
struct xfs_owner_info *oinfo;
|
||||
xfs_filblks_t *blocks;
|
||||
const struct xfs_owner_info *oinfo;
|
||||
xfs_filblks_t *blocks;
|
||||
};
|
||||
|
||||
STATIC int
|
||||
@ -347,15 +347,15 @@ int
|
||||
xchk_count_rmap_ownedby_ag(
|
||||
struct xfs_scrub *sc,
|
||||
struct xfs_btree_cur *cur,
|
||||
struct xfs_owner_info *oinfo,
|
||||
const struct xfs_owner_info *oinfo,
|
||||
xfs_filblks_t *blocks)
|
||||
{
|
||||
struct xchk_rmap_ownedby_info sroi;
|
||||
struct xchk_rmap_ownedby_info sroi = {
|
||||
.oinfo = oinfo,
|
||||
.blocks = blocks,
|
||||
};
|
||||
|
||||
sroi.oinfo = oinfo;
|
||||
*blocks = 0;
|
||||
sroi.blocks = blocks;
|
||||
|
||||
return xfs_rmap_query_all(cur, xchk_count_rmap_ownedby_irec,
|
||||
&sroi);
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ int xchk_ag_read_headers(struct xfs_scrub *sc, xfs_agnumber_t agno,
|
||||
void xchk_ag_btcur_free(struct xchk_ag *sa);
|
||||
int xchk_ag_btcur_init(struct xfs_scrub *sc, struct xchk_ag *sa);
|
||||
int xchk_count_rmap_ownedby_ag(struct xfs_scrub *sc, struct xfs_btree_cur *cur,
|
||||
struct xfs_owner_info *oinfo, xfs_filblks_t *blocks);
|
||||
const struct xfs_owner_info *oinfo, xfs_filblks_t *blocks);
|
||||
|
||||
int xchk_setup_ag_btree(struct xfs_scrub *sc, struct xfs_inode *ip,
|
||||
bool force_log);
|
||||
|
@ -44,6 +44,11 @@ xchk_setup_ag_iallocbt(
|
||||
|
||||
/* Inode btree scrubber. */
|
||||
|
||||
struct xchk_iallocbt {
|
||||
/* Number of inodes we see while scanning inobt. */
|
||||
unsigned long long inodes;
|
||||
};
|
||||
|
||||
/*
|
||||
* If we're checking the finobt, cross-reference with the inobt.
|
||||
* Otherwise we're checking the inobt; if there is an finobt, make sure
|
||||
@ -82,15 +87,12 @@ xchk_iallocbt_chunk_xref(
|
||||
xfs_agblock_t agbno,
|
||||
xfs_extlen_t len)
|
||||
{
|
||||
struct xfs_owner_info oinfo;
|
||||
|
||||
if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
|
||||
return;
|
||||
|
||||
xchk_xref_is_used_space(sc, agbno, len);
|
||||
xchk_iallocbt_chunk_xref_other(sc, irec, agino);
|
||||
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INODES);
|
||||
xchk_xref_is_owned_by(sc, agbno, len, &oinfo);
|
||||
xchk_xref_is_owned_by(sc, agbno, len, &XFS_RMAP_OINFO_INODES);
|
||||
xchk_xref_is_not_shared(sc, agbno, len);
|
||||
}
|
||||
|
||||
@ -186,7 +188,6 @@ xchk_iallocbt_check_freemask(
|
||||
struct xchk_btree *bs,
|
||||
struct xfs_inobt_rec_incore *irec)
|
||||
{
|
||||
struct xfs_owner_info oinfo;
|
||||
struct xfs_imap imap;
|
||||
struct xfs_mount *mp = bs->cur->bc_mp;
|
||||
struct xfs_dinode *dip;
|
||||
@ -197,19 +198,16 @@ xchk_iallocbt_check_freemask(
|
||||
xfs_agino_t chunkino;
|
||||
xfs_agino_t clusterino;
|
||||
xfs_agblock_t agbno;
|
||||
int blks_per_cluster;
|
||||
uint16_t holemask;
|
||||
uint16_t ir_holemask;
|
||||
int error = 0;
|
||||
|
||||
/* Make sure the freemask matches the inode records. */
|
||||
blks_per_cluster = xfs_icluster_size_fsb(mp);
|
||||
nr_inodes = XFS_OFFBNO_TO_AGINO(mp, blks_per_cluster, 0);
|
||||
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INODES);
|
||||
nr_inodes = mp->m_inodes_per_cluster;
|
||||
|
||||
for (agino = irec->ir_startino;
|
||||
agino < irec->ir_startino + XFS_INODES_PER_CHUNK;
|
||||
agino += blks_per_cluster * mp->m_sb.sb_inopblock) {
|
||||
agino += mp->m_inodes_per_cluster) {
|
||||
fsino = XFS_AGINO_TO_INO(mp, bs->cur->bc_private.a.agno, agino);
|
||||
chunkino = agino - irec->ir_startino;
|
||||
agbno = XFS_AGINO_TO_AGBNO(mp, agino);
|
||||
@ -230,17 +228,18 @@ xchk_iallocbt_check_freemask(
|
||||
/* If any part of this is a hole, skip it. */
|
||||
if (ir_holemask) {
|
||||
xchk_xref_is_not_owned_by(bs->sc, agbno,
|
||||
blks_per_cluster, &oinfo);
|
||||
mp->m_blocks_per_cluster,
|
||||
&XFS_RMAP_OINFO_INODES);
|
||||
continue;
|
||||
}
|
||||
|
||||
xchk_xref_is_owned_by(bs->sc, agbno, blks_per_cluster,
|
||||
&oinfo);
|
||||
xchk_xref_is_owned_by(bs->sc, agbno, mp->m_blocks_per_cluster,
|
||||
&XFS_RMAP_OINFO_INODES);
|
||||
|
||||
/* Grab the inode cluster buffer. */
|
||||
imap.im_blkno = XFS_AGB_TO_DADDR(mp, bs->cur->bc_private.a.agno,
|
||||
agbno);
|
||||
imap.im_len = XFS_FSB_TO_BB(mp, blks_per_cluster);
|
||||
imap.im_len = XFS_FSB_TO_BB(mp, mp->m_blocks_per_cluster);
|
||||
imap.im_boffset = 0;
|
||||
|
||||
error = xfs_imap_to_bp(mp, bs->cur->bc_tp, &imap,
|
||||
@ -272,7 +271,7 @@ xchk_iallocbt_rec(
|
||||
union xfs_btree_rec *rec)
|
||||
{
|
||||
struct xfs_mount *mp = bs->cur->bc_mp;
|
||||
xfs_filblks_t *inode_blocks = bs->private;
|
||||
struct xchk_iallocbt *iabt = bs->private;
|
||||
struct xfs_inobt_rec_incore irec;
|
||||
uint64_t holes;
|
||||
xfs_agnumber_t agno = bs->cur->bc_private.a.agno;
|
||||
@ -306,12 +305,11 @@ xchk_iallocbt_rec(
|
||||
|
||||
/* Make sure this record is aligned to cluster and inoalignmnt size. */
|
||||
agbno = XFS_AGINO_TO_AGBNO(mp, irec.ir_startino);
|
||||
if ((agbno & (xfs_ialloc_cluster_alignment(mp) - 1)) ||
|
||||
(agbno & (xfs_icluster_size_fsb(mp) - 1)))
|
||||
if ((agbno & (mp->m_cluster_align - 1)) ||
|
||||
(agbno & (mp->m_blocks_per_cluster - 1)))
|
||||
xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
|
||||
|
||||
*inode_blocks += XFS_B_TO_FSB(mp,
|
||||
irec.ir_count * mp->m_sb.sb_inodesize);
|
||||
iabt->inodes += irec.ir_count;
|
||||
|
||||
/* Handle non-sparse inodes */
|
||||
if (!xfs_inobt_issparse(irec.ir_holemask)) {
|
||||
@ -366,7 +364,6 @@ xchk_iallocbt_xref_rmap_btreeblks(
|
||||
struct xfs_scrub *sc,
|
||||
int which)
|
||||
{
|
||||
struct xfs_owner_info oinfo;
|
||||
xfs_filblks_t blocks;
|
||||
xfs_extlen_t inobt_blocks = 0;
|
||||
xfs_extlen_t finobt_blocks = 0;
|
||||
@ -388,9 +385,8 @@ xchk_iallocbt_xref_rmap_btreeblks(
|
||||
return;
|
||||
}
|
||||
|
||||
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INOBT);
|
||||
error = xchk_count_rmap_ownedby_ag(sc, sc->sa.rmap_cur, &oinfo,
|
||||
&blocks);
|
||||
error = xchk_count_rmap_ownedby_ag(sc, sc->sa.rmap_cur,
|
||||
&XFS_RMAP_OINFO_INOBT, &blocks);
|
||||
if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
|
||||
return;
|
||||
if (blocks != inobt_blocks + finobt_blocks)
|
||||
@ -405,21 +401,21 @@ STATIC void
|
||||
xchk_iallocbt_xref_rmap_inodes(
|
||||
struct xfs_scrub *sc,
|
||||
int which,
|
||||
xfs_filblks_t inode_blocks)
|
||||
unsigned long long inodes)
|
||||
{
|
||||
struct xfs_owner_info oinfo;
|
||||
xfs_filblks_t blocks;
|
||||
xfs_filblks_t inode_blocks;
|
||||
int error;
|
||||
|
||||
if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
|
||||
return;
|
||||
|
||||
/* Check that we saw as many inode blocks as the rmap knows about. */
|
||||
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INODES);
|
||||
error = xchk_count_rmap_ownedby_ag(sc, sc->sa.rmap_cur, &oinfo,
|
||||
&blocks);
|
||||
error = xchk_count_rmap_ownedby_ag(sc, sc->sa.rmap_cur,
|
||||
&XFS_RMAP_OINFO_INODES, &blocks);
|
||||
if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
|
||||
return;
|
||||
inode_blocks = XFS_B_TO_FSB(sc->mp, inodes * sc->mp->m_sb.sb_inodesize);
|
||||
if (blocks != inode_blocks)
|
||||
xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
|
||||
}
|
||||
@ -431,14 +427,14 @@ xchk_iallocbt(
|
||||
xfs_btnum_t which)
|
||||
{
|
||||
struct xfs_btree_cur *cur;
|
||||
struct xfs_owner_info oinfo;
|
||||
xfs_filblks_t inode_blocks = 0;
|
||||
struct xchk_iallocbt iabt = {
|
||||
.inodes = 0,
|
||||
};
|
||||
int error;
|
||||
|
||||
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INOBT);
|
||||
cur = which == XFS_BTNUM_INO ? sc->sa.ino_cur : sc->sa.fino_cur;
|
||||
error = xchk_btree(sc, cur, xchk_iallocbt_rec, &oinfo,
|
||||
&inode_blocks);
|
||||
error = xchk_btree(sc, cur, xchk_iallocbt_rec, &XFS_RMAP_OINFO_INOBT,
|
||||
&iabt);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@ -452,7 +448,7 @@ xchk_iallocbt(
|
||||
* to inode chunks with free inodes.
|
||||
*/
|
||||
if (which == XFS_BTNUM_INO)
|
||||
xchk_iallocbt_xref_rmap_inodes(sc, which, inode_blocks);
|
||||
xchk_iallocbt_xref_rmap_inodes(sc, which, iabt.inodes);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
@ -509,7 +509,6 @@ xchk_inode_xref(
|
||||
xfs_ino_t ino,
|
||||
struct xfs_dinode *dip)
|
||||
{
|
||||
struct xfs_owner_info oinfo;
|
||||
xfs_agnumber_t agno;
|
||||
xfs_agblock_t agbno;
|
||||
int error;
|
||||
@ -526,8 +525,7 @@ xchk_inode_xref(
|
||||
|
||||
xchk_xref_is_used_space(sc, agbno, 1);
|
||||
xchk_inode_xref_finobt(sc, ino);
|
||||
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INODES);
|
||||
xchk_xref_is_owned_by(sc, agbno, 1, &oinfo);
|
||||
xchk_xref_is_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_INODES);
|
||||
xchk_xref_is_not_shared(sc, agbno, 1);
|
||||
xchk_inode_xref_bmap(sc, dip);
|
||||
|
||||
|
@ -383,7 +383,6 @@ xchk_refcountbt_rec(
|
||||
STATIC void
|
||||
xchk_refcount_xref_rmap(
|
||||
struct xfs_scrub *sc,
|
||||
struct xfs_owner_info *oinfo,
|
||||
xfs_filblks_t cow_blocks)
|
||||
{
|
||||
xfs_extlen_t refcbt_blocks = 0;
|
||||
@ -397,17 +396,16 @@ xchk_refcount_xref_rmap(
|
||||
error = xfs_btree_count_blocks(sc->sa.refc_cur, &refcbt_blocks);
|
||||
if (!xchk_btree_process_error(sc, sc->sa.refc_cur, 0, &error))
|
||||
return;
|
||||
error = xchk_count_rmap_ownedby_ag(sc, sc->sa.rmap_cur, oinfo,
|
||||
&blocks);
|
||||
error = xchk_count_rmap_ownedby_ag(sc, sc->sa.rmap_cur,
|
||||
&XFS_RMAP_OINFO_REFC, &blocks);
|
||||
if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
|
||||
return;
|
||||
if (blocks != refcbt_blocks)
|
||||
xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
|
||||
|
||||
/* Check that we saw as many cow blocks as the rmap knows about. */
|
||||
xfs_rmap_ag_owner(oinfo, XFS_RMAP_OWN_COW);
|
||||
error = xchk_count_rmap_ownedby_ag(sc, sc->sa.rmap_cur, oinfo,
|
||||
&blocks);
|
||||
error = xchk_count_rmap_ownedby_ag(sc, sc->sa.rmap_cur,
|
||||
&XFS_RMAP_OINFO_COW, &blocks);
|
||||
if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
|
||||
return;
|
||||
if (blocks != cow_blocks)
|
||||
@ -419,17 +417,15 @@ int
|
||||
xchk_refcountbt(
|
||||
struct xfs_scrub *sc)
|
||||
{
|
||||
struct xfs_owner_info oinfo;
|
||||
xfs_agblock_t cow_blocks = 0;
|
||||
int error;
|
||||
|
||||
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_REFC);
|
||||
error = xchk_btree(sc, sc->sa.refc_cur, xchk_refcountbt_rec,
|
||||
&oinfo, &cow_blocks);
|
||||
&XFS_RMAP_OINFO_REFC, &cow_blocks);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
xchk_refcount_xref_rmap(sc, &oinfo, cow_blocks);
|
||||
xchk_refcount_xref_rmap(sc, cow_blocks);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -299,14 +299,14 @@ xrep_calc_ag_resblks(
|
||||
/* Allocate a block in an AG. */
|
||||
int
|
||||
xrep_alloc_ag_block(
|
||||
struct xfs_scrub *sc,
|
||||
struct xfs_owner_info *oinfo,
|
||||
xfs_fsblock_t *fsbno,
|
||||
enum xfs_ag_resv_type resv)
|
||||
struct xfs_scrub *sc,
|
||||
const struct xfs_owner_info *oinfo,
|
||||
xfs_fsblock_t *fsbno,
|
||||
enum xfs_ag_resv_type resv)
|
||||
{
|
||||
struct xfs_alloc_arg args = {0};
|
||||
xfs_agblock_t bno;
|
||||
int error;
|
||||
struct xfs_alloc_arg args = {0};
|
||||
xfs_agblock_t bno;
|
||||
int error;
|
||||
|
||||
switch (resv) {
|
||||
case XFS_AG_RESV_AGFL:
|
||||
@ -505,7 +505,6 @@ xrep_put_freelist(
|
||||
struct xfs_scrub *sc,
|
||||
xfs_agblock_t agbno)
|
||||
{
|
||||
struct xfs_owner_info oinfo;
|
||||
int error;
|
||||
|
||||
/* Make sure there's space on the freelist. */
|
||||
@ -518,9 +517,8 @@ xrep_put_freelist(
|
||||
* create an rmap for the block prior to merging it or else other
|
||||
* parts will break.
|
||||
*/
|
||||
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_AG);
|
||||
error = xfs_rmap_alloc(sc->tp, sc->sa.agf_bp, sc->sa.agno, agbno, 1,
|
||||
&oinfo);
|
||||
&XFS_RMAP_OINFO_AG);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@ -538,17 +536,17 @@ xrep_put_freelist(
|
||||
/* Dispose of a single block. */
|
||||
STATIC int
|
||||
xrep_reap_block(
|
||||
struct xfs_scrub *sc,
|
||||
xfs_fsblock_t fsbno,
|
||||
struct xfs_owner_info *oinfo,
|
||||
enum xfs_ag_resv_type resv)
|
||||
struct xfs_scrub *sc,
|
||||
xfs_fsblock_t fsbno,
|
||||
const struct xfs_owner_info *oinfo,
|
||||
enum xfs_ag_resv_type resv)
|
||||
{
|
||||
struct xfs_btree_cur *cur;
|
||||
struct xfs_buf *agf_bp = NULL;
|
||||
xfs_agnumber_t agno;
|
||||
xfs_agblock_t agbno;
|
||||
bool has_other_rmap;
|
||||
int error;
|
||||
struct xfs_btree_cur *cur;
|
||||
struct xfs_buf *agf_bp = NULL;
|
||||
xfs_agnumber_t agno;
|
||||
xfs_agblock_t agbno;
|
||||
bool has_other_rmap;
|
||||
int error;
|
||||
|
||||
agno = XFS_FSB_TO_AGNO(sc->mp, fsbno);
|
||||
agbno = XFS_FSB_TO_AGBNO(sc->mp, fsbno);
|
||||
@ -612,15 +610,15 @@ out_free:
|
||||
/* Dispose of every block of every extent in the bitmap. */
|
||||
int
|
||||
xrep_reap_extents(
|
||||
struct xfs_scrub *sc,
|
||||
struct xfs_bitmap *bitmap,
|
||||
struct xfs_owner_info *oinfo,
|
||||
enum xfs_ag_resv_type type)
|
||||
struct xfs_scrub *sc,
|
||||
struct xfs_bitmap *bitmap,
|
||||
const struct xfs_owner_info *oinfo,
|
||||
enum xfs_ag_resv_type type)
|
||||
{
|
||||
struct xfs_bitmap_range *bmr;
|
||||
struct xfs_bitmap_range *n;
|
||||
xfs_fsblock_t fsbno;
|
||||
int error = 0;
|
||||
struct xfs_bitmap_range *bmr;
|
||||
struct xfs_bitmap_range *n;
|
||||
xfs_fsblock_t fsbno;
|
||||
int error = 0;
|
||||
|
||||
ASSERT(xfs_sb_version_hasrmapbt(&sc->mp->m_sb));
|
||||
|
||||
|
@ -21,8 +21,9 @@ int xrep_roll_ag_trans(struct xfs_scrub *sc);
|
||||
bool xrep_ag_has_space(struct xfs_perag *pag, xfs_extlen_t nr_blocks,
|
||||
enum xfs_ag_resv_type type);
|
||||
xfs_extlen_t xrep_calc_ag_resblks(struct xfs_scrub *sc);
|
||||
int xrep_alloc_ag_block(struct xfs_scrub *sc, struct xfs_owner_info *oinfo,
|
||||
xfs_fsblock_t *fsbno, enum xfs_ag_resv_type resv);
|
||||
int xrep_alloc_ag_block(struct xfs_scrub *sc,
|
||||
const struct xfs_owner_info *oinfo, xfs_fsblock_t *fsbno,
|
||||
enum xfs_ag_resv_type resv);
|
||||
int xrep_init_btblock(struct xfs_scrub *sc, xfs_fsblock_t fsb,
|
||||
struct xfs_buf **bpp, xfs_btnum_t btnum,
|
||||
const struct xfs_buf_ops *ops);
|
||||
@ -32,7 +33,7 @@ struct xfs_bitmap;
|
||||
int xrep_fix_freelist(struct xfs_scrub *sc, bool can_shrink);
|
||||
int xrep_invalidate_blocks(struct xfs_scrub *sc, struct xfs_bitmap *btlist);
|
||||
int xrep_reap_extents(struct xfs_scrub *sc, struct xfs_bitmap *exlist,
|
||||
struct xfs_owner_info *oinfo, enum xfs_ag_resv_type type);
|
||||
const struct xfs_owner_info *oinfo, enum xfs_ag_resv_type type);
|
||||
|
||||
struct xrep_find_ag_btree {
|
||||
/* in: rmap owner of the btree we're looking for */
|
||||
|
@ -174,24 +174,21 @@ int
|
||||
xchk_rmapbt(
|
||||
struct xfs_scrub *sc)
|
||||
{
|
||||
struct xfs_owner_info oinfo;
|
||||
|
||||
xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_AG);
|
||||
return xchk_btree(sc, sc->sa.rmap_cur, xchk_rmapbt_rec,
|
||||
&oinfo, NULL);
|
||||
&XFS_RMAP_OINFO_AG, NULL);
|
||||
}
|
||||
|
||||
/* xref check that the extent is owned by a given owner */
|
||||
static inline void
|
||||
xchk_xref_check_owner(
|
||||
struct xfs_scrub *sc,
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
struct xfs_owner_info *oinfo,
|
||||
bool should_have_rmap)
|
||||
struct xfs_scrub *sc,
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
const struct xfs_owner_info *oinfo,
|
||||
bool should_have_rmap)
|
||||
{
|
||||
bool has_rmap;
|
||||
int error;
|
||||
bool has_rmap;
|
||||
int error;
|
||||
|
||||
if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
|
||||
return;
|
||||
@ -207,10 +204,10 @@ xchk_xref_check_owner(
|
||||
/* xref check that the extent is owned by a given owner */
|
||||
void
|
||||
xchk_xref_is_owned_by(
|
||||
struct xfs_scrub *sc,
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
struct xfs_owner_info *oinfo)
|
||||
struct xfs_scrub *sc,
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
const struct xfs_owner_info *oinfo)
|
||||
{
|
||||
xchk_xref_check_owner(sc, bno, len, oinfo, true);
|
||||
}
|
||||
@ -218,10 +215,10 @@ xchk_xref_is_owned_by(
|
||||
/* xref check that the extent is not owned by a given owner */
|
||||
void
|
||||
xchk_xref_is_not_owned_by(
|
||||
struct xfs_scrub *sc,
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
struct xfs_owner_info *oinfo)
|
||||
struct xfs_scrub *sc,
|
||||
xfs_agblock_t bno,
|
||||
xfs_extlen_t len,
|
||||
const struct xfs_owner_info *oinfo)
|
||||
{
|
||||
xchk_xref_check_owner(sc, bno, len, oinfo, false);
|
||||
}
|
||||
|
@ -122,9 +122,9 @@ void xchk_xref_is_not_inode_chunk(struct xfs_scrub *sc, xfs_agblock_t agbno,
|
||||
void xchk_xref_is_inode_chunk(struct xfs_scrub *sc, xfs_agblock_t agbno,
|
||||
xfs_extlen_t len);
|
||||
void xchk_xref_is_owned_by(struct xfs_scrub *sc, xfs_agblock_t agbno,
|
||||
xfs_extlen_t len, struct xfs_owner_info *oinfo);
|
||||
xfs_extlen_t len, const struct xfs_owner_info *oinfo);
|
||||
void xchk_xref_is_not_owned_by(struct xfs_scrub *sc, xfs_agblock_t agbno,
|
||||
xfs_extlen_t len, struct xfs_owner_info *oinfo);
|
||||
xfs_extlen_t len, const struct xfs_owner_info *oinfo);
|
||||
void xchk_xref_has_no_owner(struct xfs_scrub *sc, xfs_agblock_t agbno,
|
||||
xfs_extlen_t len);
|
||||
void xchk_xref_is_cow_staging(struct xfs_scrub *sc, xfs_agblock_t bno,
|
||||
|
@ -12,6 +12,71 @@
|
||||
#include <linux/tracepoint.h>
|
||||
#include "xfs_bit.h"
|
||||
|
||||
/*
|
||||
* ftrace's __print_symbolic requires that all enum values be wrapped in the
|
||||
* TRACE_DEFINE_ENUM macro so that the enum value can be encoded in the ftrace
|
||||
* ring buffer. Somehow this was only worth mentioning in the ftrace sample
|
||||
* code.
|
||||
*/
|
||||
TRACE_DEFINE_ENUM(XFS_BTNUM_BNOi);
|
||||
TRACE_DEFINE_ENUM(XFS_BTNUM_CNTi);
|
||||
TRACE_DEFINE_ENUM(XFS_BTNUM_BMAPi);
|
||||
TRACE_DEFINE_ENUM(XFS_BTNUM_INOi);
|
||||
TRACE_DEFINE_ENUM(XFS_BTNUM_FINOi);
|
||||
TRACE_DEFINE_ENUM(XFS_BTNUM_RMAPi);
|
||||
TRACE_DEFINE_ENUM(XFS_BTNUM_REFCi);
|
||||
|
||||
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_PROBE);
|
||||
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_SB);
|
||||
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_AGF);
|
||||
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_AGFL);
|
||||
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_AGI);
|
||||
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_BNOBT);
|
||||
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_CNTBT);
|
||||
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_INOBT);
|
||||
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_FINOBT);
|
||||
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_RMAPBT);
|
||||
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_REFCNTBT);
|
||||
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_INODE);
|
||||
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_BMBTD);
|
||||
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_BMBTA);
|
||||
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_BMBTC);
|
||||
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_DIR);
|
||||
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_XATTR);
|
||||
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_SYMLINK);
|
||||
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_PARENT);
|
||||
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_RTBITMAP);
|
||||
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_RTSUM);
|
||||
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_UQUOTA);
|
||||
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_GQUOTA);
|
||||
TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_PQUOTA);
|
||||
|
||||
#define XFS_SCRUB_TYPE_STRINGS \
|
||||
{ XFS_SCRUB_TYPE_PROBE, "probe" }, \
|
||||
{ XFS_SCRUB_TYPE_SB, "sb" }, \
|
||||
{ XFS_SCRUB_TYPE_AGF, "agf" }, \
|
||||
{ XFS_SCRUB_TYPE_AGFL, "agfl" }, \
|
||||
{ XFS_SCRUB_TYPE_AGI, "agi" }, \
|
||||
{ XFS_SCRUB_TYPE_BNOBT, "bnobt" }, \
|
||||
{ XFS_SCRUB_TYPE_CNTBT, "cntbt" }, \
|
||||
{ XFS_SCRUB_TYPE_INOBT, "inobt" }, \
|
||||
{ XFS_SCRUB_TYPE_FINOBT, "finobt" }, \
|
||||
{ XFS_SCRUB_TYPE_RMAPBT, "rmapbt" }, \
|
||||
{ XFS_SCRUB_TYPE_REFCNTBT, "refcountbt" }, \
|
||||
{ XFS_SCRUB_TYPE_INODE, "inode" }, \
|
||||
{ XFS_SCRUB_TYPE_BMBTD, "bmapbtd" }, \
|
||||
{ XFS_SCRUB_TYPE_BMBTA, "bmapbta" }, \
|
||||
{ XFS_SCRUB_TYPE_BMBTC, "bmapbtc" }, \
|
||||
{ XFS_SCRUB_TYPE_DIR, "directory" }, \
|
||||
{ XFS_SCRUB_TYPE_XATTR, "xattr" }, \
|
||||
{ XFS_SCRUB_TYPE_SYMLINK, "symlink" }, \
|
||||
{ XFS_SCRUB_TYPE_PARENT, "parent" }, \
|
||||
{ XFS_SCRUB_TYPE_RTBITMAP, "rtbitmap" }, \
|
||||
{ XFS_SCRUB_TYPE_RTSUM, "rtsummary" }, \
|
||||
{ XFS_SCRUB_TYPE_UQUOTA, "usrquota" }, \
|
||||
{ XFS_SCRUB_TYPE_GQUOTA, "grpquota" }, \
|
||||
{ XFS_SCRUB_TYPE_PQUOTA, "prjquota" }
|
||||
|
||||
DECLARE_EVENT_CLASS(xchk_class,
|
||||
TP_PROTO(struct xfs_inode *ip, struct xfs_scrub_metadata *sm,
|
||||
int error),
|
||||
@ -36,10 +101,10 @@ DECLARE_EVENT_CLASS(xchk_class,
|
||||
__entry->flags = sm->sm_flags;
|
||||
__entry->error = error;
|
||||
),
|
||||
TP_printk("dev %d:%d ino 0x%llx type %u agno %u inum %llu gen %u flags 0x%x error %d",
|
||||
TP_printk("dev %d:%d ino 0x%llx type %s agno %u inum %llu gen %u flags 0x%x error %d",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
__entry->ino,
|
||||
__entry->type,
|
||||
__print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
|
||||
__entry->agno,
|
||||
__entry->inum,
|
||||
__entry->gen,
|
||||
@ -78,9 +143,9 @@ TRACE_EVENT(xchk_op_error,
|
||||
__entry->error = error;
|
||||
__entry->ret_ip = ret_ip;
|
||||
),
|
||||
TP_printk("dev %d:%d type %u agno %u agbno %u error %d ret_ip %pS",
|
||||
TP_printk("dev %d:%d type %s agno %u agbno %u error %d ret_ip %pS",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
__entry->type,
|
||||
__print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
|
||||
__entry->agno,
|
||||
__entry->bno,
|
||||
__entry->error,
|
||||
@ -109,11 +174,11 @@ TRACE_EVENT(xchk_file_op_error,
|
||||
__entry->error = error;
|
||||
__entry->ret_ip = ret_ip;
|
||||
),
|
||||
TP_printk("dev %d:%d ino 0x%llx fork %d type %u offset %llu error %d ret_ip %pS",
|
||||
TP_printk("dev %d:%d ino 0x%llx fork %d type %s offset %llu error %d ret_ip %pS",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
__entry->ino,
|
||||
__entry->whichfork,
|
||||
__entry->type,
|
||||
__print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
|
||||
__entry->offset,
|
||||
__entry->error,
|
||||
__entry->ret_ip)
|
||||
@ -144,9 +209,9 @@ DECLARE_EVENT_CLASS(xchk_block_error_class,
|
||||
__entry->bno = bno;
|
||||
__entry->ret_ip = ret_ip;
|
||||
),
|
||||
TP_printk("dev %d:%d type %u agno %u agbno %u ret_ip %pS",
|
||||
TP_printk("dev %d:%d type %s agno %u agbno %u ret_ip %pS",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
__entry->type,
|
||||
__print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
|
||||
__entry->agno,
|
||||
__entry->bno,
|
||||
__entry->ret_ip)
|
||||
@ -176,10 +241,10 @@ DECLARE_EVENT_CLASS(xchk_ino_error_class,
|
||||
__entry->type = sc->sm->sm_type;
|
||||
__entry->ret_ip = ret_ip;
|
||||
),
|
||||
TP_printk("dev %d:%d ino 0x%llx type %u ret_ip %pS",
|
||||
TP_printk("dev %d:%d ino 0x%llx type %s ret_ip %pS",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
__entry->ino,
|
||||
__entry->type,
|
||||
__print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
|
||||
__entry->ret_ip)
|
||||
)
|
||||
|
||||
@ -213,11 +278,11 @@ DECLARE_EVENT_CLASS(xchk_fblock_error_class,
|
||||
__entry->offset = offset;
|
||||
__entry->ret_ip = ret_ip;
|
||||
),
|
||||
TP_printk("dev %d:%d ino 0x%llx fork %d type %u offset %llu ret_ip %pS",
|
||||
TP_printk("dev %d:%d ino 0x%llx fork %d type %s offset %llu ret_ip %pS",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
__entry->ino,
|
||||
__entry->whichfork,
|
||||
__entry->type,
|
||||
__print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
|
||||
__entry->offset,
|
||||
__entry->ret_ip)
|
||||
);
|
||||
@ -244,9 +309,9 @@ TRACE_EVENT(xchk_incomplete,
|
||||
__entry->type = sc->sm->sm_type;
|
||||
__entry->ret_ip = ret_ip;
|
||||
),
|
||||
TP_printk("dev %d:%d type %u ret_ip %pS",
|
||||
TP_printk("dev %d:%d type %s ret_ip %pS",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
__entry->type,
|
||||
__print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
|
||||
__entry->ret_ip)
|
||||
);
|
||||
|
||||
@ -278,10 +343,10 @@ TRACE_EVENT(xchk_btree_op_error,
|
||||
__entry->error = error;
|
||||
__entry->ret_ip = ret_ip;
|
||||
),
|
||||
TP_printk("dev %d:%d type %u btnum %d level %d ptr %d agno %u agbno %u error %d ret_ip %pS",
|
||||
TP_printk("dev %d:%d type %s btree %s level %d ptr %d agno %u agbno %u error %d ret_ip %pS",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
__entry->type,
|
||||
__entry->btnum,
|
||||
__print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
|
||||
__print_symbolic(__entry->btnum, XFS_BTNUM_STRINGS),
|
||||
__entry->level,
|
||||
__entry->ptr,
|
||||
__entry->agno,
|
||||
@ -321,12 +386,12 @@ TRACE_EVENT(xchk_ifork_btree_op_error,
|
||||
__entry->error = error;
|
||||
__entry->ret_ip = ret_ip;
|
||||
),
|
||||
TP_printk("dev %d:%d ino 0x%llx fork %d type %u btnum %d level %d ptr %d agno %u agbno %u error %d ret_ip %pS",
|
||||
TP_printk("dev %d:%d ino 0x%llx fork %d type %s btree %s level %d ptr %d agno %u agbno %u error %d ret_ip %pS",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
__entry->ino,
|
||||
__entry->whichfork,
|
||||
__entry->type,
|
||||
__entry->btnum,
|
||||
__print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
|
||||
__print_symbolic(__entry->btnum, XFS_BTNUM_STRINGS),
|
||||
__entry->level,
|
||||
__entry->ptr,
|
||||
__entry->agno,
|
||||
@ -360,10 +425,10 @@ TRACE_EVENT(xchk_btree_error,
|
||||
__entry->ptr = cur->bc_ptrs[level];
|
||||
__entry->ret_ip = ret_ip;
|
||||
),
|
||||
TP_printk("dev %d:%d type %u btnum %d level %d ptr %d agno %u agbno %u ret_ip %pS",
|
||||
TP_printk("dev %d:%d type %s btree %s level %d ptr %d agno %u agbno %u ret_ip %pS",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
__entry->type,
|
||||
__entry->btnum,
|
||||
__print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
|
||||
__print_symbolic(__entry->btnum, XFS_BTNUM_STRINGS),
|
||||
__entry->level,
|
||||
__entry->ptr,
|
||||
__entry->agno,
|
||||
@ -400,12 +465,12 @@ TRACE_EVENT(xchk_ifork_btree_error,
|
||||
__entry->ptr = cur->bc_ptrs[level];
|
||||
__entry->ret_ip = ret_ip;
|
||||
),
|
||||
TP_printk("dev %d:%d ino 0x%llx fork %d type %u btnum %d level %d ptr %d agno %u agbno %u ret_ip %pS",
|
||||
TP_printk("dev %d:%d ino 0x%llx fork %d type %s btree %s level %d ptr %d agno %u agbno %u ret_ip %pS",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
__entry->ino,
|
||||
__entry->whichfork,
|
||||
__entry->type,
|
||||
__entry->btnum,
|
||||
__print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
|
||||
__print_symbolic(__entry->btnum, XFS_BTNUM_STRINGS),
|
||||
__entry->level,
|
||||
__entry->ptr,
|
||||
__entry->agno,
|
||||
@ -439,10 +504,10 @@ DECLARE_EVENT_CLASS(xchk_sbtree_class,
|
||||
__entry->nlevels = cur->bc_nlevels;
|
||||
__entry->ptr = cur->bc_ptrs[level];
|
||||
),
|
||||
TP_printk("dev %d:%d type %u btnum %d agno %u agbno %u level %d nlevels %d ptr %d",
|
||||
TP_printk("dev %d:%d type %s btree %s agno %u agbno %u level %d nlevels %d ptr %d",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
__entry->type,
|
||||
__entry->btnum,
|
||||
__print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
|
||||
__print_symbolic(__entry->btnum, XFS_BTNUM_STRINGS),
|
||||
__entry->agno,
|
||||
__entry->bno,
|
||||
__entry->level,
|
||||
@ -473,9 +538,9 @@ TRACE_EVENT(xchk_xref_error,
|
||||
__entry->error = error;
|
||||
__entry->ret_ip = ret_ip;
|
||||
),
|
||||
TP_printk("dev %d:%d type %u xref error %d ret_ip %pF",
|
||||
TP_printk("dev %d:%d type %s xref error %d ret_ip %pS",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
__entry->type,
|
||||
__print_symbolic(__entry->type, XFS_SCRUB_TYPE_STRINGS),
|
||||
__entry->error,
|
||||
__entry->ret_ip)
|
||||
);
|
||||
@ -598,11 +663,11 @@ TRACE_EVENT(xrep_init_btblock,
|
||||
__entry->agbno = agbno;
|
||||
__entry->btnum = btnum;
|
||||
),
|
||||
TP_printk("dev %d:%d agno %u agbno %u btnum %d",
|
||||
TP_printk("dev %d:%d agno %u agbno %u btree %s",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
__entry->agno,
|
||||
__entry->agbno,
|
||||
__entry->btnum)
|
||||
__print_symbolic(__entry->btnum, XFS_BTNUM_STRINGS))
|
||||
)
|
||||
TRACE_EVENT(xrep_findroot_block,
|
||||
TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agblock_t agbno,
|
||||
|
@ -10,6 +10,9 @@ extern struct bio_set xfs_ioend_bioset;
|
||||
|
||||
/*
|
||||
* Types of I/O for bmap clustering and I/O completion tracking.
|
||||
*
|
||||
* This enum is used in string mapping in xfs_trace.h; please keep the
|
||||
* TRACE_DEFINE_ENUMs for it up to date.
|
||||
*/
|
||||
enum {
|
||||
XFS_IO_HOLE, /* covers region without any block allocation */
|
||||
|
@ -494,7 +494,6 @@ xfs_efi_recover(
|
||||
int error = 0;
|
||||
xfs_extent_t *extp;
|
||||
xfs_fsblock_t startblock_fsb;
|
||||
struct xfs_owner_info oinfo;
|
||||
|
||||
ASSERT(!test_bit(XFS_EFI_RECOVERED, &efip->efi_flags));
|
||||
|
||||
@ -526,11 +525,11 @@ xfs_efi_recover(
|
||||
return error;
|
||||
efdp = xfs_trans_get_efd(tp, efip, efip->efi_format.efi_nextents);
|
||||
|
||||
xfs_rmap_any_owner_update(&oinfo);
|
||||
for (i = 0; i < efip->efi_format.efi_nextents; i++) {
|
||||
extp = &efip->efi_format.efi_extents[i];
|
||||
error = xfs_trans_free_extent(tp, efdp, extp->ext_start,
|
||||
extp->ext_len, &oinfo, false);
|
||||
extp->ext_len,
|
||||
&XFS_RMAP_OINFO_ANY_OWNER, false);
|
||||
if (error)
|
||||
goto abort_error;
|
||||
|
||||
|
@ -252,7 +252,7 @@ xfs_growfs_data(
|
||||
if (mp->m_sb.sb_imax_pct) {
|
||||
uint64_t icount = mp->m_sb.sb_dblocks * mp->m_sb.sb_imax_pct;
|
||||
do_div(icount, 100);
|
||||
mp->m_maxicount = icount << mp->m_sb.sb_inopblog;
|
||||
mp->m_maxicount = XFS_FSB_TO_INO(mp, icount);
|
||||
} else
|
||||
mp->m_maxicount = 0;
|
||||
|
||||
|
@ -2184,8 +2184,6 @@ xfs_ifree_cluster(
|
||||
struct xfs_icluster *xic)
|
||||
{
|
||||
xfs_mount_t *mp = free_ip->i_mount;
|
||||
int blks_per_cluster;
|
||||
int inodes_per_cluster;
|
||||
int nbufs;
|
||||
int i, j;
|
||||
int ioffset;
|
||||
@ -2199,11 +2197,9 @@ xfs_ifree_cluster(
|
||||
|
||||
inum = xic->first_ino;
|
||||
pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, inum));
|
||||
blks_per_cluster = xfs_icluster_size_fsb(mp);
|
||||
inodes_per_cluster = blks_per_cluster << mp->m_sb.sb_inopblog;
|
||||
nbufs = mp->m_ialloc_blks / blks_per_cluster;
|
||||
nbufs = mp->m_ialloc_blks / mp->m_blocks_per_cluster;
|
||||
|
||||
for (j = 0; j < nbufs; j++, inum += inodes_per_cluster) {
|
||||
for (j = 0; j < nbufs; j++, inum += mp->m_inodes_per_cluster) {
|
||||
/*
|
||||
* The allocation bitmap tells us which inodes of the chunk were
|
||||
* physically allocated. Skip the cluster if an inode falls into
|
||||
@ -2211,7 +2207,7 @@ xfs_ifree_cluster(
|
||||
*/
|
||||
ioffset = inum - xic->first_ino;
|
||||
if ((xic->alloc & XFS_INOBT_MASK(ioffset)) == 0) {
|
||||
ASSERT(ioffset % inodes_per_cluster == 0);
|
||||
ASSERT(ioffset % mp->m_inodes_per_cluster == 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -2227,7 +2223,7 @@ xfs_ifree_cluster(
|
||||
* to mark all the active inodes on the buffer stale.
|
||||
*/
|
||||
bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, blkno,
|
||||
mp->m_bsize * blks_per_cluster,
|
||||
mp->m_bsize * mp->m_blocks_per_cluster,
|
||||
XBF_UNMAPPED);
|
||||
|
||||
if (!bp)
|
||||
@ -2242,7 +2238,7 @@ xfs_ifree_cluster(
|
||||
* want it to fail. We can acheive this by adding a write
|
||||
* verifier to the buffer.
|
||||
*/
|
||||
bp->b_ops = &xfs_inode_buf_ops;
|
||||
bp->b_ops = &xfs_inode_buf_ops;
|
||||
|
||||
/*
|
||||
* Walk the inodes already attached to the buffer and mark them
|
||||
@ -2274,7 +2270,7 @@ xfs_ifree_cluster(
|
||||
* transaction stale above, which means there is no point in
|
||||
* even trying to lock them.
|
||||
*/
|
||||
for (i = 0; i < inodes_per_cluster; i++) {
|
||||
for (i = 0; i < mp->m_inodes_per_cluster; i++) {
|
||||
retry:
|
||||
rcu_read_lock();
|
||||
ip = radix_tree_lookup(&pag->pag_ici_root,
|
||||
|
@ -241,6 +241,32 @@ xfs_compat_ioc_bulkstat(
|
||||
int done;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* Output structure handling functions. Depending on the command,
|
||||
* either the xfs_bstat and xfs_inogrp structures are written out
|
||||
* to userpace memory via bulkreq.ubuffer. Normally the compat
|
||||
* functions and structure size are the correct ones to use ...
|
||||
*/
|
||||
inumbers_fmt_pf inumbers_func = xfs_inumbers_fmt_compat;
|
||||
bulkstat_one_pf bs_one_func = xfs_bulkstat_one_compat;
|
||||
size_t bs_one_size = sizeof(struct compat_xfs_bstat);
|
||||
|
||||
#ifdef CONFIG_X86_X32
|
||||
if (in_x32_syscall()) {
|
||||
/*
|
||||
* ... but on x32 the input xfs_fsop_bulkreq has pointers
|
||||
* which must be handled in the "compat" (32-bit) way, while
|
||||
* the xfs_bstat and xfs_inogrp structures follow native 64-
|
||||
* bit layout convention. So adjust accordingly, otherwise
|
||||
* the data written out in compat layout will not match what
|
||||
* x32 userspace expects.
|
||||
*/
|
||||
inumbers_func = xfs_inumbers_fmt;
|
||||
bs_one_func = xfs_bulkstat_one;
|
||||
bs_one_size = sizeof(struct xfs_bstat);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* done = 1 if there are more stats to get and if bulkstat */
|
||||
/* should be called again (unused here, but used in dmapi) */
|
||||
|
||||
@ -272,15 +298,15 @@ xfs_compat_ioc_bulkstat(
|
||||
|
||||
if (cmd == XFS_IOC_FSINUMBERS_32) {
|
||||
error = xfs_inumbers(mp, &inlast, &count,
|
||||
bulkreq.ubuffer, xfs_inumbers_fmt_compat);
|
||||
bulkreq.ubuffer, inumbers_func);
|
||||
} else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE_32) {
|
||||
int res;
|
||||
|
||||
error = xfs_bulkstat_one_compat(mp, inlast, bulkreq.ubuffer,
|
||||
sizeof(compat_xfs_bstat_t), NULL, &res);
|
||||
error = bs_one_func(mp, inlast, bulkreq.ubuffer,
|
||||
bs_one_size, NULL, &res);
|
||||
} else if (cmd == XFS_IOC_FSBULKSTAT_32) {
|
||||
error = xfs_bulkstat(mp, &inlast, &count,
|
||||
xfs_bulkstat_one_compat, sizeof(compat_xfs_bstat_t),
|
||||
bs_one_func, bs_one_size,
|
||||
bulkreq.ubuffer, &done);
|
||||
} else
|
||||
error = -EINVAL;
|
||||
@ -336,6 +362,7 @@ xfs_compat_attrlist_by_handle(
|
||||
{
|
||||
int error;
|
||||
attrlist_cursor_kern_t *cursor;
|
||||
compat_xfs_fsop_attrlist_handlereq_t __user *p = arg;
|
||||
compat_xfs_fsop_attrlist_handlereq_t al_hreq;
|
||||
struct dentry *dentry;
|
||||
char *kbuf;
|
||||
@ -370,6 +397,11 @@ xfs_compat_attrlist_by_handle(
|
||||
if (error)
|
||||
goto out_kfree;
|
||||
|
||||
if (copy_to_user(&p->pos, cursor, sizeof(attrlist_cursor_kern_t))) {
|
||||
error = -EFAULT;
|
||||
goto out_kfree;
|
||||
}
|
||||
|
||||
if (copy_to_user(compat_ptr(al_hreq.buffer), kbuf, al_hreq.buflen))
|
||||
error = -EFAULT;
|
||||
|
||||
@ -547,8 +579,12 @@ xfs_file_compat_ioctl(
|
||||
case FS_IOC_GETFSMAP:
|
||||
case XFS_IOC_SCRUB_METADATA:
|
||||
return xfs_file_ioctl(filp, cmd, p);
|
||||
#ifndef BROKEN_X86_ALIGNMENT
|
||||
/* These are handled fine if no alignment issues */
|
||||
#if !defined(BROKEN_X86_ALIGNMENT) || defined(CONFIG_X86_X32)
|
||||
/*
|
||||
* These are handled fine if no alignment issues. To support x32
|
||||
* which uses native 64-bit alignment we must emit these cases in
|
||||
* addition to the ia-32 compat set below.
|
||||
*/
|
||||
case XFS_IOC_ALLOCSP:
|
||||
case XFS_IOC_FREESP:
|
||||
case XFS_IOC_RESVSP:
|
||||
@ -561,8 +597,16 @@ xfs_file_compat_ioctl(
|
||||
case XFS_IOC_FSGROWFSDATA:
|
||||
case XFS_IOC_FSGROWFSRT:
|
||||
case XFS_IOC_ZERO_RANGE:
|
||||
#ifdef CONFIG_X86_X32
|
||||
/*
|
||||
* x32 special: this gets a different cmd number from the ia-32 compat
|
||||
* case below; the associated data will match native 64-bit alignment.
|
||||
*/
|
||||
case XFS_IOC_SWAPEXT:
|
||||
#endif
|
||||
return xfs_file_ioctl(filp, cmd, p);
|
||||
#else
|
||||
#endif
|
||||
#if defined(BROKEN_X86_ALIGNMENT)
|
||||
case XFS_IOC_ALLOCSP_32:
|
||||
case XFS_IOC_FREESP_32:
|
||||
case XFS_IOC_ALLOCSP64_32:
|
||||
|
@ -167,20 +167,18 @@ xfs_bulkstat_ichunk_ra(
|
||||
{
|
||||
xfs_agblock_t agbno;
|
||||
struct blk_plug plug;
|
||||
int blks_per_cluster;
|
||||
int inodes_per_cluster;
|
||||
int i; /* inode chunk index */
|
||||
|
||||
agbno = XFS_AGINO_TO_AGBNO(mp, irec->ir_startino);
|
||||
blks_per_cluster = xfs_icluster_size_fsb(mp);
|
||||
inodes_per_cluster = blks_per_cluster << mp->m_sb.sb_inopblog;
|
||||
|
||||
blk_start_plug(&plug);
|
||||
for (i = 0; i < XFS_INODES_PER_CHUNK;
|
||||
i += inodes_per_cluster, agbno += blks_per_cluster) {
|
||||
if (xfs_inobt_maskn(i, inodes_per_cluster) & ~irec->ir_free) {
|
||||
xfs_btree_reada_bufs(mp, agno, agbno, blks_per_cluster,
|
||||
&xfs_inode_buf_ops);
|
||||
i += mp->m_inodes_per_cluster, agbno += mp->m_blocks_per_cluster) {
|
||||
if (xfs_inobt_maskn(i, mp->m_inodes_per_cluster) &
|
||||
~irec->ir_free) {
|
||||
xfs_btree_reada_bufs(mp, agno, agbno,
|
||||
mp->m_blocks_per_cluster,
|
||||
&xfs_inode_buf_ops);
|
||||
}
|
||||
}
|
||||
blk_finish_plug(&plug);
|
||||
|
@ -3850,7 +3850,6 @@ xlog_recover_do_icreate_pass2(
|
||||
unsigned int count;
|
||||
unsigned int isize;
|
||||
xfs_agblock_t length;
|
||||
int blks_per_cluster;
|
||||
int bb_per_cluster;
|
||||
int cancel_count;
|
||||
int nbufs;
|
||||
@ -3918,14 +3917,13 @@ xlog_recover_do_icreate_pass2(
|
||||
* buffers for cancellation so we don't overwrite anything written after
|
||||
* a cancellation.
|
||||
*/
|
||||
blks_per_cluster = xfs_icluster_size_fsb(mp);
|
||||
bb_per_cluster = XFS_FSB_TO_BB(mp, blks_per_cluster);
|
||||
nbufs = length / blks_per_cluster;
|
||||
bb_per_cluster = XFS_FSB_TO_BB(mp, mp->m_blocks_per_cluster);
|
||||
nbufs = length / mp->m_blocks_per_cluster;
|
||||
for (i = 0, cancel_count = 0; i < nbufs; i++) {
|
||||
xfs_daddr_t daddr;
|
||||
|
||||
daddr = XFS_AGB_TO_DADDR(mp, agno,
|
||||
agbno + i * blks_per_cluster);
|
||||
agbno + i * mp->m_blocks_per_cluster);
|
||||
if (xlog_check_buffer_cancelled(log, daddr, bb_per_cluster, 0))
|
||||
cancel_count++;
|
||||
}
|
||||
|
@ -798,6 +798,10 @@ xfs_mountfs(
|
||||
if (mp->m_sb.sb_inoalignmt >= XFS_B_TO_FSBT(mp, new_size))
|
||||
mp->m_inode_cluster_size = new_size;
|
||||
}
|
||||
mp->m_blocks_per_cluster = xfs_icluster_size_fsb(mp);
|
||||
mp->m_inodes_per_cluster = XFS_FSB_TO_INO(mp, mp->m_blocks_per_cluster);
|
||||
mp->m_cluster_align = xfs_ialloc_cluster_alignment(mp);
|
||||
mp->m_cluster_align_inodes = XFS_FSB_TO_INO(mp, mp->m_cluster_align);
|
||||
|
||||
/*
|
||||
* If enabled, sparse inode chunk alignment is expected to match the
|
||||
|
@ -89,6 +89,13 @@ typedef struct xfs_mount {
|
||||
int m_logbsize; /* size of each log buffer */
|
||||
uint m_rsumlevels; /* rt summary levels */
|
||||
uint m_rsumsize; /* size of rt summary, bytes */
|
||||
/*
|
||||
* Optional cache of rt summary level per bitmap block with the
|
||||
* invariant that m_rsum_cache[bbno] <= the minimum i for which
|
||||
* rsum[i][bbno] != 0. Reads and writes are serialized by the rsumip
|
||||
* inode lock.
|
||||
*/
|
||||
uint8_t *m_rsum_cache;
|
||||
struct xfs_inode *m_rbmip; /* pointer to bitmap inode */
|
||||
struct xfs_inode *m_rsumip; /* pointer to summary inode */
|
||||
struct xfs_inode *m_rootip; /* pointer to root directory */
|
||||
@ -101,6 +108,10 @@ typedef struct xfs_mount {
|
||||
uint8_t m_agno_log; /* log #ag's */
|
||||
uint8_t m_agino_log; /* #bits for agino in inum */
|
||||
uint m_inode_cluster_size;/* min inode buf size */
|
||||
unsigned int m_inodes_per_cluster;
|
||||
unsigned int m_blocks_per_cluster;
|
||||
unsigned int m_cluster_align;
|
||||
unsigned int m_cluster_align_inodes;
|
||||
uint m_blockmask; /* sb_blocksize-1 */
|
||||
uint m_blockwsize; /* sb_blocksize in words */
|
||||
uint m_blockwmask; /* blockwsize-1 */
|
||||
|
@ -623,54 +623,47 @@ out:
|
||||
}
|
||||
|
||||
/*
|
||||
* Remap parts of a file's data fork after a successful CoW.
|
||||
* Remap part of the CoW fork into the data fork.
|
||||
*
|
||||
* We aim to remap the range starting at @offset_fsb and ending at @end_fsb
|
||||
* into the data fork; this function will remap what it can (at the end of the
|
||||
* range) and update @end_fsb appropriately. Each remap gets its own
|
||||
* transaction because we can end up merging and splitting bmbt blocks for
|
||||
* every remap operation and we'd like to keep the block reservation
|
||||
* requirements as low as possible.
|
||||
*/
|
||||
int
|
||||
xfs_reflink_end_cow(
|
||||
struct xfs_inode *ip,
|
||||
xfs_off_t offset,
|
||||
xfs_off_t count)
|
||||
STATIC int
|
||||
xfs_reflink_end_cow_extent(
|
||||
struct xfs_inode *ip,
|
||||
xfs_fileoff_t offset_fsb,
|
||||
xfs_fileoff_t *end_fsb)
|
||||
{
|
||||
struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK);
|
||||
struct xfs_bmbt_irec got, del;
|
||||
struct xfs_trans *tp;
|
||||
xfs_fileoff_t offset_fsb;
|
||||
xfs_fileoff_t end_fsb;
|
||||
int error;
|
||||
unsigned int resblks;
|
||||
xfs_filblks_t rlen;
|
||||
struct xfs_iext_cursor icur;
|
||||
|
||||
trace_xfs_reflink_end_cow(ip, offset, count);
|
||||
struct xfs_bmbt_irec got, del;
|
||||
struct xfs_iext_cursor icur;
|
||||
struct xfs_mount *mp = ip->i_mount;
|
||||
struct xfs_trans *tp;
|
||||
struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK);
|
||||
xfs_filblks_t rlen;
|
||||
unsigned int resblks;
|
||||
int error;
|
||||
|
||||
/* No COW extents? That's easy! */
|
||||
if (ifp->if_bytes == 0)
|
||||
if (ifp->if_bytes == 0) {
|
||||
*end_fsb = offset_fsb;
|
||||
return 0;
|
||||
}
|
||||
|
||||
offset_fsb = XFS_B_TO_FSBT(ip->i_mount, offset);
|
||||
end_fsb = XFS_B_TO_FSB(ip->i_mount, offset + count);
|
||||
resblks = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK);
|
||||
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0,
|
||||
XFS_TRANS_RESERVE | XFS_TRANS_NOFS, &tp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/*
|
||||
* Start a rolling transaction to switch the mappings. We're
|
||||
* unlikely ever to have to remap 16T worth of single-block
|
||||
* extents, so just cap the worst case extent count to 2^32-1.
|
||||
* Stick a warning in just in case, and avoid 64-bit division.
|
||||
* Lock the inode. We have to ijoin without automatic unlock because
|
||||
* the lead transaction is the refcountbt record deletion; the data
|
||||
* fork update follows as a deferred log item.
|
||||
*/
|
||||
BUILD_BUG_ON(MAX_RW_COUNT > UINT_MAX);
|
||||
if (end_fsb - offset_fsb > UINT_MAX) {
|
||||
error = -EFSCORRUPTED;
|
||||
xfs_force_shutdown(ip->i_mount, SHUTDOWN_CORRUPT_INCORE);
|
||||
ASSERT(0);
|
||||
goto out;
|
||||
}
|
||||
resblks = XFS_NEXTENTADD_SPACE_RES(ip->i_mount,
|
||||
(unsigned int)(end_fsb - offset_fsb),
|
||||
XFS_DATA_FORK);
|
||||
error = xfs_trans_alloc(ip->i_mount, &M_RES(ip->i_mount)->tr_write,
|
||||
resblks, 0, XFS_TRANS_RESERVE | XFS_TRANS_NOFS, &tp);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||
xfs_trans_ijoin(tp, ip, 0);
|
||||
|
||||
@ -679,80 +672,131 @@ xfs_reflink_end_cow(
|
||||
* left by the time I/O completes for the loser of the race. In that
|
||||
* case we are done.
|
||||
*/
|
||||
if (!xfs_iext_lookup_extent_before(ip, ifp, &end_fsb, &icur, &got))
|
||||
if (!xfs_iext_lookup_extent_before(ip, ifp, end_fsb, &icur, &got) ||
|
||||
got.br_startoff + got.br_blockcount <= offset_fsb) {
|
||||
*end_fsb = offset_fsb;
|
||||
goto out_cancel;
|
||||
}
|
||||
|
||||
/*
|
||||
* Structure copy @got into @del, then trim @del to the range that we
|
||||
* were asked to remap. We preserve @got for the eventual CoW fork
|
||||
* deletion; from now on @del represents the mapping that we're
|
||||
* actually remapping.
|
||||
*/
|
||||
del = got;
|
||||
xfs_trim_extent(&del, offset_fsb, *end_fsb - offset_fsb);
|
||||
|
||||
ASSERT(del.br_blockcount > 0);
|
||||
|
||||
/*
|
||||
* Only remap real extents that contain data. With AIO, speculative
|
||||
* preallocations can leak into the range we are called upon, and we
|
||||
* need to skip them.
|
||||
*/
|
||||
if (!xfs_bmap_is_real_extent(&got)) {
|
||||
*end_fsb = del.br_startoff;
|
||||
goto out_cancel;
|
||||
}
|
||||
|
||||
/* Unmap the old blocks in the data fork. */
|
||||
rlen = del.br_blockcount;
|
||||
error = __xfs_bunmapi(tp, ip, del.br_startoff, &rlen, 0, 1);
|
||||
if (error)
|
||||
goto out_cancel;
|
||||
|
||||
/* Walk backwards until we're out of the I/O range... */
|
||||
while (got.br_startoff + got.br_blockcount > offset_fsb) {
|
||||
del = got;
|
||||
xfs_trim_extent(&del, offset_fsb, end_fsb - offset_fsb);
|
||||
/* Trim the extent to whatever got unmapped. */
|
||||
xfs_trim_extent(&del, del.br_startoff + rlen, del.br_blockcount - rlen);
|
||||
trace_xfs_reflink_cow_remap(ip, &del);
|
||||
|
||||
/* Extent delete may have bumped ext forward */
|
||||
if (!del.br_blockcount)
|
||||
goto prev_extent;
|
||||
/* Free the CoW orphan record. */
|
||||
error = xfs_refcount_free_cow_extent(tp, del.br_startblock,
|
||||
del.br_blockcount);
|
||||
if (error)
|
||||
goto out_cancel;
|
||||
|
||||
/*
|
||||
* Only remap real extent that contain data. With AIO
|
||||
* speculatively preallocations can leak into the range we
|
||||
* are called upon, and we need to skip them.
|
||||
*/
|
||||
if (!xfs_bmap_is_real_extent(&got))
|
||||
goto prev_extent;
|
||||
/* Map the new blocks into the data fork. */
|
||||
error = xfs_bmap_map_extent(tp, ip, &del);
|
||||
if (error)
|
||||
goto out_cancel;
|
||||
|
||||
/* Unmap the old blocks in the data fork. */
|
||||
ASSERT(tp->t_firstblock == NULLFSBLOCK);
|
||||
rlen = del.br_blockcount;
|
||||
error = __xfs_bunmapi(tp, ip, del.br_startoff, &rlen, 0, 1);
|
||||
if (error)
|
||||
goto out_cancel;
|
||||
/* Charge this new data fork mapping to the on-disk quota. */
|
||||
xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_DELBCOUNT,
|
||||
(long)del.br_blockcount);
|
||||
|
||||
/* Trim the extent to whatever got unmapped. */
|
||||
if (rlen) {
|
||||
xfs_trim_extent(&del, del.br_startoff + rlen,
|
||||
del.br_blockcount - rlen);
|
||||
}
|
||||
trace_xfs_reflink_cow_remap(ip, &del);
|
||||
|
||||
/* Free the CoW orphan record. */
|
||||
error = xfs_refcount_free_cow_extent(tp, del.br_startblock,
|
||||
del.br_blockcount);
|
||||
if (error)
|
||||
goto out_cancel;
|
||||
|
||||
/* Map the new blocks into the data fork. */
|
||||
error = xfs_bmap_map_extent(tp, ip, &del);
|
||||
if (error)
|
||||
goto out_cancel;
|
||||
|
||||
/* Charge this new data fork mapping to the on-disk quota. */
|
||||
xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_DELBCOUNT,
|
||||
(long)del.br_blockcount);
|
||||
|
||||
/* Remove the mapping from the CoW fork. */
|
||||
xfs_bmap_del_extent_cow(ip, &icur, &got, &del);
|
||||
|
||||
error = xfs_defer_finish(&tp);
|
||||
if (error)
|
||||
goto out_cancel;
|
||||
if (!xfs_iext_get_extent(ifp, &icur, &got))
|
||||
break;
|
||||
continue;
|
||||
prev_extent:
|
||||
if (!xfs_iext_prev_extent(ifp, &icur, &got))
|
||||
break;
|
||||
}
|
||||
/* Remove the mapping from the CoW fork. */
|
||||
xfs_bmap_del_extent_cow(ip, &icur, &got, &del);
|
||||
|
||||
error = xfs_trans_commit(tp);
|
||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||
if (error)
|
||||
goto out;
|
||||
return error;
|
||||
|
||||
/* Update the caller about how much progress we made. */
|
||||
*end_fsb = del.br_startoff;
|
||||
return 0;
|
||||
|
||||
out_cancel:
|
||||
xfs_trans_cancel(tp);
|
||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||
out:
|
||||
trace_xfs_reflink_end_cow_error(ip, error, _RET_IP_);
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remap parts of a file's data fork after a successful CoW.
|
||||
*/
|
||||
int
|
||||
xfs_reflink_end_cow(
|
||||
struct xfs_inode *ip,
|
||||
xfs_off_t offset,
|
||||
xfs_off_t count)
|
||||
{
|
||||
xfs_fileoff_t offset_fsb;
|
||||
xfs_fileoff_t end_fsb;
|
||||
int error = 0;
|
||||
|
||||
trace_xfs_reflink_end_cow(ip, offset, count);
|
||||
|
||||
offset_fsb = XFS_B_TO_FSBT(ip->i_mount, offset);
|
||||
end_fsb = XFS_B_TO_FSB(ip->i_mount, offset + count);
|
||||
|
||||
/*
|
||||
* Walk backwards until we're out of the I/O range. The loop function
|
||||
* repeatedly cycles the ILOCK to allocate one transaction per remapped
|
||||
* extent.
|
||||
*
|
||||
* If we're being called by writeback then the the pages will still
|
||||
* have PageWriteback set, which prevents races with reflink remapping
|
||||
* and truncate. Reflink remapping prevents races with writeback by
|
||||
* taking the iolock and mmaplock before flushing the pages and
|
||||
* remapping, which means there won't be any further writeback or page
|
||||
* cache dirtying until the reflink completes.
|
||||
*
|
||||
* We should never have two threads issuing writeback for the same file
|
||||
* region. There are also have post-eof checks in the writeback
|
||||
* preparation code so that we don't bother writing out pages that are
|
||||
* about to be truncated.
|
||||
*
|
||||
* If we're being called as part of directio write completion, the dio
|
||||
* count is still elevated, which reflink and truncate will wait for.
|
||||
* Reflink remapping takes the iolock and mmaplock and waits for
|
||||
* pending dio to finish, which should prevent any directio until the
|
||||
* remap completes. Multiple concurrent directio writes to the same
|
||||
* region are handled by end_cow processing only occurring for the
|
||||
* threads which succeed; the outcome of multiple overlapping direct
|
||||
* writes is not well defined anyway.
|
||||
*
|
||||
* It's possible that a buffered write and a direct write could collide
|
||||
* here (the buffered write stumbles in after the dio flushes and
|
||||
* invalidates the page cache and immediately queues writeback), but we
|
||||
* have never supported this 100%. If either disk write succeeds the
|
||||
* blocks will be remapped.
|
||||
*/
|
||||
while (end_fsb > offset_fsb && !error)
|
||||
error = xfs_reflink_end_cow_extent(ip, offset_fsb, &end_fsb);
|
||||
|
||||
if (error)
|
||||
trace_xfs_reflink_end_cow_error(ip, error, _RET_IP_);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -64,8 +64,12 @@ xfs_rtany_summary(
|
||||
int log; /* loop counter, log2 of ext. size */
|
||||
xfs_suminfo_t sum; /* summary data */
|
||||
|
||||
/* There are no extents at levels < m_rsum_cache[bbno]. */
|
||||
if (mp->m_rsum_cache && low < mp->m_rsum_cache[bbno])
|
||||
low = mp->m_rsum_cache[bbno];
|
||||
|
||||
/*
|
||||
* Loop over logs of extent sizes. Order is irrelevant.
|
||||
* Loop over logs of extent sizes.
|
||||
*/
|
||||
for (log = low; log <= high; log++) {
|
||||
/*
|
||||
@ -80,13 +84,17 @@ xfs_rtany_summary(
|
||||
*/
|
||||
if (sum) {
|
||||
*stat = 1;
|
||||
return 0;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Found nothing, return failure.
|
||||
*/
|
||||
*stat = 0;
|
||||
out:
|
||||
/* There were no extents at levels < log. */
|
||||
if (mp->m_rsum_cache && log > mp->m_rsum_cache[bbno])
|
||||
mp->m_rsum_cache[bbno] = log;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -853,6 +861,21 @@ out_trans_cancel:
|
||||
return error;
|
||||
}
|
||||
|
||||
static void
|
||||
xfs_alloc_rsum_cache(
|
||||
xfs_mount_t *mp, /* file system mount structure */
|
||||
xfs_extlen_t rbmblocks) /* number of rt bitmap blocks */
|
||||
{
|
||||
/*
|
||||
* The rsum cache is initialized to all zeroes, which is trivially a
|
||||
* lower bound on the minimum level with any free extents. We can
|
||||
* continue without the cache if it couldn't be allocated.
|
||||
*/
|
||||
mp->m_rsum_cache = kmem_zalloc_large(rbmblocks, KM_SLEEP);
|
||||
if (!mp->m_rsum_cache)
|
||||
xfs_warn(mp, "could not allocate realtime summary cache");
|
||||
}
|
||||
|
||||
/*
|
||||
* Visible (exported) functions.
|
||||
*/
|
||||
@ -881,6 +904,7 @@ xfs_growfs_rt(
|
||||
xfs_extlen_t rsumblocks; /* current number of rt summary blks */
|
||||
xfs_sb_t *sbp; /* old superblock */
|
||||
xfs_fsblock_t sumbno; /* summary block number */
|
||||
uint8_t *rsum_cache; /* old summary cache */
|
||||
|
||||
sbp = &mp->m_sb;
|
||||
/*
|
||||
@ -937,6 +961,11 @@ xfs_growfs_rt(
|
||||
error = xfs_growfs_rt_alloc(mp, rsumblocks, nrsumblocks, mp->m_rsumip);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
rsum_cache = mp->m_rsum_cache;
|
||||
if (nrbmblocks != sbp->sb_rbmblocks)
|
||||
xfs_alloc_rsum_cache(mp, nrbmblocks);
|
||||
|
||||
/*
|
||||
* Allocate a new (fake) mount/sb.
|
||||
*/
|
||||
@ -1062,6 +1091,20 @@ error_cancel:
|
||||
*/
|
||||
kmem_free(nmp);
|
||||
|
||||
/*
|
||||
* If we had to allocate a new rsum_cache, we either need to free the
|
||||
* old one (if we succeeded) or free the new one and restore the old one
|
||||
* (if there was an error).
|
||||
*/
|
||||
if (rsum_cache != mp->m_rsum_cache) {
|
||||
if (error) {
|
||||
kmem_free(mp->m_rsum_cache);
|
||||
mp->m_rsum_cache = rsum_cache;
|
||||
} else {
|
||||
kmem_free(rsum_cache);
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -1187,8 +1230,8 @@ xfs_rtmount_init(
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the bitmap and summary inodes into the mount structure
|
||||
* at mount time.
|
||||
* Get the bitmap and summary inodes and the summary cache into the mount
|
||||
* structure at mount time.
|
||||
*/
|
||||
int /* error */
|
||||
xfs_rtmount_inodes(
|
||||
@ -1198,19 +1241,18 @@ xfs_rtmount_inodes(
|
||||
xfs_sb_t *sbp;
|
||||
|
||||
sbp = &mp->m_sb;
|
||||
if (sbp->sb_rbmino == NULLFSINO)
|
||||
return 0;
|
||||
error = xfs_iget(mp, NULL, sbp->sb_rbmino, 0, 0, &mp->m_rbmip);
|
||||
if (error)
|
||||
return error;
|
||||
ASSERT(mp->m_rbmip != NULL);
|
||||
ASSERT(sbp->sb_rsumino != NULLFSINO);
|
||||
|
||||
error = xfs_iget(mp, NULL, sbp->sb_rsumino, 0, 0, &mp->m_rsumip);
|
||||
if (error) {
|
||||
xfs_irele(mp->m_rbmip);
|
||||
return error;
|
||||
}
|
||||
ASSERT(mp->m_rsumip != NULL);
|
||||
xfs_alloc_rsum_cache(mp, sbp->sb_rbmblocks);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1218,6 +1260,7 @@ void
|
||||
xfs_rtunmount_inodes(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
kmem_free(mp->m_rsum_cache);
|
||||
if (mp->m_rbmip)
|
||||
xfs_irele(mp->m_rbmip);
|
||||
if (mp->m_rsumip)
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "xfs_refcount_item.h"
|
||||
#include "xfs_bmap_item.h"
|
||||
#include "xfs_reflink.h"
|
||||
#include "xfs_defer.h"
|
||||
|
||||
#include <linux/namei.h>
|
||||
#include <linux/dax.h>
|
||||
@ -607,7 +608,7 @@ xfs_set_inode_alloc(
|
||||
}
|
||||
|
||||
/* Get the last possible inode in the filesystem */
|
||||
agino = XFS_OFFBNO_TO_AGINO(mp, sbp->sb_agblocks - 1, 0);
|
||||
agino = XFS_AGB_TO_AGINO(mp, sbp->sb_agblocks - 1);
|
||||
ino = XFS_AGINO_TO_INO(mp, agcount - 1, agino);
|
||||
|
||||
/*
|
||||
@ -1149,7 +1150,7 @@ xfs_fs_statfs(
|
||||
statp->f_bfree = fdblocks - mp->m_alloc_set_aside;
|
||||
statp->f_bavail = statp->f_bfree;
|
||||
|
||||
fakeinos = statp->f_bfree << sbp->sb_inopblog;
|
||||
fakeinos = XFS_FSB_TO_INO(mp, statp->f_bfree);
|
||||
statp->f_files = min(icount + fakeinos, (uint64_t)XFS_MAXINUMBER);
|
||||
if (mp->m_maxicount)
|
||||
statp->f_files = min_t(typeof(statp->f_files),
|
||||
@ -2085,11 +2086,6 @@ init_xfs_fs(void)
|
||||
printk(KERN_INFO XFS_VERSION_STRING " with "
|
||||
XFS_BUILD_OPTIONS " enabled\n");
|
||||
|
||||
xfs_extent_free_init_defer_op();
|
||||
xfs_rmap_update_init_defer_op();
|
||||
xfs_refcount_update_init_defer_op();
|
||||
xfs_bmap_update_init_defer_op();
|
||||
|
||||
xfs_dir_startup();
|
||||
|
||||
error = xfs_init_zones();
|
||||
|
@ -192,6 +192,7 @@ xfs_symlink(
|
||||
pathlen = strlen(target_path);
|
||||
if (pathlen >= XFS_SYMLINK_MAXLEN) /* total string too long */
|
||||
return -ENAMETOOLONG;
|
||||
ASSERT(pathlen > 0);
|
||||
|
||||
udqp = gdqp = NULL;
|
||||
prid = xfs_get_initial_prid(dp);
|
||||
@ -378,6 +379,12 @@ out_release_inode:
|
||||
|
||||
/*
|
||||
* Free a symlink that has blocks associated with it.
|
||||
*
|
||||
* Note: zero length symlinks are not allowed to exist. When we set the size to
|
||||
* zero, also change it to a regular file so that it does not get written to
|
||||
* disk as a zero length symlink. The inode is on the unlinked list already, so
|
||||
* userspace cannot find this inode anymore, so this change is not user visible
|
||||
* but allows us to catch corrupt zero-length symlinks in the verifiers.
|
||||
*/
|
||||
STATIC int
|
||||
xfs_inactive_symlink_rmt(
|
||||
@ -412,13 +419,14 @@ xfs_inactive_symlink_rmt(
|
||||
xfs_trans_ijoin(tp, ip, 0);
|
||||
|
||||
/*
|
||||
* Lock the inode, fix the size, and join it to the transaction.
|
||||
* Hold it so in the normal path, we still have it locked for
|
||||
* the second transaction. In the error paths we need it
|
||||
* Lock the inode, fix the size, turn it into a regular file and join it
|
||||
* to the transaction. Hold it so in the normal path, we still have it
|
||||
* locked for the second transaction. In the error paths we need it
|
||||
* held so the cancel won't rele it, see below.
|
||||
*/
|
||||
size = (int)ip->i_d.di_size;
|
||||
ip->i_d.di_size = 0;
|
||||
VFS_I(ip)->i_mode = (VFS_I(ip)->i_mode & ~S_IFMT) | S_IFREG;
|
||||
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
|
||||
/*
|
||||
* Find the block(s) so we can inval and unmap them.
|
||||
@ -494,17 +502,10 @@ xfs_inactive_symlink(
|
||||
return -EIO;
|
||||
|
||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||
|
||||
/*
|
||||
* Zero length symlinks _can_ exist.
|
||||
*/
|
||||
pathlen = (int)ip->i_d.di_size;
|
||||
if (!pathlen) {
|
||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||
return 0;
|
||||
}
|
||||
ASSERT(pathlen);
|
||||
|
||||
if (pathlen < 0 || pathlen > XFS_SYMLINK_MAXLEN) {
|
||||
if (pathlen <= 0 || pathlen > XFS_SYMLINK_MAXLEN) {
|
||||
xfs_alert(mp, "%s: inode (0x%llx) bad symlink length (%d)",
|
||||
__func__, (unsigned long long)ip->i_ino, pathlen);
|
||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||
@ -512,12 +513,12 @@ xfs_inactive_symlink(
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Inline fork state gets removed by xfs_difree() so we have nothing to
|
||||
* do here in that case.
|
||||
*/
|
||||
if (ip->i_df.if_flags & XFS_IFINLINE) {
|
||||
if (ip->i_df.if_bytes > 0)
|
||||
xfs_idata_realloc(ip, -(ip->i_df.if_bytes),
|
||||
XFS_DATA_FORK);
|
||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||
ASSERT(ip->i_df.if_bytes == 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -640,6 +640,16 @@ DEFINE_INODE_EVENT(xfs_inode_set_cowblocks_tag);
|
||||
DEFINE_INODE_EVENT(xfs_inode_clear_cowblocks_tag);
|
||||
DEFINE_INODE_EVENT(xfs_inode_free_cowblocks_invalid);
|
||||
|
||||
/*
|
||||
* ftrace's __print_symbolic requires that all enum values be wrapped in the
|
||||
* TRACE_DEFINE_ENUM macro so that the enum value can be encoded in the ftrace
|
||||
* ring buffer. Somehow this was only worth mentioning in the ftrace sample
|
||||
* code.
|
||||
*/
|
||||
TRACE_DEFINE_ENUM(PE_SIZE_PTE);
|
||||
TRACE_DEFINE_ENUM(PE_SIZE_PMD);
|
||||
TRACE_DEFINE_ENUM(PE_SIZE_PUD);
|
||||
|
||||
TRACE_EVENT(xfs_filemap_fault,
|
||||
TP_PROTO(struct xfs_inode *ip, enum page_entry_size pe_size,
|
||||
bool write_fault),
|
||||
@ -1208,6 +1218,12 @@ DEFINE_EVENT(xfs_readpage_class, name, \
|
||||
DEFINE_READPAGE_EVENT(xfs_vm_readpage);
|
||||
DEFINE_READPAGE_EVENT(xfs_vm_readpages);
|
||||
|
||||
TRACE_DEFINE_ENUM(XFS_IO_HOLE);
|
||||
TRACE_DEFINE_ENUM(XFS_IO_DELALLOC);
|
||||
TRACE_DEFINE_ENUM(XFS_IO_UNWRITTEN);
|
||||
TRACE_DEFINE_ENUM(XFS_IO_OVERWRITE);
|
||||
TRACE_DEFINE_ENUM(XFS_IO_COW);
|
||||
|
||||
DECLARE_EVENT_CLASS(xfs_imap_class,
|
||||
TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count,
|
||||
int type, struct xfs_bmbt_irec *irec),
|
||||
@ -1885,11 +1901,11 @@ TRACE_EVENT(xfs_dir2_leafn_moveents,
|
||||
{ 0, "target" }, \
|
||||
{ 1, "temp" }
|
||||
|
||||
#define XFS_INODE_FORMAT_STR \
|
||||
{ 0, "invalid" }, \
|
||||
{ 1, "local" }, \
|
||||
{ 2, "extent" }, \
|
||||
{ 3, "btree" }
|
||||
TRACE_DEFINE_ENUM(XFS_DINODE_FMT_DEV);
|
||||
TRACE_DEFINE_ENUM(XFS_DINODE_FMT_LOCAL);
|
||||
TRACE_DEFINE_ENUM(XFS_DINODE_FMT_EXTENTS);
|
||||
TRACE_DEFINE_ENUM(XFS_DINODE_FMT_BTREE);
|
||||
TRACE_DEFINE_ENUM(XFS_DINODE_FMT_UUID);
|
||||
|
||||
DECLARE_EVENT_CLASS(xfs_swap_extent_class,
|
||||
TP_PROTO(struct xfs_inode *ip, int which),
|
||||
@ -2178,6 +2194,14 @@ DEFINE_DISCARD_EVENT(xfs_discard_exclude);
|
||||
DEFINE_DISCARD_EVENT(xfs_discard_busy);
|
||||
|
||||
/* btree cursor events */
|
||||
TRACE_DEFINE_ENUM(XFS_BTNUM_BNOi);
|
||||
TRACE_DEFINE_ENUM(XFS_BTNUM_CNTi);
|
||||
TRACE_DEFINE_ENUM(XFS_BTNUM_BMAPi);
|
||||
TRACE_DEFINE_ENUM(XFS_BTNUM_INOi);
|
||||
TRACE_DEFINE_ENUM(XFS_BTNUM_FINOi);
|
||||
TRACE_DEFINE_ENUM(XFS_BTNUM_RMAPi);
|
||||
TRACE_DEFINE_ENUM(XFS_BTNUM_REFCi);
|
||||
|
||||
DECLARE_EVENT_CLASS(xfs_btree_cur_class,
|
||||
TP_PROTO(struct xfs_btree_cur *cur, int level, struct xfs_buf *bp),
|
||||
TP_ARGS(cur, level, bp),
|
||||
@ -2197,9 +2221,9 @@ DECLARE_EVENT_CLASS(xfs_btree_cur_class,
|
||||
__entry->ptr = cur->bc_ptrs[level];
|
||||
__entry->daddr = bp ? bp->b_bn : -1;
|
||||
),
|
||||
TP_printk("dev %d:%d btnum %d level %d/%d ptr %d daddr 0x%llx",
|
||||
TP_printk("dev %d:%d btree %s level %d/%d ptr %d daddr 0x%llx",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
__entry->btnum,
|
||||
__print_symbolic(__entry->btnum, XFS_BTNUM_STRINGS),
|
||||
__entry->level,
|
||||
__entry->nlevels,
|
||||
__entry->ptr,
|
||||
@ -2276,7 +2300,7 @@ DECLARE_EVENT_CLASS(xfs_defer_pending_class,
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->dev = mp ? mp->m_super->s_dev : 0;
|
||||
__entry->type = dfp->dfp_type->type;
|
||||
__entry->type = dfp->dfp_type;
|
||||
__entry->intent = dfp->dfp_intent;
|
||||
__entry->committed = dfp->dfp_done != NULL;
|
||||
__entry->nr = dfp->dfp_count;
|
||||
@ -2405,7 +2429,7 @@ DEFINE_BMAP_FREE_DEFERRED_EVENT(xfs_agfl_free_deferred);
|
||||
DECLARE_EVENT_CLASS(xfs_rmap_class,
|
||||
TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno,
|
||||
xfs_agblock_t agbno, xfs_extlen_t len, bool unwritten,
|
||||
struct xfs_owner_info *oinfo),
|
||||
const struct xfs_owner_info *oinfo),
|
||||
TP_ARGS(mp, agno, agbno, len, unwritten, oinfo),
|
||||
TP_STRUCT__entry(
|
||||
__field(dev_t, dev)
|
||||
@ -2440,7 +2464,7 @@ DECLARE_EVENT_CLASS(xfs_rmap_class,
|
||||
DEFINE_EVENT(xfs_rmap_class, name, \
|
||||
TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \
|
||||
xfs_agblock_t agbno, xfs_extlen_t len, bool unwritten, \
|
||||
struct xfs_owner_info *oinfo), \
|
||||
const struct xfs_owner_info *oinfo), \
|
||||
TP_ARGS(mp, agno, agbno, len, unwritten, oinfo))
|
||||
|
||||
/* simple AG-based error/%ip tracepoint class */
|
||||
@ -2610,10 +2634,9 @@ DEFINE_AG_ERROR_EVENT(xfs_ag_resv_init_error);
|
||||
#define DEFINE_AG_EXTENT_EVENT(name) DEFINE_DISCARD_EVENT(name)
|
||||
|
||||
/* ag btree lookup tracepoint class */
|
||||
#define XFS_AG_BTREE_CMP_FORMAT_STR \
|
||||
{ XFS_LOOKUP_EQ, "eq" }, \
|
||||
{ XFS_LOOKUP_LE, "le" }, \
|
||||
{ XFS_LOOKUP_GE, "ge" }
|
||||
TRACE_DEFINE_ENUM(XFS_LOOKUP_EQi);
|
||||
TRACE_DEFINE_ENUM(XFS_LOOKUP_LEi);
|
||||
TRACE_DEFINE_ENUM(XFS_LOOKUP_GEi);
|
||||
DECLARE_EVENT_CLASS(xfs_ag_btree_lookup_class,
|
||||
TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno,
|
||||
xfs_agblock_t agbno, xfs_lookup_t dir),
|
||||
|
@ -223,13 +223,13 @@ void xfs_trans_dirty_buf(struct xfs_trans *, struct xfs_buf *);
|
||||
bool xfs_trans_buf_is_dirty(struct xfs_buf *bp);
|
||||
void xfs_trans_log_inode(xfs_trans_t *, struct xfs_inode *, uint);
|
||||
|
||||
void xfs_extent_free_init_defer_op(void);
|
||||
struct xfs_efd_log_item *xfs_trans_get_efd(struct xfs_trans *,
|
||||
struct xfs_efi_log_item *,
|
||||
uint);
|
||||
int xfs_trans_free_extent(struct xfs_trans *,
|
||||
struct xfs_efd_log_item *, xfs_fsblock_t,
|
||||
xfs_extlen_t, struct xfs_owner_info *,
|
||||
xfs_extlen_t,
|
||||
const struct xfs_owner_info *,
|
||||
bool);
|
||||
int xfs_trans_commit(struct xfs_trans *);
|
||||
int xfs_trans_roll(struct xfs_trans **);
|
||||
@ -248,7 +248,6 @@ extern kmem_zone_t *xfs_trans_zone;
|
||||
/* rmap updates */
|
||||
enum xfs_rmap_intent_type;
|
||||
|
||||
void xfs_rmap_update_init_defer_op(void);
|
||||
struct xfs_rud_log_item *xfs_trans_get_rud(struct xfs_trans *tp,
|
||||
struct xfs_rui_log_item *ruip);
|
||||
int xfs_trans_log_finish_rmap_update(struct xfs_trans *tp,
|
||||
@ -260,7 +259,6 @@ int xfs_trans_log_finish_rmap_update(struct xfs_trans *tp,
|
||||
/* refcount updates */
|
||||
enum xfs_refcount_intent_type;
|
||||
|
||||
void xfs_refcount_update_init_defer_op(void);
|
||||
struct xfs_cud_log_item *xfs_trans_get_cud(struct xfs_trans *tp,
|
||||
struct xfs_cui_log_item *cuip);
|
||||
int xfs_trans_log_finish_refcount_update(struct xfs_trans *tp,
|
||||
@ -272,7 +270,6 @@ int xfs_trans_log_finish_refcount_update(struct xfs_trans *tp,
|
||||
/* mapping updates */
|
||||
enum xfs_bmap_intent_type;
|
||||
|
||||
void xfs_bmap_update_init_defer_op(void);
|
||||
struct xfs_bud_log_item *xfs_trans_get_bud(struct xfs_trans *tp,
|
||||
struct xfs_bui_log_item *buip);
|
||||
int xfs_trans_log_finish_bmap_update(struct xfs_trans *tp,
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "xfs_alloc.h"
|
||||
#include "xfs_bmap.h"
|
||||
#include "xfs_inode.h"
|
||||
#include "xfs_defer.h"
|
||||
|
||||
/*
|
||||
* This routine is called to allocate a "bmap update done"
|
||||
@ -220,8 +221,7 @@ xfs_bmap_update_cancel_item(
|
||||
kmem_free(bmap);
|
||||
}
|
||||
|
||||
static const struct xfs_defer_op_type xfs_bmap_update_defer_type = {
|
||||
.type = XFS_DEFER_OPS_TYPE_BMAP,
|
||||
const struct xfs_defer_op_type xfs_bmap_update_defer_type = {
|
||||
.max_items = XFS_BUI_MAX_FAST_EXTENTS,
|
||||
.diff_items = xfs_bmap_update_diff_items,
|
||||
.create_intent = xfs_bmap_update_create_intent,
|
||||
@ -231,10 +231,3 @@ static const struct xfs_defer_op_type xfs_bmap_update_defer_type = {
|
||||
.finish_item = xfs_bmap_update_finish_item,
|
||||
.cancel_item = xfs_bmap_update_cancel_item,
|
||||
};
|
||||
|
||||
/* Register the deferred op type. */
|
||||
void
|
||||
xfs_bmap_update_init_defer_op(void)
|
||||
{
|
||||
xfs_defer_init_op_type(&xfs_bmap_update_defer_type);
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "xfs_alloc.h"
|
||||
#include "xfs_bmap.h"
|
||||
#include "xfs_trace.h"
|
||||
#include "xfs_defer.h"
|
||||
|
||||
/*
|
||||
* This routine is called to allocate an "extent free done"
|
||||
@ -52,19 +53,20 @@ xfs_trans_get_efd(struct xfs_trans *tp,
|
||||
*/
|
||||
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,
|
||||
struct xfs_owner_info *oinfo,
|
||||
bool skip_discard)
|
||||
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_mount *mp = tp->t_mountp;
|
||||
uint next_extent;
|
||||
xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, start_block);
|
||||
xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp, start_block);
|
||||
struct xfs_extent *extp;
|
||||
int error;
|
||||
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_agblock_t agbno = XFS_FSB_TO_AGBNO(mp,
|
||||
start_block);
|
||||
int error;
|
||||
|
||||
trace_xfs_bmap_free_deferred(tp->t_mountp, agno, 0, agbno, ext_len);
|
||||
|
||||
@ -206,8 +208,7 @@ xfs_extent_free_cancel_item(
|
||||
kmem_free(free);
|
||||
}
|
||||
|
||||
static const struct xfs_defer_op_type xfs_extent_free_defer_type = {
|
||||
.type = XFS_DEFER_OPS_TYPE_FREE,
|
||||
const struct xfs_defer_op_type xfs_extent_free_defer_type = {
|
||||
.max_items = XFS_EFI_MAX_FAST_EXTENTS,
|
||||
.diff_items = xfs_extent_free_diff_items,
|
||||
.create_intent = xfs_extent_free_create_intent,
|
||||
@ -274,8 +275,7 @@ xfs_agfl_free_finish_item(
|
||||
|
||||
|
||||
/* sub-type with special handling for AGFL deferred frees */
|
||||
static const struct xfs_defer_op_type xfs_agfl_free_defer_type = {
|
||||
.type = XFS_DEFER_OPS_TYPE_AGFL_FREE,
|
||||
const struct xfs_defer_op_type xfs_agfl_free_defer_type = {
|
||||
.max_items = XFS_EFI_MAX_FAST_EXTENTS,
|
||||
.diff_items = xfs_extent_free_diff_items,
|
||||
.create_intent = xfs_extent_free_create_intent,
|
||||
@ -285,11 +285,3 @@ static const struct xfs_defer_op_type xfs_agfl_free_defer_type = {
|
||||
.finish_item = xfs_agfl_free_finish_item,
|
||||
.cancel_item = xfs_extent_free_cancel_item,
|
||||
};
|
||||
|
||||
/* Register the deferred op type. */
|
||||
void
|
||||
xfs_extent_free_init_defer_op(void)
|
||||
{
|
||||
xfs_defer_init_op_type(&xfs_extent_free_defer_type);
|
||||
xfs_defer_init_op_type(&xfs_agfl_free_defer_type);
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "xfs_refcount_item.h"
|
||||
#include "xfs_alloc.h"
|
||||
#include "xfs_refcount.h"
|
||||
#include "xfs_defer.h"
|
||||
|
||||
/*
|
||||
* This routine is called to allocate a "refcount update done"
|
||||
@ -227,8 +228,7 @@ xfs_refcount_update_cancel_item(
|
||||
kmem_free(refc);
|
||||
}
|
||||
|
||||
static const struct xfs_defer_op_type xfs_refcount_update_defer_type = {
|
||||
.type = XFS_DEFER_OPS_TYPE_REFCOUNT,
|
||||
const struct xfs_defer_op_type xfs_refcount_update_defer_type = {
|
||||
.max_items = XFS_CUI_MAX_FAST_EXTENTS,
|
||||
.diff_items = xfs_refcount_update_diff_items,
|
||||
.create_intent = xfs_refcount_update_create_intent,
|
||||
@ -239,10 +239,3 @@ static const struct xfs_defer_op_type xfs_refcount_update_defer_type = {
|
||||
.finish_cleanup = xfs_refcount_update_finish_cleanup,
|
||||
.cancel_item = xfs_refcount_update_cancel_item,
|
||||
};
|
||||
|
||||
/* Register the deferred op type. */
|
||||
void
|
||||
xfs_refcount_update_init_defer_op(void)
|
||||
{
|
||||
xfs_defer_init_op_type(&xfs_refcount_update_defer_type);
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "xfs_rmap_item.h"
|
||||
#include "xfs_alloc.h"
|
||||
#include "xfs_rmap.h"
|
||||
#include "xfs_defer.h"
|
||||
|
||||
/* Set the map extent flags for this reverse mapping. */
|
||||
static void
|
||||
@ -244,8 +245,7 @@ xfs_rmap_update_cancel_item(
|
||||
kmem_free(rmap);
|
||||
}
|
||||
|
||||
static const struct xfs_defer_op_type xfs_rmap_update_defer_type = {
|
||||
.type = XFS_DEFER_OPS_TYPE_RMAP,
|
||||
const struct xfs_defer_op_type xfs_rmap_update_defer_type = {
|
||||
.max_items = XFS_RUI_MAX_FAST_EXTENTS,
|
||||
.diff_items = xfs_rmap_update_diff_items,
|
||||
.create_intent = xfs_rmap_update_create_intent,
|
||||
@ -256,10 +256,3 @@ static const struct xfs_defer_op_type xfs_rmap_update_defer_type = {
|
||||
.finish_cleanup = xfs_rmap_update_finish_cleanup,
|
||||
.cancel_item = xfs_rmap_update_cancel_item,
|
||||
};
|
||||
|
||||
/* Register the deferred op type. */
|
||||
void
|
||||
xfs_rmap_update_init_defer_op(void)
|
||||
{
|
||||
xfs_defer_init_op_type(&xfs_rmap_update_defer_type);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user