* %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>
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 },
{ "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 }
};
{ "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 },
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;
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;
* %End-Header%
*/
+#define _XOPEN_SOURCE 600 /* for inclusion of strtoull */
+
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#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 */
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));
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;
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
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;
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;
if (!arg) {
r_usage++;
+ badopt = token;
continue;
}
}
} 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);
}
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,
.I extended-options
]
[
+.B \-E
+.I extended-options
+]
+[
.B \-L
.I volume-name
]
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
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;
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) {
"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);
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);
}