Re: [PATCH] Add basic BIGALLOC support for cluster-based allocation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sat, Feb 26, 2011 at 4:50 AM, Theodore Ts'o <tytso@xxxxxxx> wrote:
> This adds the superblock fields needed so that dumpe2fs works and the
> code points and renames the superblock fields from describing
> fragments to clusters.
>
> Signed-off-by: "Theodore Ts'o" <tytso@xxxxxxx>
> ---
>  debugfs/set_fields.c        |    4 ++--
>  e2fsck/super.c              |   23 ++++++++---------------
>  lib/e2p/feature.c           |    2 ++
>  lib/e2p/ls.c                |   14 ++++++++++++--
>  lib/ext2fs/ext2_fs.h        |   25 +++++++++++--------------
>  lib/ext2fs/ext2fs.h         |    4 ++--
>  lib/ext2fs/initialize.c     |   11 ++++-------
>  lib/ext2fs/openfs.c         |    2 +-
>  lib/ext2fs/swapfs.c         |    4 ++--
>  lib/ext2fs/tst_super_size.c |    4 ++--
>  misc/mke2fs.c               |   24 ++++++++++++++++--------
>  11 files changed, 62 insertions(+), 55 deletions(-)
>
> diff --git a/debugfs/set_fields.c b/debugfs/set_fields.c
> index 3b40117..9d7099b 100644
> --- a/debugfs/set_fields.c
> +++ b/debugfs/set_fields.c
> @@ -74,9 +74,9 @@ static struct field_set_info super_fields[] = {
>        { "free_inodes_count", &set_sb.s_free_inodes_count, 4, parse_uint },
>        { "first_data_block", &set_sb.s_first_data_block, 4, parse_uint },
>        { "log_block_size", &set_sb.s_log_block_size, 4, parse_uint },
> -       { "log_frag_size", &set_sb.s_log_frag_size, 4, parse_int },
> +       { "log_cluster_size", &set_sb.s_log_cluster_size, 4, parse_int },
>        { "blocks_per_group", &set_sb.s_blocks_per_group, 4, parse_uint },
> -       { "frags_per_group", &set_sb.s_frags_per_group, 4, parse_uint },
> +       { "clusters_per_group", &set_sb.s_clusters_per_group, 4, parse_uint },
>        { "inodes_per_group", &set_sb.s_inodes_per_group, 4, parse_uint },
>        { "mtime", &set_sb.s_mtime, 4, parse_time },
>        { "wtime", &set_sb.s_wtime, 4, parse_time },
> diff --git a/e2fsck/super.c b/e2fsck/super.c
> index accc2f1..82c07b2 100644
> --- a/e2fsck/super.c
> +++ b/e2fsck/super.c
> @@ -501,9 +501,12 @@ void check_super_block(e2fsck_t ctx)
>        check_super_value(ctx, "log_block_size", sb->s_log_block_size,
>                          MIN_CHECK | MAX_CHECK, 0,
>                          EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
> -       check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
> -                         MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
> -       check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
> +       check_super_value(ctx, "log_cluster_size",
> +                         sb->s_log_cluster_size,
> +                         MIN_CHECK | MAX_CHECK, sb->s_log_block_size,
> +                         (EXT2_MAX_CLUSTER_LOG_SIZE -
> +                          EXT2_MIN_CLUSTER_LOG_SIZE));
> +       check_super_value(ctx, "clusters_per_group", sb->s_clusters_per_group,
>                          MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
>                          bpg_max);
>        check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
> @@ -541,24 +544,14 @@ void check_super_block(e2fsck_t ctx)
>                }
>        }
>
> -       if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
> +       if (sb->s_log_block_size != (__u32) sb->s_log_cluster_size) {
>                pctx.blk = EXT2_BLOCK_SIZE(sb);
> -               pctx.blk2 = EXT2_FRAG_SIZE(sb);
> +               pctx.blk2 = EXT2_CLUSTER_SIZE(sb);
>                fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
>                ctx->flags |= E2F_FLAG_ABORT;
>                return;
>        }
>
> -       should_be = sb->s_frags_per_group >>
> -               (sb->s_log_block_size - sb->s_log_frag_size);
> -       if (sb->s_blocks_per_group != should_be) {
> -               pctx.blk = sb->s_blocks_per_group;
> -               pctx.blk2 = should_be;
> -               fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
> -               ctx->flags |= E2F_FLAG_ABORT;
> -               return;
> -       }
> -
>        should_be = (sb->s_log_block_size == 0) ? 1 : 0;
>        if (sb->s_first_data_block != should_be) {
>                pctx.blk = sb->s_first_data_block;
> diff --git a/lib/e2p/feature.c b/lib/e2p/feature.c
> index 9324199..16fba53 100644
> --- a/lib/e2p/feature.c
> +++ b/lib/e2p/feature.c
> @@ -57,6 +57,8 @@ static struct feature feature_list[] = {
>                        "extra_isize" },
>        {       E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_QUOTA,
>                        "quota" },
> +       {       E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_BIGALLOC,
> +                       "bigalloc"},
>
>        {       E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_COMPRESSION,
>                        "compression" },
> diff --git a/lib/e2p/ls.c b/lib/e2p/ls.c
> index 8b8360a..04a2c71 100644
> --- a/lib/e2p/ls.c
> +++ b/lib/e2p/ls.c
> @@ -229,12 +229,22 @@ void list_super2(struct ext2_super_block * sb, FILE *f)
>        fprintf(f, "Free inodes:              %u\n", sb->s_free_inodes_count);
>        fprintf(f, "First block:              %u\n", sb->s_first_data_block);
>        fprintf(f, "Block size:               %u\n", EXT2_BLOCK_SIZE(sb));
> -       fprintf(f, "Fragment size:            %u\n", EXT2_FRAG_SIZE(sb));
> +       if (sb->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_BIGALLOC)
> +               fprintf(f, "Cluster size:             %u\n",
> +                       EXT2_CLUSTER_SIZE(sb));
> +       else
> +               fprintf(f, "Fragment size:            %u\n",
> +                       EXT2_CLUSTER_SIZE(sb));
>        if (sb->s_reserved_gdt_blocks)
>                fprintf(f, "Reserved GDT blocks:      %u\n",
>                        sb->s_reserved_gdt_blocks);
>        fprintf(f, "Blocks per group:         %u\n", sb->s_blocks_per_group);
> -       fprintf(f, "Fragments per group:      %u\n", sb->s_frags_per_group);
> +       if (sb->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_BIGALLOC)
> +               fprintf(f, "Clusters per group:       %u\n",
> +                       sb->s_clusters_per_group);
> +       else
> +               fprintf(f, "Fragments per group:      %u\n",
> +                       sb->s_clusters_per_group);
>        fprintf(f, "Inodes per group:         %u\n", sb->s_inodes_per_group);
>        fprintf(f, "Inode blocks per group:   %u\n", inode_blocks_per_group);
>        if (sb->s_raid_stride)
> diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h
> index f396a10..b4fc6d9 100644
> --- a/lib/ext2fs/ext2_fs.h
> +++ b/lib/ext2fs/ext2_fs.h
> @@ -98,18 +98,15 @@
>  #define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof(__u32))
>
>  /*
> - * Macro-instructions used to manage fragments
> + * Macro-instructions used to manage allocation clusters
>  */
> -#define EXT2_MIN_FRAG_SIZE             EXT2_MIN_BLOCK_SIZE
> -#define EXT2_MAX_FRAG_SIZE             EXT2_MAX_BLOCK_SIZE
> -#define EXT2_MIN_FRAG_LOG_SIZE         EXT2_MIN_BLOCK_LOG_SIZE
> -#ifdef __KERNEL__
> -# define EXT2_FRAG_SIZE(s)             (EXT2_SB(s)->s_frag_size)
> -# define EXT2_FRAGS_PER_BLOCK(s)       (EXT2_SB(s)->s_frags_per_block)
> -#else
> -# define EXT2_FRAG_SIZE(s)             (EXT2_MIN_FRAG_SIZE << (s)->s_log_frag_size)
> -# define EXT2_FRAGS_PER_BLOCK(s)       (EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s))
> -#endif
> +#define EXT2_MIN_CLUSTER_LOG_SIZE      EXT2_MIN_BLOCK_LOG_SIZE
> +#define EXT2_MAX_CLUSTER_LOG_SIZE      29      /* 512MB  */
> +#define EXT2_MIN_CLUSTER_SIZE          EXT2_MIN_BLOCK_SIZE
> +#define EXT2_MAX_CLUSTER_SIZE          (1 << EXT2_MAX_CLUSTER_LOG_SIZE)
> +#define EXT2_CLUSTER_SIZE(s)           (EXT2_MIN_BLOCK_SIZE << \
> +                                               (s)->s_log_cluster_size)
> +#define EXT2_CLUSTER_SIZE_BITS(s)      ((s)->s_log_cluster_size + 10)
>
>  /*
>  * ACL structures
> @@ -518,9 +515,9 @@ struct ext2_super_block {
>        __u32   s_free_inodes_count;    /* Free inodes count */
>        __u32   s_first_data_block;     /* First Data Block */
>        __u32   s_log_block_size;       /* Block size */
> -       __s32   s_log_frag_size;        /* Fragment size */
> +       __s32   s_log_cluster_size;     /* Allocation cluster size */
>        __u32   s_blocks_per_group;     /* # Blocks per group */
> -       __u32   s_frags_per_group;      /* # Fragments per group */
> +       __u32   s_clusters_per_group;   /* # Fragments per group */
>        __u32   s_inodes_per_group;     /* # Inodes per group */

