aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2020-10-01 17:13:27 -0400
committerTheodore Ts'o <tytso@mit.edu>2020-10-01 17:13:27 -0400
commit7b8253ba09e635d328a48c98a184b571b809911b (patch)
treedb21ee5a31bc251d526370e707a50e6835f320f5
parent9a32973bd15b62d69cc311e108282c412bc9c435 (diff)
parent1dd48bc23c3776df76459aff0c7723fff850ea45 (diff)
downloade2fsprogs-7b8253ba09e635d328a48c98a184b571b809911b.tar.gz
Merge branch 'maint' into next
-rw-r--r--configure.ac3
-rw-r--r--debugfs/debugfs.c15
-rw-r--r--debugfs/debugfs.h4
-rw-r--r--debugfs/util.c35
-rw-r--r--debugfs/zap.c35
-rw-r--r--e2fsck/e2fsck.h2
-rw-r--r--e2fsck/pass1.c2
-rw-r--r--e2fsck/rehash.c4
-rw-r--r--e2fsck/unix.c2
-rw-r--r--e2fsck/util.c8
-rw-r--r--lib/e2p/pf.c1
-rw-r--r--lib/ext2fs/csum.c5
-rw-r--r--lib/ext2fs/ext2_fs.h1
-rw-r--r--lib/ext2fs/fallocate.c28
-rw-r--r--lib/ext2fs/imager.c2
-rw-r--r--lib/ext2fs/openfs.c7
-rw-r--r--lib/ext2fs/swapfs.c3
-rw-r--r--misc/chattr.1.in15
-rw-r--r--misc/chattr.c3
-rw-r--r--misc/create_inode.c2
-rw-r--r--misc/e2fuzz.c10
-rw-r--r--misc/e4crypt.8.in4
-rw-r--r--misc/e4crypt.c18
-rw-r--r--misc/mke2fs.c81
-rw-r--r--misc/tune2fs.c84
-rw-r--r--tests/f_badjour_indblks/imagebin8388608 -> 0 bytes
-rw-r--r--tests/r_inline_xattr/expect4
-rw-r--r--tests/r_inline_xattr/script8
-rw-r--r--tests/t_mmp_2off/script4
-rw-r--r--tests/t_mmp_fail/is_slow_test0
-rw-r--r--tests/t_mmp_fail/name1
-rw-r--r--tests/t_mmp_fail/script44
32 files changed, 285 insertions, 150 deletions
diff --git a/configure.ac b/configure.ac
index 18e434bc6..7d9210740 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1142,6 +1142,9 @@ if test -n "$BLKID_CMT"; then
AC_CHECK_LIB(blkid, blkid_probe_get_topology,
AC_DEFINE(HAVE_BLKID_PROBE_GET_TOPOLOGY, 1,
[Define to 1 if blkid has blkid_probe_get_topology]))
+ AC_CHECK_LIB(blkid, blkid_topology_get_dax,
+ AC_DEFINE(HAVE_BLKID_TOPOLOGY_GET_DAX, 1,
+ [Define to 1 if blkid has blkid_topology_get_dax]))
AC_CHECK_LIB(blkid, blkid_probe_enable_partitions,
AC_DEFINE(HAVE_BLKID_PROBE_ENABLE_PARTITIONS, 1,
[Define to 1 if blkid has blkid_probe_enable_partitions]))
diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c
index 2022f3dae..78e557792 100644
--- a/debugfs/debugfs.c
+++ b/debugfs/debugfs.c
@@ -276,7 +276,11 @@ void do_open_filesys(int argc, char **argv, int sci_idx EXT2FS_ATTR((unused)),
return;
break;
case 'z':
+#ifdef READ_ONLY
+ goto print_usage;
+#else
undo_file = optarg;
+#endif
break;
default:
goto print_usage;
@@ -294,9 +298,10 @@ void do_open_filesys(int argc, char **argv, int sci_idx EXT2FS_ATTR((unused)),
print_usage:
fprintf(stderr, "%s: Usage: open [-s superblock] [-b blocksize] "
+#ifdef READ_ONLY
"[-d image_filename] [-z undo_file] [-c] [-i] [-f] [-e] [-D] "
-#ifndef READ_ONLY
- "[-w] "
+#else
+ "[-d image_filename] [-c] [-i] [-f] [-e] [-D] [-w] "
#endif
"<device>\n", argv[0]);
}
@@ -2379,7 +2384,6 @@ void do_fallocate(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)),
return;
}
}
-#endif /* READ_ONLY */
void do_symlink(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)),
void *infop EXT2FS_ATTR((unused)))
@@ -2395,6 +2399,7 @@ void do_symlink(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)),
com_err(argv[0], retval, 0);
}
+#endif /* READ_ONLY */
#if CONFIG_MMP
void do_dump_mmp(int argc EXT2FS_ATTR((unused)), char *argv[],
@@ -2539,8 +2544,8 @@ int main(int argc, char **argv)
const char *opt_string = "nicR:f:b:s:Vd:D";
#else
const char *opt_string = "niwcR:f:b:s:Vd:Dz:";
- char *undo_file = NULL;
#endif
+ char *undo_file = NULL;
#ifdef CONFIG_JBD_DEBUG
char *jbd_debug;
#endif
@@ -2612,9 +2617,11 @@ int main(int argc, char **argv)
fprintf(stderr, "\tUsing %s\n",
error_message(EXT2_ET_BASE));
exit(0);
+#ifndef READ_ONLY
case 'z':
undo_file = optarg;
break;
+#endif
default:
com_err(argv[0], 0, usage, debug_prog_name);
return 1;
diff --git a/debugfs/debugfs.h b/debugfs/debugfs.h
index 956517bcf..39bc0247f 100644
--- a/debugfs/debugfs.h
+++ b/debugfs/debugfs.h
@@ -193,7 +193,8 @@ extern void do_get_quota(int argc, char *argv[], int sci_idx, void *infop);
/* util.c */
extern __s64 string_to_time(const char *arg);
-errcode_t read_list(char *str, blk64_t **list, size_t *len);
+extern errcode_t read_list(char *str, blk64_t **list, size_t *len);
+extern void do_byte_hexdump(FILE *fp, unsigned char *buf, size_t bufsize);
/* xattrs.c */
void dump_inode_attributes(FILE *out, ext2_ino_t ino);
@@ -207,4 +208,3 @@ void block_xattr_dump(FILE *f, unsigned char *buf, unsigned int len);
/* zap.c */
extern void do_zap_block(int argc, char **argv, int sci_idx, void *infop);
extern void do_block_dump(int argc, char **argv, int sci_idx, void *infop);
-extern void do_byte_hexdump(FILE *fp, unsigned char *buf, size_t bufsize);
diff --git a/debugfs/util.c b/debugfs/util.c
index 759bb3924..da3a7ef76 100644
--- a/debugfs/util.c
+++ b/debugfs/util.c
@@ -562,3 +562,38 @@ err:
free(lst);
return retval;
}
+
+void do_byte_hexdump(FILE *fp, unsigned char *buf, size_t bufsize)
+{
+ size_t i, j, max;
+ int suppress = -1;
+
+ for (i = 0; i < bufsize; i += 16) {
+ max = (bufsize - i > 16) ? 16 : bufsize - i;
+ if (suppress < 0) {
+ if (i && memcmp(buf + i, buf + i - max, max) == 0) {
+ suppress = i;
+ fprintf(fp, "*\n");
+ continue;
+ }
+ } else {
+ if (memcmp(buf + i, buf + suppress, max) == 0)
+ continue;
+ suppress = -1;
+ }
+ fprintf(fp, "%04o ", (unsigned int)i);
+ for (j = 0; j < 16; j++) {
+ if (j < max)
+ fprintf(fp, "%02x", buf[i+j]);
+ else
+ fprintf(fp, " ");
+ if ((j % 2) == 1)
+ fprintf(fp, " ");
+ }
+ fprintf(fp, " ");
+ for (j = 0; j < max; j++)
+ fprintf(fp, "%c", isprint(buf[i+j]) ? buf[i+j] : '.');
+ fprintf(fp, "\n");
+ }
+ fprintf(fp, "\n");
+}
diff --git a/debugfs/zap.c b/debugfs/zap.c
index c7996b229..f12037741 100644
--- a/debugfs/zap.c
+++ b/debugfs/zap.c
@@ -239,38 +239,3 @@ void do_block_dump(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)),
errout:
free(buf);
}
-
-void do_byte_hexdump(FILE *fp, unsigned char *buf, size_t bufsize)
-{
- size_t i, j, max;
- int suppress = -1;
-
- for (i = 0; i < bufsize; i += 16) {
- max = (bufsize - i > 16) ? 16 : bufsize - i;
- if (suppress < 0) {
- if (i && memcmp(buf + i, buf + i - max, max) == 0) {
- suppress = i;
- fprintf(fp, "*\n");
- continue;
- }
- } else {
- if (memcmp(buf + i, buf + suppress, max) == 0)
- continue;
- suppress = -1;
- }
- fprintf(fp, "%04o ", (unsigned int)i);
- for (j = 0; j < 16; j++) {
- if (j < max)
- fprintf(fp, "%02x", buf[i+j]);
- else
- fprintf(fp, " ");
- if ((j % 2) == 1)
- fprintf(fp, " ");
- }
- fprintf(fp, " ");
- for (j = 0; j < max; j++)
- fprintf(fp, "%c", isprint(buf[i+j]) ? buf[i+j] : '.');
- fprintf(fp, "\n");
- }
- fprintf(fp, "\n");
-}
diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h
index 9b2b9ce8b..85f953b2e 100644
--- a/e2fsck/e2fsck.h
+++ b/e2fsck/e2fsck.h
@@ -627,7 +627,7 @@ extern void log_err(e2fsck_t ctx, const char *fmt, ...)
extern void e2fsck_read_bitmaps(e2fsck_t ctx);
extern void e2fsck_write_bitmaps(e2fsck_t ctx);
extern void preenhalt(e2fsck_t ctx);
-extern char *string_copy(e2fsck_t ctx, const char *str, int len);
+extern char *string_copy(e2fsck_t ctx, const char *str, size_t len);
extern int fs_proc_check(const char *fs_name);
extern int check_for_modules(const char *fs_name);
#ifdef RESOURCE_TRACK
diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index 4de9ca653..8eecd9583 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -2654,7 +2654,7 @@ static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
return 1;
pctx->num = root->indirect_levels;
- if ((root->indirect_levels > ext2_dir_htree_level(fs)) &&
+ if ((root->indirect_levels >= ext2_dir_htree_level(fs)) &&
fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
return 1;
diff --git a/e2fsck/rehash.c b/e2fsck/rehash.c
index 1616d07a5..30e510a6c 100644
--- a/e2fsck/rehash.c
+++ b/e2fsck/rehash.c
@@ -109,7 +109,7 @@ static int fill_dir_block(ext2_filsys fs,
void *priv_data)
{
struct fill_dir_struct *fd = (struct fill_dir_struct *) priv_data;
- struct hash_entry *new_array, *ent;
+ struct hash_entry *ent;
struct ext2_dir_entry *dirent;
char *dir;
unsigned int offset, dir_offset, rec_len, name_len;
@@ -460,7 +460,7 @@ static errcode_t copy_dir_entries(e2fsck_t ctx,
struct hash_entry *ent;
struct ext2_dir_entry *dirent;
unsigned int rec_len, prev_rec_len, left, slack, offset;
- int i;
+ blk_t i;
ext2_dirhash_t prev_hash;
int csum_size = 0;
struct ext2_dir_entry_tail *t;
diff --git a/e2fsck/unix.c b/e2fsck/unix.c
index b144c385a..1cb516721 100644
--- a/e2fsck/unix.c
+++ b/e2fsck/unix.c
@@ -1444,7 +1444,7 @@ int main (int argc, char *argv[])
fputs("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n",
ctx->problem_logf);
fprintf(ctx->problem_logf, "<problem_log time=\"%lu\">\n",
- ctx->now);
+ (unsigned long) ctx->now);
fprintf(ctx->problem_logf, "<invocation prog=\"%s\"",
argv[0]);
for (i = 1; i < argc; i++)
diff --git a/e2fsck/util.c b/e2fsck/util.c
index d98b8e47b..e0623e4c8 100644
--- a/e2fsck/util.c
+++ b/e2fsck/util.c
@@ -123,10 +123,10 @@ void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned long size,
char buf[256];
#ifdef DEBUG_ALLOCATE_MEMORY
- printf("Allocating %u bytes for %s...\n", size, description);
+ printf("Allocating %lu bytes for %s...\n", size, description);
#endif
if (ext2fs_get_memzero(size, &ret)) {
- sprintf(buf, "Can't allocate %u bytes for %s\n",
+ sprintf(buf, "Can't allocate %lu bytes for %s\n",
size, description);
fatal_error(ctx, buf);
}
@@ -135,7 +135,7 @@ void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned long size,
}
char *string_copy(e2fsck_t ctx EXT2FS_ATTR((unused)),
- const char *str, int len)
+ const char *str, size_t len)
{
char *ret;
@@ -436,7 +436,7 @@ void print_resource_track(e2fsck_t ctx, const char *desc,
#define kbytes(x) (((unsigned long long)(x) + 1023) / 1024)
#ifdef HAVE_MALLINFO
/* don't use mallinfo() if over 2GB used, since it returns "int" */
- if ((char *)sbrk(0) - (char *)track->brk_start < 2ULL << 30) {
+ if ((char *)sbrk(0) - (char *)track->brk_start < 2LL << 30) {
struct mallinfo malloc_info = mallinfo();
log_out(ctx, _("Memory used: %lluk/%lluk (%lluk/%lluk), "),
diff --git a/lib/e2p/pf.c b/lib/e2p/pf.c
index 0c6998c4b..61fd4ab70 100644
--- a/lib/e2p/pf.c
+++ b/lib/e2p/pf.c
@@ -44,6 +44,7 @@ static struct flags_name flags_array[] = {
{ EXT2_TOPDIR_FL, "T", "Top_of_Directory_Hierarchies" },
{ EXT4_EXTENTS_FL, "e", "Extents" },
{ FS_NOCOW_FL, "C", "No_COW" },
+ { FS_DAX_FL, "x", "DAX" },
{ EXT4_CASEFOLD_FL, "F", "Casefold" },
{ EXT4_INLINE_DATA_FL, "N", "Inline_Data" },
{ EXT4_PROJINHERIT_FL, "P", "Project_Hierarchy" },
diff --git a/lib/ext2fs/csum.c b/lib/ext2fs/csum.c
index 8513d1abb..86184b682 100644
--- a/lib/ext2fs/csum.c
+++ b/lib/ext2fs/csum.c
@@ -266,15 +266,14 @@ static errcode_t __get_dirent_tail(ext2_filsys fs,
d = dirent;
top = EXT2_DIRENT_TAIL(dirent, fs->blocksize);
- rec_len = translate(d->rec_len);
while ((void *) d < top) {
+ rec_len = translate(d->rec_len);
if ((rec_len < 8) || (rec_len & 0x03))
return EXT2_ET_DIR_CORRUPTED;
d = (struct ext2_dir_entry *)(((char *)d) + rec_len);
- rec_len = translate(d->rec_len);
}
- if ((void *)d > ((void *)dirent + fs->blocksize))
+ if ((char *)d > ((char *)dirent + fs->blocksize))
return EXT2_ET_DIR_CORRUPTED;
if (d != top)
return EXT2_ET_DIR_NO_SPACE_FOR_CSUM;
diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h
index 0376674c4..bfc30c29a 100644
--- a/lib/ext2fs/ext2_fs.h
+++ b/lib/ext2fs/ext2_fs.h
@@ -335,6 +335,7 @@ struct ext2_dx_tail {
/* EXT4_EOFBLOCKS_FL 0x00400000 was here */
#define FS_NOCOW_FL 0x00800000 /* Do not cow file */
#define EXT4_SNAPFILE_FL 0x01000000 /* Inode is a snapshot */
+#define FS_DAX_FL 0x02000000 /* Inode is DAX */
#define EXT4_SNAPFILE_DELETED_FL 0x04000000 /* Snapshot is being deleted */
#define EXT4_SNAPFILE_SHRUNK_FL 0x08000000 /* Snapshot shrink has completed */
#define EXT4_INLINE_DATA_FL 0x10000000 /* Inode has inline data */
diff --git a/lib/ext2fs/fallocate.c b/lib/ext2fs/fallocate.c
index 31e47f8de..5cde7d5c2 100644
--- a/lib/ext2fs/fallocate.c
+++ b/lib/ext2fs/fallocate.c
@@ -805,7 +805,8 @@ errcode_t ext2fs_fallocate(ext2_filsys fs, int flags, ext2_ino_t ino,
blk64_t start, blk64_t len)
{
struct ext2_inode inode_buf;
- blk64_t blk, x;
+ blk64_t blk, x, zero_blk, last = 0;
+ int zero_len = 0;
errcode_t err;
if (((flags & EXT2_FALLOCATE_FORCE_INIT) &&
@@ -841,15 +842,32 @@ errcode_t ext2fs_fallocate(ext2_filsys fs, int flags, ext2_ino_t ino,
if (x)
continue;
- err = ext2fs_bmap2(fs, ino, inode, NULL,
- BMAP_ALLOC | BMAP_UNINIT | BMAP_ZERO, blk,
- 0, &x);
+ err = ext2fs_bmap2(fs, ino, inode, NULL, BMAP_ALLOC,
+ blk, 0, &x);
if (err)
- return err;
+ goto errout;
+ if ((zero_len && (x != last+1)) ||
+ (zero_len >= 65536)) {
+ err = ext2fs_zero_blocks2(fs, zero_blk, zero_len,
+ NULL, NULL);
+ zero_len = 0;
+ if (err)
+ goto errout;
+ }
+ if (zero_len == 0) {
+ zero_blk = x;
+ zero_len = 1;
+ } else {
+ zero_len++;
+ }
+ last = x;
}
out:
if (inode == &inode_buf)
ext2fs_write_inode(fs, ino, inode);
+errout:
+ if (zero_len)
+ ext2fs_zero_blocks2(fs, zero_blk, zero_len, NULL, NULL);
return err;
}
diff --git a/lib/ext2fs/imager.c b/lib/ext2fs/imager.c
index f8d67d86b..586227fc4 100644
--- a/lib/ext2fs/imager.c
+++ b/lib/ext2fs/imager.c
@@ -67,7 +67,7 @@ errcode_t ext2fs_image_inode_write(ext2_filsys fs, int fd, int flags)
blk64_t blk;
ssize_t actual;
errcode_t retval;
- loff_t r;
+ ext2_loff_t r;
buf = malloc(fs->blocksize * BUF_BLOCKS);
if (!buf)
diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c
index 3331452df..3ed1e25cd 100644
--- a/lib/ext2fs/openfs.c
+++ b/lib/ext2fs/openfs.c
@@ -134,6 +134,7 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
int j;
#endif
char *time_env;
+ int csum_retries = 0;
EXT2_CHECK_MAGIC(manager, EXT2_ET_MAGIC_IO_MANAGER);
@@ -221,6 +222,7 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
if (retval)
goto cleanup;
}
+retry:
retval = io_channel_read_blk(fs->io, superblock, -SUPERBLOCK_SIZE,
fs->super);
if (retval)
@@ -232,8 +234,11 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
retval = 0;
if (!ext2fs_verify_csum_type(fs, fs->super))
retval = EXT2_ET_UNKNOWN_CSUM;
- if (!ext2fs_superblock_csum_verify(fs, fs->super))
+ if (!ext2fs_superblock_csum_verify(fs, fs->super)) {
+ if (csum_retries++ < 3)
+ goto retry;
retval = EXT2_ET_SB_CSUM_INVALID;
+ }
}
#ifdef WORDS_BIGENDIAN
diff --git a/lib/ext2fs/swapfs.c b/lib/ext2fs/swapfs.c
index 5b93b5011..bc9f32300 100644
--- a/lib/ext2fs/swapfs.c
+++ b/lib/ext2fs/swapfs.c
@@ -456,12 +456,11 @@ errcode_t ext2fs_dirent_swab_out2(ext2_filsys fs, char *buf,
{
errcode_t retval;
char *p, *end;
- unsigned int rec_len, left;
+ unsigned int rec_len;
struct ext2_dir_entry *dirent;
p = buf;
end = buf + size;
- left = size;
while (p < end) {
dirent = (struct ext2_dir_entry *) p;
retval = ext2fs_get_rec_len(fs, dirent, &rec_len);
diff --git a/misc/chattr.1.in b/misc/chattr.1.in
index ff2fcf003..5a4928a54 100644
--- a/misc/chattr.1.in
+++ b/misc/chattr.1.in
@@ -23,13 +23,13 @@ chattr \- change file attributes on a Linux file system
.B chattr
changes the file attributes on a Linux file system.
.PP
-The format of a symbolic mode is +-=[aAcCdDeFijPsStTu].
+The format of a symbolic mode is +-=[aAcCdDeFijPsStTux].
.PP
The operator '+' causes the selected attributes to be added to the
existing attributes of the files; '-' causes them to be removed; and '='
causes them to be the only attributes that the files have.
.PP
-The letters 'aAcCdDeFijPsStTu' select the new attributes for the files:
+The letters 'aAcCdDeFijPsStTux' select the new attributes for the files:
append only (a),
no atime updates (A),
compressed (c),
@@ -45,7 +45,8 @@ secure deletion (s),
synchronous updates (S),
no tail-merging (t),
top of directory hierarchy (T),
-and undeletable (u).
+undeletable (u),
+and direct access for files (x).
.PP
The following attributes are read-only, and may be listed by
.BR lsattr (1)
@@ -210,6 +211,14 @@ saved. This allows the user to ask for its undeletion. Note: please
make sure to read the bugs and limitations section at the end of this
document.
.TP
+.B x
+The 'x' attribute can be set on a directory or file. If the attribute
+is set on an existing directory, it will be inherited by all files and
+subdirectories that are subsequently created in the directory. If an
+existing directory has contained some files and subdirectories, modifying
+the attribute on the parent directory doesn't change the attributes on
+these files and subdirectories.
+.TP
.B V
A file with the 'V' attribute set has fs-verity enabled. It cannot be
written to, and the filesystem will automatically verify all data read
diff --git a/misc/chattr.c b/misc/chattr.c
index a5d60170b..c0337f86b 100644
--- a/misc/chattr.c
+++ b/misc/chattr.c
@@ -86,7 +86,7 @@ static unsigned long sf;
static void usage(void)
{
fprintf(stderr,
- _("Usage: %s [-pRVf] [-+=aAcCdDeijPsStTuF] [-v version] files...\n"),
+ _("Usage: %s [-pRVf] [-+=aAcCdDeijPsStTuFx] [-v version] files...\n"),
program_name);
exit(1);
}
@@ -112,6 +112,7 @@ static const struct flags_char flags_array[] = {
{ EXT2_NOTAIL_FL, 't' },
{ EXT2_TOPDIR_FL, 'T' },
{ FS_NOCOW_FL, 'C' },
+ { FS_DAX_FL, 'x' },
{ EXT4_CASEFOLD_FL, 'F' },
{ 0, 0 }
};
diff --git a/misc/create_inode.c b/misc/create_inode.c
index e8d1df6b5..837f38755 100644
--- a/misc/create_inode.c
+++ b/misc/create_inode.c
@@ -601,7 +601,7 @@ out:
return err;
}
-static int is_hardlink(struct hdlinks_s *hdlinks, dev_t dev, ext2_ino_t ino)
+static int is_hardlink(struct hdlinks_s *hdlinks, dev_t dev, ino_t ino)
{
int i;
diff --git a/misc/e2fuzz.c b/misc/e2fuzz.c
index 7c0f776fe..685cdbe29 100644
--- a/misc/e2fuzz.c
+++ b/misc/e2fuzz.c
@@ -33,9 +33,10 @@ static unsigned long long user_corrupt_bytes = 0;
static double user_corrupt_pct = 0.0;
#if !defined HAVE_PWRITE64 && !defined HAVE_PWRITE
-static ssize_t my_pwrite(int fd, const void *buf, size_t count, off_t offset)
+static ssize_t my_pwrite(int fd, const void *buf, size_t count,
+ ext2_loff_t offset)
{
- if (lseek(fd, offset, SEEK_SET) < 0)
+ if (ext2fs_llseek(fd, offset, SEEK_SET) < 0)
return 0;
return write(fd, buf, count);
@@ -82,7 +83,7 @@ static int find_block_helper(ext2_filsys fs EXT2FS_ATTR((unused)),
}
static errcode_t find_metadata_blocks(ext2_filsys fs, ext2fs_block_bitmap bmap,
- off_t *corrupt_bytes)
+ ext2_loff_t *corrupt_bytes)
{
dgrp_t i;
blk64_t b, c;
@@ -181,9 +182,8 @@ static int process_fs(const char *fsname)
int flags, fd;
ext2_filsys fs = NULL;
ext2fs_block_bitmap corrupt_map;
- loff_t hsize, count, off, offset, corrupt_bytes;
+ ext2_loff_t hsize, count, off, offset, corrupt_bytes, i;
unsigned char c;
- loff_t i;
/* If mounted rw, force dryrun mode */
ret = ext2fs_check_if_mounted(fsname, &flags);
diff --git a/misc/e4crypt.8.in b/misc/e4crypt.8.in
index 75b968a0f..fe9372cf3 100644
--- a/misc/e4crypt.8.in
+++ b/misc/e4crypt.8.in
@@ -48,7 +48,9 @@ values are 4, 8, 16, and 32.
If one or more directory paths are specified, e4crypt will try to
set the policy of those directories to use the key just added by the
.B add_key
-command.
+command. If a salt was explicitly specified, then it will be used
+to derive the encryption key of those directories. Otherwise a
+directory-specific default salt will be used.
.TP
.B e4crypt get_policy \fIpath\fR ...
Print the policy for the directories specified on the command line.
diff --git a/misc/e4crypt.c b/misc/e4crypt.c
index 2ae6254a2..67d25d88d 100644
--- a/misc/e4crypt.c
+++ b/misc/e4crypt.c
@@ -26,6 +26,7 @@
#include <getopt.h>
#include <dirent.h>
#include <errno.h>
+#include <stdbool.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@@ -652,6 +653,7 @@ static void do_help(int argc, char **argv, const struct cmd_desc *cmd);
static void do_add_key(int argc, char **argv, const struct cmd_desc *cmd)
{
struct salt *salt;
+ bool explicit_salt = false;
char *keyring = NULL;
int i, opt, pad = 4;
unsigned j;
@@ -666,8 +668,13 @@ static void do_add_key(int argc, char **argv, const struct cmd_desc *cmd)
pad = atoi(optarg);
break;
case 'S':
+ if (explicit_salt) {
+ fputs("May only provide -S once\n", stderr);
+ exit(1);
+ }
/* Salt value for passphrase. */
parse_salt(optarg, 0);
+ explicit_salt = true;
break;
case 'v':
options |= OPT_VERBOSE;
@@ -692,8 +699,9 @@ static void do_add_key(int argc, char **argv, const struct cmd_desc *cmd)
exit(1);
}
validate_paths(argc, argv, optind);
- for (i = optind; i < argc; i++)
- parse_salt(argv[i], PARSE_FLAGS_FORCE_FN);
+ if (!explicit_salt)
+ for (i = optind; i < argc; i++)
+ parse_salt(argv[i], PARSE_FLAGS_FORCE_FN);
printf("Enter passphrase (echo disabled): ");
get_passphrase(in_passphrase, sizeof(in_passphrase));
for (j = 0, salt = salt_list; j < num_salt; j++, salt++) {
@@ -702,8 +710,10 @@ static void do_add_key(int argc, char **argv, const struct cmd_desc *cmd)
generate_key_ref_str(salt);
insert_key_into_keyring(keyring, salt);
}
- if (optind != argc)
- set_policy(NULL, pad, argc, argv, optind);
+ if (optind != argc) {
+ salt = explicit_salt ? salt_list : NULL;
+ set_policy(salt, pad, argc, argv, optind);
+ }
clear_secrets();
exit(0);
}
diff --git a/misc/mke2fs.c b/misc/mke2fs.c
index c90dcf0e8..8c8f5ea46 100644
--- a/misc/mke2fs.c
+++ b/misc/mke2fs.c
@@ -1468,23 +1468,30 @@ int get_bool_from_profile(char **types, const char *opt, int def_val)
extern const char *mke2fs_default_profile;
static const char *default_files[] = { "<default>", 0 };
+struct device_param {
+ unsigned long min_io; /* prefered minimum IO size */
+ unsigned long opt_io; /* optimal IO size */
+ unsigned long alignment_offset; /* alignment offset wrt physical block size */
+ unsigned int dax:1; /* supports dax? */
+};
+
#ifdef HAVE_BLKID_PROBE_GET_TOPOLOGY
/*
* Sets the geometry of a device (stripe/stride), and returns the
* device's alignment offset, if any, or a negative error.
*/
static int get_device_geometry(const char *file,
- struct ext2_super_block *param,
- unsigned int psector_size)
+ unsigned int blocksize,
+ unsigned int psector_size,
+ struct device_param *dev_param)
{
int rc = -1;
- unsigned int blocksize;
blkid_probe pr;
blkid_topology tp;
- unsigned long min_io;
- unsigned long opt_io;
struct stat statbuf;
+ memset(dev_param, 0, sizeof(*dev_param));
+
/* Nothing to do for a regular file */
if (!stat(file, &statbuf) && S_ISREG(statbuf.st_mode))
return 0;
@@ -1497,23 +1504,20 @@ static int get_device_geometry(const char *file,
if (!tp)
goto out;
- min_io = blkid_topology_get_minimum_io_size(tp);
- opt_io = blkid_topology_get_optimal_io_size(tp);
- blocksize = EXT2_BLOCK_SIZE(param);
- if ((min_io == 0) && (psector_size > blocksize))
- min_io = psector_size;
- if ((opt_io == 0) && min_io)
- opt_io = min_io;
- if ((opt_io == 0) && (psector_size > blocksize))
- opt_io = psector_size;
-
- /* setting stripe/stride to blocksize is pointless */
- if (min_io > blocksize)
- param->s_raid_stride = min_io / blocksize;
- if (opt_io > blocksize)
- param->s_raid_stripe_width = opt_io / blocksize;
-
- rc = blkid_topology_get_alignment_offset(tp);
+ dev_param->min_io = blkid_topology_get_minimum_io_size(tp);
+ dev_param->opt_io = blkid_topology_get_optimal_io_size(tp);
+ if ((dev_param->min_io == 0) && (psector_size > blocksize))
+ dev_param->min_io = psector_size;
+ if ((dev_param->opt_io == 0) && dev_param->min_io > 0)
+ dev_param->opt_io = dev_param->min_io;
+ if ((dev_param->opt_io == 0) && (psector_size > blocksize))
+ dev_param->opt_io = psector_size;
+
+ dev_param->alignment_offset = blkid_topology_get_alignment_offset(tp);
+#ifdef HAVE_BLKID_TOPOLOGY_GET_DAX
+ dev_param->dax = blkid_topology_get_dax(tp);
+#endif
+ rc = 0;
out:
blkid_free_probe(pr);
return rc;
@@ -1562,6 +1566,7 @@ static void PRS(int argc, char *argv[])
int use_bsize;
char *newpath;
int pathlen = sizeof(PATH_SET) + 1;
+ struct device_param dev_param;
if (oldpath)
pathlen += strlen(oldpath);
@@ -2307,17 +2312,35 @@ profile_error:
}
#ifdef HAVE_BLKID_PROBE_GET_TOPOLOGY
- retval = get_device_geometry(device_name, &fs_param,
- (unsigned int) psector_size);
+ retval = get_device_geometry(device_name, blocksize,
+ psector_size, &dev_param);
if (retval < 0) {
fprintf(stderr,
_("warning: Unable to get device geometry for %s\n"),
device_name);
- } else if (retval) {
- printf(_("%s alignment is offset by %lu bytes.\n"),
- device_name, retval);
- printf(_("This may result in very poor performance, "
- "(re)-partitioning suggested.\n"));
+ } else {
+ /* setting stripe/stride to blocksize is pointless */
+ if (dev_param.min_io > blocksize)
+ fs_param.s_raid_stride = dev_param.min_io / blocksize;
+ if (dev_param.opt_io > blocksize) {
+ fs_param.s_raid_stripe_width =
+ dev_param.opt_io / blocksize;
+ }
+
+ if (dev_param.alignment_offset) {
+ printf(_("%s alignment is offset by %lu bytes.\n"),
+ device_name, dev_param.alignment_offset);
+ printf(_("This may result in very poor performance, "
+ "(re)-partitioning suggested.\n"));
+ }
+
+ if (dev_param.dax && blocksize != sys_page_size) {
+ fprintf(stderr,
+ _("%s is capable of DAX but current block size "
+ "%u is different from system page size %u so "
+ "filesystem will not support DAX.\n"),
+ device_name, blocksize, sys_page_size);
+ }
}
#endif
diff --git a/misc/tune2fs.c b/misc/tune2fs.c
index 81f90cbf9..f942c698a 100644
--- a/misc/tune2fs.c
+++ b/misc/tune2fs.c
@@ -426,7 +426,7 @@ static int update_mntopts(ext2_filsys fs, char *mntopts)
return 0;
}
-static void check_fsck_needed(ext2_filsys fs, const char *prompt)
+static int check_fsck_needed(ext2_filsys fs, const char *prompt)
{
/* Refuse to modify anything but a freshly checked valid filesystem. */
if (!(fs->super->s_state & EXT2_VALID_FS) ||
@@ -436,15 +436,17 @@ static void check_fsck_needed(ext2_filsys fs, const char *prompt)
puts(_(please_fsck));
if (mount_flags & EXT2_MF_READONLY)
printf("%s", _("(and reboot afterwards!)\n"));
- exit(1);
+ return 1;
}
/* Give the admin a few seconds to bail out of a dangerous op. */
if (!getenv("TUNE2FS_FORCE_PROMPT") && (!isatty(0) || !isatty(1)))
- return;
+ return 0;
puts(prompt);
proceed_question(5);
+
+ return 0;
}
static void request_dir_fsck_afterwards(ext2_filsys fs)
@@ -1274,12 +1276,13 @@ mmp_error:
if (FEATURE_ON(E2P_FEATURE_RO_INCOMPAT,
EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
- check_fsck_needed(fs,
- _("Enabling checksums could take some time."));
+ if (check_fsck_needed(fs,
+ _("Enabling checksums could take some time.")))
+ return 1;
if (mount_flags & EXT2_MF_MOUNTED) {
fputs(_("Cannot enable metadata_csum on a mounted "
"filesystem!\n"), stderr);
- exit(1);
+ return 1;
}
if (!ext2fs_has_feature_extents(fs->super))
printf("%s",
@@ -1315,12 +1318,13 @@ mmp_error:
EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
__u32 test_features[3];
- check_fsck_needed(fs,
- _("Disabling checksums could take some time."));
+ if (check_fsck_needed(fs,
+ _("Disabling checksums could take some time.")))
+ return 1;
if (mount_flags & EXT2_MF_MOUNTED) {
fputs(_("Cannot disable metadata_csum on a mounted "
"filesystem!\n"), stderr);
- exit(1);
+ return 1;
}
rewrite_checksums = REWRITE_ALL;
@@ -1361,7 +1365,7 @@ mmp_error:
if (mount_flags & EXT2_MF_MOUNTED) {
fputs(_("Cannot enable uninit_bg on a mounted "
"filesystem!\n"), stderr);
- exit(1);
+ return 1;
}
/* Do not enable uninit_bg when metadata_csum enabled */
@@ -1376,7 +1380,7 @@ mmp_error:
if (mount_flags & EXT2_MF_MOUNTED) {
fputs(_("Cannot disable uninit_bg on a mounted "
"filesystem!\n"), stderr);
- exit(1);
+ return 1;
}
err = disable_uninit_bg(fs,
@@ -1395,7 +1399,7 @@ mmp_error:
if (mount_flags & EXT2_MF_MOUNTED) {
fprintf(stderr, _("Cannot enable 64-bit mode "
"while mounted!\n"));
- exit(1);
+ return 1;
}
ext2fs_clear_feature_64bit(sb);
feature_64bit = 1;
@@ -1405,7 +1409,7 @@ mmp_error:
if (mount_flags & EXT2_MF_MOUNTED) {
fprintf(stderr, _("Cannot disable 64-bit mode "
"while mounted!\n"));
- exit(1);
+ return 1;
}
ext2fs_set_feature_64bit(sb);
feature_64bit = -1;
@@ -1435,7 +1439,7 @@ mmp_error:
if (fs->super->s_inode_size == EXT2_GOOD_OLD_INODE_SIZE) {
fprintf(stderr, _("Cannot enable project feature; "
"inode size too small.\n"));
- exit(1);
+ return 1;
}
Q_flag = 1;
quota_enable[PRJQUOTA] = QOPT_ENABLE;
@@ -1502,8 +1506,9 @@ mmp_error:
stderr);
return 1;
}
- check_fsck_needed(fs, _("Recalculating checksums "
- "could take some time."));
+ if (check_fsck_needed(fs, _("Recalculating checksums "
+ "could take some time.")))
+ return 1;
rewrite_checksums = REWRITE_ALL;
}
}
@@ -1616,7 +1621,7 @@ err:
return 1;
}
-static void handle_quota_options(ext2_filsys fs)
+static int handle_quota_options(ext2_filsys fs)
{
errcode_t retval;
quota_ctx_t qctx;
@@ -1630,13 +1635,13 @@ static void handle_quota_options(ext2_filsys fs)
break;
if (qtype == MAXQUOTAS)
/* Nothing to do. */
- return;
+ return 0;
if (quota_enable[PRJQUOTA] == QOPT_ENABLE &&
fs->super->s_inode_size == EXT2_GOOD_OLD_INODE_SIZE) {
fprintf(stderr, _("Cannot enable project quota; "
"inode size too small.\n"));
- exit(1);
+ return 1;
}
for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
@@ -1648,7 +1653,7 @@ static void handle_quota_options(ext2_filsys fs)
if (retval) {
com_err(program_name, retval,
_("while initializing quota context in support library"));
- exit(1);
+ return 1;
}
if (qtype_bits)
@@ -1664,7 +1669,7 @@ static void handle_quota_options(ext2_filsys fs)
com_err(program_name, retval,
_("while updating quota limits (%d)"),
qtype);
- exit(1);
+ return 1;
}
}
retval = quota_write_inode(qctx, 1 << qtype);
@@ -1672,7 +1677,7 @@ static void handle_quota_options(ext2_filsys fs)
com_err(program_name, retval,
_("while writing quota file (%d)"),
qtype);
- exit(1);
+ return 1;
}
/* Enable Quota feature if one of quota enabled */
if (!ext2fs_has_feature_quota(fs->super)) {
@@ -1690,7 +1695,7 @@ static void handle_quota_options(ext2_filsys fs)
com_err(program_name, retval,
_("while removing quota file (%d)"),
qtype);
- exit(1);
+ return 1;
}
if (qtype == PRJQUOTA) {
ext2fs_clear_feature_project(fs->super);
@@ -1713,7 +1718,7 @@ static void handle_quota_options(ext2_filsys fs)
}
if (need_dirty)
ext2fs_mark_super_dirty(fs);
- return;
+ return 0;
}
static int option_handle_function(char *token)
@@ -3008,8 +3013,10 @@ retry_open:
rc = 1;
goto closefs;
}
- check_fsck_needed(fs,
+ rc = check_fsck_needed(fs,
_("Resizing inodes could take some time."));
+ if (rc)
+ goto closefs;
/*
* If inode resize is requested use the
* Undo I/O manager
@@ -3065,16 +3072,16 @@ _("Warning: The journal is dirty. You may wish to replay the journal like:\n\n"
/* Recover the journal if possible. */
if ((open_flag & EXT2_FLAG_RW) && !(mount_flags & (EXT2_MF_BUSY | EXT2_MF_MOUNTED)) &&
ext2fs_has_feature_journal_needs_recovery(fs->super)) {
- errcode_t err;
-
printf(_("Recovering journal.\n"));
- err = ext2fs_run_ext3_journal(&fs);
- if (err) {
- com_err("tune2fs", err, "while recovering journal.\n");
+ retval = ext2fs_run_ext3_journal(&fs);
+ if (retval) {
+ com_err("tune2fs", retval,
+ "while recovering journal.\n");
printf(_("Please run e2fsck -fy %s.\n"), argv[1]);
if (fs)
ext2fs_close_free(&fs);
- exit(1);
+ rc = 1;
+ goto closefs;
}
sb = fs->super;
}
@@ -3178,13 +3185,13 @@ _("Warning: The journal is dirty. You may wish to replay the journal like:\n\n"
fputs(_("Warning: label too long, truncating.\n"),
stderr);
memset(sb->s_volume_name, 0, sizeof(sb->s_volume_name));
- strncpy(sb->s_volume_name, new_label,
+ strncpy((char *)sb->s_volume_name, new_label,
sizeof(sb->s_volume_name));
ext2fs_mark_super_dirty(fs);
}
if (M_flag) {
memset(sb->s_last_mounted, 0, sizeof(sb->s_last_mounted));
- strncpy(sb->s_last_mounted, new_last_mounted,
+ strncpy((char *)sb->s_last_mounted, new_last_mounted,
sizeof(sb->s_last_mounted));
ext2fs_mark_super_dirty(fs);
}
@@ -3226,7 +3233,9 @@ _("Warning: The journal is dirty. You may wish to replay the journal like:\n\n"
rc = 1;
goto closefs;
}
- handle_quota_options(fs);
+ rc = handle_quota_options(fs);
+ if (rc)
+ goto closefs;
}
if (U_flag) {
@@ -3245,9 +3254,11 @@ _("Warning: The journal is dirty. You may wish to replay the journal like:\n\n"
if (!ext2fs_has_feature_csum_seed(fs->super) &&
(ext2fs_has_feature_metadata_csum(fs->super) ||
ext2fs_has_feature_ea_inode(fs->super))) {
- check_fsck_needed(fs,
+ rc = check_fsck_needed(fs,
_("Setting the UUID on this "
"filesystem could take some time."));
+ if (rc)
+ goto closefs;
rewrite_checksums = REWRITE_ALL;
}
@@ -3269,7 +3280,8 @@ _("Warning: The journal is dirty. You may wish to replay the journal like:\n\n"
"metadata_csum_seed' and re-run this "
"command.\n"), stderr);
try_confirm_csum_seed_support();
- exit(1);
+ rc = 1;
+ goto closefs;
}
/*
diff --git a/tests/f_badjour_indblks/image b/tests/f_badjour_indblks/image
deleted file mode 100644
index adbd1d795..000000000
--- a/tests/f_badjour_indblks/image
+++ /dev/null
Binary files differ
diff --git a/tests/r_inline_xattr/expect b/tests/r_inline_xattr/expect
index 885de59db..773db1021 100644
--- a/tests/r_inline_xattr/expect
+++ b/tests/r_inline_xattr/expect
@@ -1,5 +1,5 @@
resize2fs test
-debugfs -R ''stat file'' test.img 2>&1 | grep ''^Inode\|in inode body\|user.name (''
+debugfs -R ''stat file'' test.img 2>&1 | grep -E ''^Inode\|in inode body\|user.name \(''
Inode: 1550 Type: regular Mode: 0644 Flags: 0x0
user.name (11) = "propervalue"
Exit status is 0
@@ -8,7 +8,7 @@ Resizing the filesystem on test.img to 5120 (1k) blocks.
The filesystem on test.img is now 5120 (1k) blocks long.
Exit status is 0
-debugfs -R ''stat file'' test.img 2>&1 | grep ''^Inode\|in inode body\|user.name (''
+debugfs -R ''stat file'' test.img 2>&1 | grep -E ''^Inode\|in inode body\|user.name \(''
Inode: 12 Type: regular Mode: 0644 Flags: 0x0
user.name (11) = "propervalue"
Exit status is 0
diff --git a/tests/r_inline_xattr/script b/tests/r_inline_xattr/script
index 4e7dd94cf..2f754e60b 100644
--- a/tests/r_inline_xattr/script
+++ b/tests/r_inline_xattr/script
@@ -13,8 +13,8 @@ gunzip < $IMAGE > $TMPFILE
echo "resize2fs test" > $OUT.new
# Look at existing inline extended attribute
-echo "debugfs -R ''stat file'' test.img 2>&1 | grep ''^Inode\|in inode body\|user.name (''" >> $OUT.new
-$DEBUGFS -R "stat file" $TMPFILE 2>&1 | grep "^Inode\|in inode body\|user.name (" >> $OUT.new
+echo "debugfs -R ''stat file'' test.img 2>&1 | grep -E ''^Inode\|in inode body\|user.name \\(''" >> $OUT.new
+$DEBUGFS -R "stat file" $TMPFILE 2>&1 | grep -E "^Inode|in inode body|user.name \(" >> $OUT.new
status=$?
echo Exit status is $status >> $OUT.new
@@ -25,8 +25,8 @@ status=$?
echo Exit status is $status >> $OUT.new
# Look at inline extended attribute in resized fs
-echo "debugfs -R ''stat file'' test.img 2>&1 | grep ''^Inode\|in inode body\|user.name (''" >> $OUT.new
-$DEBUGFS -R "stat file" $TMPFILE 2>&1 | grep "^Inode\|in inode body\|user.name (" >> $OUT.new
+echo "debugfs -R ''stat file'' test.img 2>&1 | grep -E ''^Inode\|in inode body\|user.name \\(''" >> $OUT.new
+$DEBUGFS -R "stat file" $TMPFILE 2>&1 | grep -E "^Inode|in inode body|user.name \(" >> $OUT.new
status=$?
echo Exit status is $status >> $OUT.new
diff --git a/tests/t_mmp_2off/script b/tests/t_mmp_2off/script
index ccd859b2f..1cd071919 100644
--- a/tests/t_mmp_2off/script
+++ b/tests/t_mmp_2off/script
@@ -8,7 +8,7 @@ if [ "$status" != 0 ] ; then
return $status
fi
-$TUNE2FS -O ^mmp $TMPFILE > $test_name.log 2>&1
+$TUNE2FS -O ^mmp $TMPFILE >> $test_name.log 2>&1
status=$?
if [ "$status" != 0 ] ; then
echo "tune2fs -O ^mmp failed" > $test_name.failed
@@ -16,7 +16,7 @@ if [ "$status" != 0 ] ; then
return $status
fi
-$FSCK $FSCK_OPT $TMPFILE > $test_name.log 2>&1
+$FSCK $FSCK_OPT $TMPFILE >> $test_name.log 2>&1
status=$?
if [ "$status" = 0 ] ; then
echo "$test_name: $test_description: ok"
diff --git a/tests/t_mmp_fail/is_slow_test b/tests/t_mmp_fail/is_slow_test
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/t_mmp_fail/is_slow_test
diff --git a/tests/t_mmp_fail/name b/tests/t_mmp_fail/name
new file mode 100644
index 000000000..e872ddaaa
--- /dev/null
+++ b/tests/t_mmp_fail/name
@@ -0,0 +1 @@
+error running tune2fs with MMP
diff --git a/tests/t_mmp_fail/script b/tests/t_mmp_fail/script
new file mode 100644
index 000000000..5fa6a846b
--- /dev/null
+++ b/tests/t_mmp_fail/script
@@ -0,0 +1,44 @@
+FSCK_OPT=-yf
+
+$MKE2FS -q -F -o Linux -I 128 -b 1024 -O mmp $TMPFILE 100 > $test_name.log 2>&1
+status=$?
+if [ "$status" != 0 ] ; then
+ echo "mke2fs -O mmp failed" > $test_name.failed
+ echo "$test_name: $test_description: failed"
+ return $status
+fi
+
+$TUNE2FS -O project $TMPFILE >> $test_name.log 2>&1
+status=$?
+if [ "$status" == 0 ] ; then
+ echo "'tune2fs -O project' succeeded on small inode" > $test_name.failed
+ echo "$test_name: $test_description: failed"
+ return 1
+fi
+$TUNE2FS -o bad_option $TMPFILE >> $test_name.log 2>&1
+status=$?
+if [ "$status" == 0 ] ; then
+ echo "'tune2fs -o bad_option' succeeded" > $test_name.failed
+ echo "$test_name: $test_description: failed"
+ return 1
+fi
+$E2MMPSTATUS -i $TMPFILE >> $test_name.log 2>&1
+$E2MMPSTATUS $TMPFILE >> $test_name.log 2>&1
+status=$?
+if [ "$status" != 0 ] ; then
+ echo "$TUNE2FS left MMP block in bad state" > $test_name.failed
+ echo "$test_name: $test_description: failed"
+ return $status
+fi
+
+$FSCK $FSCK_OPT $TMPFILE >> $test_name.log 2>&1
+status=$?
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "e2fsck after MMP disable failed" > $test_name.failed
+ echo "$test_name: $test_description: failed"
+ return $status
+fi
+rm -f $TMPFILE