diff options
| author | Theodore Ts'o <tytso@mit.edu> | 2008-02-27 18:53:34 -0500 |
|---|---|---|
| committer | Theodore Ts'o <tytso@mit.edu> | 2008-02-27 18:53:34 -0500 |
| commit | a49670e64e28ac3b15e36cb6bd0a8135d3ecdbbb (patch) | |
| tree | 30f0ecd00942e15e097ca2c253131f4d3abce3a9 | |
| parent | e6bbc002c5a3d30df156d4f23bc93a7f2dbde3a1 (diff) | |
| parent | 4f9abdcb306ff515a8009a1e0fd35041688133c9 (diff) | |
| download | android_external_e2fsprogs-a49670e64e28ac3b15e36cb6bd0a8135d3ecdbbb.tar.gz android_external_e2fsprogs-a49670e64e28ac3b15e36cb6bd0a8135d3ecdbbb.tar.bz2 android_external_e2fsprogs-a49670e64e28ac3b15e36cb6bd0a8135d3ecdbbb.zip | |
Merge branch 'maint'
Conflicts:
lib/blkid/devname.c
lib/blkid/probe.c
misc/mke2fs.c
misc/tune2fs.c
| -rw-r--r-- | debian/libuuid1.postinst | 4 | ||||
| -rw-r--r-- | debugfs/debugfs.c | 7 | ||||
| -rw-r--r-- | e2fsck/Makefile.in | 12 | ||||
| -rw-r--r-- | e2fsck/badblocks.c | 1 | ||||
| -rw-r--r-- | e2fsck/e2fsck.8.in | 5 | ||||
| -rw-r--r-- | e2fsck/pass2.c | 9 | ||||
| -rw-r--r-- | e2fsck/unix.c | 49 | ||||
| -rw-r--r-- | lib/blkid/devname.c | 93 | ||||
| -rw-r--r-- | lib/blkid/probe.c | 82 | ||||
| -rw-r--r-- | lib/blkid/probe.h | 14 | ||||
| -rw-r--r-- | lib/e2p/e2p.h | 5 | ||||
| -rw-r--r-- | lib/e2p/feature.c | 47 | ||||
| -rw-r--r-- | lib/e2p/ls.c | 4 | ||||
| -rw-r--r-- | lib/ext2fs/alloc.c | 1 | ||||
| -rw-r--r-- | lib/ext2fs/ext2fs.h | 1 | ||||
| -rw-r--r-- | lib/ext2fs/openfs.c | 6 | ||||
| -rw-r--r-- | misc/dumpe2fs.8.in | 10 | ||||
| -rw-r--r-- | misc/dumpe2fs.c | 103 | ||||
| -rw-r--r-- | misc/fsck.c | 2 | ||||
| -rw-r--r-- | misc/mke2fs.8.in | 4 | ||||
| -rw-r--r-- | misc/mke2fs.c | 10 | ||||
| -rw-r--r-- | misc/tune2fs.8.in | 31 | ||||
| -rw-r--r-- | misc/tune2fs.c | 124 | ||||
| -rw-r--r-- | tests/m_raid_opt/expect.1 | 1 |
24 files changed, 452 insertions, 173 deletions
diff --git a/debian/libuuid1.postinst b/debian/libuuid1.postinst index 50a86183..cd5b093c 100644 --- a/debian/libuuid1.postinst +++ b/debian/libuuid1.postinst @@ -1,9 +1,9 @@ #!/bin/sh set -e -groupadd -f -K GID_MIN=1 -K GID_MAX=999 libuuid +groupadd -f -K GID_MIN=100 -K GID_MAX=999 libuuid if ! grep -q libuuid /etc/passwd; then - useradd -d /var/lib/libuuid -K UID_MIN=1 -K UID_MAX=499 -g libuuid libuuid + useradd -d /var/lib/libuuid -K UID_MIN=100 -K UID_MAX=999 -g libuuid libuuid fi mkdir -p /var/lib/libuuid chown libuuid:libuuid /var/lib/libuuid diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c index b0a7ef3f..c4da2a20 100644 --- a/debugfs/debugfs.c +++ b/debugfs/debugfs.c @@ -1152,7 +1152,7 @@ void do_unlink(int argc, char *argv[]) void do_find_free_block(int argc, char *argv[]) { - blk_t free_blk, goal; + blk_t free_blk, goal, first_free = 0; int count; errcode_t retval; char *tmp; @@ -1188,6 +1188,11 @@ void do_find_free_block(int argc, char *argv[]) while (count-- > 0) { retval = ext2fs_new_block(current_fs, free_blk + 1, 0, &free_blk); + if (first_free) { + if (first_free == free_blk) + break; + } else + first_free = free_blk; if (retval) { com_err("ext2fs_new_block", retval, 0); return; diff --git a/e2fsck/Makefile.in b/e2fsck/Makefile.in index f65ca6c8..ed22d7aa 100644 --- a/e2fsck/Makefile.in +++ b/e2fsck/Makefile.in @@ -17,18 +17,18 @@ MANPAGES= e2fsck.8 FMANPAGES= e2fsck.conf.5 XTRA_CFLAGS= -DRESOURCE_TRACK -I. -LIBS= $(LIBEXT2FS) $(LIBCOM_ERR) $(LIBBLKID) $(LIBUUID) $(LIBINTL) -DEPLIBS= $(LIBEXT2FS) $(LIBCOM_ERR) $(DEPLIBBLKID) $(DEPLIBUUID) +LIBS= $(LIBEXT2FS) $(LIBCOM_ERR) $(LIBBLKID) $(LIBUUID) $(LIBINTL) $(LIBE2P) +DEPLIBS= $(LIBEXT2FS) $(LIBCOM_ERR) $(DEPLIBBLKID) $(DEPLIBUUID) $(DEPLIBE2P) STATIC_LIBS= $(STATIC_LIBEXT2FS) $(STATIC_LIBCOM_ERR) $(STATIC_LIBBLKID) \ - $(STATIC_LIBUUID) $(LIBINTL) + $(STATIC_LIBUUID) $(LIBINTL) $(STATIC_LIBE2P) STATIC_DEPLIBS= $(STATIC_LIBEXT2FS) $(STATIC_LIBCOM_ERR) $(DEPSTATIC_LIBBLKID) \ - $(DEPSTATIC_LIBUUID) + $(DEPSTATIC_LIBUUID) $(DEPSTATIC_LIBE2P) PROFILED_LIBS= $(PROFILED_LIBEXT2FS) $(PROFILED_LIBCOM_ERR) \ - $(PROFILED_LIBBLKID) $(PROFILED_LIBUUID) $(LIBINTL) + $(PROFILED_LIBBLKID) $(PROFILED_LIBUUID) $(PROFILED_LIBE2P) $(LIBINTL) PROFILED_DEPLIBS= $(PROFILED_LIBEXT2FS) $(PROFILED_LIBCOM_ERR) \ - $(DEPPROFILED_LIBBLKID) $(DEPPROFILED_LIBUUID) + $(DEPPROFILED_LIBBLKID) $(DEPPROFILED_LIBUUID) $(DEPPROFILED_LIBE2P) COMPILE_ET=$(top_builddir)/lib/et/compile_et --build-tree diff --git a/e2fsck/badblocks.c b/e2fsck/badblocks.c index 36dc208e..72f88aa7 100644 --- a/e2fsck/badblocks.c +++ b/e2fsck/badblocks.c @@ -97,6 +97,7 @@ void read_bad_blocks_file(e2fsck_t ctx, const char *bad_blocks_file, /* * Finally, update the bad blocks from the bad_block_map */ + printf("%s: Updating bad block inode.\n", ctx->device_name); retval = ext2fs_update_bb_inode(fs, bb_list); if (retval) { com_err("ext2fs_update_bb_inode", retval, diff --git a/e2fsck/e2fsck.8.in b/e2fsck/e2fsck.8.in index df6fd288..cd110b3b 100644 --- a/e2fsck/e2fsck.8.in +++ b/e2fsck/e2fsck.8.in @@ -167,6 +167,11 @@ and need to be rebuilt. The option forces all directories in the filesystem to be optimized. This can sometimes make them a little smaller and slightly faster to search, but in practice, you should rarely need to use this option. +.IP +The +.B \-D +option will detect directory entries with duplicate names in a single +directory, which e2fsck normally does not enforce for performance reasons. .TP .BI \-E " extended_options" Set e2fsck extended options. Extended options are comma diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c index 011dba0e..94d94057 100644 --- a/e2fsck/pass2.c +++ b/e2fsck/pass2.c @@ -275,15 +275,6 @@ void e2fsck_pass2(e2fsck_t ctx) ext2fs_update_dynamic_rev(fs); ext2fs_mark_super_dirty(fs); } - } else if (!ctx->large_files && - (sb->s_feature_ro_compat & - EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) { - if (fs->flags & EXT2_FLAG_RW) { - sb->s_feature_ro_compat &= - ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE; - fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY; - ext2fs_mark_super_dirty(fs); - } } #ifdef RESOURCE_TRACK diff --git a/e2fsck/unix.c b/e2fsck/unix.c index 433ae8e2..3a5cf471 100644 --- a/e2fsck/unix.c +++ b/e2fsck/unix.c @@ -858,6 +858,7 @@ int main (int argc, char *argv[]) int flags, run_result; int journal_size; int sysval, sys_page_size = 4096; + __u32 features[3]; clear_problem_context(&pctx); #ifdef MTRACE @@ -919,7 +920,7 @@ restart: #else io_ptr = unix_io_manager; #endif - flags = 0; + flags = EXT2_FLAG_NOFREE_ON_ERROR; if ((ctx->options & E2F_OPT_READONLY) == 0) flags |= EXT2_FLAG_RW; if ((ctx->mount_flags & EXT2_MF_MOUNTED) == 0) @@ -948,6 +949,10 @@ restart: ((retval == EXT2_ET_BAD_MAGIC) || (retval == EXT2_ET_CORRUPT_SUPERBLOCK) || ((retval == 0) && ext2fs_check_desc(fs)))) { + if (fs->flags & EXT2_FLAG_NOFREE_ON_ERROR) { + ext2fs_free(fs); + fs = NULL; + } if (!fs || (fs->group_desc_count > 1)) { printf(_("%s: %s trying backup blocks...\n"), ctx->program_name, @@ -960,6 +965,19 @@ restart: goto restart; } } + if (((retval == EXT2_ET_UNSUPP_FEATURE) || + (retval == EXT2_ET_RO_UNSUPP_FEATURE)) && + fs && fs->super) { + sb = fs->super; + features[0] = (sb->s_feature_compat & + ~EXT2_LIB_FEATURE_COMPAT_SUPP); + features[1] = (sb->s_feature_incompat & + ~EXT2_LIB_FEATURE_INCOMPAT_SUPP); + features[2] = (sb->s_feature_ro_compat & + ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP); + if (features[0] || features[1] || features[2]) + goto print_unsupp_features; + } if (retval) { if (orig_retval) retval = orig_retval; @@ -1115,15 +1133,26 @@ restart: * Check for compatibility with the feature sets. We need to * be more stringent than ext2fs_open(). */ - if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) || - (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) { - com_err(ctx->program_name, EXT2_ET_UNSUPP_FEATURE, - "(%s)", ctx->device_name); - goto get_newer; - } - if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) { - com_err(ctx->program_name, EXT2_ET_RO_UNSUPP_FEATURE, - "(%s)", ctx->device_name); + features[0] = sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP; + features[1] = sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP; + features[2] = (sb->s_feature_ro_compat & + ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP); +print_unsupp_features: + if (features[0] || features[1] || features[2]) { + int i, j; + __u32 *mask = features, m; + + fprintf(stderr, _("%s has unsupported feature(s):"), + ctx->filesystem_name); + + for (i=0; i <3; i++,mask++) { + for (j=0,m=1; j < 32; j++, m<<=1) { + if (*mask & m) + fprintf(stderr, " %s", + e2p_feature2string(i, m)); + } + } + putc('\n', stderr); goto get_newer; } #ifdef ENABLE_COMPRESSION diff --git a/lib/blkid/devname.c b/lib/blkid/devname.c index 0bcba448..29cde8e7 100644 --- a/lib/blkid/devname.c +++ b/lib/blkid/devname.c @@ -171,37 +171,42 @@ static int dm_device_has_dep(const dev_t dev, const char *name) struct dm_deps *deps; struct dm_info info; unsigned int i; + int ret = 0; task = dm_task_create(DM_DEVICE_DEPS); if (!task) - return 0; + goto out; - dm_task_set_name(task, name); - dm_task_run(task); - dm_task_get_info(task, &info); + if (!dm_task_set_name(task, name)) + goto out; - if (!info.exists) { - dm_task_destroy(task); - return 0; - } + if (!dm_task_run(task)) + goto out; + if (!dm_task_get_info(task, &info)) + goto out; + + if (!info.exists) + goto out; + deps = dm_task_get_deps(task); - if (!deps || deps->count == 0) { - dm_task_destroy(task); - return 0; - } + if (!deps || deps->count == 0) + goto out; for (i = 0; i < deps->count; i++) { dev_t dep_dev = deps->device[i]; if (dev == dep_dev) { - dm_task_destroy(task); - return 1; + ret = 1; + goto out; } } - dm_task_destroy(task); - return 0; +out: + if (task) + dm_task_destroy(task); + + return ret; } static int dm_device_is_leaf(const dev_t dev) @@ -214,15 +219,16 @@ static int dm_device_is_leaf(const dev_t dev) dm_log_init(dm_quiet_log); task = dm_task_create(DM_DEVICE_LIST); if (!task) - return 1; + goto out; + dm_log_init(0); - dm_task_run(task); + if (!dm_task_run(task)) + goto out; + names = dm_task_get_names(task); - if (!names || !names->dev) { - dm_task_destroy(task); - return 1; - } + if (!names || !names->dev) + goto out; n = 0; do { @@ -234,7 +240,9 @@ static int dm_device_is_leaf(const dev_t dev) next = names->next; } while (next); - dm_task_destroy(task); +out: + if (task) + dm_task_destroy(task); return ret; } @@ -247,20 +255,25 @@ static dev_t dm_get_devno(const char *name) task = dm_task_create(DM_DEVICE_INFO); if (!task) - return ret; + goto out; - dm_task_set_name(task, name); - dm_task_run(task); - dm_task_get_info(task, &info); + if (!dm_task_set_name(task, name)) + goto out; - if (!info.exists) { - dm_task_destroy(task); - return ret; - } + if (!dm_task_run(task)) + goto out; + + if (!dm_task_get_info(task, &info)) + goto out; + + if (!info.exists) + goto out; ret = makedev(info.major, info.minor); - dm_task_destroy(task); +out: + if (task) + dm_task_destroy(task); return ret; } @@ -275,15 +288,15 @@ static void dm_probe_all(blkid_cache cache, int only_if_new) dm_log_init(dm_quiet_log); task = dm_task_create(DM_DEVICE_LIST); if (!task) - return; + goto out; dm_log_init(0); - dm_task_run(task); + if (!dm_task_run(task)) + goto out; + names = dm_task_get_names(task); - if (!names || !names->dev) { - dm_task_destroy(task); - return; - } + if (!names || !names->dev) + goto out; n = 0; do { @@ -311,7 +324,9 @@ try_next: next = names->next; } while (next); - dm_task_destroy(task); +out: + if (task) + dm_task_destroy(task); } #endif /* HAVE_DEVMAPPER */ diff --git a/lib/blkid/probe.c b/lib/blkid/probe.c index 04527eaf..10e018a9 100644 --- a/lib/blkid/probe.c +++ b/lib/blkid/probe.c @@ -18,6 +18,7 @@ #include <stdlib.h> #include <unistd.h> #include <fcntl.h> +#include <ctype.h> #include <sys/types.h> #ifdef HAVE_SYS_STAT_H #include <sys/stat.h> @@ -163,7 +164,7 @@ static void get_ext2_info(blkid_dev dev, struct blkid_magic *id, * Check to see if a filesystem is in /proc/filesystems. * Returns 1 if found, 0 if not */ -int fs_proc_check(const char *fs_name) +static int fs_proc_check(const char *fs_name) { FILE *f; char buf[80], *cp, *t; @@ -200,7 +201,7 @@ int fs_proc_check(const char *fs_name) * Check to see if a filesystem is available as a module * Returns 1 if found, 0 if not */ -int check_for_modules(const char *fs_name) +static int check_for_modules(const char *fs_name) { struct utsname uts; FILE *f; @@ -236,7 +237,7 @@ int check_for_modules(const char *fs_name) return (0); } -static int system_supports_ext4() +static int system_supports_ext4(void) { static time_t last_check = 0; static int ret = -1; @@ -249,7 +250,7 @@ static int system_supports_ext4() return ret; } -static int system_supports_ext4dev() +static int system_supports_ext4dev(void) { static time_t last_check = 0; static int ret = -1; @@ -1008,7 +1009,7 @@ static int probe_gfs2(struct blkid_probe *probe, return 1; } -static int probe_hfsplus(struct blkid_probe *probe, +static int probe_hfsplus(struct blkid_probe *probe __BLKID_ATTR((unused)), struct blkid_magic *id __BLKID_ATTR((unused)), unsigned char *buf) { @@ -1021,6 +1022,73 @@ static int probe_hfsplus(struct blkid_probe *probe, return 1; } +#define LVM2_LABEL_SIZE 512 +static unsigned int lvm2_calc_crc(const void *buf, uint size) +{ + static const uint crctab[] = { + 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, + 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, + 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, + 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c + }; + uint i, crc = 0xf597a6cf; + const __u8 *data = (const __u8 *) buf; + + for (i = 0; i < size; i++) { + crc ^= *data++; + crc = (crc >> 4) ^ crctab[crc & 0xf]; + crc = (crc >> 4) ^ crctab[crc & 0xf]; + } + return crc; +} + +static int probe_lvm2(struct blkid_probe *probe, + struct blkid_magic *id __BLKID_ATTR((unused)), + unsigned char *buf) +{ + int sector = (id->bim_kboff) << 1;; + struct lvm2_pv_label_header *label; + label = (struct lvm2_pv_label_header *)buf; + char *p, *q, uuid[40]; + unsigned int i, b; + + /* buf is at 0k or 1k offset; find label inside */ + if (memcmp(buf, "LABELONE", 8) == 0) { + label = (struct lvm2_pv_label_header *)buf; + } else if (memcmp(buf + 512, "LABELONE", 8) == 0) { + label = (struct lvm2_pv_label_header *)(buf + 512); + sector++; + } else { + return 1; + } + + if (blkid_le64(label->sector_xl) != (unsigned) sector) { + DBG(DEBUG_PROBE, + printf("LVM2: label for sector %llu found at sector %d\n", + blkid_le64(label->sector_xl), sector)); + return 1; + } + + if (lvm2_calc_crc(&label->offset_xl, LVM2_LABEL_SIZE - + ((char *)&label->offset_xl - (char *)label)) != + blkid_le32(label->crc_xl)) { + DBG(DEBUG_PROBE, + printf("LVM2: label checksum incorrect at sector %d\n", + sector)); + return 1; + } + + for (i=0, b=1, p=uuid, q= (char *) label->pv_uuid; i <= 32; + i++, b <<= 1) { + if (b & 0x4444440) + *p++ = '-'; + *p++ = *q++; + } + + blkid_set_tag(probe->dev, "UUID", uuid, LVM2_ID_LEN+6); + + return 0; +} /* * BLKID_BLK_OFFS is at least as large as the highest bim_kboff defined * in the type_array table below + bim_kbalign. @@ -1114,6 +1182,10 @@ static struct blkid_magic type_array[] = { { "crypt_LUKS", 0, 0, 6, "LUKS\xba\xbe", probe_luks }, { "squashfs", 0, 0, 4, "sqsh", 0 }, { "squashfs", 0, 0, 4, "hsqs", 0 }, + { "lvm2pv", 0, 0x218, 8, "LVM2 001", probe_lvm2 }, + { "lvm2pv", 0, 0x018, 8, "LVM2 001", probe_lvm2 }, + { "lvm2pv", 1, 0x018, 8, "LVM2 001", probe_lvm2 }, + { "lvm2pv", 1, 0x218, 8, "LVM2 001", probe_lvm2 }, { NULL, 0, 0, 0, NULL, NULL } }; diff --git a/lib/blkid/probe.h b/lib/blkid/probe.h index acfe1195..b3cc26b9 100644 --- a/lib/blkid/probe.h +++ b/lib/blkid/probe.h @@ -531,6 +531,20 @@ struct hfs_mdb { __u16 embed_blockcount; } __attribute__((packed)); +/* this is lvm's label_header & pv_header combined. */ + +#define LVM2_ID_LEN 32 + +struct lvm2_pv_label_header { + /* label_header */ + __u8 id[8]; /* LABELONE */ + __u64 sector_xl; /* Sector number of this label */ + __u32 crc_xl; /* From next field to end of sector */ + __u32 offset_xl; /* Offset from start of struct to contents */ + __u8 type[8]; /* LVM2 001 */ + /* pv_header */ + __u8 pv_uuid[LVM2_ID_LEN]; +} __attribute__ ((packed)); /* * Byte swap functions diff --git a/lib/e2p/e2p.h b/lib/e2p/e2p.h index 5d9131fd..06e2120d 100644 --- a/lib/e2p/e2p.h +++ b/lib/e2p/e2p.h @@ -7,7 +7,9 @@ #define E2P_FEATURE_COMPAT 0 #define E2P_FEATURE_INCOMPAT 1 #define E2P_FEATURE_RO_INCOMPAT 2 +#define E2P_FEATURE_TYPE_MASK 0x03 +#define E2P_FEATURE_NEGATE_FLAG 0x80 /* `options' for print_flags() */ @@ -34,6 +36,9 @@ int setversion (int fd, unsigned long version); const char *e2p_feature2string(int compat, unsigned int mask); int e2p_string2feature(char *string, int *compat, unsigned int *mask); int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array); +int e2p_edit_feature2(const char *str, __u32 *compat_array, __u32 *ok_array, + __u32 *clear_ok_array, int *type_err, + unsigned int *mask_err); int e2p_is_null_uuid(void *uu); void e2p_uuid_to_str(void *uu, char *out); diff --git a/lib/e2p/feature.c b/lib/e2p/feature.c index 4bf56301..fc6052c1 100644 --- a/lib/e2p/feature.c +++ b/lib/e2p/feature.c @@ -163,9 +163,12 @@ static char *skip_over_word(char *cp) /* * Edit a feature set array as requested by the user. The ok_array, * if set, allows the application to limit what features the user is - * allowed to set or clear using this function. + * allowed to set or clear using this function. If clear_ok_array is set, + * then use it tell whether or not it is OK to clear a filesystem feature. */ -int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array) +int e2p_edit_feature2(const char *str, __u32 *compat_array, __u32 *ok_array, + __u32 *clear_ok_array, int *type_err, + unsigned int *mask_err) { char *cp, *buf, *next; int neg; @@ -173,6 +176,14 @@ int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array) int compat_type; int rc = 0; + if (!clear_ok_array) + clear_ok_array = ok_array; + + if (type_err) + *type_err = 0; + if (mask_err) + *mask_err = 0; + buf = malloc(strlen(str)+1); if (!buf) return 1; @@ -207,15 +218,35 @@ int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array) rc = 1; break; } - if (ok_array && !(ok_array[compat_type] & mask)) { - rc = 1; - break; - } - if (neg) + if (neg) { + if (clear_ok_array && + !(clear_ok_array[compat_type] & mask)) { + rc = 1; + if (type_err) + *type_err = (compat_type | + E2P_FEATURE_NEGATE_FLAG); + if (mask_err) + *mask_err = mask; + break; + } compat_array[compat_type] &= ~mask; - else + } else { + if (ok_array && !(ok_array[compat_type] & mask)) { + rc = 1; + if (type_err) + *type_err = compat_type; + if (mask_err) + *mask_err = mask; + break; + } compat_array[compat_type] |= mask; + } } free(buf); return rc; } + +int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array) +{ + return e2p_edit_feature2(str, compat_array, ok_array, 0, 0, 0); +} diff --git a/lib/e2p/ls.c b/lib/e2p/ls.c index 23c33a58..d249f88b 100644 --- a/lib/e2p/ls.c +++ b/lib/e2p/ls.c @@ -234,10 +234,10 @@ void list_super2(struct ext2_super_block * sb, FILE *f) 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) - fprintf(f, "Raid stride: %u\n", + fprintf(f, "RAID stride: %u\n", sb->s_raid_stride); if (sb->s_raid_stripe_width) - fprintf(f, "Raid stripe width: %u\n", + fprintf(f, "RAID stripe width: %u\n", sb->s_raid_stripe_width); if (sb->s_first_meta_bg) fprintf(f, "First meta block group: %u\n", diff --git a/lib/ext2fs/alloc.c b/lib/ext2fs/alloc.c index 7385123b..65f3ea1c 100644 --- a/lib/ext2fs/alloc.c +++ b/lib/ext2fs/alloc.c @@ -134,7 +134,6 @@ errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal, ext2fs_block_alloc_stats(fs, block, +1); *ret = block; - return 0; fail: if (buf) diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h index 4fea613b..b7de2301 100644 --- a/lib/ext2fs/ext2fs.h +++ b/lib/ext2fs/ext2fs.h @@ -171,6 +171,7 @@ typedef struct ext2_file *ext2_file_t; #define EXT2_FLAG_IMAGE_FILE 0x2000 #define EXT2_FLAG_EXCLUSIVE 0x4000 #define EXT2_FLAG_SOFTSUPP_FEATURES 0x8000 +#define EXT2_FLAG_NOFREE_ON_ERROR 0x10000 /* * Special flag in the ext2 inode i_flag field that means that this is diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c index cb683eea..a6a82174 100644 --- a/lib/ext2fs/openfs.c +++ b/lib/ext2fs/openfs.c @@ -303,10 +303,14 @@ errcode_t ext2fs_open2(const char *name, const char *io_options, fs->stride = fs->super->s_raid_stride; + fs->flags &= ~EXT2_FLAG_NOFREE_ON_ERROR; *ret_fs = fs; return 0; cleanup: - ext2fs_free(fs); + if (flags & EXT2_FLAG_NOFREE_ON_ERROR) + *ret_fs = fs; + else + ext2fs_free(fs); return retval; } diff --git a/misc/dumpe2fs.8.in b/misc/dumpe2fs.8.in index 6d57d23f..79cf8638 100644 --- a/misc/dumpe2fs.8.in +++ b/misc/dumpe2fs.8.in @@ -11,12 +11,10 @@ dumpe2fs \- dump ext2/ext3 filesystem information .B \-bfhixV ] [ -.B \-ob -.I superblock +.B \-o superblock=\fIsuperblock ] [ -.B \-oB -.I blocksize +.B \-o blocksize=\fIblocksize ] .I device .SH DESCRIPTION @@ -34,14 +32,14 @@ program for the BSD Fast File System. .B \-b print the blocks which are reserved as bad in the filesystem. .TP -.BI \-ob " superblock" +.B \-o superblock=\fIsuperblock use the block .I superblock when examining the filesystem. This option is not usually needed except by a filesystem wizard who is examining the remains of a very badly corrupted filesystem. .TP -.BI \-oB " blocksize" +.B \-o blocksize=\fIblocksize use blocks of .I blocksize bytes when examining the filesystem. diff --git a/misc/dumpe2fs.c b/misc/dumpe2fs.c index d4d95bb5..f6e7972e 100644 --- a/misc/dumpe2fs.c +++ b/misc/dumpe2fs.c @@ -333,6 +333,83 @@ static void print_journal_information(ext2_filsys fs) } } +static void parse_extended_opts(const char *opts, blk_t *superblock, + int *blocksize) +{ + char *buf, *token, *next, *p, *arg, *badopt = ""; + int len; + int usage = 0; + + len = strlen(opts); + buf = malloc(len+1); + if (!buf) { + fprintf(stderr, + _("Couldn't allocate memory to parse options!\n")); + exit(1); + } + strcpy(buf, opts); + for (token = buf; token && *token; token = next) { + p = strchr(token, ','); + next = 0; + if (p) { + *p = 0; + next = p+1; + } + arg = strchr(token, '='); + if (arg) { + *arg = 0; + arg++; + } + if (strcmp(token, "superblock") == 0 || + strcmp(token, "sb") == 0) { + if (!arg) { + usage++; + badopt = token; + continue; + } + *superblock = strtoul(arg, &p, 0); + if (*p) { + fprintf(stderr, + _("Invalid superblock parameter: %s\n"), + arg); + usage++; + continue; + } + } else if (strcmp(token, "blocksize") == 0 || + strcmp(token, "bs") == 0) { + if (!arg) { + usage++; + badopt = token; + continue; + } + *blocksize = strtoul(arg, &p, 0); + if (*p) { + fprintf(stderr, + _("Invalid blocksize parameter: %s\n"), + arg); + usage++; + continue; + } + } else { + usage++; + badopt = token; + } + } + if (usage) { + fprintf(stderr, _("\nBad extended 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" + "\tsuperblock=<superblock number>\n" + "\tblocksize=<blocksize>\n"), + badopt); + free(buf); + exit(1); + } + free(buf); +} + int main (int argc, char ** argv) { errcode_t retval; @@ -373,12 +450,8 @@ int main (int argc, char ** argv) image_dump++; break; case 'o': - if (optarg[0] == 'b') - use_superblock = atoi(optarg+1); - else if (optarg[0] == 'B') - use_blocksize = atoi(optarg+1); - else - usage(); + parse_extended_opts(optarg, &use_superblock, + &use_blocksize); break; case 'V': /* Print version number and exit */ @@ -395,16 +468,26 @@ int main (int argc, char ** argv) if (optind > argc - 1) usage(); device_name = argv[optind++]; - if (use_superblock && !use_blocksize) - use_blocksize = 1024; flags = EXT2_FLAG_JOURNAL_DEV_OK | EXT2_FLAG_SOFTSUPP_FEATURES; if (force) flags |= EXT2_FLAG_FORCE; if (image_dump) flags |= EXT2_FLAG_IMAGE_FILE; - retval = ext2fs_open (device_name, flags, use_superblock, - use_blocksize, unix_io_manager, &fs); + if (use_superblock && !use_blocksize) { + for (use_blocksize = EXT2_MIN_BLOCK_SIZE; + use_blocksize <= EXT2_MAX_BLOCK_SIZE; + use_blocksize *= 2) { + retval = ext2fs_open (device_name, flags, + use_superblock, + use_blocksize, unix_io_manager, + &fs); + if (!retval) + break; + } + } else + retval = ext2fs_open (device_name, flags, use_superblock, + use_blocksize, unix_io_manager, &fs); if (retval) { com_err (program_name, retval, _("while trying to open %s"), device_name); diff --git a/misc/fsck.c b/misc/fsck.c index 24c095a4..db572b1e 100644 --- a/misc/fsck.c +++ b/misc/fsck.c @@ -364,7 +364,7 @@ static void load_fs_info(const char *filename) fclose(f); - if (old_fstab) { + if (old_fstab && filesys_info) { fputs(_("\007\007\007" "WARNING: Your /etc/fstab does not contain the fsck passno\n" " field. I will kludge around things for you, but you\n" diff --git a/misc/mke2fs.8.in b/misc/mke2fs.8.in index 65c42bf3..6b394a5d 100644 --- a/misc/mke2fs.8.in +++ b/misc/mke2fs.8.in @@ -415,6 +415,10 @@ prefix the feature name with a caret ('^') character. The pseudo-filesystem feature "none" will clear all filesystem features. .RS 1.2i .TP +.B large_file +Filesystem can contain files that are greater than 2GB. (Modern kernels +set this feature automatically when a file > 2GB is created.) +.TP .B dir_index Use hashed b-trees to speed up lookups in large directories. .TP diff --git a/misc/mke2fs.c b/misc/mke2fs.c index a5eb4ee5..d6798788 100644 --- a/misc/mke2fs.c +++ b/misc/mke2fs.c @@ -897,17 +897,21 @@ static void parse_extended_opts(struct ext2_super_block *param, } static __u32 ok_features[3] = { + /* Compat */ EXT3_FEATURE_COMPAT_HAS_JOURNAL | EXT2_FEATURE_COMPAT_RESIZE_INODE | EXT2_FEATURE_COMPAT_DIR_INDEX | EXT2_FEATURE_COMPAT_LAZY_BG | - EXT2_FEATURE_COMPAT_EXT_ATTR, /* Compat */ - EXT2_FEATURE_INCOMPAT_FILETYPE| /* Incompat */ + EXT2_FEATURE_COMPAT_EXT_ATTR, + /* Incompat */ + EXT2_FEATURE_INCOMPAT_FILETYPE| EXT3_FEATURE_INCOMPAT_EXTENTS| EXT3_FEATURE_INCOMPAT_JOURNAL_DEV| EXT2_FEATURE_INCOMPAT_META_BG| EXT4_FEATURE_INCOMPAT_FLEX_BG, - EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER /* R/O compat */ + /* R/O compat */ + EXT2_FEATURE_RO_COMPAT_LARGE_FILE| + EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER }; diff --git a/misc/tune2fs.8.in b/misc/tune2fs.8.in index 435556f4..b37e99d7 100644 --- a/misc/tune2fs.8.in +++ b/misc/tune2fs.8.in @@ -415,6 +415,10 @@ The following filesystem features can be set or cleared using .BR tune2fs : .RS 1.2i .TP +.B large_file +Filesystem can contain files that are greater than 2GB. (Modern kernels +set this feature automatically when a file > 2GB is created.) +.TP .B dir_index Use hashed b-trees to speed up lookups in large directories. .TP @@ -429,12 +433,19 @@ option. .TP .B sparse_super Limit the number of backup superblocks to save space on large filesystems. +.TP +.B resize_inode +Reserve space so the block group descriptor table may grow in the +future. +.B Tune2fs +only supports clearing this filesystem feature. .RE .IP After setting or clearing -.B sparse_super -and -.B filetype +.BR sparse_super , +.BR filetype , +or +.B resize_inode filesystem features, .BR e2fsck (8) must be run on the filesystem to return the filesystem to a consistent state. @@ -446,12 +457,6 @@ if necessary. After setting the feature, .B e2fsck -D can be run to convert existing directories to the hashed B-tree format. -.IP -.B Warning: -Linux kernels before 2.0.39 and many 2.1 series kernels do not support -the filesystems that use any of these features. -Enabling certain filesystem features may prevent the filesystem from -being mounted by kernels which do not support those features. .TP .BI \-r " reserved-blocks-count" Set the number of reserved filesystem blocks. @@ -461,14 +466,6 @@ Turn the sparse super feature off or on. Turning this feature on saves space on really big filesystems. This is the same as using the .B "\-O sparse_super" option. -.IP -.B Warning: -Linux kernels before 2.0.39 do not support this feature. Neither do -all Linux 2.1 kernels; please don't use this unless you know what you're -doing! You need to run -.BR e2fsck (8) -on the filesystem after changing this feature in order to have a valid -filesystem. .TP .BI \-T " time-last-checked" Set the time the filesystem was last checked using diff --git a/misc/tune2fs.c b/misc/tune2fs.c index d63148b2..fae5875b 100644 --- a/misc/tune2fs.c +++ b/misc/tune2fs.c @@ -108,12 +108,29 @@ static void usage(void) } static __u32 ok_features[3] = { + /* Compat */ EXT3_FEATURE_COMPAT_HAS_JOURNAL | - EXT2_FEATURE_COMPAT_DIR_INDEX, /* Compat */ - EXT2_FEATURE_INCOMPAT_FILETYPE| /* Incompat */ - EXT3_FEATURE_INCOMPAT_EXTENTS| + EXT2_FEATURE_COMPAT_DIR_INDEX, + /* Incompat */ + EXT2_FEATURE_INCOMPAT_FILETYPE | + EXT3_FEATURE_INCOMPAT_EXTENTS | EXT4_FEATURE_INCOMPAT_FLEX_BG, - EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER /* R/O compat */ + /* R/O compat */ + EXT2_FEATURE_RO_COMPAT_LARGE_FILE | + EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER +}; + +static __u32 clear_ok_features[3] = { + /* Compat */ + EXT3_FEATURE_COMPAT_HAS_JOURNAL | + EXT2_FEATURE_COMPAT_RESIZE_INODE | + EXT2_FEATURE_COMPAT_DIR_INDEX, + /* Incompat */ + EXT2_FEATURE_INCOMPAT_FILETYPE | + EXT4_FEATURE_INCOMPAT_FLEX_BG, + /* R/O compat */ + EXT2_FEATURE_RO_COMPAT_LARGE_FILE | + EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER }; /* @@ -297,47 +314,44 @@ static void update_mntopts(ext2_filsys fs, char *mntopts) */ static void update_feature_set(ext2_filsys fs, char *features) { - int sparse, old_sparse, filetype, old_filetype; - int journal, old_journal, dxdir, old_dxdir; - int flex_bg, old_flex_bg, extents, old_extents; struct ext2_super_block *sb= fs->super; __u32 old_compat, old_incompat, old_ro_compat; + __u32 old_features[3]; + int type_err; + unsigned int mask_err; - old_compat = sb->s_feature_compat; - old_ro_compat = sb->s_feature_ro_compat; - old_incompat = sb->s_feature_incompat; +#define FEATURE_ON(type, mask) (!(old_features[(type)] & (mask)) && \ + ((&sb->s_feature_compat)[(type)] & (mask))) +#define FEATURE_OFF(type, mask) ((old_features[(type)] & (mask)) && \ + !((&sb->s_feature_compat)[(type)] & (mask))) +#define FEATURE_CHANGED(type, mask) ((mask) & \ + (old_features[(type)] ^ (&sb->s_feature_compat)[(type)])) - old_sparse = sb->s_feature_ro_compat & - EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER; - old_filetype = sb->s_feature_incompat & - EXT2_FEATURE_INCOMPAT_FILETYPE; - old_extents = sb->s_feature_incompat & - EXT3_FEATURE_INCOMPAT_EXTENTS; - old_flex_bg = sb->s_feature_incompat & - EXT4_FEATURE_INCOMPAT_FLEX_BG; - old_journal = sb->s_feature_compat & - EXT3_FEATURE_COMPAT_HAS_JOURNAL; - old_dxdir = sb->s_feature_compat & - EXT2_FEATURE_COMPAT_DIR_INDEX; - if (e2p_edit_feature(features, &sb->s_feature_compat, - ok_features)) { - fprintf(stderr, _("Invalid filesystem option set: %s\n"), - features); + old_features[E2P_FEATURE_COMPAT] = sb->s_feature_compat; + old_features[E2P_FEATURE_INCOMPAT] = sb->s_feature_incompat; + old_features[E2P_FEATURE_RO_INCOMPAT] = sb->s_feature_ro_compat; + + if (e2p_edit_feature2(features, &sb->s_feature_compat, + ok_features, clear_ok_features, + &type_err, &mask_err)) { + if (!mask_err) + fprintf(stderr, + _("Invalid filesystem option set: %s\n"), + features); + else if (type_err & E2P_FEATURE_NEGATE_FLAG) + fprintf(stderr, _("Clearing filesystem feature '%s' " + "not supported.\n"), + e2p_feature2string(type_err & + E2P_FEATURE_TYPE_MASK, + mask_err)); + else + fprintf(stderr, _("Setting filesystem feature '%s' " + "not supported.\n"), + e2p_feature2string(type_err, mask_err)); exit(1); } - sparse = sb->s_feature_ro_compat & - EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER; - filetype = sb->s_feature_incompat & - EXT2_FEATURE_INCOMPAT_FILETYPE; - extents = sb->s_feature_incompat & - EXT3_FEATURE_INCOMPAT_EXTENTS; - flex_bg = sb->s_feature_incompat & - EXT4_FEATURE_INCOMPAT_FLEX_BG; - journal = sb->s_feature_compat & - EXT3_FEATURE_COMPAT_HAS_JOURNAL; - dxdir = sb->s_feature_compat & - EXT2_FEATURE_COMPAT_DIR_INDEX; - if (old_journal && !journal) { + + if (FEATURE_OFF(E2P_FEATURE_COMPAT, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) { if ((mount_flags & EXT2_MF_MOUNTED) && !(mount_flags & EXT2_MF_READONLY)) { fputs(_("The has_journal flag may only be " @@ -360,7 +374,8 @@ static void update_feature_set(ext2_filsys fs, char *features) remove_journal_device(fs); } } - if (journal && !old_journal) { + + if (FEATURE_ON(E2P_FEATURE_COMPAT, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) { /* * If adding a journal flag, let the create journal * code below handle creating setting the flag and @@ -371,18 +386,15 @@ static void update_feature_set(ext2_filsys fs, char *features) journal_size = -1; sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL; } - if (old_extents && !extents) { - fputs(_("Clearing the extents feature flag not supported.\n"), - stderr); - exit(1); - } - if (dxdir && !old_dxdir) { + + if (FEATURE_ON(E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_INDEX)) { if (!sb->s_def_hash_version) sb->s_def_hash_version = EXT2_HASH_TEA; if (uuid_is_null((unsigned char *) sb->s_hash_seed)) uuid_generate((unsigned char *) sb->s_hash_seed); } - if (!flex_bg && old_flex_bg) { + + if (FEATURE_OFF(E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_FLEX_BG)) { if (ext2fs_check_desc(fs)) { fputs(_("Clearing the flex_bg flag would " "cause the the filesystem to be\n" @@ -395,14 +407,22 @@ static void update_feature_set(ext2_filsys fs, char *features) (sb->s_feature_compat || sb->s_feature_ro_compat || sb->s_feature_incompat)) ext2fs_update_dynamic_rev(fs); - if ((sparse != old_sparse) || - (filetype != old_filetype)) { + + if (FEATURE_CHANGED(E2P_FEATURE_RO_INCOMPAT, + EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) || + FEATURE_CHANGED(E2P_FEATURE_INCOMPAT, + EXT2_FEATURE_INCOMPAT_FILETYPE) || + FEATURE_CHANGED(E2P_FEATURE_COMPAT, + EXT2_FEATURE_COMPAT_RESIZE_INODE) || + FEATURE_OFF(E2P_FEATURE_RO_INCOMPAT, + EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) { sb->s_state &= ~EXT2_VALID_FS; printf("\n%s\n", _(please_fsck)); } - if ((old_compat != sb->s_feature_compat) || - (old_ro_compat != sb->s_feature_ro_compat) || - (old_incompat != sb->s_feature_incompat)) + + if ((old_features[E2P_FEATURE_COMPAT] != sb->s_feature_compat) || + (old_features[E2P_FEATURE_INCOMPAT] != sb->s_feature_incompat) || + (old_features[E2P_FEATURE_RO_INCOMPAT] != sb->s_feature_ro_compat)) ext2fs_mark_super_dirty(fs); } diff --git a/tests/m_raid_opt/expect.1 b/tests/m_raid_opt/expect.1 index 28e11645..9bd78943 100644 --- a/tests/m_raid_opt/expect.1 +++ b/tests/m_raid_opt/expect.1 @@ -151,6 +151,7 @@ Blocks per group: 1024 Fragments per group: 1024 Inodes per group: 256 Inode blocks per group: 32 +RAID stride: 13 Mount count: 0 Check interval: 15552000 (6 months) Reserved blocks uid: 0 |
