lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Sun, 20 Mar 2011 12:33:44 +0200
From:	Amir Goldstein <amir73il@...il.com>
To:	"Theodore Ts'o" <tytso@....edu>
Cc:	linux-ext4@...r.kernel.org
Subject: Re: [PATCH, RFC 00/12] bigalloc patchset

On Sat, Mar 19, 2011 at 11:28 PM, Theodore Ts'o <tytso@....edu> wrote:
> This is an initial patchset of the bigalloc patches to ext4.  This patch
> adds support for clustered allocation, so that each bit in the ext4
> block allocation bitmap addresses a power of two number of blocks.  For
> example, if the file system is mainly going to be storing large files in
> the 4-32 megabyte range, it might make sense to set a cluster size of 1
> megabyte.  This means that each bit in the block allocaiton bitmap would
> now address 256 4k blocks, and it means that the size of the block
> bitmaps for a 2T file system shrinks from 64 megabytes to 256k.  It also
> means that a block group addresses 32 gigabytes instead of 128
> megabytes, also shrinking the amount of file system overhead for
> metadata.
>
> The cost is increased disk space efficiency.  Directories will consume
> 1T, as will extent tree blocks.  (I am on the fence as to whether I
> should add complexity so that in the rare case that an inode needs more
> than 344 extents --- a highly fragmented file indeed --- and need a
> second extent tree block, we can avoid allocating any cluster and
> instead use another block from the cluster used by the inode.  The
> concern is the amount of complexity this adds to the e2fsck, not just to
> the kernel.)

Unless you define extent tree block size = cluster size.
Shouldn't be too hard to teach that to kernel and fsck, right?

>
> To test these patches, I have used an *extremely* kludgy set of patches
> to e2fsprogs, which are attached below.  These patches need *extensive*
> revision before I would consider them clean enough suitable for
> committing into e2fsprogs, but they were sufficient for me to do the
> kernel-side changes --- mke2fs, dumpe2fs, and debugfs work.  E2fsck most
> definitely does _not_ work at this stage.
>
> Please comment!  I do not intend for these patches to be merged during
> the 2.6.39 merge window.  I am targetting 2.6.40, 3 months from now,
> since these patches are quite extensive.
>
>                                                        - Ted
>
> Theodore Ts'o (12):
>  ext4: read-only support for bigalloc file systems
>  ext4: enforce bigalloc restrictions (e.g., no online resizing, etc.)
>  ext4: Convert instances of EXT4_BLOCKS_PER_GROUP to
>    EXT4_CLUSTERS_PER_GROUP
>  ext4: Remove block bitmap initialization in ext4_new_inode()
>  ext4: factor out block group accounting into functions
>  ext4: split out ext4_free_blocks_after_init()
>  ext4: bigalloc changes to block bitmap initialization functions
>  ext4: Convert block group-relative offsets to use clusters
>  ext4: teach ext4_ext_map_blocks() about the bigalloc feature


I think you are missing an important patch here:

ext4: teach ext4_free_blocks() about the bigalloc feature

Free only clusters whose 'base' block is contained within the
requested blocks range.


