xref: /linux/fs/ext4/super.c (revision dd0db94f305c9f5dd44d0ecc7bf29944d4867074)
1f5166768STheodore Ts'o // SPDX-License-Identifier: GPL-2.0
2ac27a0ecSDave Kleikamp /*
3617ba13bSMingming Cao  *  linux/fs/ext4/super.c
4ac27a0ecSDave Kleikamp  *
5ac27a0ecSDave Kleikamp  * Copyright (C) 1992, 1993, 1994, 1995
6ac27a0ecSDave Kleikamp  * Remy Card (card@masi.ibp.fr)
7ac27a0ecSDave Kleikamp  * Laboratoire MASI - Institut Blaise Pascal
8ac27a0ecSDave Kleikamp  * Universite Pierre et Marie Curie (Paris VI)
9ac27a0ecSDave Kleikamp  *
10ac27a0ecSDave Kleikamp  *  from
11ac27a0ecSDave Kleikamp  *
12ac27a0ecSDave Kleikamp  *  linux/fs/minix/inode.c
13ac27a0ecSDave Kleikamp  *
14ac27a0ecSDave Kleikamp  *  Copyright (C) 1991, 1992  Linus Torvalds
15ac27a0ecSDave Kleikamp  *
16ac27a0ecSDave Kleikamp  *  Big-endian to little-endian byte-swapping/bitmaps by
17ac27a0ecSDave Kleikamp  *        David S. Miller (davem@caip.rutgers.edu), 1995
18ac27a0ecSDave Kleikamp  */
19ac27a0ecSDave Kleikamp 
20ac27a0ecSDave Kleikamp #include <linux/module.h>
21ac27a0ecSDave Kleikamp #include <linux/string.h>
22ac27a0ecSDave Kleikamp #include <linux/fs.h>
23ac27a0ecSDave Kleikamp #include <linux/time.h>
24c5ca7c76STheodore Ts'o #include <linux/vmalloc.h>
25ac27a0ecSDave Kleikamp #include <linux/slab.h>
26ac27a0ecSDave Kleikamp #include <linux/init.h>
27ac27a0ecSDave Kleikamp #include <linux/blkdev.h>
2866114cadSTejun Heo #include <linux/backing-dev.h>
29ac27a0ecSDave Kleikamp #include <linux/parser.h>
30ac27a0ecSDave Kleikamp #include <linux/buffer_head.h>
31a5694255SChristoph Hellwig #include <linux/exportfs.h>
32ac27a0ecSDave Kleikamp #include <linux/vfs.h>
33ac27a0ecSDave Kleikamp #include <linux/random.h>
34ac27a0ecSDave Kleikamp #include <linux/mount.h>
35ac27a0ecSDave Kleikamp #include <linux/namei.h>
36ac27a0ecSDave Kleikamp #include <linux/quotaops.h>
37ac27a0ecSDave Kleikamp #include <linux/seq_file.h>
383197ebdbSTheodore Ts'o #include <linux/ctype.h>
391330593eSVignesh Babu #include <linux/log2.h>
40717d50e4SAndreas Dilger #include <linux/crc16.h>
41ef510424SDan Williams #include <linux/dax.h>
427abc52c2SDan Magenheimer #include <linux/cleancache.h>
437c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
44ee73f9a5SJeff Layton #include <linux/iversion.h>
45c83ad55eSGabriel Krisman Bertazi #include <linux/unicode.h>
46c6a564ffSChristoph Hellwig #include <linux/part_stat.h>
47bfff6873SLukas Czerner #include <linux/kthread.h>
48bfff6873SLukas Czerner #include <linux/freezer.h>
49bfff6873SLukas Czerner 
503dcf5451SChristoph Hellwig #include "ext4.h"
514a092d73STheodore Ts'o #include "ext4_extents.h"	/* Needed for trace points definition */
523dcf5451SChristoph Hellwig #include "ext4_jbd2.h"
53ac27a0ecSDave Kleikamp #include "xattr.h"
54ac27a0ecSDave Kleikamp #include "acl.h"
553661d286STheodore Ts'o #include "mballoc.h"
560c9ec4beSDarrick J. Wong #include "fsmap.h"
57ac27a0ecSDave Kleikamp 
589bffad1eSTheodore Ts'o #define CREATE_TRACE_POINTS
599bffad1eSTheodore Ts'o #include <trace/events/ext4.h>
609bffad1eSTheodore Ts'o 
610b75a840SLukas Czerner static struct ext4_lazy_init *ext4_li_info;
620b75a840SLukas Czerner static struct mutex ext4_li_mtx;
63e294a537STheodore Ts'o static struct ratelimit_state ext4_mount_msg_ratelimit;
649f6200bbSTheodore Ts'o 
65617ba13bSMingming Cao static int ext4_load_journal(struct super_block *, struct ext4_super_block *,
66ac27a0ecSDave Kleikamp 			     unsigned long journal_devnum);
672adf6da8STheodore Ts'o static int ext4_show_options(struct seq_file *seq, struct dentry *root);
68e2d67052STheodore Ts'o static int ext4_commit_super(struct super_block *sb, int sync);
6911215630SJan Kara static int ext4_mark_recovery_complete(struct super_block *sb,
70617ba13bSMingming Cao 					struct ext4_super_block *es);
7111215630SJan Kara static int ext4_clear_journal_err(struct super_block *sb,
72617ba13bSMingming Cao 				  struct ext4_super_block *es);
73617ba13bSMingming Cao static int ext4_sync_fs(struct super_block *sb, int wait);
74617ba13bSMingming Cao static int ext4_remount(struct super_block *sb, int *flags, char *data);
75617ba13bSMingming Cao static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf);
76c4be0c1dSTakashi Sato static int ext4_unfreeze(struct super_block *sb);
77c4be0c1dSTakashi Sato static int ext4_freeze(struct super_block *sb);
78152a0836SAl Viro static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags,
79152a0836SAl Viro 		       const char *dev_name, void *data);
802035e776STheodore Ts'o static inline int ext2_feature_set_ok(struct super_block *sb);
812035e776STheodore Ts'o static inline int ext3_feature_set_ok(struct super_block *sb);
82d39195c3SAmir Goldstein static int ext4_feature_set_ok(struct super_block *sb, int readonly);
83bfff6873SLukas Czerner static void ext4_destroy_lazyinit_thread(void);
84bfff6873SLukas Czerner static void ext4_unregister_li_request(struct super_block *sb);
858f1f7453SEric Sandeen static void ext4_clear_request_list(void);
86c6cb7e77SEric Whitney static struct inode *ext4_get_journal_inode(struct super_block *sb,
87c6cb7e77SEric Whitney 					    unsigned int journal_inum);
88ac27a0ecSDave Kleikamp 
89e74031fdSJan Kara /*
90e74031fdSJan Kara  * Lock ordering
91e74031fdSJan Kara  *
92e74031fdSJan Kara  * Note the difference between i_mmap_sem (EXT4_I(inode)->i_mmap_sem) and
93e74031fdSJan Kara  * i_mmap_rwsem (inode->i_mmap_rwsem)!
94e74031fdSJan Kara  *
95e74031fdSJan Kara  * page fault path:
96c1e8d7c6SMichel Lespinasse  * mmap_lock -> sb_start_pagefault -> i_mmap_sem (r) -> transaction start ->
97e74031fdSJan Kara  *   page lock -> i_data_sem (rw)
98e74031fdSJan Kara  *
99e74031fdSJan Kara  * buffered write path:
100c1e8d7c6SMichel Lespinasse  * sb_start_write -> i_mutex -> mmap_lock
101e74031fdSJan Kara  * sb_start_write -> i_mutex -> transaction start -> page lock ->
102e74031fdSJan Kara  *   i_data_sem (rw)
103e74031fdSJan Kara  *
104e74031fdSJan Kara  * truncate:
1051d39834fSNikolay Borisov  * sb_start_write -> i_mutex -> i_mmap_sem (w) -> i_mmap_rwsem (w) -> page lock
1061d39834fSNikolay Borisov  * sb_start_write -> i_mutex -> i_mmap_sem (w) -> transaction start ->
1071d39834fSNikolay Borisov  *   i_data_sem (rw)
108e74031fdSJan Kara  *
109e74031fdSJan Kara  * direct IO:
110c1e8d7c6SMichel Lespinasse  * sb_start_write -> i_mutex -> mmap_lock
1111d39834fSNikolay Borisov  * sb_start_write -> i_mutex -> transaction start -> i_data_sem (rw)
112e74031fdSJan Kara  *
113e74031fdSJan Kara  * writepages:
114e74031fdSJan Kara  * transaction start -> page lock(s) -> i_data_sem (rw)
115e74031fdSJan Kara  */
116e74031fdSJan Kara 
117c290ea01SJan Kara #if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT2)
1182035e776STheodore Ts'o static struct file_system_type ext2_fs_type = {
1192035e776STheodore Ts'o 	.owner		= THIS_MODULE,
1202035e776STheodore Ts'o 	.name		= "ext2",
1212035e776STheodore Ts'o 	.mount		= ext4_mount,
1222035e776STheodore Ts'o 	.kill_sb	= kill_block_super,
1232035e776STheodore Ts'o 	.fs_flags	= FS_REQUIRES_DEV,
1242035e776STheodore Ts'o };
1257f78e035SEric W. Biederman MODULE_ALIAS_FS("ext2");
126fa7614ddSEric W. Biederman MODULE_ALIAS("ext2");
1272035e776STheodore Ts'o #define IS_EXT2_SB(sb) ((sb)->s_bdev->bd_holder == &ext2_fs_type)
1282035e776STheodore Ts'o #else
1292035e776STheodore Ts'o #define IS_EXT2_SB(sb) (0)
1302035e776STheodore Ts'o #endif
1312035e776STheodore Ts'o 
1322035e776STheodore Ts'o 
133ba69f9abSJan Kara static struct file_system_type ext3_fs_type = {
134ba69f9abSJan Kara 	.owner		= THIS_MODULE,
135ba69f9abSJan Kara 	.name		= "ext3",
136152a0836SAl Viro 	.mount		= ext4_mount,
137ba69f9abSJan Kara 	.kill_sb	= kill_block_super,
138ba69f9abSJan Kara 	.fs_flags	= FS_REQUIRES_DEV,
139ba69f9abSJan Kara };
1407f78e035SEric W. Biederman MODULE_ALIAS_FS("ext3");
141fa7614ddSEric W. Biederman MODULE_ALIAS("ext3");
142ba69f9abSJan Kara #define IS_EXT3_SB(sb) ((sb)->s_bdev->bd_holder == &ext3_fs_type)
143bd81d8eeSLaurent Vivier 
144fb265c9cSTheodore Ts'o /*
145fb265c9cSTheodore Ts'o  * This works like sb_bread() except it uses ERR_PTR for error
146fb265c9cSTheodore Ts'o  * returns.  Currently with sb_bread it's impossible to distinguish
147fb265c9cSTheodore Ts'o  * between ENOMEM and EIO situations (since both result in a NULL
148fb265c9cSTheodore Ts'o  * return.
149fb265c9cSTheodore Ts'o  */
150fb265c9cSTheodore Ts'o struct buffer_head *
151fb265c9cSTheodore Ts'o ext4_sb_bread(struct super_block *sb, sector_t block, int op_flags)
152fb265c9cSTheodore Ts'o {
153fb265c9cSTheodore Ts'o 	struct buffer_head *bh = sb_getblk(sb, block);
154fb265c9cSTheodore Ts'o 
155fb265c9cSTheodore Ts'o 	if (bh == NULL)
156fb265c9cSTheodore Ts'o 		return ERR_PTR(-ENOMEM);
157cf2834a5STheodore Ts'o 	if (ext4_buffer_uptodate(bh))
158fb265c9cSTheodore Ts'o 		return bh;
159fb265c9cSTheodore Ts'o 	ll_rw_block(REQ_OP_READ, REQ_META | op_flags, 1, &bh);
160fb265c9cSTheodore Ts'o 	wait_on_buffer(bh);
161fb265c9cSTheodore Ts'o 	if (buffer_uptodate(bh))
162fb265c9cSTheodore Ts'o 		return bh;
163fb265c9cSTheodore Ts'o 	put_bh(bh);
164fb265c9cSTheodore Ts'o 	return ERR_PTR(-EIO);
165fb265c9cSTheodore Ts'o }
166fb265c9cSTheodore Ts'o 
167d25425f8SDarrick J. Wong static int ext4_verify_csum_type(struct super_block *sb,
168d25425f8SDarrick J. Wong 				 struct ext4_super_block *es)
169d25425f8SDarrick J. Wong {
170e2b911c5SDarrick J. Wong 	if (!ext4_has_feature_metadata_csum(sb))
171d25425f8SDarrick J. Wong 		return 1;
172d25425f8SDarrick J. Wong 
173d25425f8SDarrick J. Wong 	return es->s_checksum_type == EXT4_CRC32C_CHKSUM;
174d25425f8SDarrick J. Wong }
175d25425f8SDarrick J. Wong 
176a9c47317SDarrick J. Wong static __le32 ext4_superblock_csum(struct super_block *sb,
177a9c47317SDarrick J. Wong 				   struct ext4_super_block *es)
178a9c47317SDarrick J. Wong {
179a9c47317SDarrick J. Wong 	struct ext4_sb_info *sbi = EXT4_SB(sb);
180a9c47317SDarrick J. Wong 	int offset = offsetof(struct ext4_super_block, s_checksum);
181a9c47317SDarrick J. Wong 	__u32 csum;
182a9c47317SDarrick J. Wong 
183a9c47317SDarrick J. Wong 	csum = ext4_chksum(sbi, ~0, (char *)es, offset);
184a9c47317SDarrick J. Wong 
185a9c47317SDarrick J. Wong 	return cpu_to_le32(csum);
186a9c47317SDarrick J. Wong }
187a9c47317SDarrick J. Wong 
188c197855eSStephen Hemminger static int ext4_superblock_csum_verify(struct super_block *sb,
189a9c47317SDarrick J. Wong 				       struct ext4_super_block *es)
190a9c47317SDarrick J. Wong {
1919aa5d32bSDmitry Monakhov 	if (!ext4_has_metadata_csum(sb))
192a9c47317SDarrick J. Wong 		return 1;
193a9c47317SDarrick J. Wong 
194a9c47317SDarrick J. Wong 	return es->s_checksum == ext4_superblock_csum(sb, es);
195a9c47317SDarrick J. Wong }
196a9c47317SDarrick J. Wong 
19706db49e6STheodore Ts'o void ext4_superblock_csum_set(struct super_block *sb)
198a9c47317SDarrick J. Wong {
19906db49e6STheodore Ts'o 	struct ext4_super_block *es = EXT4_SB(sb)->s_es;
20006db49e6STheodore Ts'o 
2019aa5d32bSDmitry Monakhov 	if (!ext4_has_metadata_csum(sb))
202a9c47317SDarrick J. Wong 		return;
203a9c47317SDarrick J. Wong 
204acaa5326SConstantine Sapuntzakis 	/*
205acaa5326SConstantine Sapuntzakis 	 * Locking the superblock prevents the scenario
206acaa5326SConstantine Sapuntzakis 	 * where:
207acaa5326SConstantine Sapuntzakis 	 *  1) a first thread pauses during checksum calculation.
208acaa5326SConstantine Sapuntzakis 	 *  2) a second thread updates the superblock, recalculates
209acaa5326SConstantine Sapuntzakis 	 *     the checksum, and updates s_checksum
210acaa5326SConstantine Sapuntzakis 	 *  3) the first thread resumes and finishes its checksum calculation
211acaa5326SConstantine Sapuntzakis 	 *     and updates s_checksum with a potentially stale or torn value.
212acaa5326SConstantine Sapuntzakis 	 */
213acaa5326SConstantine Sapuntzakis 	lock_buffer(EXT4_SB(sb)->s_sbh);
214a9c47317SDarrick J. Wong 	es->s_checksum = ext4_superblock_csum(sb, es);
215acaa5326SConstantine Sapuntzakis 	unlock_buffer(EXT4_SB(sb)->s_sbh);
216a9c47317SDarrick J. Wong }
217a9c47317SDarrick J. Wong 
2188fadc143SAlexandre Ratchov ext4_fsblk_t ext4_block_bitmap(struct super_block *sb,
2198fadc143SAlexandre Ratchov 			       struct ext4_group_desc *bg)
220bd81d8eeSLaurent Vivier {
2213a14589cSAneesh Kumar K.V 	return le32_to_cpu(bg->bg_block_bitmap_lo) |
2228fadc143SAlexandre Ratchov 		(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
2238fadc143SAlexandre Ratchov 		 (ext4_fsblk_t)le32_to_cpu(bg->bg_block_bitmap_hi) << 32 : 0);
224bd81d8eeSLaurent Vivier }
225bd81d8eeSLaurent Vivier 
2268fadc143SAlexandre Ratchov ext4_fsblk_t ext4_inode_bitmap(struct super_block *sb,
2278fadc143SAlexandre Ratchov 			       struct ext4_group_desc *bg)
228bd81d8eeSLaurent Vivier {
2295272f837SAneesh Kumar K.V 	return le32_to_cpu(bg->bg_inode_bitmap_lo) |
2308fadc143SAlexandre Ratchov 		(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
2318fadc143SAlexandre Ratchov 		 (ext4_fsblk_t)le32_to_cpu(bg->bg_inode_bitmap_hi) << 32 : 0);
232bd81d8eeSLaurent Vivier }
233bd81d8eeSLaurent Vivier 
2348fadc143SAlexandre Ratchov ext4_fsblk_t ext4_inode_table(struct super_block *sb,
2358fadc143SAlexandre Ratchov 			      struct ext4_group_desc *bg)
236bd81d8eeSLaurent Vivier {
2375272f837SAneesh Kumar K.V 	return le32_to_cpu(bg->bg_inode_table_lo) |
2388fadc143SAlexandre Ratchov 		(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
2398fadc143SAlexandre Ratchov 		 (ext4_fsblk_t)le32_to_cpu(bg->bg_inode_table_hi) << 32 : 0);
240bd81d8eeSLaurent Vivier }
241bd81d8eeSLaurent Vivier 
242021b65bbSTheodore Ts'o __u32 ext4_free_group_clusters(struct super_block *sb,
243560671a0SAneesh Kumar K.V 			       struct ext4_group_desc *bg)
244560671a0SAneesh Kumar K.V {
245560671a0SAneesh Kumar K.V 	return le16_to_cpu(bg->bg_free_blocks_count_lo) |
246560671a0SAneesh Kumar K.V 		(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
247560671a0SAneesh Kumar K.V 		 (__u32)le16_to_cpu(bg->bg_free_blocks_count_hi) << 16 : 0);
248560671a0SAneesh Kumar K.V }
249560671a0SAneesh Kumar K.V 
250560671a0SAneesh Kumar K.V __u32 ext4_free_inodes_count(struct super_block *sb,
251560671a0SAneesh Kumar K.V 			      struct ext4_group_desc *bg)
252560671a0SAneesh Kumar K.V {
253560671a0SAneesh Kumar K.V 	return le16_to_cpu(bg->bg_free_inodes_count_lo) |
254560671a0SAneesh Kumar K.V 		(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
255560671a0SAneesh Kumar K.V 		 (__u32)le16_to_cpu(bg->bg_free_inodes_count_hi) << 16 : 0);
256560671a0SAneesh Kumar K.V }
257560671a0SAneesh Kumar K.V 
258560671a0SAneesh Kumar K.V __u32 ext4_used_dirs_count(struct super_block *sb,
259560671a0SAneesh Kumar K.V 			      struct ext4_group_desc *bg)
260560671a0SAneesh Kumar K.V {
261560671a0SAneesh Kumar K.V 	return le16_to_cpu(bg->bg_used_dirs_count_lo) |
262560671a0SAneesh Kumar K.V 		(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
263560671a0SAneesh Kumar K.V 		 (__u32)le16_to_cpu(bg->bg_used_dirs_count_hi) << 16 : 0);
264560671a0SAneesh Kumar K.V }
265560671a0SAneesh Kumar K.V 
266560671a0SAneesh Kumar K.V __u32 ext4_itable_unused_count(struct super_block *sb,
267560671a0SAneesh Kumar K.V 			      struct ext4_group_desc *bg)
268560671a0SAneesh Kumar K.V {
269560671a0SAneesh Kumar K.V 	return le16_to_cpu(bg->bg_itable_unused_lo) |
270560671a0SAneesh Kumar K.V 		(EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT ?
271560671a0SAneesh Kumar K.V 		 (__u32)le16_to_cpu(bg->bg_itable_unused_hi) << 16 : 0);
272560671a0SAneesh Kumar K.V }
273560671a0SAneesh Kumar K.V 
2748fadc143SAlexandre Ratchov void ext4_block_bitmap_set(struct super_block *sb,
2758fadc143SAlexandre Ratchov 			   struct ext4_group_desc *bg, ext4_fsblk_t blk)
276bd81d8eeSLaurent Vivier {
2773a14589cSAneesh Kumar K.V 	bg->bg_block_bitmap_lo = cpu_to_le32((u32)blk);
2788fadc143SAlexandre Ratchov 	if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
2798fadc143SAlexandre Ratchov 		bg->bg_block_bitmap_hi = cpu_to_le32(blk >> 32);
280bd81d8eeSLaurent Vivier }
281bd81d8eeSLaurent Vivier 
2828fadc143SAlexandre Ratchov void ext4_inode_bitmap_set(struct super_block *sb,
2838fadc143SAlexandre Ratchov 			   struct ext4_group_desc *bg, ext4_fsblk_t blk)
284bd81d8eeSLaurent Vivier {
2855272f837SAneesh Kumar K.V 	bg->bg_inode_bitmap_lo  = cpu_to_le32((u32)blk);
2868fadc143SAlexandre Ratchov 	if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
2878fadc143SAlexandre Ratchov 		bg->bg_inode_bitmap_hi = cpu_to_le32(blk >> 32);
288bd81d8eeSLaurent Vivier }
289bd81d8eeSLaurent Vivier 
2908fadc143SAlexandre Ratchov void ext4_inode_table_set(struct super_block *sb,
2918fadc143SAlexandre Ratchov 			  struct ext4_group_desc *bg, ext4_fsblk_t blk)
292bd81d8eeSLaurent Vivier {
2935272f837SAneesh Kumar K.V 	bg->bg_inode_table_lo = cpu_to_le32((u32)blk);
2948fadc143SAlexandre Ratchov 	if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
2958fadc143SAlexandre Ratchov 		bg->bg_inode_table_hi = cpu_to_le32(blk >> 32);
296bd81d8eeSLaurent Vivier }
297bd81d8eeSLaurent Vivier 
298021b65bbSTheodore Ts'o void ext4_free_group_clusters_set(struct super_block *sb,
299560671a0SAneesh Kumar K.V 				  struct ext4_group_desc *bg, __u32 count)
300560671a0SAneesh Kumar K.V {
301560671a0SAneesh Kumar K.V 	bg->bg_free_blocks_count_lo = cpu_to_le16((__u16)count);
302560671a0SAneesh Kumar K.V 	if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
303560671a0SAneesh Kumar K.V 		bg->bg_free_blocks_count_hi = cpu_to_le16(count >> 16);
304560671a0SAneesh Kumar K.V }
305560671a0SAneesh Kumar K.V 
306560671a0SAneesh Kumar K.V void ext4_free_inodes_set(struct super_block *sb,
307560671a0SAneesh Kumar K.V 			  struct ext4_group_desc *bg, __u32 count)
308560671a0SAneesh Kumar K.V {
309560671a0SAneesh Kumar K.V 	bg->bg_free_inodes_count_lo = cpu_to_le16((__u16)count);
310560671a0SAneesh Kumar K.V 	if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
311560671a0SAneesh Kumar K.V 		bg->bg_free_inodes_count_hi = cpu_to_le16(count >> 16);
312560671a0SAneesh Kumar K.V }
313560671a0SAneesh Kumar K.V 
314560671a0SAneesh Kumar K.V void ext4_used_dirs_set(struct super_block *sb,
315560671a0SAneesh Kumar K.V 			  struct ext4_group_desc *bg, __u32 count)
316560671a0SAneesh Kumar K.V {
317560671a0SAneesh Kumar K.V 	bg->bg_used_dirs_count_lo = cpu_to_le16((__u16)count);
318560671a0SAneesh Kumar K.V 	if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
319560671a0SAneesh Kumar K.V 		bg->bg_used_dirs_count_hi = cpu_to_le16(count >> 16);
320560671a0SAneesh Kumar K.V }
321560671a0SAneesh Kumar K.V 
322560671a0SAneesh Kumar K.V void ext4_itable_unused_set(struct super_block *sb,
323560671a0SAneesh Kumar K.V 			  struct ext4_group_desc *bg, __u32 count)
324560671a0SAneesh Kumar K.V {
325560671a0SAneesh Kumar K.V 	bg->bg_itable_unused_lo = cpu_to_le16((__u16)count);
326560671a0SAneesh Kumar K.V 	if (EXT4_DESC_SIZE(sb) >= EXT4_MIN_DESC_SIZE_64BIT)
327560671a0SAneesh Kumar K.V 		bg->bg_itable_unused_hi = cpu_to_le16(count >> 16);
328560671a0SAneesh Kumar K.V }
329560671a0SAneesh Kumar K.V 
3306a0678a7SArnd Bergmann static void __ext4_update_tstamp(__le32 *lo, __u8 *hi)
3316a0678a7SArnd Bergmann {
3326a0678a7SArnd Bergmann 	time64_t now = ktime_get_real_seconds();
3336a0678a7SArnd Bergmann 
3346a0678a7SArnd Bergmann 	now = clamp_val(now, 0, (1ull << 40) - 1);
3356a0678a7SArnd Bergmann 
3366a0678a7SArnd Bergmann 	*lo = cpu_to_le32(lower_32_bits(now));
3376a0678a7SArnd Bergmann 	*hi = upper_32_bits(now);
3386a0678a7SArnd Bergmann }
3396a0678a7SArnd Bergmann 
3406a0678a7SArnd Bergmann static time64_t __ext4_get_tstamp(__le32 *lo, __u8 *hi)
3416a0678a7SArnd Bergmann {
3426a0678a7SArnd Bergmann 	return ((time64_t)(*hi) << 32) + le32_to_cpu(*lo);
3436a0678a7SArnd Bergmann }
3446a0678a7SArnd Bergmann #define ext4_update_tstamp(es, tstamp) \
3456a0678a7SArnd Bergmann 	__ext4_update_tstamp(&(es)->tstamp, &(es)->tstamp ## _hi)
3466a0678a7SArnd Bergmann #define ext4_get_tstamp(es, tstamp) \
3476a0678a7SArnd Bergmann 	__ext4_get_tstamp(&(es)->tstamp, &(es)->tstamp ## _hi)
348d3d1faf6SCurt Wohlgemuth 
34954d3adbcSTheodore Ts'o static void __save_error_info(struct super_block *sb, int error,
35054d3adbcSTheodore Ts'o 			      __u32 ino, __u64 block,
35154d3adbcSTheodore Ts'o 			      const char *func, unsigned int line)
3521c13d5c0STheodore Ts'o {
3531c13d5c0STheodore Ts'o 	struct ext4_super_block *es = EXT4_SB(sb)->s_es;
35454d3adbcSTheodore Ts'o 	int err;
3551c13d5c0STheodore Ts'o 
3561c13d5c0STheodore Ts'o 	EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
3571b46617bSTheodore Ts'o 	if (bdev_read_only(sb->s_bdev))
3581b46617bSTheodore Ts'o 		return;
3591c13d5c0STheodore Ts'o 	es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
3606a0678a7SArnd Bergmann 	ext4_update_tstamp(es, s_last_error_time);
3611c13d5c0STheodore Ts'o 	strncpy(es->s_last_error_func, func, sizeof(es->s_last_error_func));
3621c13d5c0STheodore Ts'o 	es->s_last_error_line = cpu_to_le32(line);
36354d3adbcSTheodore Ts'o 	es->s_last_error_ino = cpu_to_le32(ino);
36454d3adbcSTheodore Ts'o 	es->s_last_error_block = cpu_to_le64(block);
36554d3adbcSTheodore Ts'o 	switch (error) {
36654d3adbcSTheodore Ts'o 	case EIO:
36754d3adbcSTheodore Ts'o 		err = EXT4_ERR_EIO;
36854d3adbcSTheodore Ts'o 		break;
36954d3adbcSTheodore Ts'o 	case ENOMEM:
37054d3adbcSTheodore Ts'o 		err = EXT4_ERR_ENOMEM;
37154d3adbcSTheodore Ts'o 		break;
37254d3adbcSTheodore Ts'o 	case EFSBADCRC:
37354d3adbcSTheodore Ts'o 		err = EXT4_ERR_EFSBADCRC;
37454d3adbcSTheodore Ts'o 		break;
37554d3adbcSTheodore Ts'o 	case 0:
37654d3adbcSTheodore Ts'o 	case EFSCORRUPTED:
37754d3adbcSTheodore Ts'o 		err = EXT4_ERR_EFSCORRUPTED;
37854d3adbcSTheodore Ts'o 		break;
37954d3adbcSTheodore Ts'o 	case ENOSPC:
38054d3adbcSTheodore Ts'o 		err = EXT4_ERR_ENOSPC;
38154d3adbcSTheodore Ts'o 		break;
38254d3adbcSTheodore Ts'o 	case ENOKEY:
38354d3adbcSTheodore Ts'o 		err = EXT4_ERR_ENOKEY;
38454d3adbcSTheodore Ts'o 		break;
38554d3adbcSTheodore Ts'o 	case EROFS:
38654d3adbcSTheodore Ts'o 		err = EXT4_ERR_EROFS;
38754d3adbcSTheodore Ts'o 		break;
38854d3adbcSTheodore Ts'o 	case EFBIG:
38954d3adbcSTheodore Ts'o 		err = EXT4_ERR_EFBIG;
39054d3adbcSTheodore Ts'o 		break;
39154d3adbcSTheodore Ts'o 	case EEXIST:
39254d3adbcSTheodore Ts'o 		err = EXT4_ERR_EEXIST;
39354d3adbcSTheodore Ts'o 		break;
39454d3adbcSTheodore Ts'o 	case ERANGE:
39554d3adbcSTheodore Ts'o 		err = EXT4_ERR_ERANGE;
39654d3adbcSTheodore Ts'o 		break;
39754d3adbcSTheodore Ts'o 	case EOVERFLOW:
39854d3adbcSTheodore Ts'o 		err = EXT4_ERR_EOVERFLOW;
39954d3adbcSTheodore Ts'o 		break;
40054d3adbcSTheodore Ts'o 	case EBUSY:
40154d3adbcSTheodore Ts'o 		err = EXT4_ERR_EBUSY;
40254d3adbcSTheodore Ts'o 		break;
40354d3adbcSTheodore Ts'o 	case ENOTDIR:
40454d3adbcSTheodore Ts'o 		err = EXT4_ERR_ENOTDIR;
40554d3adbcSTheodore Ts'o 		break;
40654d3adbcSTheodore Ts'o 	case ENOTEMPTY:
40754d3adbcSTheodore Ts'o 		err = EXT4_ERR_ENOTEMPTY;
40854d3adbcSTheodore Ts'o 		break;
40954d3adbcSTheodore Ts'o 	case ESHUTDOWN:
41054d3adbcSTheodore Ts'o 		err = EXT4_ERR_ESHUTDOWN;
41154d3adbcSTheodore Ts'o 		break;
41254d3adbcSTheodore Ts'o 	case EFAULT:
41354d3adbcSTheodore Ts'o 		err = EXT4_ERR_EFAULT;
41454d3adbcSTheodore Ts'o 		break;
41554d3adbcSTheodore Ts'o 	default:
41654d3adbcSTheodore Ts'o 		err = EXT4_ERR_UNKNOWN;
41754d3adbcSTheodore Ts'o 	}
41854d3adbcSTheodore Ts'o 	es->s_last_error_errcode = err;
4191c13d5c0STheodore Ts'o 	if (!es->s_first_error_time) {
4201c13d5c0STheodore Ts'o 		es->s_first_error_time = es->s_last_error_time;
4216a0678a7SArnd Bergmann 		es->s_first_error_time_hi = es->s_last_error_time_hi;
4221c13d5c0STheodore Ts'o 		strncpy(es->s_first_error_func, func,
4231c13d5c0STheodore Ts'o 			sizeof(es->s_first_error_func));
4241c13d5c0STheodore Ts'o 		es->s_first_error_line = cpu_to_le32(line);
4251c13d5c0STheodore Ts'o 		es->s_first_error_ino = es->s_last_error_ino;
4261c13d5c0STheodore Ts'o 		es->s_first_error_block = es->s_last_error_block;
427878520acSTheodore Ts'o 		es->s_first_error_errcode = es->s_last_error_errcode;
4281c13d5c0STheodore Ts'o 	}
42966e61a9eSTheodore Ts'o 	/*
43066e61a9eSTheodore Ts'o 	 * Start the daily error reporting function if it hasn't been
43166e61a9eSTheodore Ts'o 	 * started already
43266e61a9eSTheodore Ts'o 	 */
43366e61a9eSTheodore Ts'o 	if (!es->s_error_count)
43466e61a9eSTheodore Ts'o 		mod_timer(&EXT4_SB(sb)->s_err_report, jiffies + 24*60*60*HZ);
435ba39ebb6SWei Yongjun 	le32_add_cpu(&es->s_error_count, 1);
4361c13d5c0STheodore Ts'o }
4371c13d5c0STheodore Ts'o 
43854d3adbcSTheodore Ts'o static void save_error_info(struct super_block *sb, int error,
43954d3adbcSTheodore Ts'o 			    __u32 ino, __u64 block,
44054d3adbcSTheodore Ts'o 			    const char *func, unsigned int line)
4411c13d5c0STheodore Ts'o {
44254d3adbcSTheodore Ts'o 	__save_error_info(sb, error, ino, block, func, line);
443c96e2b85SEric Sandeen 	if (!bdev_read_only(sb->s_bdev))
4441c13d5c0STheodore Ts'o 		ext4_commit_super(sb, 1);
4451c13d5c0STheodore Ts'o }
4461c13d5c0STheodore Ts'o 
447bdfe0cbdSTheodore Ts'o /*
448bdfe0cbdSTheodore Ts'o  * The del_gendisk() function uninitializes the disk-specific data
449bdfe0cbdSTheodore Ts'o  * structures, including the bdi structure, without telling anyone
450bdfe0cbdSTheodore Ts'o  * else.  Once this happens, any attempt to call mark_buffer_dirty()
451bdfe0cbdSTheodore Ts'o  * (for example, by ext4_commit_super), will cause a kernel OOPS.
452bdfe0cbdSTheodore Ts'o  * This is a kludge to prevent these oops until we can put in a proper
453bdfe0cbdSTheodore Ts'o  * hook in del_gendisk() to inform the VFS and file system layers.
454bdfe0cbdSTheodore Ts'o  */
455bdfe0cbdSTheodore Ts'o static int block_device_ejected(struct super_block *sb)
456bdfe0cbdSTheodore Ts'o {
457bdfe0cbdSTheodore Ts'o 	struct inode *bd_inode = sb->s_bdev->bd_inode;
458bdfe0cbdSTheodore Ts'o 	struct backing_dev_info *bdi = inode_to_bdi(bd_inode);
459bdfe0cbdSTheodore Ts'o 
460bdfe0cbdSTheodore Ts'o 	return bdi->dev == NULL;
461bdfe0cbdSTheodore Ts'o }
462bdfe0cbdSTheodore Ts'o 
46318aadd47SBobi Jam static void ext4_journal_commit_callback(journal_t *journal, transaction_t *txn)
46418aadd47SBobi Jam {
46518aadd47SBobi Jam 	struct super_block		*sb = journal->j_private;
46618aadd47SBobi Jam 	struct ext4_sb_info		*sbi = EXT4_SB(sb);
46718aadd47SBobi Jam 	int				error = is_journal_aborted(journal);
4685d3ee208SDmitry Monakhov 	struct ext4_journal_cb_entry	*jce;
46918aadd47SBobi Jam 
4705d3ee208SDmitry Monakhov 	BUG_ON(txn->t_state == T_FINISHED);
471a0154344SDaeho Jeong 
472a0154344SDaeho Jeong 	ext4_process_freed_data(sb, txn->t_tid);
473a0154344SDaeho Jeong 
47418aadd47SBobi Jam 	spin_lock(&sbi->s_md_lock);
4755d3ee208SDmitry Monakhov 	while (!list_empty(&txn->t_private_list)) {
4765d3ee208SDmitry Monakhov 		jce = list_entry(txn->t_private_list.next,
4775d3ee208SDmitry Monakhov 				 struct ext4_journal_cb_entry, jce_list);
47818aadd47SBobi Jam 		list_del_init(&jce->jce_list);
47918aadd47SBobi Jam 		spin_unlock(&sbi->s_md_lock);
48018aadd47SBobi Jam 		jce->jce_func(sb, jce, error);
48118aadd47SBobi Jam 		spin_lock(&sbi->s_md_lock);
48218aadd47SBobi Jam 	}
48318aadd47SBobi Jam 	spin_unlock(&sbi->s_md_lock);
48418aadd47SBobi Jam }
4851c13d5c0STheodore Ts'o 
4861dc1097fSJan Kara static bool system_going_down(void)
4871dc1097fSJan Kara {
4881dc1097fSJan Kara 	return system_state == SYSTEM_HALT || system_state == SYSTEM_POWER_OFF
4891dc1097fSJan Kara 		|| system_state == SYSTEM_RESTART;
4901dc1097fSJan Kara }
4911dc1097fSJan Kara 
492ac27a0ecSDave Kleikamp /* Deal with the reporting of failure conditions on a filesystem such as
493ac27a0ecSDave Kleikamp  * inconsistencies detected or read IO failures.
494ac27a0ecSDave Kleikamp  *
495ac27a0ecSDave Kleikamp  * On ext2, we can store the error state of the filesystem in the
496617ba13bSMingming Cao  * superblock.  That is not possible on ext4, because we may have other
497ac27a0ecSDave Kleikamp  * write ordering constraints on the superblock which prevent us from
498ac27a0ecSDave Kleikamp  * writing it out straight away; and given that the journal is about to
499ac27a0ecSDave Kleikamp  * be aborted, we can't rely on the current, or future, transactions to
500ac27a0ecSDave Kleikamp  * write out the superblock safely.
501ac27a0ecSDave Kleikamp  *
502dab291afSMingming Cao  * We'll just use the jbd2_journal_abort() error code to record an error in
503d6b198bcSThadeu Lima de Souza Cascardo  * the journal instead.  On recovery, the journal will complain about
504ac27a0ecSDave Kleikamp  * that error until we've noted it down and cleared it.
505ac27a0ecSDave Kleikamp  */
506ac27a0ecSDave Kleikamp 
507617ba13bSMingming Cao static void ext4_handle_error(struct super_block *sb)
508ac27a0ecSDave Kleikamp {
509327eaf73STheodore Ts'o 	if (test_opt(sb, WARN_ON_ERROR))
510327eaf73STheodore Ts'o 		WARN_ON_ONCE(1);
511327eaf73STheodore Ts'o 
512bc98a42cSDavid Howells 	if (sb_rdonly(sb))
513ac27a0ecSDave Kleikamp 		return;
514ac27a0ecSDave Kleikamp 
515ac27a0ecSDave Kleikamp 	if (!test_opt(sb, ERRORS_CONT)) {
516617ba13bSMingming Cao 		journal_t *journal = EXT4_SB(sb)->s_journal;
517ac27a0ecSDave Kleikamp 
5184ab2f15bSTheodore Ts'o 		EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED;
519ac27a0ecSDave Kleikamp 		if (journal)
520dab291afSMingming Cao 			jbd2_journal_abort(journal, -EIO);
521ac27a0ecSDave Kleikamp 	}
5221dc1097fSJan Kara 	/*
5231dc1097fSJan Kara 	 * We force ERRORS_RO behavior when system is rebooting. Otherwise we
5241dc1097fSJan Kara 	 * could panic during 'reboot -f' as the underlying device got already
5251dc1097fSJan Kara 	 * disabled.
5261dc1097fSJan Kara 	 */
5271dc1097fSJan Kara 	if (test_opt(sb, ERRORS_RO) || system_going_down()) {
528b31e1552SEric Sandeen 		ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");
5294418e141SDmitry Monakhov 		/*
5304418e141SDmitry Monakhov 		 * Make sure updated value of ->s_mount_flags will be visible
5314418e141SDmitry Monakhov 		 * before ->s_flags update
5324418e141SDmitry Monakhov 		 */
5334418e141SDmitry Monakhov 		smp_wmb();
5341751e8a6SLinus Torvalds 		sb->s_flags |= SB_RDONLY;
5351dc1097fSJan Kara 	} else if (test_opt(sb, ERRORS_PANIC)) {
536617ba13bSMingming Cao 		panic("EXT4-fs (device %s): panic forced after error\n",
537ac27a0ecSDave Kleikamp 			sb->s_id);
538ac27a0ecSDave Kleikamp 	}
5394327ba52SDaeho Jeong }
540ac27a0ecSDave Kleikamp 
541efbed4dcSTheodore Ts'o #define ext4_error_ratelimit(sb)					\
542efbed4dcSTheodore Ts'o 		___ratelimit(&(EXT4_SB(sb)->s_err_ratelimit_state),	\
543efbed4dcSTheodore Ts'o 			     "EXT4-fs error")
544efbed4dcSTheodore Ts'o 
54512062dddSEric Sandeen void __ext4_error(struct super_block *sb, const char *function,
54654d3adbcSTheodore Ts'o 		  unsigned int line, int error, __u64 block,
54754d3adbcSTheodore Ts'o 		  const char *fmt, ...)
548ac27a0ecSDave Kleikamp {
5490ff2ea7dSJoe Perches 	struct va_format vaf;
550ac27a0ecSDave Kleikamp 	va_list args;
551ac27a0ecSDave Kleikamp 
5520db1ff22STheodore Ts'o 	if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
5530db1ff22STheodore Ts'o 		return;
5540db1ff22STheodore Ts'o 
555ccf0f32aSTheodore Ts'o 	trace_ext4_error(sb, function, line);
556efbed4dcSTheodore Ts'o 	if (ext4_error_ratelimit(sb)) {
557ac27a0ecSDave Kleikamp 		va_start(args, fmt);
5580ff2ea7dSJoe Perches 		vaf.fmt = fmt;
5590ff2ea7dSJoe Perches 		vaf.va = &args;
560efbed4dcSTheodore Ts'o 		printk(KERN_CRIT
561efbed4dcSTheodore Ts'o 		       "EXT4-fs error (device %s): %s:%d: comm %s: %pV\n",
5620ff2ea7dSJoe Perches 		       sb->s_id, function, line, current->comm, &vaf);
563ac27a0ecSDave Kleikamp 		va_end(args);
564efbed4dcSTheodore Ts'o 	}
56554d3adbcSTheodore Ts'o 	save_error_info(sb, error, 0, block, function, line);
566617ba13bSMingming Cao 	ext4_handle_error(sb);
567ac27a0ecSDave Kleikamp }
568ac27a0ecSDave Kleikamp 
569e7c96e8eSJoe Perches void __ext4_error_inode(struct inode *inode, const char *function,
57054d3adbcSTheodore Ts'o 			unsigned int line, ext4_fsblk_t block, int error,
571273df556SFrank Mayhar 			const char *fmt, ...)
572273df556SFrank Mayhar {
573273df556SFrank Mayhar 	va_list args;
574f7c21177STheodore Ts'o 	struct va_format vaf;
575273df556SFrank Mayhar 
5760db1ff22STheodore Ts'o 	if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
5770db1ff22STheodore Ts'o 		return;
5780db1ff22STheodore Ts'o 
579ccf0f32aSTheodore Ts'o 	trace_ext4_error(inode->i_sb, function, line);
580efbed4dcSTheodore Ts'o 	if (ext4_error_ratelimit(inode->i_sb)) {
581273df556SFrank Mayhar 		va_start(args, fmt);
582f7c21177STheodore Ts'o 		vaf.fmt = fmt;
583f7c21177STheodore Ts'o 		vaf.va = &args;
584c398eda0STheodore Ts'o 		if (block)
585d9ee81daSJoe Perches 			printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: "
586d9ee81daSJoe Perches 			       "inode #%lu: block %llu: comm %s: %pV\n",
587d9ee81daSJoe Perches 			       inode->i_sb->s_id, function, line, inode->i_ino,
588d9ee81daSJoe Perches 			       block, current->comm, &vaf);
589d9ee81daSJoe Perches 		else
590d9ee81daSJoe Perches 			printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: "
591d9ee81daSJoe Perches 			       "inode #%lu: comm %s: %pV\n",
592d9ee81daSJoe Perches 			       inode->i_sb->s_id, function, line, inode->i_ino,
593d9ee81daSJoe Perches 			       current->comm, &vaf);
594273df556SFrank Mayhar 		va_end(args);
595efbed4dcSTheodore Ts'o 	}
59654d3adbcSTheodore Ts'o 	save_error_info(inode->i_sb, error, inode->i_ino, block,
59754d3adbcSTheodore Ts'o 			function, line);
598273df556SFrank Mayhar 	ext4_handle_error(inode->i_sb);
599273df556SFrank Mayhar }
600273df556SFrank Mayhar 
601e7c96e8eSJoe Perches void __ext4_error_file(struct file *file, const char *function,
602f7c21177STheodore Ts'o 		       unsigned int line, ext4_fsblk_t block,
603f7c21177STheodore Ts'o 		       const char *fmt, ...)
604273df556SFrank Mayhar {
605273df556SFrank Mayhar 	va_list args;
606f7c21177STheodore Ts'o 	struct va_format vaf;
607496ad9aaSAl Viro 	struct inode *inode = file_inode(file);
608273df556SFrank Mayhar 	char pathname[80], *path;
609273df556SFrank Mayhar 
6100db1ff22STheodore Ts'o 	if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb))))
6110db1ff22STheodore Ts'o 		return;
6120db1ff22STheodore Ts'o 
613ccf0f32aSTheodore Ts'o 	trace_ext4_error(inode->i_sb, function, line);
614efbed4dcSTheodore Ts'o 	if (ext4_error_ratelimit(inode->i_sb)) {
6159bf39ab2SMiklos Szeredi 		path = file_path(file, pathname, sizeof(pathname));
616f9a62d09SDan Carpenter 		if (IS_ERR(path))
617273df556SFrank Mayhar 			path = "(unknown)";
618f7c21177STheodore Ts'o 		va_start(args, fmt);
619f7c21177STheodore Ts'o 		vaf.fmt = fmt;
620f7c21177STheodore Ts'o 		vaf.va = &args;
621d9ee81daSJoe Perches 		if (block)
622d9ee81daSJoe Perches 			printk(KERN_CRIT
623d9ee81daSJoe Perches 			       "EXT4-fs error (device %s): %s:%d: inode #%lu: "
624d9ee81daSJoe Perches 			       "block %llu: comm %s: path %s: %pV\n",
625d9ee81daSJoe Perches 			       inode->i_sb->s_id, function, line, inode->i_ino,
626d9ee81daSJoe Perches 			       block, current->comm, path, &vaf);
627d9ee81daSJoe Perches 		else
628d9ee81daSJoe Perches 			printk(KERN_CRIT
629d9ee81daSJoe Perches 			       "EXT4-fs error (device %s): %s:%d: inode #%lu: "
630d9ee81daSJoe Perches 			       "comm %s: path %s: %pV\n",
631d9ee81daSJoe Perches 			       inode->i_sb->s_id, function, line, inode->i_ino,
632d9ee81daSJoe Perches 			       current->comm, path, &vaf);
633273df556SFrank Mayhar 		va_end(args);
634efbed4dcSTheodore Ts'o 	}
63554d3adbcSTheodore Ts'o 	save_error_info(inode->i_sb, EFSCORRUPTED, inode->i_ino, block,
63654d3adbcSTheodore Ts'o 			function, line);
637273df556SFrank Mayhar 	ext4_handle_error(inode->i_sb);
638273df556SFrank Mayhar }
639273df556SFrank Mayhar 
640722887ddSTheodore Ts'o const char *ext4_decode_error(struct super_block *sb, int errno,
641ac27a0ecSDave Kleikamp 			      char nbuf[16])
642ac27a0ecSDave Kleikamp {
643ac27a0ecSDave Kleikamp 	char *errstr = NULL;
644ac27a0ecSDave Kleikamp 
645ac27a0ecSDave Kleikamp 	switch (errno) {
6466a797d27SDarrick J. Wong 	case -EFSCORRUPTED:
6476a797d27SDarrick J. Wong 		errstr = "Corrupt filesystem";
6486a797d27SDarrick J. Wong 		break;
6496a797d27SDarrick J. Wong 	case -EFSBADCRC:
6506a797d27SDarrick J. Wong 		errstr = "Filesystem failed CRC";
6516a797d27SDarrick J. Wong 		break;
652ac27a0ecSDave Kleikamp 	case -EIO:
653ac27a0ecSDave Kleikamp 		errstr = "IO failure";
654ac27a0ecSDave Kleikamp 		break;
655ac27a0ecSDave Kleikamp 	case -ENOMEM:
656ac27a0ecSDave Kleikamp 		errstr = "Out of memory";
657ac27a0ecSDave Kleikamp 		break;
658ac27a0ecSDave Kleikamp 	case -EROFS:
65978f1ddbbSTheodore Ts'o 		if (!sb || (EXT4_SB(sb)->s_journal &&
66078f1ddbbSTheodore Ts'o 			    EXT4_SB(sb)->s_journal->j_flags & JBD2_ABORT))
661ac27a0ecSDave Kleikamp 			errstr = "Journal has aborted";
662ac27a0ecSDave Kleikamp 		else
663ac27a0ecSDave Kleikamp 			errstr = "Readonly filesystem";
664ac27a0ecSDave Kleikamp 		break;
665ac27a0ecSDave Kleikamp 	default:
666ac27a0ecSDave Kleikamp 		/* If the caller passed in an extra buffer for unknown
667ac27a0ecSDave Kleikamp 		 * errors, textualise them now.  Else we just return
668ac27a0ecSDave Kleikamp 		 * NULL. */
669ac27a0ecSDave Kleikamp 		if (nbuf) {
670ac27a0ecSDave Kleikamp 			/* Check for truncated error codes... */
671ac27a0ecSDave Kleikamp 			if (snprintf(nbuf, 16, "error %d", -errno) >= 0)
672ac27a0ecSDave Kleikamp 				errstr = nbuf;
673ac27a0ecSDave Kleikamp 		}
674ac27a0ecSDave Kleikamp 		break;
675ac27a0ecSDave Kleikamp 	}
676ac27a0ecSDave Kleikamp 
677ac27a0ecSDave Kleikamp 	return errstr;
678ac27a0ecSDave Kleikamp }
679ac27a0ecSDave Kleikamp 
680617ba13bSMingming Cao /* __ext4_std_error decodes expected errors from journaling functions
681ac27a0ecSDave Kleikamp  * automatically and invokes the appropriate error response.  */
682ac27a0ecSDave Kleikamp 
683c398eda0STheodore Ts'o void __ext4_std_error(struct super_block *sb, const char *function,
684c398eda0STheodore Ts'o 		      unsigned int line, int errno)
685ac27a0ecSDave Kleikamp {
686ac27a0ecSDave Kleikamp 	char nbuf[16];
687ac27a0ecSDave Kleikamp 	const char *errstr;
688ac27a0ecSDave Kleikamp 
6890db1ff22STheodore Ts'o 	if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
6900db1ff22STheodore Ts'o 		return;
6910db1ff22STheodore Ts'o 
692ac27a0ecSDave Kleikamp 	/* Special case: if the error is EROFS, and we're not already
693ac27a0ecSDave Kleikamp 	 * inside a transaction, then there's really no point in logging
694ac27a0ecSDave Kleikamp 	 * an error. */
695bc98a42cSDavid Howells 	if (errno == -EROFS && journal_current_handle() == NULL && sb_rdonly(sb))
696ac27a0ecSDave Kleikamp 		return;
697ac27a0ecSDave Kleikamp 
698efbed4dcSTheodore Ts'o 	if (ext4_error_ratelimit(sb)) {
699617ba13bSMingming Cao 		errstr = ext4_decode_error(sb, errno, nbuf);
700c398eda0STheodore Ts'o 		printk(KERN_CRIT "EXT4-fs error (device %s) in %s:%d: %s\n",
701c398eda0STheodore Ts'o 		       sb->s_id, function, line, errstr);
702efbed4dcSTheodore Ts'o 	}
703ac27a0ecSDave Kleikamp 
70454d3adbcSTheodore Ts'o 	save_error_info(sb, -errno, 0, 0, function, line);
705617ba13bSMingming Cao 	ext4_handle_error(sb);
706ac27a0ecSDave Kleikamp }
707ac27a0ecSDave Kleikamp 
708ac27a0ecSDave Kleikamp /*
709617ba13bSMingming Cao  * ext4_abort is a much stronger failure handler than ext4_error.  The
710ac27a0ecSDave Kleikamp  * abort function may be used to deal with unrecoverable failures such
711ac27a0ecSDave Kleikamp  * as journal IO errors or ENOMEM at a critical moment in log management.
712ac27a0ecSDave Kleikamp  *
713ac27a0ecSDave Kleikamp  * We unconditionally force the filesystem into an ABORT|READONLY state,
714ac27a0ecSDave Kleikamp  * unless the error response on the fs has been set to panic in which
715ac27a0ecSDave Kleikamp  * case we take the easy way out and panic immediately.
716ac27a0ecSDave Kleikamp  */
717ac27a0ecSDave Kleikamp 
718c67d859eSTheodore Ts'o void __ext4_abort(struct super_block *sb, const char *function,
71954d3adbcSTheodore Ts'o 		  unsigned int line, int error, const char *fmt, ...)
720ac27a0ecSDave Kleikamp {
721651e1c3bSJoe Perches 	struct va_format vaf;
722ac27a0ecSDave Kleikamp 	va_list args;
723ac27a0ecSDave Kleikamp 
7240db1ff22STheodore Ts'o 	if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
7250db1ff22STheodore Ts'o 		return;
7260db1ff22STheodore Ts'o 
72754d3adbcSTheodore Ts'o 	save_error_info(sb, error, 0, 0, function, line);
728ac27a0ecSDave Kleikamp 	va_start(args, fmt);
729651e1c3bSJoe Perches 	vaf.fmt = fmt;
730651e1c3bSJoe Perches 	vaf.va = &args;
731651e1c3bSJoe Perches 	printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: %pV\n",
732651e1c3bSJoe Perches 	       sb->s_id, function, line, &vaf);
733ac27a0ecSDave Kleikamp 	va_end(args);
734ac27a0ecSDave Kleikamp 
735bc98a42cSDavid Howells 	if (sb_rdonly(sb) == 0) {
7364ab2f15bSTheodore Ts'o 		EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED;
7377b97d868Szhangyi (F) 		if (EXT4_SB(sb)->s_journal)
7387b97d868Szhangyi (F) 			jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO);
7397b97d868Szhangyi (F) 
7407b97d868Szhangyi (F) 		ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");
7414418e141SDmitry Monakhov 		/*
7424418e141SDmitry Monakhov 		 * Make sure updated value of ->s_mount_flags will be visible
7434418e141SDmitry Monakhov 		 * before ->s_flags update
7444418e141SDmitry Monakhov 		 */
7454418e141SDmitry Monakhov 		smp_wmb();
7461751e8a6SLinus Torvalds 		sb->s_flags |= SB_RDONLY;
7471c13d5c0STheodore Ts'o 	}
7487b97d868Szhangyi (F) 	if (test_opt(sb, ERRORS_PANIC) && !system_going_down())
7491c13d5c0STheodore Ts'o 		panic("EXT4-fs panic from previous error\n");
750ac27a0ecSDave Kleikamp }
751ac27a0ecSDave Kleikamp 
752e7c96e8eSJoe Perches void __ext4_msg(struct super_block *sb,
753e7c96e8eSJoe Perches 		const char *prefix, const char *fmt, ...)
754b31e1552SEric Sandeen {
7550ff2ea7dSJoe Perches 	struct va_format vaf;
756b31e1552SEric Sandeen 	va_list args;
757b31e1552SEric Sandeen 
7581cf006edSDmitry Monakhov 	atomic_inc(&EXT4_SB(sb)->s_msg_count);
759efbed4dcSTheodore Ts'o 	if (!___ratelimit(&(EXT4_SB(sb)->s_msg_ratelimit_state), "EXT4-fs"))
760efbed4dcSTheodore Ts'o 		return;
761efbed4dcSTheodore Ts'o 
762b31e1552SEric Sandeen 	va_start(args, fmt);
7630ff2ea7dSJoe Perches 	vaf.fmt = fmt;
7640ff2ea7dSJoe Perches 	vaf.va = &args;
7650ff2ea7dSJoe Perches 	printk("%sEXT4-fs (%s): %pV\n", prefix, sb->s_id, &vaf);
766b31e1552SEric Sandeen 	va_end(args);
767b31e1552SEric Sandeen }
768b31e1552SEric Sandeen 
7691cf006edSDmitry Monakhov static int ext4_warning_ratelimit(struct super_block *sb)
7701cf006edSDmitry Monakhov {
7711cf006edSDmitry Monakhov 	atomic_inc(&EXT4_SB(sb)->s_warning_count);
7721cf006edSDmitry Monakhov 	return ___ratelimit(&(EXT4_SB(sb)->s_warning_ratelimit_state),
7731cf006edSDmitry Monakhov 			    "EXT4-fs warning");
7741cf006edSDmitry Monakhov }
775b03a2f7eSAndreas Dilger 
77612062dddSEric Sandeen void __ext4_warning(struct super_block *sb, const char *function,
777c398eda0STheodore Ts'o 		    unsigned int line, const char *fmt, ...)
778ac27a0ecSDave Kleikamp {
7790ff2ea7dSJoe Perches 	struct va_format vaf;
780ac27a0ecSDave Kleikamp 	va_list args;
781ac27a0ecSDave Kleikamp 
782b03a2f7eSAndreas Dilger 	if (!ext4_warning_ratelimit(sb))
783efbed4dcSTheodore Ts'o 		return;
784efbed4dcSTheodore Ts'o 
785ac27a0ecSDave Kleikamp 	va_start(args, fmt);
7860ff2ea7dSJoe Perches 	vaf.fmt = fmt;
7870ff2ea7dSJoe Perches 	vaf.va = &args;
7880ff2ea7dSJoe Perches 	printk(KERN_WARNING "EXT4-fs warning (device %s): %s:%d: %pV\n",
7890ff2ea7dSJoe Perches 	       sb->s_id, function, line, &vaf);
790ac27a0ecSDave Kleikamp 	va_end(args);
791ac27a0ecSDave Kleikamp }
792ac27a0ecSDave Kleikamp 
793b03a2f7eSAndreas Dilger void __ext4_warning_inode(const struct inode *inode, const char *function,
794b03a2f7eSAndreas Dilger 			  unsigned int line, const char *fmt, ...)
795b03a2f7eSAndreas Dilger {
796b03a2f7eSAndreas Dilger 	struct va_format vaf;
797b03a2f7eSAndreas Dilger 	va_list args;
798b03a2f7eSAndreas Dilger 
799b03a2f7eSAndreas Dilger 	if (!ext4_warning_ratelimit(inode->i_sb))
800b03a2f7eSAndreas Dilger 		return;
801b03a2f7eSAndreas Dilger 
802b03a2f7eSAndreas Dilger 	va_start(args, fmt);
803b03a2f7eSAndreas Dilger 	vaf.fmt = fmt;
804b03a2f7eSAndreas Dilger 	vaf.va = &args;
805b03a2f7eSAndreas Dilger 	printk(KERN_WARNING "EXT4-fs warning (device %s): %s:%d: "
806b03a2f7eSAndreas Dilger 	       "inode #%lu: comm %s: %pV\n", inode->i_sb->s_id,
807b03a2f7eSAndreas Dilger 	       function, line, inode->i_ino, current->comm, &vaf);
808b03a2f7eSAndreas Dilger 	va_end(args);
809b03a2f7eSAndreas Dilger }
810b03a2f7eSAndreas Dilger 
811e29136f8STheodore Ts'o void __ext4_grp_locked_error(const char *function, unsigned int line,
812e29136f8STheodore Ts'o 			     struct super_block *sb, ext4_group_t grp,
813e29136f8STheodore Ts'o 			     unsigned long ino, ext4_fsblk_t block,
814e29136f8STheodore Ts'o 			     const char *fmt, ...)
8155d1b1b3fSAneesh Kumar K.V __releases(bitlock)
8165d1b1b3fSAneesh Kumar K.V __acquires(bitlock)
8175d1b1b3fSAneesh Kumar K.V {
8180ff2ea7dSJoe Perches 	struct va_format vaf;
8195d1b1b3fSAneesh Kumar K.V 	va_list args;
8205d1b1b3fSAneesh Kumar K.V 
8210db1ff22STheodore Ts'o 	if (unlikely(ext4_forced_shutdown(EXT4_SB(sb))))
8220db1ff22STheodore Ts'o 		return;
8230db1ff22STheodore Ts'o 
824ccf0f32aSTheodore Ts'o 	trace_ext4_error(sb, function, line);
82554d3adbcSTheodore Ts'o 	__save_error_info(sb, EFSCORRUPTED, ino, block, function, line);
8260ff2ea7dSJoe Perches 
827efbed4dcSTheodore Ts'o 	if (ext4_error_ratelimit(sb)) {
8285d1b1b3fSAneesh Kumar K.V 		va_start(args, fmt);
8290ff2ea7dSJoe Perches 		vaf.fmt = fmt;
8300ff2ea7dSJoe Perches 		vaf.va = &args;
83121149d61SRobin Dong 		printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: group %u, ",
832e29136f8STheodore Ts'o 		       sb->s_id, function, line, grp);
833e29136f8STheodore Ts'o 		if (ino)
8340ff2ea7dSJoe Perches 			printk(KERN_CONT "inode %lu: ", ino);
835e29136f8STheodore Ts'o 		if (block)
836efbed4dcSTheodore Ts'o 			printk(KERN_CONT "block %llu:",
837efbed4dcSTheodore Ts'o 			       (unsigned long long) block);
8380ff2ea7dSJoe Perches 		printk(KERN_CONT "%pV\n", &vaf);
8395d1b1b3fSAneesh Kumar K.V 		va_end(args);
840efbed4dcSTheodore Ts'o 	}
8415d1b1b3fSAneesh Kumar K.V 
842327eaf73STheodore Ts'o 	if (test_opt(sb, WARN_ON_ERROR))
843327eaf73STheodore Ts'o 		WARN_ON_ONCE(1);
844327eaf73STheodore Ts'o 
8455d1b1b3fSAneesh Kumar K.V 	if (test_opt(sb, ERRORS_CONT)) {
846e2d67052STheodore Ts'o 		ext4_commit_super(sb, 0);
8475d1b1b3fSAneesh Kumar K.V 		return;
8485d1b1b3fSAneesh Kumar K.V 	}
8491c13d5c0STheodore Ts'o 
8505d1b1b3fSAneesh Kumar K.V 	ext4_unlock_group(sb, grp);
85106f29cc8SZhouyi Zhou 	ext4_commit_super(sb, 1);
8525d1b1b3fSAneesh Kumar K.V 	ext4_handle_error(sb);
8535d1b1b3fSAneesh Kumar K.V 	/*
8545d1b1b3fSAneesh Kumar K.V 	 * We only get here in the ERRORS_RO case; relocking the group
8555d1b1b3fSAneesh Kumar K.V 	 * may be dangerous, but nothing bad will happen since the
8565d1b1b3fSAneesh Kumar K.V 	 * filesystem will have already been marked read/only and the
8575d1b1b3fSAneesh Kumar K.V 	 * journal has been aborted.  We return 1 as a hint to callers
8585d1b1b3fSAneesh Kumar K.V 	 * who might what to use the return value from
85925985edcSLucas De Marchi 	 * ext4_grp_locked_error() to distinguish between the
8605d1b1b3fSAneesh Kumar K.V 	 * ERRORS_CONT and ERRORS_RO case, and perhaps return more
8615d1b1b3fSAneesh Kumar K.V 	 * aggressively from the ext4 function in question, with a
8625d1b1b3fSAneesh Kumar K.V 	 * more appropriate error code.
8635d1b1b3fSAneesh Kumar K.V 	 */
8645d1b1b3fSAneesh Kumar K.V 	ext4_lock_group(sb, grp);
8655d1b1b3fSAneesh Kumar K.V 	return;
8665d1b1b3fSAneesh Kumar K.V }
8675d1b1b3fSAneesh Kumar K.V 
868db79e6d1SWang Shilong void ext4_mark_group_bitmap_corrupted(struct super_block *sb,
869db79e6d1SWang Shilong 				     ext4_group_t group,
870db79e6d1SWang Shilong 				     unsigned int flags)
871db79e6d1SWang Shilong {
872db79e6d1SWang Shilong 	struct ext4_sb_info *sbi = EXT4_SB(sb);
873db79e6d1SWang Shilong 	struct ext4_group_info *grp = ext4_get_group_info(sb, group);
874db79e6d1SWang Shilong 	struct ext4_group_desc *gdp = ext4_get_group_desc(sb, group, NULL);
8759af0b3d1SWang Shilong 	int ret;
876db79e6d1SWang Shilong 
8779af0b3d1SWang Shilong 	if (flags & EXT4_GROUP_INFO_BBITMAP_CORRUPT) {
8789af0b3d1SWang Shilong 		ret = ext4_test_and_set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT,
8799af0b3d1SWang Shilong 					    &grp->bb_state);
8809af0b3d1SWang Shilong 		if (!ret)
881db79e6d1SWang Shilong 			percpu_counter_sub(&sbi->s_freeclusters_counter,
882db79e6d1SWang Shilong 					   grp->bb_free);
883db79e6d1SWang Shilong 	}
884db79e6d1SWang Shilong 
8859af0b3d1SWang Shilong 	if (flags & EXT4_GROUP_INFO_IBITMAP_CORRUPT) {
8869af0b3d1SWang Shilong 		ret = ext4_test_and_set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT,
8879af0b3d1SWang Shilong 					    &grp->bb_state);
8889af0b3d1SWang Shilong 		if (!ret && gdp) {
889db79e6d1SWang Shilong 			int count;
890db79e6d1SWang Shilong 
891db79e6d1SWang Shilong 			count = ext4_free_inodes_count(sb, gdp);
892db79e6d1SWang Shilong 			percpu_counter_sub(&sbi->s_freeinodes_counter,
893db79e6d1SWang Shilong 					   count);
894db79e6d1SWang Shilong 		}
895db79e6d1SWang Shilong 	}
896db79e6d1SWang Shilong }
897db79e6d1SWang Shilong 
898617ba13bSMingming Cao void ext4_update_dynamic_rev(struct super_block *sb)
899ac27a0ecSDave Kleikamp {
900617ba13bSMingming Cao 	struct ext4_super_block *es = EXT4_SB(sb)->s_es;
901ac27a0ecSDave Kleikamp 
902617ba13bSMingming Cao 	if (le32_to_cpu(es->s_rev_level) > EXT4_GOOD_OLD_REV)
903ac27a0ecSDave Kleikamp 		return;
904ac27a0ecSDave Kleikamp 
90512062dddSEric Sandeen 	ext4_warning(sb,
906ac27a0ecSDave Kleikamp 		     "updating to rev %d because of new feature flag, "
907ac27a0ecSDave Kleikamp 		     "running e2fsck is recommended",
908617ba13bSMingming Cao 		     EXT4_DYNAMIC_REV);
909ac27a0ecSDave Kleikamp 
910617ba13bSMingming Cao 	es->s_first_ino = cpu_to_le32(EXT4_GOOD_OLD_FIRST_INO);
911617ba13bSMingming Cao 	es->s_inode_size = cpu_to_le16(EXT4_GOOD_OLD_INODE_SIZE);
912617ba13bSMingming Cao 	es->s_rev_level = cpu_to_le32(EXT4_DYNAMIC_REV);
913ac27a0ecSDave Kleikamp 	/* leave es->s_feature_*compat flags alone */
914ac27a0ecSDave Kleikamp 	/* es->s_uuid will be set by e2fsck if empty */
915ac27a0ecSDave Kleikamp 
916ac27a0ecSDave Kleikamp 	/*
917ac27a0ecSDave Kleikamp 	 * The rest of the superblock fields should be zero, and if not it
918ac27a0ecSDave Kleikamp 	 * means they are likely already in use, so leave them alone.  We
919ac27a0ecSDave Kleikamp 	 * can leave it up to e2fsck to clean up any inconsistencies there.
920ac27a0ecSDave Kleikamp 	 */
921ac27a0ecSDave Kleikamp }
922ac27a0ecSDave Kleikamp 
923ac27a0ecSDave Kleikamp /*
924ac27a0ecSDave Kleikamp  * Open the external journal device
925ac27a0ecSDave Kleikamp  */
926b31e1552SEric Sandeen static struct block_device *ext4_blkdev_get(dev_t dev, struct super_block *sb)
927ac27a0ecSDave Kleikamp {
928ac27a0ecSDave Kleikamp 	struct block_device *bdev;
929ac27a0ecSDave Kleikamp 
930d4d77629STejun Heo 	bdev = blkdev_get_by_dev(dev, FMODE_READ|FMODE_WRITE|FMODE_EXCL, sb);
931ac27a0ecSDave Kleikamp 	if (IS_ERR(bdev))
932ac27a0ecSDave Kleikamp 		goto fail;
933ac27a0ecSDave Kleikamp 	return bdev;
934ac27a0ecSDave Kleikamp 
935ac27a0ecSDave Kleikamp fail:
936ea3edd4dSChristoph Hellwig 	ext4_msg(sb, KERN_ERR,
937ea3edd4dSChristoph Hellwig 		 "failed to open journal device unknown-block(%u,%u) %ld",
938ea3edd4dSChristoph Hellwig 		 MAJOR(dev), MINOR(dev), PTR_ERR(bdev));
939ac27a0ecSDave Kleikamp 	return NULL;
940ac27a0ecSDave Kleikamp }
941ac27a0ecSDave Kleikamp 
942ac27a0ecSDave Kleikamp /*
943ac27a0ecSDave Kleikamp  * Release the journal device
944ac27a0ecSDave Kleikamp  */
9454385bab1SAl Viro static void ext4_blkdev_put(struct block_device *bdev)
946ac27a0ecSDave Kleikamp {
9474385bab1SAl Viro 	blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
948ac27a0ecSDave Kleikamp }
949ac27a0ecSDave Kleikamp 
9504385bab1SAl Viro static void ext4_blkdev_remove(struct ext4_sb_info *sbi)
951ac27a0ecSDave Kleikamp {
952ac27a0ecSDave Kleikamp 	struct block_device *bdev;
953ee7ed3aaSChunguang Xu 	bdev = sbi->s_journal_bdev;
954ac27a0ecSDave Kleikamp 	if (bdev) {
9554385bab1SAl Viro 		ext4_blkdev_put(bdev);
956ee7ed3aaSChunguang Xu 		sbi->s_journal_bdev = NULL;
957ac27a0ecSDave Kleikamp 	}
958ac27a0ecSDave Kleikamp }
959ac27a0ecSDave Kleikamp 
960ac27a0ecSDave Kleikamp static inline struct inode *orphan_list_entry(struct list_head *l)
961ac27a0ecSDave Kleikamp {
962617ba13bSMingming Cao 	return &list_entry(l, struct ext4_inode_info, i_orphan)->vfs_inode;
963ac27a0ecSDave Kleikamp }
964ac27a0ecSDave Kleikamp 
965617ba13bSMingming Cao static void dump_orphan_list(struct super_block *sb, struct ext4_sb_info *sbi)
966ac27a0ecSDave Kleikamp {
967ac27a0ecSDave Kleikamp 	struct list_head *l;
968ac27a0ecSDave Kleikamp 
969b31e1552SEric Sandeen 	ext4_msg(sb, KERN_ERR, "sb orphan head is %d",
970ac27a0ecSDave Kleikamp 		 le32_to_cpu(sbi->s_es->s_last_orphan));
971ac27a0ecSDave Kleikamp 
972ac27a0ecSDave Kleikamp 	printk(KERN_ERR "sb_info orphan list:\n");
973ac27a0ecSDave Kleikamp 	list_for_each(l, &sbi->s_orphan) {
974ac27a0ecSDave Kleikamp 		struct inode *inode = orphan_list_entry(l);
975ac27a0ecSDave Kleikamp 		printk(KERN_ERR "  "
976ac27a0ecSDave Kleikamp 		       "inode %s:%lu at %p: mode %o, nlink %d, next %d\n",
977ac27a0ecSDave Kleikamp 		       inode->i_sb->s_id, inode->i_ino, inode,
978ac27a0ecSDave Kleikamp 		       inode->i_mode, inode->i_nlink,
979ac27a0ecSDave Kleikamp 		       NEXT_ORPHAN(inode));
980ac27a0ecSDave Kleikamp 	}
981ac27a0ecSDave Kleikamp }
982ac27a0ecSDave Kleikamp 
983957153fcSJan Kara #ifdef CONFIG_QUOTA
984957153fcSJan Kara static int ext4_quota_off(struct super_block *sb, int type);
985957153fcSJan Kara 
986957153fcSJan Kara static inline void ext4_quota_off_umount(struct super_block *sb)
987957153fcSJan Kara {
988957153fcSJan Kara 	int type;
989957153fcSJan Kara 
990957153fcSJan Kara 	/* Use our quota_off function to clear inode flags etc. */
991957153fcSJan Kara 	for (type = 0; type < EXT4_MAXQUOTAS; type++)
992957153fcSJan Kara 		ext4_quota_off(sb, type);
993957153fcSJan Kara }
99433458eabSTheodore Ts'o 
99533458eabSTheodore Ts'o /*
99633458eabSTheodore Ts'o  * This is a helper function which is used in the mount/remount
99733458eabSTheodore Ts'o  * codepaths (which holds s_umount) to fetch the quota file name.
99833458eabSTheodore Ts'o  */
99933458eabSTheodore Ts'o static inline char *get_qf_name(struct super_block *sb,
100033458eabSTheodore Ts'o 				struct ext4_sb_info *sbi,
100133458eabSTheodore Ts'o 				int type)
100233458eabSTheodore Ts'o {
100333458eabSTheodore Ts'o 	return rcu_dereference_protected(sbi->s_qf_names[type],
100433458eabSTheodore Ts'o 					 lockdep_is_held(&sb->s_umount));
100533458eabSTheodore Ts'o }
1006957153fcSJan Kara #else
1007957153fcSJan Kara static inline void ext4_quota_off_umount(struct super_block *sb)
1008957153fcSJan Kara {
1009957153fcSJan Kara }
1010957153fcSJan Kara #endif
1011957153fcSJan Kara 
1012617ba13bSMingming Cao static void ext4_put_super(struct super_block *sb)
1013ac27a0ecSDave Kleikamp {
1014617ba13bSMingming Cao 	struct ext4_sb_info *sbi = EXT4_SB(sb);
1015617ba13bSMingming Cao 	struct ext4_super_block *es = sbi->s_es;
10161d0c3924STheodore Ts'o 	struct buffer_head **group_desc;
10177c990728SSuraj Jitindar Singh 	struct flex_groups **flex_groups;
101897abd7d4STheodore Ts'o 	int aborted = 0;
1019ef2cabf7SHidehiro Kawai 	int i, err;
1020ac27a0ecSDave Kleikamp 
1021857ac889SLukas Czerner 	ext4_unregister_li_request(sb);
1022957153fcSJan Kara 	ext4_quota_off_umount(sb);
1023e0ccfd95SChristoph Hellwig 
10242e8fa54eSJan Kara 	destroy_workqueue(sbi->rsv_conversion_wq);
10254c0425ffSMingming Cao 
10265e47868fSRitesh Harjani 	/*
10275e47868fSRitesh Harjani 	 * Unregister sysfs before destroying jbd2 journal.
10285e47868fSRitesh Harjani 	 * Since we could still access attr_journal_task attribute via sysfs
10295e47868fSRitesh Harjani 	 * path which could have sbi->s_journal->j_task as NULL
10305e47868fSRitesh Harjani 	 */
10315e47868fSRitesh Harjani 	ext4_unregister_sysfs(sb);
10325e47868fSRitesh Harjani 
10330390131bSFrank Mayhar 	if (sbi->s_journal) {
103497abd7d4STheodore Ts'o 		aborted = is_journal_aborted(sbi->s_journal);
1035ef2cabf7SHidehiro Kawai 		err = jbd2_journal_destroy(sbi->s_journal);
103647b4a50bSJan Kara 		sbi->s_journal = NULL;
1037878520acSTheodore Ts'o 		if ((err < 0) && !aborted) {
103854d3adbcSTheodore Ts'o 			ext4_abort(sb, -err, "Couldn't clean up the journal");
10390390131bSFrank Mayhar 		}
1040878520acSTheodore Ts'o 	}
1041d4edac31SJosef Bacik 
1042d3922a77SZheng Liu 	ext4_es_unregister_shrinker(sbi);
10439105bb14SAl Viro 	del_timer_sync(&sbi->s_err_report);
1044d4edac31SJosef Bacik 	ext4_release_system_zone(sb);
1045d4edac31SJosef Bacik 	ext4_mb_release(sb);
1046d4edac31SJosef Bacik 	ext4_ext_release(sb);
1047d4edac31SJosef Bacik 
1048bc98a42cSDavid Howells 	if (!sb_rdonly(sb) && !aborted) {
1049e2b911c5SDarrick J. Wong 		ext4_clear_feature_journal_needs_recovery(sb);
1050ac27a0ecSDave Kleikamp 		es->s_state = cpu_to_le16(sbi->s_mount_state);
1051ac27a0ecSDave Kleikamp 	}
1052bc98a42cSDavid Howells 	if (!sb_rdonly(sb))
1053a8e25a83SArtem Bityutskiy 		ext4_commit_super(sb, 1);
1054a8e25a83SArtem Bityutskiy 
10551d0c3924STheodore Ts'o 	rcu_read_lock();
10561d0c3924STheodore Ts'o 	group_desc = rcu_dereference(sbi->s_group_desc);
1057ac27a0ecSDave Kleikamp 	for (i = 0; i < sbi->s_gdb_count; i++)
10581d0c3924STheodore Ts'o 		brelse(group_desc[i]);
10591d0c3924STheodore Ts'o 	kvfree(group_desc);
10607c990728SSuraj Jitindar Singh 	flex_groups = rcu_dereference(sbi->s_flex_groups);
10617c990728SSuraj Jitindar Singh 	if (flex_groups) {
10627c990728SSuraj Jitindar Singh 		for (i = 0; i < sbi->s_flex_groups_allocated; i++)
10637c990728SSuraj Jitindar Singh 			kvfree(flex_groups[i]);
10647c990728SSuraj Jitindar Singh 		kvfree(flex_groups);
10657c990728SSuraj Jitindar Singh 	}
10661d0c3924STheodore Ts'o 	rcu_read_unlock();
106757042651STheodore Ts'o 	percpu_counter_destroy(&sbi->s_freeclusters_counter);
1068ac27a0ecSDave Kleikamp 	percpu_counter_destroy(&sbi->s_freeinodes_counter);
1069ac27a0ecSDave Kleikamp 	percpu_counter_destroy(&sbi->s_dirs_counter);
107057042651STheodore Ts'o 	percpu_counter_destroy(&sbi->s_dirtyclusters_counter);
1071bbd55937SEric Biggers 	percpu_free_rwsem(&sbi->s_writepages_rwsem);
1072ac27a0ecSDave Kleikamp #ifdef CONFIG_QUOTA
1073a2d4a646SJan Kara 	for (i = 0; i < EXT4_MAXQUOTAS; i++)
107433458eabSTheodore Ts'o 		kfree(get_qf_name(sb, sbi, i));
1075ac27a0ecSDave Kleikamp #endif
1076ac27a0ecSDave Kleikamp 
1077ac27a0ecSDave Kleikamp 	/* Debugging code just in case the in-memory inode orphan list
1078ac27a0ecSDave Kleikamp 	 * isn't empty.  The on-disk one can be non-empty if we've
1079ac27a0ecSDave Kleikamp 	 * detected an error and taken the fs readonly, but the
1080ac27a0ecSDave Kleikamp 	 * in-memory list had better be clean by this point. */
1081ac27a0ecSDave Kleikamp 	if (!list_empty(&sbi->s_orphan))
1082ac27a0ecSDave Kleikamp 		dump_orphan_list(sb, sbi);
1083ac27a0ecSDave Kleikamp 	J_ASSERT(list_empty(&sbi->s_orphan));
1084ac27a0ecSDave Kleikamp 
108589d96a6fSTheodore Ts'o 	sync_blockdev(sb->s_bdev);
1086f98393a6SPeter Zijlstra 	invalidate_bdev(sb->s_bdev);
1087ee7ed3aaSChunguang Xu 	if (sbi->s_journal_bdev && sbi->s_journal_bdev != sb->s_bdev) {
1088ac27a0ecSDave Kleikamp 		/*
1089ac27a0ecSDave Kleikamp 		 * Invalidate the journal device's buffers.  We don't want them
1090ac27a0ecSDave Kleikamp 		 * floating about in memory - the physical journal device may
1091ac27a0ecSDave Kleikamp 		 * hotswapped, and it breaks the `ro-after' testing code.
1092ac27a0ecSDave Kleikamp 		 */
1093ee7ed3aaSChunguang Xu 		sync_blockdev(sbi->s_journal_bdev);
1094ee7ed3aaSChunguang Xu 		invalidate_bdev(sbi->s_journal_bdev);
1095617ba13bSMingming Cao 		ext4_blkdev_remove(sbi);
1096ac27a0ecSDave Kleikamp 	}
109750c15df6SChengguang Xu 
1098dec214d0STahsin Erdogan 	ext4_xattr_destroy_cache(sbi->s_ea_inode_cache);
1099dec214d0STahsin Erdogan 	sbi->s_ea_inode_cache = NULL;
110050c15df6SChengguang Xu 
110147387409STahsin Erdogan 	ext4_xattr_destroy_cache(sbi->s_ea_block_cache);
110247387409STahsin Erdogan 	sbi->s_ea_block_cache = NULL;
110350c15df6SChengguang Xu 
1104c5e06d10SJohann Lombardi 	if (sbi->s_mmp_tsk)
1105c5e06d10SJohann Lombardi 		kthread_stop(sbi->s_mmp_tsk);
11069060dd2cSEric Sandeen 	brelse(sbi->s_sbh);
1107ac27a0ecSDave Kleikamp 	sb->s_fs_info = NULL;
11083197ebdbSTheodore Ts'o 	/*
11093197ebdbSTheodore Ts'o 	 * Now that we are completely done shutting down the
11103197ebdbSTheodore Ts'o 	 * superblock, we need to actually destroy the kobject.
11113197ebdbSTheodore Ts'o 	 */
11123197ebdbSTheodore Ts'o 	kobject_put(&sbi->s_kobj);
11133197ebdbSTheodore Ts'o 	wait_for_completion(&sbi->s_kobj_unregister);
11140441984aSDarrick J. Wong 	if (sbi->s_chksum_driver)
11150441984aSDarrick J. Wong 		crypto_free_shash(sbi->s_chksum_driver);
1116705895b6SPekka Enberg 	kfree(sbi->s_blockgroup_lock);
11175e405595SDan Williams 	fs_put_dax(sbi->s_daxdev);
1118ed318a6cSEric Biggers 	fscrypt_free_dummy_context(&sbi->s_dummy_enc_ctx);
1119c83ad55eSGabriel Krisman Bertazi #ifdef CONFIG_UNICODE
1120c83ad55eSGabriel Krisman Bertazi 	utf8_unload(sbi->s_encoding);
1121c83ad55eSGabriel Krisman Bertazi #endif
1122ac27a0ecSDave Kleikamp 	kfree(sbi);
1123ac27a0ecSDave Kleikamp }
1124ac27a0ecSDave Kleikamp 
1125e18b890bSChristoph Lameter static struct kmem_cache *ext4_inode_cachep;
1126ac27a0ecSDave Kleikamp 
1127ac27a0ecSDave Kleikamp /*
1128ac27a0ecSDave Kleikamp  * Called inside transaction, so use GFP_NOFS
1129ac27a0ecSDave Kleikamp  */
1130617ba13bSMingming Cao static struct inode *ext4_alloc_inode(struct super_block *sb)
1131ac27a0ecSDave Kleikamp {
1132617ba13bSMingming Cao 	struct ext4_inode_info *ei;
1133ac27a0ecSDave Kleikamp 
1134e6b4f8daSChristoph Lameter 	ei = kmem_cache_alloc(ext4_inode_cachep, GFP_NOFS);
1135ac27a0ecSDave Kleikamp 	if (!ei)
1136ac27a0ecSDave Kleikamp 		return NULL;
11370b8e58a1SAndreas Dilger 
1138ee73f9a5SJeff Layton 	inode_set_iversion(&ei->vfs_inode, 1);
1139202ee5dfSTheodore Ts'o 	spin_lock_init(&ei->i_raw_lock);
1140c9de560dSAlex Tomas 	INIT_LIST_HEAD(&ei->i_prealloc_list);
114127bc446eSbrookxu 	atomic_set(&ei->i_prealloc_active, 0);
1142c9de560dSAlex Tomas 	spin_lock_init(&ei->i_prealloc_lock);
11439a26b661SZheng Liu 	ext4_es_init_tree(&ei->i_es_tree);
11449a26b661SZheng Liu 	rwlock_init(&ei->i_es_lock);
1145edaa53caSZheng Liu 	INIT_LIST_HEAD(&ei->i_es_list);
1146eb68d0e2SZheng Liu 	ei->i_es_all_nr = 0;
1147edaa53caSZheng Liu 	ei->i_es_shk_nr = 0;
1148dd475925SJan Kara 	ei->i_es_shrink_lblk = 0;
1149d2a17637SMingming Cao 	ei->i_reserved_data_blocks = 0;
1150d2a17637SMingming Cao 	spin_lock_init(&(ei->i_block_reservation_lock));
11511dc0aa46SEric Whitney 	ext4_init_pending_tree(&ei->i_pending_tree);
1152a9e7f447SDmitry Monakhov #ifdef CONFIG_QUOTA
1153a9e7f447SDmitry Monakhov 	ei->i_reserved_quota = 0;
115496c7e0d9SJan Kara 	memset(&ei->i_dquot, 0, sizeof(ei->i_dquot));
1155a9e7f447SDmitry Monakhov #endif
11568aefcd55STheodore Ts'o 	ei->jinode = NULL;
11572e8fa54eSJan Kara 	INIT_LIST_HEAD(&ei->i_rsv_conversion_list);
1158744692dcSJiaying Zhang 	spin_lock_init(&ei->i_completed_io_lock);
1159b436b9beSJan Kara 	ei->i_sync_tid = 0;
1160b436b9beSJan Kara 	ei->i_datasync_tid = 0;
1161e27f41e1SDmitry Monakhov 	atomic_set(&ei->i_unwritten, 0);
11622e8fa54eSJan Kara 	INIT_WORK(&ei->i_rsv_conversion_work, ext4_end_io_rsv_work);
1163ac27a0ecSDave Kleikamp 	return &ei->vfs_inode;
1164ac27a0ecSDave Kleikamp }
1165ac27a0ecSDave Kleikamp 
11667ff9c073STheodore Ts'o static int ext4_drop_inode(struct inode *inode)
11677ff9c073STheodore Ts'o {
11687ff9c073STheodore Ts'o 	int drop = generic_drop_inode(inode);
11697ff9c073STheodore Ts'o 
117029b3692eSEric Biggers 	if (!drop)
117129b3692eSEric Biggers 		drop = fscrypt_drop_inode(inode);
117229b3692eSEric Biggers 
11737ff9c073STheodore Ts'o 	trace_ext4_drop_inode(inode, drop);
11747ff9c073STheodore Ts'o 	return drop;
11757ff9c073STheodore Ts'o }
11767ff9c073STheodore Ts'o 
117794053139SAl Viro static void ext4_free_in_core_inode(struct inode *inode)
1178fa0d7e3dSNick Piggin {
11792c58d548SEric Biggers 	fscrypt_free_inode(inode);
1180fa0d7e3dSNick Piggin 	kmem_cache_free(ext4_inode_cachep, EXT4_I(inode));
1181fa0d7e3dSNick Piggin }
1182fa0d7e3dSNick Piggin 
1183617ba13bSMingming Cao static void ext4_destroy_inode(struct inode *inode)
1184ac27a0ecSDave Kleikamp {
11859f7dd93dSVasily Averin 	if (!list_empty(&(EXT4_I(inode)->i_orphan))) {
1186b31e1552SEric Sandeen 		ext4_msg(inode->i_sb, KERN_ERR,
1187b31e1552SEric Sandeen 			 "Inode %lu (%p): orphan list check failed!",
1188b31e1552SEric Sandeen 			 inode->i_ino, EXT4_I(inode));
11899f7dd93dSVasily Averin 		print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 16, 4,
11909f7dd93dSVasily Averin 				EXT4_I(inode), sizeof(struct ext4_inode_info),
11919f7dd93dSVasily Averin 				true);
11929f7dd93dSVasily Averin 		dump_stack();
11939f7dd93dSVasily Averin 	}
1194ac27a0ecSDave Kleikamp }
1195ac27a0ecSDave Kleikamp 
119651cc5068SAlexey Dobriyan static void init_once(void *foo)
1197ac27a0ecSDave Kleikamp {
1198617ba13bSMingming Cao 	struct ext4_inode_info *ei = (struct ext4_inode_info *) foo;
1199ac27a0ecSDave Kleikamp 
1200ac27a0ecSDave Kleikamp 	INIT_LIST_HEAD(&ei->i_orphan);
1201ac27a0ecSDave Kleikamp 	init_rwsem(&ei->xattr_sem);
12020e855ac8SAneesh Kumar K.V 	init_rwsem(&ei->i_data_sem);
1203ea3d7209SJan Kara 	init_rwsem(&ei->i_mmap_sem);
1204ac27a0ecSDave Kleikamp 	inode_init_once(&ei->vfs_inode);
1205ac27a0ecSDave Kleikamp }
1206ac27a0ecSDave Kleikamp 
1207e67bc2b3SFabian Frederick static int __init init_inodecache(void)
1208ac27a0ecSDave Kleikamp {
1209f8dd7c70SDavid Windsor 	ext4_inode_cachep = kmem_cache_create_usercopy("ext4_inode_cache",
1210f8dd7c70SDavid Windsor 				sizeof(struct ext4_inode_info), 0,
1211f8dd7c70SDavid Windsor 				(SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD|
1212f8dd7c70SDavid Windsor 					SLAB_ACCOUNT),
1213f8dd7c70SDavid Windsor 				offsetof(struct ext4_inode_info, i_data),
1214f8dd7c70SDavid Windsor 				sizeof_field(struct ext4_inode_info, i_data),
121520c2df83SPaul Mundt 				init_once);
1216617ba13bSMingming Cao 	if (ext4_inode_cachep == NULL)
1217ac27a0ecSDave Kleikamp 		return -ENOMEM;
1218ac27a0ecSDave Kleikamp 	return 0;
1219ac27a0ecSDave Kleikamp }
1220ac27a0ecSDave Kleikamp 
1221ac27a0ecSDave Kleikamp static void destroy_inodecache(void)
1222ac27a0ecSDave Kleikamp {
12238c0a8537SKirill A. Shutemov 	/*
12248c0a8537SKirill A. Shutemov 	 * Make sure all delayed rcu free inodes are flushed before we
12258c0a8537SKirill A. Shutemov 	 * destroy cache.
12268c0a8537SKirill A. Shutemov 	 */
12278c0a8537SKirill A. Shutemov 	rcu_barrier();
1228617ba13bSMingming Cao 	kmem_cache_destroy(ext4_inode_cachep);
1229ac27a0ecSDave Kleikamp }
1230ac27a0ecSDave Kleikamp 
12310930fcc1SAl Viro void ext4_clear_inode(struct inode *inode)
1232ac27a0ecSDave Kleikamp {
12330930fcc1SAl Viro 	invalidate_inode_buffers(inode);
1234dbd5768fSJan Kara 	clear_inode(inode);
123527bc446eSbrookxu 	ext4_discard_preallocations(inode, 0);
123651865fdaSZheng Liu 	ext4_es_remove_extent(inode, 0, EXT_MAX_BLOCKS);
1237f4c2d372SJan Kara 	dquot_drop(inode);
12388aefcd55STheodore Ts'o 	if (EXT4_I(inode)->jinode) {
12398aefcd55STheodore Ts'o 		jbd2_journal_release_jbd_inode(EXT4_JOURNAL(inode),
12408aefcd55STheodore Ts'o 					       EXT4_I(inode)->jinode);
12418aefcd55STheodore Ts'o 		jbd2_free_inode(EXT4_I(inode)->jinode);
12428aefcd55STheodore Ts'o 		EXT4_I(inode)->jinode = NULL;
12438aefcd55STheodore Ts'o 	}
12443d204e24SEric Biggers 	fscrypt_put_encryption_info(inode);
1245c93d8f88SEric Biggers 	fsverity_cleanup_inode(inode);
1246ac27a0ecSDave Kleikamp }
1247ac27a0ecSDave Kleikamp 
12481b961ac0SChristoph Hellwig static struct inode *ext4_nfs_get_inode(struct super_block *sb,
12491b961ac0SChristoph Hellwig 					u64 ino, u32 generation)
1250ac27a0ecSDave Kleikamp {
1251ac27a0ecSDave Kleikamp 	struct inode *inode;
1252ac27a0ecSDave Kleikamp 
12538a363970STheodore Ts'o 	/*
1254ac27a0ecSDave Kleikamp 	 * Currently we don't know the generation for parent directory, so
1255ac27a0ecSDave Kleikamp 	 * a generation of 0 means "accept any"
1256ac27a0ecSDave Kleikamp 	 */
12578a363970STheodore Ts'o 	inode = ext4_iget(sb, ino, EXT4_IGET_HANDLE);
12581d1fe1eeSDavid Howells 	if (IS_ERR(inode))
12591d1fe1eeSDavid Howells 		return ERR_CAST(inode);
12601d1fe1eeSDavid Howells 	if (generation && inode->i_generation != generation) {
1261ac27a0ecSDave Kleikamp 		iput(inode);
1262ac27a0ecSDave Kleikamp 		return ERR_PTR(-ESTALE);
1263ac27a0ecSDave Kleikamp 	}
12641b961ac0SChristoph Hellwig 
12651b961ac0SChristoph Hellwig 	return inode;
1266ac27a0ecSDave Kleikamp }
12671b961ac0SChristoph Hellwig 
12681b961ac0SChristoph Hellwig static struct dentry *ext4_fh_to_dentry(struct super_block *sb, struct fid *fid,
12691b961ac0SChristoph Hellwig 					int fh_len, int fh_type)
12701b961ac0SChristoph Hellwig {
12711b961ac0SChristoph Hellwig 	return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
12721b961ac0SChristoph Hellwig 				    ext4_nfs_get_inode);
12731b961ac0SChristoph Hellwig }
12741b961ac0SChristoph Hellwig 
12751b961ac0SChristoph Hellwig static struct dentry *ext4_fh_to_parent(struct super_block *sb, struct fid *fid,
12761b961ac0SChristoph Hellwig 					int fh_len, int fh_type)
12771b961ac0SChristoph Hellwig {
12781b961ac0SChristoph Hellwig 	return generic_fh_to_parent(sb, fid, fh_len, fh_type,
12791b961ac0SChristoph Hellwig 				    ext4_nfs_get_inode);
1280ac27a0ecSDave Kleikamp }
1281ac27a0ecSDave Kleikamp 
1282fde87268STheodore Ts'o static int ext4_nfs_commit_metadata(struct inode *inode)
1283fde87268STheodore Ts'o {
1284fde87268STheodore Ts'o 	struct writeback_control wbc = {
1285fde87268STheodore Ts'o 		.sync_mode = WB_SYNC_ALL
1286fde87268STheodore Ts'o 	};
1287fde87268STheodore Ts'o 
1288fde87268STheodore Ts'o 	trace_ext4_nfs_commit_metadata(inode);
1289fde87268STheodore Ts'o 	return ext4_write_inode(inode, &wbc);
1290fde87268STheodore Ts'o }
1291fde87268STheodore Ts'o 
1292c39a7f84SToshiyuki Okajima /*
1293c39a7f84SToshiyuki Okajima  * Try to release metadata pages (indirect blocks, directories) which are
1294c39a7f84SToshiyuki Okajima  * mapped via the block device.  Since these pages could have journal heads
1295c39a7f84SToshiyuki Okajima  * which would prevent try_to_free_buffers() from freeing them, we must use
1296c39a7f84SToshiyuki Okajima  * jbd2 layer's try_to_free_buffers() function to release them.
1297c39a7f84SToshiyuki Okajima  */
12980b8e58a1SAndreas Dilger static int bdev_try_to_free_page(struct super_block *sb, struct page *page,
12990b8e58a1SAndreas Dilger 				 gfp_t wait)
1300c39a7f84SToshiyuki Okajima {
1301c39a7f84SToshiyuki Okajima 	journal_t *journal = EXT4_SB(sb)->s_journal;
1302c39a7f84SToshiyuki Okajima 
1303c39a7f84SToshiyuki Okajima 	WARN_ON(PageChecked(page));
1304c39a7f84SToshiyuki Okajima 	if (!page_has_buffers(page))
1305c39a7f84SToshiyuki Okajima 		return 0;
1306c39a7f84SToshiyuki Okajima 	if (journal)
1307529a781eSzhangyi (F) 		return jbd2_journal_try_to_free_buffers(journal, page);
1308529a781eSzhangyi (F) 
1309c39a7f84SToshiyuki Okajima 	return try_to_free_buffers(page);
1310c39a7f84SToshiyuki Okajima }
1311c39a7f84SToshiyuki Okajima 
1312643fa961SChandan Rajendra #ifdef CONFIG_FS_ENCRYPTION
1313a7550b30SJaegeuk Kim static int ext4_get_context(struct inode *inode, void *ctx, size_t len)
1314a7550b30SJaegeuk Kim {
1315a7550b30SJaegeuk Kim 	return ext4_xattr_get(inode, EXT4_XATTR_INDEX_ENCRYPTION,
1316a7550b30SJaegeuk Kim 				 EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, ctx, len);
1317a7550b30SJaegeuk Kim }
1318a7550b30SJaegeuk Kim 
1319a7550b30SJaegeuk Kim static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,
1320a7550b30SJaegeuk Kim 							void *fs_data)
1321a7550b30SJaegeuk Kim {
13222f8f5e76SEric Biggers 	handle_t *handle = fs_data;
1323c1a5d5f6STahsin Erdogan 	int res, res2, credits, retries = 0;
1324a7550b30SJaegeuk Kim 
13259ce0151aSEric Biggers 	/*
13269ce0151aSEric Biggers 	 * Encrypting the root directory is not allowed because e2fsck expects
13279ce0151aSEric Biggers 	 * lost+found to exist and be unencrypted, and encrypting the root
13289ce0151aSEric Biggers 	 * directory would imply encrypting the lost+found directory as well as
13299ce0151aSEric Biggers 	 * the filename "lost+found" itself.
13309ce0151aSEric Biggers 	 */
13319ce0151aSEric Biggers 	if (inode->i_ino == EXT4_ROOT_INO)
13329ce0151aSEric Biggers 		return -EPERM;
1333a7550b30SJaegeuk Kim 
13347d3e06a8SRoss Zwisler 	if (WARN_ON_ONCE(IS_DAX(inode) && i_size_read(inode)))
13357d3e06a8SRoss Zwisler 		return -EINVAL;
13367d3e06a8SRoss Zwisler 
1337b383a73fSIra Weiny 	if (ext4_test_inode_flag(inode, EXT4_INODE_DAX))
1338b383a73fSIra Weiny 		return -EOPNOTSUPP;
1339b383a73fSIra Weiny 
134094840e3cSEric Biggers 	res = ext4_convert_inline_data(inode);
134194840e3cSEric Biggers 	if (res)
134294840e3cSEric Biggers 		return res;
134394840e3cSEric Biggers 
13442f8f5e76SEric Biggers 	/*
13452f8f5e76SEric Biggers 	 * If a journal handle was specified, then the encryption context is
13462f8f5e76SEric Biggers 	 * being set on a new inode via inheritance and is part of a larger
13472f8f5e76SEric Biggers 	 * transaction to create the inode.  Otherwise the encryption context is
13482f8f5e76SEric Biggers 	 * being set on an existing inode in its own transaction.  Only in the
13492f8f5e76SEric Biggers 	 * latter case should the "retry on ENOSPC" logic be used.
13502f8f5e76SEric Biggers 	 */
13512f8f5e76SEric Biggers 
13522f8f5e76SEric Biggers 	if (handle) {
13532f8f5e76SEric Biggers 		res = ext4_xattr_set_handle(handle, inode,
13542f8f5e76SEric Biggers 					    EXT4_XATTR_INDEX_ENCRYPTION,
13552f8f5e76SEric Biggers 					    EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
13562f8f5e76SEric Biggers 					    ctx, len, 0);
1357a7550b30SJaegeuk Kim 		if (!res) {
1358a7550b30SJaegeuk Kim 			ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);
1359a7550b30SJaegeuk Kim 			ext4_clear_inode_state(inode,
1360a7550b30SJaegeuk Kim 					EXT4_STATE_MAY_INLINE_DATA);
1361a3caa24bSJan Kara 			/*
13622ee6a576SEric Biggers 			 * Update inode->i_flags - S_ENCRYPTED will be enabled,
13632ee6a576SEric Biggers 			 * S_DAX may be disabled
1364a3caa24bSJan Kara 			 */
1365043546e4SIra Weiny 			ext4_set_inode_flags(inode, false);
1366a7550b30SJaegeuk Kim 		}
1367a7550b30SJaegeuk Kim 		return res;
1368a7550b30SJaegeuk Kim 	}
1369a7550b30SJaegeuk Kim 
1370b8cb5a54STahsin Erdogan 	res = dquot_initialize(inode);
1371b8cb5a54STahsin Erdogan 	if (res)
1372b8cb5a54STahsin Erdogan 		return res;
13732f8f5e76SEric Biggers retry:
1374af65207cSTahsin Erdogan 	res = ext4_xattr_set_credits(inode, len, false /* is_create */,
1375af65207cSTahsin Erdogan 				     &credits);
1376dec214d0STahsin Erdogan 	if (res)
1377dec214d0STahsin Erdogan 		return res;
1378dec214d0STahsin Erdogan 
1379c1a5d5f6STahsin Erdogan 	handle = ext4_journal_start(inode, EXT4_HT_MISC, credits);
1380a7550b30SJaegeuk Kim 	if (IS_ERR(handle))
1381a7550b30SJaegeuk Kim 		return PTR_ERR(handle);
1382a7550b30SJaegeuk Kim 
13832f8f5e76SEric Biggers 	res = ext4_xattr_set_handle(handle, inode, EXT4_XATTR_INDEX_ENCRYPTION,
13842f8f5e76SEric Biggers 				    EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
13852f8f5e76SEric Biggers 				    ctx, len, 0);
1386a7550b30SJaegeuk Kim 	if (!res) {
1387a7550b30SJaegeuk Kim 		ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);
13882ee6a576SEric Biggers 		/*
13892ee6a576SEric Biggers 		 * Update inode->i_flags - S_ENCRYPTED will be enabled,
13902ee6a576SEric Biggers 		 * S_DAX may be disabled
13912ee6a576SEric Biggers 		 */
1392043546e4SIra Weiny 		ext4_set_inode_flags(inode, false);
1393a7550b30SJaegeuk Kim 		res = ext4_mark_inode_dirty(handle, inode);
1394a7550b30SJaegeuk Kim 		if (res)
1395a7550b30SJaegeuk Kim 			EXT4_ERROR_INODE(inode, "Failed to mark inode dirty");
1396a7550b30SJaegeuk Kim 	}
1397a7550b30SJaegeuk Kim 	res2 = ext4_journal_stop(handle);
13982f8f5e76SEric Biggers 
13992f8f5e76SEric Biggers 	if (res == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
14002f8f5e76SEric Biggers 		goto retry;
1401a7550b30SJaegeuk Kim 	if (!res)
1402a7550b30SJaegeuk Kim 		res = res2;
1403a7550b30SJaegeuk Kim 	return res;
1404a7550b30SJaegeuk Kim }
1405a7550b30SJaegeuk Kim 
1406ed318a6cSEric Biggers static const union fscrypt_context *
1407ed318a6cSEric Biggers ext4_get_dummy_context(struct super_block *sb)
1408a7550b30SJaegeuk Kim {
1409ed318a6cSEric Biggers 	return EXT4_SB(sb)->s_dummy_enc_ctx.ctx;
1410a7550b30SJaegeuk Kim }
1411a7550b30SJaegeuk Kim 
1412b925acb8SEric Biggers static bool ext4_has_stable_inodes(struct super_block *sb)
1413b925acb8SEric Biggers {
1414b925acb8SEric Biggers 	return ext4_has_feature_stable_inodes(sb);
1415b925acb8SEric Biggers }
1416b925acb8SEric Biggers 
1417b925acb8SEric Biggers static void ext4_get_ino_and_lblk_bits(struct super_block *sb,
1418b925acb8SEric Biggers 				       int *ino_bits_ret, int *lblk_bits_ret)
1419b925acb8SEric Biggers {
1420b925acb8SEric Biggers 	*ino_bits_ret = 8 * sizeof(EXT4_SB(sb)->s_es->s_inodes_count);
1421b925acb8SEric Biggers 	*lblk_bits_ret = 8 * sizeof(ext4_lblk_t);
1422b925acb8SEric Biggers }
1423b925acb8SEric Biggers 
14246f69f0edSEric Biggers static const struct fscrypt_operations ext4_cryptops = {
1425a5d431efSEric Biggers 	.key_prefix		= "ext4:",
1426a7550b30SJaegeuk Kim 	.get_context		= ext4_get_context,
1427a7550b30SJaegeuk Kim 	.set_context		= ext4_set_context,
1428ed318a6cSEric Biggers 	.get_dummy_context	= ext4_get_dummy_context,
1429a7550b30SJaegeuk Kim 	.empty_dir		= ext4_empty_dir,
1430e12ee683SEric Biggers 	.max_namelen		= EXT4_NAME_LEN,
1431b925acb8SEric Biggers 	.has_stable_inodes	= ext4_has_stable_inodes,
1432b925acb8SEric Biggers 	.get_ino_and_lblk_bits	= ext4_get_ino_and_lblk_bits,
1433a7550b30SJaegeuk Kim };
1434a7550b30SJaegeuk Kim #endif
1435a7550b30SJaegeuk Kim 
1436ac27a0ecSDave Kleikamp #ifdef CONFIG_QUOTA
1437d6006186SEric Biggers static const char * const quotatypes[] = INITQFNAMES;
1438689c958cSLi Xi #define QTYPE2NAME(t) (quotatypes[t])
1439ac27a0ecSDave Kleikamp 
1440617ba13bSMingming Cao static int ext4_write_dquot(struct dquot *dquot);
1441617ba13bSMingming Cao static int ext4_acquire_dquot(struct dquot *dquot);
1442617ba13bSMingming Cao static int ext4_release_dquot(struct dquot *dquot);
1443617ba13bSMingming Cao static int ext4_mark_dquot_dirty(struct dquot *dquot);
1444617ba13bSMingming Cao static int ext4_write_info(struct super_block *sb, int type);
14456f28e087SJan Kara static int ext4_quota_on(struct super_block *sb, int type, int format_id,
14468c54ca9cSAl Viro 			 const struct path *path);
1447617ba13bSMingming Cao static int ext4_quota_on_mount(struct super_block *sb, int type);
1448617ba13bSMingming Cao static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data,
1449ac27a0ecSDave Kleikamp 			       size_t len, loff_t off);
1450617ba13bSMingming Cao static ssize_t ext4_quota_write(struct super_block *sb, int type,
1451ac27a0ecSDave Kleikamp 				const char *data, size_t len, loff_t off);
14527c319d32SAditya Kali static int ext4_quota_enable(struct super_block *sb, int type, int format_id,
14537c319d32SAditya Kali 			     unsigned int flags);
14547c319d32SAditya Kali static int ext4_enable_quotas(struct super_block *sb);
1455ac27a0ecSDave Kleikamp 
145696c7e0d9SJan Kara static struct dquot **ext4_get_dquots(struct inode *inode)
145796c7e0d9SJan Kara {
145896c7e0d9SJan Kara 	return EXT4_I(inode)->i_dquot;
145996c7e0d9SJan Kara }
146096c7e0d9SJan Kara 
146161e225dcSAlexey Dobriyan static const struct dquot_operations ext4_quota_operations = {
146260e58e0fSMingming Cao 	.get_reserved_space	= ext4_get_reserved_space,
1463617ba13bSMingming Cao 	.write_dquot		= ext4_write_dquot,
1464617ba13bSMingming Cao 	.acquire_dquot		= ext4_acquire_dquot,
1465617ba13bSMingming Cao 	.release_dquot		= ext4_release_dquot,
1466617ba13bSMingming Cao 	.mark_dirty		= ext4_mark_dquot_dirty,
1467a5b5ee32SJan Kara 	.write_info		= ext4_write_info,
1468a5b5ee32SJan Kara 	.alloc_dquot		= dquot_alloc,
1469a5b5ee32SJan Kara 	.destroy_dquot		= dquot_destroy,
1470040cb378SLi Xi 	.get_projid		= ext4_get_projid,
14717a9ca53aSTahsin Erdogan 	.get_inode_usage	= ext4_get_inode_usage,
1472ebc11f7bSChengguang Xu 	.get_next_id		= dquot_get_next_id,
1473ac27a0ecSDave Kleikamp };
1474ac27a0ecSDave Kleikamp 
14750d54b217SAlexey Dobriyan static const struct quotactl_ops ext4_qctl_operations = {
1476617ba13bSMingming Cao 	.quota_on	= ext4_quota_on,
1477ca0e05e4SDmitry Monakhov 	.quota_off	= ext4_quota_off,
1478287a8095SChristoph Hellwig 	.quota_sync	= dquot_quota_sync,
14790a240339SJan Kara 	.get_state	= dquot_get_state,
1480287a8095SChristoph Hellwig 	.set_info	= dquot_set_dqinfo,
1481287a8095SChristoph Hellwig 	.get_dqblk	= dquot_get_dqblk,
14826332b9b5SEric Sandeen 	.set_dqblk	= dquot_set_dqblk,
14836332b9b5SEric Sandeen 	.get_nextdqblk	= dquot_get_next_dqblk,
1484ac27a0ecSDave Kleikamp };
1485ac27a0ecSDave Kleikamp #endif
1486ac27a0ecSDave Kleikamp 
1487ee9b6d61SJosef 'Jeff' Sipek static const struct super_operations ext4_sops = {
1488617ba13bSMingming Cao 	.alloc_inode	= ext4_alloc_inode,
148994053139SAl Viro 	.free_inode	= ext4_free_in_core_inode,
1490617ba13bSMingming Cao 	.destroy_inode	= ext4_destroy_inode,
1491617ba13bSMingming Cao 	.write_inode	= ext4_write_inode,
1492617ba13bSMingming Cao 	.dirty_inode	= ext4_dirty_inode,
14937ff9c073STheodore Ts'o 	.drop_inode	= ext4_drop_inode,
14940930fcc1SAl Viro 	.evict_inode	= ext4_evict_inode,
1495617ba13bSMingming Cao 	.put_super	= ext4_put_super,
1496617ba13bSMingming Cao 	.sync_fs	= ext4_sync_fs,
1497c4be0c1dSTakashi Sato 	.freeze_fs	= ext4_freeze,
1498c4be0c1dSTakashi Sato 	.unfreeze_fs	= ext4_unfreeze,
1499617ba13bSMingming Cao 	.statfs		= ext4_statfs,
1500617ba13bSMingming Cao 	.remount_fs	= ext4_remount,
1501617ba13bSMingming Cao 	.show_options	= ext4_show_options,
1502ac27a0ecSDave Kleikamp #ifdef CONFIG_QUOTA
1503617ba13bSMingming Cao 	.quota_read	= ext4_quota_read,
1504617ba13bSMingming Cao 	.quota_write	= ext4_quota_write,
150596c7e0d9SJan Kara 	.get_dquots	= ext4_get_dquots,
1506ac27a0ecSDave Kleikamp #endif
1507c39a7f84SToshiyuki Okajima 	.bdev_try_to_free_page = bdev_try_to_free_page,
1508ac27a0ecSDave Kleikamp };
1509ac27a0ecSDave Kleikamp 
151039655164SChristoph Hellwig static const struct export_operations ext4_export_ops = {
15111b961ac0SChristoph Hellwig 	.fh_to_dentry = ext4_fh_to_dentry,
15121b961ac0SChristoph Hellwig 	.fh_to_parent = ext4_fh_to_parent,
1513617ba13bSMingming Cao 	.get_parent = ext4_get_parent,
1514fde87268STheodore Ts'o 	.commit_metadata = ext4_nfs_commit_metadata,
1515ac27a0ecSDave Kleikamp };
1516ac27a0ecSDave Kleikamp 
1517ac27a0ecSDave Kleikamp enum {
1518ac27a0ecSDave Kleikamp 	Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid,
1519ac27a0ecSDave Kleikamp 	Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro,
152072578c33STheodore Ts'o 	Opt_nouid32, Opt_debug, Opt_removed,
1521ac27a0ecSDave Kleikamp 	Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl,
152272578c33STheodore Ts'o 	Opt_auto_da_alloc, Opt_noauto_da_alloc, Opt_noload,
1523ad4eec61SEric Sandeen 	Opt_commit, Opt_min_batch_time, Opt_max_batch_time, Opt_journal_dev,
1524ad4eec61SEric Sandeen 	Opt_journal_path, Opt_journal_checksum, Opt_journal_async_commit,
1525ac27a0ecSDave Kleikamp 	Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
15266ddb2447STheodore Ts'o 	Opt_data_err_abort, Opt_data_err_ignore, Opt_test_dummy_encryption,
15274f74d15fSEric Biggers 	Opt_inlinecrypt,
1528ac27a0ecSDave Kleikamp 	Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
15295a20bdfcSJan Kara 	Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota,
1530ee4a3fcdSTheodore Ts'o 	Opt_noquota, Opt_barrier, Opt_nobarrier, Opt_err,
15319cb20f94SIra Weiny 	Opt_usrquota, Opt_grpquota, Opt_prjquota, Opt_i_version,
15329cb20f94SIra Weiny 	Opt_dax, Opt_dax_always, Opt_dax_inode, Opt_dax_never,
1533327eaf73STheodore Ts'o 	Opt_stripe, Opt_delalloc, Opt_nodelalloc, Opt_warn_on_error,
1534327eaf73STheodore Ts'o 	Opt_nowarn_on_error, Opt_mblk_io_submit,
1535670e9875STheodore Ts'o 	Opt_lazytime, Opt_nolazytime, Opt_debug_want_extra_isize,
15361449032bSTheodore Ts'o 	Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity,
15375328e635SEric Sandeen 	Opt_inode_readahead_blks, Opt_journal_ioprio,
1538744692dcSJiaying Zhang 	Opt_dioread_nolock, Opt_dioread_lock,
1539fc6cb1cdSTheodore Ts'o 	Opt_discard, Opt_nodiscard, Opt_init_itable, Opt_noinit_itable,
1540cdb7ee4cSTahsin Erdogan 	Opt_max_dir_size_kb, Opt_nojournal_checksum, Opt_nombcache,
15413d392b26STheodore Ts'o 	Opt_prefetch_block_bitmaps,
1542ac27a0ecSDave Kleikamp };
1543ac27a0ecSDave Kleikamp 
1544a447c093SSteven Whitehouse static const match_table_t tokens = {
1545ac27a0ecSDave Kleikamp 	{Opt_bsd_df, "bsddf"},
1546ac27a0ecSDave Kleikamp 	{Opt_minix_df, "minixdf"},
1547ac27a0ecSDave Kleikamp 	{Opt_grpid, "grpid"},
1548ac27a0ecSDave Kleikamp 	{Opt_grpid, "bsdgroups"},
1549ac27a0ecSDave Kleikamp 	{Opt_nogrpid, "nogrpid"},
1550ac27a0ecSDave Kleikamp 	{Opt_nogrpid, "sysvgroups"},
1551ac27a0ecSDave Kleikamp 	{Opt_resgid, "resgid=%u"},
1552ac27a0ecSDave Kleikamp 	{Opt_resuid, "resuid=%u"},
1553ac27a0ecSDave Kleikamp 	{Opt_sb, "sb=%u"},
1554ac27a0ecSDave Kleikamp 	{Opt_err_cont, "errors=continue"},
1555ac27a0ecSDave Kleikamp 	{Opt_err_panic, "errors=panic"},
1556ac27a0ecSDave Kleikamp 	{Opt_err_ro, "errors=remount-ro"},
1557ac27a0ecSDave Kleikamp 	{Opt_nouid32, "nouid32"},
1558ac27a0ecSDave Kleikamp 	{Opt_debug, "debug"},
155972578c33STheodore Ts'o 	{Opt_removed, "oldalloc"},
156072578c33STheodore Ts'o 	{Opt_removed, "orlov"},
1561ac27a0ecSDave Kleikamp 	{Opt_user_xattr, "user_xattr"},
1562ac27a0ecSDave Kleikamp 	{Opt_nouser_xattr, "nouser_xattr"},
1563ac27a0ecSDave Kleikamp 	{Opt_acl, "acl"},
1564ac27a0ecSDave Kleikamp 	{Opt_noacl, "noacl"},
1565e3bb52aeSEric Sandeen 	{Opt_noload, "norecovery"},
15665a916be1STheodore Ts'o 	{Opt_noload, "noload"},
156772578c33STheodore Ts'o 	{Opt_removed, "nobh"},
156872578c33STheodore Ts'o 	{Opt_removed, "bh"},
1569ac27a0ecSDave Kleikamp 	{Opt_commit, "commit=%u"},
157030773840STheodore Ts'o 	{Opt_min_batch_time, "min_batch_time=%u"},
157130773840STheodore Ts'o 	{Opt_max_batch_time, "max_batch_time=%u"},
1572ac27a0ecSDave Kleikamp 	{Opt_journal_dev, "journal_dev=%u"},
1573ad4eec61SEric Sandeen 	{Opt_journal_path, "journal_path=%s"},
1574818d276cSGirish Shilamkar 	{Opt_journal_checksum, "journal_checksum"},
1575c6d3d56dSDarrick J. Wong 	{Opt_nojournal_checksum, "nojournal_checksum"},
1576818d276cSGirish Shilamkar 	{Opt_journal_async_commit, "journal_async_commit"},
1577ac27a0ecSDave Kleikamp 	{Opt_abort, "abort"},
1578ac27a0ecSDave Kleikamp 	{Opt_data_journal, "data=journal"},
1579ac27a0ecSDave Kleikamp 	{Opt_data_ordered, "data=ordered"},
1580ac27a0ecSDave Kleikamp 	{Opt_data_writeback, "data=writeback"},
15815bf5683aSHidehiro Kawai 	{Opt_data_err_abort, "data_err=abort"},
15825bf5683aSHidehiro Kawai 	{Opt_data_err_ignore, "data_err=ignore"},
1583ac27a0ecSDave Kleikamp 	{Opt_offusrjquota, "usrjquota="},
1584ac27a0ecSDave Kleikamp 	{Opt_usrjquota, "usrjquota=%s"},
1585ac27a0ecSDave Kleikamp 	{Opt_offgrpjquota, "grpjquota="},
1586ac27a0ecSDave Kleikamp 	{Opt_grpjquota, "grpjquota=%s"},
1587ac27a0ecSDave Kleikamp 	{Opt_jqfmt_vfsold, "jqfmt=vfsold"},
1588ac27a0ecSDave Kleikamp 	{Opt_jqfmt_vfsv0, "jqfmt=vfsv0"},
15895a20bdfcSJan Kara 	{Opt_jqfmt_vfsv1, "jqfmt=vfsv1"},
1590ac27a0ecSDave Kleikamp 	{Opt_grpquota, "grpquota"},
1591ac27a0ecSDave Kleikamp 	{Opt_noquota, "noquota"},
1592ac27a0ecSDave Kleikamp 	{Opt_quota, "quota"},
1593ac27a0ecSDave Kleikamp 	{Opt_usrquota, "usrquota"},
159449da9392SJan Kara 	{Opt_prjquota, "prjquota"},
1595ac27a0ecSDave Kleikamp 	{Opt_barrier, "barrier=%u"},
159606705bffSTheodore Ts'o 	{Opt_barrier, "barrier"},
159706705bffSTheodore Ts'o 	{Opt_nobarrier, "nobarrier"},
159825ec56b5SJean Noel Cordenner 	{Opt_i_version, "i_version"},
1599923ae0ffSRoss Zwisler 	{Opt_dax, "dax"},
16009cb20f94SIra Weiny 	{Opt_dax_always, "dax=always"},
16019cb20f94SIra Weiny 	{Opt_dax_inode, "dax=inode"},
16029cb20f94SIra Weiny 	{Opt_dax_never, "dax=never"},
1603c9de560dSAlex Tomas 	{Opt_stripe, "stripe=%u"},
160464769240SAlex Tomas 	{Opt_delalloc, "delalloc"},
1605327eaf73STheodore Ts'o 	{Opt_warn_on_error, "warn_on_error"},
1606327eaf73STheodore Ts'o 	{Opt_nowarn_on_error, "nowarn_on_error"},
1607a26f4992STheodore Ts'o 	{Opt_lazytime, "lazytime"},
1608a26f4992STheodore Ts'o 	{Opt_nolazytime, "nolazytime"},
1609670e9875STheodore Ts'o 	{Opt_debug_want_extra_isize, "debug_want_extra_isize=%u"},
1610dd919b98SAneesh Kumar K.V 	{Opt_nodelalloc, "nodelalloc"},
161136ade451SJan Kara 	{Opt_removed, "mblk_io_submit"},
161236ade451SJan Kara 	{Opt_removed, "nomblk_io_submit"},
16136fd058f7STheodore Ts'o 	{Opt_block_validity, "block_validity"},
16146fd058f7STheodore Ts'o 	{Opt_noblock_validity, "noblock_validity"},
1615240799cdSTheodore Ts'o 	{Opt_inode_readahead_blks, "inode_readahead_blks=%u"},
1616b3881f74STheodore Ts'o 	{Opt_journal_ioprio, "journal_ioprio=%u"},
1617afd4672dSTheodore Ts'o 	{Opt_auto_da_alloc, "auto_da_alloc=%u"},
161806705bffSTheodore Ts'o 	{Opt_auto_da_alloc, "auto_da_alloc"},
161906705bffSTheodore Ts'o 	{Opt_noauto_da_alloc, "noauto_da_alloc"},
1620744692dcSJiaying Zhang 	{Opt_dioread_nolock, "dioread_nolock"},
1621244adf64STheodore Ts'o 	{Opt_dioread_lock, "nodioread_nolock"},
1622744692dcSJiaying Zhang 	{Opt_dioread_lock, "dioread_lock"},
16235328e635SEric Sandeen 	{Opt_discard, "discard"},
16245328e635SEric Sandeen 	{Opt_nodiscard, "nodiscard"},
1625fc6cb1cdSTheodore Ts'o 	{Opt_init_itable, "init_itable=%u"},
1626fc6cb1cdSTheodore Ts'o 	{Opt_init_itable, "init_itable"},
1627fc6cb1cdSTheodore Ts'o 	{Opt_noinit_itable, "noinit_itable"},
1628df981d03STheodore Ts'o 	{Opt_max_dir_size_kb, "max_dir_size_kb=%u"},
1629ed318a6cSEric Biggers 	{Opt_test_dummy_encryption, "test_dummy_encryption=%s"},
16306ddb2447STheodore Ts'o 	{Opt_test_dummy_encryption, "test_dummy_encryption"},
16314f74d15fSEric Biggers 	{Opt_inlinecrypt, "inlinecrypt"},
1632cdb7ee4cSTahsin Erdogan 	{Opt_nombcache, "nombcache"},
1633cdb7ee4cSTahsin Erdogan 	{Opt_nombcache, "no_mbcache"},	/* for backward compatibility */
16343d392b26STheodore Ts'o 	{Opt_prefetch_block_bitmaps, "prefetch_block_bitmaps"},
1635c7198b9cSTheodore Ts'o 	{Opt_removed, "check=none"},	/* mount option from ext2/3 */
1636c7198b9cSTheodore Ts'o 	{Opt_removed, "nocheck"},	/* mount option from ext2/3 */
1637c7198b9cSTheodore Ts'o 	{Opt_removed, "reservation"},	/* mount option from ext2/3 */
1638c7198b9cSTheodore Ts'o 	{Opt_removed, "noreservation"}, /* mount option from ext2/3 */
1639c7198b9cSTheodore Ts'o 	{Opt_removed, "journal=%u"},	/* mount option from ext2/3 */
1640f3f12faaSJosef Bacik 	{Opt_err, NULL},
1641ac27a0ecSDave Kleikamp };
1642ac27a0ecSDave Kleikamp 
1643617ba13bSMingming Cao static ext4_fsblk_t get_sb_block(void **data)
1644ac27a0ecSDave Kleikamp {
1645617ba13bSMingming Cao 	ext4_fsblk_t	sb_block;
1646ac27a0ecSDave Kleikamp 	char		*options = (char *) *data;
1647ac27a0ecSDave Kleikamp 
1648ac27a0ecSDave Kleikamp 	if (!options || strncmp(options, "sb=", 3) != 0)
1649ac27a0ecSDave Kleikamp 		return 1;	/* Default location */
16500b8e58a1SAndreas Dilger 
1651ac27a0ecSDave Kleikamp 	options += 3;
16520b8e58a1SAndreas Dilger 	/* TODO: use simple_strtoll with >32bit ext4 */
1653ac27a0ecSDave Kleikamp 	sb_block = simple_strtoul(options, &options, 0);
1654ac27a0ecSDave Kleikamp 	if (*options && *options != ',') {
16554776004fSTheodore Ts'o 		printk(KERN_ERR "EXT4-fs: Invalid sb specification: %s\n",
1656ac27a0ecSDave Kleikamp 		       (char *) *data);
1657ac27a0ecSDave Kleikamp 		return 1;
1658ac27a0ecSDave Kleikamp 	}
1659ac27a0ecSDave Kleikamp 	if (*options == ',')
1660ac27a0ecSDave Kleikamp 		options++;
1661ac27a0ecSDave Kleikamp 	*data = (void *) options;
16620b8e58a1SAndreas Dilger 
1663ac27a0ecSDave Kleikamp 	return sb_block;
1664ac27a0ecSDave Kleikamp }
1665ac27a0ecSDave Kleikamp 
1666b3881f74STheodore Ts'o #define DEFAULT_JOURNAL_IOPRIO (IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 3))
1667d6006186SEric Biggers static const char deprecated_msg[] =
1668d6006186SEric Biggers 	"Mount option \"%s\" will be removed by %s\n"
1669437ca0fdSDmitry Monakhov 	"Contact linux-ext4@vger.kernel.org if you think we should keep it.\n";
1670b3881f74STheodore Ts'o 
167156c50f11SDmitry Monakhov #ifdef CONFIG_QUOTA
167256c50f11SDmitry Monakhov static int set_qf_name(struct super_block *sb, int qtype, substring_t *args)
167356c50f11SDmitry Monakhov {
167456c50f11SDmitry Monakhov 	struct ext4_sb_info *sbi = EXT4_SB(sb);
167533458eabSTheodore Ts'o 	char *qname, *old_qname = get_qf_name(sb, sbi, qtype);
167603dafb5fSChen Gang 	int ret = -1;
167756c50f11SDmitry Monakhov 
167833458eabSTheodore Ts'o 	if (sb_any_quota_loaded(sb) && !old_qname) {
167956c50f11SDmitry Monakhov 		ext4_msg(sb, KERN_ERR,
168056c50f11SDmitry Monakhov 			"Cannot change journaled "
168156c50f11SDmitry Monakhov 			"quota options when quota turned on");
168257f73c2cSTheodore Ts'o 		return -1;
168356c50f11SDmitry Monakhov 	}
1684e2b911c5SDarrick J. Wong 	if (ext4_has_feature_quota(sb)) {
1685c325a67cSTheodore Ts'o 		ext4_msg(sb, KERN_INFO, "Journaled quota options "
1686c325a67cSTheodore Ts'o 			 "ignored when QUOTA feature is enabled");
1687c325a67cSTheodore Ts'o 		return 1;
1688262b4662SJan Kara 	}
168956c50f11SDmitry Monakhov 	qname = match_strdup(args);
169056c50f11SDmitry Monakhov 	if (!qname) {
169156c50f11SDmitry Monakhov 		ext4_msg(sb, KERN_ERR,
169256c50f11SDmitry Monakhov 			"Not enough memory for storing quotafile name");
169357f73c2cSTheodore Ts'o 		return -1;
169456c50f11SDmitry Monakhov 	}
169533458eabSTheodore Ts'o 	if (old_qname) {
169633458eabSTheodore Ts'o 		if (strcmp(old_qname, qname) == 0)
169703dafb5fSChen Gang 			ret = 1;
169803dafb5fSChen Gang 		else
169956c50f11SDmitry Monakhov 			ext4_msg(sb, KERN_ERR,
170003dafb5fSChen Gang 				 "%s quota file already specified",
170103dafb5fSChen Gang 				 QTYPE2NAME(qtype));
170203dafb5fSChen Gang 		goto errout;
170356c50f11SDmitry Monakhov 	}
170403dafb5fSChen Gang 	if (strchr(qname, '/')) {
170556c50f11SDmitry Monakhov 		ext4_msg(sb, KERN_ERR,
170656c50f11SDmitry Monakhov 			"quotafile must be on filesystem root");
170703dafb5fSChen Gang 		goto errout;
170856c50f11SDmitry Monakhov 	}
170933458eabSTheodore Ts'o 	rcu_assign_pointer(sbi->s_qf_names[qtype], qname);
1710fd8c37ecSTheodore Ts'o 	set_opt(sb, QUOTA);
171156c50f11SDmitry Monakhov 	return 1;
171203dafb5fSChen Gang errout:
171303dafb5fSChen Gang 	kfree(qname);
171403dafb5fSChen Gang 	return ret;
171556c50f11SDmitry Monakhov }
171656c50f11SDmitry Monakhov 
171756c50f11SDmitry Monakhov static int clear_qf_name(struct super_block *sb, int qtype)
171856c50f11SDmitry Monakhov {
171956c50f11SDmitry Monakhov 
172056c50f11SDmitry Monakhov 	struct ext4_sb_info *sbi = EXT4_SB(sb);
172133458eabSTheodore Ts'o 	char *old_qname = get_qf_name(sb, sbi, qtype);
172256c50f11SDmitry Monakhov 
172333458eabSTheodore Ts'o 	if (sb_any_quota_loaded(sb) && old_qname) {
172456c50f11SDmitry Monakhov 		ext4_msg(sb, KERN_ERR, "Cannot change journaled quota options"
172556c50f11SDmitry Monakhov 			" when quota turned on");
172657f73c2cSTheodore Ts'o 		return -1;
172756c50f11SDmitry Monakhov 	}
172833458eabSTheodore Ts'o 	rcu_assign_pointer(sbi->s_qf_names[qtype], NULL);
172933458eabSTheodore Ts'o 	synchronize_rcu();
173033458eabSTheodore Ts'o 	kfree(old_qname);
173156c50f11SDmitry Monakhov 	return 1;
173256c50f11SDmitry Monakhov }
173356c50f11SDmitry Monakhov #endif
173456c50f11SDmitry Monakhov 
173526092bf5STheodore Ts'o #define MOPT_SET	0x0001
173626092bf5STheodore Ts'o #define MOPT_CLEAR	0x0002
173726092bf5STheodore Ts'o #define MOPT_NOSUPPORT	0x0004
173826092bf5STheodore Ts'o #define MOPT_EXPLICIT	0x0008
173926092bf5STheodore Ts'o #define MOPT_CLEAR_ERR	0x0010
174026092bf5STheodore Ts'o #define MOPT_GTE0	0x0020
174126092bf5STheodore Ts'o #ifdef CONFIG_QUOTA
174226092bf5STheodore Ts'o #define MOPT_Q		0
174326092bf5STheodore Ts'o #define MOPT_QFMT	0x0040
174426092bf5STheodore Ts'o #else
174526092bf5STheodore Ts'o #define MOPT_Q		MOPT_NOSUPPORT
174626092bf5STheodore Ts'o #define MOPT_QFMT	MOPT_NOSUPPORT
174726092bf5STheodore Ts'o #endif
174826092bf5STheodore Ts'o #define MOPT_DATAJ	0x0080
17498dc0aa8cSTheodore Ts'o #define MOPT_NO_EXT2	0x0100
17508dc0aa8cSTheodore Ts'o #define MOPT_NO_EXT3	0x0200
17518dc0aa8cSTheodore Ts'o #define MOPT_EXT4_ONLY	(MOPT_NO_EXT2 | MOPT_NO_EXT3)
1752ad4eec61SEric Sandeen #define MOPT_STRING	0x0400
17539cb20f94SIra Weiny #define MOPT_SKIP	0x0800
175426092bf5STheodore Ts'o 
175526092bf5STheodore Ts'o static const struct mount_opts {
175626092bf5STheodore Ts'o 	int	token;
175726092bf5STheodore Ts'o 	int	mount_opt;
175826092bf5STheodore Ts'o 	int	flags;
175926092bf5STheodore Ts'o } ext4_mount_opts[] = {
176026092bf5STheodore Ts'o 	{Opt_minix_df, EXT4_MOUNT_MINIX_DF, MOPT_SET},
176126092bf5STheodore Ts'o 	{Opt_bsd_df, EXT4_MOUNT_MINIX_DF, MOPT_CLEAR},
176226092bf5STheodore Ts'o 	{Opt_grpid, EXT4_MOUNT_GRPID, MOPT_SET},
176326092bf5STheodore Ts'o 	{Opt_nogrpid, EXT4_MOUNT_GRPID, MOPT_CLEAR},
176426092bf5STheodore Ts'o 	{Opt_block_validity, EXT4_MOUNT_BLOCK_VALIDITY, MOPT_SET},
176526092bf5STheodore Ts'o 	{Opt_noblock_validity, EXT4_MOUNT_BLOCK_VALIDITY, MOPT_CLEAR},
17668dc0aa8cSTheodore Ts'o 	{Opt_dioread_nolock, EXT4_MOUNT_DIOREAD_NOLOCK,
17678dc0aa8cSTheodore Ts'o 	 MOPT_EXT4_ONLY | MOPT_SET},
17688dc0aa8cSTheodore Ts'o 	{Opt_dioread_lock, EXT4_MOUNT_DIOREAD_NOLOCK,
17698dc0aa8cSTheodore Ts'o 	 MOPT_EXT4_ONLY | MOPT_CLEAR},
177026092bf5STheodore Ts'o 	{Opt_discard, EXT4_MOUNT_DISCARD, MOPT_SET},
177126092bf5STheodore Ts'o 	{Opt_nodiscard, EXT4_MOUNT_DISCARD, MOPT_CLEAR},
17728dc0aa8cSTheodore Ts'o 	{Opt_delalloc, EXT4_MOUNT_DELALLOC,
17738dc0aa8cSTheodore Ts'o 	 MOPT_EXT4_ONLY | MOPT_SET | MOPT_EXPLICIT},
17748dc0aa8cSTheodore Ts'o 	{Opt_nodelalloc, EXT4_MOUNT_DELALLOC,
177559d9fa5cSTheodore Ts'o 	 MOPT_EXT4_ONLY | MOPT_CLEAR},
1776327eaf73STheodore Ts'o 	{Opt_warn_on_error, EXT4_MOUNT_WARN_ON_ERROR, MOPT_SET},
1777327eaf73STheodore Ts'o 	{Opt_nowarn_on_error, EXT4_MOUNT_WARN_ON_ERROR, MOPT_CLEAR},
1778c6d3d56dSDarrick J. Wong 	{Opt_nojournal_checksum, EXT4_MOUNT_JOURNAL_CHECKSUM,
1779c6d3d56dSDarrick J. Wong 	 MOPT_EXT4_ONLY | MOPT_CLEAR},
17808dc0aa8cSTheodore Ts'o 	{Opt_journal_checksum, EXT4_MOUNT_JOURNAL_CHECKSUM,
17811e381f60SDmitry Monakhov 	 MOPT_EXT4_ONLY | MOPT_SET | MOPT_EXPLICIT},
178226092bf5STheodore Ts'o 	{Opt_journal_async_commit, (EXT4_MOUNT_JOURNAL_ASYNC_COMMIT |
17838dc0aa8cSTheodore Ts'o 				    EXT4_MOUNT_JOURNAL_CHECKSUM),
17841e381f60SDmitry Monakhov 	 MOPT_EXT4_ONLY | MOPT_SET | MOPT_EXPLICIT},
17858dc0aa8cSTheodore Ts'o 	{Opt_noload, EXT4_MOUNT_NOLOAD, MOPT_NO_EXT2 | MOPT_SET},
178626092bf5STheodore Ts'o 	{Opt_err_panic, EXT4_MOUNT_ERRORS_PANIC, MOPT_SET | MOPT_CLEAR_ERR},
178726092bf5STheodore Ts'o 	{Opt_err_ro, EXT4_MOUNT_ERRORS_RO, MOPT_SET | MOPT_CLEAR_ERR},
178826092bf5STheodore Ts'o 	{Opt_err_cont, EXT4_MOUNT_ERRORS_CONT, MOPT_SET | MOPT_CLEAR_ERR},
17898dc0aa8cSTheodore Ts'o 	{Opt_data_err_abort, EXT4_MOUNT_DATA_ERR_ABORT,
17907915a861SAles Novak 	 MOPT_NO_EXT2},
17918dc0aa8cSTheodore Ts'o 	{Opt_data_err_ignore, EXT4_MOUNT_DATA_ERR_ABORT,
17927915a861SAles Novak 	 MOPT_NO_EXT2},
179326092bf5STheodore Ts'o 	{Opt_barrier, EXT4_MOUNT_BARRIER, MOPT_SET},
179426092bf5STheodore Ts'o 	{Opt_nobarrier, EXT4_MOUNT_BARRIER, MOPT_CLEAR},
179526092bf5STheodore Ts'o 	{Opt_noauto_da_alloc, EXT4_MOUNT_NO_AUTO_DA_ALLOC, MOPT_SET},
179626092bf5STheodore Ts'o 	{Opt_auto_da_alloc, EXT4_MOUNT_NO_AUTO_DA_ALLOC, MOPT_CLEAR},
179726092bf5STheodore Ts'o 	{Opt_noinit_itable, EXT4_MOUNT_INIT_INODE_TABLE, MOPT_CLEAR},
179826092bf5STheodore Ts'o 	{Opt_commit, 0, MOPT_GTE0},
179926092bf5STheodore Ts'o 	{Opt_max_batch_time, 0, MOPT_GTE0},
180026092bf5STheodore Ts'o 	{Opt_min_batch_time, 0, MOPT_GTE0},
180126092bf5STheodore Ts'o 	{Opt_inode_readahead_blks, 0, MOPT_GTE0},
180226092bf5STheodore Ts'o 	{Opt_init_itable, 0, MOPT_GTE0},
18039cb20f94SIra Weiny 	{Opt_dax, EXT4_MOUNT_DAX_ALWAYS, MOPT_SET | MOPT_SKIP},
18049cb20f94SIra Weiny 	{Opt_dax_always, EXT4_MOUNT_DAX_ALWAYS,
18059cb20f94SIra Weiny 		MOPT_EXT4_ONLY | MOPT_SET | MOPT_SKIP},
18069cb20f94SIra Weiny 	{Opt_dax_inode, EXT4_MOUNT2_DAX_INODE,
18079cb20f94SIra Weiny 		MOPT_EXT4_ONLY | MOPT_SET | MOPT_SKIP},
18089cb20f94SIra Weiny 	{Opt_dax_never, EXT4_MOUNT2_DAX_NEVER,
18099cb20f94SIra Weiny 		MOPT_EXT4_ONLY | MOPT_SET | MOPT_SKIP},
181026092bf5STheodore Ts'o 	{Opt_stripe, 0, MOPT_GTE0},
18110efb3b23SJan Kara 	{Opt_resuid, 0, MOPT_GTE0},
18120efb3b23SJan Kara 	{Opt_resgid, 0, MOPT_GTE0},
18135ba92bcfSCarlos Maiolino 	{Opt_journal_dev, 0, MOPT_NO_EXT2 | MOPT_GTE0},
18145ba92bcfSCarlos Maiolino 	{Opt_journal_path, 0, MOPT_NO_EXT2 | MOPT_STRING},
18155ba92bcfSCarlos Maiolino 	{Opt_journal_ioprio, 0, MOPT_NO_EXT2 | MOPT_GTE0},
18168dc0aa8cSTheodore Ts'o 	{Opt_data_journal, EXT4_MOUNT_JOURNAL_DATA, MOPT_NO_EXT2 | MOPT_DATAJ},
18178dc0aa8cSTheodore Ts'o 	{Opt_data_ordered, EXT4_MOUNT_ORDERED_DATA, MOPT_NO_EXT2 | MOPT_DATAJ},
18188dc0aa8cSTheodore Ts'o 	{Opt_data_writeback, EXT4_MOUNT_WRITEBACK_DATA,
18198dc0aa8cSTheodore Ts'o 	 MOPT_NO_EXT2 | MOPT_DATAJ},
182026092bf5STheodore Ts'o 	{Opt_user_xattr, EXT4_MOUNT_XATTR_USER, MOPT_SET},
182126092bf5STheodore Ts'o 	{Opt_nouser_xattr, EXT4_MOUNT_XATTR_USER, MOPT_CLEAR},
182226092bf5STheodore Ts'o #ifdef CONFIG_EXT4_FS_POSIX_ACL
182326092bf5STheodore Ts'o 	{Opt_acl, EXT4_MOUNT_POSIX_ACL, MOPT_SET},
182426092bf5STheodore Ts'o 	{Opt_noacl, EXT4_MOUNT_POSIX_ACL, MOPT_CLEAR},
182526092bf5STheodore Ts'o #else
182626092bf5STheodore Ts'o 	{Opt_acl, 0, MOPT_NOSUPPORT},
182726092bf5STheodore Ts'o 	{Opt_noacl, 0, MOPT_NOSUPPORT},
182826092bf5STheodore Ts'o #endif
182926092bf5STheodore Ts'o 	{Opt_nouid32, EXT4_MOUNT_NO_UID32, MOPT_SET},
183026092bf5STheodore Ts'o 	{Opt_debug, EXT4_MOUNT_DEBUG, MOPT_SET},
1831670e9875STheodore Ts'o 	{Opt_debug_want_extra_isize, 0, MOPT_GTE0},
183226092bf5STheodore Ts'o 	{Opt_quota, EXT4_MOUNT_QUOTA | EXT4_MOUNT_USRQUOTA, MOPT_SET | MOPT_Q},
183326092bf5STheodore Ts'o 	{Opt_usrquota, EXT4_MOUNT_QUOTA | EXT4_MOUNT_USRQUOTA,
183426092bf5STheodore Ts'o 							MOPT_SET | MOPT_Q},
183526092bf5STheodore Ts'o 	{Opt_grpquota, EXT4_MOUNT_QUOTA | EXT4_MOUNT_GRPQUOTA,
183626092bf5STheodore Ts'o 							MOPT_SET | MOPT_Q},
183749da9392SJan Kara 	{Opt_prjquota, EXT4_MOUNT_QUOTA | EXT4_MOUNT_PRJQUOTA,
183849da9392SJan Kara 							MOPT_SET | MOPT_Q},
183926092bf5STheodore Ts'o 	{Opt_noquota, (EXT4_MOUNT_QUOTA | EXT4_MOUNT_USRQUOTA |
184049da9392SJan Kara 		       EXT4_MOUNT_GRPQUOTA | EXT4_MOUNT_PRJQUOTA),
184149da9392SJan Kara 							MOPT_CLEAR | MOPT_Q},
184226092bf5STheodore Ts'o 	{Opt_usrjquota, 0, MOPT_Q},
184326092bf5STheodore Ts'o 	{Opt_grpjquota, 0, MOPT_Q},
184426092bf5STheodore Ts'o 	{Opt_offusrjquota, 0, MOPT_Q},
184526092bf5STheodore Ts'o 	{Opt_offgrpjquota, 0, MOPT_Q},
184626092bf5STheodore Ts'o 	{Opt_jqfmt_vfsold, QFMT_VFS_OLD, MOPT_QFMT},
184726092bf5STheodore Ts'o 	{Opt_jqfmt_vfsv0, QFMT_VFS_V0, MOPT_QFMT},
184826092bf5STheodore Ts'o 	{Opt_jqfmt_vfsv1, QFMT_VFS_V1, MOPT_QFMT},
1849df981d03STheodore Ts'o 	{Opt_max_dir_size_kb, 0, MOPT_GTE0},
1850ed318a6cSEric Biggers 	{Opt_test_dummy_encryption, 0, MOPT_STRING},
1851cdb7ee4cSTahsin Erdogan 	{Opt_nombcache, EXT4_MOUNT_NO_MBCACHE, MOPT_SET},
18523d392b26STheodore Ts'o 	{Opt_prefetch_block_bitmaps, EXT4_MOUNT_PREFETCH_BLOCK_BITMAPS,
18533d392b26STheodore Ts'o 	 MOPT_SET},
185426092bf5STheodore Ts'o 	{Opt_err, 0, 0}
185526092bf5STheodore Ts'o };
185626092bf5STheodore Ts'o 
1857c83ad55eSGabriel Krisman Bertazi #ifdef CONFIG_UNICODE
1858c83ad55eSGabriel Krisman Bertazi static const struct ext4_sb_encodings {
1859c83ad55eSGabriel Krisman Bertazi 	__u16 magic;
1860c83ad55eSGabriel Krisman Bertazi 	char *name;
1861c83ad55eSGabriel Krisman Bertazi 	char *version;
1862c83ad55eSGabriel Krisman Bertazi } ext4_sb_encoding_map[] = {
1863c83ad55eSGabriel Krisman Bertazi 	{EXT4_ENC_UTF8_12_1, "utf8", "12.1.0"},
1864c83ad55eSGabriel Krisman Bertazi };
1865c83ad55eSGabriel Krisman Bertazi 
1866c83ad55eSGabriel Krisman Bertazi static int ext4_sb_read_encoding(const struct ext4_super_block *es,
1867c83ad55eSGabriel Krisman Bertazi 				 const struct ext4_sb_encodings **encoding,
1868c83ad55eSGabriel Krisman Bertazi 				 __u16 *flags)
1869c83ad55eSGabriel Krisman Bertazi {
1870c83ad55eSGabriel Krisman Bertazi 	__u16 magic = le16_to_cpu(es->s_encoding);
1871c83ad55eSGabriel Krisman Bertazi 	int i;
1872c83ad55eSGabriel Krisman Bertazi 
1873c83ad55eSGabriel Krisman Bertazi 	for (i = 0; i < ARRAY_SIZE(ext4_sb_encoding_map); i++)
1874c83ad55eSGabriel Krisman Bertazi 		if (magic == ext4_sb_encoding_map[i].magic)
1875c83ad55eSGabriel Krisman Bertazi 			break;
1876c83ad55eSGabriel Krisman Bertazi 
1877c83ad55eSGabriel Krisman Bertazi 	if (i >= ARRAY_SIZE(ext4_sb_encoding_map))
1878c83ad55eSGabriel Krisman Bertazi 		return -EINVAL;
1879c83ad55eSGabriel Krisman Bertazi 
1880c83ad55eSGabriel Krisman Bertazi 	*encoding = &ext4_sb_encoding_map[i];
1881c83ad55eSGabriel Krisman Bertazi 	*flags = le16_to_cpu(es->s_encoding_flags);
1882c83ad55eSGabriel Krisman Bertazi 
1883c83ad55eSGabriel Krisman Bertazi 	return 0;
1884c83ad55eSGabriel Krisman Bertazi }
1885c83ad55eSGabriel Krisman Bertazi #endif
1886c83ad55eSGabriel Krisman Bertazi 
1887ed318a6cSEric Biggers static int ext4_set_test_dummy_encryption(struct super_block *sb,
1888ed318a6cSEric Biggers 					  const char *opt,
1889ed318a6cSEric Biggers 					  const substring_t *arg,
1890ed318a6cSEric Biggers 					  bool is_remount)
1891ed318a6cSEric Biggers {
1892ed318a6cSEric Biggers #ifdef CONFIG_FS_ENCRYPTION
1893ed318a6cSEric Biggers 	struct ext4_sb_info *sbi = EXT4_SB(sb);
1894ed318a6cSEric Biggers 	int err;
1895ed318a6cSEric Biggers 
1896ed318a6cSEric Biggers 	/*
1897ed318a6cSEric Biggers 	 * This mount option is just for testing, and it's not worthwhile to
1898ed318a6cSEric Biggers 	 * implement the extra complexity (e.g. RCU protection) that would be
1899ed318a6cSEric Biggers 	 * needed to allow it to be set or changed during remount.  We do allow
1900ed318a6cSEric Biggers 	 * it to be specified during remount, but only if there is no change.
1901ed318a6cSEric Biggers 	 */
1902ed318a6cSEric Biggers 	if (is_remount && !sbi->s_dummy_enc_ctx.ctx) {
1903ed318a6cSEric Biggers 		ext4_msg(sb, KERN_WARNING,
1904ed318a6cSEric Biggers 			 "Can't set test_dummy_encryption on remount");
1905ed318a6cSEric Biggers 		return -1;
1906ed318a6cSEric Biggers 	}
1907ed318a6cSEric Biggers 	err = fscrypt_set_test_dummy_encryption(sb, arg, &sbi->s_dummy_enc_ctx);
1908ed318a6cSEric Biggers 	if (err) {
1909ed318a6cSEric Biggers 		if (err == -EEXIST)
1910ed318a6cSEric Biggers 			ext4_msg(sb, KERN_WARNING,
1911ed318a6cSEric Biggers 				 "Can't change test_dummy_encryption on remount");
1912ed318a6cSEric Biggers 		else if (err == -EINVAL)
1913ed318a6cSEric Biggers 			ext4_msg(sb, KERN_WARNING,
1914ed318a6cSEric Biggers 				 "Value of option \"%s\" is unrecognized", opt);
1915ed318a6cSEric Biggers 		else
1916ed318a6cSEric Biggers 			ext4_msg(sb, KERN_WARNING,
1917ed318a6cSEric Biggers 				 "Error processing option \"%s\" [%d]",
1918ed318a6cSEric Biggers 				 opt, err);
1919ed318a6cSEric Biggers 		return -1;
1920ed318a6cSEric Biggers 	}
1921ed318a6cSEric Biggers 	ext4_msg(sb, KERN_WARNING, "Test dummy encryption mode enabled");
1922ed318a6cSEric Biggers #else
1923ed318a6cSEric Biggers 	ext4_msg(sb, KERN_WARNING,
1924ed318a6cSEric Biggers 		 "Test dummy encryption mount option ignored");
1925ed318a6cSEric Biggers #endif
1926ed318a6cSEric Biggers 	return 1;
1927ed318a6cSEric Biggers }
1928ed318a6cSEric Biggers 
192926092bf5STheodore Ts'o static int handle_mount_opt(struct super_block *sb, char *opt, int token,
193026092bf5STheodore Ts'o 			    substring_t *args, unsigned long *journal_devnum,
193126092bf5STheodore Ts'o 			    unsigned int *journal_ioprio, int is_remount)
193226092bf5STheodore Ts'o {
193326092bf5STheodore Ts'o 	struct ext4_sb_info *sbi = EXT4_SB(sb);
193426092bf5STheodore Ts'o 	const struct mount_opts *m;
193508cefc7aSEric W. Biederman 	kuid_t uid;
193608cefc7aSEric W. Biederman 	kgid_t gid;
193726092bf5STheodore Ts'o 	int arg = 0;
193826092bf5STheodore Ts'o 
193957f73c2cSTheodore Ts'o #ifdef CONFIG_QUOTA
194057f73c2cSTheodore Ts'o 	if (token == Opt_usrjquota)
194157f73c2cSTheodore Ts'o 		return set_qf_name(sb, USRQUOTA, &args[0]);
194257f73c2cSTheodore Ts'o 	else if (token == Opt_grpjquota)
194357f73c2cSTheodore Ts'o 		return set_qf_name(sb, GRPQUOTA, &args[0]);
194457f73c2cSTheodore Ts'o 	else if (token == Opt_offusrjquota)
194557f73c2cSTheodore Ts'o 		return clear_qf_name(sb, USRQUOTA);
194657f73c2cSTheodore Ts'o 	else if (token == Opt_offgrpjquota)
194757f73c2cSTheodore Ts'o 		return clear_qf_name(sb, GRPQUOTA);
194857f73c2cSTheodore Ts'o #endif
194926092bf5STheodore Ts'o 	switch (token) {
1950f7048605STheodore Ts'o 	case Opt_noacl:
1951f7048605STheodore Ts'o 	case Opt_nouser_xattr:
1952f7048605STheodore Ts'o 		ext4_msg(sb, KERN_WARNING, deprecated_msg, opt, "3.5");
1953f7048605STheodore Ts'o 		break;
195426092bf5STheodore Ts'o 	case Opt_sb:
195526092bf5STheodore Ts'o 		return 1;	/* handled by get_sb_block() */
195626092bf5STheodore Ts'o 	case Opt_removed:
19575f3633e3SJan Kara 		ext4_msg(sb, KERN_WARNING, "Ignoring removed %s option", opt);
195826092bf5STheodore Ts'o 		return 1;
195926092bf5STheodore Ts'o 	case Opt_abort:
196026092bf5STheodore Ts'o 		sbi->s_mount_flags |= EXT4_MF_FS_ABORTED;
196126092bf5STheodore Ts'o 		return 1;
196226092bf5STheodore Ts'o 	case Opt_i_version:
1963357fdad0SMatthew Garrett 		sb->s_flags |= SB_I_VERSION;
196426092bf5STheodore Ts'o 		return 1;
1965a26f4992STheodore Ts'o 	case Opt_lazytime:
19661751e8a6SLinus Torvalds 		sb->s_flags |= SB_LAZYTIME;
1967a26f4992STheodore Ts'o 		return 1;
1968a26f4992STheodore Ts'o 	case Opt_nolazytime:
19691751e8a6SLinus Torvalds 		sb->s_flags &= ~SB_LAZYTIME;
1970a26f4992STheodore Ts'o 		return 1;
19714f74d15fSEric Biggers 	case Opt_inlinecrypt:
19724f74d15fSEric Biggers #ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT
19734f74d15fSEric Biggers 		sb->s_flags |= SB_INLINECRYPT;
19744f74d15fSEric Biggers #else
19754f74d15fSEric Biggers 		ext4_msg(sb, KERN_ERR, "inline encryption not supported");
19764f74d15fSEric Biggers #endif
19774f74d15fSEric Biggers 		return 1;
197826092bf5STheodore Ts'o 	}
197926092bf5STheodore Ts'o 
19805f3633e3SJan Kara 	for (m = ext4_mount_opts; m->token != Opt_err; m++)
19815f3633e3SJan Kara 		if (token == m->token)
19825f3633e3SJan Kara 			break;
19835f3633e3SJan Kara 
19845f3633e3SJan Kara 	if (m->token == Opt_err) {
19855f3633e3SJan Kara 		ext4_msg(sb, KERN_ERR, "Unrecognized mount option \"%s\" "
19865f3633e3SJan Kara 			 "or missing value", opt);
19875f3633e3SJan Kara 		return -1;
19885f3633e3SJan Kara 	}
19895f3633e3SJan Kara 
19908dc0aa8cSTheodore Ts'o 	if ((m->flags & MOPT_NO_EXT2) && IS_EXT2_SB(sb)) {
19918dc0aa8cSTheodore Ts'o 		ext4_msg(sb, KERN_ERR,
19928dc0aa8cSTheodore Ts'o 			 "Mount option \"%s\" incompatible with ext2", opt);
19938dc0aa8cSTheodore Ts'o 		return -1;
19948dc0aa8cSTheodore Ts'o 	}
19958dc0aa8cSTheodore Ts'o 	if ((m->flags & MOPT_NO_EXT3) && IS_EXT3_SB(sb)) {
19968dc0aa8cSTheodore Ts'o 		ext4_msg(sb, KERN_ERR,
19978dc0aa8cSTheodore Ts'o 			 "Mount option \"%s\" incompatible with ext3", opt);
19988dc0aa8cSTheodore Ts'o 		return -1;
19998dc0aa8cSTheodore Ts'o 	}
20008dc0aa8cSTheodore Ts'o 
2001ad4eec61SEric Sandeen 	if (args->from && !(m->flags & MOPT_STRING) && match_int(args, &arg))
20020efb3b23SJan Kara 		return -1;
200326092bf5STheodore Ts'o 	if (args->from && (m->flags & MOPT_GTE0) && (arg < 0))
200426092bf5STheodore Ts'o 		return -1;
2005c93cf2d7SDmitry Monakhov 	if (m->flags & MOPT_EXPLICIT) {
2006c93cf2d7SDmitry Monakhov 		if (m->mount_opt & EXT4_MOUNT_DELALLOC) {
200726092bf5STheodore Ts'o 			set_opt2(sb, EXPLICIT_DELALLOC);
20081e381f60SDmitry Monakhov 		} else if (m->mount_opt & EXT4_MOUNT_JOURNAL_CHECKSUM) {
20091e381f60SDmitry Monakhov 			set_opt2(sb, EXPLICIT_JOURNAL_CHECKSUM);
2010c93cf2d7SDmitry Monakhov 		} else
2011c93cf2d7SDmitry Monakhov 			return -1;
2012c93cf2d7SDmitry Monakhov 	}
201326092bf5STheodore Ts'o 	if (m->flags & MOPT_CLEAR_ERR)
201426092bf5STheodore Ts'o 		clear_opt(sb, ERRORS_MASK);
201526092bf5STheodore Ts'o 	if (token == Opt_noquota && sb_any_quota_loaded(sb)) {
201626092bf5STheodore Ts'o 		ext4_msg(sb, KERN_ERR, "Cannot change quota "
201726092bf5STheodore Ts'o 			 "options when quota turned on");
201826092bf5STheodore Ts'o 		return -1;
201926092bf5STheodore Ts'o 	}
202026092bf5STheodore Ts'o 
202126092bf5STheodore Ts'o 	if (m->flags & MOPT_NOSUPPORT) {
202226092bf5STheodore Ts'o 		ext4_msg(sb, KERN_ERR, "%s option not supported", opt);
202326092bf5STheodore Ts'o 	} else if (token == Opt_commit) {
202426092bf5STheodore Ts'o 		if (arg == 0)
202526092bf5STheodore Ts'o 			arg = JBD2_DEFAULT_MAX_COMMIT_AGE;
20269ba55543Szhangyi (F) 		else if (arg > INT_MAX / HZ) {
20279ba55543Szhangyi (F) 			ext4_msg(sb, KERN_ERR,
20289ba55543Szhangyi (F) 				 "Invalid commit interval %d, "
20299ba55543Szhangyi (F) 				 "must be smaller than %d",
20309ba55543Szhangyi (F) 				 arg, INT_MAX / HZ);
20319ba55543Szhangyi (F) 			return -1;
20329ba55543Szhangyi (F) 		}
203326092bf5STheodore Ts'o 		sbi->s_commit_interval = HZ * arg;
2034670e9875STheodore Ts'o 	} else if (token == Opt_debug_want_extra_isize) {
20359803387cSTheodore Ts'o 		if ((arg & 1) ||
20369803387cSTheodore Ts'o 		    (arg < 4) ||
20379803387cSTheodore Ts'o 		    (arg > (sbi->s_inode_size - EXT4_GOOD_OLD_INODE_SIZE))) {
20389803387cSTheodore Ts'o 			ext4_msg(sb, KERN_ERR,
20399803387cSTheodore Ts'o 				 "Invalid want_extra_isize %d", arg);
20409803387cSTheodore Ts'o 			return -1;
20419803387cSTheodore Ts'o 		}
2042670e9875STheodore Ts'o 		sbi->s_want_extra_isize = arg;
204326092bf5STheodore Ts'o 	} else if (token == Opt_max_batch_time) {
204426092bf5STheodore Ts'o 		sbi->s_max_batch_time = arg;
204526092bf5STheodore Ts'o 	} else if (token == Opt_min_batch_time) {
204626092bf5STheodore Ts'o 		sbi->s_min_batch_time = arg;
204726092bf5STheodore Ts'o 	} else if (token == Opt_inode_readahead_blks) {
2048e33e60eaSJan Kara 		if (arg && (arg > (1 << 30) || !is_power_of_2(arg))) {
2049e33e60eaSJan Kara 			ext4_msg(sb, KERN_ERR,
2050e33e60eaSJan Kara 				 "EXT4-fs: inode_readahead_blks must be "
2051e33e60eaSJan Kara 				 "0 or a power of 2 smaller than 2^31");
205226092bf5STheodore Ts'o 			return -1;
205326092bf5STheodore Ts'o 		}
205426092bf5STheodore Ts'o 		sbi->s_inode_readahead_blks = arg;
205526092bf5STheodore Ts'o 	} else if (token == Opt_init_itable) {
205626092bf5STheodore Ts'o 		set_opt(sb, INIT_INODE_TABLE);
205726092bf5STheodore Ts'o 		if (!args->from)
205826092bf5STheodore Ts'o 			arg = EXT4_DEF_LI_WAIT_MULT;
205926092bf5STheodore Ts'o 		sbi->s_li_wait_mult = arg;
2060df981d03STheodore Ts'o 	} else if (token == Opt_max_dir_size_kb) {
2061df981d03STheodore Ts'o 		sbi->s_max_dir_size_kb = arg;
206226092bf5STheodore Ts'o 	} else if (token == Opt_stripe) {
206326092bf5STheodore Ts'o 		sbi->s_stripe = arg;
20640efb3b23SJan Kara 	} else if (token == Opt_resuid) {
20650efb3b23SJan Kara 		uid = make_kuid(current_user_ns(), arg);
20660efb3b23SJan Kara 		if (!uid_valid(uid)) {
20675f3633e3SJan Kara 			ext4_msg(sb, KERN_ERR, "Invalid uid value %d", arg);
20680efb3b23SJan Kara 			return -1;
20690efb3b23SJan Kara 		}
20700efb3b23SJan Kara 		sbi->s_resuid = uid;
20710efb3b23SJan Kara 	} else if (token == Opt_resgid) {
20720efb3b23SJan Kara 		gid = make_kgid(current_user_ns(), arg);
20730efb3b23SJan Kara 		if (!gid_valid(gid)) {
20745f3633e3SJan Kara 			ext4_msg(sb, KERN_ERR, "Invalid gid value %d", arg);
20750efb3b23SJan Kara 			return -1;
20760efb3b23SJan Kara 		}
20770efb3b23SJan Kara 		sbi->s_resgid = gid;
20780efb3b23SJan Kara 	} else if (token == Opt_journal_dev) {
20790efb3b23SJan Kara 		if (is_remount) {
20800efb3b23SJan Kara 			ext4_msg(sb, KERN_ERR,
20810efb3b23SJan Kara 				 "Cannot specify journal on remount");
20820efb3b23SJan Kara 			return -1;
20830efb3b23SJan Kara 		}
20840efb3b23SJan Kara 		*journal_devnum = arg;
2085ad4eec61SEric Sandeen 	} else if (token == Opt_journal_path) {
2086ad4eec61SEric Sandeen 		char *journal_path;
2087ad4eec61SEric Sandeen 		struct inode *journal_inode;
2088ad4eec61SEric Sandeen 		struct path path;
2089ad4eec61SEric Sandeen 		int error;
2090ad4eec61SEric Sandeen 
2091ad4eec61SEric Sandeen 		if (is_remount) {
2092ad4eec61SEric Sandeen 			ext4_msg(sb, KERN_ERR,
2093ad4eec61SEric Sandeen 				 "Cannot specify journal on remount");
2094ad4eec61SEric Sandeen 			return -1;
2095ad4eec61SEric Sandeen 		}
2096ad4eec61SEric Sandeen 		journal_path = match_strdup(&args[0]);
2097ad4eec61SEric Sandeen 		if (!journal_path) {
2098ad4eec61SEric Sandeen 			ext4_msg(sb, KERN_ERR, "error: could not dup "
2099ad4eec61SEric Sandeen 				"journal device string");
2100ad4eec61SEric Sandeen 			return -1;
2101ad4eec61SEric Sandeen 		}
2102ad4eec61SEric Sandeen 
2103ad4eec61SEric Sandeen 		error = kern_path(journal_path, LOOKUP_FOLLOW, &path);
2104ad4eec61SEric Sandeen 		if (error) {
2105ad4eec61SEric Sandeen 			ext4_msg(sb, KERN_ERR, "error: could not find "
2106ad4eec61SEric Sandeen 				"journal device path: error %d", error);
2107ad4eec61SEric Sandeen 			kfree(journal_path);
2108ad4eec61SEric Sandeen 			return -1;
2109ad4eec61SEric Sandeen 		}
2110ad4eec61SEric Sandeen 
21112b0143b5SDavid Howells 		journal_inode = d_inode(path.dentry);
2112ad4eec61SEric Sandeen 		if (!S_ISBLK(journal_inode->i_mode)) {
2113ad4eec61SEric Sandeen 			ext4_msg(sb, KERN_ERR, "error: journal path %s "
2114ad4eec61SEric Sandeen 				"is not a block device", journal_path);
2115ad4eec61SEric Sandeen 			path_put(&path);
2116ad4eec61SEric Sandeen 			kfree(journal_path);
2117ad4eec61SEric Sandeen 			return -1;
2118ad4eec61SEric Sandeen 		}
2119ad4eec61SEric Sandeen 
2120ad4eec61SEric Sandeen 		*journal_devnum = new_encode_dev(journal_inode->i_rdev);
2121ad4eec61SEric Sandeen 		path_put(&path);
2122ad4eec61SEric Sandeen 		kfree(journal_path);
21230efb3b23SJan Kara 	} else if (token == Opt_journal_ioprio) {
21240efb3b23SJan Kara 		if (arg > 7) {
21255f3633e3SJan Kara 			ext4_msg(sb, KERN_ERR, "Invalid journal IO priority"
21260efb3b23SJan Kara 				 " (must be 0-7)");
21270efb3b23SJan Kara 			return -1;
21280efb3b23SJan Kara 		}
21290efb3b23SJan Kara 		*journal_ioprio =
21300efb3b23SJan Kara 			IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, arg);
21316ddb2447STheodore Ts'o 	} else if (token == Opt_test_dummy_encryption) {
2132ed318a6cSEric Biggers 		return ext4_set_test_dummy_encryption(sb, opt, &args[0],
2133ed318a6cSEric Biggers 						      is_remount);
213426092bf5STheodore Ts'o 	} else if (m->flags & MOPT_DATAJ) {
213526092bf5STheodore Ts'o 		if (is_remount) {
213626092bf5STheodore Ts'o 			if (!sbi->s_journal)
213726092bf5STheodore Ts'o 				ext4_msg(sb, KERN_WARNING, "Remounting file system with no journal so ignoring journalled data option");
21385f3633e3SJan Kara 			else if (test_opt(sb, DATA_FLAGS) != m->mount_opt) {
213926092bf5STheodore Ts'o 				ext4_msg(sb, KERN_ERR,
214026092bf5STheodore Ts'o 					 "Cannot change data mode on remount");
214126092bf5STheodore Ts'o 				return -1;
214226092bf5STheodore Ts'o 			}
214326092bf5STheodore Ts'o 		} else {
214426092bf5STheodore Ts'o 			clear_opt(sb, DATA_FLAGS);
214526092bf5STheodore Ts'o 			sbi->s_mount_opt |= m->mount_opt;
214626092bf5STheodore Ts'o 		}
214726092bf5STheodore Ts'o #ifdef CONFIG_QUOTA
214826092bf5STheodore Ts'o 	} else if (m->flags & MOPT_QFMT) {
214926092bf5STheodore Ts'o 		if (sb_any_quota_loaded(sb) &&
215026092bf5STheodore Ts'o 		    sbi->s_jquota_fmt != m->mount_opt) {
21515f3633e3SJan Kara 			ext4_msg(sb, KERN_ERR, "Cannot change journaled "
21525f3633e3SJan Kara 				 "quota options when quota turned on");
215326092bf5STheodore Ts'o 			return -1;
215426092bf5STheodore Ts'o 		}
2155e2b911c5SDarrick J. Wong 		if (ext4_has_feature_quota(sb)) {
2156c325a67cSTheodore Ts'o 			ext4_msg(sb, KERN_INFO,
2157c325a67cSTheodore Ts'o 				 "Quota format mount options ignored "
2158262b4662SJan Kara 				 "when QUOTA feature is enabled");
2159c325a67cSTheodore Ts'o 			return 1;
2160262b4662SJan Kara 		}
216126092bf5STheodore Ts'o 		sbi->s_jquota_fmt = m->mount_opt;
216226092bf5STheodore Ts'o #endif
21639cb20f94SIra Weiny 	} else if (token == Opt_dax || token == Opt_dax_always ||
21649cb20f94SIra Weiny 		   token == Opt_dax_inode || token == Opt_dax_never) {
2165ef83b6e8SDan Williams #ifdef CONFIG_FS_DAX
21669cb20f94SIra Weiny 		switch (token) {
21679cb20f94SIra Weiny 		case Opt_dax:
21689cb20f94SIra Weiny 		case Opt_dax_always:
2169829b37b8STheodore Ts'o 			if (is_remount &&
2170829b37b8STheodore Ts'o 			    (!(sbi->s_mount_opt & EXT4_MOUNT_DAX_ALWAYS) ||
2171829b37b8STheodore Ts'o 			     (sbi->s_mount_opt2 & EXT4_MOUNT2_DAX_NEVER))) {
2172829b37b8STheodore Ts'o 			fail_dax_change_remount:
2173829b37b8STheodore Ts'o 				ext4_msg(sb, KERN_ERR, "can't change "
2174829b37b8STheodore Ts'o 					 "dax mount option while remounting");
2175829b37b8STheodore Ts'o 				return -1;
2176829b37b8STheodore Ts'o 			}
2177829b37b8STheodore Ts'o 			if (is_remount &&
2178829b37b8STheodore Ts'o 			    (test_opt(sb, DATA_FLAGS) ==
2179829b37b8STheodore Ts'o 			     EXT4_MOUNT_JOURNAL_DATA)) {
2180829b37b8STheodore Ts'o 				    ext4_msg(sb, KERN_ERR, "can't mount with "
2181829b37b8STheodore Ts'o 					     "both data=journal and dax");
2182829b37b8STheodore Ts'o 				    return -1;
2183829b37b8STheodore Ts'o 			}
2184ef83b6e8SDan Williams 			ext4_msg(sb, KERN_WARNING,
2185ef83b6e8SDan Williams 				"DAX enabled. Warning: EXPERIMENTAL, use at your own risk");
21869cb20f94SIra Weiny 			sbi->s_mount_opt |= EXT4_MOUNT_DAX_ALWAYS;
21879cb20f94SIra Weiny 			sbi->s_mount_opt2 &= ~EXT4_MOUNT2_DAX_NEVER;
21889cb20f94SIra Weiny 			break;
21899cb20f94SIra Weiny 		case Opt_dax_never:
2190829b37b8STheodore Ts'o 			if (is_remount &&
2191829b37b8STheodore Ts'o 			    (!(sbi->s_mount_opt2 & EXT4_MOUNT2_DAX_NEVER) ||
2192829b37b8STheodore Ts'o 			     (sbi->s_mount_opt & EXT4_MOUNT_DAX_ALWAYS)))
2193829b37b8STheodore Ts'o 				goto fail_dax_change_remount;
21949cb20f94SIra Weiny 			sbi->s_mount_opt2 |= EXT4_MOUNT2_DAX_NEVER;
21959cb20f94SIra Weiny 			sbi->s_mount_opt &= ~EXT4_MOUNT_DAX_ALWAYS;
21969cb20f94SIra Weiny 			break;
21979cb20f94SIra Weiny 		case Opt_dax_inode:
2198829b37b8STheodore Ts'o 			if (is_remount &&
2199829b37b8STheodore Ts'o 			    ((sbi->s_mount_opt & EXT4_MOUNT_DAX_ALWAYS) ||
2200829b37b8STheodore Ts'o 			     (sbi->s_mount_opt2 & EXT4_MOUNT2_DAX_NEVER) ||
2201829b37b8STheodore Ts'o 			     !(sbi->s_mount_opt2 & EXT4_MOUNT2_DAX_INODE)))
2202829b37b8STheodore Ts'o 				goto fail_dax_change_remount;
22039cb20f94SIra Weiny 			sbi->s_mount_opt &= ~EXT4_MOUNT_DAX_ALWAYS;
22049cb20f94SIra Weiny 			sbi->s_mount_opt2 &= ~EXT4_MOUNT2_DAX_NEVER;
22059cb20f94SIra Weiny 			/* Strictly for printing options */
22069cb20f94SIra Weiny 			sbi->s_mount_opt2 |= EXT4_MOUNT2_DAX_INODE;
22079cb20f94SIra Weiny 			break;
22089cb20f94SIra Weiny 		}
2209ef83b6e8SDan Williams #else
2210923ae0ffSRoss Zwisler 		ext4_msg(sb, KERN_INFO, "dax option not supported");
22119cb20f94SIra Weiny 		sbi->s_mount_opt2 |= EXT4_MOUNT2_DAX_NEVER;
22129cb20f94SIra Weiny 		sbi->s_mount_opt &= ~EXT4_MOUNT_DAX_ALWAYS;
2213923ae0ffSRoss Zwisler 		return -1;
2214923ae0ffSRoss Zwisler #endif
22157915a861SAles Novak 	} else if (token == Opt_data_err_abort) {
22167915a861SAles Novak 		sbi->s_mount_opt |= m->mount_opt;
22177915a861SAles Novak 	} else if (token == Opt_data_err_ignore) {
22187915a861SAles Novak 		sbi->s_mount_opt &= ~m->mount_opt;
221926092bf5STheodore Ts'o 	} else {
222026092bf5STheodore Ts'o 		if (!args->from)
222126092bf5STheodore Ts'o 			arg = 1;
222226092bf5STheodore Ts'o 		if (m->flags & MOPT_CLEAR)
222326092bf5STheodore Ts'o 			arg = !arg;
222426092bf5STheodore Ts'o 		else if (unlikely(!(m->flags & MOPT_SET))) {
222526092bf5STheodore Ts'o 			ext4_msg(sb, KERN_WARNING,
222626092bf5STheodore Ts'o 				 "buggy handling of option %s", opt);
222726092bf5STheodore Ts'o 			WARN_ON(1);
222826092bf5STheodore Ts'o 			return -1;
222926092bf5STheodore Ts'o 		}
223026092bf5STheodore Ts'o 		if (arg != 0)
223126092bf5STheodore Ts'o 			sbi->s_mount_opt |= m->mount_opt;
223226092bf5STheodore Ts'o 		else
223326092bf5STheodore Ts'o 			sbi->s_mount_opt &= ~m->mount_opt;
223426092bf5STheodore Ts'o 	}
223526092bf5STheodore Ts'o 	return 1;
223626092bf5STheodore Ts'o }
223726092bf5STheodore Ts'o 
2238ac27a0ecSDave Kleikamp static int parse_options(char *options, struct super_block *sb,
2239c3191067STheodore Ts'o 			 unsigned long *journal_devnum,
2240b3881f74STheodore Ts'o 			 unsigned int *journal_ioprio,
2241661aa520SEric Sandeen 			 int is_remount)
2242ac27a0ecSDave Kleikamp {
22431e1a76edSOlof Johansson 	struct ext4_sb_info __maybe_unused *sbi = EXT4_SB(sb);
224433458eabSTheodore Ts'o 	char *p, __maybe_unused *usr_qf_name, __maybe_unused *grp_qf_name;
2245ac27a0ecSDave Kleikamp 	substring_t args[MAX_OPT_ARGS];
224626092bf5STheodore Ts'o 	int token;
2247ac27a0ecSDave Kleikamp 
2248ac27a0ecSDave Kleikamp 	if (!options)
2249ac27a0ecSDave Kleikamp 		return 1;
2250ac27a0ecSDave Kleikamp 
2251ac27a0ecSDave Kleikamp 	while ((p = strsep(&options, ",")) != NULL) {
2252ac27a0ecSDave Kleikamp 		if (!*p)
2253ac27a0ecSDave Kleikamp 			continue;
225415121c18SEric Sandeen 		/*
225515121c18SEric Sandeen 		 * Initialize args struct so we know whether arg was
225615121c18SEric Sandeen 		 * found; some options take optional arguments.
225715121c18SEric Sandeen 		 */
2258caecd0afSSachin Kamat 		args[0].to = args[0].from = NULL;
2259ac27a0ecSDave Kleikamp 		token = match_token(p, tokens, args);
226026092bf5STheodore Ts'o 		if (handle_mount_opt(sb, p, token, args, journal_devnum,
226126092bf5STheodore Ts'o 				     journal_ioprio, is_remount) < 0)
2262ac27a0ecSDave Kleikamp 			return 0;
2263ac27a0ecSDave Kleikamp 	}
2264ac27a0ecSDave Kleikamp #ifdef CONFIG_QUOTA
226549da9392SJan Kara 	/*
226649da9392SJan Kara 	 * We do the test below only for project quotas. 'usrquota' and
226749da9392SJan Kara 	 * 'grpquota' mount options are allowed even without quota feature
226849da9392SJan Kara 	 * to support legacy quotas in quota files.
226949da9392SJan Kara 	 */
227049da9392SJan Kara 	if (test_opt(sb, PRJQUOTA) && !ext4_has_feature_project(sb)) {
227149da9392SJan Kara 		ext4_msg(sb, KERN_ERR, "Project quota feature not enabled. "
227249da9392SJan Kara 			 "Cannot enable project quota enforcement.");
227349da9392SJan Kara 		return 0;
227449da9392SJan Kara 	}
227533458eabSTheodore Ts'o 	usr_qf_name = get_qf_name(sb, sbi, USRQUOTA);
227633458eabSTheodore Ts'o 	grp_qf_name = get_qf_name(sb, sbi, GRPQUOTA);
227733458eabSTheodore Ts'o 	if (usr_qf_name || grp_qf_name) {
227833458eabSTheodore Ts'o 		if (test_opt(sb, USRQUOTA) && usr_qf_name)
2279fd8c37ecSTheodore Ts'o 			clear_opt(sb, USRQUOTA);
2280ac27a0ecSDave Kleikamp 
228133458eabSTheodore Ts'o 		if (test_opt(sb, GRPQUOTA) && grp_qf_name)
2282fd8c37ecSTheodore Ts'o 			clear_opt(sb, GRPQUOTA);
2283ac27a0ecSDave Kleikamp 
228456c50f11SDmitry Monakhov 		if (test_opt(sb, GRPQUOTA) || test_opt(sb, USRQUOTA)) {
2285b31e1552SEric Sandeen 			ext4_msg(sb, KERN_ERR, "old and new quota "
2286b31e1552SEric Sandeen 					"format mixing");
2287ac27a0ecSDave Kleikamp 			return 0;
2288ac27a0ecSDave Kleikamp 		}
2289ac27a0ecSDave Kleikamp 
2290ac27a0ecSDave Kleikamp 		if (!sbi->s_jquota_fmt) {
2291b31e1552SEric Sandeen 			ext4_msg(sb, KERN_ERR, "journaled quota format "
2292b31e1552SEric Sandeen 					"not specified");
2293ac27a0ecSDave Kleikamp 			return 0;
2294ac27a0ecSDave Kleikamp 		}
2295ac27a0ecSDave Kleikamp 	}
2296ac27a0ecSDave Kleikamp #endif
2297626b035bSRitesh Harjani 	if (test_opt(sb, DIOREAD_NOLOCK)) {
2298626b035bSRitesh Harjani 		int blocksize =
2299626b035bSRitesh Harjani 			BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size);
2300626b035bSRitesh Harjani 		if (blocksize < PAGE_SIZE)
2301626b035bSRitesh Harjani 			ext4_msg(sb, KERN_WARNING, "Warning: mounting with an "
2302626b035bSRitesh Harjani 				 "experimental mount option 'dioread_nolock' "
2303626b035bSRitesh Harjani 				 "for blocksize < PAGE_SIZE");
2304626b035bSRitesh Harjani 	}
2305ac27a0ecSDave Kleikamp 	return 1;
2306ac27a0ecSDave Kleikamp }
2307ac27a0ecSDave Kleikamp 
23082adf6da8STheodore Ts'o static inline void ext4_show_quota_options(struct seq_file *seq,
23092adf6da8STheodore Ts'o 					   struct super_block *sb)
23102adf6da8STheodore Ts'o {
23112adf6da8STheodore Ts'o #if defined(CONFIG_QUOTA)
23122adf6da8STheodore Ts'o 	struct ext4_sb_info *sbi = EXT4_SB(sb);
231333458eabSTheodore Ts'o 	char *usr_qf_name, *grp_qf_name;
23142adf6da8STheodore Ts'o 
23152adf6da8STheodore Ts'o 	if (sbi->s_jquota_fmt) {
23162adf6da8STheodore Ts'o 		char *fmtname = "";
23172adf6da8STheodore Ts'o 
23182adf6da8STheodore Ts'o 		switch (sbi->s_jquota_fmt) {
23192adf6da8STheodore Ts'o 		case QFMT_VFS_OLD:
23202adf6da8STheodore Ts'o 			fmtname = "vfsold";
23212adf6da8STheodore Ts'o 			break;
23222adf6da8STheodore Ts'o 		case QFMT_VFS_V0:
23232adf6da8STheodore Ts'o 			fmtname = "vfsv0";
23242adf6da8STheodore Ts'o 			break;
23252adf6da8STheodore Ts'o 		case QFMT_VFS_V1:
23262adf6da8STheodore Ts'o 			fmtname = "vfsv1";
23272adf6da8STheodore Ts'o 			break;
23282adf6da8STheodore Ts'o 		}
23292adf6da8STheodore Ts'o 		seq_printf(seq, ",jqfmt=%s", fmtname);
23302adf6da8STheodore Ts'o 	}
23312adf6da8STheodore Ts'o 
233233458eabSTheodore Ts'o 	rcu_read_lock();
233333458eabSTheodore Ts'o 	usr_qf_name = rcu_dereference(sbi->s_qf_names[USRQUOTA]);
233433458eabSTheodore Ts'o 	grp_qf_name = rcu_dereference(sbi->s_qf_names[GRPQUOTA]);
233533458eabSTheodore Ts'o 	if (usr_qf_name)
233633458eabSTheodore Ts'o 		seq_show_option(seq, "usrjquota", usr_qf_name);
233733458eabSTheodore Ts'o 	if (grp_qf_name)
233833458eabSTheodore Ts'o 		seq_show_option(seq, "grpjquota", grp_qf_name);
233933458eabSTheodore Ts'o 	rcu_read_unlock();
23402adf6da8STheodore Ts'o #endif
23412adf6da8STheodore Ts'o }
23422adf6da8STheodore Ts'o 
23435a916be1STheodore Ts'o static const char *token2str(int token)
23445a916be1STheodore Ts'o {
234550df9fd5SHerton Ronaldo Krzesinski 	const struct match_token *t;
23465a916be1STheodore Ts'o 
23475a916be1STheodore Ts'o 	for (t = tokens; t->token != Opt_err; t++)
23485a916be1STheodore Ts'o 		if (t->token == token && !strchr(t->pattern, '='))
23495a916be1STheodore Ts'o 			break;
23505a916be1STheodore Ts'o 	return t->pattern;
23515a916be1STheodore Ts'o }
23525a916be1STheodore Ts'o 
23532adf6da8STheodore Ts'o /*
23542adf6da8STheodore Ts'o  * Show an option if
23552adf6da8STheodore Ts'o  *  - it's set to a non-default value OR
23562adf6da8STheodore Ts'o  *  - if the per-sb default is different from the global default
23572adf6da8STheodore Ts'o  */
235866acdcf4STheodore Ts'o static int _ext4_show_options(struct seq_file *seq, struct super_block *sb,
235966acdcf4STheodore Ts'o 			      int nodefs)
23602adf6da8STheodore Ts'o {
23612adf6da8STheodore Ts'o 	struct ext4_sb_info *sbi = EXT4_SB(sb);
23622adf6da8STheodore Ts'o 	struct ext4_super_block *es = sbi->s_es;
236368afa7e0STyson Nottingham 	int def_errors, def_mount_opt = sbi->s_def_mount_opt;
23645a916be1STheodore Ts'o 	const struct mount_opts *m;
236566acdcf4STheodore Ts'o 	char sep = nodefs ? '\n' : ',';
23662adf6da8STheodore Ts'o 
236766acdcf4STheodore Ts'o #define SEQ_OPTS_PUTS(str) seq_printf(seq, "%c" str, sep)
236866acdcf4STheodore Ts'o #define SEQ_OPTS_PRINT(str, arg) seq_printf(seq, "%c" str, sep, arg)
23692adf6da8STheodore Ts'o 
23702adf6da8STheodore Ts'o 	if (sbi->s_sb_block != 1)
23715a916be1STheodore Ts'o 		SEQ_OPTS_PRINT("sb=%llu", sbi->s_sb_block);
23725a916be1STheodore Ts'o 
23735a916be1STheodore Ts'o 	for (m = ext4_mount_opts; m->token != Opt_err; m++) {
23745a916be1STheodore Ts'o 		int want_set = m->flags & MOPT_SET;
23755a916be1STheodore Ts'o 		if (((m->flags & (MOPT_SET|MOPT_CLEAR)) == 0) ||
23769cb20f94SIra Weiny 		    (m->flags & MOPT_CLEAR_ERR) || m->flags & MOPT_SKIP)
23775a916be1STheodore Ts'o 			continue;
237868afa7e0STyson Nottingham 		if (!nodefs && !(m->mount_opt & (sbi->s_mount_opt ^ def_mount_opt)))
23795a916be1STheodore Ts'o 			continue; /* skip if same as the default */
23805a916be1STheodore Ts'o 		if ((want_set &&
23815a916be1STheodore Ts'o 		     (sbi->s_mount_opt & m->mount_opt) != m->mount_opt) ||
23825a916be1STheodore Ts'o 		    (!want_set && (sbi->s_mount_opt & m->mount_opt)))
23835a916be1STheodore Ts'o 			continue; /* select Opt_noFoo vs Opt_Foo */
23845a916be1STheodore Ts'o 		SEQ_OPTS_PRINT("%s", token2str(m->token));
23855a916be1STheodore Ts'o 	}
23865a916be1STheodore Ts'o 
238708cefc7aSEric W. Biederman 	if (nodefs || !uid_eq(sbi->s_resuid, make_kuid(&init_user_ns, EXT4_DEF_RESUID)) ||
23885a916be1STheodore Ts'o 	    le16_to_cpu(es->s_def_resuid) != EXT4_DEF_RESUID)
238908cefc7aSEric W. Biederman 		SEQ_OPTS_PRINT("resuid=%u",
239008cefc7aSEric W. Biederman 				from_kuid_munged(&init_user_ns, sbi->s_resuid));
239108cefc7aSEric W. Biederman 	if (nodefs || !gid_eq(sbi->s_resgid, make_kgid(&init_user_ns, EXT4_DEF_RESGID)) ||
23925a916be1STheodore Ts'o 	    le16_to_cpu(es->s_def_resgid) != EXT4_DEF_RESGID)
239308cefc7aSEric W. Biederman 		SEQ_OPTS_PRINT("resgid=%u",
239408cefc7aSEric W. Biederman 				from_kgid_munged(&init_user_ns, sbi->s_resgid));
239566acdcf4STheodore Ts'o 	def_errors = nodefs ? -1 : le16_to_cpu(es->s_errors);
23965a916be1STheodore Ts'o 	if (test_opt(sb, ERRORS_RO) && def_errors != EXT4_ERRORS_RO)
23975a916be1STheodore Ts'o 		SEQ_OPTS_PUTS("errors=remount-ro");
23982adf6da8STheodore Ts'o 	if (test_opt(sb, ERRORS_CONT) && def_errors != EXT4_ERRORS_CONTINUE)
23995a916be1STheodore Ts'o 		SEQ_OPTS_PUTS("errors=continue");
24002adf6da8STheodore Ts'o 	if (test_opt(sb, ERRORS_PANIC) && def_errors != EXT4_ERRORS_PANIC)
24015a916be1STheodore Ts'o 		SEQ_OPTS_PUTS("errors=panic");
240266acdcf4STheodore Ts'o 	if (nodefs || sbi->s_commit_interval != JBD2_DEFAULT_MAX_COMMIT_AGE*HZ)
24035a916be1STheodore Ts'o 		SEQ_OPTS_PRINT("commit=%lu", sbi->s_commit_interval / HZ);
240466acdcf4STheodore Ts'o 	if (nodefs || sbi->s_min_batch_time != EXT4_DEF_MIN_BATCH_TIME)
24055a916be1STheodore Ts'o 		SEQ_OPTS_PRINT("min_batch_time=%u", sbi->s_min_batch_time);
240666acdcf4STheodore Ts'o 	if (nodefs || sbi->s_max_batch_time != EXT4_DEF_MAX_BATCH_TIME)
24075a916be1STheodore Ts'o 		SEQ_OPTS_PRINT("max_batch_time=%u", sbi->s_max_batch_time);
2408357fdad0SMatthew Garrett 	if (sb->s_flags & SB_I_VERSION)
24095a916be1STheodore Ts'o 		SEQ_OPTS_PUTS("i_version");
241066acdcf4STheodore Ts'o 	if (nodefs || sbi->s_stripe)
24115a916be1STheodore Ts'o 		SEQ_OPTS_PRINT("stripe=%lu", sbi->s_stripe);
241268afa7e0STyson Nottingham 	if (nodefs || EXT4_MOUNT_DATA_FLAGS &
241368afa7e0STyson Nottingham 			(sbi->s_mount_opt ^ def_mount_opt)) {
24142adf6da8STheodore Ts'o 		if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
24155a916be1STheodore Ts'o 			SEQ_OPTS_PUTS("data=journal");
24162adf6da8STheodore Ts'o 		else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
24175a916be1STheodore Ts'o 			SEQ_OPTS_PUTS("data=ordered");
24182adf6da8STheodore Ts'o 		else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
24195a916be1STheodore Ts'o 			SEQ_OPTS_PUTS("data=writeback");
24205a916be1STheodore Ts'o 	}
242166acdcf4STheodore Ts'o 	if (nodefs ||
242266acdcf4STheodore Ts'o 	    sbi->s_inode_readahead_blks != EXT4_DEF_INODE_READAHEAD_BLKS)
24235a916be1STheodore Ts'o 		SEQ_OPTS_PRINT("inode_readahead_blks=%u",
24242adf6da8STheodore Ts'o 			       sbi->s_inode_readahead_blks);
24252adf6da8STheodore Ts'o 
2426ceec0376STyson Nottingham 	if (test_opt(sb, INIT_INODE_TABLE) && (nodefs ||
242766acdcf4STheodore Ts'o 		       (sbi->s_li_wait_mult != EXT4_DEF_LI_WAIT_MULT)))
24285a916be1STheodore Ts'o 		SEQ_OPTS_PRINT("init_itable=%u", sbi->s_li_wait_mult);
2429df981d03STheodore Ts'o 	if (nodefs || sbi->s_max_dir_size_kb)
2430df981d03STheodore Ts'o 		SEQ_OPTS_PRINT("max_dir_size_kb=%u", sbi->s_max_dir_size_kb);
24317915a861SAles Novak 	if (test_opt(sb, DATA_ERR_ABORT))
24327915a861SAles Novak 		SEQ_OPTS_PUTS("data_err=abort");
2433ed318a6cSEric Biggers 
2434ed318a6cSEric Biggers 	fscrypt_show_test_dummy_encryption(seq, sep, sb);
24352adf6da8STheodore Ts'o 
24364f74d15fSEric Biggers 	if (sb->s_flags & SB_INLINECRYPT)
24374f74d15fSEric Biggers 		SEQ_OPTS_PUTS("inlinecrypt");
24384f74d15fSEric Biggers 
24399cb20f94SIra Weiny 	if (test_opt(sb, DAX_ALWAYS)) {
24409cb20f94SIra Weiny 		if (IS_EXT2_SB(sb))
24419cb20f94SIra Weiny 			SEQ_OPTS_PUTS("dax");
24429cb20f94SIra Weiny 		else
24439cb20f94SIra Weiny 			SEQ_OPTS_PUTS("dax=always");
24449cb20f94SIra Weiny 	} else if (test_opt2(sb, DAX_NEVER)) {
24459cb20f94SIra Weiny 		SEQ_OPTS_PUTS("dax=never");
24469cb20f94SIra Weiny 	} else if (test_opt2(sb, DAX_INODE)) {
24479cb20f94SIra Weiny 		SEQ_OPTS_PUTS("dax=inode");
24489cb20f94SIra Weiny 	}
24499cb20f94SIra Weiny 
24502adf6da8STheodore Ts'o 	ext4_show_quota_options(seq, sb);
24512adf6da8STheodore Ts'o 	return 0;
24522adf6da8STheodore Ts'o }
24532adf6da8STheodore Ts'o 
245466acdcf4STheodore Ts'o static int ext4_show_options(struct seq_file *seq, struct dentry *root)
245566acdcf4STheodore Ts'o {
245666acdcf4STheodore Ts'o 	return _ext4_show_options(seq, root->d_sb, 0);
245766acdcf4STheodore Ts'o }
245866acdcf4STheodore Ts'o 
2459ebd173beSTheodore Ts'o int ext4_seq_options_show(struct seq_file *seq, void *offset)
246066acdcf4STheodore Ts'o {
246166acdcf4STheodore Ts'o 	struct super_block *sb = seq->private;
246266acdcf4STheodore Ts'o 	int rc;
246366acdcf4STheodore Ts'o 
2464bc98a42cSDavid Howells 	seq_puts(seq, sb_rdonly(sb) ? "ro" : "rw");
246566acdcf4STheodore Ts'o 	rc = _ext4_show_options(seq, sb, 1);
246666acdcf4STheodore Ts'o 	seq_puts(seq, "\n");
246766acdcf4STheodore Ts'o 	return rc;
246866acdcf4STheodore Ts'o }
246966acdcf4STheodore Ts'o 
2470617ba13bSMingming Cao static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
2471ac27a0ecSDave Kleikamp 			    int read_only)
2472ac27a0ecSDave Kleikamp {
2473617ba13bSMingming Cao 	struct ext4_sb_info *sbi = EXT4_SB(sb);
2474c89128a0SJaegeuk Kim 	int err = 0;
2475ac27a0ecSDave Kleikamp 
2476617ba13bSMingming Cao 	if (le32_to_cpu(es->s_rev_level) > EXT4_MAX_SUPP_REV) {
2477b31e1552SEric Sandeen 		ext4_msg(sb, KERN_ERR, "revision level too high, "
2478b31e1552SEric Sandeen 			 "forcing read-only mode");
2479c89128a0SJaegeuk Kim 		err = -EROFS;
24805adaccacSyangerkun 		goto done;
2481ac27a0ecSDave Kleikamp 	}
2482ac27a0ecSDave Kleikamp 	if (read_only)
2483281b5995STheodore Ts'o 		goto done;
2484617ba13bSMingming Cao 	if (!(sbi->s_mount_state & EXT4_VALID_FS))
2485b31e1552SEric Sandeen 		ext4_msg(sb, KERN_WARNING, "warning: mounting unchecked fs, "
2486b31e1552SEric Sandeen 			 "running e2fsck is recommended");
2487c8b459f4SLukas Czerner 	else if (sbi->s_mount_state & EXT4_ERROR_FS)
2488b31e1552SEric Sandeen 		ext4_msg(sb, KERN_WARNING,
2489b31e1552SEric Sandeen 			 "warning: mounting fs with errors, "
2490b31e1552SEric Sandeen 			 "running e2fsck is recommended");
2491ed3ce80aSTao Ma 	else if ((__s16) le16_to_cpu(es->s_max_mnt_count) > 0 &&
2492ac27a0ecSDave Kleikamp 		 le16_to_cpu(es->s_mnt_count) >=
2493ac27a0ecSDave Kleikamp 		 (unsigned short) (__s16) le16_to_cpu(es->s_max_mnt_count))
2494b31e1552SEric Sandeen 		ext4_msg(sb, KERN_WARNING,
2495b31e1552SEric Sandeen 			 "warning: maximal mount count reached, "
2496b31e1552SEric Sandeen 			 "running e2fsck is recommended");
2497ac27a0ecSDave Kleikamp 	else if (le32_to_cpu(es->s_checkinterval) &&
24986a0678a7SArnd Bergmann 		 (ext4_get_tstamp(es, s_lastcheck) +
24996a0678a7SArnd Bergmann 		  le32_to_cpu(es->s_checkinterval) <= ktime_get_real_seconds()))
2500b31e1552SEric Sandeen 		ext4_msg(sb, KERN_WARNING,
2501b31e1552SEric Sandeen 			 "warning: checktime reached, "
2502b31e1552SEric Sandeen 			 "running e2fsck is recommended");
25030390131bSFrank Mayhar 	if (!sbi->s_journal)
2504216c34b2SMarcin Slusarz 		es->s_state &= cpu_to_le16(~EXT4_VALID_FS);
2505ac27a0ecSDave Kleikamp 	if (!(__s16) le16_to_cpu(es->s_max_mnt_count))
2506617ba13bSMingming Cao 		es->s_max_mnt_count = cpu_to_le16(EXT4_DFL_MAX_MNT_COUNT);
2507e8546d06SMarcin Slusarz 	le16_add_cpu(&es->s_mnt_count, 1);
25086a0678a7SArnd Bergmann 	ext4_update_tstamp(es, s_mtime);
25090390131bSFrank Mayhar 	if (sbi->s_journal)
2510e2b911c5SDarrick J. Wong 		ext4_set_feature_journal_needs_recovery(sb);
2511ac27a0ecSDave Kleikamp 
2512c89128a0SJaegeuk Kim 	err = ext4_commit_super(sb, 1);
2513281b5995STheodore Ts'o done:
2514ac27a0ecSDave Kleikamp 	if (test_opt(sb, DEBUG))
2515a9df9a49STheodore Ts'o 		printk(KERN_INFO "[EXT4 FS bs=%lu, gc=%u, "
2516a2595b8aSTheodore Ts'o 				"bpg=%lu, ipg=%lu, mo=%04x, mo2=%04x]\n",
2517ac27a0ecSDave Kleikamp 			sb->s_blocksize,
2518ac27a0ecSDave Kleikamp 			sbi->s_groups_count,
2519617ba13bSMingming Cao 			EXT4_BLOCKS_PER_GROUP(sb),
2520617ba13bSMingming Cao 			EXT4_INODES_PER_GROUP(sb),
2521a2595b8aSTheodore Ts'o 			sbi->s_mount_opt, sbi->s_mount_opt2);
2522ac27a0ecSDave Kleikamp 
25237abc52c2SDan Magenheimer 	cleancache_init_fs(sb);
2524c89128a0SJaegeuk Kim 	return err;
2525ac27a0ecSDave Kleikamp }
2526ac27a0ecSDave Kleikamp 
2527117fff10STheodore Ts'o int ext4_alloc_flex_bg_array(struct super_block *sb, ext4_group_t ngroup)
2528117fff10STheodore Ts'o {
2529117fff10STheodore Ts'o 	struct ext4_sb_info *sbi = EXT4_SB(sb);
25307c990728SSuraj Jitindar Singh 	struct flex_groups **old_groups, **new_groups;
253137b0b6b8SDan Carpenter 	int size, i, j;
2532117fff10STheodore Ts'o 
2533117fff10STheodore Ts'o 	if (!sbi->s_log_groups_per_flex)
2534117fff10STheodore Ts'o 		return 0;
2535117fff10STheodore Ts'o 
2536117fff10STheodore Ts'o 	size = ext4_flex_group(sbi, ngroup - 1) + 1;
2537117fff10STheodore Ts'o 	if (size <= sbi->s_flex_groups_allocated)
2538117fff10STheodore Ts'o 		return 0;
2539117fff10STheodore Ts'o 
25407c990728SSuraj Jitindar Singh 	new_groups = kvzalloc(roundup_pow_of_two(size *
25417c990728SSuraj Jitindar Singh 			      sizeof(*sbi->s_flex_groups)), GFP_KERNEL);
2542117fff10STheodore Ts'o 	if (!new_groups) {
25437c990728SSuraj Jitindar Singh 		ext4_msg(sb, KERN_ERR,
25447c990728SSuraj Jitindar Singh 			 "not enough memory for %d flex group pointers", size);
2545117fff10STheodore Ts'o 		return -ENOMEM;
2546117fff10STheodore Ts'o 	}
25477c990728SSuraj Jitindar Singh 	for (i = sbi->s_flex_groups_allocated; i < size; i++) {
25487c990728SSuraj Jitindar Singh 		new_groups[i] = kvzalloc(roundup_pow_of_two(
25497c990728SSuraj Jitindar Singh 					 sizeof(struct flex_groups)),
25507c990728SSuraj Jitindar Singh 					 GFP_KERNEL);
25517c990728SSuraj Jitindar Singh 		if (!new_groups[i]) {
255237b0b6b8SDan Carpenter 			for (j = sbi->s_flex_groups_allocated; j < i; j++)
255337b0b6b8SDan Carpenter 				kvfree(new_groups[j]);
25547c990728SSuraj Jitindar Singh 			kvfree(new_groups);
25557c990728SSuraj Jitindar Singh 			ext4_msg(sb, KERN_ERR,
25567c990728SSuraj Jitindar Singh 				 "not enough memory for %d flex groups", size);
25577c990728SSuraj Jitindar Singh 			return -ENOMEM;
2558117fff10STheodore Ts'o 		}
25597c990728SSuraj Jitindar Singh 	}
25607c990728SSuraj Jitindar Singh 	rcu_read_lock();
25617c990728SSuraj Jitindar Singh 	old_groups = rcu_dereference(sbi->s_flex_groups);
25627c990728SSuraj Jitindar Singh 	if (old_groups)
25637c990728SSuraj Jitindar Singh 		memcpy(new_groups, old_groups,
25647c990728SSuraj Jitindar Singh 		       (sbi->s_flex_groups_allocated *
25657c990728SSuraj Jitindar Singh 			sizeof(struct flex_groups *)));
25667c990728SSuraj Jitindar Singh 	rcu_read_unlock();
25677c990728SSuraj Jitindar Singh 	rcu_assign_pointer(sbi->s_flex_groups, new_groups);
25687c990728SSuraj Jitindar Singh 	sbi->s_flex_groups_allocated = size;
25697c990728SSuraj Jitindar Singh 	if (old_groups)
25707c990728SSuraj Jitindar Singh 		ext4_kvfree_array_rcu(old_groups);
2571117fff10STheodore Ts'o 	return 0;
2572117fff10STheodore Ts'o }
2573117fff10STheodore Ts'o 
2574772cb7c8SJose R. Santos static int ext4_fill_flex_info(struct super_block *sb)
2575772cb7c8SJose R. Santos {
2576772cb7c8SJose R. Santos 	struct ext4_sb_info *sbi = EXT4_SB(sb);
2577772cb7c8SJose R. Santos 	struct ext4_group_desc *gdp = NULL;
25787c990728SSuraj Jitindar Singh 	struct flex_groups *fg;
2579772cb7c8SJose R. Santos 	ext4_group_t flex_group;
2580117fff10STheodore Ts'o 	int i, err;
2581772cb7c8SJose R. Santos 
2582503358aeSTheodore Ts'o 	sbi->s_log_groups_per_flex = sbi->s_es->s_log_groups_per_flex;
2583d50f2ab6SXi Wang 	if (sbi->s_log_groups_per_flex < 1 || sbi->s_log_groups_per_flex > 31) {
2584772cb7c8SJose R. Santos 		sbi->s_log_groups_per_flex = 0;
2585772cb7c8SJose R. Santos 		return 1;
2586772cb7c8SJose R. Santos 	}
2587772cb7c8SJose R. Santos 
2588117fff10STheodore Ts'o 	err = ext4_alloc_flex_bg_array(sb, sbi->s_groups_count);
2589117fff10STheodore Ts'o 	if (err)
2590772cb7c8SJose R. Santos 		goto failed;
2591772cb7c8SJose R. Santos 
2592772cb7c8SJose R. Santos 	for (i = 0; i < sbi->s_groups_count; i++) {
259388b6edd1STheodore Ts'o 		gdp = ext4_get_group_desc(sb, i, NULL);
2594772cb7c8SJose R. Santos 
2595772cb7c8SJose R. Santos 		flex_group = ext4_flex_group(sbi, i);
25967c990728SSuraj Jitindar Singh 		fg = sbi_array_rcu_deref(sbi, s_flex_groups, flex_group);
25977c990728SSuraj Jitindar Singh 		atomic_add(ext4_free_inodes_count(sb, gdp), &fg->free_inodes);
259890ba983fSTheodore Ts'o 		atomic64_add(ext4_free_group_clusters(sb, gdp),
25997c990728SSuraj Jitindar Singh 			     &fg->free_clusters);
26007c990728SSuraj Jitindar Singh 		atomic_add(ext4_used_dirs_count(sb, gdp), &fg->used_dirs);
2601772cb7c8SJose R. Santos 	}
2602772cb7c8SJose R. Santos 
2603772cb7c8SJose R. Santos 	return 1;
2604772cb7c8SJose R. Santos failed:
2605772cb7c8SJose R. Santos 	return 0;
2606772cb7c8SJose R. Santos }
2607772cb7c8SJose R. Santos 
2608e2b911c5SDarrick J. Wong static __le16 ext4_group_desc_csum(struct super_block *sb, __u32 block_group,
2609717d50e4SAndreas Dilger 				   struct ext4_group_desc *gdp)
2610717d50e4SAndreas Dilger {
2611b47820edSDaeho Jeong 	int offset = offsetof(struct ext4_group_desc, bg_checksum);
2612717d50e4SAndreas Dilger 	__u16 crc = 0;
2613717d50e4SAndreas Dilger 	__le32 le_group = cpu_to_le32(block_group);
2614e2b911c5SDarrick J. Wong 	struct ext4_sb_info *sbi = EXT4_SB(sb);
2615717d50e4SAndreas Dilger 
26169aa5d32bSDmitry Monakhov 	if (ext4_has_metadata_csum(sbi->s_sb)) {
2617feb0ab32SDarrick J. Wong 		/* Use new metadata_csum algorithm */
2618feb0ab32SDarrick J. Wong 		__u32 csum32;
2619b47820edSDaeho Jeong 		__u16 dummy_csum = 0;
2620feb0ab32SDarrick J. Wong 
2621feb0ab32SDarrick J. Wong 		csum32 = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)&le_group,
2622feb0ab32SDarrick J. Wong 				     sizeof(le_group));
2623b47820edSDaeho Jeong 		csum32 = ext4_chksum(sbi, csum32, (__u8 *)gdp, offset);
2624b47820edSDaeho Jeong 		csum32 = ext4_chksum(sbi, csum32, (__u8 *)&dummy_csum,
2625b47820edSDaeho Jeong 				     sizeof(dummy_csum));
2626b47820edSDaeho Jeong 		offset += sizeof(dummy_csum);
2627b47820edSDaeho Jeong 		if (offset < sbi->s_desc_size)
2628b47820edSDaeho Jeong 			csum32 = ext4_chksum(sbi, csum32, (__u8 *)gdp + offset,
2629b47820edSDaeho Jeong 					     sbi->s_desc_size - offset);
2630feb0ab32SDarrick J. Wong 
2631feb0ab32SDarrick J. Wong 		crc = csum32 & 0xFFFF;
2632feb0ab32SDarrick J. Wong 		goto out;
2633feb0ab32SDarrick J. Wong 	}
2634feb0ab32SDarrick J. Wong 
2635feb0ab32SDarrick J. Wong 	/* old crc16 code */
2636e2b911c5SDarrick J. Wong 	if (!ext4_has_feature_gdt_csum(sb))
2637813d32f9SDarrick J. Wong 		return 0;
2638813d32f9SDarrick J. Wong 
2639717d50e4SAndreas Dilger 	crc = crc16(~0, sbi->s_es->s_uuid, sizeof(sbi->s_es->s_uuid));
2640717d50e4SAndreas Dilger 	crc = crc16(crc, (__u8 *)&le_group, sizeof(le_group));
2641717d50e4SAndreas Dilger 	crc = crc16(crc, (__u8 *)gdp, offset);
2642717d50e4SAndreas Dilger 	offset += sizeof(gdp->bg_checksum); /* skip checksum */
2643717d50e4SAndreas Dilger 	/* for checksum of struct ext4_group_desc do the rest...*/
2644e2b911c5SDarrick J. Wong 	if (ext4_has_feature_64bit(sb) &&
2645717d50e4SAndreas Dilger 	    offset < le16_to_cpu(sbi->s_es->s_desc_size))
2646717d50e4SAndreas Dilger 		crc = crc16(crc, (__u8 *)gdp + offset,
2647717d50e4SAndreas Dilger 			    le16_to_cpu(sbi->s_es->s_desc_size) -
2648717d50e4SAndreas Dilger 				offset);
2649717d50e4SAndreas Dilger 
2650feb0ab32SDarrick J. Wong out:
2651717d50e4SAndreas Dilger 	return cpu_to_le16(crc);
2652717d50e4SAndreas Dilger }
2653717d50e4SAndreas Dilger 
2654feb0ab32SDarrick J. Wong int ext4_group_desc_csum_verify(struct super_block *sb, __u32 block_group,
2655717d50e4SAndreas Dilger 				struct ext4_group_desc *gdp)
2656717d50e4SAndreas Dilger {
2657feb0ab32SDarrick J. Wong 	if (ext4_has_group_desc_csum(sb) &&
2658e2b911c5SDarrick J. Wong 	    (gdp->bg_checksum != ext4_group_desc_csum(sb, block_group, gdp)))
2659717d50e4SAndreas Dilger 		return 0;
2660717d50e4SAndreas Dilger 
2661717d50e4SAndreas Dilger 	return 1;
2662717d50e4SAndreas Dilger }
2663717d50e4SAndreas Dilger 
2664feb0ab32SDarrick J. Wong void ext4_group_desc_csum_set(struct super_block *sb, __u32 block_group,
2665feb0ab32SDarrick J. Wong 			      struct ext4_group_desc *gdp)
2666feb0ab32SDarrick J. Wong {
2667feb0ab32SDarrick J. Wong 	if (!ext4_has_group_desc_csum(sb))
2668feb0ab32SDarrick J. Wong 		return;
2669e2b911c5SDarrick J. Wong 	gdp->bg_checksum = ext4_group_desc_csum(sb, block_group, gdp);
2670feb0ab32SDarrick J. Wong }
2671feb0ab32SDarrick J. Wong 
2672ac27a0ecSDave Kleikamp /* Called at mount-time, super-block is locked */
2673bfff6873SLukas Czerner static int ext4_check_descriptors(struct super_block *sb,
2674829fa70dSTheodore Ts'o 				  ext4_fsblk_t sb_block,
2675bfff6873SLukas Czerner 				  ext4_group_t *first_not_zeroed)
2676ac27a0ecSDave Kleikamp {
2677617ba13bSMingming Cao 	struct ext4_sb_info *sbi = EXT4_SB(sb);
2678617ba13bSMingming Cao 	ext4_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block);
2679617ba13bSMingming Cao 	ext4_fsblk_t last_block;
268044de022cSTheodore Ts'o 	ext4_fsblk_t last_bg_block = sb_block + ext4_bg_num_gdb(sb, 0);
2681bd81d8eeSLaurent Vivier 	ext4_fsblk_t block_bitmap;
2682bd81d8eeSLaurent Vivier 	ext4_fsblk_t inode_bitmap;
2683bd81d8eeSLaurent Vivier 	ext4_fsblk_t inode_table;
2684ce421581SJose R. Santos 	int flexbg_flag = 0;
2685bfff6873SLukas Czerner 	ext4_group_t i, grp = sbi->s_groups_count;
2686ac27a0ecSDave Kleikamp 
2687e2b911c5SDarrick J. Wong 	if (ext4_has_feature_flex_bg(sb))
2688ce421581SJose R. Santos 		flexbg_flag = 1;
2689ce421581SJose R. Santos 
2690617ba13bSMingming Cao 	ext4_debug("Checking group descriptors");
2691ac27a0ecSDave Kleikamp 
2692197cd65aSAkinobu Mita 	for (i = 0; i < sbi->s_groups_count; i++) {
2693197cd65aSAkinobu Mita 		struct ext4_group_desc *gdp = ext4_get_group_desc(sb, i, NULL);
2694197cd65aSAkinobu Mita 
2695ce421581SJose R. Santos 		if (i == sbi->s_groups_count - 1 || flexbg_flag)
2696bd81d8eeSLaurent Vivier 			last_block = ext4_blocks_count(sbi->s_es) - 1;
2697ac27a0ecSDave Kleikamp 		else
2698ac27a0ecSDave Kleikamp 			last_block = first_block +
2699617ba13bSMingming Cao 				(EXT4_BLOCKS_PER_GROUP(sb) - 1);
2700ac27a0ecSDave Kleikamp 
2701bfff6873SLukas Czerner 		if ((grp == sbi->s_groups_count) &&
2702bfff6873SLukas Czerner 		   !(gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED)))
2703bfff6873SLukas Czerner 			grp = i;
2704bfff6873SLukas Czerner 
27058fadc143SAlexandre Ratchov 		block_bitmap = ext4_block_bitmap(sb, gdp);
2706829fa70dSTheodore Ts'o 		if (block_bitmap == sb_block) {
2707829fa70dSTheodore Ts'o 			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
2708829fa70dSTheodore Ts'o 				 "Block bitmap for group %u overlaps "
2709829fa70dSTheodore Ts'o 				 "superblock", i);
271018db4b4eSTheodore Ts'o 			if (!sb_rdonly(sb))
271118db4b4eSTheodore Ts'o 				return 0;
2712829fa70dSTheodore Ts'o 		}
271377260807STheodore Ts'o 		if (block_bitmap >= sb_block + 1 &&
271477260807STheodore Ts'o 		    block_bitmap <= last_bg_block) {
271577260807STheodore Ts'o 			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
271677260807STheodore Ts'o 				 "Block bitmap for group %u overlaps "
271777260807STheodore Ts'o 				 "block group descriptors", i);
271877260807STheodore Ts'o 			if (!sb_rdonly(sb))
271977260807STheodore Ts'o 				return 0;
272077260807STheodore Ts'o 		}
27212b2d6d01STheodore Ts'o 		if (block_bitmap < first_block || block_bitmap > last_block) {
2722b31e1552SEric Sandeen 			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
2723a9df9a49STheodore Ts'o 			       "Block bitmap for group %u not in group "
2724b31e1552SEric Sandeen 			       "(block %llu)!", i, block_bitmap);
2725ac27a0ecSDave Kleikamp 			return 0;
2726ac27a0ecSDave Kleikamp 		}
27278fadc143SAlexandre Ratchov 		inode_bitmap = ext4_inode_bitmap(sb, gdp);
2728829fa70dSTheodore Ts'o 		if (inode_bitmap == sb_block) {
2729829fa70dSTheodore Ts'o 			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
2730829fa70dSTheodore Ts'o 				 "Inode bitmap for group %u overlaps "
2731829fa70dSTheodore Ts'o 				 "superblock", i);
273218db4b4eSTheodore Ts'o 			if (!sb_rdonly(sb))
273318db4b4eSTheodore Ts'o 				return 0;
2734829fa70dSTheodore Ts'o 		}
273577260807STheodore Ts'o 		if (inode_bitmap >= sb_block + 1 &&
273677260807STheodore Ts'o 		    inode_bitmap <= last_bg_block) {
273777260807STheodore Ts'o 			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
273877260807STheodore Ts'o 				 "Inode bitmap for group %u overlaps "
273977260807STheodore Ts'o 				 "block group descriptors", i);
274077260807STheodore Ts'o 			if (!sb_rdonly(sb))
274177260807STheodore Ts'o 				return 0;
274277260807STheodore Ts'o 		}
27432b2d6d01STheodore Ts'o 		if (inode_bitmap < first_block || inode_bitmap > last_block) {
2744b31e1552SEric Sandeen 			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
2745a9df9a49STheodore Ts'o 			       "Inode bitmap for group %u not in group "
2746b31e1552SEric Sandeen 			       "(block %llu)!", i, inode_bitmap);
2747ac27a0ecSDave Kleikamp 			return 0;
2748ac27a0ecSDave Kleikamp 		}
27498fadc143SAlexandre Ratchov 		inode_table = ext4_inode_table(sb, gdp);
2750829fa70dSTheodore Ts'o 		if (inode_table == sb_block) {
2751829fa70dSTheodore Ts'o 			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
2752829fa70dSTheodore Ts'o 				 "Inode table for group %u overlaps "
2753829fa70dSTheodore Ts'o 				 "superblock", i);
275418db4b4eSTheodore Ts'o 			if (!sb_rdonly(sb))
275518db4b4eSTheodore Ts'o 				return 0;
2756829fa70dSTheodore Ts'o 		}
275777260807STheodore Ts'o 		if (inode_table >= sb_block + 1 &&
275877260807STheodore Ts'o 		    inode_table <= last_bg_block) {
275977260807STheodore Ts'o 			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
276077260807STheodore Ts'o 				 "Inode table for group %u overlaps "
276177260807STheodore Ts'o 				 "block group descriptors", i);
276277260807STheodore Ts'o 			if (!sb_rdonly(sb))
276377260807STheodore Ts'o 				return 0;
276477260807STheodore Ts'o 		}
2765bd81d8eeSLaurent Vivier 		if (inode_table < first_block ||
27662b2d6d01STheodore Ts'o 		    inode_table + sbi->s_itb_per_group - 1 > last_block) {
2767b31e1552SEric Sandeen 			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
2768a9df9a49STheodore Ts'o 			       "Inode table for group %u not in group "
2769b31e1552SEric Sandeen 			       "(block %llu)!", i, inode_table);
2770ac27a0ecSDave Kleikamp 			return 0;
2771ac27a0ecSDave Kleikamp 		}
2772955ce5f5SAneesh Kumar K.V 		ext4_lock_group(sb, i);
2773feb0ab32SDarrick J. Wong 		if (!ext4_group_desc_csum_verify(sb, i, gdp)) {
2774b31e1552SEric Sandeen 			ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
2775b31e1552SEric Sandeen 				 "Checksum for group %u failed (%u!=%u)",
2776e2b911c5SDarrick J. Wong 				 i, le16_to_cpu(ext4_group_desc_csum(sb, i,
2777fd2d4291SAvantika Mathur 				     gdp)), le16_to_cpu(gdp->bg_checksum));
2778bc98a42cSDavid Howells 			if (!sb_rdonly(sb)) {
2779955ce5f5SAneesh Kumar K.V 				ext4_unlock_group(sb, i);
2780717d50e4SAndreas Dilger 				return 0;
2781717d50e4SAndreas Dilger 			}
27827ee1ec4cSLi Zefan 		}
2783955ce5f5SAneesh Kumar K.V 		ext4_unlock_group(sb, i);
2784ce421581SJose R. Santos 		if (!flexbg_flag)
2785617ba13bSMingming Cao 			first_block += EXT4_BLOCKS_PER_GROUP(sb);
2786ac27a0ecSDave Kleikamp 	}
2787bfff6873SLukas Czerner 	if (NULL != first_not_zeroed)
2788bfff6873SLukas Czerner 		*first_not_zeroed = grp;
2789ac27a0ecSDave Kleikamp 	return 1;
2790ac27a0ecSDave Kleikamp }
2791ac27a0ecSDave Kleikamp 
2792617ba13bSMingming Cao /* ext4_orphan_cleanup() walks a singly-linked list of inodes (starting at
2793ac27a0ecSDave Kleikamp  * the superblock) which were deleted from all directories, but held open by
2794ac27a0ecSDave Kleikamp  * a process at the time of a crash.  We walk the list and try to delete these
2795ac27a0ecSDave Kleikamp  * inodes at recovery time (only with a read-write filesystem).
2796ac27a0ecSDave Kleikamp  *
2797ac27a0ecSDave Kleikamp  * In order to keep the orphan inode chain consistent during traversal (in
2798ac27a0ecSDave Kleikamp  * case of crash during recovery), we link each inode into the superblock
2799ac27a0ecSDave Kleikamp  * orphan list_head and handle it the same way as an inode deletion during
2800ac27a0ecSDave Kleikamp  * normal operation (which journals the operations for us).
2801ac27a0ecSDave Kleikamp  *
2802ac27a0ecSDave Kleikamp  * We only do an iget() and an iput() on each inode, which is very safe if we
2803ac27a0ecSDave Kleikamp  * accidentally point at an in-use or already deleted inode.  The worst that
2804ac27a0ecSDave Kleikamp  * can happen in this case is that we get a "bit already cleared" message from
2805617ba13bSMingming Cao  * ext4_free_inode().  The only reason we would point at a wrong inode is if
2806ac27a0ecSDave Kleikamp  * e2fsck was run on this filesystem, and it must have already done the orphan
2807ac27a0ecSDave Kleikamp  * inode cleanup for us, so we can safely abort without any further action.
2808ac27a0ecSDave Kleikamp  */
2809617ba13bSMingming Cao static void ext4_orphan_cleanup(struct super_block *sb,
2810617ba13bSMingming Cao 				struct ext4_super_block *es)
2811ac27a0ecSDave Kleikamp {
2812ac27a0ecSDave Kleikamp 	unsigned int s_flags = sb->s_flags;
28132c98eb5eSTheodore Ts'o 	int ret, nr_orphans = 0, nr_truncates = 0;
2814ac27a0ecSDave Kleikamp #ifdef CONFIG_QUOTA
281595f1fda4Szhangyi (F) 	int quota_update = 0;
2816ac27a0ecSDave Kleikamp 	int i;
2817ac27a0ecSDave Kleikamp #endif
2818ac27a0ecSDave Kleikamp 	if (!es->s_last_orphan) {
2819ac27a0ecSDave Kleikamp 		jbd_debug(4, "no orphan inodes to clean up\n");
2820ac27a0ecSDave Kleikamp 		return;
2821ac27a0ecSDave Kleikamp 	}
2822ac27a0ecSDave Kleikamp 
2823a8f48a95SEric Sandeen 	if (bdev_read_only(sb->s_bdev)) {
2824b31e1552SEric Sandeen 		ext4_msg(sb, KERN_ERR, "write access "
2825b31e1552SEric Sandeen 			"unavailable, skipping orphan cleanup");
2826a8f48a95SEric Sandeen 		return;
2827a8f48a95SEric Sandeen 	}
2828a8f48a95SEric Sandeen 
2829d39195c3SAmir Goldstein 	/* Check if feature set would not allow a r/w mount */
2830d39195c3SAmir Goldstein 	if (!ext4_feature_set_ok(sb, 0)) {
2831d39195c3SAmir Goldstein 		ext4_msg(sb, KERN_INFO, "Skipping orphan cleanup due to "
2832d39195c3SAmir Goldstein 			 "unknown ROCOMPAT features");
2833d39195c3SAmir Goldstein 		return;
2834d39195c3SAmir Goldstein 	}
2835d39195c3SAmir Goldstein 
2836617ba13bSMingming Cao 	if (EXT4_SB(sb)->s_mount_state & EXT4_ERROR_FS) {
2837c25f9bc6SEric Sandeen 		/* don't clear list on RO mount w/ errors */
28381751e8a6SLinus Torvalds 		if (es->s_last_orphan && !(s_flags & SB_RDONLY)) {
283984474976SDmitry Monakhov 			ext4_msg(sb, KERN_INFO, "Errors on filesystem, "
2840ac27a0ecSDave Kleikamp 				  "clearing orphan list.\n");
2841ac27a0ecSDave Kleikamp 			es->s_last_orphan = 0;
2842c25f9bc6SEric Sandeen 		}
2843ac27a0ecSDave Kleikamp 		jbd_debug(1, "Skipping orphan recovery on fs with errors.\n");
2844ac27a0ecSDave Kleikamp 		return;
2845ac27a0ecSDave Kleikamp 	}
2846ac27a0ecSDave Kleikamp 
28471751e8a6SLinus Torvalds 	if (s_flags & SB_RDONLY) {
2848b31e1552SEric Sandeen 		ext4_msg(sb, KERN_INFO, "orphan cleanup on readonly fs");
28491751e8a6SLinus Torvalds 		sb->s_flags &= ~SB_RDONLY;
2850ac27a0ecSDave Kleikamp 	}
2851ac27a0ecSDave Kleikamp #ifdef CONFIG_QUOTA
2852ac27a0ecSDave Kleikamp 	/* Needed for iput() to work correctly and not trash data */
28531751e8a6SLinus Torvalds 	sb->s_flags |= SB_ACTIVE;
285495f1fda4Szhangyi (F) 
285595f1fda4Szhangyi (F) 	/*
285695f1fda4Szhangyi (F) 	 * Turn on quotas which were not enabled for read-only mounts if
285795f1fda4Szhangyi (F) 	 * filesystem has quota feature, so that they are updated correctly.
285895f1fda4Szhangyi (F) 	 */
28591751e8a6SLinus Torvalds 	if (ext4_has_feature_quota(sb) && (s_flags & SB_RDONLY)) {
286095f1fda4Szhangyi (F) 		int ret = ext4_enable_quotas(sb);
286195f1fda4Szhangyi (F) 
286295f1fda4Szhangyi (F) 		if (!ret)
286395f1fda4Szhangyi (F) 			quota_update = 1;
286495f1fda4Szhangyi (F) 		else
286595f1fda4Szhangyi (F) 			ext4_msg(sb, KERN_ERR,
286695f1fda4Szhangyi (F) 				"Cannot turn on quotas: error %d", ret);
286795f1fda4Szhangyi (F) 	}
286895f1fda4Szhangyi (F) 
286995f1fda4Szhangyi (F) 	/* Turn on journaled quotas used for old sytle */
2870a2d4a646SJan Kara 	for (i = 0; i < EXT4_MAXQUOTAS; i++) {
2871617ba13bSMingming Cao 		if (EXT4_SB(sb)->s_qf_names[i]) {
2872617ba13bSMingming Cao 			int ret = ext4_quota_on_mount(sb, i);
287395f1fda4Szhangyi (F) 
287495f1fda4Szhangyi (F) 			if (!ret)
287595f1fda4Szhangyi (F) 				quota_update = 1;
287695f1fda4Szhangyi (F) 			else
2877b31e1552SEric Sandeen 				ext4_msg(sb, KERN_ERR,
2878b31e1552SEric Sandeen 					"Cannot turn on journaled "
287995f1fda4Szhangyi (F) 					"quota: type %d: error %d", i, ret);
2880ac27a0ecSDave Kleikamp 		}
2881ac27a0ecSDave Kleikamp 	}
2882ac27a0ecSDave Kleikamp #endif
2883ac27a0ecSDave Kleikamp 
2884ac27a0ecSDave Kleikamp 	while (es->s_last_orphan) {
2885ac27a0ecSDave Kleikamp 		struct inode *inode;
2886ac27a0ecSDave Kleikamp 
2887c65d5c6cSVegard Nossum 		/*
2888c65d5c6cSVegard Nossum 		 * We may have encountered an error during cleanup; if
2889c65d5c6cSVegard Nossum 		 * so, skip the rest.
2890c65d5c6cSVegard Nossum 		 */
2891c65d5c6cSVegard Nossum 		if (EXT4_SB(sb)->s_mount_state & EXT4_ERROR_FS) {
2892c65d5c6cSVegard Nossum 			jbd_debug(1, "Skipping orphan recovery on fs with errors.\n");
2893c65d5c6cSVegard Nossum 			es->s_last_orphan = 0;
2894c65d5c6cSVegard Nossum 			break;
2895c65d5c6cSVegard Nossum 		}
2896c65d5c6cSVegard Nossum 
289797bd42b9SJosef Bacik 		inode = ext4_orphan_get(sb, le32_to_cpu(es->s_last_orphan));
289897bd42b9SJosef Bacik 		if (IS_ERR(inode)) {
2899ac27a0ecSDave Kleikamp 			es->s_last_orphan = 0;
2900ac27a0ecSDave Kleikamp 			break;
2901ac27a0ecSDave Kleikamp 		}
2902ac27a0ecSDave Kleikamp 
2903617ba13bSMingming Cao 		list_add(&EXT4_I(inode)->i_orphan, &EXT4_SB(sb)->s_orphan);
2904871a2931SChristoph Hellwig 		dquot_initialize(inode);
2905ac27a0ecSDave Kleikamp 		if (inode->i_nlink) {
2906566370a2SPaul Taysom 			if (test_opt(sb, DEBUG))
2907b31e1552SEric Sandeen 				ext4_msg(sb, KERN_DEBUG,
2908b31e1552SEric Sandeen 					"%s: truncating inode %lu to %lld bytes",
290946e665e9SHarvey Harrison 					__func__, inode->i_ino, inode->i_size);
2910e5f8eab8STheodore Ts'o 			jbd_debug(2, "truncating inode %lu to %lld bytes\n",
2911ac27a0ecSDave Kleikamp 				  inode->i_ino, inode->i_size);
29125955102cSAl Viro 			inode_lock(inode);
291355f252c9SLukas Czerner 			truncate_inode_pages(inode->i_mapping, inode->i_size);
29142c98eb5eSTheodore Ts'o 			ret = ext4_truncate(inode);
29152c98eb5eSTheodore Ts'o 			if (ret)
29162c98eb5eSTheodore Ts'o 				ext4_std_error(inode->i_sb, ret);
29175955102cSAl Viro 			inode_unlock(inode);
2918ac27a0ecSDave Kleikamp 			nr_truncates++;
2919ac27a0ecSDave Kleikamp 		} else {
2920566370a2SPaul Taysom 			if (test_opt(sb, DEBUG))
2921b31e1552SEric Sandeen 				ext4_msg(sb, KERN_DEBUG,
2922b31e1552SEric Sandeen 					"%s: deleting unreferenced inode %lu",
292346e665e9SHarvey Harrison 					__func__, inode->i_ino);
2924ac27a0ecSDave Kleikamp 			jbd_debug(2, "deleting unreferenced inode %lu\n",
2925ac27a0ecSDave Kleikamp 				  inode->i_ino);
2926ac27a0ecSDave Kleikamp 			nr_orphans++;
2927ac27a0ecSDave Kleikamp 		}
2928ac27a0ecSDave Kleikamp 		iput(inode);  /* The delete magic happens here! */
2929ac27a0ecSDave Kleikamp 	}
2930ac27a0ecSDave Kleikamp 
2931ac27a0ecSDave Kleikamp #define PLURAL(x) (x), ((x) == 1) ? "" : "s"
2932ac27a0ecSDave Kleikamp 
2933ac27a0ecSDave Kleikamp 	if (nr_orphans)
2934b31e1552SEric Sandeen 		ext4_msg(sb, KERN_INFO, "%d orphan inode%s deleted",
2935b31e1552SEric Sandeen 		       PLURAL(nr_orphans));
2936ac27a0ecSDave Kleikamp 	if (nr_truncates)
2937b31e1552SEric Sandeen 		ext4_msg(sb, KERN_INFO, "%d truncate%s cleaned up",
2938b31e1552SEric Sandeen 		       PLURAL(nr_truncates));
2939ac27a0ecSDave Kleikamp #ifdef CONFIG_QUOTA
294095f1fda4Szhangyi (F) 	/* Turn off quotas if they were enabled for orphan cleanup */
294195f1fda4Szhangyi (F) 	if (quota_update) {
2942a2d4a646SJan Kara 		for (i = 0; i < EXT4_MAXQUOTAS; i++) {
294395f1fda4Szhangyi (F) 			if (sb_dqopt(sb)->files[i])
2944287a8095SChristoph Hellwig 				dquot_quota_off(sb, i);
2945ac27a0ecSDave Kleikamp 		}
294695f1fda4Szhangyi (F) 	}
2947ac27a0ecSDave Kleikamp #endif
29481751e8a6SLinus Torvalds 	sb->s_flags = s_flags; /* Restore SB_RDONLY status */
2949ac27a0ecSDave Kleikamp }
29500b8e58a1SAndreas Dilger 
2951cd2291a4SEric Sandeen /*
2952cd2291a4SEric Sandeen  * Maximal extent format file size.
2953cd2291a4SEric Sandeen  * Resulting logical blkno at s_maxbytes must fit in our on-disk
2954cd2291a4SEric Sandeen  * extent format containers, within a sector_t, and within i_blocks
2955cd2291a4SEric Sandeen  * in the vfs.  ext4 inode has 48 bits of i_block in fsblock units,
2956cd2291a4SEric Sandeen  * so that won't be a limiting factor.
2957cd2291a4SEric Sandeen  *
2958f17722f9SLukas Czerner  * However there is other limiting factor. We do store extents in the form
2959f17722f9SLukas Czerner  * of starting block and length, hence the resulting length of the extent
2960f17722f9SLukas Czerner  * covering maximum file size must fit into on-disk format containers as
2961f17722f9SLukas Czerner  * well. Given that length is always by 1 unit bigger than max unit (because
2962f17722f9SLukas Czerner  * we count 0 as well) we have to lower the s_maxbytes by one fs block.
2963f17722f9SLukas Czerner  *
2964cd2291a4SEric Sandeen  * Note, this does *not* consider any metadata overhead for vfs i_blocks.
2965cd2291a4SEric Sandeen  */
2966f287a1a5STheodore Ts'o static loff_t ext4_max_size(int blkbits, int has_huge_files)
2967cd2291a4SEric Sandeen {
2968cd2291a4SEric Sandeen 	loff_t res;
2969cd2291a4SEric Sandeen 	loff_t upper_limit = MAX_LFS_FILESIZE;
2970cd2291a4SEric Sandeen 
297172deb455SChristoph Hellwig 	BUILD_BUG_ON(sizeof(blkcnt_t) < sizeof(u64));
297272deb455SChristoph Hellwig 
297372deb455SChristoph Hellwig 	if (!has_huge_files) {
2974cd2291a4SEric Sandeen 		upper_limit = (1LL << 32) - 1;
2975cd2291a4SEric Sandeen 
2976cd2291a4SEric Sandeen 		/* total blocks in file system block size */
2977cd2291a4SEric Sandeen 		upper_limit >>= (blkbits - 9);
2978cd2291a4SEric Sandeen 		upper_limit <<= blkbits;
2979cd2291a4SEric Sandeen 	}
2980cd2291a4SEric Sandeen 
2981f17722f9SLukas Czerner 	/*
2982f17722f9SLukas Czerner 	 * 32-bit extent-start container, ee_block. We lower the maxbytes
2983f17722f9SLukas Czerner 	 * by one fs block, so ee_len can cover the extent of maximum file
2984f17722f9SLukas Czerner 	 * size
2985f17722f9SLukas Czerner 	 */
2986f17722f9SLukas Czerner 	res = (1LL << 32) - 1;
2987cd2291a4SEric Sandeen 	res <<= blkbits;
2988cd2291a4SEric Sandeen 
2989cd2291a4SEric Sandeen 	/* Sanity check against vm- & vfs- imposed limits */
2990cd2291a4SEric Sandeen 	if (res > upper_limit)
2991cd2291a4SEric Sandeen 		res = upper_limit;
2992cd2291a4SEric Sandeen 
2993cd2291a4SEric Sandeen 	return res;
2994cd2291a4SEric Sandeen }
2995ac27a0ecSDave Kleikamp 
2996ac27a0ecSDave Kleikamp /*
2997cd2291a4SEric Sandeen  * Maximal bitmap file size.  There is a direct, and {,double-,triple-}indirect
29980fc1b451SAneesh Kumar K.V  * block limit, and also a limit of (2^48 - 1) 512-byte sectors in i_blocks.
29990fc1b451SAneesh Kumar K.V  * We need to be 1 filesystem block less than the 2^48 sector limit.
3000ac27a0ecSDave Kleikamp  */
3001f287a1a5STheodore Ts'o static loff_t ext4_max_bitmap_size(int bits, int has_huge_files)
3002ac27a0ecSDave Kleikamp {
3003617ba13bSMingming Cao 	loff_t res = EXT4_NDIR_BLOCKS;
30040fc1b451SAneesh Kumar K.V 	int meta_blocks;
30050fc1b451SAneesh Kumar K.V 	loff_t upper_limit;
30060b8e58a1SAndreas Dilger 	/* This is calculated to be the largest file size for a dense, block
30070b8e58a1SAndreas Dilger 	 * mapped file such that the file's total number of 512-byte sectors,
30080b8e58a1SAndreas Dilger 	 * including data and all indirect blocks, does not exceed (2^48 - 1).
30090b8e58a1SAndreas Dilger 	 *
30100b8e58a1SAndreas Dilger 	 * __u32 i_blocks_lo and _u16 i_blocks_high represent the total
30110b8e58a1SAndreas Dilger 	 * number of 512-byte sectors of the file.
30120fc1b451SAneesh Kumar K.V 	 */
30130fc1b451SAneesh Kumar K.V 
301472deb455SChristoph Hellwig 	if (!has_huge_files) {
30150fc1b451SAneesh Kumar K.V 		/*
301672deb455SChristoph Hellwig 		 * !has_huge_files or implies that the inode i_block field
301772deb455SChristoph Hellwig 		 * represents total file blocks in 2^32 512-byte sectors ==
301872deb455SChristoph Hellwig 		 * size of vfs inode i_blocks * 8
30190fc1b451SAneesh Kumar K.V 		 */
30200fc1b451SAneesh Kumar K.V 		upper_limit = (1LL << 32) - 1;
30210fc1b451SAneesh Kumar K.V 
30220fc1b451SAneesh Kumar K.V 		/* total blocks in file system block size */
30230fc1b451SAneesh Kumar K.V 		upper_limit >>= (bits - 9);
30240fc1b451SAneesh Kumar K.V 
30250fc1b451SAneesh Kumar K.V 	} else {
30268180a562SAneesh Kumar K.V 		/*
30278180a562SAneesh Kumar K.V 		 * We use 48 bit ext4_inode i_blocks
30288180a562SAneesh Kumar K.V 		 * With EXT4_HUGE_FILE_FL set the i_blocks
30298180a562SAneesh Kumar K.V 		 * represent total number of blocks in
30308180a562SAneesh Kumar K.V 		 * file system block size
30318180a562SAneesh Kumar K.V 		 */
30320fc1b451SAneesh Kumar K.V 		upper_limit = (1LL << 48) - 1;
30330fc1b451SAneesh Kumar K.V 
30340fc1b451SAneesh Kumar K.V 	}
30350fc1b451SAneesh Kumar K.V 
30360fc1b451SAneesh Kumar K.V 	/* indirect blocks */
30370fc1b451SAneesh Kumar K.V 	meta_blocks = 1;
30380fc1b451SAneesh Kumar K.V 	/* double indirect blocks */
30390fc1b451SAneesh Kumar K.V 	meta_blocks += 1 + (1LL << (bits-2));
30400fc1b451SAneesh Kumar K.V 	/* tripple indirect blocks */
30410fc1b451SAneesh Kumar K.V 	meta_blocks += 1 + (1LL << (bits-2)) + (1LL << (2*(bits-2)));
30420fc1b451SAneesh Kumar K.V 
30430fc1b451SAneesh Kumar K.V 	upper_limit -= meta_blocks;
30440fc1b451SAneesh Kumar K.V 	upper_limit <<= bits;
3045ac27a0ecSDave Kleikamp 
3046ac27a0ecSDave Kleikamp 	res += 1LL << (bits-2);
3047ac27a0ecSDave Kleikamp 	res += 1LL << (2*(bits-2));
3048ac27a0ecSDave Kleikamp 	res += 1LL << (3*(bits-2));
3049ac27a0ecSDave Kleikamp 	res <<= bits;
3050ac27a0ecSDave Kleikamp 	if (res > upper_limit)
3051ac27a0ecSDave Kleikamp 		res = upper_limit;
30520fc1b451SAneesh Kumar K.V 
30530fc1b451SAneesh Kumar K.V 	if (res > MAX_LFS_FILESIZE)
30540fc1b451SAneesh Kumar K.V 		res = MAX_LFS_FILESIZE;
30550fc1b451SAneesh Kumar K.V 
3056ac27a0ecSDave Kleikamp 	return res;
3057ac27a0ecSDave Kleikamp }
3058ac27a0ecSDave Kleikamp 
3059617ba13bSMingming Cao static ext4_fsblk_t descriptor_loc(struct super_block *sb,
306070bbb3e0SAndrew Morton 				   ext4_fsblk_t logical_sb_block, int nr)
3061ac27a0ecSDave Kleikamp {
3062617ba13bSMingming Cao 	struct ext4_sb_info *sbi = EXT4_SB(sb);
3063fd2d4291SAvantika Mathur 	ext4_group_t bg, first_meta_bg;
3064ac27a0ecSDave Kleikamp 	int has_super = 0;
3065ac27a0ecSDave Kleikamp 
3066ac27a0ecSDave Kleikamp 	first_meta_bg = le32_to_cpu(sbi->s_es->s_first_meta_bg);
3067ac27a0ecSDave Kleikamp 
3068e2b911c5SDarrick J. Wong 	if (!ext4_has_feature_meta_bg(sb) || nr < first_meta_bg)
306970bbb3e0SAndrew Morton 		return logical_sb_block + nr + 1;
3070ac27a0ecSDave Kleikamp 	bg = sbi->s_desc_per_block * nr;
3071617ba13bSMingming Cao 	if (ext4_bg_has_super(sb, bg))
3072ac27a0ecSDave Kleikamp 		has_super = 1;
30730b8e58a1SAndreas Dilger 
3074bd63f6b0SDarrick J. Wong 	/*
3075bd63f6b0SDarrick J. Wong 	 * If we have a meta_bg fs with 1k blocks, group 0's GDT is at
3076bd63f6b0SDarrick J. Wong 	 * block 2, not 1.  If s_first_data_block == 0 (bigalloc is enabled
3077bd63f6b0SDarrick J. Wong 	 * on modern mke2fs or blksize > 1k on older mke2fs) then we must
3078bd63f6b0SDarrick J. Wong 	 * compensate.
3079bd63f6b0SDarrick J. Wong 	 */
3080bd63f6b0SDarrick J. Wong 	if (sb->s_blocksize == 1024 && nr == 0 &&
308149598e04SJun Piao 	    le32_to_cpu(sbi->s_es->s_first_data_block) == 0)
3082bd63f6b0SDarrick J. Wong 		has_super++;
3083bd63f6b0SDarrick J. Wong 
3084617ba13bSMingming Cao 	return (has_super + ext4_group_first_block_no(sb, bg));
3085ac27a0ecSDave Kleikamp }
3086ac27a0ecSDave Kleikamp 
3087c9de560dSAlex Tomas /**
3088c9de560dSAlex Tomas  * ext4_get_stripe_size: Get the stripe size.
3089c9de560dSAlex Tomas  * @sbi: In memory super block info
3090c9de560dSAlex Tomas  *
3091c9de560dSAlex Tomas  * If we have specified it via mount option, then
3092c9de560dSAlex Tomas  * use the mount option value. If the value specified at mount time is
3093c9de560dSAlex Tomas  * greater than the blocks per group use the super block value.
3094c9de560dSAlex Tomas  * If the super block value is greater than blocks per group return 0.
3095c9de560dSAlex Tomas  * Allocator needs it be less than blocks per group.
3096c9de560dSAlex Tomas  *
3097c9de560dSAlex Tomas  */
3098c9de560dSAlex Tomas static unsigned long ext4_get_stripe_size(struct ext4_sb_info *sbi)
3099c9de560dSAlex Tomas {
3100c9de560dSAlex Tomas 	unsigned long stride = le16_to_cpu(sbi->s_es->s_raid_stride);
3101c9de560dSAlex Tomas 	unsigned long stripe_width =
3102c9de560dSAlex Tomas 			le32_to_cpu(sbi->s_es->s_raid_stripe_width);
31033eb08658SDan Ehrenberg 	int ret;
3104c9de560dSAlex Tomas 
3105c9de560dSAlex Tomas 	if (sbi->s_stripe && sbi->s_stripe <= sbi->s_blocks_per_group)
31063eb08658SDan Ehrenberg 		ret = sbi->s_stripe;
31075469d7c3SJan Kara 	else if (stripe_width && stripe_width <= sbi->s_blocks_per_group)
31083eb08658SDan Ehrenberg 		ret = stripe_width;
31095469d7c3SJan Kara 	else if (stride && stride <= sbi->s_blocks_per_group)
31103eb08658SDan Ehrenberg 		ret = stride;
31113eb08658SDan Ehrenberg 	else
31123eb08658SDan Ehrenberg 		ret = 0;
3113c9de560dSAlex Tomas 
31143eb08658SDan Ehrenberg 	/*
31153eb08658SDan Ehrenberg 	 * If the stripe width is 1, this makes no sense and
31163eb08658SDan Ehrenberg 	 * we set it to 0 to turn off stripe handling code.
31173eb08658SDan Ehrenberg 	 */
31183eb08658SDan Ehrenberg 	if (ret <= 1)
31193eb08658SDan Ehrenberg 		ret = 0;
3120c9de560dSAlex Tomas 
31213eb08658SDan Ehrenberg 	return ret;
3122c9de560dSAlex Tomas }
3123ac27a0ecSDave Kleikamp 
3124a13fb1a4SEric Sandeen /*
3125a13fb1a4SEric Sandeen  * Check whether this filesystem can be mounted based on
3126a13fb1a4SEric Sandeen  * the features present and the RDONLY/RDWR mount requested.
3127a13fb1a4SEric Sandeen  * Returns 1 if this filesystem can be mounted as requested,
3128a13fb1a4SEric Sandeen  * 0 if it cannot be.
3129a13fb1a4SEric Sandeen  */
3130a13fb1a4SEric Sandeen static int ext4_feature_set_ok(struct super_block *sb, int readonly)
3131a13fb1a4SEric Sandeen {
3132e2b911c5SDarrick J. Wong 	if (ext4_has_unknown_ext4_incompat_features(sb)) {
3133a13fb1a4SEric Sandeen 		ext4_msg(sb, KERN_ERR,
3134a13fb1a4SEric Sandeen 			"Couldn't mount because of "
3135a13fb1a4SEric Sandeen 			"unsupported optional features (%x)",
3136a13fb1a4SEric Sandeen 			(le32_to_cpu(EXT4_SB(sb)->s_es->s_feature_incompat) &
3137a13fb1a4SEric Sandeen 			~EXT4_FEATURE_INCOMPAT_SUPP));
3138a13fb1a4SEric Sandeen 		return 0;
3139a13fb1a4SEric Sandeen 	}
3140a13fb1a4SEric Sandeen 
3141c83ad55eSGabriel Krisman Bertazi #ifndef CONFIG_UNICODE
3142c83ad55eSGabriel Krisman Bertazi 	if (ext4_has_feature_casefold(sb)) {
3143c83ad55eSGabriel Krisman Bertazi 		ext4_msg(sb, KERN_ERR,
3144c83ad55eSGabriel Krisman Bertazi 			 "Filesystem with casefold feature cannot be "
3145c83ad55eSGabriel Krisman Bertazi 			 "mounted without CONFIG_UNICODE");
3146c83ad55eSGabriel Krisman Bertazi 		return 0;
3147c83ad55eSGabriel Krisman Bertazi 	}
3148c83ad55eSGabriel Krisman Bertazi #endif
3149c83ad55eSGabriel Krisman Bertazi 
3150a13fb1a4SEric Sandeen 	if (readonly)
3151a13fb1a4SEric Sandeen 		return 1;
3152a13fb1a4SEric Sandeen 
3153e2b911c5SDarrick J. Wong 	if (ext4_has_feature_readonly(sb)) {
31542cb5cc8bSDarrick J. Wong 		ext4_msg(sb, KERN_INFO, "filesystem is read-only");
31551751e8a6SLinus Torvalds 		sb->s_flags |= SB_RDONLY;
31562cb5cc8bSDarrick J. Wong 		return 1;
31572cb5cc8bSDarrick J. Wong 	}
31582cb5cc8bSDarrick J. Wong 
3159a13fb1a4SEric Sandeen 	/* Check that feature set is OK for a read-write mount */
3160e2b911c5SDarrick J. Wong 	if (ext4_has_unknown_ext4_ro_compat_features(sb)) {
3161a13fb1a4SEric Sandeen 		ext4_msg(sb, KERN_ERR, "couldn't mount RDWR because of "
3162a13fb1a4SEric Sandeen 			 "unsupported optional features (%x)",
3163a13fb1a4SEric Sandeen 			 (le32_to_cpu(EXT4_SB(sb)->s_es->s_feature_ro_compat) &
3164a13fb1a4SEric Sandeen 				~EXT4_FEATURE_RO_COMPAT_SUPP));
3165a13fb1a4SEric Sandeen 		return 0;
3166a13fb1a4SEric Sandeen 	}
3167e2b911c5SDarrick J. Wong 	if (ext4_has_feature_bigalloc(sb) && !ext4_has_feature_extents(sb)) {
3168bab08ab9STheodore Ts'o 		ext4_msg(sb, KERN_ERR,
3169bab08ab9STheodore Ts'o 			 "Can't support bigalloc feature without "
3170bab08ab9STheodore Ts'o 			 "extents feature\n");
3171bab08ab9STheodore Ts'o 		return 0;
3172bab08ab9STheodore Ts'o 	}
31737c319d32SAditya Kali 
31749db176bcSJan Kara #if !IS_ENABLED(CONFIG_QUOTA) || !IS_ENABLED(CONFIG_QFMT_V2)
3175d65d87a0STheodore Ts'o 	if (!readonly && (ext4_has_feature_quota(sb) ||
3176d65d87a0STheodore Ts'o 			  ext4_has_feature_project(sb))) {
31777c319d32SAditya Kali 		ext4_msg(sb, KERN_ERR,
3178d65d87a0STheodore Ts'o 			 "The kernel was not built with CONFIG_QUOTA and CONFIG_QFMT_V2");
3179689c958cSLi Xi 		return 0;
3180689c958cSLi Xi 	}
31817c319d32SAditya Kali #endif  /* CONFIG_QUOTA */
3182a13fb1a4SEric Sandeen 	return 1;
3183a13fb1a4SEric Sandeen }
3184a13fb1a4SEric Sandeen 
318566e61a9eSTheodore Ts'o /*
318666e61a9eSTheodore Ts'o  * This function is called once a day if we have errors logged
318766e61a9eSTheodore Ts'o  * on the file system
318866e61a9eSTheodore Ts'o  */
3189235699a8SKees Cook static void print_daily_error_info(struct timer_list *t)
319066e61a9eSTheodore Ts'o {
3191235699a8SKees Cook 	struct ext4_sb_info *sbi = from_timer(sbi, t, s_err_report);
3192235699a8SKees Cook 	struct super_block *sb = sbi->s_sb;
3193235699a8SKees Cook 	struct ext4_super_block *es = sbi->s_es;
319466e61a9eSTheodore Ts'o 
319566e61a9eSTheodore Ts'o 	if (es->s_error_count)
3196ae0f78deSTheodore Ts'o 		/* fsck newer than v1.41.13 is needed to clean this condition. */
3197ae0f78deSTheodore Ts'o 		ext4_msg(sb, KERN_NOTICE, "error count since last fsck: %u",
319866e61a9eSTheodore Ts'o 			 le32_to_cpu(es->s_error_count));
319966e61a9eSTheodore Ts'o 	if (es->s_first_error_time) {
32006a0678a7SArnd Bergmann 		printk(KERN_NOTICE "EXT4-fs (%s): initial error at time %llu: %.*s:%d",
32016a0678a7SArnd Bergmann 		       sb->s_id,
32026a0678a7SArnd Bergmann 		       ext4_get_tstamp(es, s_first_error_time),
320366e61a9eSTheodore Ts'o 		       (int) sizeof(es->s_first_error_func),
320466e61a9eSTheodore Ts'o 		       es->s_first_error_func,
320566e61a9eSTheodore Ts'o 		       le32_to_cpu(es->s_first_error_line));
320666e61a9eSTheodore Ts'o 		if (es->s_first_error_ino)
3207651e1c3bSJoe Perches 			printk(KERN_CONT ": inode %u",
320866e61a9eSTheodore Ts'o 			       le32_to_cpu(es->s_first_error_ino));
320966e61a9eSTheodore Ts'o 		if (es->s_first_error_block)
3210651e1c3bSJoe Perches 			printk(KERN_CONT ": block %llu", (unsigned long long)
321166e61a9eSTheodore Ts'o 			       le64_to_cpu(es->s_first_error_block));
3212651e1c3bSJoe Perches 		printk(KERN_CONT "\n");
321366e61a9eSTheodore Ts'o 	}
321466e61a9eSTheodore Ts'o 	if (es->s_last_error_time) {
32156a0678a7SArnd Bergmann 		printk(KERN_NOTICE "EXT4-fs (%s): last error at time %llu: %.*s:%d",
32166a0678a7SArnd Bergmann 		       sb->s_id,
32176a0678a7SArnd Bergmann 		       ext4_get_tstamp(es, s_last_error_time),
321866e61a9eSTheodore Ts'o 		       (int) sizeof(es->s_last_error_func),
321966e61a9eSTheodore Ts'o 		       es->s_last_error_func,
322066e61a9eSTheodore Ts'o 		       le32_to_cpu(es->s_last_error_line));
322166e61a9eSTheodore Ts'o 		if (es->s_last_error_ino)
3222651e1c3bSJoe Perches 			printk(KERN_CONT ": inode %u",
322366e61a9eSTheodore Ts'o 			       le32_to_cpu(es->s_last_error_ino));
322466e61a9eSTheodore Ts'o 		if (es->s_last_error_block)
3225651e1c3bSJoe Perches 			printk(KERN_CONT ": block %llu", (unsigned long long)
322666e61a9eSTheodore Ts'o 			       le64_to_cpu(es->s_last_error_block));
3227651e1c3bSJoe Perches 		printk(KERN_CONT "\n");
322866e61a9eSTheodore Ts'o 	}
322966e61a9eSTheodore Ts'o 	mod_timer(&sbi->s_err_report, jiffies + 24*60*60*HZ);  /* Once a day */
323066e61a9eSTheodore Ts'o }
323166e61a9eSTheodore Ts'o 
3232bfff6873SLukas Czerner /* Find next suitable group and run ext4_init_inode_table */
3233bfff6873SLukas Czerner static int ext4_run_li_request(struct ext4_li_request *elr)
3234bfff6873SLukas Czerner {
3235bfff6873SLukas Czerner 	struct ext4_group_desc *gdp = NULL;
32363d392b26STheodore Ts'o 	struct super_block *sb = elr->lr_super;
32373d392b26STheodore Ts'o 	ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count;
32383d392b26STheodore Ts'o 	ext4_group_t group = elr->lr_next_group;
3239bfff6873SLukas Czerner 	unsigned long timeout = 0;
32403d392b26STheodore Ts'o 	unsigned int prefetch_ios = 0;
3241bfff6873SLukas Czerner 	int ret = 0;
3242bfff6873SLukas Czerner 
32433d392b26STheodore Ts'o 	if (elr->lr_mode == EXT4_LI_MODE_PREFETCH_BBITMAP) {
32443d392b26STheodore Ts'o 		elr->lr_next_group = ext4_mb_prefetch(sb, group,
32453d392b26STheodore Ts'o 				EXT4_SB(sb)->s_mb_prefetch, &prefetch_ios);
32463d392b26STheodore Ts'o 		if (prefetch_ios)
32473d392b26STheodore Ts'o 			ext4_mb_prefetch_fini(sb, elr->lr_next_group,
32483d392b26STheodore Ts'o 					      prefetch_ios);
32493d392b26STheodore Ts'o 		trace_ext4_prefetch_bitmaps(sb, group, elr->lr_next_group,
32503d392b26STheodore Ts'o 					    prefetch_ios);
32513d392b26STheodore Ts'o 		if (group >= elr->lr_next_group) {
32523d392b26STheodore Ts'o 			ret = 1;
32533d392b26STheodore Ts'o 			if (elr->lr_first_not_zeroed != ngroups &&
32543d392b26STheodore Ts'o 			    !sb_rdonly(sb) && test_opt(sb, INIT_INODE_TABLE)) {
32553d392b26STheodore Ts'o 				elr->lr_next_group = elr->lr_first_not_zeroed;
32563d392b26STheodore Ts'o 				elr->lr_mode = EXT4_LI_MODE_ITABLE;
32573d392b26STheodore Ts'o 				ret = 0;
32583d392b26STheodore Ts'o 			}
32593d392b26STheodore Ts'o 		}
32603d392b26STheodore Ts'o 		return ret;
32613d392b26STheodore Ts'o 	}
3262bfff6873SLukas Czerner 
32633d392b26STheodore Ts'o 	for (; group < ngroups; group++) {
3264bfff6873SLukas Czerner 		gdp = ext4_get_group_desc(sb, group, NULL);
3265bfff6873SLukas Czerner 		if (!gdp) {
3266bfff6873SLukas Czerner 			ret = 1;
3267bfff6873SLukas Czerner 			break;
3268bfff6873SLukas Czerner 		}
3269bfff6873SLukas Czerner 
3270bfff6873SLukas Czerner 		if (!(gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED)))
3271bfff6873SLukas Czerner 			break;
3272bfff6873SLukas Czerner 	}
3273bfff6873SLukas Czerner 
32747f511862STheodore Ts'o 	if (group >= ngroups)
3275bfff6873SLukas Czerner 		ret = 1;
3276bfff6873SLukas Czerner 
3277bfff6873SLukas Czerner 	if (!ret) {
3278bfff6873SLukas Czerner 		timeout = jiffies;
3279bfff6873SLukas Czerner 		ret = ext4_init_inode_table(sb, group,
3280bfff6873SLukas Czerner 					    elr->lr_timeout ? 0 : 1);
32813d392b26STheodore Ts'o 		trace_ext4_lazy_itable_init(sb, group);
3282bfff6873SLukas Czerner 		if (elr->lr_timeout == 0) {
328351ce6511SLukas Czerner 			timeout = (jiffies - timeout) *
32843d392b26STheodore Ts'o 				EXT4_SB(elr->lr_super)->s_li_wait_mult;
3285bfff6873SLukas Czerner 			elr->lr_timeout = timeout;
3286bfff6873SLukas Czerner 		}
3287bfff6873SLukas Czerner 		elr->lr_next_sched = jiffies + elr->lr_timeout;
3288bfff6873SLukas Czerner 		elr->lr_next_group = group + 1;
3289bfff6873SLukas Czerner 	}
3290bfff6873SLukas Czerner 	return ret;
3291bfff6873SLukas Czerner }
3292bfff6873SLukas Czerner 
3293bfff6873SLukas Czerner /*
3294bfff6873SLukas Czerner  * Remove lr_request from the list_request and free the
32954ed5c033SLukas Czerner  * request structure. Should be called with li_list_mtx held
3296bfff6873SLukas Czerner  */
3297bfff6873SLukas Czerner static void ext4_remove_li_request(struct ext4_li_request *elr)
3298bfff6873SLukas Czerner {
3299bfff6873SLukas Czerner 	if (!elr)
3300bfff6873SLukas Czerner 		return;
3301bfff6873SLukas Czerner 
3302bfff6873SLukas Czerner 	list_del(&elr->lr_request);
33033d392b26STheodore Ts'o 	EXT4_SB(elr->lr_super)->s_li_request = NULL;
3304bfff6873SLukas Czerner 	kfree(elr);
3305bfff6873SLukas Czerner }
3306bfff6873SLukas Czerner 
3307bfff6873SLukas Czerner static void ext4_unregister_li_request(struct super_block *sb)
3308bfff6873SLukas Czerner {
33091bb933fbSLukas Czerner 	mutex_lock(&ext4_li_mtx);
33101bb933fbSLukas Czerner 	if (!ext4_li_info) {
33111bb933fbSLukas Czerner 		mutex_unlock(&ext4_li_mtx);
3312bfff6873SLukas Czerner 		return;
33131bb933fbSLukas Czerner 	}
3314bfff6873SLukas Czerner 
3315bfff6873SLukas Czerner 	mutex_lock(&ext4_li_info->li_list_mtx);
33161bb933fbSLukas Czerner 	ext4_remove_li_request(EXT4_SB(sb)->s_li_request);
3317bfff6873SLukas Czerner 	mutex_unlock(&ext4_li_info->li_list_mtx);
33181bb933fbSLukas Czerner 	mutex_unlock(&ext4_li_mtx);
3319bfff6873SLukas Czerner }
3320bfff6873SLukas Czerner 
33218f1f7453SEric Sandeen static struct task_struct *ext4_lazyinit_task;
33228f1f7453SEric Sandeen 
3323bfff6873SLukas Czerner /*
3324bfff6873SLukas Czerner  * This is the function where ext4lazyinit thread lives. It walks
3325bfff6873SLukas Czerner  * through the request list searching for next scheduled filesystem.
3326bfff6873SLukas Czerner  * When such a fs is found, run the lazy initialization request
3327bfff6873SLukas Czerner  * (ext4_rn_li_request) and keep track of the time spend in this
3328bfff6873SLukas Czerner  * function. Based on that time we compute next schedule time of
3329bfff6873SLukas Czerner  * the request. When walking through the list is complete, compute
3330bfff6873SLukas Czerner  * next waking time and put itself into sleep.
3331bfff6873SLukas Czerner  */
3332bfff6873SLukas Czerner static int ext4_lazyinit_thread(void *arg)
3333bfff6873SLukas Czerner {
3334bfff6873SLukas Czerner 	struct ext4_lazy_init *eli = (struct ext4_lazy_init *)arg;
3335bfff6873SLukas Czerner 	struct list_head *pos, *n;
3336bfff6873SLukas Czerner 	struct ext4_li_request *elr;
33374ed5c033SLukas Czerner 	unsigned long next_wakeup, cur;
3338bfff6873SLukas Czerner 
3339bfff6873SLukas Czerner 	BUG_ON(NULL == eli);
3340bfff6873SLukas Czerner 
3341bfff6873SLukas Czerner cont_thread:
3342bfff6873SLukas Czerner 	while (true) {
3343bfff6873SLukas Czerner 		next_wakeup = MAX_JIFFY_OFFSET;
3344bfff6873SLukas Czerner 
3345bfff6873SLukas Czerner 		mutex_lock(&eli->li_list_mtx);
3346bfff6873SLukas Czerner 		if (list_empty(&eli->li_request_list)) {
3347bfff6873SLukas Czerner 			mutex_unlock(&eli->li_list_mtx);
3348bfff6873SLukas Czerner 			goto exit_thread;
3349bfff6873SLukas Czerner 		}
3350bfff6873SLukas Czerner 		list_for_each_safe(pos, n, &eli->li_request_list) {
3351e22834f0SDmitry Monakhov 			int err = 0;
3352e22834f0SDmitry Monakhov 			int progress = 0;
3353bfff6873SLukas Czerner 			elr = list_entry(pos, struct ext4_li_request,
3354bfff6873SLukas Czerner 					 lr_request);
3355bfff6873SLukas Czerner 
3356e22834f0SDmitry Monakhov 			if (time_before(jiffies, elr->lr_next_sched)) {
3357e22834f0SDmitry Monakhov 				if (time_before(elr->lr_next_sched, next_wakeup))
3358e22834f0SDmitry Monakhov 					next_wakeup = elr->lr_next_sched;
3359e22834f0SDmitry Monakhov 				continue;
3360e22834f0SDmitry Monakhov 			}
3361e22834f0SDmitry Monakhov 			if (down_read_trylock(&elr->lr_super->s_umount)) {
3362e22834f0SDmitry Monakhov 				if (sb_start_write_trylock(elr->lr_super)) {
3363e22834f0SDmitry Monakhov 					progress = 1;
3364e22834f0SDmitry Monakhov 					/*
3365e22834f0SDmitry Monakhov 					 * We hold sb->s_umount, sb can not
3366e22834f0SDmitry Monakhov 					 * be removed from the list, it is
3367e22834f0SDmitry Monakhov 					 * now safe to drop li_list_mtx
3368e22834f0SDmitry Monakhov 					 */
3369e22834f0SDmitry Monakhov 					mutex_unlock(&eli->li_list_mtx);
3370e22834f0SDmitry Monakhov 					err = ext4_run_li_request(elr);
3371e22834f0SDmitry Monakhov 					sb_end_write(elr->lr_super);
3372e22834f0SDmitry Monakhov 					mutex_lock(&eli->li_list_mtx);
3373e22834f0SDmitry Monakhov 					n = pos->next;
3374e22834f0SDmitry Monakhov 				}
3375e22834f0SDmitry Monakhov 				up_read((&elr->lr_super->s_umount));
3376e22834f0SDmitry Monakhov 			}
3377b2c78cd0STheodore Ts'o 			/* error, remove the lazy_init job */
3378e22834f0SDmitry Monakhov 			if (err) {
3379bfff6873SLukas Czerner 				ext4_remove_li_request(elr);
3380bfff6873SLukas Czerner 				continue;
3381bfff6873SLukas Czerner 			}
3382e22834f0SDmitry Monakhov 			if (!progress) {
3383e22834f0SDmitry Monakhov 				elr->lr_next_sched = jiffies +
3384e22834f0SDmitry Monakhov 					(prandom_u32()
3385e22834f0SDmitry Monakhov 					 % (EXT4_DEF_LI_MAX_START_DELAY * HZ));
3386b2c78cd0STheodore Ts'o 			}
3387bfff6873SLukas Czerner 			if (time_before(elr->lr_next_sched, next_wakeup))
3388bfff6873SLukas Czerner 				next_wakeup = elr->lr_next_sched;
3389bfff6873SLukas Czerner 		}
3390bfff6873SLukas Czerner 		mutex_unlock(&eli->li_list_mtx);
3391bfff6873SLukas Czerner 
3392a0acae0eSTejun Heo 		try_to_freeze();
3393bfff6873SLukas Czerner 
33944ed5c033SLukas Czerner 		cur = jiffies;
33954ed5c033SLukas Czerner 		if ((time_after_eq(cur, next_wakeup)) ||
3396f4245bd4SLukas Czerner 		    (MAX_JIFFY_OFFSET == next_wakeup)) {
3397bfff6873SLukas Czerner 			cond_resched();
3398bfff6873SLukas Czerner 			continue;
3399bfff6873SLukas Czerner 		}
3400bfff6873SLukas Czerner 
34014ed5c033SLukas Czerner 		schedule_timeout_interruptible(next_wakeup - cur);
34024ed5c033SLukas Czerner 
34038f1f7453SEric Sandeen 		if (kthread_should_stop()) {
34048f1f7453SEric Sandeen 			ext4_clear_request_list();
34058f1f7453SEric Sandeen 			goto exit_thread;
34068f1f7453SEric Sandeen 		}
3407bfff6873SLukas Czerner 	}
3408bfff6873SLukas Czerner 
3409bfff6873SLukas Czerner exit_thread:
3410bfff6873SLukas Czerner 	/*
3411bfff6873SLukas Czerner 	 * It looks like the request list is empty, but we need
3412bfff6873SLukas Czerner 	 * to check it under the li_list_mtx lock, to prevent any
3413bfff6873SLukas Czerner 	 * additions into it, and of course we should lock ext4_li_mtx
3414bfff6873SLukas Czerner 	 * to atomically free the list and ext4_li_info, because at
3415bfff6873SLukas Czerner 	 * this point another ext4 filesystem could be registering
3416bfff6873SLukas Czerner 	 * new one.
3417bfff6873SLukas Czerner 	 */
3418bfff6873SLukas Czerner 	mutex_lock(&ext4_li_mtx);
3419bfff6873SLukas Czerner 	mutex_lock(&eli->li_list_mtx);
3420bfff6873SLukas Czerner 	if (!list_empty(&eli->li_request_list)) {
3421bfff6873SLukas Czerner 		mutex_unlock(&eli->li_list_mtx);
3422bfff6873SLukas Czerner 		mutex_unlock(&ext4_li_mtx);
3423bfff6873SLukas Czerner 		goto cont_thread;
3424bfff6873SLukas Czerner 	}
3425bfff6873SLukas Czerner 	mutex_unlock(&eli->li_list_mtx);
3426bfff6873SLukas Czerner 	kfree(ext4_li_info);
3427bfff6873SLukas Czerner 	ext4_li_info = NULL;
3428bfff6873SLukas Czerner 	mutex_unlock(&ext4_li_mtx);
3429bfff6873SLukas Czerner 
3430bfff6873SLukas Czerner 	return 0;
3431bfff6873SLukas Czerner }
3432bfff6873SLukas Czerner 
3433bfff6873SLukas Czerner static void ext4_clear_request_list(void)
3434bfff6873SLukas Czerner {
3435bfff6873SLukas Czerner 	struct list_head *pos, *n;
3436bfff6873SLukas Czerner 	struct ext4_li_request *elr;
3437bfff6873SLukas Czerner 
3438bfff6873SLukas Czerner 	mutex_lock(&ext4_li_info->li_list_mtx);
3439bfff6873SLukas Czerner 	list_for_each_safe(pos, n, &ext4_li_info->li_request_list) {
3440bfff6873SLukas Czerner 		elr = list_entry(pos, struct ext4_li_request,
3441bfff6873SLukas Czerner 				 lr_request);
3442bfff6873SLukas Czerner 		ext4_remove_li_request(elr);
3443bfff6873SLukas Czerner 	}
3444bfff6873SLukas Czerner 	mutex_unlock(&ext4_li_info->li_list_mtx);
3445bfff6873SLukas Czerner }
3446bfff6873SLukas Czerner 
3447bfff6873SLukas Czerner static int ext4_run_lazyinit_thread(void)
3448bfff6873SLukas Czerner {
34498f1f7453SEric Sandeen 	ext4_lazyinit_task = kthread_run(ext4_lazyinit_thread,
34508f1f7453SEric Sandeen 					 ext4_li_info, "ext4lazyinit");
34518f1f7453SEric Sandeen 	if (IS_ERR(ext4_lazyinit_task)) {
34528f1f7453SEric Sandeen 		int err = PTR_ERR(ext4_lazyinit_task);
3453bfff6873SLukas Czerner 		ext4_clear_request_list();
3454bfff6873SLukas Czerner 		kfree(ext4_li_info);
3455bfff6873SLukas Czerner 		ext4_li_info = NULL;
345692b97816STheodore Ts'o 		printk(KERN_CRIT "EXT4-fs: error %d creating inode table "
3457bfff6873SLukas Czerner 				 "initialization thread\n",
3458bfff6873SLukas Czerner 				 err);
3459bfff6873SLukas Czerner 		return err;
3460bfff6873SLukas Czerner 	}
3461bfff6873SLukas Czerner 	ext4_li_info->li_state |= EXT4_LAZYINIT_RUNNING;
3462bfff6873SLukas Czerner 	return 0;
3463bfff6873SLukas Czerner }
3464bfff6873SLukas Czerner 
3465bfff6873SLukas Czerner /*
3466bfff6873SLukas Czerner  * Check whether it make sense to run itable init. thread or not.
3467bfff6873SLukas Czerner  * If there is at least one uninitialized inode table, return
3468bfff6873SLukas Czerner  * corresponding group number, else the loop goes through all
3469bfff6873SLukas Czerner  * groups and return total number of groups.
3470bfff6873SLukas Czerner  */
3471bfff6873SLukas Czerner static ext4_group_t ext4_has_uninit_itable(struct super_block *sb)
3472bfff6873SLukas Czerner {
3473bfff6873SLukas Czerner 	ext4_group_t group, ngroups = EXT4_SB(sb)->s_groups_count;
3474bfff6873SLukas Czerner 	struct ext4_group_desc *gdp = NULL;
3475bfff6873SLukas Czerner 
34768844618dSTheodore Ts'o 	if (!ext4_has_group_desc_csum(sb))
34778844618dSTheodore Ts'o 		return ngroups;
34788844618dSTheodore Ts'o 
3479bfff6873SLukas Czerner 	for (group = 0; group < ngroups; group++) {
3480bfff6873SLukas Czerner 		gdp = ext4_get_group_desc(sb, group, NULL);
3481bfff6873SLukas Czerner 		if (!gdp)
3482bfff6873SLukas Czerner 			continue;
3483bfff6873SLukas Czerner 
348450122847STheodore Ts'o 		if (!(gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED)))
3485bfff6873SLukas Czerner 			break;
3486bfff6873SLukas Czerner 	}
3487bfff6873SLukas Czerner 
3488bfff6873SLukas Czerner 	return group;
3489bfff6873SLukas Czerner }
3490bfff6873SLukas Czerner 
3491bfff6873SLukas Czerner static int ext4_li_info_new(void)
3492bfff6873SLukas Czerner {
3493bfff6873SLukas Czerner 	struct ext4_lazy_init *eli = NULL;
3494bfff6873SLukas Czerner 
3495bfff6873SLukas Czerner 	eli = kzalloc(sizeof(*eli), GFP_KERNEL);
3496bfff6873SLukas Czerner 	if (!eli)
3497bfff6873SLukas Czerner 		return -ENOMEM;
3498bfff6873SLukas Czerner 
3499bfff6873SLukas Czerner 	INIT_LIST_HEAD(&eli->li_request_list);
3500bfff6873SLukas Czerner 	mutex_init(&eli->li_list_mtx);
3501bfff6873SLukas Czerner 
3502bfff6873SLukas Czerner 	eli->li_state |= EXT4_LAZYINIT_QUIT;
3503bfff6873SLukas Czerner 
3504bfff6873SLukas Czerner 	ext4_li_info = eli;
3505bfff6873SLukas Czerner 
3506bfff6873SLukas Czerner 	return 0;
3507bfff6873SLukas Czerner }
3508bfff6873SLukas Czerner 
3509bfff6873SLukas Czerner static struct ext4_li_request *ext4_li_request_new(struct super_block *sb,
3510bfff6873SLukas Czerner 					    ext4_group_t start)
3511bfff6873SLukas Czerner {
3512bfff6873SLukas Czerner 	struct ext4_li_request *elr;
3513bfff6873SLukas Czerner 
3514bfff6873SLukas Czerner 	elr = kzalloc(sizeof(*elr), GFP_KERNEL);
3515bfff6873SLukas Czerner 	if (!elr)
3516bfff6873SLukas Czerner 		return NULL;
3517bfff6873SLukas Czerner 
3518bfff6873SLukas Czerner 	elr->lr_super = sb;
35193d392b26STheodore Ts'o 	elr->lr_first_not_zeroed = start;
35203d392b26STheodore Ts'o 	if (test_opt(sb, PREFETCH_BLOCK_BITMAPS))
35213d392b26STheodore Ts'o 		elr->lr_mode = EXT4_LI_MODE_PREFETCH_BBITMAP;
35223d392b26STheodore Ts'o 	else {
35233d392b26STheodore Ts'o 		elr->lr_mode = EXT4_LI_MODE_ITABLE;
3524bfff6873SLukas Czerner 		elr->lr_next_group = start;
35253d392b26STheodore Ts'o 	}
3526bfff6873SLukas Czerner 
3527bfff6873SLukas Czerner 	/*
3528bfff6873SLukas Czerner 	 * Randomize first schedule time of the request to
3529bfff6873SLukas Czerner 	 * spread the inode table initialization requests
3530bfff6873SLukas Czerner 	 * better.
3531bfff6873SLukas Czerner 	 */
3532dd1f723bSTheodore Ts'o 	elr->lr_next_sched = jiffies + (prandom_u32() %
3533dd1f723bSTheodore Ts'o 				(EXT4_DEF_LI_MAX_START_DELAY * HZ));
3534bfff6873SLukas Czerner 	return elr;
3535bfff6873SLukas Czerner }
3536bfff6873SLukas Czerner 
35377f511862STheodore Ts'o int ext4_register_li_request(struct super_block *sb,
3538bfff6873SLukas Czerner 			     ext4_group_t first_not_zeroed)
3539bfff6873SLukas Czerner {
3540bfff6873SLukas Czerner 	struct ext4_sb_info *sbi = EXT4_SB(sb);
35417f511862STheodore Ts'o 	struct ext4_li_request *elr = NULL;
354249598e04SJun Piao 	ext4_group_t ngroups = sbi->s_groups_count;
35436c5a6cb9SAndrew Morton 	int ret = 0;
3544bfff6873SLukas Czerner 
35457f511862STheodore Ts'o 	mutex_lock(&ext4_li_mtx);
354651ce6511SLukas Czerner 	if (sbi->s_li_request != NULL) {
354751ce6511SLukas Czerner 		/*
354851ce6511SLukas Czerner 		 * Reset timeout so it can be computed again, because
354951ce6511SLukas Czerner 		 * s_li_wait_mult might have changed.
355051ce6511SLukas Czerner 		 */
355151ce6511SLukas Czerner 		sbi->s_li_request->lr_timeout = 0;
35527f511862STheodore Ts'o 		goto out;
355351ce6511SLukas Czerner 	}
3554bfff6873SLukas Czerner 
35553d392b26STheodore Ts'o 	if (!test_opt(sb, PREFETCH_BLOCK_BITMAPS) &&
35563d392b26STheodore Ts'o 	    (first_not_zeroed == ngroups || sb_rdonly(sb) ||
35573d392b26STheodore Ts'o 	     !test_opt(sb, INIT_INODE_TABLE)))
35587f511862STheodore Ts'o 		goto out;
3559bfff6873SLukas Czerner 
3560bfff6873SLukas Czerner 	elr = ext4_li_request_new(sb, first_not_zeroed);
35617f511862STheodore Ts'o 	if (!elr) {
35627f511862STheodore Ts'o 		ret = -ENOMEM;
35637f511862STheodore Ts'o 		goto out;
35647f511862STheodore Ts'o 	}
3565bfff6873SLukas Czerner 
3566bfff6873SLukas Czerner 	if (NULL == ext4_li_info) {
3567bfff6873SLukas Czerner 		ret = ext4_li_info_new();
3568bfff6873SLukas Czerner 		if (ret)
3569bfff6873SLukas Czerner 			goto out;
3570bfff6873SLukas Czerner 	}
3571bfff6873SLukas Czerner 
3572bfff6873SLukas Czerner 	mutex_lock(&ext4_li_info->li_list_mtx);
3573bfff6873SLukas Czerner 	list_add(&elr->lr_request, &ext4_li_info->li_request_list);
3574bfff6873SLukas Czerner 	mutex_unlock(&ext4_li_info->li_list_mtx);
3575bfff6873SLukas Czerner 
3576bfff6873SLukas Czerner 	sbi->s_li_request = elr;
357746e4690bSTao Ma 	/*
357846e4690bSTao Ma 	 * set elr to NULL here since it has been inserted to
357946e4690bSTao Ma 	 * the request_list and the removal and free of it is
358046e4690bSTao Ma 	 * handled by ext4_clear_request_list from now on.
358146e4690bSTao Ma 	 */
358246e4690bSTao Ma 	elr = NULL;
3583bfff6873SLukas Czerner 
3584bfff6873SLukas Czerner 	if (!(ext4_li_info->li_state & EXT4_LAZYINIT_RUNNING)) {
3585bfff6873SLukas Czerner 		ret = ext4_run_lazyinit_thread();
3586bfff6873SLukas Czerner 		if (ret)
3587bfff6873SLukas Czerner 			goto out;
3588bfff6873SLukas Czerner 	}
3589bfff6873SLukas Czerner out:
3590bfff6873SLukas Czerner 	mutex_unlock(&ext4_li_mtx);
3591beed5ecbSNicolas Kaiser 	if (ret)
3592bfff6873SLukas Czerner 		kfree(elr);
3593bfff6873SLukas Czerner 	return ret;
3594bfff6873SLukas Czerner }
3595bfff6873SLukas Czerner 
3596bfff6873SLukas Czerner /*
3597bfff6873SLukas Czerner  * We do not need to lock anything since this is called on
3598bfff6873SLukas Czerner  * module unload.
3599bfff6873SLukas Czerner  */
3600bfff6873SLukas Czerner static void ext4_destroy_lazyinit_thread(void)
3601bfff6873SLukas Czerner {
3602bfff6873SLukas Czerner 	/*
3603bfff6873SLukas Czerner 	 * If thread exited earlier
3604bfff6873SLukas Czerner 	 * there's nothing to be done.
3605bfff6873SLukas Czerner 	 */
36068f1f7453SEric Sandeen 	if (!ext4_li_info || !ext4_lazyinit_task)
3607bfff6873SLukas Czerner 		return;
3608bfff6873SLukas Czerner 
36098f1f7453SEric Sandeen 	kthread_stop(ext4_lazyinit_task);
3610bfff6873SLukas Czerner }
3611bfff6873SLukas Czerner 
361225ed6e8aSDarrick J. Wong static int set_journal_csum_feature_set(struct super_block *sb)
361325ed6e8aSDarrick J. Wong {
361425ed6e8aSDarrick J. Wong 	int ret = 1;
361525ed6e8aSDarrick J. Wong 	int compat, incompat;
361625ed6e8aSDarrick J. Wong 	struct ext4_sb_info *sbi = EXT4_SB(sb);
361725ed6e8aSDarrick J. Wong 
36189aa5d32bSDmitry Monakhov 	if (ext4_has_metadata_csum(sb)) {
3619db9ee220SDarrick J. Wong 		/* journal checksum v3 */
362025ed6e8aSDarrick J. Wong 		compat = 0;
3621db9ee220SDarrick J. Wong 		incompat = JBD2_FEATURE_INCOMPAT_CSUM_V3;
362225ed6e8aSDarrick J. Wong 	} else {
362325ed6e8aSDarrick J. Wong 		/* journal checksum v1 */
362425ed6e8aSDarrick J. Wong 		compat = JBD2_FEATURE_COMPAT_CHECKSUM;
362525ed6e8aSDarrick J. Wong 		incompat = 0;
362625ed6e8aSDarrick J. Wong 	}
362725ed6e8aSDarrick J. Wong 
3628feb8c6d3SDarrick J. Wong 	jbd2_journal_clear_features(sbi->s_journal,
3629feb8c6d3SDarrick J. Wong 			JBD2_FEATURE_COMPAT_CHECKSUM, 0,
3630feb8c6d3SDarrick J. Wong 			JBD2_FEATURE_INCOMPAT_CSUM_V3 |
3631feb8c6d3SDarrick J. Wong 			JBD2_FEATURE_INCOMPAT_CSUM_V2);
363225ed6e8aSDarrick J. Wong 	if (test_opt(sb, JOURNAL_ASYNC_COMMIT)) {
363325ed6e8aSDarrick J. Wong 		ret = jbd2_journal_set_features(sbi->s_journal,
363425ed6e8aSDarrick J. Wong 				compat, 0,
363525ed6e8aSDarrick J. Wong 				JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT |
363625ed6e8aSDarrick J. Wong 				incompat);
363725ed6e8aSDarrick J. Wong 	} else if (test_opt(sb, JOURNAL_CHECKSUM)) {
363825ed6e8aSDarrick J. Wong 		ret = jbd2_journal_set_features(sbi->s_journal,
363925ed6e8aSDarrick J. Wong 				compat, 0,
364025ed6e8aSDarrick J. Wong 				incompat);
364125ed6e8aSDarrick J. Wong 		jbd2_journal_clear_features(sbi->s_journal, 0, 0,
364225ed6e8aSDarrick J. Wong 				JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT);
364325ed6e8aSDarrick J. Wong 	} else {
3644feb8c6d3SDarrick J. Wong 		jbd2_journal_clear_features(sbi->s_journal, 0, 0,
3645feb8c6d3SDarrick J. Wong 				JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT);
364625ed6e8aSDarrick J. Wong 	}
364725ed6e8aSDarrick J. Wong 
364825ed6e8aSDarrick J. Wong 	return ret;
364925ed6e8aSDarrick J. Wong }
365025ed6e8aSDarrick J. Wong 
3651952fc18eSTheodore Ts'o /*
3652952fc18eSTheodore Ts'o  * Note: calculating the overhead so we can be compatible with
3653952fc18eSTheodore Ts'o  * historical BSD practice is quite difficult in the face of
3654952fc18eSTheodore Ts'o  * clusters/bigalloc.  This is because multiple metadata blocks from
3655952fc18eSTheodore Ts'o  * different block group can end up in the same allocation cluster.
3656952fc18eSTheodore Ts'o  * Calculating the exact overhead in the face of clustered allocation
3657952fc18eSTheodore Ts'o  * requires either O(all block bitmaps) in memory or O(number of block
3658952fc18eSTheodore Ts'o  * groups**2) in time.  We will still calculate the superblock for
3659952fc18eSTheodore Ts'o  * older file systems --- and if we come across with a bigalloc file
3660952fc18eSTheodore Ts'o  * system with zero in s_overhead_clusters the estimate will be close to
3661952fc18eSTheodore Ts'o  * correct especially for very large cluster sizes --- but for newer
3662952fc18eSTheodore Ts'o  * file systems, it's better to calculate this figure once at mkfs
3663952fc18eSTheodore Ts'o  * time, and store it in the superblock.  If the superblock value is
3664952fc18eSTheodore Ts'o  * present (even for non-bigalloc file systems), we will use it.
3665952fc18eSTheodore Ts'o  */
3666952fc18eSTheodore Ts'o static int count_overhead(struct super_block *sb, ext4_group_t grp,
3667952fc18eSTheodore Ts'o 			  char *buf)
3668952fc18eSTheodore Ts'o {
3669952fc18eSTheodore Ts'o 	struct ext4_sb_info	*sbi = EXT4_SB(sb);
3670952fc18eSTheodore Ts'o 	struct ext4_group_desc	*gdp;
3671952fc18eSTheodore Ts'o 	ext4_fsblk_t		first_block, last_block, b;
3672952fc18eSTheodore Ts'o 	ext4_group_t		i, ngroups = ext4_get_groups_count(sb);
3673952fc18eSTheodore Ts'o 	int			s, j, count = 0;
3674952fc18eSTheodore Ts'o 
3675e2b911c5SDarrick J. Wong 	if (!ext4_has_feature_bigalloc(sb))
36760548bbb8STheodore Ts'o 		return (ext4_bg_has_super(sb, grp) + ext4_bg_num_gdb(sb, grp) +
36770548bbb8STheodore Ts'o 			sbi->s_itb_per_group + 2);
36780548bbb8STheodore Ts'o 
3679952fc18eSTheodore Ts'o 	first_block = le32_to_cpu(sbi->s_es->s_first_data_block) +
3680952fc18eSTheodore Ts'o 		(grp * EXT4_BLOCKS_PER_GROUP(sb));
3681952fc18eSTheodore Ts'o 	last_block = first_block + EXT4_BLOCKS_PER_GROUP(sb) - 1;
3682952fc18eSTheodore Ts'o 	for (i = 0; i < ngroups; i++) {
3683952fc18eSTheodore Ts'o 		gdp = ext4_get_group_desc(sb, i, NULL);
3684952fc18eSTheodore Ts'o 		b = ext4_block_bitmap(sb, gdp);
3685952fc18eSTheodore Ts'o 		if (b >= first_block && b <= last_block) {
3686952fc18eSTheodore Ts'o 			ext4_set_bit(EXT4_B2C(sbi, b - first_block), buf);
3687952fc18eSTheodore Ts'o 			count++;
3688952fc18eSTheodore Ts'o 		}
3689952fc18eSTheodore Ts'o 		b = ext4_inode_bitmap(sb, gdp);
3690952fc18eSTheodore Ts'o 		if (b >= first_block && b <= last_block) {
3691952fc18eSTheodore Ts'o 			ext4_set_bit(EXT4_B2C(sbi, b - first_block), buf);
3692952fc18eSTheodore Ts'o 			count++;
3693952fc18eSTheodore Ts'o 		}
3694952fc18eSTheodore Ts'o 		b = ext4_inode_table(sb, gdp);
3695952fc18eSTheodore Ts'o 		if (b >= first_block && b + sbi->s_itb_per_group <= last_block)
3696952fc18eSTheodore Ts'o 			for (j = 0; j < sbi->s_itb_per_group; j++, b++) {
3697952fc18eSTheodore Ts'o 				int c = EXT4_B2C(sbi, b - first_block);
3698952fc18eSTheodore Ts'o 				ext4_set_bit(c, buf);
3699952fc18eSTheodore Ts'o 				count++;
3700952fc18eSTheodore Ts'o 			}
3701952fc18eSTheodore Ts'o 		if (i != grp)
3702952fc18eSTheodore Ts'o 			continue;
3703952fc18eSTheodore Ts'o 		s = 0;
3704952fc18eSTheodore Ts'o 		if (ext4_bg_has_super(sb, grp)) {
3705952fc18eSTheodore Ts'o 			ext4_set_bit(s++, buf);
3706952fc18eSTheodore Ts'o 			count++;
3707952fc18eSTheodore Ts'o 		}
3708c48ae41bSTheodore Ts'o 		j = ext4_bg_num_gdb(sb, grp);
3709c48ae41bSTheodore Ts'o 		if (s + j > EXT4_BLOCKS_PER_GROUP(sb)) {
3710c48ae41bSTheodore Ts'o 			ext4_error(sb, "Invalid number of block group "
3711c48ae41bSTheodore Ts'o 				   "descriptor blocks: %d", j);
3712c48ae41bSTheodore Ts'o 			j = EXT4_BLOCKS_PER_GROUP(sb) - s;
3713952fc18eSTheodore Ts'o 		}
3714c48ae41bSTheodore Ts'o 		count += j;
3715c48ae41bSTheodore Ts'o 		for (; j > 0; j--)
3716c48ae41bSTheodore Ts'o 			ext4_set_bit(EXT4_B2C(sbi, s++), buf);
3717952fc18eSTheodore Ts'o 	}
3718952fc18eSTheodore Ts'o 	if (!count)
3719952fc18eSTheodore Ts'o 		return 0;
3720952fc18eSTheodore Ts'o 	return EXT4_CLUSTERS_PER_GROUP(sb) -
3721952fc18eSTheodore Ts'o 		ext4_count_free(buf, EXT4_CLUSTERS_PER_GROUP(sb) / 8);
3722952fc18eSTheodore Ts'o }
3723952fc18eSTheodore Ts'o 
3724952fc18eSTheodore Ts'o /*
3725952fc18eSTheodore Ts'o  * Compute the overhead and stash it in sbi->s_overhead
3726952fc18eSTheodore Ts'o  */
3727952fc18eSTheodore Ts'o int ext4_calculate_overhead(struct super_block *sb)
3728952fc18eSTheodore Ts'o {
3729952fc18eSTheodore Ts'o 	struct ext4_sb_info *sbi = EXT4_SB(sb);
3730952fc18eSTheodore Ts'o 	struct ext4_super_block *es = sbi->s_es;
37313c816dedSEric Whitney 	struct inode *j_inode;
37323c816dedSEric Whitney 	unsigned int j_blocks, j_inum = le32_to_cpu(es->s_journal_inum);
3733952fc18eSTheodore Ts'o 	ext4_group_t i, ngroups = ext4_get_groups_count(sb);
3734952fc18eSTheodore Ts'o 	ext4_fsblk_t overhead = 0;
37354fdb5543SDmitry Monakhov 	char *buf = (char *) get_zeroed_page(GFP_NOFS);
3736952fc18eSTheodore Ts'o 
3737952fc18eSTheodore Ts'o 	if (!buf)
3738952fc18eSTheodore Ts'o 		return -ENOMEM;
3739952fc18eSTheodore Ts'o 
3740952fc18eSTheodore Ts'o 	/*
3741952fc18eSTheodore Ts'o 	 * Compute the overhead (FS structures).  This is constant
3742952fc18eSTheodore Ts'o 	 * for a given filesystem unless the number of block groups
3743952fc18eSTheodore Ts'o 	 * changes so we cache the previous value until it does.
3744952fc18eSTheodore Ts'o 	 */
3745952fc18eSTheodore Ts'o 
3746952fc18eSTheodore Ts'o 	/*
3747952fc18eSTheodore Ts'o 	 * All of the blocks before first_data_block are overhead
3748952fc18eSTheodore Ts'o 	 */
3749952fc18eSTheodore Ts'o 	overhead = EXT4_B2C(sbi, le32_to_cpu(es->s_first_data_block));
3750952fc18eSTheodore Ts'o 
3751952fc18eSTheodore Ts'o 	/*
3752952fc18eSTheodore Ts'o 	 * Add the overhead found in each block group
3753952fc18eSTheodore Ts'o 	 */
3754952fc18eSTheodore Ts'o 	for (i = 0; i < ngroups; i++) {
3755952fc18eSTheodore Ts'o 		int blks;
3756952fc18eSTheodore Ts'o 
3757952fc18eSTheodore Ts'o 		blks = count_overhead(sb, i, buf);
3758952fc18eSTheodore Ts'o 		overhead += blks;
3759952fc18eSTheodore Ts'o 		if (blks)
3760952fc18eSTheodore Ts'o 			memset(buf, 0, PAGE_SIZE);
3761952fc18eSTheodore Ts'o 		cond_resched();
3762952fc18eSTheodore Ts'o 	}
37633c816dedSEric Whitney 
37643c816dedSEric Whitney 	/*
37653c816dedSEric Whitney 	 * Add the internal journal blocks whether the journal has been
37663c816dedSEric Whitney 	 * loaded or not
37673c816dedSEric Whitney 	 */
3768ee7ed3aaSChunguang Xu 	if (sbi->s_journal && !sbi->s_journal_bdev)
3769810da240SLukas Czerner 		overhead += EXT4_NUM_B2C(sbi, sbi->s_journal->j_maxlen);
3770f1eec3b0SRitesh Harjani 	else if (ext4_has_feature_journal(sb) && !sbi->s_journal && j_inum) {
3771f1eec3b0SRitesh Harjani 		/* j_inum for internal journal is non-zero */
37723c816dedSEric Whitney 		j_inode = ext4_get_journal_inode(sb, j_inum);
37733c816dedSEric Whitney 		if (j_inode) {
37743c816dedSEric Whitney 			j_blocks = j_inode->i_size >> sb->s_blocksize_bits;
37753c816dedSEric Whitney 			overhead += EXT4_NUM_B2C(sbi, j_blocks);
37763c816dedSEric Whitney 			iput(j_inode);
37773c816dedSEric Whitney 		} else {
37783c816dedSEric Whitney 			ext4_msg(sb, KERN_ERR, "can't get journal size");
37793c816dedSEric Whitney 		}
37803c816dedSEric Whitney 	}
3781952fc18eSTheodore Ts'o 	sbi->s_overhead = overhead;
3782952fc18eSTheodore Ts'o 	smp_wmb();
3783952fc18eSTheodore Ts'o 	free_page((unsigned long) buf);
3784952fc18eSTheodore Ts'o 	return 0;
3785952fc18eSTheodore Ts'o }
3786952fc18eSTheodore Ts'o 
3787b5799018STheodore Ts'o static void ext4_set_resv_clusters(struct super_block *sb)
378827dd4385SLukas Czerner {
378927dd4385SLukas Czerner 	ext4_fsblk_t resv_clusters;
3790b5799018STheodore Ts'o 	struct ext4_sb_info *sbi = EXT4_SB(sb);
379127dd4385SLukas Czerner 
379227dd4385SLukas Czerner 	/*
379330fac0f7SJan Kara 	 * There's no need to reserve anything when we aren't using extents.
379430fac0f7SJan Kara 	 * The space estimates are exact, there are no unwritten extents,
379530fac0f7SJan Kara 	 * hole punching doesn't need new metadata... This is needed especially
379630fac0f7SJan Kara 	 * to keep ext2/3 backward compatibility.
379730fac0f7SJan Kara 	 */
3798e2b911c5SDarrick J. Wong 	if (!ext4_has_feature_extents(sb))
3799b5799018STheodore Ts'o 		return;
380030fac0f7SJan Kara 	/*
380127dd4385SLukas Czerner 	 * By default we reserve 2% or 4096 clusters, whichever is smaller.
380227dd4385SLukas Czerner 	 * This should cover the situations where we can not afford to run
380327dd4385SLukas Czerner 	 * out of space like for example punch hole, or converting
3804556615dcSLukas Czerner 	 * unwritten extents in delalloc path. In most cases such
380527dd4385SLukas Czerner 	 * allocation would require 1, or 2 blocks, higher numbers are
380627dd4385SLukas Czerner 	 * very rare.
380727dd4385SLukas Czerner 	 */
3808b5799018STheodore Ts'o 	resv_clusters = (ext4_blocks_count(sbi->s_es) >>
3809b5799018STheodore Ts'o 			 sbi->s_cluster_bits);
381027dd4385SLukas Czerner 
381127dd4385SLukas Czerner 	do_div(resv_clusters, 50);
381227dd4385SLukas Czerner 	resv_clusters = min_t(ext4_fsblk_t, resv_clusters, 4096);
381327dd4385SLukas Czerner 
3814b5799018STheodore Ts'o 	atomic64_set(&sbi->s_resv_clusters, resv_clusters);
381527dd4385SLukas Czerner }
381627dd4385SLukas Czerner 
3817617ba13bSMingming Cao static int ext4_fill_super(struct super_block *sb, void *data, int silent)
3818ac27a0ecSDave Kleikamp {
38195e405595SDan Williams 	struct dax_device *dax_dev = fs_dax_get_by_bdev(sb->s_bdev);
3820d4c402d9SCurt Wohlgemuth 	char *orig_data = kstrdup(data, GFP_KERNEL);
38211d0c3924STheodore Ts'o 	struct buffer_head *bh, **group_desc;
3822617ba13bSMingming Cao 	struct ext4_super_block *es = NULL;
38235aee0f8aSTheodore Ts'o 	struct ext4_sb_info *sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
38247c990728SSuraj Jitindar Singh 	struct flex_groups **flex_groups;
3825617ba13bSMingming Cao 	ext4_fsblk_t block;
3826617ba13bSMingming Cao 	ext4_fsblk_t sb_block = get_sb_block(&data);
382770bbb3e0SAndrew Morton 	ext4_fsblk_t logical_sb_block;
3828ac27a0ecSDave Kleikamp 	unsigned long offset = 0;
3829ac27a0ecSDave Kleikamp 	unsigned long journal_devnum = 0;
3830ac27a0ecSDave Kleikamp 	unsigned long def_mount_opts;
3831ac27a0ecSDave Kleikamp 	struct inode *root;
38320390131bSFrank Mayhar 	const char *descr;
3833dcc7dae3SCyrill Gorcunov 	int ret = -ENOMEM;
3834281b5995STheodore Ts'o 	int blocksize, clustersize;
38354ec11028STheodore Ts'o 	unsigned int db_count;
38364ec11028STheodore Ts'o 	unsigned int i;
3837ef5fd681SKaixu Xia 	int needs_recovery, has_huge_files;
3838bd81d8eeSLaurent Vivier 	__u64 blocks_count;
383907aa2ea1SLukas Czerner 	int err = 0;
3840b3881f74STheodore Ts'o 	unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO;
3841bfff6873SLukas Czerner 	ext4_group_t first_not_zeroed;
3842ac27a0ecSDave Kleikamp 
38435aee0f8aSTheodore Ts'o 	if ((data && !orig_data) || !sbi)
38445aee0f8aSTheodore Ts'o 		goto out_free_base;
3845705895b6SPekka Enberg 
3846aed9eb1bSColin Ian King 	sbi->s_daxdev = dax_dev;
3847705895b6SPekka Enberg 	sbi->s_blockgroup_lock =
3848705895b6SPekka Enberg 		kzalloc(sizeof(struct blockgroup_lock), GFP_KERNEL);
38495aee0f8aSTheodore Ts'o 	if (!sbi->s_blockgroup_lock)
38505aee0f8aSTheodore Ts'o 		goto out_free_base;
38515aee0f8aSTheodore Ts'o 
3852ac27a0ecSDave Kleikamp 	sb->s_fs_info = sbi;
38532c0544b2STheodore Ts'o 	sbi->s_sb = sb;
3854240799cdSTheodore Ts'o 	sbi->s_inode_readahead_blks = EXT4_DEF_INODE_READAHEAD_BLKS;
3855d9c9bef1SMiklos Szeredi 	sbi->s_sb_block = sb_block;
3856f613dfcbSTheodore Ts'o 	if (sb->s_bdev->bd_part)
3857f613dfcbSTheodore Ts'o 		sbi->s_sectors_written_start =
3858dbae2c55SMichael Callahan 			part_stat_read(sb->s_bdev->bd_part, sectors[STAT_WRITE]);
3859ac27a0ecSDave Kleikamp 
38609f6200bbSTheodore Ts'o 	/* Cleanup superblock name */
3861ec3904dcSRasmus Villemoes 	strreplace(sb->s_id, '/', '!');
38629f6200bbSTheodore Ts'o 
386307aa2ea1SLukas Czerner 	/* -EINVAL is default */
3864dcc7dae3SCyrill Gorcunov 	ret = -EINVAL;
3865617ba13bSMingming Cao 	blocksize = sb_min_blocksize(sb, EXT4_MIN_BLOCK_SIZE);
3866ac27a0ecSDave Kleikamp 	if (!blocksize) {
3867b31e1552SEric Sandeen 		ext4_msg(sb, KERN_ERR, "unable to set blocksize");
3868ac27a0ecSDave Kleikamp 		goto out_fail;
3869ac27a0ecSDave Kleikamp 	}
3870ac27a0ecSDave Kleikamp 
3871ac27a0ecSDave Kleikamp 	/*
3872617ba13bSMingming Cao 	 * The ext4 superblock will not be buffer aligned for other than 1kB
3873ac27a0ecSDave Kleikamp 	 * block sizes.  We need to calculate the offset from buffer start.
3874ac27a0ecSDave Kleikamp 	 */
3875617ba13bSMingming Cao 	if (blocksize != EXT4_MIN_BLOCK_SIZE) {
387670bbb3e0SAndrew Morton 		logical_sb_block = sb_block * EXT4_MIN_BLOCK_SIZE;
387770bbb3e0SAndrew Morton 		offset = do_div(logical_sb_block, blocksize);
3878ac27a0ecSDave Kleikamp 	} else {
387970bbb3e0SAndrew Morton 		logical_sb_block = sb_block;
3880ac27a0ecSDave Kleikamp 	}
3881ac27a0ecSDave Kleikamp 
3882a8ac900bSGioh Kim 	if (!(bh = sb_bread_unmovable(sb, logical_sb_block))) {
3883b31e1552SEric Sandeen 		ext4_msg(sb, KERN_ERR, "unable to read superblock");
3884ac27a0ecSDave Kleikamp 		goto out_fail;
3885ac27a0ecSDave Kleikamp 	}
3886ac27a0ecSDave Kleikamp 	/*
3887ac27a0ecSDave Kleikamp 	 * Note: s_es must be initialized as soon as possible because
3888617ba13bSMingming Cao 	 *       some ext4 macro-instructions depend on its value
3889ac27a0ecSDave Kleikamp 	 */
38902716b802STheodore Ts'o 	es = (struct ext4_super_block *) (bh->b_data + offset);
3891ac27a0ecSDave Kleikamp 	sbi->s_es = es;
3892ac27a0ecSDave Kleikamp 	sb->s_magic = le16_to_cpu(es->s_magic);
3893617ba13bSMingming Cao 	if (sb->s_magic != EXT4_SUPER_MAGIC)
3894617ba13bSMingming Cao 		goto cantfind_ext4;
3895afc32f7eSTheodore Ts'o 	sbi->s_kbytes_written = le64_to_cpu(es->s_kbytes_written);
3896ac27a0ecSDave Kleikamp 
3897feb0ab32SDarrick J. Wong 	/* Warn if metadata_csum and gdt_csum are both set. */
3898e2b911c5SDarrick J. Wong 	if (ext4_has_feature_metadata_csum(sb) &&
3899e2b911c5SDarrick J. Wong 	    ext4_has_feature_gdt_csum(sb))
3900363307e6SJakub Wilk 		ext4_warning(sb, "metadata_csum and uninit_bg are "
3901feb0ab32SDarrick J. Wong 			     "redundant flags; please run fsck.");
3902feb0ab32SDarrick J. Wong 
3903d25425f8SDarrick J. Wong 	/* Check for a known checksum algorithm */
3904d25425f8SDarrick J. Wong 	if (!ext4_verify_csum_type(sb, es)) {
3905d25425f8SDarrick J. Wong 		ext4_msg(sb, KERN_ERR, "VFS: Found ext4 filesystem with "
3906d25425f8SDarrick J. Wong 			 "unknown checksum algorithm.");
3907d25425f8SDarrick J. Wong 		silent = 1;
3908d25425f8SDarrick J. Wong 		goto cantfind_ext4;
3909d25425f8SDarrick J. Wong 	}
3910d25425f8SDarrick J. Wong 
39110441984aSDarrick J. Wong 	/* Load the checksum driver */
39120441984aSDarrick J. Wong 	sbi->s_chksum_driver = crypto_alloc_shash("crc32c", 0, 0);
39130441984aSDarrick J. Wong 	if (IS_ERR(sbi->s_chksum_driver)) {
39140441984aSDarrick J. Wong 		ext4_msg(sb, KERN_ERR, "Cannot load crc32c driver.");
39150441984aSDarrick J. Wong 		ret = PTR_ERR(sbi->s_chksum_driver);
39160441984aSDarrick J. Wong 		sbi->s_chksum_driver = NULL;
39170441984aSDarrick J. Wong 		goto failed_mount;
39180441984aSDarrick J. Wong 	}
39190441984aSDarrick J. Wong 
3920a9c47317SDarrick J. Wong 	/* Check superblock checksum */
3921a9c47317SDarrick J. Wong 	if (!ext4_superblock_csum_verify(sb, es)) {
3922a9c47317SDarrick J. Wong 		ext4_msg(sb, KERN_ERR, "VFS: Found ext4 filesystem with "
3923a9c47317SDarrick J. Wong 			 "invalid superblock checksum.  Run e2fsck?");
3924a9c47317SDarrick J. Wong 		silent = 1;
39256a797d27SDarrick J. Wong 		ret = -EFSBADCRC;
3926a9c47317SDarrick J. Wong 		goto cantfind_ext4;
3927a9c47317SDarrick J. Wong 	}
3928a9c47317SDarrick J. Wong 
3929a9c47317SDarrick J. Wong 	/* Precompute checksum seed for all metadata */
3930e2b911c5SDarrick J. Wong 	if (ext4_has_feature_csum_seed(sb))
39318c81bd8fSDarrick J. Wong 		sbi->s_csum_seed = le32_to_cpu(es->s_checksum_seed);
3932dec214d0STahsin Erdogan 	else if (ext4_has_metadata_csum(sb) || ext4_has_feature_ea_inode(sb))
3933a9c47317SDarrick J. Wong 		sbi->s_csum_seed = ext4_chksum(sbi, ~0, es->s_uuid,
3934a9c47317SDarrick J. Wong 					       sizeof(es->s_uuid));
3935a9c47317SDarrick J. Wong 
3936ac27a0ecSDave Kleikamp 	/* Set defaults before we parse the mount options */
3937ac27a0ecSDave Kleikamp 	def_mount_opts = le32_to_cpu(es->s_default_mount_opts);
3938fd8c37ecSTheodore Ts'o 	set_opt(sb, INIT_INODE_TABLE);
3939617ba13bSMingming Cao 	if (def_mount_opts & EXT4_DEFM_DEBUG)
3940fd8c37ecSTheodore Ts'o 		set_opt(sb, DEBUG);
394187f26807STheodore Ts'o 	if (def_mount_opts & EXT4_DEFM_BSDGROUPS)
3942fd8c37ecSTheodore Ts'o 		set_opt(sb, GRPID);
3943617ba13bSMingming Cao 	if (def_mount_opts & EXT4_DEFM_UID16)
3944fd8c37ecSTheodore Ts'o 		set_opt(sb, NO_UID32);
3945ea663336SEric Sandeen 	/* xattr user namespace & acls are now defaulted on */
3946fd8c37ecSTheodore Ts'o 	set_opt(sb, XATTR_USER);
394703010a33STheodore Ts'o #ifdef CONFIG_EXT4_FS_POSIX_ACL
3948fd8c37ecSTheodore Ts'o 	set_opt(sb, POSIX_ACL);
39492e7842b8SHugh Dickins #endif
395098c1a759SDarrick J. Wong 	/* don't forget to enable journal_csum when metadata_csum is enabled. */
395198c1a759SDarrick J. Wong 	if (ext4_has_metadata_csum(sb))
395298c1a759SDarrick J. Wong 		set_opt(sb, JOURNAL_CHECKSUM);
395398c1a759SDarrick J. Wong 
3954617ba13bSMingming Cao 	if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_DATA)
3955fd8c37ecSTheodore Ts'o 		set_opt(sb, JOURNAL_DATA);
3956617ba13bSMingming Cao 	else if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_ORDERED)
3957fd8c37ecSTheodore Ts'o 		set_opt(sb, ORDERED_DATA);
3958617ba13bSMingming Cao 	else if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_WBACK)
3959fd8c37ecSTheodore Ts'o 		set_opt(sb, WRITEBACK_DATA);
3960ac27a0ecSDave Kleikamp 
3961617ba13bSMingming Cao 	if (le16_to_cpu(sbi->s_es->s_errors) == EXT4_ERRORS_PANIC)
3962fd8c37ecSTheodore Ts'o 		set_opt(sb, ERRORS_PANIC);
3963bb4f397aSAneesh Kumar K.V 	else if (le16_to_cpu(sbi->s_es->s_errors) == EXT4_ERRORS_CONTINUE)
3964fd8c37ecSTheodore Ts'o 		set_opt(sb, ERRORS_CONT);
3965bb4f397aSAneesh Kumar K.V 	else
3966fd8c37ecSTheodore Ts'o 		set_opt(sb, ERRORS_RO);
396745f1a9c3SDarrick J. Wong 	/* block_validity enabled by default; disable with noblock_validity */
3968fd8c37ecSTheodore Ts'o 	set_opt(sb, BLOCK_VALIDITY);
39698b67f04aSTheodore Ts'o 	if (def_mount_opts & EXT4_DEFM_DISCARD)
3970fd8c37ecSTheodore Ts'o 		set_opt(sb, DISCARD);
3971ac27a0ecSDave Kleikamp 
397208cefc7aSEric W. Biederman 	sbi->s_resuid = make_kuid(&init_user_ns, le16_to_cpu(es->s_def_resuid));
397308cefc7aSEric W. Biederman 	sbi->s_resgid = make_kgid(&init_user_ns, le16_to_cpu(es->s_def_resgid));
397430773840STheodore Ts'o 	sbi->s_commit_interval = JBD2_DEFAULT_MAX_COMMIT_AGE * HZ;
397530773840STheodore Ts'o 	sbi->s_min_batch_time = EXT4_DEF_MIN_BATCH_TIME;
397630773840STheodore Ts'o 	sbi->s_max_batch_time = EXT4_DEF_MAX_BATCH_TIME;
3977ac27a0ecSDave Kleikamp 
39788b67f04aSTheodore Ts'o 	if ((def_mount_opts & EXT4_DEFM_NOBARRIER) == 0)
3979fd8c37ecSTheodore Ts'o 		set_opt(sb, BARRIER);
3980ac27a0ecSDave Kleikamp 
39811e2462f9SMingming Cao 	/*
3982dd919b98SAneesh Kumar K.V 	 * enable delayed allocation by default
3983dd919b98SAneesh Kumar K.V 	 * Use -o nodelalloc to turn it off
3984dd919b98SAneesh Kumar K.V 	 */
3985bc0b75f7STheodore Ts'o 	if (!IS_EXT3_SB(sb) && !IS_EXT2_SB(sb) &&
39868b67f04aSTheodore Ts'o 	    ((def_mount_opts & EXT4_DEFM_NODELALLOC) == 0))
3987fd8c37ecSTheodore Ts'o 		set_opt(sb, DELALLOC);
3988dd919b98SAneesh Kumar K.V 
398951ce6511SLukas Czerner 	/*
399051ce6511SLukas Czerner 	 * set default s_li_wait_mult for lazyinit, for the case there is
399151ce6511SLukas Czerner 	 * no mount option specified.
399251ce6511SLukas Czerner 	 */
399351ce6511SLukas Czerner 	sbi->s_li_wait_mult = EXT4_DEF_LI_WAIT_MULT;
399451ce6511SLukas Czerner 
39954f97a681STheodore Ts'o 	blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size);
3996626b035bSRitesh Harjani 
3997626b035bSRitesh Harjani 	if (blocksize == PAGE_SIZE)
3998626b035bSRitesh Harjani 		set_opt(sb, DIOREAD_NOLOCK);
3999626b035bSRitesh Harjani 
40004f97a681STheodore Ts'o 	if (blocksize < EXT4_MIN_BLOCK_SIZE ||
40014f97a681STheodore Ts'o 	    blocksize > EXT4_MAX_BLOCK_SIZE) {
40024f97a681STheodore Ts'o 		ext4_msg(sb, KERN_ERR,
40034f97a681STheodore Ts'o 		       "Unsupported filesystem blocksize %d (%d log_block_size)",
40044f97a681STheodore Ts'o 			 blocksize, le32_to_cpu(es->s_log_block_size));
40054f97a681STheodore Ts'o 		goto failed_mount;
40064f97a681STheodore Ts'o 	}
40074f97a681STheodore Ts'o 
40089803387cSTheodore Ts'o 	if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV) {
40099803387cSTheodore Ts'o 		sbi->s_inode_size = EXT4_GOOD_OLD_INODE_SIZE;
40109803387cSTheodore Ts'o 		sbi->s_first_ino = EXT4_GOOD_OLD_FIRST_INO;
40119803387cSTheodore Ts'o 	} else {
40129803387cSTheodore Ts'o 		sbi->s_inode_size = le16_to_cpu(es->s_inode_size);
40139803387cSTheodore Ts'o 		sbi->s_first_ino = le32_to_cpu(es->s_first_ino);
40149803387cSTheodore Ts'o 		if (sbi->s_first_ino < EXT4_GOOD_OLD_FIRST_INO) {
40159803387cSTheodore Ts'o 			ext4_msg(sb, KERN_ERR, "invalid first ino: %u",
40169803387cSTheodore Ts'o 				 sbi->s_first_ino);
40179803387cSTheodore Ts'o 			goto failed_mount;
40189803387cSTheodore Ts'o 		}
40199803387cSTheodore Ts'o 		if ((sbi->s_inode_size < EXT4_GOOD_OLD_INODE_SIZE) ||
40209803387cSTheodore Ts'o 		    (!is_power_of_2(sbi->s_inode_size)) ||
40219803387cSTheodore Ts'o 		    (sbi->s_inode_size > blocksize)) {
40229803387cSTheodore Ts'o 			ext4_msg(sb, KERN_ERR,
40239803387cSTheodore Ts'o 			       "unsupported inode size: %d",
40249803387cSTheodore Ts'o 			       sbi->s_inode_size);
40254f97a681STheodore Ts'o 			ext4_msg(sb, KERN_ERR, "blocksize: %d", blocksize);
40269803387cSTheodore Ts'o 			goto failed_mount;
40279803387cSTheodore Ts'o 		}
40289803387cSTheodore Ts'o 		/*
40299803387cSTheodore Ts'o 		 * i_atime_extra is the last extra field available for
40309803387cSTheodore Ts'o 		 * [acm]times in struct ext4_inode. Checking for that
40319803387cSTheodore Ts'o 		 * field should suffice to ensure we have extra space
40329803387cSTheodore Ts'o 		 * for all three.
40339803387cSTheodore Ts'o 		 */
40349803387cSTheodore Ts'o 		if (sbi->s_inode_size >= offsetof(struct ext4_inode, i_atime_extra) +
40359803387cSTheodore Ts'o 			sizeof(((struct ext4_inode *)0)->i_atime_extra)) {
40369803387cSTheodore Ts'o 			sb->s_time_gran = 1;
40379803387cSTheodore Ts'o 			sb->s_time_max = EXT4_EXTRA_TIMESTAMP_MAX;
40389803387cSTheodore Ts'o 		} else {
40399803387cSTheodore Ts'o 			sb->s_time_gran = NSEC_PER_SEC;
40409803387cSTheodore Ts'o 			sb->s_time_max = EXT4_NON_EXTRA_TIMESTAMP_MAX;
40419803387cSTheodore Ts'o 		}
40429803387cSTheodore Ts'o 		sb->s_time_min = EXT4_TIMESTAMP_MIN;
40439803387cSTheodore Ts'o 	}
40449803387cSTheodore Ts'o 	if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE) {
40459803387cSTheodore Ts'o 		sbi->s_want_extra_isize = sizeof(struct ext4_inode) -
40469803387cSTheodore Ts'o 			EXT4_GOOD_OLD_INODE_SIZE;
40479803387cSTheodore Ts'o 		if (ext4_has_feature_extra_isize(sb)) {
40489803387cSTheodore Ts'o 			unsigned v, max = (sbi->s_inode_size -
40499803387cSTheodore Ts'o 					   EXT4_GOOD_OLD_INODE_SIZE);
40509803387cSTheodore Ts'o 
40519803387cSTheodore Ts'o 			v = le16_to_cpu(es->s_want_extra_isize);
40529803387cSTheodore Ts'o 			if (v > max) {
40539803387cSTheodore Ts'o 				ext4_msg(sb, KERN_ERR,
40549803387cSTheodore Ts'o 					 "bad s_want_extra_isize: %d", v);
40559803387cSTheodore Ts'o 				goto failed_mount;
40569803387cSTheodore Ts'o 			}
40579803387cSTheodore Ts'o 			if (sbi->s_want_extra_isize < v)
40589803387cSTheodore Ts'o 				sbi->s_want_extra_isize = v;
40599803387cSTheodore Ts'o 
40609803387cSTheodore Ts'o 			v = le16_to_cpu(es->s_min_extra_isize);
40619803387cSTheodore Ts'o 			if (v > max) {
40629803387cSTheodore Ts'o 				ext4_msg(sb, KERN_ERR,
40639803387cSTheodore Ts'o 					 "bad s_min_extra_isize: %d", v);
40649803387cSTheodore Ts'o 				goto failed_mount;
40659803387cSTheodore Ts'o 			}
40669803387cSTheodore Ts'o 			if (sbi->s_want_extra_isize < v)
40679803387cSTheodore Ts'o 				sbi->s_want_extra_isize = v;
40689803387cSTheodore Ts'o 		}
40699803387cSTheodore Ts'o 	}
40709803387cSTheodore Ts'o 
40715aee0f8aSTheodore Ts'o 	if (sbi->s_es->s_mount_opts[0]) {
40725aee0f8aSTheodore Ts'o 		char *s_mount_opts = kstrndup(sbi->s_es->s_mount_opts,
40735aee0f8aSTheodore Ts'o 					      sizeof(sbi->s_es->s_mount_opts),
40745aee0f8aSTheodore Ts'o 					      GFP_KERNEL);
40755aee0f8aSTheodore Ts'o 		if (!s_mount_opts)
40765aee0f8aSTheodore Ts'o 			goto failed_mount;
40775aee0f8aSTheodore Ts'o 		if (!parse_options(s_mount_opts, sb, &journal_devnum,
40785aee0f8aSTheodore Ts'o 				   &journal_ioprio, 0)) {
40798b67f04aSTheodore Ts'o 			ext4_msg(sb, KERN_WARNING,
40808b67f04aSTheodore Ts'o 				 "failed to parse options in superblock: %s",
40815aee0f8aSTheodore Ts'o 				 s_mount_opts);
40825aee0f8aSTheodore Ts'o 		}
40835aee0f8aSTheodore Ts'o 		kfree(s_mount_opts);
40848b67f04aSTheodore Ts'o 	}
40855a916be1STheodore Ts'o 	sbi->s_def_mount_opt = sbi->s_mount_opt;
4086b3881f74STheodore Ts'o 	if (!parse_options((char *) data, sb, &journal_devnum,
4087661aa520SEric Sandeen 			   &journal_ioprio, 0))
4088ac27a0ecSDave Kleikamp 		goto failed_mount;
4089ac27a0ecSDave Kleikamp 
4090c83ad55eSGabriel Krisman Bertazi #ifdef CONFIG_UNICODE
4091c83ad55eSGabriel Krisman Bertazi 	if (ext4_has_feature_casefold(sb) && !sbi->s_encoding) {
4092c83ad55eSGabriel Krisman Bertazi 		const struct ext4_sb_encodings *encoding_info;
4093c83ad55eSGabriel Krisman Bertazi 		struct unicode_map *encoding;
4094c83ad55eSGabriel Krisman Bertazi 		__u16 encoding_flags;
4095c83ad55eSGabriel Krisman Bertazi 
4096c83ad55eSGabriel Krisman Bertazi 		if (ext4_has_feature_encrypt(sb)) {
4097c83ad55eSGabriel Krisman Bertazi 			ext4_msg(sb, KERN_ERR,
4098c83ad55eSGabriel Krisman Bertazi 				 "Can't mount with encoding and encryption");
4099c83ad55eSGabriel Krisman Bertazi 			goto failed_mount;
4100c83ad55eSGabriel Krisman Bertazi 		}
4101c83ad55eSGabriel Krisman Bertazi 
4102c83ad55eSGabriel Krisman Bertazi 		if (ext4_sb_read_encoding(es, &encoding_info,
4103c83ad55eSGabriel Krisman Bertazi 					  &encoding_flags)) {
4104c83ad55eSGabriel Krisman Bertazi 			ext4_msg(sb, KERN_ERR,
4105c83ad55eSGabriel Krisman Bertazi 				 "Encoding requested by superblock is unknown");
4106c83ad55eSGabriel Krisman Bertazi 			goto failed_mount;
4107c83ad55eSGabriel Krisman Bertazi 		}
4108c83ad55eSGabriel Krisman Bertazi 
4109c83ad55eSGabriel Krisman Bertazi 		encoding = utf8_load(encoding_info->version);
4110c83ad55eSGabriel Krisman Bertazi 		if (IS_ERR(encoding)) {
4111c83ad55eSGabriel Krisman Bertazi 			ext4_msg(sb, KERN_ERR,
4112c83ad55eSGabriel Krisman Bertazi 				 "can't mount with superblock charset: %s-%s "
4113c83ad55eSGabriel Krisman Bertazi 				 "not supported by the kernel. flags: 0x%x.",
4114c83ad55eSGabriel Krisman Bertazi 				 encoding_info->name, encoding_info->version,
4115c83ad55eSGabriel Krisman Bertazi 				 encoding_flags);
4116c83ad55eSGabriel Krisman Bertazi 			goto failed_mount;
4117c83ad55eSGabriel Krisman Bertazi 		}
4118c83ad55eSGabriel Krisman Bertazi 		ext4_msg(sb, KERN_INFO,"Using encoding defined by superblock: "
4119c83ad55eSGabriel Krisman Bertazi 			 "%s-%s with flags 0x%hx", encoding_info->name,
4120c83ad55eSGabriel Krisman Bertazi 			 encoding_info->version?:"\b", encoding_flags);
4121c83ad55eSGabriel Krisman Bertazi 
4122c83ad55eSGabriel Krisman Bertazi 		sbi->s_encoding = encoding;
4123c83ad55eSGabriel Krisman Bertazi 		sbi->s_encoding_flags = encoding_flags;
4124c83ad55eSGabriel Krisman Bertazi 	}
4125c83ad55eSGabriel Krisman Bertazi #endif
4126c83ad55eSGabriel Krisman Bertazi 
412756889787STheodore Ts'o 	if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) {
4128244adf64STheodore Ts'o 		printk_once(KERN_WARNING "EXT4-fs: Warning: mounting with data=journal disables delayed allocation, dioread_nolock, and O_DIRECT support!\n");
4129781c036bSKaixu Xia 		/* can't mount with both data=journal and dioread_nolock. */
4130244adf64STheodore Ts'o 		clear_opt(sb, DIOREAD_NOLOCK);
413156889787STheodore Ts'o 		if (test_opt2(sb, EXPLICIT_DELALLOC)) {
413256889787STheodore Ts'o 			ext4_msg(sb, KERN_ERR, "can't mount with "
413356889787STheodore Ts'o 				 "both data=journal and delalloc");
413456889787STheodore Ts'o 			goto failed_mount;
413556889787STheodore Ts'o 		}
4136fc626fe3SIra Weiny 		if (test_opt(sb, DAX_ALWAYS)) {
4137923ae0ffSRoss Zwisler 			ext4_msg(sb, KERN_ERR, "can't mount with "
4138923ae0ffSRoss Zwisler 				 "both data=journal and dax");
4139923ae0ffSRoss Zwisler 			goto failed_mount;
4140923ae0ffSRoss Zwisler 		}
414173b92a2aSSergey Karamov 		if (ext4_has_feature_encrypt(sb)) {
414273b92a2aSSergey Karamov 			ext4_msg(sb, KERN_WARNING,
414373b92a2aSSergey Karamov 				 "encrypted files will use data=ordered "
414473b92a2aSSergey Karamov 				 "instead of data journaling mode");
414573b92a2aSSergey Karamov 		}
414656889787STheodore Ts'o 		if (test_opt(sb, DELALLOC))
414756889787STheodore Ts'o 			clear_opt(sb, DELALLOC);
4148001e4a87STejun Heo 	} else {
4149001e4a87STejun Heo 		sb->s_iflags |= SB_I_CGROUPWB;
415056889787STheodore Ts'o 	}
415156889787STheodore Ts'o 
41521751e8a6SLinus Torvalds 	sb->s_flags = (sb->s_flags & ~SB_POSIXACL) |
41531751e8a6SLinus Torvalds 		(test_opt(sb, POSIX_ACL) ? SB_POSIXACL : 0);
4154ac27a0ecSDave Kleikamp 
4155617ba13bSMingming Cao 	if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV &&
4156e2b911c5SDarrick J. Wong 	    (ext4_has_compat_features(sb) ||
4157e2b911c5SDarrick J. Wong 	     ext4_has_ro_compat_features(sb) ||
4158e2b911c5SDarrick J. Wong 	     ext4_has_incompat_features(sb)))
4159b31e1552SEric Sandeen 		ext4_msg(sb, KERN_WARNING,
4160b31e1552SEric Sandeen 		       "feature flags set on rev 0 fs, "
4161b31e1552SEric Sandeen 		       "running e2fsck is recommended");
4162469108ffSTheodore Tso 
4163ed3654ebSTheodore Ts'o 	if (es->s_creator_os == cpu_to_le32(EXT4_OS_HURD)) {
4164ed3654ebSTheodore Ts'o 		set_opt2(sb, HURD_COMPAT);
4165e2b911c5SDarrick J. Wong 		if (ext4_has_feature_64bit(sb)) {
4166ed3654ebSTheodore Ts'o 			ext4_msg(sb, KERN_ERR,
4167ed3654ebSTheodore Ts'o 				 "The Hurd can't support 64-bit file systems");
4168ed3654ebSTheodore Ts'o 			goto failed_mount;
4169ed3654ebSTheodore Ts'o 		}
4170dec214d0STahsin Erdogan 
4171dec214d0STahsin Erdogan 		/*
4172dec214d0STahsin Erdogan 		 * ea_inode feature uses l_i_version field which is not
4173dec214d0STahsin Erdogan 		 * available in HURD_COMPAT mode.
4174dec214d0STahsin Erdogan 		 */
4175dec214d0STahsin Erdogan 		if (ext4_has_feature_ea_inode(sb)) {
4176dec214d0STahsin Erdogan 			ext4_msg(sb, KERN_ERR,
4177dec214d0STahsin Erdogan 				 "ea_inode feature is not supported for Hurd");
4178dec214d0STahsin Erdogan 			goto failed_mount;
4179dec214d0STahsin Erdogan 		}
4180ed3654ebSTheodore Ts'o 	}
4181ed3654ebSTheodore Ts'o 
41822035e776STheodore Ts'o 	if (IS_EXT2_SB(sb)) {
41832035e776STheodore Ts'o 		if (ext2_feature_set_ok(sb))
41842035e776STheodore Ts'o 			ext4_msg(sb, KERN_INFO, "mounting ext2 file system "
41852035e776STheodore Ts'o 				 "using the ext4 subsystem");
41862035e776STheodore Ts'o 		else {
41870d9366d6SEric Sandeen 			/*
41880d9366d6SEric Sandeen 			 * If we're probing be silent, if this looks like
41890d9366d6SEric Sandeen 			 * it's actually an ext[34] filesystem.
41900d9366d6SEric Sandeen 			 */
41910d9366d6SEric Sandeen 			if (silent && ext4_feature_set_ok(sb, sb_rdonly(sb)))
41920d9366d6SEric Sandeen 				goto failed_mount;
41932035e776STheodore Ts'o 			ext4_msg(sb, KERN_ERR, "couldn't mount as ext2 due "
41942035e776STheodore Ts'o 				 "to feature incompatibilities");
41952035e776STheodore Ts'o 			goto failed_mount;
41962035e776STheodore Ts'o 		}
41972035e776STheodore Ts'o 	}
41982035e776STheodore Ts'o 
41992035e776STheodore Ts'o 	if (IS_EXT3_SB(sb)) {
42002035e776STheodore Ts'o 		if (ext3_feature_set_ok(sb))
42012035e776STheodore Ts'o 			ext4_msg(sb, KERN_INFO, "mounting ext3 file system "
42022035e776STheodore Ts'o 				 "using the ext4 subsystem");
42032035e776STheodore Ts'o 		else {
42040d9366d6SEric Sandeen 			/*
42050d9366d6SEric Sandeen 			 * If we're probing be silent, if this looks like
42060d9366d6SEric Sandeen 			 * it's actually an ext4 filesystem.
42070d9366d6SEric Sandeen 			 */
42080d9366d6SEric Sandeen 			if (silent && ext4_feature_set_ok(sb, sb_rdonly(sb)))
42090d9366d6SEric Sandeen 				goto failed_mount;
42102035e776STheodore Ts'o 			ext4_msg(sb, KERN_ERR, "couldn't mount as ext3 due "
42112035e776STheodore Ts'o 				 "to feature incompatibilities");
42122035e776STheodore Ts'o 			goto failed_mount;
42132035e776STheodore Ts'o 		}
42142035e776STheodore Ts'o 	}
42152035e776STheodore Ts'o 
4216469108ffSTheodore Tso 	/*
4217ac27a0ecSDave Kleikamp 	 * Check feature flags regardless of the revision level, since we
4218ac27a0ecSDave Kleikamp 	 * previously didn't change the revision level when setting the flags,
4219ac27a0ecSDave Kleikamp 	 * so there is a chance incompat flags are set on a rev 0 filesystem.
4220ac27a0ecSDave Kleikamp 	 */
4221bc98a42cSDavid Howells 	if (!ext4_feature_set_ok(sb, (sb_rdonly(sb))))
4222ac27a0ecSDave Kleikamp 		goto failed_mount;
4223a13fb1a4SEric Sandeen 
42248cdf3372STheodore Ts'o 	if (le32_to_cpu(es->s_log_block_size) >
42258cdf3372STheodore Ts'o 	    (EXT4_MAX_BLOCK_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) {
42268cdf3372STheodore Ts'o 		ext4_msg(sb, KERN_ERR,
42278cdf3372STheodore Ts'o 			 "Invalid log block size: %u",
42288cdf3372STheodore Ts'o 			 le32_to_cpu(es->s_log_block_size));
4229ac27a0ecSDave Kleikamp 		goto failed_mount;
4230ac27a0ecSDave Kleikamp 	}
4231bfe0a5f4STheodore Ts'o 	if (le32_to_cpu(es->s_log_cluster_size) >
4232bfe0a5f4STheodore Ts'o 	    (EXT4_MAX_CLUSTER_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) {
4233bfe0a5f4STheodore Ts'o 		ext4_msg(sb, KERN_ERR,
4234bfe0a5f4STheodore Ts'o 			 "Invalid log cluster size: %u",
4235bfe0a5f4STheodore Ts'o 			 le32_to_cpu(es->s_log_cluster_size));
4236bfe0a5f4STheodore Ts'o 		goto failed_mount;
4237bfe0a5f4STheodore Ts'o 	}
4238ac27a0ecSDave Kleikamp 
42395b9554dcSTheodore Ts'o 	if (le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) > (blocksize / 4)) {
42405b9554dcSTheodore Ts'o 		ext4_msg(sb, KERN_ERR,
42415b9554dcSTheodore Ts'o 			 "Number of reserved GDT blocks insanely large: %d",
42425b9554dcSTheodore Ts'o 			 le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks));
42435b9554dcSTheodore Ts'o 		goto failed_mount;
42445b9554dcSTheodore Ts'o 	}
42455b9554dcSTheodore Ts'o 
4246a8ab6d38SIra Weiny 	if (bdev_dax_supported(sb->s_bdev, blocksize))
4247a8ab6d38SIra Weiny 		set_bit(EXT4_FLAGS_BDEV_IS_DAX, &sbi->s_ext4_flags);
4248a8ab6d38SIra Weiny 
4249fc626fe3SIra Weiny 	if (sbi->s_mount_opt & EXT4_MOUNT_DAX_ALWAYS) {
4250559db4c6SRoss Zwisler 		if (ext4_has_feature_inline_data(sb)) {
4251559db4c6SRoss Zwisler 			ext4_msg(sb, KERN_ERR, "Cannot use DAX on a filesystem"
4252559db4c6SRoss Zwisler 					" that may contain inline data");
4253361d24d4SEric Sandeen 			goto failed_mount;
4254559db4c6SRoss Zwisler 		}
4255a8ab6d38SIra Weiny 		if (!test_bit(EXT4_FLAGS_BDEV_IS_DAX, &sbi->s_ext4_flags)) {
425624f3478dSDan Williams 			ext4_msg(sb, KERN_ERR,
4257361d24d4SEric Sandeen 				"DAX unsupported by block device.");
4258361d24d4SEric Sandeen 			goto failed_mount;
425924f3478dSDan Williams 		}
4260923ae0ffSRoss Zwisler 	}
4261923ae0ffSRoss Zwisler 
4262e2b911c5SDarrick J. Wong 	if (ext4_has_feature_encrypt(sb) && es->s_encryption_level) {
42636ddb2447STheodore Ts'o 		ext4_msg(sb, KERN_ERR, "Unsupported encryption level %d",
42646ddb2447STheodore Ts'o 			 es->s_encryption_level);
42656ddb2447STheodore Ts'o 		goto failed_mount;
42666ddb2447STheodore Ts'o 	}
42676ddb2447STheodore Ts'o 
4268ac27a0ecSDave Kleikamp 	if (sb->s_blocksize != blocksize) {
4269ce40733cSAneesh Kumar K.V 		/* Validate the filesystem blocksize */
4270ce40733cSAneesh Kumar K.V 		if (!sb_set_blocksize(sb, blocksize)) {
4271b31e1552SEric Sandeen 			ext4_msg(sb, KERN_ERR, "bad block size %d",
4272ce40733cSAneesh Kumar K.V 					blocksize);
4273ac27a0ecSDave Kleikamp 			goto failed_mount;
4274ac27a0ecSDave Kleikamp 		}
4275ac27a0ecSDave Kleikamp 
4276ac27a0ecSDave Kleikamp 		brelse(bh);
427770bbb3e0SAndrew Morton 		logical_sb_block = sb_block * EXT4_MIN_BLOCK_SIZE;
427870bbb3e0SAndrew Morton 		offset = do_div(logical_sb_block, blocksize);
4279a8ac900bSGioh Kim 		bh = sb_bread_unmovable(sb, logical_sb_block);
4280ac27a0ecSDave Kleikamp 		if (!bh) {
4281b31e1552SEric Sandeen 			ext4_msg(sb, KERN_ERR,
4282b31e1552SEric Sandeen 			       "Can't read superblock on 2nd try");
4283ac27a0ecSDave Kleikamp 			goto failed_mount;
4284ac27a0ecSDave Kleikamp 		}
42852716b802STheodore Ts'o 		es = (struct ext4_super_block *)(bh->b_data + offset);
4286ac27a0ecSDave Kleikamp 		sbi->s_es = es;
4287617ba13bSMingming Cao 		if (es->s_magic != cpu_to_le16(EXT4_SUPER_MAGIC)) {
4288b31e1552SEric Sandeen 			ext4_msg(sb, KERN_ERR,
4289b31e1552SEric Sandeen 			       "Magic mismatch, very weird!");
4290ac27a0ecSDave Kleikamp 			goto failed_mount;
4291ac27a0ecSDave Kleikamp 		}
4292ac27a0ecSDave Kleikamp 	}
4293ac27a0ecSDave Kleikamp 
4294e2b911c5SDarrick J. Wong 	has_huge_files = ext4_has_feature_huge_file(sb);
4295f287a1a5STheodore Ts'o 	sbi->s_bitmap_maxbytes = ext4_max_bitmap_size(sb->s_blocksize_bits,
4296f287a1a5STheodore Ts'o 						      has_huge_files);
4297f287a1a5STheodore Ts'o 	sb->s_maxbytes = ext4_max_size(sb->s_blocksize_bits, has_huge_files);
4298ac27a0ecSDave Kleikamp 
42990d1ee42fSAlexandre Ratchov 	sbi->s_desc_size = le16_to_cpu(es->s_desc_size);
4300e2b911c5SDarrick J. Wong 	if (ext4_has_feature_64bit(sb)) {
43018fadc143SAlexandre Ratchov 		if (sbi->s_desc_size < EXT4_MIN_DESC_SIZE_64BIT ||
43020d1ee42fSAlexandre Ratchov 		    sbi->s_desc_size > EXT4_MAX_DESC_SIZE ||
4303d8ea6cf8Svignesh babu 		    !is_power_of_2(sbi->s_desc_size)) {
4304b31e1552SEric Sandeen 			ext4_msg(sb, KERN_ERR,
4305b31e1552SEric Sandeen 			       "unsupported descriptor size %lu",
43060d1ee42fSAlexandre Ratchov 			       sbi->s_desc_size);
43070d1ee42fSAlexandre Ratchov 			goto failed_mount;
43080d1ee42fSAlexandre Ratchov 		}
43090d1ee42fSAlexandre Ratchov 	} else
43100d1ee42fSAlexandre Ratchov 		sbi->s_desc_size = EXT4_MIN_DESC_SIZE;
43110b8e58a1SAndreas Dilger 
4312ac27a0ecSDave Kleikamp 	sbi->s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group);
4313ac27a0ecSDave Kleikamp 	sbi->s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group);
43140b8e58a1SAndreas Dilger 
4315617ba13bSMingming Cao 	sbi->s_inodes_per_block = blocksize / EXT4_INODE_SIZE(sb);
4316ac27a0ecSDave Kleikamp 	if (sbi->s_inodes_per_block == 0)
4317617ba13bSMingming Cao 		goto cantfind_ext4;
4318cd6bb35bSTheodore Ts'o 	if (sbi->s_inodes_per_group < sbi->s_inodes_per_block ||
4319cd6bb35bSTheodore Ts'o 	    sbi->s_inodes_per_group > blocksize * 8) {
4320cd6bb35bSTheodore Ts'o 		ext4_msg(sb, KERN_ERR, "invalid inodes per group: %lu\n",
4321b9c538daSJosh Triplett 			 sbi->s_inodes_per_group);
4322cd6bb35bSTheodore Ts'o 		goto failed_mount;
4323cd6bb35bSTheodore Ts'o 	}
4324ac27a0ecSDave Kleikamp 	sbi->s_itb_per_group = sbi->s_inodes_per_group /
4325ac27a0ecSDave Kleikamp 					sbi->s_inodes_per_block;
43260d1ee42fSAlexandre Ratchov 	sbi->s_desc_per_block = blocksize / EXT4_DESC_SIZE(sb);
4327ac27a0ecSDave Kleikamp 	sbi->s_sbh = bh;
4328ac27a0ecSDave Kleikamp 	sbi->s_mount_state = le16_to_cpu(es->s_state);
4329e57aa839SFengguang Wu 	sbi->s_addr_per_block_bits = ilog2(EXT4_ADDR_PER_BLOCK(sb));
4330e57aa839SFengguang Wu 	sbi->s_desc_per_block_bits = ilog2(EXT4_DESC_PER_BLOCK(sb));
43310b8e58a1SAndreas Dilger 
4332ac27a0ecSDave Kleikamp 	for (i = 0; i < 4; i++)
4333ac27a0ecSDave Kleikamp 		sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);
4334ac27a0ecSDave Kleikamp 	sbi->s_def_hash_version = es->s_def_hash_version;
4335e2b911c5SDarrick J. Wong 	if (ext4_has_feature_dir_index(sb)) {
4336f99b2589STheodore Ts'o 		i = le32_to_cpu(es->s_flags);
4337f99b2589STheodore Ts'o 		if (i & EXT2_FLAGS_UNSIGNED_HASH)
4338f99b2589STheodore Ts'o 			sbi->s_hash_unsigned = 3;
4339f99b2589STheodore Ts'o 		else if ((i & EXT2_FLAGS_SIGNED_HASH) == 0) {
4340f99b2589STheodore Ts'o #ifdef __CHAR_UNSIGNED__
4341bc98a42cSDavid Howells 			if (!sb_rdonly(sb))
434223301410STheodore Ts'o 				es->s_flags |=
434323301410STheodore Ts'o 					cpu_to_le32(EXT2_FLAGS_UNSIGNED_HASH);
4344f99b2589STheodore Ts'o 			sbi->s_hash_unsigned = 3;
4345f99b2589STheodore Ts'o #else
4346bc98a42cSDavid Howells 			if (!sb_rdonly(sb))
434723301410STheodore Ts'o 				es->s_flags |=
434823301410STheodore Ts'o 					cpu_to_le32(EXT2_FLAGS_SIGNED_HASH);
4349f99b2589STheodore Ts'o #endif
4350f99b2589STheodore Ts'o 		}
435123301410STheodore Ts'o 	}
4352ac27a0ecSDave Kleikamp 
4353281b5995STheodore Ts'o 	/* Handle clustersize */
4354281b5995STheodore Ts'o 	clustersize = BLOCK_SIZE << le32_to_cpu(es->s_log_cluster_size);
4355ef5fd681SKaixu Xia 	if (ext4_has_feature_bigalloc(sb)) {
4356281b5995STheodore Ts'o 		if (clustersize < blocksize) {
4357281b5995STheodore Ts'o 			ext4_msg(sb, KERN_ERR,
4358281b5995STheodore Ts'o 				 "cluster size (%d) smaller than "
4359281b5995STheodore Ts'o 				 "block size (%d)", clustersize, blocksize);
4360281b5995STheodore Ts'o 			goto failed_mount;
4361281b5995STheodore Ts'o 		}
4362281b5995STheodore Ts'o 		sbi->s_cluster_bits = le32_to_cpu(es->s_log_cluster_size) -
4363281b5995STheodore Ts'o 			le32_to_cpu(es->s_log_block_size);
4364281b5995STheodore Ts'o 		sbi->s_clusters_per_group =
4365281b5995STheodore Ts'o 			le32_to_cpu(es->s_clusters_per_group);
4366281b5995STheodore Ts'o 		if (sbi->s_clusters_per_group > blocksize * 8) {
4367281b5995STheodore Ts'o 			ext4_msg(sb, KERN_ERR,
4368281b5995STheodore Ts'o 				 "#clusters per group too big: %lu",
4369281b5995STheodore Ts'o 				 sbi->s_clusters_per_group);
4370281b5995STheodore Ts'o 			goto failed_mount;
4371281b5995STheodore Ts'o 		}
4372281b5995STheodore Ts'o 		if (sbi->s_blocks_per_group !=
4373281b5995STheodore Ts'o 		    (sbi->s_clusters_per_group * (clustersize / blocksize))) {
4374281b5995STheodore Ts'o 			ext4_msg(sb, KERN_ERR, "blocks per group (%lu) and "
4375281b5995STheodore Ts'o 				 "clusters per group (%lu) inconsistent",
4376281b5995STheodore Ts'o 				 sbi->s_blocks_per_group,
4377281b5995STheodore Ts'o 				 sbi->s_clusters_per_group);
4378281b5995STheodore Ts'o 			goto failed_mount;
4379281b5995STheodore Ts'o 		}
4380281b5995STheodore Ts'o 	} else {
4381281b5995STheodore Ts'o 		if (clustersize != blocksize) {
4382bfe0a5f4STheodore Ts'o 			ext4_msg(sb, KERN_ERR,
4383bfe0a5f4STheodore Ts'o 				 "fragment/cluster size (%d) != "
4384bfe0a5f4STheodore Ts'o 				 "block size (%d)", clustersize, blocksize);
4385bfe0a5f4STheodore Ts'o 			goto failed_mount;
4386281b5995STheodore Ts'o 		}
4387ac27a0ecSDave Kleikamp 		if (sbi->s_blocks_per_group > blocksize * 8) {
4388b31e1552SEric Sandeen 			ext4_msg(sb, KERN_ERR,
4389b31e1552SEric Sandeen 				 "#blocks per group too big: %lu",
4390ac27a0ecSDave Kleikamp 				 sbi->s_blocks_per_group);
4391ac27a0ecSDave Kleikamp 			goto failed_mount;
4392ac27a0ecSDave Kleikamp 		}
4393281b5995STheodore Ts'o 		sbi->s_clusters_per_group = sbi->s_blocks_per_group;
4394281b5995STheodore Ts'o 		sbi->s_cluster_bits = 0;
4395281b5995STheodore Ts'o 	}
4396281b5995STheodore Ts'o 	sbi->s_cluster_ratio = clustersize / blocksize;
4397281b5995STheodore Ts'o 
4398960fd856STheodore Ts'o 	/* Do we have standard group size of clustersize * 8 blocks ? */
4399960fd856STheodore Ts'o 	if (sbi->s_blocks_per_group == clustersize << 3)
4400960fd856STheodore Ts'o 		set_opt2(sb, STD_GROUP_SIZE);
4401960fd856STheodore Ts'o 
4402bf43d84bSEric Sandeen 	/*
4403bf43d84bSEric Sandeen 	 * Test whether we have more sectors than will fit in sector_t,
4404bf43d84bSEric Sandeen 	 * and whether the max offset is addressable by the page cache.
4405bf43d84bSEric Sandeen 	 */
44065a9ae68aSDarrick J. Wong 	err = generic_check_addressable(sb->s_blocksize_bits,
440730ca22c7SPatrick J. LoPresti 					ext4_blocks_count(es));
44085a9ae68aSDarrick J. Wong 	if (err) {
4409b31e1552SEric Sandeen 		ext4_msg(sb, KERN_ERR, "filesystem"
4410bf43d84bSEric Sandeen 			 " too large to mount safely on this system");
4411ac27a0ecSDave Kleikamp 		goto failed_mount;
4412ac27a0ecSDave Kleikamp 	}
4413ac27a0ecSDave Kleikamp 
4414617ba13bSMingming Cao 	if (EXT4_BLOCKS_PER_GROUP(sb) == 0)
4415617ba13bSMingming Cao 		goto cantfind_ext4;
4416e7c95593SEric Sandeen 
44170f2ddca6SFrom: Thiemo Nagel 	/* check blocks count against device size */
44180f2ddca6SFrom: Thiemo Nagel 	blocks_count = sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits;
44190f2ddca6SFrom: Thiemo Nagel 	if (blocks_count && ext4_blocks_count(es) > blocks_count) {
4420b31e1552SEric Sandeen 		ext4_msg(sb, KERN_WARNING, "bad geometry: block count %llu "
4421b31e1552SEric Sandeen 		       "exceeds size of device (%llu blocks)",
44220f2ddca6SFrom: Thiemo Nagel 		       ext4_blocks_count(es), blocks_count);
44230f2ddca6SFrom: Thiemo Nagel 		goto failed_mount;
44240f2ddca6SFrom: Thiemo Nagel 	}
44250f2ddca6SFrom: Thiemo Nagel 
44264ec11028STheodore Ts'o 	/*
44274ec11028STheodore Ts'o 	 * It makes no sense for the first data block to be beyond the end
44284ec11028STheodore Ts'o 	 * of the filesystem.
44294ec11028STheodore Ts'o 	 */
44304ec11028STheodore Ts'o 	if (le32_to_cpu(es->s_first_data_block) >= ext4_blocks_count(es)) {
4431b31e1552SEric Sandeen 		ext4_msg(sb, KERN_WARNING, "bad geometry: first data "
4432b31e1552SEric Sandeen 			 "block %u is beyond end of filesystem (%llu)",
4433e7c95593SEric Sandeen 			 le32_to_cpu(es->s_first_data_block),
44344ec11028STheodore Ts'o 			 ext4_blocks_count(es));
4435e7c95593SEric Sandeen 		goto failed_mount;
4436e7c95593SEric Sandeen 	}
4437bfe0a5f4STheodore Ts'o 	if ((es->s_first_data_block == 0) && (es->s_log_block_size == 0) &&
4438bfe0a5f4STheodore Ts'o 	    (sbi->s_cluster_ratio == 1)) {
4439bfe0a5f4STheodore Ts'o 		ext4_msg(sb, KERN_WARNING, "bad geometry: first data "
4440bfe0a5f4STheodore Ts'o 			 "block is 0 with a 1k block and cluster size");
4441bfe0a5f4STheodore Ts'o 		goto failed_mount;
4442bfe0a5f4STheodore Ts'o 	}
4443bfe0a5f4STheodore Ts'o 
4444bd81d8eeSLaurent Vivier 	blocks_count = (ext4_blocks_count(es) -
4445bd81d8eeSLaurent Vivier 			le32_to_cpu(es->s_first_data_block) +
4446bd81d8eeSLaurent Vivier 			EXT4_BLOCKS_PER_GROUP(sb) - 1);
4447bd81d8eeSLaurent Vivier 	do_div(blocks_count, EXT4_BLOCKS_PER_GROUP(sb));
44484ec11028STheodore Ts'o 	if (blocks_count > ((uint64_t)1<<32) - EXT4_DESC_PER_BLOCK(sb)) {
4449df41460aSJosh Triplett 		ext4_msg(sb, KERN_WARNING, "groups count too large: %llu "
44504ec11028STheodore Ts'o 		       "(block count %llu, first data block %u, "
4451df41460aSJosh Triplett 		       "blocks per group %lu)", blocks_count,
44524ec11028STheodore Ts'o 		       ext4_blocks_count(es),
44534ec11028STheodore Ts'o 		       le32_to_cpu(es->s_first_data_block),
44544ec11028STheodore Ts'o 		       EXT4_BLOCKS_PER_GROUP(sb));
44554ec11028STheodore Ts'o 		goto failed_mount;
44564ec11028STheodore Ts'o 	}
4457bd81d8eeSLaurent Vivier 	sbi->s_groups_count = blocks_count;
4458fb0a387dSEric Sandeen 	sbi->s_blockfile_groups = min_t(ext4_group_t, sbi->s_groups_count,
4459fb0a387dSEric Sandeen 			(EXT4_MAX_BLOCK_FILE_PHYS / EXT4_BLOCKS_PER_GROUP(sb)));
44609e463084STheodore Ts'o 	if (((u64)sbi->s_groups_count * sbi->s_inodes_per_group) !=
44619e463084STheodore Ts'o 	    le32_to_cpu(es->s_inodes_count)) {
44629e463084STheodore Ts'o 		ext4_msg(sb, KERN_ERR, "inodes count not valid: %u vs %llu",
44639e463084STheodore Ts'o 			 le32_to_cpu(es->s_inodes_count),
44649e463084STheodore Ts'o 			 ((u64)sbi->s_groups_count * sbi->s_inodes_per_group));
44659e463084STheodore Ts'o 		ret = -EINVAL;
44669e463084STheodore Ts'o 		goto failed_mount;
44679e463084STheodore Ts'o 	}
4468617ba13bSMingming Cao 	db_count = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) /
4469617ba13bSMingming Cao 		   EXT4_DESC_PER_BLOCK(sb);
44703a4b77cdSEryu Guan 	if (ext4_has_feature_meta_bg(sb)) {
44712ba3e6e8STheodore Ts'o 		if (le32_to_cpu(es->s_first_meta_bg) > db_count) {
44723a4b77cdSEryu Guan 			ext4_msg(sb, KERN_WARNING,
44733a4b77cdSEryu Guan 				 "first meta block group too large: %u "
44743a4b77cdSEryu Guan 				 "(group descriptor block count %u)",
44753a4b77cdSEryu Guan 				 le32_to_cpu(es->s_first_meta_bg), db_count);
44763a4b77cdSEryu Guan 			goto failed_mount;
44773a4b77cdSEryu Guan 		}
44783a4b77cdSEryu Guan 	}
44791d0c3924STheodore Ts'o 	rcu_assign_pointer(sbi->s_group_desc,
44801d0c3924STheodore Ts'o 			   kvmalloc_array(db_count,
4481f18a5f21STheodore Ts'o 					  sizeof(struct buffer_head *),
44821d0c3924STheodore Ts'o 					  GFP_KERNEL));
4483ac27a0ecSDave Kleikamp 	if (sbi->s_group_desc == NULL) {
4484b31e1552SEric Sandeen 		ext4_msg(sb, KERN_ERR, "not enough memory");
44852cde417dSTheodore Ts'o 		ret = -ENOMEM;
4486ac27a0ecSDave Kleikamp 		goto failed_mount;
4487ac27a0ecSDave Kleikamp 	}
4488ac27a0ecSDave Kleikamp 
4489705895b6SPekka Enberg 	bgl_lock_init(sbi->s_blockgroup_lock);
4490ac27a0ecSDave Kleikamp 
449185c8f176SAndrew Perepechko 	/* Pre-read the descriptors into the buffer cache */
449285c8f176SAndrew Perepechko 	for (i = 0; i < db_count; i++) {
449385c8f176SAndrew Perepechko 		block = descriptor_loc(sb, logical_sb_block, i);
4494d87f6392SRoman Gushchin 		sb_breadahead_unmovable(sb, block);
449585c8f176SAndrew Perepechko 	}
449685c8f176SAndrew Perepechko 
4497ac27a0ecSDave Kleikamp 	for (i = 0; i < db_count; i++) {
44981d0c3924STheodore Ts'o 		struct buffer_head *bh;
44991d0c3924STheodore Ts'o 
450070bbb3e0SAndrew Morton 		block = descriptor_loc(sb, logical_sb_block, i);
45011d0c3924STheodore Ts'o 		bh = sb_bread_unmovable(sb, block);
45021d0c3924STheodore Ts'o 		if (!bh) {
4503b31e1552SEric Sandeen 			ext4_msg(sb, KERN_ERR,
4504b31e1552SEric Sandeen 			       "can't read group descriptor %d", i);
4505ac27a0ecSDave Kleikamp 			db_count = i;
4506ac27a0ecSDave Kleikamp 			goto failed_mount2;
4507ac27a0ecSDave Kleikamp 		}
45081d0c3924STheodore Ts'o 		rcu_read_lock();
45091d0c3924STheodore Ts'o 		rcu_dereference(sbi->s_group_desc)[i] = bh;
45101d0c3924STheodore Ts'o 		rcu_read_unlock();
4511ac27a0ecSDave Kleikamp 	}
451244de022cSTheodore Ts'o 	sbi->s_gdb_count = db_count;
4513829fa70dSTheodore Ts'o 	if (!ext4_check_descriptors(sb, logical_sb_block, &first_not_zeroed)) {
4514b31e1552SEric Sandeen 		ext4_msg(sb, KERN_ERR, "group descriptors corrupted!");
45156a797d27SDarrick J. Wong 		ret = -EFSCORRUPTED;
4516f9ae9cf5STheodore Ts'o 		goto failed_mount2;
4517ac27a0ecSDave Kleikamp 	}
4518772cb7c8SJose R. Santos 
4519235699a8SKees Cook 	timer_setup(&sbi->s_err_report, print_daily_error_info, 0);
452004496411STao Ma 
4521a75ae78fSDmitry Monakhov 	/* Register extent status tree shrinker */
4522eb68d0e2SZheng Liu 	if (ext4_es_register_shrinker(sbi))
4523ce7e010aSTheodore Ts'o 		goto failed_mount3;
4524ce7e010aSTheodore Ts'o 
4525c9de560dSAlex Tomas 	sbi->s_stripe = ext4_get_stripe_size(sbi);
452667a5da56SZheng Liu 	sbi->s_extent_max_zeroout_kb = 32;
4527c9de560dSAlex Tomas 
4528f9ae9cf5STheodore Ts'o 	/*
4529f9ae9cf5STheodore Ts'o 	 * set up enough so that it can read an inode
4530f9ae9cf5STheodore Ts'o 	 */
4531f9ae9cf5STheodore Ts'o 	sb->s_op = &ext4_sops;
4532617ba13bSMingming Cao 	sb->s_export_op = &ext4_export_ops;
4533617ba13bSMingming Cao 	sb->s_xattr = ext4_xattr_handlers;
4534643fa961SChandan Rajendra #ifdef CONFIG_FS_ENCRYPTION
4535a7550b30SJaegeuk Kim 	sb->s_cop = &ext4_cryptops;
4536ffcc4182SEric Biggers #endif
4537c93d8f88SEric Biggers #ifdef CONFIG_FS_VERITY
4538c93d8f88SEric Biggers 	sb->s_vop = &ext4_verityops;
4539c93d8f88SEric Biggers #endif
4540ac27a0ecSDave Kleikamp #ifdef CONFIG_QUOTA
4541617ba13bSMingming Cao 	sb->dq_op = &ext4_quota_operations;
4542e2b911c5SDarrick J. Wong 	if (ext4_has_feature_quota(sb))
45431fa5efe3SJan Kara 		sb->s_qcop = &dquot_quotactl_sysfile_ops;
4544262b4662SJan Kara 	else
4545262b4662SJan Kara 		sb->s_qcop = &ext4_qctl_operations;
4546689c958cSLi Xi 	sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP | QTYPE_MASK_PRJ;
4547ac27a0ecSDave Kleikamp #endif
454885787090SChristoph Hellwig 	memcpy(&sb->s_uuid, es->s_uuid, sizeof(es->s_uuid));
4549f2fa2ffcSAneesh Kumar K.V 
4550ac27a0ecSDave Kleikamp 	INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */
45513b9d4ed2STheodore Ts'o 	mutex_init(&sbi->s_orphan_lock);
4552ac27a0ecSDave Kleikamp 
4553ac27a0ecSDave Kleikamp 	sb->s_root = NULL;
4554ac27a0ecSDave Kleikamp 
4555ac27a0ecSDave Kleikamp 	needs_recovery = (es->s_last_orphan != 0 ||
4556e2b911c5SDarrick J. Wong 			  ext4_has_feature_journal_needs_recovery(sb));
4557ac27a0ecSDave Kleikamp 
4558bc98a42cSDavid Howells 	if (ext4_has_feature_mmp(sb) && !sb_rdonly(sb))
4559c5e06d10SJohann Lombardi 		if (ext4_multi_mount_protect(sb, le64_to_cpu(es->s_mmp_block)))
456050460fe8SDarrick J. Wong 			goto failed_mount3a;
4561c5e06d10SJohann Lombardi 
4562ac27a0ecSDave Kleikamp 	/*
4563ac27a0ecSDave Kleikamp 	 * The first inode we look at is the journal inode.  Don't try
4564ac27a0ecSDave Kleikamp 	 * root first: it may be modified in the journal!
4565ac27a0ecSDave Kleikamp 	 */
4566e2b911c5SDarrick J. Wong 	if (!test_opt(sb, NOLOAD) && ext4_has_feature_journal(sb)) {
45674753d8a2STheodore Ts'o 		err = ext4_load_journal(sb, es, journal_devnum);
45684753d8a2STheodore Ts'o 		if (err)
456950460fe8SDarrick J. Wong 			goto failed_mount3a;
4570bc98a42cSDavid Howells 	} else if (test_opt(sb, NOLOAD) && !sb_rdonly(sb) &&
4571e2b911c5SDarrick J. Wong 		   ext4_has_feature_journal_needs_recovery(sb)) {
4572b31e1552SEric Sandeen 		ext4_msg(sb, KERN_ERR, "required journal recovery "
4573b31e1552SEric Sandeen 		       "suppressed and not mounted read-only");
4574744692dcSJiaying Zhang 		goto failed_mount_wq;
4575ac27a0ecSDave Kleikamp 	} else {
45761e381f60SDmitry Monakhov 		/* Nojournal mode, all journal mount options are illegal */
45771e381f60SDmitry Monakhov 		if (test_opt2(sb, EXPLICIT_JOURNAL_CHECKSUM)) {
45781e381f60SDmitry Monakhov 			ext4_msg(sb, KERN_ERR, "can't mount with "
45791e381f60SDmitry Monakhov 				 "journal_checksum, fs mounted w/o journal");
45801e381f60SDmitry Monakhov 			goto failed_mount_wq;
45811e381f60SDmitry Monakhov 		}
45821e381f60SDmitry Monakhov 		if (test_opt(sb, JOURNAL_ASYNC_COMMIT)) {
45831e381f60SDmitry Monakhov 			ext4_msg(sb, KERN_ERR, "can't mount with "
45841e381f60SDmitry Monakhov 				 "journal_async_commit, fs mounted w/o journal");
45851e381f60SDmitry Monakhov 			goto failed_mount_wq;
45861e381f60SDmitry Monakhov 		}
45871e381f60SDmitry Monakhov 		if (sbi->s_commit_interval != JBD2_DEFAULT_MAX_COMMIT_AGE*HZ) {
45881e381f60SDmitry Monakhov 			ext4_msg(sb, KERN_ERR, "can't mount with "
45891e381f60SDmitry Monakhov 				 "commit=%lu, fs mounted w/o journal",
45901e381f60SDmitry Monakhov 				 sbi->s_commit_interval / HZ);
45911e381f60SDmitry Monakhov 			goto failed_mount_wq;
45921e381f60SDmitry Monakhov 		}
45931e381f60SDmitry Monakhov 		if (EXT4_MOUNT_DATA_FLAGS &
45941e381f60SDmitry Monakhov 		    (sbi->s_mount_opt ^ sbi->s_def_mount_opt)) {
45951e381f60SDmitry Monakhov 			ext4_msg(sb, KERN_ERR, "can't mount with "
45961e381f60SDmitry Monakhov 				 "data=, fs mounted w/o journal");
45971e381f60SDmitry Monakhov 			goto failed_mount_wq;
45981e381f60SDmitry Monakhov 		}
459950b29d8fSDebabrata Banerjee 		sbi->s_def_mount_opt &= ~EXT4_MOUNT_JOURNAL_CHECKSUM;
46001e381f60SDmitry Monakhov 		clear_opt(sb, JOURNAL_CHECKSUM);
4601fd8c37ecSTheodore Ts'o 		clear_opt(sb, DATA_FLAGS);
46020390131bSFrank Mayhar 		sbi->s_journal = NULL;
46030390131bSFrank Mayhar 		needs_recovery = 0;
46040390131bSFrank Mayhar 		goto no_journal;
4605ac27a0ecSDave Kleikamp 	}
4606ac27a0ecSDave Kleikamp 
4607e2b911c5SDarrick J. Wong 	if (ext4_has_feature_64bit(sb) &&
4608eb40a09cSJose R. Santos 	    !jbd2_journal_set_features(EXT4_SB(sb)->s_journal, 0, 0,
4609eb40a09cSJose R. Santos 				       JBD2_FEATURE_INCOMPAT_64BIT)) {
4610b31e1552SEric Sandeen 		ext4_msg(sb, KERN_ERR, "Failed to set 64-bit journal feature");
4611744692dcSJiaying Zhang 		goto failed_mount_wq;
4612eb40a09cSJose R. Santos 	}
4613eb40a09cSJose R. Santos 
461425ed6e8aSDarrick J. Wong 	if (!set_journal_csum_feature_set(sb)) {
461525ed6e8aSDarrick J. Wong 		ext4_msg(sb, KERN_ERR, "Failed to set journal checksum "
461625ed6e8aSDarrick J. Wong 			 "feature set");
461725ed6e8aSDarrick J. Wong 		goto failed_mount_wq;
4618d4da6c9cSLinus Torvalds 	}
4619818d276cSGirish Shilamkar 
4620ac27a0ecSDave Kleikamp 	/* We have now updated the journal if required, so we can
4621ac27a0ecSDave Kleikamp 	 * validate the data journaling mode. */
4622ac27a0ecSDave Kleikamp 	switch (test_opt(sb, DATA_FLAGS)) {
4623ac27a0ecSDave Kleikamp 	case 0:
4624ac27a0ecSDave Kleikamp 		/* No mode set, assume a default based on the journal
462563f57933SAndrew Morton 		 * capabilities: ORDERED_DATA if the journal can
462663f57933SAndrew Morton 		 * cope, else JOURNAL_DATA
462763f57933SAndrew Morton 		 */
4628dab291afSMingming Cao 		if (jbd2_journal_check_available_features
462927f394a7STyson Nottingham 		    (sbi->s_journal, 0, 0, JBD2_FEATURE_INCOMPAT_REVOKE)) {
4630fd8c37ecSTheodore Ts'o 			set_opt(sb, ORDERED_DATA);
463127f394a7STyson Nottingham 			sbi->s_def_mount_opt |= EXT4_MOUNT_ORDERED_DATA;
463227f394a7STyson Nottingham 		} else {
4633fd8c37ecSTheodore Ts'o 			set_opt(sb, JOURNAL_DATA);
463427f394a7STyson Nottingham 			sbi->s_def_mount_opt |= EXT4_MOUNT_JOURNAL_DATA;
463527f394a7STyson Nottingham 		}
4636ac27a0ecSDave Kleikamp 		break;
4637ac27a0ecSDave Kleikamp 
4638617ba13bSMingming Cao 	case EXT4_MOUNT_ORDERED_DATA:
4639617ba13bSMingming Cao 	case EXT4_MOUNT_WRITEBACK_DATA:
4640dab291afSMingming Cao 		if (!jbd2_journal_check_available_features
4641dab291afSMingming Cao 		    (sbi->s_journal, 0, 0, JBD2_FEATURE_INCOMPAT_REVOKE)) {
4642b31e1552SEric Sandeen 			ext4_msg(sb, KERN_ERR, "Journal does not support "
4643b31e1552SEric Sandeen 			       "requested data journaling mode");
4644744692dcSJiaying Zhang 			goto failed_mount_wq;
4645ac27a0ecSDave Kleikamp 		}
4646ac27a0ecSDave Kleikamp 	default:
4647ac27a0ecSDave Kleikamp 		break;
4648ac27a0ecSDave Kleikamp 	}
4649ab04df78SJan Kara 
4650ab04df78SJan Kara 	if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA &&
4651ab04df78SJan Kara 	    test_opt(sb, JOURNAL_ASYNC_COMMIT)) {
4652ab04df78SJan Kara 		ext4_msg(sb, KERN_ERR, "can't mount with "
4653ab04df78SJan Kara 			"journal_async_commit in data=ordered mode");
4654ab04df78SJan Kara 		goto failed_mount_wq;
4655ab04df78SJan Kara 	}
4656ab04df78SJan Kara 
4657b3881f74STheodore Ts'o 	set_task_ioprio(sbi->s_journal->j_task, journal_ioprio);
4658ac27a0ecSDave Kleikamp 
465918aadd47SBobi Jam 	sbi->s_journal->j_commit_callback = ext4_journal_commit_callback;
466018aadd47SBobi Jam 
4661ce7e010aSTheodore Ts'o no_journal:
4662cdb7ee4cSTahsin Erdogan 	if (!test_opt(sb, NO_MBCACHE)) {
466347387409STahsin Erdogan 		sbi->s_ea_block_cache = ext4_xattr_create_cache();
466447387409STahsin Erdogan 		if (!sbi->s_ea_block_cache) {
4665cdb7ee4cSTahsin Erdogan 			ext4_msg(sb, KERN_ERR,
4666cdb7ee4cSTahsin Erdogan 				 "Failed to create ea_block_cache");
46679c191f70ST Makphaibulchoke 			goto failed_mount_wq;
46689c191f70ST Makphaibulchoke 		}
46699c191f70ST Makphaibulchoke 
4670dec214d0STahsin Erdogan 		if (ext4_has_feature_ea_inode(sb)) {
4671dec214d0STahsin Erdogan 			sbi->s_ea_inode_cache = ext4_xattr_create_cache();
4672dec214d0STahsin Erdogan 			if (!sbi->s_ea_inode_cache) {
4673dec214d0STahsin Erdogan 				ext4_msg(sb, KERN_ERR,
4674dec214d0STahsin Erdogan 					 "Failed to create ea_inode_cache");
4675dec214d0STahsin Erdogan 				goto failed_mount_wq;
4676dec214d0STahsin Erdogan 			}
4677dec214d0STahsin Erdogan 		}
4678cdb7ee4cSTahsin Erdogan 	}
4679dec214d0STahsin Erdogan 
4680c93d8f88SEric Biggers 	if (ext4_has_feature_verity(sb) && blocksize != PAGE_SIZE) {
4681c93d8f88SEric Biggers 		ext4_msg(sb, KERN_ERR, "Unsupported blocksize for fs-verity");
4682c93d8f88SEric Biggers 		goto failed_mount_wq;
4683c93d8f88SEric Biggers 	}
4684c93d8f88SEric Biggers 
4685bc98a42cSDavid Howells 	if (DUMMY_ENCRYPTION_ENABLED(sbi) && !sb_rdonly(sb) &&
4686e2b911c5SDarrick J. Wong 	    !ext4_has_feature_encrypt(sb)) {
4687e2b911c5SDarrick J. Wong 		ext4_set_feature_encrypt(sb);
46886ddb2447STheodore Ts'o 		ext4_commit_super(sb, 1);
46896ddb2447STheodore Ts'o 	}
46906ddb2447STheodore Ts'o 
4691fd89d5f2STejun Heo 	/*
4692952fc18eSTheodore Ts'o 	 * Get the # of file system overhead blocks from the
4693952fc18eSTheodore Ts'o 	 * superblock if present.
4694952fc18eSTheodore Ts'o 	 */
4695952fc18eSTheodore Ts'o 	if (es->s_overhead_clusters)
4696952fc18eSTheodore Ts'o 		sbi->s_overhead = le32_to_cpu(es->s_overhead_clusters);
4697952fc18eSTheodore Ts'o 	else {
469807aa2ea1SLukas Czerner 		err = ext4_calculate_overhead(sb);
469907aa2ea1SLukas Czerner 		if (err)
4700952fc18eSTheodore Ts'o 			goto failed_mount_wq;
4701952fc18eSTheodore Ts'o 	}
4702952fc18eSTheodore Ts'o 
4703952fc18eSTheodore Ts'o 	/*
4704fd89d5f2STejun Heo 	 * The maximum number of concurrent works can be high and
4705fd89d5f2STejun Heo 	 * concurrency isn't really necessary.  Limit it to 1.
4706fd89d5f2STejun Heo 	 */
47072e8fa54eSJan Kara 	EXT4_SB(sb)->rsv_conversion_wq =
47082e8fa54eSJan Kara 		alloc_workqueue("ext4-rsv-conversion", WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
47092e8fa54eSJan Kara 	if (!EXT4_SB(sb)->rsv_conversion_wq) {
47102e8fa54eSJan Kara 		printk(KERN_ERR "EXT4-fs: failed to create workqueue\n");
471107aa2ea1SLukas Czerner 		ret = -ENOMEM;
47122e8fa54eSJan Kara 		goto failed_mount4;
47132e8fa54eSJan Kara 	}
47142e8fa54eSJan Kara 
4715ac27a0ecSDave Kleikamp 	/*
4716dab291afSMingming Cao 	 * The jbd2_journal_load will have done any necessary log recovery,
4717ac27a0ecSDave Kleikamp 	 * so we can safely mount the rest of the filesystem now.
4718ac27a0ecSDave Kleikamp 	 */
4719ac27a0ecSDave Kleikamp 
47208a363970STheodore Ts'o 	root = ext4_iget(sb, EXT4_ROOT_INO, EXT4_IGET_SPECIAL);
47211d1fe1eeSDavid Howells 	if (IS_ERR(root)) {
4722b31e1552SEric Sandeen 		ext4_msg(sb, KERN_ERR, "get root inode failed");
47231d1fe1eeSDavid Howells 		ret = PTR_ERR(root);
472432a9bb57SManish Katiyar 		root = NULL;
4725ac27a0ecSDave Kleikamp 		goto failed_mount4;
4726ac27a0ecSDave Kleikamp 	}
4727ac27a0ecSDave Kleikamp 	if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) {
4728b31e1552SEric Sandeen 		ext4_msg(sb, KERN_ERR, "corrupt root inode, run e2fsck");
472994bf608aSAl Viro 		iput(root);
4730ac27a0ecSDave Kleikamp 		goto failed_mount4;
4731ac27a0ecSDave Kleikamp 	}
4732b886ee3eSGabriel Krisman Bertazi 
4733b886ee3eSGabriel Krisman Bertazi #ifdef CONFIG_UNICODE
4734b886ee3eSGabriel Krisman Bertazi 	if (sbi->s_encoding)
4735b886ee3eSGabriel Krisman Bertazi 		sb->s_d_op = &ext4_dentry_ops;
4736b886ee3eSGabriel Krisman Bertazi #endif
4737b886ee3eSGabriel Krisman Bertazi 
473848fde701SAl Viro 	sb->s_root = d_make_root(root);
47391d1fe1eeSDavid Howells 	if (!sb->s_root) {
4740b31e1552SEric Sandeen 		ext4_msg(sb, KERN_ERR, "get root dentry failed");
47411d1fe1eeSDavid Howells 		ret = -ENOMEM;
47421d1fe1eeSDavid Howells 		goto failed_mount4;
47431d1fe1eeSDavid Howells 	}
4744ac27a0ecSDave Kleikamp 
4745c89128a0SJaegeuk Kim 	ret = ext4_setup_super(sb, es, sb_rdonly(sb));
4746c89128a0SJaegeuk Kim 	if (ret == -EROFS) {
47471751e8a6SLinus Torvalds 		sb->s_flags |= SB_RDONLY;
4748c89128a0SJaegeuk Kim 		ret = 0;
4749c89128a0SJaegeuk Kim 	} else if (ret)
4750c89128a0SJaegeuk Kim 		goto failed_mount4a;
4751ef7f3835SKalpak Shah 
4752b5799018STheodore Ts'o 	ext4_set_resv_clusters(sb);
475327dd4385SLukas Czerner 
47540f5bde1dSJan Kara 	if (test_opt(sb, BLOCK_VALIDITY)) {
47556fd058f7STheodore Ts'o 		err = ext4_setup_system_zone(sb);
47566fd058f7STheodore Ts'o 		if (err) {
4757b31e1552SEric Sandeen 			ext4_msg(sb, KERN_ERR, "failed to initialize system "
4758fbe845ddSCurt Wohlgemuth 				 "zone (%d)", err);
4759f9ae9cf5STheodore Ts'o 			goto failed_mount4a;
4760f9ae9cf5STheodore Ts'o 		}
47610f5bde1dSJan Kara 	}
4762f9ae9cf5STheodore Ts'o 
4763f9ae9cf5STheodore Ts'o 	ext4_ext_init(sb);
4764f9ae9cf5STheodore Ts'o 	err = ext4_mb_init(sb);
4765f9ae9cf5STheodore Ts'o 	if (err) {
4766f9ae9cf5STheodore Ts'o 		ext4_msg(sb, KERN_ERR, "failed to initialize mballoc (%d)",
4767f9ae9cf5STheodore Ts'o 			 err);
4768dcf2d804STao Ma 		goto failed_mount5;
4769c2774d84SAneesh Kumar K.V 	}
4770c2774d84SAneesh Kumar K.V 
4771d5e03cbbSTheodore Ts'o 	block = ext4_count_free_clusters(sb);
4772d5e03cbbSTheodore Ts'o 	ext4_free_blocks_count_set(sbi->s_es,
4773d5e03cbbSTheodore Ts'o 				   EXT4_C2B(sbi, block));
47744274f516STheodore Ts'o 	ext4_superblock_csum_set(sb);
4775908c7f19STejun Heo 	err = percpu_counter_init(&sbi->s_freeclusters_counter, block,
4776908c7f19STejun Heo 				  GFP_KERNEL);
4777d5e03cbbSTheodore Ts'o 	if (!err) {
4778d5e03cbbSTheodore Ts'o 		unsigned long freei = ext4_count_free_inodes(sb);
4779d5e03cbbSTheodore Ts'o 		sbi->s_es->s_free_inodes_count = cpu_to_le32(freei);
47804274f516STheodore Ts'o 		ext4_superblock_csum_set(sb);
4781908c7f19STejun Heo 		err = percpu_counter_init(&sbi->s_freeinodes_counter, freei,
4782908c7f19STejun Heo 					  GFP_KERNEL);
4783d5e03cbbSTheodore Ts'o 	}
4784d5e03cbbSTheodore Ts'o 	if (!err)
4785d5e03cbbSTheodore Ts'o 		err = percpu_counter_init(&sbi->s_dirs_counter,
4786908c7f19STejun Heo 					  ext4_count_dirs(sb), GFP_KERNEL);
4787d5e03cbbSTheodore Ts'o 	if (!err)
4788908c7f19STejun Heo 		err = percpu_counter_init(&sbi->s_dirtyclusters_counter, 0,
4789908c7f19STejun Heo 					  GFP_KERNEL);
4790c8585c6fSDaeho Jeong 	if (!err)
4791bbd55937SEric Biggers 		err = percpu_init_rwsem(&sbi->s_writepages_rwsem);
4792c8585c6fSDaeho Jeong 
4793d5e03cbbSTheodore Ts'o 	if (err) {
4794d5e03cbbSTheodore Ts'o 		ext4_msg(sb, KERN_ERR, "insufficient memory");
4795d5e03cbbSTheodore Ts'o 		goto failed_mount6;
4796d5e03cbbSTheodore Ts'o 	}
4797d5e03cbbSTheodore Ts'o 
4798e2b911c5SDarrick J. Wong 	if (ext4_has_feature_flex_bg(sb))
4799d5e03cbbSTheodore Ts'o 		if (!ext4_fill_flex_info(sb)) {
4800d5e03cbbSTheodore Ts'o 			ext4_msg(sb, KERN_ERR,
4801d5e03cbbSTheodore Ts'o 			       "unable to initialize "
4802d5e03cbbSTheodore Ts'o 			       "flex_bg meta info!");
4803d5e03cbbSTheodore Ts'o 			goto failed_mount6;
4804d5e03cbbSTheodore Ts'o 		}
4805d5e03cbbSTheodore Ts'o 
4806bfff6873SLukas Czerner 	err = ext4_register_li_request(sb, first_not_zeroed);
4807bfff6873SLukas Czerner 	if (err)
4808dcf2d804STao Ma 		goto failed_mount6;
4809bfff6873SLukas Czerner 
4810b5799018STheodore Ts'o 	err = ext4_register_sysfs(sb);
4811dcf2d804STao Ma 	if (err)
4812dcf2d804STao Ma 		goto failed_mount7;
48133197ebdbSTheodore Ts'o 
48149b2ff357SJan Kara #ifdef CONFIG_QUOTA
48159b2ff357SJan Kara 	/* Enable quota usage during mount. */
4816bc98a42cSDavid Howells 	if (ext4_has_feature_quota(sb) && !sb_rdonly(sb)) {
48179b2ff357SJan Kara 		err = ext4_enable_quotas(sb);
48189b2ff357SJan Kara 		if (err)
48199b2ff357SJan Kara 			goto failed_mount8;
48209b2ff357SJan Kara 	}
48219b2ff357SJan Kara #endif  /* CONFIG_QUOTA */
48229b2ff357SJan Kara 
4823bc71726cSzhangyi (F) 	/*
4824bc71726cSzhangyi (F) 	 * Save the original bdev mapping's wb_err value which could be
4825bc71726cSzhangyi (F) 	 * used to detect the metadata async write error.
4826bc71726cSzhangyi (F) 	 */
4827bc71726cSzhangyi (F) 	spin_lock_init(&sbi->s_bdev_wb_lock);
4828bc71726cSzhangyi (F) 	if (!sb_rdonly(sb))
4829bc71726cSzhangyi (F) 		errseq_check_and_advance(&sb->s_bdev->bd_inode->i_mapping->wb_err,
4830bc71726cSzhangyi (F) 					 &sbi->s_bdev_wb_err);
4831bc71726cSzhangyi (F) 	sb->s_bdev->bd_super = sb;
4832617ba13bSMingming Cao 	EXT4_SB(sb)->s_mount_state |= EXT4_ORPHAN_FS;
4833617ba13bSMingming Cao 	ext4_orphan_cleanup(sb, es);
4834617ba13bSMingming Cao 	EXT4_SB(sb)->s_mount_state &= ~EXT4_ORPHAN_FS;
48350390131bSFrank Mayhar 	if (needs_recovery) {
4836b31e1552SEric Sandeen 		ext4_msg(sb, KERN_INFO, "recovery complete");
483711215630SJan Kara 		err = ext4_mark_recovery_complete(sb, es);
483811215630SJan Kara 		if (err)
483911215630SJan Kara 			goto failed_mount8;
48400390131bSFrank Mayhar 	}
48410390131bSFrank Mayhar 	if (EXT4_SB(sb)->s_journal) {
48420390131bSFrank Mayhar 		if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
48430390131bSFrank Mayhar 			descr = " journalled data mode";
48440390131bSFrank Mayhar 		else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
48450390131bSFrank Mayhar 			descr = " ordered data mode";
48460390131bSFrank Mayhar 		else
48470390131bSFrank Mayhar 			descr = " writeback data mode";
48480390131bSFrank Mayhar 	} else
48490390131bSFrank Mayhar 		descr = "out journal";
48500390131bSFrank Mayhar 
485179add3a3SLukas Czerner 	if (test_opt(sb, DISCARD)) {
485279add3a3SLukas Czerner 		struct request_queue *q = bdev_get_queue(sb->s_bdev);
485379add3a3SLukas Czerner 		if (!blk_queue_discard(q))
485479add3a3SLukas Czerner 			ext4_msg(sb, KERN_WARNING,
485579add3a3SLukas Czerner 				 "mounting with \"discard\" option, but "
485679add3a3SLukas Czerner 				 "the device does not support discard");
485779add3a3SLukas Czerner 	}
485879add3a3SLukas Czerner 
4859e294a537STheodore Ts'o 	if (___ratelimit(&ext4_mount_msg_ratelimit, "EXT4-fs mount"))
4860d4c402d9SCurt Wohlgemuth 		ext4_msg(sb, KERN_INFO, "mounted filesystem with%s. "
48615aee0f8aSTheodore Ts'o 			 "Opts: %.*s%s%s", descr,
48625aee0f8aSTheodore Ts'o 			 (int) sizeof(sbi->s_es->s_mount_opts),
48635aee0f8aSTheodore Ts'o 			 sbi->s_es->s_mount_opts,
48648b67f04aSTheodore Ts'o 			 *sbi->s_es->s_mount_opts ? "; " : "", orig_data);
4865ac27a0ecSDave Kleikamp 
486666e61a9eSTheodore Ts'o 	if (es->s_error_count)
486766e61a9eSTheodore Ts'o 		mod_timer(&sbi->s_err_report, jiffies + 300*HZ); /* 5 minutes */
4868ac27a0ecSDave Kleikamp 
4869efbed4dcSTheodore Ts'o 	/* Enable message ratelimiting. Default is 10 messages per 5 secs. */
4870efbed4dcSTheodore Ts'o 	ratelimit_state_init(&sbi->s_err_ratelimit_state, 5 * HZ, 10);
4871efbed4dcSTheodore Ts'o 	ratelimit_state_init(&sbi->s_warning_ratelimit_state, 5 * HZ, 10);
4872efbed4dcSTheodore Ts'o 	ratelimit_state_init(&sbi->s_msg_ratelimit_state, 5 * HZ, 10);
48731cf006edSDmitry Monakhov 	atomic_set(&sbi->s_warning_count, 0);
48741cf006edSDmitry Monakhov 	atomic_set(&sbi->s_msg_count, 0);
4875efbed4dcSTheodore Ts'o 
4876d4c402d9SCurt Wohlgemuth 	kfree(orig_data);
4877ac27a0ecSDave Kleikamp 	return 0;
4878ac27a0ecSDave Kleikamp 
4879617ba13bSMingming Cao cantfind_ext4:
4880ac27a0ecSDave Kleikamp 	if (!silent)
4881b31e1552SEric Sandeen 		ext4_msg(sb, KERN_ERR, "VFS: Can't find ext4 filesystem");
4882ac27a0ecSDave Kleikamp 	goto failed_mount;
4883ac27a0ecSDave Kleikamp 
488472ba7450STheodore Ts'o failed_mount8:
4885ebd173beSTheodore Ts'o 	ext4_unregister_sysfs(sb);
4886cb8d53d2SEric Biggers 	kobject_put(&sbi->s_kobj);
4887dcf2d804STao Ma failed_mount7:
4888dcf2d804STao Ma 	ext4_unregister_li_request(sb);
4889dcf2d804STao Ma failed_mount6:
4890f9ae9cf5STheodore Ts'o 	ext4_mb_release(sb);
48917c990728SSuraj Jitindar Singh 	rcu_read_lock();
48927c990728SSuraj Jitindar Singh 	flex_groups = rcu_dereference(sbi->s_flex_groups);
48937c990728SSuraj Jitindar Singh 	if (flex_groups) {
48947c990728SSuraj Jitindar Singh 		for (i = 0; i < sbi->s_flex_groups_allocated; i++)
48957c990728SSuraj Jitindar Singh 			kvfree(flex_groups[i]);
48967c990728SSuraj Jitindar Singh 		kvfree(flex_groups);
48977c990728SSuraj Jitindar Singh 	}
48987c990728SSuraj Jitindar Singh 	rcu_read_unlock();
4899d5e03cbbSTheodore Ts'o 	percpu_counter_destroy(&sbi->s_freeclusters_counter);
4900d5e03cbbSTheodore Ts'o 	percpu_counter_destroy(&sbi->s_freeinodes_counter);
4901d5e03cbbSTheodore Ts'o 	percpu_counter_destroy(&sbi->s_dirs_counter);
4902d5e03cbbSTheodore Ts'o 	percpu_counter_destroy(&sbi->s_dirtyclusters_counter);
4903bbd55937SEric Biggers 	percpu_free_rwsem(&sbi->s_writepages_rwsem);
490400764937SAzat Khuzhin failed_mount5:
4905f9ae9cf5STheodore Ts'o 	ext4_ext_release(sb);
4906f9ae9cf5STheodore Ts'o 	ext4_release_system_zone(sb);
4907f9ae9cf5STheodore Ts'o failed_mount4a:
490894bf608aSAl Viro 	dput(sb->s_root);
490932a9bb57SManish Katiyar 	sb->s_root = NULL;
491094bf608aSAl Viro failed_mount4:
4911b31e1552SEric Sandeen 	ext4_msg(sb, KERN_ERR, "mount failed");
49122e8fa54eSJan Kara 	if (EXT4_SB(sb)->rsv_conversion_wq)
49132e8fa54eSJan Kara 		destroy_workqueue(EXT4_SB(sb)->rsv_conversion_wq);
49144c0425ffSMingming Cao failed_mount_wq:
4915dec214d0STahsin Erdogan 	ext4_xattr_destroy_cache(sbi->s_ea_inode_cache);
4916dec214d0STahsin Erdogan 	sbi->s_ea_inode_cache = NULL;
491750c15df6SChengguang Xu 
491847387409STahsin Erdogan 	ext4_xattr_destroy_cache(sbi->s_ea_block_cache);
491947387409STahsin Erdogan 	sbi->s_ea_block_cache = NULL;
492050c15df6SChengguang Xu 
49210390131bSFrank Mayhar 	if (sbi->s_journal) {
4922dab291afSMingming Cao 		jbd2_journal_destroy(sbi->s_journal);
492347b4a50bSJan Kara 		sbi->s_journal = NULL;
49240390131bSFrank Mayhar 	}
492550460fe8SDarrick J. Wong failed_mount3a:
4926d3922a77SZheng Liu 	ext4_es_unregister_shrinker(sbi);
4927eb68d0e2SZheng Liu failed_mount3:
49289105bb14SAl Viro 	del_timer_sync(&sbi->s_err_report);
4929c5e06d10SJohann Lombardi 	if (sbi->s_mmp_tsk)
4930c5e06d10SJohann Lombardi 		kthread_stop(sbi->s_mmp_tsk);
4931ac27a0ecSDave Kleikamp failed_mount2:
49321d0c3924STheodore Ts'o 	rcu_read_lock();
49331d0c3924STheodore Ts'o 	group_desc = rcu_dereference(sbi->s_group_desc);
4934ac27a0ecSDave Kleikamp 	for (i = 0; i < db_count; i++)
49351d0c3924STheodore Ts'o 		brelse(group_desc[i]);
49361d0c3924STheodore Ts'o 	kvfree(group_desc);
49371d0c3924STheodore Ts'o 	rcu_read_unlock();
4938ac27a0ecSDave Kleikamp failed_mount:
49390441984aSDarrick J. Wong 	if (sbi->s_chksum_driver)
49400441984aSDarrick J. Wong 		crypto_free_shash(sbi->s_chksum_driver);
4941c83ad55eSGabriel Krisman Bertazi 
4942c83ad55eSGabriel Krisman Bertazi #ifdef CONFIG_UNICODE
4943c83ad55eSGabriel Krisman Bertazi 	utf8_unload(sbi->s_encoding);
4944c83ad55eSGabriel Krisman Bertazi #endif
4945c83ad55eSGabriel Krisman Bertazi 
4946ac27a0ecSDave Kleikamp #ifdef CONFIG_QUOTA
4947a2d4a646SJan Kara 	for (i = 0; i < EXT4_MAXQUOTAS; i++)
49480ba33facSTheodore Ts'o 		kfree(get_qf_name(sb, sbi, i));
4949ac27a0ecSDave Kleikamp #endif
4950ed318a6cSEric Biggers 	fscrypt_free_dummy_context(&sbi->s_dummy_enc_ctx);
4951617ba13bSMingming Cao 	ext4_blkdev_remove(sbi);
4952ac27a0ecSDave Kleikamp 	brelse(bh);
4953ac27a0ecSDave Kleikamp out_fail:
4954ac27a0ecSDave Kleikamp 	sb->s_fs_info = NULL;
4955f6830165SManish Katiyar 	kfree(sbi->s_blockgroup_lock);
49565aee0f8aSTheodore Ts'o out_free_base:
4957ac27a0ecSDave Kleikamp 	kfree(sbi);
4958d4c402d9SCurt Wohlgemuth 	kfree(orig_data);
49595e405595SDan Williams 	fs_put_dax(dax_dev);
496007aa2ea1SLukas Czerner 	return err ? err : ret;
4961ac27a0ecSDave Kleikamp }
4962ac27a0ecSDave Kleikamp 
4963ac27a0ecSDave Kleikamp /*
4964ac27a0ecSDave Kleikamp  * Setup any per-fs journal parameters now.  We'll do this both on
4965ac27a0ecSDave Kleikamp  * initial mount, once the journal has been initialised but before we've
4966ac27a0ecSDave Kleikamp  * done any recovery; and again on any subsequent remount.
4967ac27a0ecSDave Kleikamp  */
4968617ba13bSMingming Cao static void ext4_init_journal_params(struct super_block *sb, journal_t *journal)
4969ac27a0ecSDave Kleikamp {
4970617ba13bSMingming Cao 	struct ext4_sb_info *sbi = EXT4_SB(sb);
4971ac27a0ecSDave Kleikamp 
4972ac27a0ecSDave Kleikamp 	journal->j_commit_interval = sbi->s_commit_interval;
497330773840STheodore Ts'o 	journal->j_min_batch_time = sbi->s_min_batch_time;
497430773840STheodore Ts'o 	journal->j_max_batch_time = sbi->s_max_batch_time;
4975ac27a0ecSDave Kleikamp 
4976a931da6aSTheodore Ts'o 	write_lock(&journal->j_state_lock);
4977ac27a0ecSDave Kleikamp 	if (test_opt(sb, BARRIER))
4978dab291afSMingming Cao 		journal->j_flags |= JBD2_BARRIER;
4979ac27a0ecSDave Kleikamp 	else
4980dab291afSMingming Cao 		journal->j_flags &= ~JBD2_BARRIER;
49815bf5683aSHidehiro Kawai 	if (test_opt(sb, DATA_ERR_ABORT))
49825bf5683aSHidehiro Kawai 		journal->j_flags |= JBD2_ABORT_ON_SYNCDATA_ERR;
49835bf5683aSHidehiro Kawai 	else
49845bf5683aSHidehiro Kawai 		journal->j_flags &= ~JBD2_ABORT_ON_SYNCDATA_ERR;
4985a931da6aSTheodore Ts'o 	write_unlock(&journal->j_state_lock);
4986ac27a0ecSDave Kleikamp }
4987ac27a0ecSDave Kleikamp 
4988c6cb7e77SEric Whitney static struct inode *ext4_get_journal_inode(struct super_block *sb,
4989ac27a0ecSDave Kleikamp 					     unsigned int journal_inum)
4990ac27a0ecSDave Kleikamp {
4991ac27a0ecSDave Kleikamp 	struct inode *journal_inode;
4992ac27a0ecSDave Kleikamp 
4993c6cb7e77SEric Whitney 	/*
4994c6cb7e77SEric Whitney 	 * Test for the existence of a valid inode on disk.  Bad things
4995c6cb7e77SEric Whitney 	 * happen if we iget() an unused inode, as the subsequent iput()
4996c6cb7e77SEric Whitney 	 * will try to delete it.
4997c6cb7e77SEric Whitney 	 */
49988a363970STheodore Ts'o 	journal_inode = ext4_iget(sb, journal_inum, EXT4_IGET_SPECIAL);
49991d1fe1eeSDavid Howells 	if (IS_ERR(journal_inode)) {
5000b31e1552SEric Sandeen 		ext4_msg(sb, KERN_ERR, "no journal found");
5001ac27a0ecSDave Kleikamp 		return NULL;
5002ac27a0ecSDave Kleikamp 	}
5003ac27a0ecSDave Kleikamp 	if (!journal_inode->i_nlink) {
5004ac27a0ecSDave Kleikamp 		make_bad_inode(journal_inode);
5005ac27a0ecSDave Kleikamp 		iput(journal_inode);
5006b31e1552SEric Sandeen 		ext4_msg(sb, KERN_ERR, "journal inode is deleted");
5007ac27a0ecSDave Kleikamp 		return NULL;
5008ac27a0ecSDave Kleikamp 	}
5009ac27a0ecSDave Kleikamp 
5010e5f8eab8STheodore Ts'o 	jbd_debug(2, "Journal inode found at %p: %lld bytes\n",
5011ac27a0ecSDave Kleikamp 		  journal_inode, journal_inode->i_size);
50121d1fe1eeSDavid Howells 	if (!S_ISREG(journal_inode->i_mode)) {
5013b31e1552SEric Sandeen 		ext4_msg(sb, KERN_ERR, "invalid journal inode");
5014ac27a0ecSDave Kleikamp 		iput(journal_inode);
5015ac27a0ecSDave Kleikamp 		return NULL;
5016ac27a0ecSDave Kleikamp 	}
5017c6cb7e77SEric Whitney 	return journal_inode;
5018c6cb7e77SEric Whitney }
5019c6cb7e77SEric Whitney 
5020c6cb7e77SEric Whitney static journal_t *ext4_get_journal(struct super_block *sb,
5021c6cb7e77SEric Whitney 				   unsigned int journal_inum)
5022c6cb7e77SEric Whitney {
5023c6cb7e77SEric Whitney 	struct inode *journal_inode;
5024c6cb7e77SEric Whitney 	journal_t *journal;
5025c6cb7e77SEric Whitney 
502611215630SJan Kara 	if (WARN_ON_ONCE(!ext4_has_feature_journal(sb)))
502711215630SJan Kara 		return NULL;
5028c6cb7e77SEric Whitney 
5029c6cb7e77SEric Whitney 	journal_inode = ext4_get_journal_inode(sb, journal_inum);
5030c6cb7e77SEric Whitney 	if (!journal_inode)
5031c6cb7e77SEric Whitney 		return NULL;
5032ac27a0ecSDave Kleikamp 
5033dab291afSMingming Cao 	journal = jbd2_journal_init_inode(journal_inode);
5034ac27a0ecSDave Kleikamp 	if (!journal) {
5035b31e1552SEric Sandeen 		ext4_msg(sb, KERN_ERR, "Could not load journal inode");
5036ac27a0ecSDave Kleikamp 		iput(journal_inode);
5037ac27a0ecSDave Kleikamp 		return NULL;
5038ac27a0ecSDave Kleikamp 	}
5039ac27a0ecSDave Kleikamp 	journal->j_private = sb;
5040617ba13bSMingming Cao 	ext4_init_journal_params(sb, journal);
5041ac27a0ecSDave Kleikamp 	return journal;
5042ac27a0ecSDave Kleikamp }
5043ac27a0ecSDave Kleikamp 
5044617ba13bSMingming Cao static journal_t *ext4_get_dev_journal(struct super_block *sb,
5045ac27a0ecSDave Kleikamp 				       dev_t j_dev)
5046ac27a0ecSDave Kleikamp {
5047ac27a0ecSDave Kleikamp 	struct buffer_head *bh;
5048ac27a0ecSDave Kleikamp 	journal_t *journal;
5049617ba13bSMingming Cao 	ext4_fsblk_t start;
5050617ba13bSMingming Cao 	ext4_fsblk_t len;
5051ac27a0ecSDave Kleikamp 	int hblock, blocksize;
5052617ba13bSMingming Cao 	ext4_fsblk_t sb_block;
5053ac27a0ecSDave Kleikamp 	unsigned long offset;
5054617ba13bSMingming Cao 	struct ext4_super_block *es;
5055ac27a0ecSDave Kleikamp 	struct block_device *bdev;
5056ac27a0ecSDave Kleikamp 
505711215630SJan Kara 	if (WARN_ON_ONCE(!ext4_has_feature_journal(sb)))
505811215630SJan Kara 		return NULL;
50590390131bSFrank Mayhar 
5060b31e1552SEric Sandeen 	bdev = ext4_blkdev_get(j_dev, sb);
5061ac27a0ecSDave Kleikamp 	if (bdev == NULL)
5062ac27a0ecSDave Kleikamp 		return NULL;
5063ac27a0ecSDave Kleikamp 
5064ac27a0ecSDave Kleikamp 	blocksize = sb->s_blocksize;
5065e1defc4fSMartin K. Petersen 	hblock = bdev_logical_block_size(bdev);
5066ac27a0ecSDave Kleikamp 	if (blocksize < hblock) {
5067b31e1552SEric Sandeen 		ext4_msg(sb, KERN_ERR,
5068b31e1552SEric Sandeen 			"blocksize too small for journal device");
5069ac27a0ecSDave Kleikamp 		goto out_bdev;
5070ac27a0ecSDave Kleikamp 	}
5071ac27a0ecSDave Kleikamp 
5072617ba13bSMingming Cao 	sb_block = EXT4_MIN_BLOCK_SIZE / blocksize;
5073617ba13bSMingming Cao 	offset = EXT4_MIN_BLOCK_SIZE % blocksize;
5074ac27a0ecSDave Kleikamp 	set_blocksize(bdev, blocksize);
5075ac27a0ecSDave Kleikamp 	if (!(bh = __bread(bdev, sb_block, blocksize))) {
5076b31e1552SEric Sandeen 		ext4_msg(sb, KERN_ERR, "couldn't read superblock of "
5077b31e1552SEric Sandeen 		       "external journal");
5078ac27a0ecSDave Kleikamp 		goto out_bdev;
5079ac27a0ecSDave Kleikamp 	}
5080ac27a0ecSDave Kleikamp 
50812716b802STheodore Ts'o 	es = (struct ext4_super_block *) (bh->b_data + offset);
5082617ba13bSMingming Cao 	if ((le16_to_cpu(es->s_magic) != EXT4_SUPER_MAGIC) ||
5083ac27a0ecSDave Kleikamp 	    !(le32_to_cpu(es->s_feature_incompat) &
5084617ba13bSMingming Cao 	      EXT4_FEATURE_INCOMPAT_JOURNAL_DEV)) {
5085b31e1552SEric Sandeen 		ext4_msg(sb, KERN_ERR, "external journal has "
5086b31e1552SEric Sandeen 					"bad superblock");
5087ac27a0ecSDave Kleikamp 		brelse(bh);
5088ac27a0ecSDave Kleikamp 		goto out_bdev;
5089ac27a0ecSDave Kleikamp 	}
5090ac27a0ecSDave Kleikamp 
5091df4763beSDarrick J. Wong 	if ((le32_to_cpu(es->s_feature_ro_compat) &
5092df4763beSDarrick J. Wong 	     EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) &&
5093df4763beSDarrick J. Wong 	    es->s_checksum != ext4_superblock_csum(sb, es)) {
5094df4763beSDarrick J. Wong 		ext4_msg(sb, KERN_ERR, "external journal has "
5095df4763beSDarrick J. Wong 				       "corrupt superblock");
5096df4763beSDarrick J. Wong 		brelse(bh);
5097df4763beSDarrick J. Wong 		goto out_bdev;
5098df4763beSDarrick J. Wong 	}
5099df4763beSDarrick J. Wong 
5100617ba13bSMingming Cao 	if (memcmp(EXT4_SB(sb)->s_es->s_journal_uuid, es->s_uuid, 16)) {
5101b31e1552SEric Sandeen 		ext4_msg(sb, KERN_ERR, "journal UUID does not match");
5102ac27a0ecSDave Kleikamp 		brelse(bh);
5103ac27a0ecSDave Kleikamp 		goto out_bdev;
5104ac27a0ecSDave Kleikamp 	}
5105ac27a0ecSDave Kleikamp 
5106bd81d8eeSLaurent Vivier 	len = ext4_blocks_count(es);
5107ac27a0ecSDave Kleikamp 	start = sb_block + 1;
5108ac27a0ecSDave Kleikamp 	brelse(bh);	/* we're done with the superblock */
5109ac27a0ecSDave Kleikamp 
5110dab291afSMingming Cao 	journal = jbd2_journal_init_dev(bdev, sb->s_bdev,
5111ac27a0ecSDave Kleikamp 					start, len, blocksize);
5112ac27a0ecSDave Kleikamp 	if (!journal) {
5113b31e1552SEric Sandeen 		ext4_msg(sb, KERN_ERR, "failed to create device journal");
5114ac27a0ecSDave Kleikamp 		goto out_bdev;
5115ac27a0ecSDave Kleikamp 	}
5116ac27a0ecSDave Kleikamp 	journal->j_private = sb;
5117dfec8a14SMike Christie 	ll_rw_block(REQ_OP_READ, REQ_META | REQ_PRIO, 1, &journal->j_sb_buffer);
5118ac27a0ecSDave Kleikamp 	wait_on_buffer(journal->j_sb_buffer);
5119ac27a0ecSDave Kleikamp 	if (!buffer_uptodate(journal->j_sb_buffer)) {
5120b31e1552SEric Sandeen 		ext4_msg(sb, KERN_ERR, "I/O error on journal device");
5121ac27a0ecSDave Kleikamp 		goto out_journal;
5122ac27a0ecSDave Kleikamp 	}
5123ac27a0ecSDave Kleikamp 	if (be32_to_cpu(journal->j_superblock->s_nr_users) != 1) {
5124b31e1552SEric Sandeen 		ext4_msg(sb, KERN_ERR, "External journal has more than one "
5125b31e1552SEric Sandeen 					"user (unsupported) - %d",
5126ac27a0ecSDave Kleikamp 			be32_to_cpu(journal->j_superblock->s_nr_users));
5127ac27a0ecSDave Kleikamp 		goto out_journal;
5128ac27a0ecSDave Kleikamp 	}
5129ee7ed3aaSChunguang Xu 	EXT4_SB(sb)->s_journal_bdev = bdev;
5130617ba13bSMingming Cao 	ext4_init_journal_params(sb, journal);
5131ac27a0ecSDave Kleikamp 	return journal;
51320b8e58a1SAndreas Dilger 
5133ac27a0ecSDave Kleikamp out_journal:
5134dab291afSMingming Cao 	jbd2_journal_destroy(journal);
5135ac27a0ecSDave Kleikamp out_bdev:
5136617ba13bSMingming Cao 	ext4_blkdev_put(bdev);
5137ac27a0ecSDave Kleikamp 	return NULL;
5138ac27a0ecSDave Kleikamp }
5139ac27a0ecSDave Kleikamp 
5140617ba13bSMingming Cao static int ext4_load_journal(struct super_block *sb,
5141617ba13bSMingming Cao 			     struct ext4_super_block *es,
5142ac27a0ecSDave Kleikamp 			     unsigned long journal_devnum)
5143ac27a0ecSDave Kleikamp {
5144ac27a0ecSDave Kleikamp 	journal_t *journal;
5145ac27a0ecSDave Kleikamp 	unsigned int journal_inum = le32_to_cpu(es->s_journal_inum);
5146ac27a0ecSDave Kleikamp 	dev_t journal_dev;
5147ac27a0ecSDave Kleikamp 	int err = 0;
5148ac27a0ecSDave Kleikamp 	int really_read_only;
5149273108faSLukas Czerner 	int journal_dev_ro;
5150ac27a0ecSDave Kleikamp 
515111215630SJan Kara 	if (WARN_ON_ONCE(!ext4_has_feature_journal(sb)))
515211215630SJan Kara 		return -EFSCORRUPTED;
51530390131bSFrank Mayhar 
5154ac27a0ecSDave Kleikamp 	if (journal_devnum &&
5155ac27a0ecSDave Kleikamp 	    journal_devnum != le32_to_cpu(es->s_journal_dev)) {
5156b31e1552SEric Sandeen 		ext4_msg(sb, KERN_INFO, "external journal device major/minor "
5157b31e1552SEric Sandeen 			"numbers have changed");
5158ac27a0ecSDave Kleikamp 		journal_dev = new_decode_dev(journal_devnum);
5159ac27a0ecSDave Kleikamp 	} else
5160ac27a0ecSDave Kleikamp 		journal_dev = new_decode_dev(le32_to_cpu(es->s_journal_dev));
5161ac27a0ecSDave Kleikamp 
5162273108faSLukas Czerner 	if (journal_inum && journal_dev) {
5163273108faSLukas Czerner 		ext4_msg(sb, KERN_ERR,
5164273108faSLukas Czerner 			 "filesystem has both journal inode and journal device!");
5165273108faSLukas Czerner 		return -EINVAL;
5166273108faSLukas Czerner 	}
5167273108faSLukas Czerner 
5168273108faSLukas Czerner 	if (journal_inum) {
5169273108faSLukas Czerner 		journal = ext4_get_journal(sb, journal_inum);
5170273108faSLukas Czerner 		if (!journal)
5171273108faSLukas Czerner 			return -EINVAL;
5172273108faSLukas Czerner 	} else {
5173273108faSLukas Czerner 		journal = ext4_get_dev_journal(sb, journal_dev);
5174273108faSLukas Czerner 		if (!journal)
5175273108faSLukas Czerner 			return -EINVAL;
5176273108faSLukas Czerner 	}
5177273108faSLukas Czerner 
5178273108faSLukas Czerner 	journal_dev_ro = bdev_read_only(journal->j_dev);
5179273108faSLukas Czerner 	really_read_only = bdev_read_only(sb->s_bdev) | journal_dev_ro;
5180273108faSLukas Czerner 
5181273108faSLukas Czerner 	if (journal_dev_ro && !sb_rdonly(sb)) {
5182273108faSLukas Czerner 		ext4_msg(sb, KERN_ERR,
5183273108faSLukas Czerner 			 "journal device read-only, try mounting with '-o ro'");
5184273108faSLukas Czerner 		err = -EROFS;
5185273108faSLukas Czerner 		goto err_out;
5186273108faSLukas Czerner 	}
5187ac27a0ecSDave Kleikamp 
5188ac27a0ecSDave Kleikamp 	/*
5189ac27a0ecSDave Kleikamp 	 * Are we loading a blank journal or performing recovery after a
5190ac27a0ecSDave Kleikamp 	 * crash?  For recovery, we need to check in advance whether we
5191ac27a0ecSDave Kleikamp 	 * can get read-write access to the device.
5192ac27a0ecSDave Kleikamp 	 */
5193e2b911c5SDarrick J. Wong 	if (ext4_has_feature_journal_needs_recovery(sb)) {
5194bc98a42cSDavid Howells 		if (sb_rdonly(sb)) {
5195b31e1552SEric Sandeen 			ext4_msg(sb, KERN_INFO, "INFO: recovery "
5196b31e1552SEric Sandeen 					"required on readonly filesystem");
5197ac27a0ecSDave Kleikamp 			if (really_read_only) {
5198b31e1552SEric Sandeen 				ext4_msg(sb, KERN_ERR, "write access "
5199d98bf8cdSSimon Ruderich 					"unavailable, cannot proceed "
5200d98bf8cdSSimon Ruderich 					"(try mounting with noload)");
5201273108faSLukas Czerner 				err = -EROFS;
5202273108faSLukas Czerner 				goto err_out;
5203ac27a0ecSDave Kleikamp 			}
5204b31e1552SEric Sandeen 			ext4_msg(sb, KERN_INFO, "write access will "
5205b31e1552SEric Sandeen 			       "be enabled during recovery");
5206ac27a0ecSDave Kleikamp 		}
5207ac27a0ecSDave Kleikamp 	}
5208ac27a0ecSDave Kleikamp 
520990576c0bSTheodore Ts'o 	if (!(journal->j_flags & JBD2_BARRIER))
5210b31e1552SEric Sandeen 		ext4_msg(sb, KERN_INFO, "barriers disabled");
52114776004fSTheodore Ts'o 
5212e2b911c5SDarrick J. Wong 	if (!ext4_has_feature_journal_needs_recovery(sb))
5213dab291afSMingming Cao 		err = jbd2_journal_wipe(journal, !really_read_only);
52141c13d5c0STheodore Ts'o 	if (!err) {
52151c13d5c0STheodore Ts'o 		char *save = kmalloc(EXT4_S_ERR_LEN, GFP_KERNEL);
52161c13d5c0STheodore Ts'o 		if (save)
52171c13d5c0STheodore Ts'o 			memcpy(save, ((char *) es) +
52181c13d5c0STheodore Ts'o 			       EXT4_S_ERR_START, EXT4_S_ERR_LEN);
5219dab291afSMingming Cao 		err = jbd2_journal_load(journal);
52201c13d5c0STheodore Ts'o 		if (save)
52211c13d5c0STheodore Ts'o 			memcpy(((char *) es) + EXT4_S_ERR_START,
52221c13d5c0STheodore Ts'o 			       save, EXT4_S_ERR_LEN);
52231c13d5c0STheodore Ts'o 		kfree(save);
52241c13d5c0STheodore Ts'o 	}
5225ac27a0ecSDave Kleikamp 
5226ac27a0ecSDave Kleikamp 	if (err) {
5227b31e1552SEric Sandeen 		ext4_msg(sb, KERN_ERR, "error loading journal");
5228273108faSLukas Czerner 		goto err_out;
5229ac27a0ecSDave Kleikamp 	}
5230ac27a0ecSDave Kleikamp 
5231617ba13bSMingming Cao 	EXT4_SB(sb)->s_journal = journal;
523211215630SJan Kara 	err = ext4_clear_journal_err(sb, es);
523311215630SJan Kara 	if (err) {
523411215630SJan Kara 		EXT4_SB(sb)->s_journal = NULL;
523511215630SJan Kara 		jbd2_journal_destroy(journal);
523611215630SJan Kara 		return err;
523711215630SJan Kara 	}
5238ac27a0ecSDave Kleikamp 
5239c41303ceSMaciej Żenczykowski 	if (!really_read_only && journal_devnum &&
5240ac27a0ecSDave Kleikamp 	    journal_devnum != le32_to_cpu(es->s_journal_dev)) {
5241ac27a0ecSDave Kleikamp 		es->s_journal_dev = cpu_to_le32(journal_devnum);
5242ac27a0ecSDave Kleikamp 
5243ac27a0ecSDave Kleikamp 		/* Make sure we flush the recovery flag to disk. */
5244e2d67052STheodore Ts'o 		ext4_commit_super(sb, 1);
5245ac27a0ecSDave Kleikamp 	}
5246ac27a0ecSDave Kleikamp 
5247ac27a0ecSDave Kleikamp 	return 0;
5248273108faSLukas Czerner 
5249273108faSLukas Czerner err_out:
5250273108faSLukas Czerner 	jbd2_journal_destroy(journal);
5251273108faSLukas Czerner 	return err;
5252ac27a0ecSDave Kleikamp }
5253ac27a0ecSDave Kleikamp 
5254e2d67052STheodore Ts'o static int ext4_commit_super(struct super_block *sb, int sync)
5255ac27a0ecSDave Kleikamp {
5256e2d67052STheodore Ts'o 	struct ext4_super_block *es = EXT4_SB(sb)->s_es;
5257617ba13bSMingming Cao 	struct buffer_head *sbh = EXT4_SB(sb)->s_sbh;
5258c4be0c1dSTakashi Sato 	int error = 0;
5259ac27a0ecSDave Kleikamp 
5260bdfe0cbdSTheodore Ts'o 	if (!sbh || block_device_ejected(sb))
5261c4be0c1dSTakashi Sato 		return error;
5262a17712c8SJon Derrick 
5263a17712c8SJon Derrick 	/*
526471290b36STheodore Ts'o 	 * If the file system is mounted read-only, don't update the
526571290b36STheodore Ts'o 	 * superblock write time.  This avoids updating the superblock
526671290b36STheodore Ts'o 	 * write time when we are mounting the root file system
526771290b36STheodore Ts'o 	 * read/only but we need to replay the journal; at that point,
526871290b36STheodore Ts'o 	 * for people who are east of GMT and who make their clock
526971290b36STheodore Ts'o 	 * tick in localtime for Windows bug-for-bug compatibility,
527071290b36STheodore Ts'o 	 * the clock is set in the future, and this will cause e2fsck
527171290b36STheodore Ts'o 	 * to complain and force a full file system check.
527271290b36STheodore Ts'o 	 */
52731751e8a6SLinus Torvalds 	if (!(sb->s_flags & SB_RDONLY))
52746a0678a7SArnd Bergmann 		ext4_update_tstamp(es, s_wtime);
5275f613dfcbSTheodore Ts'o 	if (sb->s_bdev->bd_part)
5276afc32f7eSTheodore Ts'o 		es->s_kbytes_written =
5277afc32f7eSTheodore Ts'o 			cpu_to_le64(EXT4_SB(sb)->s_kbytes_written +
5278dbae2c55SMichael Callahan 			    ((part_stat_read(sb->s_bdev->bd_part,
5279dbae2c55SMichael Callahan 					     sectors[STAT_WRITE]) -
5280afc32f7eSTheodore Ts'o 			      EXT4_SB(sb)->s_sectors_written_start) >> 1));
5281f613dfcbSTheodore Ts'o 	else
5282f613dfcbSTheodore Ts'o 		es->s_kbytes_written =
5283f613dfcbSTheodore Ts'o 			cpu_to_le64(EXT4_SB(sb)->s_kbytes_written);
5284d5e03cbbSTheodore Ts'o 	if (percpu_counter_initialized(&EXT4_SB(sb)->s_freeclusters_counter))
528557042651STheodore Ts'o 		ext4_free_blocks_count_set(es,
528657042651STheodore Ts'o 			EXT4_C2B(EXT4_SB(sb), percpu_counter_sum_positive(
528757042651STheodore Ts'o 				&EXT4_SB(sb)->s_freeclusters_counter)));
5288d5e03cbbSTheodore Ts'o 	if (percpu_counter_initialized(&EXT4_SB(sb)->s_freeinodes_counter))
52897f93cff9STheodore Ts'o 		es->s_free_inodes_count =
52907f93cff9STheodore Ts'o 			cpu_to_le32(percpu_counter_sum_positive(
52915d1b1b3fSAneesh Kumar K.V 				&EXT4_SB(sb)->s_freeinodes_counter));
5292ac27a0ecSDave Kleikamp 	BUFFER_TRACE(sbh, "marking dirty");
529306db49e6STheodore Ts'o 	ext4_superblock_csum_set(sb);
52941566a48aSTheodore Ts'o 	if (sync)
52954743f839SPranay Kr. Srivastava 		lock_buffer(sbh);
5296e8680786STheodore Ts'o 	if (buffer_write_io_error(sbh) || !buffer_uptodate(sbh)) {
52974743f839SPranay Kr. Srivastava 		/*
52984743f839SPranay Kr. Srivastava 		 * Oh, dear.  A previous attempt to write the
52994743f839SPranay Kr. Srivastava 		 * superblock failed.  This could happen because the
53004743f839SPranay Kr. Srivastava 		 * USB device was yanked out.  Or it could happen to
53014743f839SPranay Kr. Srivastava 		 * be a transient write error and maybe the block will
53024743f839SPranay Kr. Srivastava 		 * be remapped.  Nothing we can do but to retry the
53034743f839SPranay Kr. Srivastava 		 * write and hope for the best.
53044743f839SPranay Kr. Srivastava 		 */
53054743f839SPranay Kr. Srivastava 		ext4_msg(sb, KERN_ERR, "previous I/O error to "
53064743f839SPranay Kr. Srivastava 		       "superblock detected");
53074743f839SPranay Kr. Srivastava 		clear_buffer_write_io_error(sbh);
53084743f839SPranay Kr. Srivastava 		set_buffer_uptodate(sbh);
53094743f839SPranay Kr. Srivastava 	}
5310ac27a0ecSDave Kleikamp 	mark_buffer_dirty(sbh);
5311914258bfSTheodore Ts'o 	if (sync) {
53121566a48aSTheodore Ts'o 		unlock_buffer(sbh);
5313564bc402SDaeho Jeong 		error = __sync_dirty_buffer(sbh,
531400473374SJan Kara 			REQ_SYNC | (test_opt(sb, BARRIER) ? REQ_FUA : 0));
5315c89128a0SJaegeuk Kim 		if (buffer_write_io_error(sbh)) {
5316b31e1552SEric Sandeen 			ext4_msg(sb, KERN_ERR, "I/O error while writing "
5317b31e1552SEric Sandeen 			       "superblock");
5318914258bfSTheodore Ts'o 			clear_buffer_write_io_error(sbh);
5319914258bfSTheodore Ts'o 			set_buffer_uptodate(sbh);
5320914258bfSTheodore Ts'o 		}
5321914258bfSTheodore Ts'o 	}
5322c4be0c1dSTakashi Sato 	return error;
5323ac27a0ecSDave Kleikamp }
5324ac27a0ecSDave Kleikamp 
5325ac27a0ecSDave Kleikamp /*
5326ac27a0ecSDave Kleikamp  * Have we just finished recovery?  If so, and if we are mounting (or
5327ac27a0ecSDave Kleikamp  * remounting) the filesystem readonly, then we will end up with a
5328ac27a0ecSDave Kleikamp  * consistent fs on disk.  Record that fact.
5329ac27a0ecSDave Kleikamp  */
533011215630SJan Kara static int ext4_mark_recovery_complete(struct super_block *sb,
5331617ba13bSMingming Cao 				       struct ext4_super_block *es)
5332ac27a0ecSDave Kleikamp {
533311215630SJan Kara 	int err;
5334617ba13bSMingming Cao 	journal_t *journal = EXT4_SB(sb)->s_journal;
5335ac27a0ecSDave Kleikamp 
5336e2b911c5SDarrick J. Wong 	if (!ext4_has_feature_journal(sb)) {
533711215630SJan Kara 		if (journal != NULL) {
533811215630SJan Kara 			ext4_error(sb, "Journal got removed while the fs was "
533911215630SJan Kara 				   "mounted!");
534011215630SJan Kara 			return -EFSCORRUPTED;
534111215630SJan Kara 		}
534211215630SJan Kara 		return 0;
53430390131bSFrank Mayhar 	}
5344dab291afSMingming Cao 	jbd2_journal_lock_updates(journal);
534511215630SJan Kara 	err = jbd2_journal_flush(journal);
534611215630SJan Kara 	if (err < 0)
53477ffe1ea8SHidehiro Kawai 		goto out;
53487ffe1ea8SHidehiro Kawai 
5349bc98a42cSDavid Howells 	if (ext4_has_feature_journal_needs_recovery(sb) && sb_rdonly(sb)) {
5350e2b911c5SDarrick J. Wong 		ext4_clear_feature_journal_needs_recovery(sb);
5351e2d67052STheodore Ts'o 		ext4_commit_super(sb, 1);
5352ac27a0ecSDave Kleikamp 	}
53537ffe1ea8SHidehiro Kawai out:
5354dab291afSMingming Cao 	jbd2_journal_unlock_updates(journal);
535511215630SJan Kara 	return err;
5356ac27a0ecSDave Kleikamp }
5357ac27a0ecSDave Kleikamp 
5358ac27a0ecSDave Kleikamp /*
5359ac27a0ecSDave Kleikamp  * If we are mounting (or read-write remounting) a filesystem whose journal
5360ac27a0ecSDave Kleikamp  * has recorded an error from a previous lifetime, move that error to the
5361ac27a0ecSDave Kleikamp  * main filesystem now.
5362ac27a0ecSDave Kleikamp  */
536311215630SJan Kara static int ext4_clear_journal_err(struct super_block *sb,
5364617ba13bSMingming Cao 				   struct ext4_super_block *es)
5365ac27a0ecSDave Kleikamp {
5366ac27a0ecSDave Kleikamp 	journal_t *journal;
5367ac27a0ecSDave Kleikamp 	int j_errno;
5368ac27a0ecSDave Kleikamp 	const char *errstr;
5369ac27a0ecSDave Kleikamp 
537011215630SJan Kara 	if (!ext4_has_feature_journal(sb)) {
537111215630SJan Kara 		ext4_error(sb, "Journal got removed while the fs was mounted!");
537211215630SJan Kara 		return -EFSCORRUPTED;
537311215630SJan Kara 	}
53740390131bSFrank Mayhar 
5375617ba13bSMingming Cao 	journal = EXT4_SB(sb)->s_journal;
5376ac27a0ecSDave Kleikamp 
5377ac27a0ecSDave Kleikamp 	/*
5378ac27a0ecSDave Kleikamp 	 * Now check for any error status which may have been recorded in the
5379617ba13bSMingming Cao 	 * journal by a prior ext4_error() or ext4_abort()
5380ac27a0ecSDave Kleikamp 	 */
5381ac27a0ecSDave Kleikamp 
5382dab291afSMingming Cao 	j_errno = jbd2_journal_errno(journal);
5383ac27a0ecSDave Kleikamp 	if (j_errno) {
5384ac27a0ecSDave Kleikamp 		char nbuf[16];
5385ac27a0ecSDave Kleikamp 
5386617ba13bSMingming Cao 		errstr = ext4_decode_error(sb, j_errno, nbuf);
538712062dddSEric Sandeen 		ext4_warning(sb, "Filesystem error recorded "
5388ac27a0ecSDave Kleikamp 			     "from previous mount: %s", errstr);
538912062dddSEric Sandeen 		ext4_warning(sb, "Marking fs in need of filesystem check.");
5390ac27a0ecSDave Kleikamp 
5391617ba13bSMingming Cao 		EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
5392617ba13bSMingming Cao 		es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
5393e2d67052STheodore Ts'o 		ext4_commit_super(sb, 1);
5394ac27a0ecSDave Kleikamp 
5395dab291afSMingming Cao 		jbd2_journal_clear_err(journal);
5396d796c52eSTheodore Ts'o 		jbd2_journal_update_sb_errno(journal);
5397ac27a0ecSDave Kleikamp 	}
539811215630SJan Kara 	return 0;
5399ac27a0ecSDave Kleikamp }
5400ac27a0ecSDave Kleikamp 
5401ac27a0ecSDave Kleikamp /*
5402ac27a0ecSDave Kleikamp  * Force the running and committing transactions to commit,
5403ac27a0ecSDave Kleikamp  * and wait on the commit.
5404ac27a0ecSDave Kleikamp  */
5405617ba13bSMingming Cao int ext4_force_commit(struct super_block *sb)
5406ac27a0ecSDave Kleikamp {
5407ac27a0ecSDave Kleikamp 	journal_t *journal;
5408ac27a0ecSDave Kleikamp 
5409bc98a42cSDavid Howells 	if (sb_rdonly(sb))
5410ac27a0ecSDave Kleikamp 		return 0;
5411ac27a0ecSDave Kleikamp 
5412617ba13bSMingming Cao 	journal = EXT4_SB(sb)->s_journal;
5413b1deefc9SGuo Chao 	return ext4_journal_force_commit(journal);
5414ac27a0ecSDave Kleikamp }
5415ac27a0ecSDave Kleikamp 
5416617ba13bSMingming Cao static int ext4_sync_fs(struct super_block *sb, int wait)
5417ac27a0ecSDave Kleikamp {
541814ce0cb4STheodore Ts'o 	int ret = 0;
54199eddacf9SJan Kara 	tid_t target;
542006a407f1SDmitry Monakhov 	bool needs_barrier = false;
54218d5d02e6SMingming Cao 	struct ext4_sb_info *sbi = EXT4_SB(sb);
5422ac27a0ecSDave Kleikamp 
542349598e04SJun Piao 	if (unlikely(ext4_forced_shutdown(sbi)))
54240db1ff22STheodore Ts'o 		return 0;
54250db1ff22STheodore Ts'o 
54269bffad1eSTheodore Ts'o 	trace_ext4_sync_fs(sb, wait);
54272e8fa54eSJan Kara 	flush_workqueue(sbi->rsv_conversion_wq);
5428a1177825SJan Kara 	/*
5429a1177825SJan Kara 	 * Writeback quota in non-journalled quota case - journalled quota has
5430a1177825SJan Kara 	 * no dirty dquots
5431a1177825SJan Kara 	 */
5432a1177825SJan Kara 	dquot_writeback_dquots(sb, -1);
543306a407f1SDmitry Monakhov 	/*
543406a407f1SDmitry Monakhov 	 * Data writeback is possible w/o journal transaction, so barrier must
543506a407f1SDmitry Monakhov 	 * being sent at the end of the function. But we can skip it if
543606a407f1SDmitry Monakhov 	 * transaction_commit will do it for us.
543706a407f1SDmitry Monakhov 	 */
5438bda32530STheodore Ts'o 	if (sbi->s_journal) {
543906a407f1SDmitry Monakhov 		target = jbd2_get_latest_transaction(sbi->s_journal);
544006a407f1SDmitry Monakhov 		if (wait && sbi->s_journal->j_flags & JBD2_BARRIER &&
544106a407f1SDmitry Monakhov 		    !jbd2_trans_will_send_data_barrier(sbi->s_journal, target))
544206a407f1SDmitry Monakhov 			needs_barrier = true;
544306a407f1SDmitry Monakhov 
54448d5d02e6SMingming Cao 		if (jbd2_journal_start_commit(sbi->s_journal, &target)) {
5445ac27a0ecSDave Kleikamp 			if (wait)
5446bda32530STheodore Ts'o 				ret = jbd2_log_wait_commit(sbi->s_journal,
5447bda32530STheodore Ts'o 							   target);
54480390131bSFrank Mayhar 		}
5449bda32530STheodore Ts'o 	} else if (wait && test_opt(sb, BARRIER))
5450bda32530STheodore Ts'o 		needs_barrier = true;
545106a407f1SDmitry Monakhov 	if (needs_barrier) {
545206a407f1SDmitry Monakhov 		int err;
54539398554fSChristoph Hellwig 		err = blkdev_issue_flush(sb->s_bdev, GFP_KERNEL);
545406a407f1SDmitry Monakhov 		if (!ret)
545506a407f1SDmitry Monakhov 			ret = err;
545606a407f1SDmitry Monakhov 	}
545706a407f1SDmitry Monakhov 
545806a407f1SDmitry Monakhov 	return ret;
545906a407f1SDmitry Monakhov }
546006a407f1SDmitry Monakhov 
5461ac27a0ecSDave Kleikamp /*
5462ac27a0ecSDave Kleikamp  * LVM calls this function before a (read-only) snapshot is created.  This
5463ac27a0ecSDave Kleikamp  * gives us a chance to flush the journal completely and mark the fs clean.
5464be4f27d3SYongqiang Yang  *
5465be4f27d3SYongqiang Yang  * Note that only this function cannot bring a filesystem to be in a clean
54668e8ad8a5SJan Kara  * state independently. It relies on upper layer to stop all data & metadata
54678e8ad8a5SJan Kara  * modifications.
5468ac27a0ecSDave Kleikamp  */
5469c4be0c1dSTakashi Sato static int ext4_freeze(struct super_block *sb)
5470ac27a0ecSDave Kleikamp {
5471c4be0c1dSTakashi Sato 	int error = 0;
5472c4be0c1dSTakashi Sato 	journal_t *journal;
5473ac27a0ecSDave Kleikamp 
5474bc98a42cSDavid Howells 	if (sb_rdonly(sb))
54759ca92389STheodore Ts'o 		return 0;
54769ca92389STheodore Ts'o 
5477c4be0c1dSTakashi Sato 	journal = EXT4_SB(sb)->s_journal;
5478ac27a0ecSDave Kleikamp 
5479bb044576STheodore Ts'o 	if (journal) {
5480ac27a0ecSDave Kleikamp 		/* Now we set up the journal barrier. */
5481dab291afSMingming Cao 		jbd2_journal_lock_updates(journal);
54827ffe1ea8SHidehiro Kawai 
54837ffe1ea8SHidehiro Kawai 		/*
5484bb044576STheodore Ts'o 		 * Don't clear the needs_recovery flag if we failed to
5485bb044576STheodore Ts'o 		 * flush the journal.
54867ffe1ea8SHidehiro Kawai 		 */
5487c4be0c1dSTakashi Sato 		error = jbd2_journal_flush(journal);
54886b0310fbSEric Sandeen 		if (error < 0)
54896b0310fbSEric Sandeen 			goto out;
5490ac27a0ecSDave Kleikamp 
5491ac27a0ecSDave Kleikamp 		/* Journal blocked and flushed, clear needs_recovery flag. */
5492e2b911c5SDarrick J. Wong 		ext4_clear_feature_journal_needs_recovery(sb);
5493c642dc9eSEric Sandeen 	}
5494c642dc9eSEric Sandeen 
5495e2d67052STheodore Ts'o 	error = ext4_commit_super(sb, 1);
54966b0310fbSEric Sandeen out:
5497bb044576STheodore Ts'o 	if (journal)
54988e8ad8a5SJan Kara 		/* we rely on upper layer to stop further updates */
5499bb044576STheodore Ts'o 		jbd2_journal_unlock_updates(journal);
55006b0310fbSEric Sandeen 	return error;
5501ac27a0ecSDave Kleikamp }
5502ac27a0ecSDave Kleikamp 
5503ac27a0ecSDave Kleikamp /*
5504ac27a0ecSDave Kleikamp  * Called by LVM after the snapshot is done.  We need to reset the RECOVER
5505ac27a0ecSDave Kleikamp  * flag here, even though the filesystem is not technically dirty yet.
5506ac27a0ecSDave Kleikamp  */
5507c4be0c1dSTakashi Sato static int ext4_unfreeze(struct super_block *sb)
5508ac27a0ecSDave Kleikamp {
5509bc98a42cSDavid Howells 	if (sb_rdonly(sb) || ext4_forced_shutdown(EXT4_SB(sb)))
55109ca92389STheodore Ts'o 		return 0;
55119ca92389STheodore Ts'o 
5512c642dc9eSEric Sandeen 	if (EXT4_SB(sb)->s_journal) {
55139ca92389STheodore Ts'o 		/* Reset the needs_recovery flag before the fs is unlocked. */
5514e2b911c5SDarrick J. Wong 		ext4_set_feature_journal_needs_recovery(sb);
5515c642dc9eSEric Sandeen 	}
5516c642dc9eSEric Sandeen 
5517e2d67052STheodore Ts'o 	ext4_commit_super(sb, 1);
5518c4be0c1dSTakashi Sato 	return 0;
5519ac27a0ecSDave Kleikamp }
5520ac27a0ecSDave Kleikamp 
5521673c6100STheodore Ts'o /*
5522673c6100STheodore Ts'o  * Structure to save mount options for ext4_remount's benefit
5523673c6100STheodore Ts'o  */
5524673c6100STheodore Ts'o struct ext4_mount_options {
5525673c6100STheodore Ts'o 	unsigned long s_mount_opt;
5526a2595b8aSTheodore Ts'o 	unsigned long s_mount_opt2;
552708cefc7aSEric W. Biederman 	kuid_t s_resuid;
552808cefc7aSEric W. Biederman 	kgid_t s_resgid;
5529673c6100STheodore Ts'o 	unsigned long s_commit_interval;
5530673c6100STheodore Ts'o 	u32 s_min_batch_time, s_max_batch_time;
5531673c6100STheodore Ts'o #ifdef CONFIG_QUOTA
5532673c6100STheodore Ts'o 	int s_jquota_fmt;
5533a2d4a646SJan Kara 	char *s_qf_names[EXT4_MAXQUOTAS];
5534673c6100STheodore Ts'o #endif
5535673c6100STheodore Ts'o };
5536673c6100STheodore Ts'o 
5537617ba13bSMingming Cao static int ext4_remount(struct super_block *sb, int *flags, char *data)
5538ac27a0ecSDave Kleikamp {
5539617ba13bSMingming Cao 	struct ext4_super_block *es;
5540617ba13bSMingming Cao 	struct ext4_sb_info *sbi = EXT4_SB(sb);
5541f25391ebSLukas Czerner 	unsigned long old_sb_flags, vfs_flags;
5542617ba13bSMingming Cao 	struct ext4_mount_options old_opts;
5543c79d967dSChristoph Hellwig 	int enable_quota = 0;
55448a266467STheodore Ts'o 	ext4_group_t g;
5545b3881f74STheodore Ts'o 	unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO;
5546c5e06d10SJohann Lombardi 	int err = 0;
5547ac27a0ecSDave Kleikamp #ifdef CONFIG_QUOTA
554803dafb5fSChen Gang 	int i, j;
554933458eabSTheodore Ts'o 	char *to_free[EXT4_MAXQUOTAS];
5550ac27a0ecSDave Kleikamp #endif
5551d4c402d9SCurt Wohlgemuth 	char *orig_data = kstrdup(data, GFP_KERNEL);
5552ac27a0ecSDave Kleikamp 
555321ac738eSChengguang Xu 	if (data && !orig_data)
555421ac738eSChengguang Xu 		return -ENOMEM;
555521ac738eSChengguang Xu 
5556ac27a0ecSDave Kleikamp 	/* Store the original options */
5557ac27a0ecSDave Kleikamp 	old_sb_flags = sb->s_flags;
5558ac27a0ecSDave Kleikamp 	old_opts.s_mount_opt = sbi->s_mount_opt;
5559a2595b8aSTheodore Ts'o 	old_opts.s_mount_opt2 = sbi->s_mount_opt2;
5560ac27a0ecSDave Kleikamp 	old_opts.s_resuid = sbi->s_resuid;
5561ac27a0ecSDave Kleikamp 	old_opts.s_resgid = sbi->s_resgid;
5562ac27a0ecSDave Kleikamp 	old_opts.s_commit_interval = sbi->s_commit_interval;
556330773840STheodore Ts'o 	old_opts.s_min_batch_time = sbi->s_min_batch_time;
556430773840STheodore Ts'o 	old_opts.s_max_batch_time = sbi->s_max_batch_time;
5565ac27a0ecSDave Kleikamp #ifdef CONFIG_QUOTA
5566ac27a0ecSDave Kleikamp 	old_opts.s_jquota_fmt = sbi->s_jquota_fmt;
5567a2d4a646SJan Kara 	for (i = 0; i < EXT4_MAXQUOTAS; i++)
556803dafb5fSChen Gang 		if (sbi->s_qf_names[i]) {
556933458eabSTheodore Ts'o 			char *qf_name = get_qf_name(sb, sbi, i);
557033458eabSTheodore Ts'o 
557133458eabSTheodore Ts'o 			old_opts.s_qf_names[i] = kstrdup(qf_name, GFP_KERNEL);
557203dafb5fSChen Gang 			if (!old_opts.s_qf_names[i]) {
557303dafb5fSChen Gang 				for (j = 0; j < i; j++)
557403dafb5fSChen Gang 					kfree(old_opts.s_qf_names[j]);
55753e36a163SWei Yongjun 				kfree(orig_data);
557603dafb5fSChen Gang 				return -ENOMEM;
557703dafb5fSChen Gang 			}
557803dafb5fSChen Gang 		} else
557903dafb5fSChen Gang 			old_opts.s_qf_names[i] = NULL;
5580ac27a0ecSDave Kleikamp #endif
5581b3881f74STheodore Ts'o 	if (sbi->s_journal && sbi->s_journal->j_task->io_context)
5582b3881f74STheodore Ts'o 		journal_ioprio = sbi->s_journal->j_task->io_context->ioprio;
5583ac27a0ecSDave Kleikamp 
5584f25391ebSLukas Czerner 	/*
5585f25391ebSLukas Czerner 	 * Some options can be enabled by ext4 and/or by VFS mount flag
5586f25391ebSLukas Czerner 	 * either way we need to make sure it matches in both *flags and
5587f25391ebSLukas Czerner 	 * s_flags. Copy those selected flags from *flags to s_flags
5588f25391ebSLukas Czerner 	 */
5589f25391ebSLukas Czerner 	vfs_flags = SB_LAZYTIME | SB_I_VERSION;
5590f25391ebSLukas Czerner 	sb->s_flags = (sb->s_flags & ~vfs_flags) | (*flags & vfs_flags);
5591f25391ebSLukas Czerner 
5592661aa520SEric Sandeen 	if (!parse_options(data, sb, NULL, &journal_ioprio, 1)) {
5593ac27a0ecSDave Kleikamp 		err = -EINVAL;
5594ac27a0ecSDave Kleikamp 		goto restore_opts;
5595ac27a0ecSDave Kleikamp 	}
5596ac27a0ecSDave Kleikamp 
55976b992ff2SDarrick J. Wong 	if ((old_opts.s_mount_opt & EXT4_MOUNT_JOURNAL_CHECKSUM) ^
55986b992ff2SDarrick J. Wong 	    test_opt(sb, JOURNAL_CHECKSUM)) {
55996b992ff2SDarrick J. Wong 		ext4_msg(sb, KERN_ERR, "changing journal_checksum "
56002d5b86e0SEric Sandeen 			 "during remount not supported; ignoring");
56012d5b86e0SEric Sandeen 		sbi->s_mount_opt ^= EXT4_MOUNT_JOURNAL_CHECKSUM;
5602c6d3d56dSDarrick J. Wong 	}
5603c6d3d56dSDarrick J. Wong 
56046ae6514bSPiotr Sarna 	if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) {
56056ae6514bSPiotr Sarna 		if (test_opt2(sb, EXPLICIT_DELALLOC)) {
56066ae6514bSPiotr Sarna 			ext4_msg(sb, KERN_ERR, "can't mount with "
56076ae6514bSPiotr Sarna 				 "both data=journal and delalloc");
56086ae6514bSPiotr Sarna 			err = -EINVAL;
56096ae6514bSPiotr Sarna 			goto restore_opts;
56106ae6514bSPiotr Sarna 		}
56116ae6514bSPiotr Sarna 		if (test_opt(sb, DIOREAD_NOLOCK)) {
56126ae6514bSPiotr Sarna 			ext4_msg(sb, KERN_ERR, "can't mount with "
56136ae6514bSPiotr Sarna 				 "both data=journal and dioread_nolock");
56146ae6514bSPiotr Sarna 			err = -EINVAL;
56156ae6514bSPiotr Sarna 			goto restore_opts;
56166ae6514bSPiotr Sarna 		}
5617ab04df78SJan Kara 	} else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA) {
5618ab04df78SJan Kara 		if (test_opt(sb, JOURNAL_ASYNC_COMMIT)) {
5619ab04df78SJan Kara 			ext4_msg(sb, KERN_ERR, "can't mount with "
5620ab04df78SJan Kara 				"journal_async_commit in data=ordered mode");
5621ab04df78SJan Kara 			err = -EINVAL;
5622ab04df78SJan Kara 			goto restore_opts;
5623ab04df78SJan Kara 		}
5624923ae0ffSRoss Zwisler 	}
5625923ae0ffSRoss Zwisler 
5626cdb7ee4cSTahsin Erdogan 	if ((sbi->s_mount_opt ^ old_opts.s_mount_opt) & EXT4_MOUNT_NO_MBCACHE) {
5627cdb7ee4cSTahsin Erdogan 		ext4_msg(sb, KERN_ERR, "can't enable nombcache during remount");
5628cdb7ee4cSTahsin Erdogan 		err = -EINVAL;
5629cdb7ee4cSTahsin Erdogan 		goto restore_opts;
5630cdb7ee4cSTahsin Erdogan 	}
5631cdb7ee4cSTahsin Erdogan 
56324ab2f15bSTheodore Ts'o 	if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED)
563354d3adbcSTheodore Ts'o 		ext4_abort(sb, EXT4_ERR_ESHUTDOWN, "Abort forced by user");
5634ac27a0ecSDave Kleikamp 
56351751e8a6SLinus Torvalds 	sb->s_flags = (sb->s_flags & ~SB_POSIXACL) |
56361751e8a6SLinus Torvalds 		(test_opt(sb, POSIX_ACL) ? SB_POSIXACL : 0);
5637ac27a0ecSDave Kleikamp 
5638ac27a0ecSDave Kleikamp 	es = sbi->s_es;
5639ac27a0ecSDave Kleikamp 
5640b3881f74STheodore Ts'o 	if (sbi->s_journal) {
5641617ba13bSMingming Cao 		ext4_init_journal_params(sb, sbi->s_journal);
5642b3881f74STheodore Ts'o 		set_task_ioprio(sbi->s_journal->j_task, journal_ioprio);
5643b3881f74STheodore Ts'o 	}
5644ac27a0ecSDave Kleikamp 
56451751e8a6SLinus Torvalds 	if ((bool)(*flags & SB_RDONLY) != sb_rdonly(sb)) {
56464ab2f15bSTheodore Ts'o 		if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED) {
5647ac27a0ecSDave Kleikamp 			err = -EROFS;
5648ac27a0ecSDave Kleikamp 			goto restore_opts;
5649ac27a0ecSDave Kleikamp 		}
5650ac27a0ecSDave Kleikamp 
56511751e8a6SLinus Torvalds 		if (*flags & SB_RDONLY) {
565238c03b34STheodore Ts'o 			err = sync_filesystem(sb);
565338c03b34STheodore Ts'o 			if (err < 0)
565438c03b34STheodore Ts'o 				goto restore_opts;
56550f0dd62fSChristoph Hellwig 			err = dquot_suspend(sb, -1);
56560f0dd62fSChristoph Hellwig 			if (err < 0)
5657c79d967dSChristoph Hellwig 				goto restore_opts;
5658c79d967dSChristoph Hellwig 
5659ac27a0ecSDave Kleikamp 			/*
5660ac27a0ecSDave Kleikamp 			 * First of all, the unconditional stuff we have to do
5661ac27a0ecSDave Kleikamp 			 * to disable replay of the journal when we next remount
5662ac27a0ecSDave Kleikamp 			 */
56631751e8a6SLinus Torvalds 			sb->s_flags |= SB_RDONLY;
5664ac27a0ecSDave Kleikamp 
5665ac27a0ecSDave Kleikamp 			/*
5666ac27a0ecSDave Kleikamp 			 * OK, test if we are remounting a valid rw partition
5667ac27a0ecSDave Kleikamp 			 * readonly, and if so set the rdonly flag and then
5668ac27a0ecSDave Kleikamp 			 * mark the partition as valid again.
5669ac27a0ecSDave Kleikamp 			 */
5670617ba13bSMingming Cao 			if (!(es->s_state & cpu_to_le16(EXT4_VALID_FS)) &&
5671617ba13bSMingming Cao 			    (sbi->s_mount_state & EXT4_VALID_FS))
5672ac27a0ecSDave Kleikamp 				es->s_state = cpu_to_le16(sbi->s_mount_state);
5673ac27a0ecSDave Kleikamp 
567411215630SJan Kara 			if (sbi->s_journal) {
567511215630SJan Kara 				/*
567611215630SJan Kara 				 * We let remount-ro finish even if marking fs
567711215630SJan Kara 				 * as clean failed...
567811215630SJan Kara 				 */
5679617ba13bSMingming Cao 				ext4_mark_recovery_complete(sb, es);
568011215630SJan Kara 			}
56812dca60d9STheodore Ts'o 			if (sbi->s_mmp_tsk)
56822dca60d9STheodore Ts'o 				kthread_stop(sbi->s_mmp_tsk);
5683ac27a0ecSDave Kleikamp 		} else {
5684a13fb1a4SEric Sandeen 			/* Make sure we can mount this feature set readwrite */
5685e2b911c5SDarrick J. Wong 			if (ext4_has_feature_readonly(sb) ||
56862cb5cc8bSDarrick J. Wong 			    !ext4_feature_set_ok(sb, 0)) {
5687ac27a0ecSDave Kleikamp 				err = -EROFS;
5688ac27a0ecSDave Kleikamp 				goto restore_opts;
5689ac27a0ecSDave Kleikamp 			}
5690ead6596bSEric Sandeen 			/*
56918a266467STheodore Ts'o 			 * Make sure the group descriptor checksums
56920b8e58a1SAndreas Dilger 			 * are sane.  If they aren't, refuse to remount r/w.
56938a266467STheodore Ts'o 			 */
56948a266467STheodore Ts'o 			for (g = 0; g < sbi->s_groups_count; g++) {
56958a266467STheodore Ts'o 				struct ext4_group_desc *gdp =
56968a266467STheodore Ts'o 					ext4_get_group_desc(sb, g, NULL);
56978a266467STheodore Ts'o 
5698feb0ab32SDarrick J. Wong 				if (!ext4_group_desc_csum_verify(sb, g, gdp)) {
5699b31e1552SEric Sandeen 					ext4_msg(sb, KERN_ERR,
5700b31e1552SEric Sandeen 	       "ext4_remount: Checksum for group %u failed (%u!=%u)",
5701e2b911c5SDarrick J. Wong 		g, le16_to_cpu(ext4_group_desc_csum(sb, g, gdp)),
57028a266467STheodore Ts'o 					       le16_to_cpu(gdp->bg_checksum));
57036a797d27SDarrick J. Wong 					err = -EFSBADCRC;
57048a266467STheodore Ts'o 					goto restore_opts;
57058a266467STheodore Ts'o 				}
57068a266467STheodore Ts'o 			}
57078a266467STheodore Ts'o 
57088a266467STheodore Ts'o 			/*
5709ead6596bSEric Sandeen 			 * If we have an unprocessed orphan list hanging
5710ead6596bSEric Sandeen 			 * around from a previously readonly bdev mount,
5711ead6596bSEric Sandeen 			 * require a full umount/remount for now.
5712ead6596bSEric Sandeen 			 */
5713ead6596bSEric Sandeen 			if (es->s_last_orphan) {
5714b31e1552SEric Sandeen 				ext4_msg(sb, KERN_WARNING, "Couldn't "
5715ead6596bSEric Sandeen 				       "remount RDWR because of unprocessed "
5716ead6596bSEric Sandeen 				       "orphan inode list.  Please "
5717b31e1552SEric Sandeen 				       "umount/remount instead");
5718ead6596bSEric Sandeen 				err = -EINVAL;
5719ead6596bSEric Sandeen 				goto restore_opts;
5720ead6596bSEric Sandeen 			}
5721ead6596bSEric Sandeen 
5722ac27a0ecSDave Kleikamp 			/*
5723bc71726cSzhangyi (F) 			 * Update the original bdev mapping's wb_err value
5724bc71726cSzhangyi (F) 			 * which could be used to detect the metadata async
5725bc71726cSzhangyi (F) 			 * write error.
5726bc71726cSzhangyi (F) 			 */
5727bc71726cSzhangyi (F) 			errseq_check_and_advance(&sb->s_bdev->bd_inode->i_mapping->wb_err,
5728bc71726cSzhangyi (F) 						 &sbi->s_bdev_wb_err);
5729bc71726cSzhangyi (F) 
5730bc71726cSzhangyi (F) 			/*
5731ac27a0ecSDave Kleikamp 			 * Mounting a RDONLY partition read-write, so reread
5732ac27a0ecSDave Kleikamp 			 * and store the current valid flag.  (It may have
5733ac27a0ecSDave Kleikamp 			 * been changed by e2fsck since we originally mounted
5734ac27a0ecSDave Kleikamp 			 * the partition.)
5735ac27a0ecSDave Kleikamp 			 */
573611215630SJan Kara 			if (sbi->s_journal) {
573711215630SJan Kara 				err = ext4_clear_journal_err(sb, es);
573811215630SJan Kara 				if (err)
573911215630SJan Kara 					goto restore_opts;
574011215630SJan Kara 			}
5741ac27a0ecSDave Kleikamp 			sbi->s_mount_state = le16_to_cpu(es->s_state);
5742c89128a0SJaegeuk Kim 
5743c89128a0SJaegeuk Kim 			err = ext4_setup_super(sb, es, 0);
5744c89128a0SJaegeuk Kim 			if (err)
5745c89128a0SJaegeuk Kim 				goto restore_opts;
5746c89128a0SJaegeuk Kim 
57471751e8a6SLinus Torvalds 			sb->s_flags &= ~SB_RDONLY;
5748e2b911c5SDarrick J. Wong 			if (ext4_has_feature_mmp(sb))
5749c5e06d10SJohann Lombardi 				if (ext4_multi_mount_protect(sb,
5750c5e06d10SJohann Lombardi 						le64_to_cpu(es->s_mmp_block))) {
5751c5e06d10SJohann Lombardi 					err = -EROFS;
5752c5e06d10SJohann Lombardi 					goto restore_opts;
5753c5e06d10SJohann Lombardi 				}
5754c79d967dSChristoph Hellwig 			enable_quota = 1;
5755ac27a0ecSDave Kleikamp 		}
5756ac27a0ecSDave Kleikamp 	}
5757bfff6873SLukas Czerner 
5758bfff6873SLukas Czerner 	/*
5759bfff6873SLukas Czerner 	 * Reinitialize lazy itable initialization thread based on
5760bfff6873SLukas Czerner 	 * current settings
5761bfff6873SLukas Czerner 	 */
5762bc98a42cSDavid Howells 	if (sb_rdonly(sb) || !test_opt(sb, INIT_INODE_TABLE))
5763bfff6873SLukas Czerner 		ext4_unregister_li_request(sb);
5764bfff6873SLukas Czerner 	else {
5765bfff6873SLukas Czerner 		ext4_group_t first_not_zeroed;
5766bfff6873SLukas Czerner 		first_not_zeroed = ext4_has_uninit_itable(sb);
5767bfff6873SLukas Czerner 		ext4_register_li_request(sb, first_not_zeroed);
5768bfff6873SLukas Czerner 	}
5769bfff6873SLukas Czerner 
57700f5bde1dSJan Kara 	/*
57710f5bde1dSJan Kara 	 * Handle creation of system zone data early because it can fail.
57720f5bde1dSJan Kara 	 * Releasing of existing data is done when we are sure remount will
57730f5bde1dSJan Kara 	 * succeed.
57740f5bde1dSJan Kara 	 */
5775*dd0db94fSChunguang Xu 	if (test_opt(sb, BLOCK_VALIDITY) && !sbi->s_system_blks) {
5776d176b1f6SJan Kara 		err = ext4_setup_system_zone(sb);
5777d176b1f6SJan Kara 		if (err)
5778d176b1f6SJan Kara 			goto restore_opts;
57790f5bde1dSJan Kara 	}
5780d176b1f6SJan Kara 
5781c89128a0SJaegeuk Kim 	if (sbi->s_journal == NULL && !(old_sb_flags & SB_RDONLY)) {
5782c89128a0SJaegeuk Kim 		err = ext4_commit_super(sb, 1);
5783c89128a0SJaegeuk Kim 		if (err)
5784c89128a0SJaegeuk Kim 			goto restore_opts;
5785c89128a0SJaegeuk Kim 	}
57860390131bSFrank Mayhar 
5787ac27a0ecSDave Kleikamp #ifdef CONFIG_QUOTA
5788ac27a0ecSDave Kleikamp 	/* Release old quota file names */
5789a2d4a646SJan Kara 	for (i = 0; i < EXT4_MAXQUOTAS; i++)
5790ac27a0ecSDave Kleikamp 		kfree(old_opts.s_qf_names[i]);
57917c319d32SAditya Kali 	if (enable_quota) {
57927c319d32SAditya Kali 		if (sb_any_quota_suspended(sb))
57930f0dd62fSChristoph Hellwig 			dquot_resume(sb, -1);
5794e2b911c5SDarrick J. Wong 		else if (ext4_has_feature_quota(sb)) {
57957c319d32SAditya Kali 			err = ext4_enable_quotas(sb);
579607724f98STheodore Ts'o 			if (err)
57977c319d32SAditya Kali 				goto restore_opts;
57987c319d32SAditya Kali 		}
57997c319d32SAditya Kali 	}
58007c319d32SAditya Kali #endif
5801*dd0db94fSChunguang Xu 	if (!test_opt(sb, BLOCK_VALIDITY) && sbi->s_system_blks)
58020f5bde1dSJan Kara 		ext4_release_system_zone(sb);
5803d4c402d9SCurt Wohlgemuth 
5804f25391ebSLukas Czerner 	/*
5805f25391ebSLukas Czerner 	 * Some options can be enabled by ext4 and/or by VFS mount flag
5806f25391ebSLukas Czerner 	 * either way we need to make sure it matches in both *flags and
5807f25391ebSLukas Czerner 	 * s_flags. Copy those selected flags from s_flags to *flags
5808f25391ebSLukas Czerner 	 */
5809f25391ebSLukas Czerner 	*flags = (*flags & ~vfs_flags) | (sb->s_flags & vfs_flags);
5810f25391ebSLukas Czerner 
5811d4c402d9SCurt Wohlgemuth 	ext4_msg(sb, KERN_INFO, "re-mounted. Opts: %s", orig_data);
5812d4c402d9SCurt Wohlgemuth 	kfree(orig_data);
5813ac27a0ecSDave Kleikamp 	return 0;
58140b8e58a1SAndreas Dilger 
5815ac27a0ecSDave Kleikamp restore_opts:
5816ac27a0ecSDave Kleikamp 	sb->s_flags = old_sb_flags;
5817ac27a0ecSDave Kleikamp 	sbi->s_mount_opt = old_opts.s_mount_opt;
5818a2595b8aSTheodore Ts'o 	sbi->s_mount_opt2 = old_opts.s_mount_opt2;
5819ac27a0ecSDave Kleikamp 	sbi->s_resuid = old_opts.s_resuid;
5820ac27a0ecSDave Kleikamp 	sbi->s_resgid = old_opts.s_resgid;
5821ac27a0ecSDave Kleikamp 	sbi->s_commit_interval = old_opts.s_commit_interval;
582230773840STheodore Ts'o 	sbi->s_min_batch_time = old_opts.s_min_batch_time;
582330773840STheodore Ts'o 	sbi->s_max_batch_time = old_opts.s_max_batch_time;
5824*dd0db94fSChunguang Xu 	if (!test_opt(sb, BLOCK_VALIDITY) && sbi->s_system_blks)
58250f5bde1dSJan Kara 		ext4_release_system_zone(sb);
5826ac27a0ecSDave Kleikamp #ifdef CONFIG_QUOTA
5827ac27a0ecSDave Kleikamp 	sbi->s_jquota_fmt = old_opts.s_jquota_fmt;
5828a2d4a646SJan Kara 	for (i = 0; i < EXT4_MAXQUOTAS; i++) {
582933458eabSTheodore Ts'o 		to_free[i] = get_qf_name(sb, sbi, i);
583033458eabSTheodore Ts'o 		rcu_assign_pointer(sbi->s_qf_names[i], old_opts.s_qf_names[i]);
5831ac27a0ecSDave Kleikamp 	}
583233458eabSTheodore Ts'o 	synchronize_rcu();
583333458eabSTheodore Ts'o 	for (i = 0; i < EXT4_MAXQUOTAS; i++)
583433458eabSTheodore Ts'o 		kfree(to_free[i]);
5835ac27a0ecSDave Kleikamp #endif
5836d4c402d9SCurt Wohlgemuth 	kfree(orig_data);
5837ac27a0ecSDave Kleikamp 	return err;
5838ac27a0ecSDave Kleikamp }
5839ac27a0ecSDave Kleikamp 
5840689c958cSLi Xi #ifdef CONFIG_QUOTA
5841689c958cSLi Xi static int ext4_statfs_project(struct super_block *sb,
5842689c958cSLi Xi 			       kprojid_t projid, struct kstatfs *buf)
5843689c958cSLi Xi {
5844689c958cSLi Xi 	struct kqid qid;
5845689c958cSLi Xi 	struct dquot *dquot;
5846689c958cSLi Xi 	u64 limit;
5847689c958cSLi Xi 	u64 curblock;
5848689c958cSLi Xi 
5849689c958cSLi Xi 	qid = make_kqid_projid(projid);
5850689c958cSLi Xi 	dquot = dqget(sb, qid);
5851689c958cSLi Xi 	if (IS_ERR(dquot))
5852689c958cSLi Xi 		return PTR_ERR(dquot);
58537b9ca4c6SJan Kara 	spin_lock(&dquot->dq_dqb_lock);
5854689c958cSLi Xi 
5855a08fe66eSChengguang Xu 	limit = min_not_zero(dquot->dq_dqb.dqb_bsoftlimit,
5856a08fe66eSChengguang Xu 			     dquot->dq_dqb.dqb_bhardlimit);
585757c32ea4SChengguang Xu 	limit >>= sb->s_blocksize_bits;
585857c32ea4SChengguang Xu 
5859689c958cSLi Xi 	if (limit && buf->f_blocks > limit) {
5860f06925c7SKonstantin Khlebnikov 		curblock = (dquot->dq_dqb.dqb_curspace +
5861f06925c7SKonstantin Khlebnikov 			    dquot->dq_dqb.dqb_rsvspace) >> sb->s_blocksize_bits;
5862689c958cSLi Xi 		buf->f_blocks = limit;
5863689c958cSLi Xi 		buf->f_bfree = buf->f_bavail =
5864689c958cSLi Xi 			(buf->f_blocks > curblock) ?
5865689c958cSLi Xi 			 (buf->f_blocks - curblock) : 0;
5866689c958cSLi Xi 	}
5867689c958cSLi Xi 
5868a08fe66eSChengguang Xu 	limit = min_not_zero(dquot->dq_dqb.dqb_isoftlimit,
5869a08fe66eSChengguang Xu 			     dquot->dq_dqb.dqb_ihardlimit);
5870689c958cSLi Xi 	if (limit && buf->f_files > limit) {
5871689c958cSLi Xi 		buf->f_files = limit;
5872689c958cSLi Xi 		buf->f_ffree =
5873689c958cSLi Xi 			(buf->f_files > dquot->dq_dqb.dqb_curinodes) ?
5874689c958cSLi Xi 			 (buf->f_files - dquot->dq_dqb.dqb_curinodes) : 0;
5875689c958cSLi Xi 	}
5876689c958cSLi Xi 
58777b9ca4c6SJan Kara 	spin_unlock(&dquot->dq_dqb_lock);
5878689c958cSLi Xi 	dqput(dquot);
5879689c958cSLi Xi 	return 0;
5880689c958cSLi Xi }
5881689c958cSLi Xi #endif
5882689c958cSLi Xi 
5883617ba13bSMingming Cao static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)
5884ac27a0ecSDave Kleikamp {
5885ac27a0ecSDave Kleikamp 	struct super_block *sb = dentry->d_sb;
5886617ba13bSMingming Cao 	struct ext4_sb_info *sbi = EXT4_SB(sb);
5887617ba13bSMingming Cao 	struct ext4_super_block *es = sbi->s_es;
588827dd4385SLukas Czerner 	ext4_fsblk_t overhead = 0, resv_blocks;
5889960cc398SPekka Enberg 	u64 fsid;
5890d02a9391SKazuya Mio 	s64 bfree;
589127dd4385SLukas Czerner 	resv_blocks = EXT4_C2B(sbi, atomic64_read(&sbi->s_resv_clusters));
5892ac27a0ecSDave Kleikamp 
5893952fc18eSTheodore Ts'o 	if (!test_opt(sb, MINIX_DF))
5894952fc18eSTheodore Ts'o 		overhead = sbi->s_overhead;
5895ac27a0ecSDave Kleikamp 
5896617ba13bSMingming Cao 	buf->f_type = EXT4_SUPER_MAGIC;
5897ac27a0ecSDave Kleikamp 	buf->f_bsize = sb->s_blocksize;
5898b72f78cbSEric Sandeen 	buf->f_blocks = ext4_blocks_count(es) - EXT4_C2B(sbi, overhead);
589957042651STheodore Ts'o 	bfree = percpu_counter_sum_positive(&sbi->s_freeclusters_counter) -
590057042651STheodore Ts'o 		percpu_counter_sum_positive(&sbi->s_dirtyclusters_counter);
5901d02a9391SKazuya Mio 	/* prevent underflow in case that few free space is available */
590257042651STheodore Ts'o 	buf->f_bfree = EXT4_C2B(sbi, max_t(s64, bfree, 0));
590327dd4385SLukas Czerner 	buf->f_bavail = buf->f_bfree -
590427dd4385SLukas Czerner 			(ext4_r_blocks_count(es) + resv_blocks);
590527dd4385SLukas Czerner 	if (buf->f_bfree < (ext4_r_blocks_count(es) + resv_blocks))
5906ac27a0ecSDave Kleikamp 		buf->f_bavail = 0;
5907ac27a0ecSDave Kleikamp 	buf->f_files = le32_to_cpu(es->s_inodes_count);
590852d9f3b4SPeter Zijlstra 	buf->f_ffree = percpu_counter_sum_positive(&sbi->s_freeinodes_counter);
5909617ba13bSMingming Cao 	buf->f_namelen = EXT4_NAME_LEN;
5910960cc398SPekka Enberg 	fsid = le64_to_cpup((void *)es->s_uuid) ^
5911960cc398SPekka Enberg 	       le64_to_cpup((void *)es->s_uuid + sizeof(u64));
5912960cc398SPekka Enberg 	buf->f_fsid.val[0] = fsid & 0xFFFFFFFFUL;
5913960cc398SPekka Enberg 	buf->f_fsid.val[1] = (fsid >> 32) & 0xFFFFFFFFUL;
59140b8e58a1SAndreas Dilger 
5915689c958cSLi Xi #ifdef CONFIG_QUOTA
5916689c958cSLi Xi 	if (ext4_test_inode_flag(dentry->d_inode, EXT4_INODE_PROJINHERIT) &&
5917689c958cSLi Xi 	    sb_has_quota_limits_enabled(sb, PRJQUOTA))
5918689c958cSLi Xi 		ext4_statfs_project(sb, EXT4_I(dentry->d_inode)->i_projid, buf);
5919689c958cSLi Xi #endif
5920ac27a0ecSDave Kleikamp 	return 0;
5921ac27a0ecSDave Kleikamp }
5922ac27a0ecSDave Kleikamp 
5923ac27a0ecSDave Kleikamp 
5924ac27a0ecSDave Kleikamp #ifdef CONFIG_QUOTA
5925ac27a0ecSDave Kleikamp 
5926bc8230eeSJan Kara /*
5927bc8230eeSJan Kara  * Helper functions so that transaction is started before we acquire dqio_sem
5928bc8230eeSJan Kara  * to keep correct lock ordering of transaction > dqio_sem
5929bc8230eeSJan Kara  */
5930ac27a0ecSDave Kleikamp static inline struct inode *dquot_to_inode(struct dquot *dquot)
5931ac27a0ecSDave Kleikamp {
59324c376dcaSEric W. Biederman 	return sb_dqopt(dquot->dq_sb)->files[dquot->dq_id.type];
5933ac27a0ecSDave Kleikamp }
5934ac27a0ecSDave Kleikamp 
5935617ba13bSMingming Cao static int ext4_write_dquot(struct dquot *dquot)
5936ac27a0ecSDave Kleikamp {
5937ac27a0ecSDave Kleikamp 	int ret, err;
5938ac27a0ecSDave Kleikamp 	handle_t *handle;
5939ac27a0ecSDave Kleikamp 	struct inode *inode;
5940ac27a0ecSDave Kleikamp 
5941ac27a0ecSDave Kleikamp 	inode = dquot_to_inode(dquot);
59429924a92aSTheodore Ts'o 	handle = ext4_journal_start(inode, EXT4_HT_QUOTA,
5943617ba13bSMingming Cao 				    EXT4_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
5944ac27a0ecSDave Kleikamp 	if (IS_ERR(handle))
5945ac27a0ecSDave Kleikamp 		return PTR_ERR(handle);
5946ac27a0ecSDave Kleikamp 	ret = dquot_commit(dquot);
5947617ba13bSMingming Cao 	err = ext4_journal_stop(handle);
5948ac27a0ecSDave Kleikamp 	if (!ret)
5949ac27a0ecSDave Kleikamp 		ret = err;
5950ac27a0ecSDave Kleikamp 	return ret;
5951ac27a0ecSDave Kleikamp }
5952ac27a0ecSDave Kleikamp 
5953617ba13bSMingming Cao static int ext4_acquire_dquot(struct dquot *dquot)
5954ac27a0ecSDave Kleikamp {
5955ac27a0ecSDave Kleikamp 	int ret, err;
5956ac27a0ecSDave Kleikamp 	handle_t *handle;
5957ac27a0ecSDave Kleikamp 
59589924a92aSTheodore Ts'o 	handle = ext4_journal_start(dquot_to_inode(dquot), EXT4_HT_QUOTA,
5959617ba13bSMingming Cao 				    EXT4_QUOTA_INIT_BLOCKS(dquot->dq_sb));
5960ac27a0ecSDave Kleikamp 	if (IS_ERR(handle))
5961ac27a0ecSDave Kleikamp 		return PTR_ERR(handle);
5962ac27a0ecSDave Kleikamp 	ret = dquot_acquire(dquot);
5963617ba13bSMingming Cao 	err = ext4_journal_stop(handle);
5964ac27a0ecSDave Kleikamp 	if (!ret)
5965ac27a0ecSDave Kleikamp 		ret = err;
5966ac27a0ecSDave Kleikamp 	return ret;
5967ac27a0ecSDave Kleikamp }
5968ac27a0ecSDave Kleikamp 
5969617ba13bSMingming Cao static int ext4_release_dquot(struct dquot *dquot)
5970ac27a0ecSDave Kleikamp {
5971ac27a0ecSDave Kleikamp 	int ret, err;
5972ac27a0ecSDave Kleikamp 	handle_t *handle;
5973ac27a0ecSDave Kleikamp 
59749924a92aSTheodore Ts'o 	handle = ext4_journal_start(dquot_to_inode(dquot), EXT4_HT_QUOTA,
5975617ba13bSMingming Cao 				    EXT4_QUOTA_DEL_BLOCKS(dquot->dq_sb));
59769c3013e9SJan Kara 	if (IS_ERR(handle)) {
59779c3013e9SJan Kara 		/* Release dquot anyway to avoid endless cycle in dqput() */
59789c3013e9SJan Kara 		dquot_release(dquot);
5979ac27a0ecSDave Kleikamp 		return PTR_ERR(handle);
59809c3013e9SJan Kara 	}
5981ac27a0ecSDave Kleikamp 	ret = dquot_release(dquot);
5982617ba13bSMingming Cao 	err = ext4_journal_stop(handle);
5983ac27a0ecSDave Kleikamp 	if (!ret)
5984ac27a0ecSDave Kleikamp 		ret = err;
5985ac27a0ecSDave Kleikamp 	return ret;
5986ac27a0ecSDave Kleikamp }
5987ac27a0ecSDave Kleikamp 
5988617ba13bSMingming Cao static int ext4_mark_dquot_dirty(struct dquot *dquot)
5989ac27a0ecSDave Kleikamp {
5990262b4662SJan Kara 	struct super_block *sb = dquot->dq_sb;
5991262b4662SJan Kara 	struct ext4_sb_info *sbi = EXT4_SB(sb);
5992262b4662SJan Kara 
59932c8be6b2SJan Kara 	/* Are we journaling quotas? */
5994e2b911c5SDarrick J. Wong 	if (ext4_has_feature_quota(sb) ||
5995262b4662SJan Kara 	    sbi->s_qf_names[USRQUOTA] || sbi->s_qf_names[GRPQUOTA]) {
5996ac27a0ecSDave Kleikamp 		dquot_mark_dquot_dirty(dquot);
5997617ba13bSMingming Cao 		return ext4_write_dquot(dquot);
5998ac27a0ecSDave Kleikamp 	} else {
5999ac27a0ecSDave Kleikamp 		return dquot_mark_dquot_dirty(dquot);
6000ac27a0ecSDave Kleikamp 	}
6001ac27a0ecSDave Kleikamp }
6002ac27a0ecSDave Kleikamp 
6003617ba13bSMingming Cao static int ext4_write_info(struct super_block *sb, int type)
6004ac27a0ecSDave Kleikamp {
6005ac27a0ecSDave Kleikamp 	int ret, err;
6006ac27a0ecSDave Kleikamp 	handle_t *handle;
6007ac27a0ecSDave Kleikamp 
6008ac27a0ecSDave Kleikamp 	/* Data block + inode block */
60092b0143b5SDavid Howells 	handle = ext4_journal_start(d_inode(sb->s_root), EXT4_HT_QUOTA, 2);
6010ac27a0ecSDave Kleikamp 	if (IS_ERR(handle))
6011ac27a0ecSDave Kleikamp 		return PTR_ERR(handle);
6012ac27a0ecSDave Kleikamp 	ret = dquot_commit_info(sb, type);
6013617ba13bSMingming Cao 	err = ext4_journal_stop(handle);
6014ac27a0ecSDave Kleikamp 	if (!ret)
6015ac27a0ecSDave Kleikamp 		ret = err;
6016ac27a0ecSDave Kleikamp 	return ret;
6017ac27a0ecSDave Kleikamp }
6018ac27a0ecSDave Kleikamp 
6019ac27a0ecSDave Kleikamp /*
6020ac27a0ecSDave Kleikamp  * Turn on quotas during mount time - we need to find
6021ac27a0ecSDave Kleikamp  * the quota file and such...
6022ac27a0ecSDave Kleikamp  */
6023617ba13bSMingming Cao static int ext4_quota_on_mount(struct super_block *sb, int type)
6024ac27a0ecSDave Kleikamp {
602533458eabSTheodore Ts'o 	return dquot_quota_on_mount(sb, get_qf_name(sb, EXT4_SB(sb), type),
6026617ba13bSMingming Cao 					EXT4_SB(sb)->s_jquota_fmt, type);
6027ac27a0ecSDave Kleikamp }
6028ac27a0ecSDave Kleikamp 
6029daf647d2STheodore Ts'o static void lockdep_set_quota_inode(struct inode *inode, int subclass)
6030daf647d2STheodore Ts'o {
6031daf647d2STheodore Ts'o 	struct ext4_inode_info *ei = EXT4_I(inode);
6032daf647d2STheodore Ts'o 
6033daf647d2STheodore Ts'o 	/* The first argument of lockdep_set_subclass has to be
6034daf647d2STheodore Ts'o 	 * *exactly* the same as the argument to init_rwsem() --- in
6035daf647d2STheodore Ts'o 	 * this case, in init_once() --- or lockdep gets unhappy
6036daf647d2STheodore Ts'o 	 * because the name of the lock is set using the
6037daf647d2STheodore Ts'o 	 * stringification of the argument to init_rwsem().
6038daf647d2STheodore Ts'o 	 */
6039daf647d2STheodore Ts'o 	(void) ei;	/* shut up clang warning if !CONFIG_LOCKDEP */
6040daf647d2STheodore Ts'o 	lockdep_set_subclass(&ei->i_data_sem, subclass);
6041daf647d2STheodore Ts'o }
6042daf647d2STheodore Ts'o 
6043ac27a0ecSDave Kleikamp /*
6044ac27a0ecSDave Kleikamp  * Standard function to be called on quota_on
6045ac27a0ecSDave Kleikamp  */
6046617ba13bSMingming Cao static int ext4_quota_on(struct super_block *sb, int type, int format_id,
60478c54ca9cSAl Viro 			 const struct path *path)
6048ac27a0ecSDave Kleikamp {
6049ac27a0ecSDave Kleikamp 	int err;
6050ac27a0ecSDave Kleikamp 
6051ac27a0ecSDave Kleikamp 	if (!test_opt(sb, QUOTA))
6052ac27a0ecSDave Kleikamp 		return -EINVAL;
60530623543bSJan Kara 
6054ac27a0ecSDave Kleikamp 	/* Quotafile not on the same filesystem? */
6055d8c9584eSAl Viro 	if (path->dentry->d_sb != sb)
6056ac27a0ecSDave Kleikamp 		return -EXDEV;
60570623543bSJan Kara 	/* Journaling quota? */
60580623543bSJan Kara 	if (EXT4_SB(sb)->s_qf_names[type]) {
60592b2d6d01STheodore Ts'o 		/* Quotafile not in fs root? */
6060f00c9e44SJan Kara 		if (path->dentry->d_parent != sb->s_root)
6061b31e1552SEric Sandeen 			ext4_msg(sb, KERN_WARNING,
6062b31e1552SEric Sandeen 				"Quota file not on filesystem root. "
6063b31e1552SEric Sandeen 				"Journaled quota will not work");
606491389240SJan Kara 		sb_dqopt(sb)->flags |= DQUOT_NOLIST_DIRTY;
606591389240SJan Kara 	} else {
606691389240SJan Kara 		/*
606791389240SJan Kara 		 * Clear the flag just in case mount options changed since
606891389240SJan Kara 		 * last time.
606991389240SJan Kara 		 */
607091389240SJan Kara 		sb_dqopt(sb)->flags &= ~DQUOT_NOLIST_DIRTY;
60710623543bSJan Kara 	}
60720623543bSJan Kara 
60730623543bSJan Kara 	/*
60740623543bSJan Kara 	 * When we journal data on quota file, we have to flush journal to see
60750623543bSJan Kara 	 * all updates to the file when we bypass pagecache...
60760623543bSJan Kara 	 */
60770390131bSFrank Mayhar 	if (EXT4_SB(sb)->s_journal &&
60782b0143b5SDavid Howells 	    ext4_should_journal_data(d_inode(path->dentry))) {
60790623543bSJan Kara 		/*
60800623543bSJan Kara 		 * We don't need to lock updates but journal_flush() could
60810623543bSJan Kara 		 * otherwise be livelocked...
60820623543bSJan Kara 		 */
60830623543bSJan Kara 		jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
60847ffe1ea8SHidehiro Kawai 		err = jbd2_journal_flush(EXT4_SB(sb)->s_journal);
60850623543bSJan Kara 		jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
6086f00c9e44SJan Kara 		if (err)
60877ffe1ea8SHidehiro Kawai 			return err;
60887ffe1ea8SHidehiro Kawai 	}
6089957153fcSJan Kara 
6090daf647d2STheodore Ts'o 	lockdep_set_quota_inode(path->dentry->d_inode, I_DATA_SEM_QUOTA);
6091daf647d2STheodore Ts'o 	err = dquot_quota_on(sb, type, format_id, path);
6092957153fcSJan Kara 	if (err) {
6093daf647d2STheodore Ts'o 		lockdep_set_quota_inode(path->dentry->d_inode,
6094daf647d2STheodore Ts'o 					     I_DATA_SEM_NORMAL);
6095957153fcSJan Kara 	} else {
6096957153fcSJan Kara 		struct inode *inode = d_inode(path->dentry);
6097957153fcSJan Kara 		handle_t *handle;
6098957153fcSJan Kara 
609961a92987SJan Kara 		/*
610061a92987SJan Kara 		 * Set inode flags to prevent userspace from messing with quota
610161a92987SJan Kara 		 * files. If this fails, we return success anyway since quotas
610261a92987SJan Kara 		 * are already enabled and this is not a hard failure.
610361a92987SJan Kara 		 */
6104957153fcSJan Kara 		inode_lock(inode);
6105957153fcSJan Kara 		handle = ext4_journal_start(inode, EXT4_HT_QUOTA, 1);
6106957153fcSJan Kara 		if (IS_ERR(handle))
6107957153fcSJan Kara 			goto unlock_inode;
6108957153fcSJan Kara 		EXT4_I(inode)->i_flags |= EXT4_NOATIME_FL | EXT4_IMMUTABLE_FL;
6109957153fcSJan Kara 		inode_set_flags(inode, S_NOATIME | S_IMMUTABLE,
6110957153fcSJan Kara 				S_NOATIME | S_IMMUTABLE);
61114209ae12SHarshad Shirwadkar 		err = ext4_mark_inode_dirty(handle, inode);
6112957153fcSJan Kara 		ext4_journal_stop(handle);
6113957153fcSJan Kara 	unlock_inode:
6114957153fcSJan Kara 		inode_unlock(inode);
6115957153fcSJan Kara 	}
6116daf647d2STheodore Ts'o 	return err;
6117ac27a0ecSDave Kleikamp }
6118ac27a0ecSDave Kleikamp 
61197c319d32SAditya Kali static int ext4_quota_enable(struct super_block *sb, int type, int format_id,
61207c319d32SAditya Kali 			     unsigned int flags)
61217c319d32SAditya Kali {
61227c319d32SAditya Kali 	int err;
61237c319d32SAditya Kali 	struct inode *qf_inode;
6124a2d4a646SJan Kara 	unsigned long qf_inums[EXT4_MAXQUOTAS] = {
61257c319d32SAditya Kali 		le32_to_cpu(EXT4_SB(sb)->s_es->s_usr_quota_inum),
6126689c958cSLi Xi 		le32_to_cpu(EXT4_SB(sb)->s_es->s_grp_quota_inum),
6127689c958cSLi Xi 		le32_to_cpu(EXT4_SB(sb)->s_es->s_prj_quota_inum)
61287c319d32SAditya Kali 	};
61297c319d32SAditya Kali 
6130e2b911c5SDarrick J. Wong 	BUG_ON(!ext4_has_feature_quota(sb));
61317c319d32SAditya Kali 
61327c319d32SAditya Kali 	if (!qf_inums[type])
61337c319d32SAditya Kali 		return -EPERM;
61347c319d32SAditya Kali 
61358a363970STheodore Ts'o 	qf_inode = ext4_iget(sb, qf_inums[type], EXT4_IGET_SPECIAL);
61367c319d32SAditya Kali 	if (IS_ERR(qf_inode)) {
61377c319d32SAditya Kali 		ext4_error(sb, "Bad quota inode # %lu", qf_inums[type]);
61387c319d32SAditya Kali 		return PTR_ERR(qf_inode);
61397c319d32SAditya Kali 	}
61407c319d32SAditya Kali 
6141bcb13850SJan Kara 	/* Don't account quota for quota files to avoid recursion */
6142bcb13850SJan Kara 	qf_inode->i_flags |= S_NOQUOTA;
6143daf647d2STheodore Ts'o 	lockdep_set_quota_inode(qf_inode, I_DATA_SEM_QUOTA);
61447212b95eSJan Kara 	err = dquot_load_quota_inode(qf_inode, type, format_id, flags);
6145daf647d2STheodore Ts'o 	if (err)
6146daf647d2STheodore Ts'o 		lockdep_set_quota_inode(qf_inode, I_DATA_SEM_NORMAL);
614761157b24SPan Bian 	iput(qf_inode);
61487c319d32SAditya Kali 
61497c319d32SAditya Kali 	return err;
61507c319d32SAditya Kali }
61517c319d32SAditya Kali 
61527c319d32SAditya Kali /* Enable usage tracking for all quota types. */
61537c319d32SAditya Kali static int ext4_enable_quotas(struct super_block *sb)
61547c319d32SAditya Kali {
61557c319d32SAditya Kali 	int type, err = 0;
6156a2d4a646SJan Kara 	unsigned long qf_inums[EXT4_MAXQUOTAS] = {
61577c319d32SAditya Kali 		le32_to_cpu(EXT4_SB(sb)->s_es->s_usr_quota_inum),
6158689c958cSLi Xi 		le32_to_cpu(EXT4_SB(sb)->s_es->s_grp_quota_inum),
6159689c958cSLi Xi 		le32_to_cpu(EXT4_SB(sb)->s_es->s_prj_quota_inum)
61607c319d32SAditya Kali 	};
616149da9392SJan Kara 	bool quota_mopt[EXT4_MAXQUOTAS] = {
616249da9392SJan Kara 		test_opt(sb, USRQUOTA),
616349da9392SJan Kara 		test_opt(sb, GRPQUOTA),
616449da9392SJan Kara 		test_opt(sb, PRJQUOTA),
616549da9392SJan Kara 	};
61667c319d32SAditya Kali 
616791389240SJan Kara 	sb_dqopt(sb)->flags |= DQUOT_QUOTA_SYS_FILE | DQUOT_NOLIST_DIRTY;
6168a2d4a646SJan Kara 	for (type = 0; type < EXT4_MAXQUOTAS; type++) {
61697c319d32SAditya Kali 		if (qf_inums[type]) {
61707c319d32SAditya Kali 			err = ext4_quota_enable(sb, type, QFMT_VFS_V1,
617149da9392SJan Kara 				DQUOT_USAGE_ENABLED |
617249da9392SJan Kara 				(quota_mopt[type] ? DQUOT_LIMITS_ENABLED : 0));
61737c319d32SAditya Kali 			if (err) {
61747c319d32SAditya Kali 				ext4_warning(sb,
617572ba7450STheodore Ts'o 					"Failed to enable quota tracking "
617672ba7450STheodore Ts'o 					"(type=%d, err=%d). Please run "
617772ba7450STheodore Ts'o 					"e2fsck to fix.", type, err);
61787f144fd0SJunichi Uekawa 				for (type--; type >= 0; type--)
61797f144fd0SJunichi Uekawa 					dquot_quota_off(sb, type);
61807f144fd0SJunichi Uekawa 
61817c319d32SAditya Kali 				return err;
61827c319d32SAditya Kali 			}
61837c319d32SAditya Kali 		}
61847c319d32SAditya Kali 	}
61857c319d32SAditya Kali 	return 0;
61867c319d32SAditya Kali }
61877c319d32SAditya Kali 
6188ca0e05e4SDmitry Monakhov static int ext4_quota_off(struct super_block *sb, int type)
6189ca0e05e4SDmitry Monakhov {
619021f97697SJan Kara 	struct inode *inode = sb_dqopt(sb)->files[type];
619121f97697SJan Kara 	handle_t *handle;
6192957153fcSJan Kara 	int err;
619321f97697SJan Kara 
619487009d86SDmitry Monakhov 	/* Force all delayed allocation blocks to be allocated.
619587009d86SDmitry Monakhov 	 * Caller already holds s_umount sem */
619687009d86SDmitry Monakhov 	if (test_opt(sb, DELALLOC))
6197ca0e05e4SDmitry Monakhov 		sync_filesystem(sb);
6198ca0e05e4SDmitry Monakhov 
6199957153fcSJan Kara 	if (!inode || !igrab(inode))
62000b268590SAmir Goldstein 		goto out;
62010b268590SAmir Goldstein 
6202957153fcSJan Kara 	err = dquot_quota_off(sb, type);
6203964edf66SJan Kara 	if (err || ext4_has_feature_quota(sb))
6204957153fcSJan Kara 		goto out_put;
6205957153fcSJan Kara 
6206957153fcSJan Kara 	inode_lock(inode);
620761a92987SJan Kara 	/*
620861a92987SJan Kara 	 * Update modification times of quota files when userspace can
620961a92987SJan Kara 	 * start looking at them. If we fail, we return success anyway since
621061a92987SJan Kara 	 * this is not a hard failure and quotas are already disabled.
621161a92987SJan Kara 	 */
62129924a92aSTheodore Ts'o 	handle = ext4_journal_start(inode, EXT4_HT_QUOTA, 1);
62134209ae12SHarshad Shirwadkar 	if (IS_ERR(handle)) {
62144209ae12SHarshad Shirwadkar 		err = PTR_ERR(handle);
6215957153fcSJan Kara 		goto out_unlock;
62164209ae12SHarshad Shirwadkar 	}
6217957153fcSJan Kara 	EXT4_I(inode)->i_flags &= ~(EXT4_NOATIME_FL | EXT4_IMMUTABLE_FL);
6218957153fcSJan Kara 	inode_set_flags(inode, 0, S_NOATIME | S_IMMUTABLE);
6219eeca7ea1SDeepa Dinamani 	inode->i_mtime = inode->i_ctime = current_time(inode);
62204209ae12SHarshad Shirwadkar 	err = ext4_mark_inode_dirty(handle, inode);
622121f97697SJan Kara 	ext4_journal_stop(handle);
6222957153fcSJan Kara out_unlock:
6223957153fcSJan Kara 	inode_unlock(inode);
6224957153fcSJan Kara out_put:
6225964edf66SJan Kara 	lockdep_set_quota_inode(inode, I_DATA_SEM_NORMAL);
6226957153fcSJan Kara 	iput(inode);
6227957153fcSJan Kara 	return err;
622821f97697SJan Kara out:
6229ca0e05e4SDmitry Monakhov 	return dquot_quota_off(sb, type);
6230ca0e05e4SDmitry Monakhov }
6231ca0e05e4SDmitry Monakhov 
6232ac27a0ecSDave Kleikamp /* Read data from quotafile - avoid pagecache and such because we cannot afford
6233ac27a0ecSDave Kleikamp  * acquiring the locks... As quota files are never truncated and quota code
6234ac27a0ecSDave Kleikamp  * itself serializes the operations (and no one else should touch the files)
6235ac27a0ecSDave Kleikamp  * we don't have to be afraid of races */
6236617ba13bSMingming Cao static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data,
6237ac27a0ecSDave Kleikamp 			       size_t len, loff_t off)
6238ac27a0ecSDave Kleikamp {
6239ac27a0ecSDave Kleikamp 	struct inode *inode = sb_dqopt(sb)->files[type];
6240725d26d3SAneesh Kumar K.V 	ext4_lblk_t blk = off >> EXT4_BLOCK_SIZE_BITS(sb);
6241ac27a0ecSDave Kleikamp 	int offset = off & (sb->s_blocksize - 1);
6242ac27a0ecSDave Kleikamp 	int tocopy;
6243ac27a0ecSDave Kleikamp 	size_t toread;
6244ac27a0ecSDave Kleikamp 	struct buffer_head *bh;
6245ac27a0ecSDave Kleikamp 	loff_t i_size = i_size_read(inode);
6246ac27a0ecSDave Kleikamp 
6247ac27a0ecSDave Kleikamp 	if (off > i_size)
6248ac27a0ecSDave Kleikamp 		return 0;
6249ac27a0ecSDave Kleikamp 	if (off+len > i_size)
6250ac27a0ecSDave Kleikamp 		len = i_size-off;
6251ac27a0ecSDave Kleikamp 	toread = len;
6252ac27a0ecSDave Kleikamp 	while (toread > 0) {
6253ac27a0ecSDave Kleikamp 		tocopy = sb->s_blocksize - offset < toread ?
6254ac27a0ecSDave Kleikamp 				sb->s_blocksize - offset : toread;
62551c215028STheodore Ts'o 		bh = ext4_bread(NULL, inode, blk, 0);
62561c215028STheodore Ts'o 		if (IS_ERR(bh))
62571c215028STheodore Ts'o 			return PTR_ERR(bh);
6258ac27a0ecSDave Kleikamp 		if (!bh)	/* A hole? */
6259ac27a0ecSDave Kleikamp 			memset(data, 0, tocopy);
6260ac27a0ecSDave Kleikamp 		else
6261ac27a0ecSDave Kleikamp 			memcpy(data, bh->b_data+offset, tocopy);
6262ac27a0ecSDave Kleikamp 		brelse(bh);
6263ac27a0ecSDave Kleikamp 		offset = 0;
6264ac27a0ecSDave Kleikamp 		toread -= tocopy;
6265ac27a0ecSDave Kleikamp 		data += tocopy;
6266ac27a0ecSDave Kleikamp 		blk++;
6267ac27a0ecSDave Kleikamp 	}
6268ac27a0ecSDave Kleikamp 	return len;
6269ac27a0ecSDave Kleikamp }
6270ac27a0ecSDave Kleikamp 
6271ac27a0ecSDave Kleikamp /* Write to quotafile (we know the transaction is already started and has
6272ac27a0ecSDave Kleikamp  * enough credits) */
6273617ba13bSMingming Cao static ssize_t ext4_quota_write(struct super_block *sb, int type,
6274ac27a0ecSDave Kleikamp 				const char *data, size_t len, loff_t off)
6275ac27a0ecSDave Kleikamp {
6276ac27a0ecSDave Kleikamp 	struct inode *inode = sb_dqopt(sb)->files[type];
6277725d26d3SAneesh Kumar K.V 	ext4_lblk_t blk = off >> EXT4_BLOCK_SIZE_BITS(sb);
62784209ae12SHarshad Shirwadkar 	int err = 0, err2 = 0, offset = off & (sb->s_blocksize - 1);
6279c5e298aeSTheodore Ts'o 	int retries = 0;
6280ac27a0ecSDave Kleikamp 	struct buffer_head *bh;
6281ac27a0ecSDave Kleikamp 	handle_t *handle = journal_current_handle();
6282ac27a0ecSDave Kleikamp 
62830390131bSFrank Mayhar 	if (EXT4_SB(sb)->s_journal && !handle) {
6284b31e1552SEric Sandeen 		ext4_msg(sb, KERN_WARNING, "Quota write (off=%llu, len=%llu)"
6285b31e1552SEric Sandeen 			" cancelled because transaction is not started",
62869c3013e9SJan Kara 			(unsigned long long)off, (unsigned long long)len);
62879c3013e9SJan Kara 		return -EIO;
62889c3013e9SJan Kara 	}
628967eeb568SDmitry Monakhov 	/*
629067eeb568SDmitry Monakhov 	 * Since we account only one data block in transaction credits,
629167eeb568SDmitry Monakhov 	 * then it is impossible to cross a block boundary.
629267eeb568SDmitry Monakhov 	 */
629367eeb568SDmitry Monakhov 	if (sb->s_blocksize - offset < len) {
629467eeb568SDmitry Monakhov 		ext4_msg(sb, KERN_WARNING, "Quota write (off=%llu, len=%llu)"
629567eeb568SDmitry Monakhov 			" cancelled because not block aligned",
629667eeb568SDmitry Monakhov 			(unsigned long long)off, (unsigned long long)len);
629767eeb568SDmitry Monakhov 		return -EIO;
629867eeb568SDmitry Monakhov 	}
629967eeb568SDmitry Monakhov 
6300c5e298aeSTheodore Ts'o 	do {
6301c5e298aeSTheodore Ts'o 		bh = ext4_bread(handle, inode, blk,
6302c5e298aeSTheodore Ts'o 				EXT4_GET_BLOCKS_CREATE |
6303c5e298aeSTheodore Ts'o 				EXT4_GET_BLOCKS_METADATA_NOFAIL);
630445586c70SMasahiro Yamada 	} while (PTR_ERR(bh) == -ENOSPC &&
6305c5e298aeSTheodore Ts'o 		 ext4_should_retry_alloc(inode->i_sb, &retries));
63061c215028STheodore Ts'o 	if (IS_ERR(bh))
63071c215028STheodore Ts'o 		return PTR_ERR(bh);
6308ac27a0ecSDave Kleikamp 	if (!bh)
6309ac27a0ecSDave Kleikamp 		goto out;
63105d601255Sliang xie 	BUFFER_TRACE(bh, "get write access");
6311617ba13bSMingming Cao 	err = ext4_journal_get_write_access(handle, bh);
6312ac27a0ecSDave Kleikamp 	if (err) {
6313ac27a0ecSDave Kleikamp 		brelse(bh);
63141c215028STheodore Ts'o 		return err;
6315ac27a0ecSDave Kleikamp 	}
6316ac27a0ecSDave Kleikamp 	lock_buffer(bh);
631767eeb568SDmitry Monakhov 	memcpy(bh->b_data+offset, data, len);
6318ac27a0ecSDave Kleikamp 	flush_dcache_page(bh->b_page);
6319ac27a0ecSDave Kleikamp 	unlock_buffer(bh);
63200390131bSFrank Mayhar 	err = ext4_handle_dirty_metadata(handle, NULL, bh);
6321ac27a0ecSDave Kleikamp 	brelse(bh);
6322ac27a0ecSDave Kleikamp out:
632367eeb568SDmitry Monakhov 	if (inode->i_size < off + len) {
632467eeb568SDmitry Monakhov 		i_size_write(inode, off + len);
6325617ba13bSMingming Cao 		EXT4_I(inode)->i_disksize = inode->i_size;
63264209ae12SHarshad Shirwadkar 		err2 = ext4_mark_inode_dirty(handle, inode);
63274209ae12SHarshad Shirwadkar 		if (unlikely(err2 && !err))
63284209ae12SHarshad Shirwadkar 			err = err2;
632921f97697SJan Kara 	}
63304209ae12SHarshad Shirwadkar 	return err ? err : len;
6331ac27a0ecSDave Kleikamp }
6332ac27a0ecSDave Kleikamp #endif
6333ac27a0ecSDave Kleikamp 
6334152a0836SAl Viro static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags,
6335152a0836SAl Viro 		       const char *dev_name, void *data)
6336ac27a0ecSDave Kleikamp {
6337152a0836SAl Viro 	return mount_bdev(fs_type, flags, dev_name, data, ext4_fill_super);
6338ac27a0ecSDave Kleikamp }
6339ac27a0ecSDave Kleikamp 
6340c290ea01SJan Kara #if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT2)
634124b58424STheodore Ts'o static inline void register_as_ext2(void)
634224b58424STheodore Ts'o {
634324b58424STheodore Ts'o 	int err = register_filesystem(&ext2_fs_type);
634424b58424STheodore Ts'o 	if (err)
634524b58424STheodore Ts'o 		printk(KERN_WARNING
634624b58424STheodore Ts'o 		       "EXT4-fs: Unable to register as ext2 (%d)\n", err);
634724b58424STheodore Ts'o }
634824b58424STheodore Ts'o 
634924b58424STheodore Ts'o static inline void unregister_as_ext2(void)
635024b58424STheodore Ts'o {
635124b58424STheodore Ts'o 	unregister_filesystem(&ext2_fs_type);
635224b58424STheodore Ts'o }
63532035e776STheodore Ts'o 
63542035e776STheodore Ts'o static inline int ext2_feature_set_ok(struct super_block *sb)
63552035e776STheodore Ts'o {
6356e2b911c5SDarrick J. Wong 	if (ext4_has_unknown_ext2_incompat_features(sb))
63572035e776STheodore Ts'o 		return 0;
6358bc98a42cSDavid Howells 	if (sb_rdonly(sb))
63592035e776STheodore Ts'o 		return 1;
6360e2b911c5SDarrick J. Wong 	if (ext4_has_unknown_ext2_ro_compat_features(sb))
63612035e776STheodore Ts'o 		return 0;
63622035e776STheodore Ts'o 	return 1;
63632035e776STheodore Ts'o }
636424b58424STheodore Ts'o #else
636524b58424STheodore Ts'o static inline void register_as_ext2(void) { }
636624b58424STheodore Ts'o static inline void unregister_as_ext2(void) { }
63672035e776STheodore Ts'o static inline int ext2_feature_set_ok(struct super_block *sb) { return 0; }
636824b58424STheodore Ts'o #endif
636924b58424STheodore Ts'o 
637024b58424STheodore Ts'o static inline void register_as_ext3(void)
637124b58424STheodore Ts'o {
637224b58424STheodore Ts'o 	int err = register_filesystem(&ext3_fs_type);
637324b58424STheodore Ts'o 	if (err)
637424b58424STheodore Ts'o 		printk(KERN_WARNING
637524b58424STheodore Ts'o 		       "EXT4-fs: Unable to register as ext3 (%d)\n", err);
637624b58424STheodore Ts'o }
637724b58424STheodore Ts'o 
637824b58424STheodore Ts'o static inline void unregister_as_ext3(void)
637924b58424STheodore Ts'o {
638024b58424STheodore Ts'o 	unregister_filesystem(&ext3_fs_type);
638124b58424STheodore Ts'o }
63822035e776STheodore Ts'o 
63832035e776STheodore Ts'o static inline int ext3_feature_set_ok(struct super_block *sb)
63842035e776STheodore Ts'o {
6385e2b911c5SDarrick J. Wong 	if (ext4_has_unknown_ext3_incompat_features(sb))
63862035e776STheodore Ts'o 		return 0;
6387e2b911c5SDarrick J. Wong 	if (!ext4_has_feature_journal(sb))
63882035e776STheodore Ts'o 		return 0;
6389bc98a42cSDavid Howells 	if (sb_rdonly(sb))
63902035e776STheodore Ts'o 		return 1;
6391e2b911c5SDarrick J. Wong 	if (ext4_has_unknown_ext3_ro_compat_features(sb))
63922035e776STheodore Ts'o 		return 0;
63932035e776STheodore Ts'o 	return 1;
63942035e776STheodore Ts'o }
639524b58424STheodore Ts'o 
639603010a33STheodore Ts'o static struct file_system_type ext4_fs_type = {
6397ac27a0ecSDave Kleikamp 	.owner		= THIS_MODULE,
639803010a33STheodore Ts'o 	.name		= "ext4",
6399152a0836SAl Viro 	.mount		= ext4_mount,
6400ac27a0ecSDave Kleikamp 	.kill_sb	= kill_block_super,
6401ac27a0ecSDave Kleikamp 	.fs_flags	= FS_REQUIRES_DEV,
6402ac27a0ecSDave Kleikamp };
64037f78e035SEric W. Biederman MODULE_ALIAS_FS("ext4");
6404ac27a0ecSDave Kleikamp 
6405e9e3bcecSEric Sandeen /* Shared across all ext4 file systems */
6406e9e3bcecSEric Sandeen wait_queue_head_t ext4__ioend_wq[EXT4_WQ_HASH_SZ];
6407e9e3bcecSEric Sandeen 
64085dabfc78STheodore Ts'o static int __init ext4_init_fs(void)
6409ac27a0ecSDave Kleikamp {
6410e9e3bcecSEric Sandeen 	int i, err;
6411c9de560dSAlex Tomas 
6412e294a537STheodore Ts'o 	ratelimit_state_init(&ext4_mount_msg_ratelimit, 30 * HZ, 64);
641307c0c5d8SAl Viro 	ext4_li_info = NULL;
641407c0c5d8SAl Viro 	mutex_init(&ext4_li_mtx);
641507c0c5d8SAl Viro 
64169a4c8019SCarlos Maiolino 	/* Build-time check for flags consistency */
641712e9b892SDmitry Monakhov 	ext4_check_flag_values();
6418e9e3bcecSEric Sandeen 
6419e142d052SJan Kara 	for (i = 0; i < EXT4_WQ_HASH_SZ; i++)
6420e9e3bcecSEric Sandeen 		init_waitqueue_head(&ext4__ioend_wq[i]);
6421e9e3bcecSEric Sandeen 
642251865fdaSZheng Liu 	err = ext4_init_es();
64236fd058f7STheodore Ts'o 	if (err)
64246fd058f7STheodore Ts'o 		return err;
642551865fdaSZheng Liu 
64261dc0aa46SEric Whitney 	err = ext4_init_pending();
64271dc0aa46SEric Whitney 	if (err)
642822cfe4b4SEric Biggers 		goto out7;
642922cfe4b4SEric Biggers 
643022cfe4b4SEric Biggers 	err = ext4_init_post_read_processing();
643122cfe4b4SEric Biggers 	if (err)
64321dc0aa46SEric Whitney 		goto out6;
64331dc0aa46SEric Whitney 
643451865fdaSZheng Liu 	err = ext4_init_pageio();
643551865fdaSZheng Liu 	if (err)
6436b5799018STheodore Ts'o 		goto out5;
643751865fdaSZheng Liu 
64385dabfc78STheodore Ts'o 	err = ext4_init_system_zone();
6439bd2d0210STheodore Ts'o 	if (err)
6440b5799018STheodore Ts'o 		goto out4;
6441857ac889SLukas Czerner 
6442b5799018STheodore Ts'o 	err = ext4_init_sysfs();
6443dd68314cSTheodore Ts'o 	if (err)
6444b5799018STheodore Ts'o 		goto out3;
6445857ac889SLukas Czerner 
64465dabfc78STheodore Ts'o 	err = ext4_init_mballoc();
6447ac27a0ecSDave Kleikamp 	if (err)
6448c9de560dSAlex Tomas 		goto out2;
6449ac27a0ecSDave Kleikamp 	err = init_inodecache();
6450ac27a0ecSDave Kleikamp 	if (err)
6451ac27a0ecSDave Kleikamp 		goto out1;
645224b58424STheodore Ts'o 	register_as_ext3();
64532035e776STheodore Ts'o 	register_as_ext2();
645403010a33STheodore Ts'o 	err = register_filesystem(&ext4_fs_type);
6455ac27a0ecSDave Kleikamp 	if (err)
6456ac27a0ecSDave Kleikamp 		goto out;
6457bfff6873SLukas Czerner 
6458ac27a0ecSDave Kleikamp 	return 0;
6459ac27a0ecSDave Kleikamp out:
646024b58424STheodore Ts'o 	unregister_as_ext2();
646124b58424STheodore Ts'o 	unregister_as_ext3();
6462ac27a0ecSDave Kleikamp 	destroy_inodecache();
6463ac27a0ecSDave Kleikamp out1:
64645dabfc78STheodore Ts'o 	ext4_exit_mballoc();
64659c191f70ST Makphaibulchoke out2:
6466b5799018STheodore Ts'o 	ext4_exit_sysfs();
6467b5799018STheodore Ts'o out3:
6468dd68314cSTheodore Ts'o 	ext4_exit_system_zone();
6469b5799018STheodore Ts'o out4:
64705dabfc78STheodore Ts'o 	ext4_exit_pageio();
6471b5799018STheodore Ts'o out5:
647222cfe4b4SEric Biggers 	ext4_exit_post_read_processing();
64731dc0aa46SEric Whitney out6:
647422cfe4b4SEric Biggers 	ext4_exit_pending();
647522cfe4b4SEric Biggers out7:
647651865fdaSZheng Liu 	ext4_exit_es();
647751865fdaSZheng Liu 
6478ac27a0ecSDave Kleikamp 	return err;
6479ac27a0ecSDave Kleikamp }
6480ac27a0ecSDave Kleikamp 
64815dabfc78STheodore Ts'o static void __exit ext4_exit_fs(void)
6482ac27a0ecSDave Kleikamp {
6483bfff6873SLukas Czerner 	ext4_destroy_lazyinit_thread();
648424b58424STheodore Ts'o 	unregister_as_ext2();
648524b58424STheodore Ts'o 	unregister_as_ext3();
648603010a33STheodore Ts'o 	unregister_filesystem(&ext4_fs_type);
6487ac27a0ecSDave Kleikamp 	destroy_inodecache();
64885dabfc78STheodore Ts'o 	ext4_exit_mballoc();
6489b5799018STheodore Ts'o 	ext4_exit_sysfs();
64905dabfc78STheodore Ts'o 	ext4_exit_system_zone();
64915dabfc78STheodore Ts'o 	ext4_exit_pageio();
649222cfe4b4SEric Biggers 	ext4_exit_post_read_processing();
6493dd12ed14SEric Sandeen 	ext4_exit_es();
64941dc0aa46SEric Whitney 	ext4_exit_pending();
6495ac27a0ecSDave Kleikamp }
6496ac27a0ecSDave Kleikamp 
6497ac27a0ecSDave Kleikamp MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
649883982b6fSTheodore Ts'o MODULE_DESCRIPTION("Fourth Extended Filesystem");
6499ac27a0ecSDave Kleikamp MODULE_LICENSE("GPL");
65007ef79ad5STheodore Ts'o MODULE_SOFTDEP("pre: crc32c");
65015dabfc78STheodore Ts'o module_init(ext4_init_fs)
65025dabfc78STheodore Ts'o module_exit(ext4_exit_fs)
6503