forked from mirrors/linux
		
	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: "Theodore Ts'o" <tytso@mit.edu>
This commit is contained in:
		
							parent
							
								
									2be4751b21
								
							
						
					
					
						commit
						56889787cf
					
				
					 3 changed files with 37 additions and 24 deletions
				
			
		| 
						 | 
					@ -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
 | 
				
			||||||
=============
 | 
					=============
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 |= \
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 "
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue