[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