[Ocfs2-tools-devel] [PATCH 2/6] Fix holes in directories

Goldwyn Rodrigues rgoldwyn at gmail.com
Tue Nov 8 19:57:03 PST 2011


Sorry for the late reply. I am on a long vacation until end November.

On Wed, Oct 26, 2011 at 2:07 AM, Sunil Mushran <sunil.mushran at oracle.com> wrote:
> 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.

Yes. I did not want to use it for refcount for now.

>
> 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;
>
>



-- 
Goldwyn



More information about the Ocfs2-tools-devel mailing list