>  ext4: teach ext4_statfs() to deal with clusters if bigalloc is
>    enabled
>  ext4: tune mballoc's default group prealloc size for bigalloc file
>    systems
>  ext4: enable mounting bigalloc as read/write
>
>  fs/ext4/balloc.c  |  268 +++++++++++++++++++++++++++++++++--------------------
>  fs/ext4/ext4.h    |   47 ++++++++--
>  fs/ext4/extents.c |  132 +++++++++++++++++++++++---
>  fs/ext4/ialloc.c  |   37 --------
>  fs/ext4/inode.c   |    7 ++
>  fs/ext4/ioctl.c   |   33 ++++++-
>  fs/ext4/mballoc.c |   49 ++++++----
>  fs/ext4/mballoc.h |    3 +-
>  fs/ext4/super.c   |  100 ++++++++++++++++----
>  9 files changed, 472 insertions(+), 204 deletions(-)
>
> --
> 1.7.3.1
>
> ------------------- e2fsprogs patches follow below
>
> diff --git a/lib/ext2fs/bmap64.h b/lib/ext2fs/bmap64.h
> index b0aa84c..cfbdfd6 100644
> --- a/lib/ext2fs/bmap64.h
> +++ b/lib/ext2fs/bmap64.h
> @@ -31,6 +31,10 @@ struct ext2fs_struct_generic_bitmap {
>         ((bmap)->magic == EXT2_ET_MAGIC_BLOCK_BITMAP64) || \
>         ((bmap)->magic == EXT2_ET_MAGIC_INODE_BITMAP64))
>
> +/* Bitmap flags */
> +
> +#define EXT2_BMFLAG_CLUSTER 0x0001
> +
>  struct ext2_bitmap_ops {
>        int     type;
>        /* Generic bmap operators */
> diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h
> index a89e33b..0970506 100644
> --- a/lib/ext2fs/ext2_fs.h
> +++ b/lib/ext2fs/ext2_fs.h
> @@ -228,9 +228,13 @@ struct ext2_dx_countlimit {
>
>  #define EXT2_BLOCKS_PER_GROUP(s)       (EXT2_SB(s)->s_blocks_per_group)
>  #define EXT2_INODES_PER_GROUP(s)       (EXT2_SB(s)->s_inodes_per_group)
> +#define EXT2_CLUSTERS_PER_GROUP(s)     (EXT2_SB(s)->s_clusters_per_group)
>  #define EXT2_INODES_PER_BLOCK(s)       (EXT2_BLOCK_SIZE(s)/EXT2_INODE_SIZE(s))
>  /* limits imposed by 16-bit value gd_free_{blocks,inode}_count */
> -#define EXT2_MAX_BLOCKS_PER_GROUP(s)   ((1 << 16) - 8)
> +#define EXT2_MAX_BLOCKS_PER_GROUP(s)   (((1 << 16) - 8) *      \
> +                                        (EXT2_CLUSTER_SIZE(s) / \
> +                                         EXT2_BLOCK_SIZE(s)))
> +#define EXT2_MAX_CLUSTERS_PER_GROUP(s) ((1 << 16) - 8)
>  #define EXT2_MAX_INODES_PER_GROUP(s)   ((1 << 16) - EXT2_INODES_PER_BLOCK(s))
>  #ifdef __KERNEL__
>  #define EXT2_DESC_PER_BLOCK(s)         (EXT2_SB(s)->s_desc_per_block)
> diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
> index d3eb31d..a065e87 100644
> --- a/lib/ext2fs/ext2fs.h
> +++ b/lib/ext2fs/ext2fs.h
> @@ -207,7 +207,7 @@ struct struct_ext2_filsys {
>        char *                          device_name;
>        struct ext2_super_block *       super;
>        unsigned int                    blocksize;
> -       int                             clustersize;
> +       int                             cluster_ratio;
>        dgrp_t                          group_desc_count;
>        unsigned long                   desc_blocks;
>        struct opaque_ext2_group_desc * group_desc;
> @@ -232,7 +232,8 @@ struct struct_ext2_filsys {
>        /*
>         * Reserved for future expansion
>         */
> -       __u32                           reserved[7];
> +       __u32                           clustersize;
> +       __u32                           reserved[6];
>
>        /*
>         * Reserved for the use of the calling application.
> @@ -553,7 +554,8 @@ typedef struct ext2_icount *ext2_icount_t;
>                                         EXT2_FEATURE_RO_COMPAT_LARGE_FILE|\
>                                         EXT4_FEATURE_RO_COMPAT_DIR_NLINK|\
>                                         EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE|\
> -                                        EXT4_FEATURE_RO_COMPAT_GDT_CSUM)
> +                                        EXT4_FEATURE_RO_COMPAT_GDT_CSUM|\
> +                                        EXT4_FEATURE_RO_COMPAT_BIGALLOC)
>
>  /*
>  * These features are only allowed if EXT2_FLAG_SOFTSUPP_FEATURES is passed
> diff --git a/lib/ext2fs/gen_bitmap64.c b/lib/ext2fs/gen_bitmap64.c
> index df095ac..60321df 100644
> --- a/lib/ext2fs/gen_bitmap64.c
> +++ b/lib/ext2fs/gen_bitmap64.c
> @@ -559,3 +559,85 @@ int ext2fs_warn_bitmap32(ext2fs_generic_bitmap bitmap, const char *func)
>                        "called %s with 64-bit bitmap", func);
>  #endif
>  }
> +
> +errcode_t ext2fs_allocate_cluster_bitmap(ext2_filsys fs,
> +                                        const char *descr,
> +                                        ext2fs_block_bitmap *ret)
> +{
> +       __u64           start, end, real_end;
> +       errcode_t       retval;
> +
> +       EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
> +
> +       if (!(fs->flags & EXT2_FLAG_64BITS))
> +               return EXT2_ET_CANT_USE_LEGACY_BITMAPS;
> +
> +       fs->write_bitmaps = ext2fs_write_bitmaps;
> +
> +       start = (fs->super->s_first_data_block >>
> +                EXT2_CLUSTER_SIZE_BITS(fs->super));
> +       end = (ext2fs_blocks_count(fs->super) - 1) / fs->cluster_ratio;
> +       real_end = ((__u64) EXT2_CLUSTERS_PER_GROUP(fs->super)
> +                   * (__u64) fs->group_desc_count)-1 + start;
> +
> +       retval = ext2fs_alloc_generic_bmap(fs,
> +                                          EXT2_ET_MAGIC_BLOCK_BITMAP64,
> +                                          EXT2FS_BMAP64_BITARRAY,
> +                                          start, end, real_end, descr, ret);
> +       if (retval)
> +               return retval;
> +
> +       (*ret)->flags = EXT2_BMFLAG_CLUSTER;
> +
> +       printf("Returning 0...\n");
> +       return 0;
> +}
> +
> +int ext2fs_is_cluster_bitmap(ext2fs_block_bitmap bm)
> +{
> +       if (EXT2FS_IS_32_BITMAP(bm))
> +               return 0;
> +
> +       return (bm->flags & EXT2_BMFLAG_CLUSTER);
> +}
> +
> +errcode_t ext2fs_convert_to_cluster_bitmap(ext2_filsys fs,
> +                                         ext2fs_block_bitmap bmap,
> +                                         ext2fs_block_bitmap *ret)
> +{
> +       ext2fs_block_bitmap     cmap;
> +       errcode_t               retval;
> +       blk64_t                 i, j, b_end, c_end;
> +       int                     n;
> +
> +       retval = ext2fs_allocate_cluster_bitmap(fs, "converted cluster bitmap",
> +                                               ret);
> +       if (retval)
> +               return retval;
> +
> +       cmap = *ret;
> +       i = bmap->start;
> +       b_end = bmap->end;
> +       bmap->end = bmap->real_end;
> +       j = cmap->start;
> +       c_end = cmap->end;
> +       cmap->end = cmap->real_end;
> +       n = 0;
> +       while (i < bmap->real_end) {
> +               if (ext2fs_test_block_bitmap2(bmap, i)) {
> +                       ext2fs_mark_block_bitmap2(cmap, j);
> +                       i += fs->cluster_ratio - n;
> +                       j++;
> +                       n = 0;
> +                       continue;
> +               }
> +               i++; n++;
> +               if (n >= fs->cluster_ratio) {
> +                       j++;
> +                       n = 0;
> +               }
> +       }
> +       bmap->end = b_end;
> +       cmap->end = c_end;
> +       return 0;
> +}
> diff --git a/lib/ext2fs/initialize.c b/lib/ext2fs/initialize.c
> index e1f229b..00a8b38 100644
> --- a/lib/ext2fs/initialize.c
> +++ b/lib/ext2fs/initialize.c
> @@ -94,6 +94,7 @@ errcode_t ext2fs_initialize(const char *name, int flags,
>        blk_t           numblocks;
>        int             rsv_gdt;
>        int             csum_flag;
> +       int             bigalloc_flag;
>        int             io_flags;
>        char            *buf = 0;
>        char            c;
> @@ -134,12 +135,25 @@ errcode_t ext2fs_initialize(const char *name, int flags,
>
>  #define set_field(field, default) (super->field = param->field ? \
>                                   param->field : (default))
> +#define assign_field(field)    (super->field = param->field)
>
>        super->s_magic = EXT2_SUPER_MAGIC;
>        super->s_state = EXT2_VALID_FS;
>
> -       set_field(s_log_block_size, 0); /* default blocksize: 1024 bytes */
> -       set_field(s_log_cluster_size, 0);
> +       bigalloc_flag = EXT2_HAS_RO_COMPAT_FEATURE(param,
> +                                  EXT4_FEATURE_RO_COMPAT_BIGALLOC);
> +
> +       assign_field(s_log_block_size);
> +
> +       if (bigalloc_flag) {
> +               set_field(s_log_cluster_size, super->s_log_block_size+4);
> +               if (super->s_log_block_size > super->s_log_cluster_size) {
> +                       retval = EXT2_ET_INVALID_ARGUMENT;
> +                       goto cleanup;
> +               }
> +       } else
> +               super->s_log_cluster_size = super->s_log_block_size;
> +
>        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);
> @@ -183,14 +197,36 @@ errcode_t ext2fs_initialize(const char *name, int flags,
>
>        fs->blocksize = EXT2_BLOCK_SIZE(super);
>        fs->clustersize = EXT2_CLUSTER_SIZE(super);
> +       fs->cluster_ratio = fs->clustersize / fs->blocksize;
> +
> +       if (bigalloc_flag) {
> +               if (param->s_blocks_per_group &&
> +                   param->s_clusters_per_group &&
> +                   ((param->s_clusters_per_group * fs->cluster_ratio) !=
> +                    param->s_blocks_per_group)) {
> +                       retval = EXT2_ET_INVALID_ARGUMENT;
> +                       goto cleanup;
> +               }
> +               if (param->s_clusters_per_group)
> +                       assign_field(s_clusters_per_group);
> +               else if (param->s_blocks_per_group)
> +                       super->s_clusters_per_group =
> +                               param->s_blocks_per_group / fs->cluster_ratio;
> +               else
> +                       super->s_clusters_per_group = fs->blocksize * 8;
> +               if (super->s_clusters_per_group > EXT2_MAX_CLUSTERS_PER_GROUP(super))
> +                       super->s_blocks_per_group = EXT2_MAX_CLUSTERS_PER_GROUP(super);
> +               super->s_blocks_per_group = super->s_clusters_per_group;
> +               super->s_blocks_per_group *= fs->cluster_ratio;
> +       } else {
> +               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_clusters_per_group = super->s_blocks_per_group;
> +       }
>
> -       /* 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_clusters_per_group = super->s_blocks_per_group;
> -
> -       ext2fs_blocks_count_set(super, ext2fs_blocks_count(param));
> +       ext2fs_blocks_count_set(super, ext2fs_blocks_count(param) &
> +                               ~((blk64_t) fs->cluster_ratio - 1));
>        ext2fs_r_blocks_count_set(super, ext2fs_r_blocks_count(param));
>        if (ext2fs_r_blocks_count(super) >= ext2fs_blocks_count(param)) {
>                retval = EXT2_ET_INVALID_ARGUMENT;
> @@ -246,7 +282,7 @@ retry:
>         */
>        ipg = ext2fs_div_ceil(super->s_inodes_count, fs->group_desc_count);
>        if (ipg > fs->blocksize * 8) {
> -               if (super->s_blocks_per_group >= 256) {
> +               if (!bigalloc_flag && super->s_blocks_per_group >= 256) {
>                        /* Try again with slightly different parameters */
>                        super->s_blocks_per_group -= 8;
>                        ext2fs_blocks_count_set(super,
> diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c
> index 90abed1..8b37852 100644
> --- a/lib/ext2fs/openfs.c
> +++ b/lib/ext2fs/openfs.c
> @@ -251,6 +251,7 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
>                goto cleanup;
>        }
>        fs->clustersize = EXT2_CLUSTER_SIZE(fs->super);
> +       fs->cluster_ratio = fs->clustersize / fs->blocksize;
>        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/rw_bitmaps.c b/lib/ext2fs/rw_bitmaps.c
> index 3031b7d..aeea997 100644
> --- a/lib/ext2fs/rw_bitmaps.c
> +++ b/lib/ext2fs/rw_bitmaps.c
> @@ -51,7 +51,7 @@ static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block)
>
>        inode_nbytes = block_nbytes = 0;
>        if (do_block) {
> -               block_nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
> +               block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8;
>                retval = ext2fs_get_memalign(fs->blocksize, fs->blocksize,
>                                             &block_buf);
>                if (retval)
> @@ -85,7 +85,7 @@ static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block)
>                        /* Force bitmap padding for the last group */
>                        nbits = ((ext2fs_blocks_count(fs->super)
>                                  - (__u64) fs->super->s_first_data_block)
> -                                % (__u64) EXT2_BLOCKS_PER_GROUP(fs->super));
> +                                % (__u64) EXT2_CLUSTERS_PER_GROUP(fs->super));
>                        if (nbits)
>                                for (j = nbits; j < fs->blocksize * 8; j++)
>                                        ext2fs_set_bit(j, block_buf);
> @@ -141,7 +141,7 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
>        char *block_bitmap = 0, *inode_bitmap = 0;
>        char *buf;
>        errcode_t retval;
> -       int block_nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
> +       int block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8;
>        int inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8;
>        int csum_flag = 0;
>        int do_image = fs->flags & EXT2_FLAG_IMAGE_FILE;
> @@ -219,7 +219,7 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
>                }
>                blk = (fs->image_header->offset_blockmap /
>                       fs->blocksize);
> -               blk_cnt = (blk64_t)EXT2_BLOCKS_PER_GROUP(fs->super) *
> +               blk_cnt = (blk64_t)EXT2_CLUSTERS_PER_GROUP(fs->super) *
>                        fs->group_desc_count;
>                while (block_nbytes > 0) {
>                        retval = io_channel_read_blk64(fs->image_io, blk++,
> diff --git a/misc/dumpe2fs.c b/misc/dumpe2fs.c
> index c01ffe5..d3f617a 100644
> --- a/misc/dumpe2fs.c
> +++ b/misc/dumpe2fs.c
> @@ -71,25 +71,26 @@ static void print_range(unsigned long long a, unsigned long long b)
>                printf("%llu-%llu", a, b);
>  }
>
> -static void print_free (unsigned long group, char * bitmap,
> -                       unsigned long nbytes, unsigned long offset)
> +static void print_free(unsigned long group, char * bitmap,
> +                      unsigned long nbytes, unsigned long offset, int ratio)
>  {
>        int p = 0;
>        unsigned long i;
>        unsigned long j;
>
> +       offset /= ratio;
>        offset += group * nbytes;
>        for (i = 0; i < nbytes; i++)
>                if (!in_use (bitmap, i))
>                {
>                        if (p)
>                                printf (", ");
> -                       print_number(i + offset);
> +                       print_number((i + offset) * ratio);
>                        for (j = i; j < nbytes && !in_use (bitmap, j); j++)
>                                ;
>                        if (--j != i) {
>                                fputc('-', stdout);
> -                               print_number(j + offset);
> +                               print_number((j + offset) * ratio);
>                                i = j;
>                        }
>                        p = 1;
> @@ -153,7 +154,7 @@ static void list_desc (ext2_filsys fs)
>        blk64_t         blk_itr = fs->super->s_first_data_block;
>        ext2_ino_t      ino_itr = 1;
>
> -       block_nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
> +       block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8;
>        inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8;
>
>        if (fs->block_map)
> @@ -238,18 +239,19 @@ static void list_desc (ext2_filsys fs)
>                        fputs(_("  Free blocks: "), stdout);
>                        ext2fs_get_block_bitmap_range2(fs->block_map,
>                                 blk_itr, block_nbytes << 3, block_bitmap);
> -                       print_free (i, block_bitmap,
> -                                   fs->super->s_blocks_per_group,
> -                                   fs->super->s_first_data_block);
> +                       print_free(i, block_bitmap,
> +                                  fs->super->s_clusters_per_group,
> +                                  fs->super->s_first_data_block,
> +                                  fs->cluster_ratio);
>                        fputc('\n', stdout);
> -                       blk_itr += fs->super->s_blocks_per_group;
> +                       blk_itr += fs->super->s_clusters_per_group;
>                }
>                if (inode_bitmap) {
>                        fputs(_("  Free inodes: "), stdout);
>                        ext2fs_get_inode_bitmap_range2(fs->inode_map,
>                                 ino_itr, inode_nbytes << 3, inode_bitmap);
> -                       print_free (i, inode_bitmap,
> -                                   fs->super->s_inodes_per_group, 1);
> +                       print_free(i, inode_bitmap,
> +                                  fs->super->s_inodes_per_group, 1, 1);
>                        fputc('\n', stdout);
>                        ino_itr += fs->super->s_inodes_per_group;
>                }
> diff --git a/misc/mke2fs.c b/misc/mke2fs.c
> index 9798b88..079638f 100644
> --- a/misc/mke2fs.c
> +++ b/misc/mke2fs.c
> @@ -815,7 +815,8 @@ static __u32 ok_features[3] = {
>                EXT4_FEATURE_RO_COMPAT_DIR_NLINK|
>                EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE|
>                EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|
> -               EXT4_FEATURE_RO_COMPAT_GDT_CSUM
> +               EXT4_FEATURE_RO_COMPAT_GDT_CSUM|
> +               EXT4_FEATURE_RO_COMPAT_BIGALLOC
>  };
>
>
> @@ -1252,7 +1253,7 @@ profile_error:
>        }
>
>        while ((c = getopt (argc, argv,
> -                   "b:cf:g:G:i:jl:m:no:qr:s:t:vE:FI:J:KL:M:N:O:R:ST:U:V")) != EOF) {
> +                   "b:cg:i:jl:m:no:qr:s:t:vC:E:FG:I:J:KL:M:N:O:R:ST:U:V")) != EOF) {
>                switch (c) {
>                case 'b':
>                        blocksize = strtol(optarg, &tmp, 0);
> @@ -1275,17 +1276,17 @@ profile_error:
>                case 'c':       /* Check for bad blocks */
>                        cflag++;
>                        break;
> -               case 'f':
> +               case 'C':
>                        size = strtoul(optarg, &tmp, 0);
> -                       if (size < EXT2_MIN_BLOCK_SIZE ||
> -                           size > EXT2_MAX_BLOCK_SIZE || *tmp) {
> +                       if (size < EXT2_MIN_CLUSTER_SIZE ||
> +                           size > EXT2_MAX_CLUSTER_SIZE || *tmp) {
>                                com_err(program_name, 0,
>                                        _("invalid fragment size - %s"),
>                                        optarg);
>                                exit(1);
>                        }
> -                       fprintf(stderr, _("Warning: fragments not supported.  "
> -                              "Ignoring -f option\n"));
> +                       fs_param.s_log_cluster_size =
> +                               int_log2(size >> EXT2_MIN_CLUSTER_LOG_SIZE);
>                        break;
>                case 'g':
>                        fs_param.s_blocks_per_group = strtoul(optarg, &tmp, 0);
> @@ -1515,8 +1516,6 @@ profile_error:
>                check_plausibility(device_name);
>        check_mount(device_name, force, _("filesystem"));
>
> -       fs_param.s_log_cluster_size = fs_param.s_log_block_size;
> -
>        /* Determine the size of the device (if possible) */
>        if (noaction && fs_blocks_count) {
>                dev_size = fs_blocks_count;
> @@ -1752,16 +1751,24 @@ profile_error:
>                }
>        }
>
> +       fs_param.s_log_block_size =
> +               int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE);
> +       if (fs_param.s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_BIGALLOC) {
> +               if (fs_param.s_log_cluster_size == 0)
> +                       fs_param.s_log_cluster_size =
> +                               fs_param.s_log_block_size + 4;
> +       } else
> +               fs_param.s_log_cluster_size = fs_param.s_log_block_size;
> +
>        if (inode_ratio == 0) {
>                inode_ratio = get_int_from_profile(fs_types, "inode_ratio",
>                                                   8192);
>                if (inode_ratio < blocksize)
>                        inode_ratio = blocksize;
> +               if (inode_ratio < EXT2_CLUSTER_SIZE(&fs_param))
> +                       inode_ratio = EXT2_CLUSTER_SIZE(&fs_param);
>        }
>
> -       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
>        retval = get_device_geometry(device_name, &fs_param, psector_size);
>        if (retval < 0) {
> @@ -2049,6 +2056,33 @@ static int mke2fs_discard_device(ext2_filsys fs)
>        return retval;
>  }
>
> +static fix_cluster_bg_counts(ext2_filsys fs)
> +{
> +       blk64_t cluster, num_clusters, tot_free;
> +       int     grp_free, num_free, group, num;
> +
> +       num_clusters = ext2fs_blocks_count(fs->super) / fs->cluster_ratio;
> +       tot_free = num_free = num = group = grp_free = 0;
> +       for (cluster = fs->super->s_first_data_block / fs->cluster_ratio;
> +            cluster < num_clusters; cluster++) {
> +               if (!ext2fs_test_block_bitmap2(fs->block_map, cluster)) {
> +                       grp_free++;
> +                       tot_free++;
> +               }
> +               num++;
> +               if ((num == fs->super->s_clusters_per_group) ||
> +                   (cluster == num_clusters-1)) {
> +                       printf("Group %d has free #: %d\n", group, grp_free);
> +                       ext2fs_bg_free_blocks_count_set(fs, group, grp_free);
> +                       ext2fs_group_desc_csum_set(fs, group);
> +                       num = 0;
> +                       grp_free = 0;
> +                       group++;
> +               }
> +       }
> +       ext2fs_free_blocks_count_set(fs->super, tot_free);
> +}
> +
>  int main (int argc, char *argv[])
>  {
>        errcode_t       retval = 0;
> @@ -2367,6 +2401,17 @@ int main (int argc, char *argv[])
>        }
>  no_journal:
>
> +       if (EXT2_HAS_RO_COMPAT_FEATURE(&fs_param,
> +                                      EXT4_FEATURE_RO_COMPAT_BIGALLOC)) {
> +               ext2fs_block_bitmap cluster_map;
> +
> +               retval = ext2fs_convert_to_cluster_bitmap(fs, fs->block_map,
> +                                                        &cluster_map);
> +               ext2fs_free_block_bitmap(fs->block_map);
> +               fs->block_map = cluster_map;
> +               fix_cluster_bg_counts(fs);
> +       }
> +
>        if (!quiet)
>                printf(_("Writing superblocks and "
>                       "filesystem accounting information: "));
> --
> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> the body of a message to majordomo@...r.kernel.org
> 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@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