[Ocfs2-tools-devel] [PATCH 2/6] Fix holes in directories
Sunil Mushran
sunil.mushran at oracle.com
Tue Oct 25 13:37:15 PDT 2011
You comment says that you are setting it for dirs only. Which is fine. But
you appear to be enabling it for refcount too.
Should I just disable it for refcount? We can handle that later.
On 08/22/2011 03:36 PM, Goldwyn Rodrigues wrote:
> Calculate the expected offset as the extent tree is traversed and
> compare with the offset in the extent record. If the file is not
> supposed to have holes, such as directories, prompt and correct it.
>
> Currently no_holes is set for directories only.
>
> I agree this is an ugly hack which bounces variables to the extent
> traversal functions, but it gets the job done.
>
> Signed-off-by: Goldwyn Rodrigues<rgoldwyn at suse.de>
> ---
> fsck.ocfs2/extent.c | 57 ++++++++++++++++++++++++++++++++----
> fsck.ocfs2/fsck.ocfs2.checks.8.in | 6 ++++
> fsck.ocfs2/include/extent.h | 7 ++++-
> fsck.ocfs2/pass1.c | 2 +-
> fsck.ocfs2/refcount.c | 16 ++++++----
> fsck.ocfs2/xattr.c | 5 ++-
> 6 files changed, 76 insertions(+), 17 deletions(-)
>
> diff --git a/fsck.ocfs2/extent.c b/fsck.ocfs2/extent.c
> index 0075319..2bd9738 100644
> --- a/fsck.ocfs2/extent.c
> +++ b/fsck.ocfs2/extent.c
> @@ -49,6 +49,7 @@ static const char *whoami = "extent.c";
>
> static errcode_t check_eb(o2fsck_state *ost, struct extent_info *ei,
> uint64_t owner, uint64_t blkno,
> + uint32_t offset, int no_holes,
> int *is_valid)
> {
> int changed = 0;
> @@ -113,10 +114,9 @@ static errcode_t check_eb(o2fsck_state *ost,
> struct extent_info *ei,
>
> /* XXX worry about suballoc node/bit */
> /* XXX worry about next_leaf_blk */
> -
> check_el(ost, ei, owner,&eb->h_list,
> ocfs2_extent_recs_per_eb(ost->ost_fs->fs_blocksize),
> - &changed);
> + offset, no_holes,&changed);
>
> if (changed) {
> ret = ocfs2_write_extent_block(ost->ost_fs, blkno, buf);
> @@ -139,7 +139,9 @@ out:
> static errcode_t check_er(o2fsck_state *ost, struct extent_info *ei,
> uint64_t owner,
> struct ocfs2_extent_list *el,
> - struct ocfs2_extent_rec *er, int *changed)
> + struct ocfs2_extent_rec *er,
> + uint32_t offset, int no_holes,
> + int *changed)
> {
> errcode_t ret = 0;
> uint32_t clusters;
> @@ -151,6 +153,15 @@ static errcode_t check_er(o2fsck_state *ost,
> struct extent_info *ei,
> if (ocfs2_block_out_of_range(ost->ost_fs, er->e_blkno))
> goto out;
>
> + if (no_holes&& (er->e_cpos != offset)&&
> + prompt(ost, PY, PR_NO_HOLES,
> + "Extent record of owner %"PRIu64" is incorrectly "
> + "set to %d instead of %d. Fix?", owner, er->e_cpos,
> + offset)) {
> + er->e_cpos = offset;
> + *changed = 1;
> + }
> +
> if (el->l_tree_depth) {
> int is_valid = 0;
> /* we only expect a given depth when we descend to extent blocks
> @@ -158,7 +169,8 @@ static errcode_t check_er(o2fsck_state *ost,
> struct extent_info *ei,
> * is checked */
> ei->ei_expect_depth = 1;
> ei->ei_expected_depth = el->l_tree_depth - 1;
> - check_eb(ost, ei, owner, er->e_blkno,&is_valid);
> + check_eb(ost, ei, owner, er->e_blkno, offset, no_holes,
> + &is_valid);
> if (!is_valid&&
> prompt(ost, PY, PR_EXTENT_EB_INVALID,
> "The extent record for cluster offset "
> @@ -175,7 +187,8 @@ static errcode_t check_er(o2fsck_state *ost,
> struct extent_info *ei,
> }
>
> if (ei->chk_rec_func)
> - ret = ei->chk_rec_func(ost, owner, el, er, changed, ei->para);
> + ret = ei->chk_rec_func(ost, owner, el, er, changed, offset,
> + no_holes, ei->para);
> /* XXX offer to remove leaf records with er_clusters set to 0? */
>
> /* XXX check that the blocks that are referenced aren't already
> @@ -188,7 +201,8 @@ out:
> errcode_t check_el(o2fsck_state *ost, struct extent_info *ei,
> uint64_t owner,
> struct ocfs2_extent_list *el,
> - uint16_t max_recs, int *changed)
> + uint16_t max_recs, uint32_t offset, int no_holes,
> + int *changed)
> {
> int trust_next_free = 1;
> struct ocfs2_extent_rec *er;
> @@ -259,7 +273,12 @@ errcode_t check_el(o2fsck_state *ost, struct
> extent_info *ei,
> /* returns immediately if blkno is out of range.
> * descends into eb. checks that data er doesn't
> * reference past the volume or anything crazy. */
> - check_er(ost, ei, owner, el, er, changed);
> + check_er(ost, ei, owner, el, er, offset, no_holes, changed);
> +
> + if (el->l_tree_depth)
> + offset += er->e_int_clusters;
> + else
> + offset += er->e_leaf_clusters;
>
> /* offer to remove records that point to nowhere */
> if (ocfs2_block_out_of_range(ost->ost_fs, er->e_blkno)&&
> @@ -313,6 +332,8 @@ errcode_t o2fsck_check_extent_rec(o2fsck_state *ost,
> struct ocfs2_extent_list *el,
> struct ocfs2_extent_rec *er,
> int *changed,
> + uint32_t offset,
> + int no_holes,
> void *para)
> {
> uint32_t clusters, last_cluster;
> @@ -417,8 +438,30 @@ errcode_t o2fsck_check_extents(o2fsck_state *ost,
> ei.para = di;
> ret = check_el(ost,&ei, di->i_blkno,&di->id2.i_list,
> ocfs2_extent_recs_per_inode(ost->ost_fs->fs_blocksize),
> + 0, S_ISDIR(di->i_mode),
> &changed);
no_holes being set for dirblocks.
> + if (S_ISDIR(di->i_mode)&& !(di->i_dyn_features
> + & OCFS2_INLINE_DATA_FL)) {
> + struct ocfs2_extent_list *el =&(di->id2.i_list);
> + struct ocfs2_extent_rec *er =
> + &(el->l_recs[el->l_next_free_rec - 1]);
> + uint64_t expected;
> + if (el->l_tree_depth)
> + expected = er->e_cpos + er->e_int_clusters;
> + else
> + expected = er->e_cpos + er->e_leaf_clusters;
> + expected = ocfs2_clusters_to_bytes(ost->ost_fs, expected);
> + if ((di->i_size> expected)&& prompt(ost, PY,
> + PR_INODE_SIZE, "Inode %"PRIu64" has a size of "
> + "%"PRIu64" but has %"PRIu64" bytes of actual "
> + "data. Correct the file size?",
> + (uint64_t)di->i_blkno,
> + (uint64_t)di->i_size, expected)) {
> + di->i_size = expected;
> + changed = 1;
> + }
> + }
> if (changed)
> o2fsck_write_inode(ost, di->i_blkno, di);
>
> diff --git a/fsck.ocfs2/fsck.ocfs2.checks.8.in
> b/fsck.ocfs2/fsck.ocfs2.checks.8.in
> index e706ea5..d887a16 100644
> --- a/fsck.ocfs2/fsck.ocfs2.checks.8.in
> +++ b/fsck.ocfs2/fsck.ocfs2.checks.8.in
> @@ -1137,6 +1137,12 @@ index entry will cause lookups on this name to fail.
>
> Answering yes will rebuild the directory index, restoring the missing entry.
>
> +.SS "NO_HOLES"
> +A metadata structure enocuntered a hole where it should not. Examples of such
> +structures are directories, refcount trees, dx_trees etc.
> +
> +Answering yes will remove the hole.
> +
> .SH "SEE ALSO"
> .BR fsck.ocfs2(8)
>
> diff --git a/fsck.ocfs2/include/extent.h b/fsck.ocfs2/include/extent.h
> index fe9b021..badd593 100644
> --- a/fsck.ocfs2/include/extent.h
> +++ b/fsck.ocfs2/include/extent.h
> @@ -27,6 +27,8 @@ typedef errcode_t (check_leaf_er_func)(o2fsck_state *ost,
> struct ocfs2_extent_list *el,
> struct ocfs2_extent_rec *er,
> int *changed,
> + uint32_t offset,
> + int no_holes,
> void *para);
> typedef errcode_t (mark_leaf_er_alloc_func)(o2fsck_state *ost,
> struct ocfs2_extent_rec *er,
> @@ -50,12 +52,15 @@ errcode_t o2fsck_check_extents(o2fsck_state *ost,
> errcode_t check_el(o2fsck_state *ost, struct extent_info *ei,
> uint64_t owner,
> struct ocfs2_extent_list *el,
> - uint16_t max_recs, int *changed);
> + uint16_t max_recs, uint32_t offset, int no_holes,
> + int *changed);
> errcode_t o2fsck_check_extent_rec(o2fsck_state *ost,
> uint64_t owner,
> struct ocfs2_extent_list *el,
> struct ocfs2_extent_rec *er,
> int *changed,
> + uint32_t offset,
> + int no_holes,
> void *para);
>
> errcode_t o2fsck_mark_tree_clusters_allocated(o2fsck_state *ost,
> diff --git a/fsck.ocfs2/pass1.c b/fsck.ocfs2/pass1.c
> index 22dafdf..398fbf3 100644
> --- a/fsck.ocfs2/pass1.c
> +++ b/fsck.ocfs2/pass1.c
> @@ -815,7 +815,7 @@ static errcode_t o2fsck_check_dx_dir(o2fsck_state
> *ost, struct ocfs2_dinode *di)
>
> ret = check_el(ost,&ei, di->i_blkno,&dx_root->dr_list,
> ocfs2_extent_recs_per_dx_root(fs->fs_blocksize),
> - &changed);
> + 0, 0,&changed);
no_holes not being set dx_dirs.
> if (ret)
> goto out;
>
> diff --git a/fsck.ocfs2/refcount.c b/fsck.ocfs2/refcount.c
> index 127c291..5a8ff73 100644
> --- a/fsck.ocfs2/refcount.c
> +++ b/fsck.ocfs2/refcount.c
> @@ -64,7 +64,8 @@ struct refcount_tree {
> };
>
> static errcode_t check_rb(o2fsck_state *ost, uint64_t blkno,
> - uint64_t root_blkno, uint64_t *c_end, int *is_valid);
> + uint64_t root_blkno, uint64_t *c_end,
> + uint32_t offset, int no_holes, int *is_valid);
>
> static void check_rl(o2fsck_state *ost,
> uint64_t rb_blkno, uint64_t root_blkno,
> @@ -167,7 +168,8 @@ static errcode_t
> refcount_check_leaf_extent_rec(o2fsck_state *ost,
> uint64_t owner,
> struct ocfs2_extent_list *el,
> struct ocfs2_extent_rec *er,
> - int *changed,
> + int *changed, uint32_t offset,
> + int no_holes,
> void *para)
> {
> errcode_t ret;
> @@ -175,7 +177,8 @@ static errcode_t
> refcount_check_leaf_extent_rec(o2fsck_state *ost,
> struct check_refcount_rec *check = para;
>
> ret = check_rb(ost, er->e_blkno,
> - check->root_blkno,&check->c_end,&is_valid);
> + check->root_blkno,&check->c_end, offset, no_holes,
> + &is_valid);
>
> if (!is_valid&&
> prompt(ost, PY, PR_REFCOUNT_BLOCK_INVALID,
> @@ -190,7 +193,8 @@ static errcode_t
> refcount_check_leaf_extent_rec(o2fsck_state *ost,
> }
>
> static errcode_t check_rb(o2fsck_state *ost, uint64_t blkno,
> - uint64_t root_blkno, uint64_t *c_end, int *is_valid)
> + uint64_t root_blkno, uint64_t *c_end,
> + uint32_t offset, int no_holes, int *is_valid)
> {
> int changed = 0;
> char *buf = NULL;
> @@ -279,7 +283,7 @@ static errcode_t check_rb(o2fsck_state *ost, uint64_t blkno,
> * here.
> */
> check_el(ost,&ei, rb->rf_blkno,&rb->rf_list,
> - max_recs,&changed);
> + max_recs, offset, no_holes,&changed);
> *c_end = check.c_end;
>
> if (ei.ei_clusters != rb->rf_clusters&&
> @@ -387,7 +391,7 @@ errcode_t o2fsck_check_refcount_tree(o2fsck_state *ost,
> return ret;
>
> ret = check_rb(ost, di->i_refcount_loc, di->i_refcount_loc,
> - &c_end,&is_valid);
> + &c_end, 0, 1,&is_valid);
no_holes being set refcount.
>
> /*
> * Add refcount tree to the rb-tree.
> diff --git a/fsck.ocfs2/xattr.c b/fsck.ocfs2/xattr.c
> index 46c54d4..4a2efe2 100644
> --- a/fsck.ocfs2/xattr.c
> +++ b/fsck.ocfs2/xattr.c
> @@ -395,7 +395,8 @@ static errcode_t check_xattr_value(o2fsck_state *ost,
> ((void *)xh + offset);
> struct ocfs2_extent_list *el =&xv->xr_list;
> owner = start + offset / ost->ost_fs->fs_blocksize;
> - ret = check_el(ost,&ei, owner, el, 1,&change);
> + ret = check_el(ost,&ei, owner, el, 1,
> + 0, 0,&change);
not being set of xattrs.
> if (ret)
> return ret;
> if (change)
> @@ -612,7 +613,7 @@ static errcode_t
> o2fsck_check_xattr_index_block(o2fsck_state *ost,
> ei.mark_rec_alloc_func = o2fsck_mark_tree_clusters_allocated;
> ei.para = di;
> ret = check_el(ost,&ei, xb->xb_blkno, el,
> - ocfs2_xattr_recs_per_xb(ost->ost_fs->fs_blocksize),
> + ocfs2_xattr_recs_per_xb(ost->ost_fs->fs_blocksize), 0, 0,
> changed);
> if (ret)
> return ret;
More information about the Ocfs2-tools-devel
mailing list