aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2008-02-27 18:53:34 -0500
committerTheodore Ts'o <tytso@mit.edu>2008-02-27 18:53:34 -0500
commita49670e64e28ac3b15e36cb6bd0a8135d3ecdbbb (patch)
tree30f0ecd00942e15e097ca2c253131f4d3abce3a9
parente6bbc002c5a3d30df156d4f23bc93a7f2dbde3a1 (diff)
parent4f9abdcb306ff515a8009a1e0fd35041688133c9 (diff)
downloadandroid_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.postinst4
-rw-r--r--debugfs/debugfs.c7
-rw-r--r--e2fsck/Makefile.in12
-rw-r--r--e2fsck/badblocks.c1
-rw-r--r--e2fsck/e2fsck.8.in5
-rw-r--r--e2fsck/pass2.c9
-rw-r--r--e2fsck/unix.c49
-rw-r--r--lib/blkid/devname.c93
-rw-r--r--lib/blkid/probe.c82
-rw-r--r--lib/blkid/probe.h14
-rw-r--r--lib/e2p/e2p.h5
-rw-r--r--lib/e2p/feature.c47
-rw-r--r--lib/e2p/ls.c4
-rw-r--r--lib/ext2fs/alloc.c1
-rw-r--r--lib/ext2fs/ext2fs.h1
-rw-r--r--lib/ext2fs/openfs.c6
-rw-r--r--misc/dumpe2fs.8.in10
-rw-r--r--misc/dumpe2fs.c103
-rw-r--r--misc/fsck.c2
-rw-r--r--misc/mke2fs.8.in4
-rw-r--r--misc/mke2fs.c10
-rw-r--r--misc/tune2fs.8.in31
-rw-r--r--misc/tune2fs.c124
-rw-r--r--tests/m_raid_opt/expect.11
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