[Ocfs2-tools-devel] [PATCH] Compress dirs option in fsck

Sunil Mushran sunil.mushran at oracle.com
Wed Aug 19 19:27:44 PDT 2009


Thanks Goldwyn.

Please can you add a test for this in ocfs2-test. Create a dir with a  
sizable number of files. Touch should be enough. Delete half the  
number of files randomly. Run fsck with -D. Run again without -D.  
Something like that. You can look at the existing tests for the tools.

If you want the test to be more thorough, you could make use of the  
dirblock command in debugfs.ocfs2.

Thanks

On Aug 19, 2009, at 3:14 PM, Goldwyn Rodrigues <rgoldwyn at gmail.com>  
wrote:

> This patch adds the option to compress directories (-D) in fsck.
> The option compresses the directory entries and consolidates a hole at
> the end of the directory block. This consolidated hole increases the
> chance of ocfs2_prepare_dir_for_insert (kmp) to find a hole using
> ocfs2_find_dir_space_* functions while inserting a new directory entry
> in the directory.
>
> Perhaps #define OCFS2_DIR_REC_LEN needs a better place.
>
> Signed-off-by: Goldwyn Rodrigues <rgoldwyn at suse.de>
> ---
> diff --git a/fsck.ocfs2/fsck.c b/fsck.ocfs2/fsck.c
> index 74c18ac..2f31257 100644
> --- a/fsck.ocfs2/fsck.c
> +++ b/fsck.ocfs2/fsck.c
> @@ -650,7 +650,7 @@ int main(int argc, char **argv)
>    setlinebuf(stderr);
>    setlinebuf(stdout);
>
> -    while((c = getopt(argc, argv, "b:B:fFGnuvVyr:")) != EOF) {
> +    while((c = getopt(argc, argv, "b:B:DfFGnuvVyr:")) != EOF) {
>        switch (c) {
>            case 'b':
>                blkno = read_number(optarg);
> @@ -675,6 +675,9 @@ int main(int argc, char **argv)
>                    goto out;
>                }
>                break;
> +            case 'D':
> +                ost->ost_rehash_dirs = 1;
> +                break;
>
>            case 'F':
>                ost->ost_skip_o2cb = 1;
> diff --git a/fsck.ocfs2/include/fsck.h b/fsck.ocfs2/include/fsck.h
> index 240286c..93c4b21 100644
> --- a/fsck.ocfs2/include/fsck.h
> +++ b/fsck.ocfs2/include/fsck.h
> @@ -73,7 +73,8 @@ typedef struct _o2fsck_state {
>              ost_stale_mounts:1, /* set when reading publish blocks
>                           * that still indicated mounted */
>            ost_fix_fs_gen:1,
> -            ost_has_journal_dirty:1;
> +            ost_has_journal_dirty:1,
> +            ost_rehash_dirs:1;
>    errcode_t ost_err;
> } o2fsck_state;
>
> diff --git a/fsck.ocfs2/pass2.c b/fsck.ocfs2/pass2.c
> index 810bf10..2d9d074 100644
> --- a/fsck.ocfs2/pass2.c
> +++ b/fsck.ocfs2/pass2.c
> @@ -668,6 +668,7 @@ static unsigned
> pass2_dir_block_iterate(o2fsck_dirblock_entry *dbe,
>    struct dirblock_data *dd = priv_data;
>    struct ocfs2_dir_entry *dirent, *prev = NULL;
>    unsigned int offset = 0, ret_flags = 0, end = dd->fs->fs_blocksize;
> +    unsigned int write_off, saved_reclen;
>    struct ocfs2_dinode *di = (struct ocfs2_dinode *)dd->inoblock_buf;
>    errcode_t ret = 0;
>
> @@ -723,6 +724,8 @@ static unsigned
> pass2_dir_block_iterate(o2fsck_dirblock_entry *dbe,
>            end = ocfs2_dir_trailer_blk_off(dd->fs);
>    }
>
> +    write_off = offset;
> +
>    while (offset < end) {
>        dirent = (struct ocfs2_dir_entry *)(dd->dirblock_buf + offset);
>
> @@ -804,8 +807,31 @@ static unsigned
> pass2_dir_block_iterate(o2fsck_dirblock_entry *dbe,
>                dirent->name, (uint64_t)dirent->inode);
>        o2fsck_icount_delta(dd->ost->ost_icount_refs, dirent->inode,  
> 1);
> next:
> -        offset += dirent->rec_len;
> +        saved_reclen=dirent->rec_len;
> +        if ((dd->ost->ost_rehash_dirs) && dirent->inode) {
> +            dirent->rec_len = OCFS2_DIR_REC_LEN(dirent->name_len);
> +            if (write_off < offset) {
> +                /* memcpy works good even though
> +                it is the same buffer*/
> +                verbosef("ino: %llu woff: %u off: %u\n",
> +                    dirent->inode, write_off, offset);
> +                memcpy(dd->dirblock_buf + write_off,
> +                        dd->dirblock_buf + offset,
> +                        dirent->rec_len);
> +                dirent = dd->dirblock_buf + write_off;
> +            }
> +            write_off += dirent->rec_len;
> +            ret_flags |= OCFS2_DIRENT_CHANGED;
> +        }
>        prev = dirent;
> +        offset += saved_reclen;
> +    }
> +
> +    /* Zero the rest of the block */
> +    if (dd->ost->ost_rehash_dirs) {
> +        memset(dd->dirblock_buf + write_off, '\0', end - write_off);
> +        ret_flags |= OCFS2_DIRENT_CHANGED;
> +        dirent->rec_len = dirent->rec_len + end - write_off;
>    }
>
>    if (ocfs2_dir_has_trailer(dd->fs, di))
> diff --git a/libocfs2/dir_iterate.h b/libocfs2/dir_iterate.h
> index f281af2..2d9587b 100644
> --- a/libocfs2/dir_iterate.h
> +++ b/libocfs2/dir_iterate.h
> @@ -49,4 +49,11 @@ extern int ocfs2_process_dir_block(ocfs2_filesys  
> *fs,
>                   uint16_t    ext_flags,
>                   void        *priv_data);
>
> +#define OCFS2_DIR_PAD                   4
> +#define OCFS2_DIR_ROUND                 (OCFS2_DIR_PAD - 1)
> +#define OCFS2_DIR_MEMBER_LEN            offsetof(struct  
> ocfs2_dir_entry, name)
> +#define OCFS2_DIR_REC_LEN(name_len)     (((name_len) +  
> OCFS2_DIR_MEMBER_LEN + \
> +                                          OCFS2_DIR_ROUND) & \
> +                                         ~OCFS2_DIR_ROUND)
> +
> #endif  /* _DIR_ITERATE_H */
>
> _______________________________________________
> Ocfs2-tools-devel mailing list
> Ocfs2-tools-devel at oss.oracle.com
> http://oss.oracle.com/mailman/listinfo/ocfs2-tools-devel



More information about the Ocfs2-tools-devel mailing list