]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
e2fsprogs-stride_option.patch
authorAndreas Dilger <adilger@sun.com>
Sat, 2 Feb 2008 08:47:06 +0000 (01:47 -0700)
committerTheodore Ts'o <tytso@mit.edu>
Mon, 11 Feb 2008 03:36:56 +0000 (22:36 -0500)
Add support for setting the s_raid_stride and s_raid_stripe_width
fields in the superblock via mke2fs and tune2fs.c.  This is useful
for mballoc to align block allocation on the RAID stripe boundaries.

Fix up the debugfs "ssv" command to set a number of new superblock fields.

Signed-off-by: Rupesh Thakare <rupesh@clusterfs.com>
Signed-off-by: Andreas Dilger <adilger@clusterfs.com>
debugfs/set_fields.c
lib/blkid/read.c
lib/ext2fs/initialize.c
misc/mke2fs.8.in
misc/mke2fs.c
misc/tune2fs.8.in
misc/tune2fs.c

index eedf3d50c5bc929346d759a1c241b4cb5324ed55..f8125773cc62fcb600d592de4741b99172f58208 100644 (file)
@@ -9,12 +9,18 @@
  * %End-Header%
  */
 
-#define _XOPEN_SOURCE 500 /* for inclusion of strptime() */
+#define _XOPEN_SOURCE 600 /* for inclusion of strptime() and strtoull */
+
+#ifdef HAVE_STRTOULL
+#define STRTOULL strtoull
+#else
+#define STRTOULL strtoul
+#endif
 
 #include <stdio.h>
 #include <unistd.h>
-#include <stdlib.h>
 #include <ctype.h>
+#include <stdlib.h>
 #include <string.h>
 #include <strings.h>
 #include <time.h>
@@ -100,7 +106,6 @@ static struct field_set_info super_fields[] = {
                  parse_uint },
        { "reserved_gdt_blocks", &set_sb.s_reserved_gdt_blocks, 2,
                  parse_uint },
-       /* s_padding1 */
        { "journal_uuid", &set_sb.s_journal_uuid, 16, parse_uuid },
        { "journal_inum", &set_sb.s_journal_inum, 4, parse_uint },
        { "journal_dev", &set_sb.s_journal_dev, 4, parse_uint },
@@ -108,13 +113,22 @@ static struct field_set_info super_fields[] = {
        { "hash_seed", &set_sb.s_hash_seed, 16, parse_uuid },
        { "def_hash_version", &set_sb.s_def_hash_version, 1, parse_hashalg },
        { "jnl_backup_type", &set_sb.s_jnl_backup_type, 1, parse_uint },
-       /* s_reserved_word_pad */
+       { "desc_size", &set_sb.s_desc_size, 2, parse_uint },
        { "default_mount_opts", &set_sb.s_default_mount_opts, 4, parse_uint },
        { "first_meta_bg", &set_sb.s_first_meta_bg, 4, parse_uint },
        { "mkfs_time", &set_sb.s_mkfs_time, 4, parse_time },
        { "jnl_blocks", &set_sb.s_jnl_blocks[0], 4, parse_uint, FLAG_ARRAY, 
          17 },
+       { "blocks_count_hi", &set_sb.s_blocks_count_hi, 4, parse_uint },
+       { "r_blocks_count_hi", &set_sb.s_r_blocks_count_hi, 4, parse_uint },
+       { "min_extra_isize", &set_sb.s_min_extra_isize, 2, parse_uint },
+       { "want_extra_isize", &set_sb.s_want_extra_isize, 2, parse_uint },
        { "flags", &set_sb.s_flags, 4, parse_uint },
+       { "raid_stride", &set_sb.s_raid_stride, 2, parse_uint },
+       { "min_extra_isize", &set_sb.s_min_extra_isize, 4, parse_uint },
+       { "mmp_interval", &set_sb.s_mmp_interval, 2, parse_uint },
+       { "mmp_block", &set_sb.s_mmp_block, 8, parse_uint },
+       { "raid_stripe_width", &set_sb.s_raid_stripe_width, 4, parse_uint },
        { 0, 0, 0, 0 }
 };
 
