Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 56889787 authored by Theodore Ts'o's avatar Theodore Ts'o
Browse files

ext4: improve handling of conflicting mount options



If the user explicitly specifies conflicting mount options for
delalloc or dioread_nolock and data=journal, fail the mount, instead
of printing a warning and continuing (since many user's won't look at
dmesg and notice the warning).

Also, print a single warning that data=journal implies that delayed
allocation is not on by default (since it's not supported), and
furthermore that O_DIRECT is not supported.  Improve the text in
Documentation/filesystems/ext4.txt so this is clear there as well.

Similarly, if the dioread_nolock mount option is specified when the
file system block size != PAGE_SIZE, fail the mount instead of
printing a warning message and ignoring the mount option.

Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
parent 2be4751b
Loading
Loading
Loading
Loading
+5 −3
Original line number Original line Diff line number Diff line
@@ -160,7 +160,9 @@ noload if the filesystem was not unmounted cleanly,
                     	lead to any number of problems.
                     	lead to any number of problems.


data=journal		All data are committed into the journal prior to being
data=journal		All data are committed into the journal prior to being
			written into the main file system.
			written into the main file system.  Enabling
			this mode will disable delayed allocation and
			O_DIRECT support.


data=ordered	(*)	All data are forced directly out to the main file
data=ordered	(*)	All data are forced directly out to the main file
			system prior to its metadata being committed to the
			system prior to its metadata being committed to the
@@ -419,8 +421,8 @@ written to the journal first, and then to its final location.
In the event of a crash, the journal can be replayed, bringing both data and
In the event of a crash, the journal can be replayed, bringing both data and
metadata into a consistent state.  This mode is the slowest except when data
metadata into a consistent state.  This mode is the slowest except when data
needs to be read from and written to disk at the same time where it
needs to be read from and written to disk at the same time where it
outperforms all others modes.  Currently ext4 does not have delayed
outperforms all others modes.  Enabling this mode will disable delayed
allocation support if this data journalling mode is selected.
allocation and O_DIRECT support.


/proc entries
/proc entries
=============
=============
+3 −0
Original line number Original line Diff line number Diff line
@@ -922,6 +922,9 @@ struct ext4_inode_info {
#define EXT4_MOUNT_DISCARD		0x40000000 /* Issue DISCARD requests */
#define EXT4_MOUNT_DISCARD		0x40000000 /* Issue DISCARD requests */
#define EXT4_MOUNT_INIT_INODE_TABLE	0x80000000 /* Initialize uninitialized itables */
#define EXT4_MOUNT_INIT_INODE_TABLE	0x80000000 /* Initialize uninitialized itables */


#define EXT4_MOUNT2_EXPLICIT_DELALLOC	0x00000001 /* User explicitly
						      specified delalloc */

#define clear_opt(sb, opt)		EXT4_SB(sb)->s_mount_opt &= \
#define clear_opt(sb, opt)		EXT4_SB(sb)->s_mount_opt &= \
						~EXT4_MOUNT_##opt
						~EXT4_MOUNT_##opt
#define set_opt(sb, opt)		EXT4_SB(sb)->s_mount_opt |= \
#define set_opt(sb, opt)		EXT4_SB(sb)->s_mount_opt |= \
+29 −21
Original line number Original line Diff line number Diff line
@@ -1801,6 +1801,7 @@ static int parse_options(char *options, struct super_block *sb,
			break;
			break;
		case Opt_nodelalloc:
		case Opt_nodelalloc:
			clear_opt(sb, DELALLOC);
			clear_opt(sb, DELALLOC);
			clear_opt2(sb, EXPLICIT_DELALLOC);
			break;
			break;
		case Opt_mblk_io_submit:
		case Opt_mblk_io_submit:
			set_opt(sb, MBLK_IO_SUBMIT);
			set_opt(sb, MBLK_IO_SUBMIT);
@@ -1817,6 +1818,7 @@ static int parse_options(char *options, struct super_block *sb,
			break;
			break;
		case Opt_delalloc:
		case Opt_delalloc:
			set_opt(sb, DELALLOC);
			set_opt(sb, DELALLOC);
			set_opt2(sb, EXPLICIT_DELALLOC);
			break;
			break;
		case Opt_block_validity:
		case Opt_block_validity:
			set_opt(sb, BLOCK_VALIDITY);
			set_opt(sb, BLOCK_VALIDITY);
@@ -3224,6 +3226,33 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
			   &journal_ioprio, NULL, 0))
			   &journal_ioprio, NULL, 0))
		goto failed_mount;
		goto failed_mount;


	if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) {
		printk_once(KERN_WARNING "EXT4-fs: Warning: mounting "
			    "with data=journal disables delayed "
			    "allocation and O_DIRECT support!\n");
		if (test_opt2(sb, EXPLICIT_DELALLOC)) {
			ext4_msg(sb, KERN_ERR, "can't mount with "
				 "both data=journal and delalloc");
			goto failed_mount;
		}
		if (test_opt(sb, DIOREAD_NOLOCK)) {
			ext4_msg(sb, KERN_ERR, "can't mount with "
				 "both data=journal and delalloc");
			goto failed_mount;
		}
		if (test_opt(sb, DELALLOC))
			clear_opt(sb, DELALLOC);
	}

	blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size);
	if (test_opt(sb, DIOREAD_NOLOCK)) {
		if (blocksize < PAGE_SIZE) {
			ext4_msg(sb, KERN_ERR, "can't mount with "
				 "dioread_nolock if block size != PAGE_SIZE");
			goto failed_mount;
		}
	}

	sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
	sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
		(test_opt(sb, POSIX_ACL) ? MS_POSIXACL : 0);
		(test_opt(sb, POSIX_ACL) ? MS_POSIXACL : 0);


@@ -3265,8 +3294,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
	if (!ext4_feature_set_ok(sb, (sb->s_flags & MS_RDONLY)))
	if (!ext4_feature_set_ok(sb, (sb->s_flags & MS_RDONLY)))
		goto failed_mount;
		goto failed_mount;


	blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size);

	if (blocksize < EXT4_MIN_BLOCK_SIZE ||
	if (blocksize < EXT4_MIN_BLOCK_SIZE ||
	    blocksize > EXT4_MAX_BLOCK_SIZE) {
	    blocksize > EXT4_MAX_BLOCK_SIZE) {
		ext4_msg(sb, KERN_ERR,
		ext4_msg(sb, KERN_ERR,
@@ -3679,25 +3706,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
			 "available");
			 "available");
	}
	}


	if (test_opt(sb, DELALLOC) &&
	    (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)) {
		ext4_msg(sb, KERN_WARNING, "Ignoring delalloc option - "
			 "requested data journaling mode");
		clear_opt(sb, DELALLOC);
	}
	if (test_opt(sb, DIOREAD_NOLOCK)) {
		if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) {
			ext4_msg(sb, KERN_WARNING, "Ignoring dioread_nolock "
				"option - requested data journaling mode");
			clear_opt(sb, DIOREAD_NOLOCK);
		}
		if (sb->s_blocksize < PAGE_SIZE) {
			ext4_msg(sb, KERN_WARNING, "Ignoring dioread_nolock "
				"option - block size is too small");
			clear_opt(sb, DIOREAD_NOLOCK);
		}
	}

	err = ext4_setup_system_zone(sb);
	err = ext4_setup_system_zone(sb);
	if (err) {
	if (err) {
		ext4_msg(sb, KERN_ERR, "failed to initialize system "
		ext4_msg(sb, KERN_ERR, "failed to initialize system "