Just to be clear, my alternative suggestion to on-disk format change was:

         __u32   s_log_block_size;       /* Block size */
 -       __s32   s_log_frag_size;        /* Fragment size */
+       __s32   s_log_cluster_size;     /* Allocation cluster size */
 -       __u32   s_blocks_per_group;     /* # Blocks per group */
+       __u32   s_clusters_per_group;   /* # Clusters per group */
 -       __u32   s_frags_per_group;      /* # Fragments per group */
+       __u32   s_blocks_per_group;   /* # Blocks per group */
         __u32   s_inodes_per_group;     /* # Inodes per group */

This way, old kernels see a sane value in what used to be
s_blocks_per_group (32K)
and new kernels (even without the BIGALLOC feature) make sure to write
correct values
in both new s_blocks_per_group and s_clusters_per_group (old s_blocks_per_group)


>        __u32   s_mtime;                /* Mount time */
>        __u32   s_wtime;                /* Write time */
> @@ -675,6 +672,7 @@ struct ext2_super_block {
>  #define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE     0x0040
>  #define EXT4_FEATURE_RO_COMPAT_HAS_SNAPSHOT    0x0080
>  #define EXT4_FEATURE_RO_COMPAT_QUOTA           0x0100
> +#define EXT4_FEATURE_RO_COMPAT_BIGALLOC                0x0200
>
>  #define EXT2_FEATURE_INCOMPAT_COMPRESSION      0x0001
>  #define EXT2_FEATURE_INCOMPAT_FILETYPE         0x0002
> @@ -688,7 +686,6 @@ struct ext2_super_block {
>  #define EXT4_FEATURE_INCOMPAT_EA_INODE         0x0400
>  #define EXT4_FEATURE_INCOMPAT_DIRDATA          0x1000
>
> -
>  #define EXT2_FEATURE_COMPAT_SUPP       0
>  #define EXT2_FEATURE_INCOMPAT_SUPP     (EXT2_FEATURE_INCOMPAT_FILETYPE)
>  #define EXT2_FEATURE_RO_COMPAT_SUPP    (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
> diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
> index cf76562..516eb1a 100644
> --- a/lib/ext2fs/ext2fs.h
> +++ b/lib/ext2fs/ext2fs.h
> @@ -195,7 +195,7 @@ struct struct_ext2_filsys {
>        char *                          device_name;
>        struct ext2_super_block *       super;
>        unsigned int                    blocksize;
> -       int                             fragsize;
> +       int                             clustersize;
>        dgrp_t                          group_desc_count;
>        unsigned long                   desc_blocks;
>        struct ext2_group_desc *        group_desc;
> @@ -545,7 +545,7 @@ typedef struct ext2_icount *ext2_icount_t;
>  * to ext2fs_openfs()
>  */
>  #define EXT2_LIB_SOFTSUPP_INCOMPAT     (0)
> -#define EXT2_LIB_SOFTSUPP_RO_COMPAT    (0)
> +#define EXT2_LIB_SOFTSUPP_RO_COMPAT    (EXT4_FEATURE_RO_COMPAT_BIGALLOC)
>
>  /*
>  * function prototypes
> diff --git a/lib/ext2fs/initialize.c b/lib/ext2fs/initialize.c
> index cba2453..c109d08 100644
> --- a/lib/ext2fs/initialize.c
> +++ b/lib/ext2fs/initialize.c
> @@ -83,7 +83,6 @@ errcode_t ext2fs_initialize(const char *name, int flags,
>        ext2_filsys     fs;
>        errcode_t       retval;
>        struct ext2_super_block *super;
> -       int             frags_per_block;
>        unsigned int    rem;
>        unsigned int    overhead = 0;
>        unsigned int    ipg;
> @@ -136,7 +135,7 @@ errcode_t ext2fs_initialize(const char *name, int flags,
>        super->s_state = EXT2_VALID_FS;
>
>        set_field(s_log_block_size, 0); /* default blocksize: 1024 bytes */
> -       set_field(s_log_frag_size, 0); /* default fragsize: 1024 bytes */
> +       set_field(s_log_cluster_size, 0);
>        set_field(s_first_data_block, super->s_log_block_size ? 0 : 1);
>        set_field(s_max_mnt_count, 0);
>        set_field(s_errors, EXT2_ERRORS_DEFAULT);
> @@ -179,14 +178,13 @@ errcode_t ext2fs_initialize(const char *name, int flags,
>        super->s_creator_os = CREATOR_OS;
>
>        fs->blocksize = EXT2_BLOCK_SIZE(super);
> -       fs->fragsize = EXT2_FRAG_SIZE(super);
> -       frags_per_block = fs->blocksize / fs->fragsize;
> +       fs->clustersize = EXT2_CLUSTER_SIZE(super);
>
>        /* default: (fs->blocksize*8) blocks/group, up to 2^16 (GDT limit) */
>        set_field(s_blocks_per_group, fs->blocksize * 8);
>        if (super->s_blocks_per_group > EXT2_MAX_BLOCKS_PER_GROUP(super))
>                super->s_blocks_per_group = EXT2_MAX_BLOCKS_PER_GROUP(super);
> -       super->s_frags_per_group = super->s_blocks_per_group * frags_per_block;
> +       super->s_clusters_per_group = super->s_blocks_per_group;
>
>        super->s_blocks_count = param->s_blocks_count;
>        super->s_r_blocks_count = param->s_r_blocks_count;
> @@ -239,8 +237,7 @@ retry:
>                        /* Try again with slightly different parameters */
>                        super->s_blocks_per_group -= 8;
>                        super->s_blocks_count = param->s_blocks_count;
> -                       super->s_frags_per_group = super->s_blocks_per_group *
> -                               frags_per_block;
> +                       super->s_clusters_per_group = super->s_blocks_per_group;
>                        goto retry;
>                } else {
>                        retval = EXT2_ET_TOO_MANY_INODES;
> diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c
> index d638da0..a20b923 100644
> --- a/lib/ext2fs/openfs.c
> +++ b/lib/ext2fs/openfs.c
> @@ -244,7 +244,7 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
>                retval = EXT2_ET_CORRUPT_SUPERBLOCK;
>                goto cleanup;
>        }
> -       fs->fragsize = EXT2_FRAG_SIZE(fs->super);
> +       fs->clustersize = EXT2_CLUSTER_SIZE(fs->super);
>        fs->inode_blocks_per_group = ((EXT2_INODES_PER_GROUP(fs->super) *
>                                       EXT2_INODE_SIZE(fs->super) +
>                                       EXT2_BLOCK_SIZE(fs->super) - 1) /
> diff --git a/lib/ext2fs/swapfs.c b/lib/ext2fs/swapfs.c
> index 15ff6fc..52b0fa9 100644
> --- a/lib/ext2fs/swapfs.c
> +++ b/lib/ext2fs/swapfs.c
> @@ -31,9 +31,9 @@ void ext2fs_swap_super(struct ext2_super_block * sb)
>        sb->s_free_inodes_count = ext2fs_swab32(sb->s_free_inodes_count);
>        sb->s_first_data_block = ext2fs_swab32(sb->s_first_data_block);
>        sb->s_log_block_size = ext2fs_swab32(sb->s_log_block_size);
> -       sb->s_log_frag_size = ext2fs_swab32(sb->s_log_frag_size);
> +       sb->s_log_cluster_size = ext2fs_swab32(sb->s_log_cluster_size);
>        sb->s_blocks_per_group = ext2fs_swab32(sb->s_blocks_per_group);
> -       sb->s_frags_per_group = ext2fs_swab32(sb->s_frags_per_group);
> +       sb->s_clusters_per_group = ext2fs_swab32(sb->s_clusters_per_group);
>        sb->s_inodes_per_group = ext2fs_swab32(sb->s_inodes_per_group);
>        sb->s_mtime = ext2fs_swab32(sb->s_mtime);
>        sb->s_wtime = ext2fs_swab32(sb->s_wtime);
> diff --git a/lib/ext2fs/tst_super_size.c b/lib/ext2fs/tst_super_size.c
> index a3a5b44..6fffcfd 100644
> --- a/lib/ext2fs/tst_super_size.c
> +++ b/lib/ext2fs/tst_super_size.c
> @@ -50,9 +50,9 @@ void check_superblock_fields()
>        check_field(s_free_inodes_count);
>        check_field(s_first_data_block);
>        check_field(s_log_block_size);
> -       check_field(s_log_frag_size);
> +       check_field(s_log_cluster_size);
>        check_field(s_blocks_per_group);
> -       check_field(s_frags_per_group);
> +       check_field(s_clusters_per_group);
>        check_field(s_inodes_per_group);
>        check_field(s_mtime);
>        check_field(s_wtime);
> diff --git a/misc/mke2fs.c b/misc/mke2fs.c
> index a5cf16b..eace0d3 100644
> --- a/misc/mke2fs.c
> +++ b/misc/mke2fs.c
> @@ -616,8 +616,13 @@ static void show_stats(ext2_filsys fs)
>        printf("\n");
>        printf(_("Block size=%u (log=%u)\n"), fs->blocksize,
>                s->s_log_block_size);
> -       printf(_("Fragment size=%u (log=%u)\n"), fs->fragsize,
> -               s->s_log_frag_size);
> +       if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
> +                                      EXT4_FEATURE_RO_COMPAT_BIGALLOC))
> +               printf(_("Cluster size=%u (log=%u)\n"),
> +                      fs->clustersize, s->s_log_cluster_size);
> +       else
> +               printf(_("Fragment size=%u (log=%u)\n"), fs->clustersize,
> +                      s->s_log_cluster_size);
>        printf(_("Stride=%u blocks, Stripe width=%u blocks\n"),
>               s->s_raid_stride, s->s_raid_stripe_width);
>        printf(_("%u inodes, %u blocks\n"), s->s_inodes_count,
> @@ -634,8 +639,13 @@ static void show_stats(ext2_filsys fs)
>                printf(_("%u block groups\n"), fs->group_desc_count);
>        else
>                printf(_("%u block group\n"), fs->group_desc_count);
> -       printf(_("%u blocks per group, %u fragments per group\n"),
> -              s->s_blocks_per_group, s->s_frags_per_group);
> +       if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
> +                                      EXT4_FEATURE_RO_COMPAT_BIGALLOC))
> +               printf(_("%u blocks per group, %u clusters per group\n"),
> +                      s->s_blocks_per_group, s->s_clusters_per_group);
> +       else
> +               printf(_("%u blocks per group, %u fragments per group\n"),
> +                      s->s_blocks_per_group, s->s_clusters_per_group);
>        printf(_("%u inodes per group\n"), s->s_inodes_per_group);
>
>        if (fs->group_desc_count == 1) {
> @@ -1309,8 +1319,6 @@ static void PRS(int argc, char *argv[])
>                                        optarg);
>                                exit(1);
>                        }
> -                       fs_param.s_log_frag_size =
> -                               int_log2(size >> EXT2_MIN_BLOCK_LOG_SIZE);
>                        fprintf(stderr, _("Warning: fragments not supported.  "
>                               "Ignoring -f option\n"));
>                        break;
> @@ -1542,7 +1550,7 @@ static void PRS(int argc, char *argv[])
>                check_plausibility(device_name);
>        check_mount(device_name, force, _("filesystem"));
>
> -       fs_param.s_log_frag_size = fs_param.s_log_block_size;
> +       fs_param.s_log_cluster_size = fs_param.s_log_block_size;
>
>        if (noaction && fs_param.s_blocks_count) {
>                dev_size = fs_param.s_blocks_count;
> @@ -1780,7 +1788,7 @@ got_size:
>                        inode_ratio = blocksize;
>        }
>
> -       fs_param.s_log_frag_size = fs_param.s_log_block_size =
> +       fs_param.s_log_cluster_size = fs_param.s_log_block_size =
>                int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE);
>
>  #ifdef HAVE_BLKID_PROBE_GET_TOPOLOGY
> --
> 1.7.3.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Reiser Filesystem Development]     [Ceph FS]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux FS]     [Yosemite National Park]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Device Mapper]     [Linux Media]

  Powered by Linux