@@ -141,6 +155,7 @@ static struct field_set_info inode_fields[] = {
        { "generation", &set_inode.i_generation, 4, parse_uint },
        { "file_acl", &set_inode.i_file_acl, 4, parse_uint },
        { "dir_acl", &set_inode.i_dir_acl, 4, parse_uint },
+       { "size_high", &set_inode.i_size_high, 4, parse_uint },
        { "faddr", &set_inode.i_faddr, 4, parse_uint },
        { "blocks_hi", &set_inode.osd2.linux2.l_i_blocks_hi, 2, parse_uint },
        { "frag", &set_inode.osd2.hurd2.h_i_frag, 1, parse_uint },
@@ -226,9 +241,10 @@ static struct field_set_info *find_field(struct field_set_info *fields,
 
 static errcode_t parse_uint(struct field_set_info *info, char *arg)
 {
-       unsigned long   num;
+       unsigned long long num, limit;
        char *tmp;
        union {
+               __u64   *ptr64;
                __u32   *ptr32;
                __u16   *ptr16;
                __u8    *ptr8;
@@ -238,13 +254,23 @@ static errcode_t parse_uint(struct field_set_info *info, char *arg)
        if (info->flags & FLAG_ARRAY)
                u.ptr8 += array_idx * info->size;
 
-       num = strtoul(arg, &tmp, 0);
-       if (*tmp) {
+       errno = 0;
+       num = STRTOULL(arg, &tmp, 0);
+       if (*tmp || errno) {
                fprintf(stderr, "Couldn't parse '%s' for field %s.\n",
                        arg, info->name);
                return EINVAL;
        }
+       limit = ~0ULL >> ((8 - info->size) * 8);
+       if (num > limit) {
+               fprintf(stderr, "Value '%s' exceeds field %s maximum %llu.\n",
+                       arg, info->name, limit);
+               return EINVAL;
+       }
        switch (info->size) {
+       case 8:
+               *u.ptr64 = num;
+               break;
        case 4:
                *u.ptr32 = num;
                break;
index dad6147edf43f26a01852ebb34cd619afad539e8..b913b63138ebbe4b6f88e9b6047f429670facbf4 100644 (file)
@@ -10,6 +10,8 @@
  * %End-Header%
  */
 
+#define _XOPEN_SOURCE 600 /* for inclusion of strtoull */
+
 #include <stdio.h>
 #include <ctype.h>
 #include <string.h>
@@ -26,7 +28,6 @@
 #include "uuid/uuid.h"
 
 #ifdef HAVE_STRTOULL
-#define __USE_ISOC9X
 #define STRTOULL strtoull /* defined in stdlib.h if you try hard enough */
 #else
 /* FIXME: need to support real strtoull here */
@@ -319,8 +320,7 @@ static int parse_tag(blkid_cache cache, blkid_dev dev, char **cp)
        else if (!strcmp(name, "PRI"))
                dev->bid_pri = strtol(value, 0, 0);
        else if (!strcmp(name, "TIME"))
-               /* FIXME: need to parse a long long eventually */
-               dev->bid_time = strtol(value, 0, 0);
+               dev->bid_time = STRTOULL(value, 0, 0);
        else
                ret = blkid_set_tag(dev, name, value, strlen(value));
 
index 4dbdbbfe97f634b5349a32f445133eb595d195f9..1916655b3f9b6e423ad3b608275861e254acb9b5 100644 (file)
@@ -156,6 +156,8 @@ errcode_t ext2fs_initialize(const char *name, int flags,
        set_field(s_feature_incompat, 0);
        set_field(s_feature_ro_compat, 0);
        set_field(s_first_meta_bg, 0);
+       set_field(s_raid_stride, 0);            /* default stride size: 0 */
+       set_field(s_raid_stripe_width, 0);      /* default stripe width: 0 */
        set_field(s_flags, 0);
        if (super->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) {
                retval = EXT2_ET_UNSUPP_FEATURE;
index 1a68687b92c7884dbfff13f5af4efb3fa5d350b1..c7db2401daec4ca3301ba3f2e9357bbd6e68ea9e 100644 (file)
@@ -179,10 +179,23 @@ option is still accepted for backwards compatibility.   The
 following extended options are supported:
 .RS 1.2i
 .TP
-.BI stride= stripe-size
+.BI stride= stride-size
 Configure the filesystem for a RAID array with
-.I stripe-size
-filesystem blocks per stripe.
+.I stride-size
+filesystem blocks. This is the number of blocks read or written to disk
+before moving to next disk. This mostly affects placement of filesystem
+metadata like bitmaps at
+.BR mke2fs (2)
+time to avoid placing them on a single disk, which can hurt the performanace.
+It may also be used by block allocator.
+.TP
+.BI stripe-width= stripe-width
+Configure the filesystem for a RAID array with
+.I stripe-width
+filesystem blocks per stripe. This is typically be stride-size * N, where
+N is the number of data disks in the RAID (e.g. RAID 5 N+1, RAID 6 N+2).
+This allows the block allocator to prevent read-modify-write of the
+parity in a RAID stripe if possible when the data is written.
 .TP
 .BI resize= max-online-resize
 Reserve enough space so that the block group descriptor table can grow
index 290cc85bd7f947ed6956c871f89971d3cb895f6d..436fd4ae5b8fd59c43617ef4d4045f654c02e2e9 100644 (file)
@@ -773,7 +773,7 @@ static int set_os(struct ext2_super_block *sb, char *os)
 static void parse_extended_opts(struct ext2_super_block *param, 
                                const char *opts)
 {
-       char    *buf, *token, *next, *p, *arg;
+       char    *buf, *token, *next, *p, *arg, *badopt = "";
        int     len;
        int     r_usage = 0;
 
@@ -800,16 +800,32 @@ static void parse_extended_opts(struct ext2_super_block *param,
                if (strcmp(token, "stride") == 0) {
                        if (!arg) {
                                r_usage++;
+                               badopt = token;
                                continue;
                        }
-                       fs_stride = strtoul(arg, &p, 0);
-                       if (*p || (fs_stride == 0)) {
+                       param->s_raid_stride = strtoul(arg, &p, 0);
+                       if (*p || (param->s_raid_stride == 0)) {
                                fprintf(stderr,
                                        _("Invalid stride parameter: %s\n"),
                                        arg);
                                r_usage++;
                                continue;
                        }
+               } else if (strcmp(token, "stripe-width") == 0 ||
+                          strcmp(token, "stripe_width") == 0) {
+                       if (!arg) {
+                               r_usage++;
+                               badopt = token;
+                               continue;
+                       }
+                       param->s_raid_stripe_width = strtoul(arg, &p, 0);
+                       if (*p || (param->s_raid_stripe_width == 0)) {
+                               fprintf(stderr,
+                                       _("Invalid stripe-width parameter: %s\n"),
+                                       arg);
+                               r_usage++;
+                               continue;
+                       }
                } else if (!strcmp(token, "resize")) {
                        unsigned long resize, bpg, rsv_groups;
                        unsigned long group_desc_count, desc_blocks;
@@ -818,6 +834,7 @@ static void parse_extended_opts(struct ext2_super_block *param,
 
                        if (!arg) {
                                r_usage++;
+                               badopt = token;
                                continue;
                        }
 
@@ -868,21 +885,31 @@ static void parse_extended_opts(struct ext2_super_block *param,
                        }
                } else if (!strcmp(token, "test_fs")) {
                        param->s_flags |= EXT2_FLAGS_TEST_FILESYS;
-               } else
+               } else {
                        r_usage++;
+                       badopt = token;
+               }
        }
        if (r_usage) {
-               fprintf(stderr, _("\nBad options specified.\n\n"
+               fprintf(stderr, _("\nBad option(s) specified: %s\n\n"
                        "Extended options are separated by commas, "
                        "and may take an argument which\n"
                        "\tis set off by an equals ('=') sign.\n\n"
                        "Valid extended options are:\n"
-                       "\tstride=<stride length in blocks>\n"
-                       "\tresize=<resize maximum size in blocks>\n"
-                       "\ttest_fs\n"));
+                       "\tstride=<RAID per-disk data chunk in blocks>\n"
+                       "\tstripe-width=<RAID stride * data disks in blocks>\n"
+                       "\tresize=<resize maximum size in blocks>\n\n"
+                       "\ttest_fs\n"),
+                       badopt);
                free(buf);
                exit(1);
        }
+       if (param->s_raid_stride &&
+           (param->s_raid_stripe_width % param->s_raid_stride) != 0)
+               fprintf(stderr, _("\nWarning: RAID stripe-width %u not an even "
+                                 "multiple of stride %u.\n\n"),
+                       param->s_raid_stripe_width, param->s_raid_stride);
+
        free(buf);
 }      
 
@@ -1661,7 +1688,7 @@ int main (int argc, char *argv[])
                test_disk(fs, &bb_list);
 
        handle_bad_blocks(fs, bb_list);
-       fs->stride = fs->super->s_raid_stride = fs_stride;
+       fs->stride = fs_stride = fs->super->s_raid_stride;
        retval = ext2fs_allocate_tables(fs);
        if (retval) {
                com_err(program_name, retval,
index b348507484dff717c1c81837a40ab29e2fa7ce3e..e6880f0f5d4ffa1c8ee0f5f8c15346147d9e20a2 100644 (file)
@@ -65,6 +65,10 @@ tune2fs \- adjust tunable filesystem parameters on ext2/ext3 filesystems
 .I extended-options
 ]
 [
+.B \-E
+.I extended-options
+]
+[
 .B \-L
 .I volume-name
 ]
@@ -163,6 +167,31 @@ Clear the test_fs flag, indicating the filesystem should only be mounted
 using production-level filesystem code.
 .RE
 .TP
+.BI \-E " extended-options"
+Set extended options for the filesystem.  Extended options are comma
+separated, and may take an argument using the equals ('=') sign.
+The following extended options are supported:
+.RS 1.2i
+.TP
+.BI stride= stride-size
+Configure the filesystem for a RAID array with
+.I stride-size
+filesystem blocks. This is the number of blocks read or written to disk
+before moving to next disk. This mostly affects placement of filesystem
+metadata like bitmaps at
+.BR mke2fs (2)
+time to avoid placing them on a single disk, which can hurt the performanace.
+It may also be used by block allocator.
+.TP
+.BI stripe-width= stripe-width
+Configure the filesystem for a RAID array with
+.I stripe-width
+filesystem blocks per stripe. This is typically be stride-size * N, where
+N is the number of data disks in the RAID (e.g. RAID 5 N+1, RAID 6 N+2).
+This allows the block allocator to prevent read-modify-write of the
+parity in a RAID stripe if possible when the data is written.
+.RE
+.TP
 .B \-f
 Force the tune2fs operation to complete even in the face of errors.  This 
 option is useful when removing the 
index f7b61b67af920619a11b0479dbb31eeb6b3bdfba..2634ad81a9e8299d1ca6d98ff0e160da1d856d2d 100644 (file)
@@ -81,6 +81,8 @@ static unsigned short errors;
 static int open_flag;
 static char *features_cmd;
 static char *mntopts_cmd;
+static int stride, stripe_width;
+static int stride_set, stripe_width_set;
 static char *extended_cmd;
 
 int journal_size, journal_flags;
@@ -811,7 +813,36 @@ static void parse_extended_opts(ext2_filsys fs, const char *opts)
                        fs->super->s_flags &= ~EXT2_FLAGS_TEST_FILESYS;
                        printf("Clearing test filesystem flag\n");
                        ext2fs_mark_super_dirty(fs);
-               } else
+               } else if (strcmp(token, "stride") == 0) {
+                       if (!arg) {
+                               r_usage++;
+                               continue;
+                       }
+                       stride = strtoul(arg, &p, 0);
+                       if (*p || (stride == 0)) {
+                               fprintf(stderr,
+                                      _("Invalid RAID stride: %s\n"),
+                                       arg);
+                               r_usage++;
+                               continue;
+                       }
+                       stride_set = 1;
+               } else if (strcmp(token, "stripe-width") == 0 ||
+                          strcmp(token, "stripe_width") == 0) {
+                       if (!arg) {
+                               r_usage++;
+                               continue;
+                       }
+                       stripe_width = strtoul(arg, &p, 0);
+                       if (*p || (stripe_width == 0)) {
+                               fprintf(stderr,
+                                       _("Invalid RAID stripe-width: %s\n"),
+                                       arg);
+                               r_usage++;
+                               continue;
+                       }
+                       stripe_width_set = 1;
+               } else 
                        r_usage++;
        }
        if (r_usage) {
@@ -820,6 +851,8 @@ static void parse_extended_opts(ext2_filsys fs, const char *opts)
                        "and may take an argument which\n"
                        "\tis set off by an equals ('=') sign.\n\n"
                        "Valid extended options are:\n"
+                       "\tstride=<RAID per-disk chunk size in blocks>\n"
+                       "\tstripe-width=<RAID stride*data disks in blocks>\n"
                        "\ttest_fs\n"
                        "\t^test_fs\n"));
                free(buf);
@@ -1020,6 +1053,16 @@ int main (int argc, char ** argv)
 
        if (l_flag)
                list_super (sb);
+       if (stride_set) {
+               sb->s_raid_stride = stride;
+               ext2fs_mark_super_dirty(fs);
+               printf(_("Setting stride size to %d\n"), stride);
+       }
+       if (stripe_width_set) {
+               sb->s_raid_stripe_width = stripe_width;
+               ext2fs_mark_super_dirty(fs);
+               printf(_("Setting stripe width to %d"), stripe_width);
+       }
        remove_error_table(&et_ext2_error_table);
        return (ext2fs_close (fs) ? 1 : 0);
 }