aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorJohann Lombardi <johann@whamcloud.com>2011-05-24 18:31:25 -0400
committerTheodore Ts'o <tytso@mit.edu>2011-05-24 18:31:25 -0400
commitc5e06d101aaf72f1f2192a661414459775e9bd74 (patch)
tree96d05d41be2bfea6d51be915ce196f033a5d9bf3 /fs/ext4
parentd02a9391f79cab65cde74cd9e8ccd2290a565229 (diff)
ext4: add support for multiple mount protection
Prevent an ext4 filesystem from being mounted multiple times. A sequence number is stored on disk and is periodically updated (every 5 seconds by default) by a mounted filesystem. At mount time, we now wait for s_mmp_update_interval seconds to make sure that the MMP sequence does not change. In case of failure, the nodename, bdevname and the time at which the MMP block was last updated is displayed. Signed-off-by: Andreas Dilger <adilger@whamcloud.com> Signed-off-by: Johann Lombardi <johann@whamcloud.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/Makefile3
-rw-r--r--fs/ext4/ext4.h76
-rw-r--r--fs/ext4/mmp.c351
-rw-r--r--fs/ext4/super.c18
4 files changed, 444 insertions, 4 deletions
diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile
index c947e36eda6c..04109460ba9e 100644
--- a/fs/ext4/Makefile
+++ b/fs/ext4/Makefile
@@ -6,7 +6,8 @@ obj-$(CONFIG_EXT4_FS) += ext4.o
6 6
7ext4-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o page-io.o \ 7ext4-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o page-io.o \
8 ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \ 8 ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \
9 ext4_jbd2.o migrate.o mballoc.o block_validity.o move_extent.o 9 ext4_jbd2.o migrate.o mballoc.o block_validity.o move_extent.o \
10 mmp.o
10 11
11ext4-$(CONFIG_EXT4_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o 12ext4-$(CONFIG_EXT4_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o
12ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o 13ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 65fe1dc0c750..c0c56c9d5933 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1028,7 +1028,7 @@ struct ext4_super_block {
1028 __le16 s_want_extra_isize; /* New inodes should reserve # bytes */ 1028 __le16 s_want_extra_isize; /* New inodes should reserve # bytes */
1029 __le32 s_flags; /* Miscellaneous flags */ 1029 __le32 s_flags; /* Miscellaneous flags */
1030 __le16 s_raid_stride; /* RAID stride */ 1030 __le16 s_raid_stride; /* RAID stride */
1031 __le16 s_mmp_interval; /* # seconds to wait in MMP checking */ 1031 __le16 s_mmp_update_interval; /* # seconds to wait in MMP checking */
1032 __le64 s_mmp_block; /* Block for multi-mount protection */ 1032 __le64 s_mmp_block; /* Block for multi-mount protection */
1033 __le32 s_raid_stripe_width; /* blocks on all data disks (N*stride)*/ 1033 __le32 s_raid_stripe_width; /* blocks on all data disks (N*stride)*/
1034 __u8 s_log_groups_per_flex; /* FLEX_BG group size */ 1034 __u8 s_log_groups_per_flex; /* FLEX_BG group size */
@@ -1204,6 +1204,9 @@ struct ext4_sb_info {
1204 struct ext4_li_request *s_li_request; 1204 struct ext4_li_request *s_li_request;
1205 /* Wait multiplier for lazy initialization thread */ 1205 /* Wait multiplier for lazy initialization thread */
1206 unsigned int s_li_wait_mult; 1206 unsigned int s_li_wait_mult;
1207
1208 /* Kernel thread for multiple mount protection */
1209 struct task_struct *s_mmp_tsk;
1207}; 1210};
1208 1211
1209static inline struct ext4_sb_info *EXT4_SB(struct super_block *sb) 1212static inline struct ext4_sb_info *EXT4_SB(struct super_block *sb)
@@ -1375,7 +1378,8 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei)
1375 EXT4_FEATURE_INCOMPAT_META_BG| \ 1378 EXT4_FEATURE_INCOMPAT_META_BG| \
1376 EXT4_FEATURE_INCOMPAT_EXTENTS| \ 1379 EXT4_FEATURE_INCOMPAT_EXTENTS| \
1377 EXT4_FEATURE_INCOMPAT_64BIT| \ 1380 EXT4_FEATURE_INCOMPAT_64BIT| \
1378 EXT4_FEATURE_INCOMPAT_FLEX_BG) 1381 EXT4_FEATURE_INCOMPAT_FLEX_BG| \
1382 EXT4_FEATURE_INCOMPAT_MMP)
1379#define EXT4_FEATURE_RO_COMPAT_SUPP (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \ 1383#define EXT4_FEATURE_RO_COMPAT_SUPP (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \
1380 EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \ 1384 EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \
1381 EXT4_FEATURE_RO_COMPAT_GDT_CSUM| \ 1385 EXT4_FEATURE_RO_COMPAT_GDT_CSUM| \
@@ -1627,6 +1631,67 @@ struct ext4_features {
1627}; 1631};
1628 1632
1629/* 1633/*
1634 * This structure will be used for multiple mount protection. It will be
1635 * written into the block number saved in the s_mmp_block field in the
1636 * superblock. Programs that check MMP should assume that if
1637 * SEQ_FSCK (or any unknown code above SEQ_MAX) is present then it is NOT safe
1638 * to use the filesystem, regardless of how old the timestamp is.
1639 */
1640#define EXT4_MMP_MAGIC 0x004D4D50U /* ASCII for MMP */
1641#define EXT4_MMP_SEQ_CLEAN 0xFF4D4D50U /* mmp_seq value for clean unmount */
1642#define EXT4_MMP_SEQ_FSCK 0xE24D4D50U /* mmp_seq value when being fscked */
1643#define EXT4_MMP_SEQ_MAX 0xE24D4D4FU /* maximum valid mmp_seq value */
1644
1645struct mmp_struct {
1646 __le32 mmp_magic; /* Magic number for MMP */
1647 __le32 mmp_seq; /* Sequence no. updated periodically */
1648
1649 /*
1650 * mmp_time, mmp_nodename & mmp_bdevname are only used for information
1651 * purposes and do not affect the correctness of the algorithm
1652 */
1653 __le64 mmp_time; /* Time last updated */
1654 char mmp_nodename[64]; /* Node which last updated MMP block */
1655 char mmp_bdevname[32]; /* Bdev which last updated MMP block */
1656
1657 /*
1658 * mmp_check_interval is used to verify if the MMP block has been
1659 * updated on the block device. The value is updated based on the
1660 * maximum time to write the MMP block during an update cycle.
1661 */
1662 __le16 mmp_check_interval;
1663
1664 __le16 mmp_pad1;
1665 __le32 mmp_pad2[227];
1666};
1667
1668/* arguments passed to the mmp thread */
1669struct mmpd_data {
1670 struct buffer_head *bh; /* bh from initial read_mmp_block() */
1671 struct super_block *sb; /* super block of the fs */
1672};
1673
1674/*
1675 * Check interval multiplier
1676 * The MMP block is written every update interval and initially checked every
1677 * update interval x the multiplier (the value is then adapted based on the
1678 * write latency). The reason is that writes can be delayed under load and we
1679 * don't want readers to incorrectly assume that the filesystem is no longer
1680 * in use.
1681 */
1682#define EXT4_MMP_CHECK_MULT 2UL
1683
1684/*
1685 * Minimum interval for MMP checking in seconds.
1686 */
1687#define EXT4_MMP_MIN_CHECK_INTERVAL 5UL
1688
1689/*
1690 * Maximum interval for MMP checking in seconds.
1691 */
1692#define EXT4_MMP_MAX_CHECK_INTERVAL 300UL
1693
1694/*
1630 * Function prototypes 1695 * Function prototypes
1631 */ 1696 */
1632 1697
@@ -1800,6 +1865,10 @@ extern void __ext4_warning(struct super_block *, const char *, unsigned int,
1800 __LINE__, ## message) 1865 __LINE__, ## message)
1801extern void ext4_msg(struct super_block *, const char *, const char *, ...) 1866extern void ext4_msg(struct super_block *, const char *, const char *, ...)
1802 __attribute__ ((format (printf, 3, 4))); 1867 __attribute__ ((format (printf, 3, 4)));
1868extern void __dump_mmp_msg(struct super_block *, struct mmp_struct *mmp,
1869 const char *, unsigned int, const char *);
1870#define dump_mmp_msg(sb, mmp, msg) __dump_mmp_msg(sb, mmp, __func__, \
1871 __LINE__, msg)
1803extern void __ext4_grp_locked_error(const char *, unsigned int, \ 1872extern void __ext4_grp_locked_error(const char *, unsigned int, \
1804 struct super_block *, ext4_group_t, \ 1873 struct super_block *, ext4_group_t, \
1805 unsigned long, ext4_fsblk_t, \ 1874 unsigned long, ext4_fsblk_t, \
@@ -2104,6 +2173,9 @@ extern int ext4_bio_write_page(struct ext4_io_submit *io,
2104 int len, 2173 int len,
2105 struct writeback_control *wbc); 2174 struct writeback_control *wbc);
2106 2175
2176/* mmp.c */
2177extern int ext4_multi_mount_protect(struct super_block *, ext4_fsblk_t);
2178
2107/* BH_Uninit flag: blocks are allocated but uninitialized on disk */ 2179/* BH_Uninit flag: blocks are allocated but uninitialized on disk */
2108enum ext4_state_bits { 2180enum ext4_state_bits {
2109 BH_Uninit /* blocks are allocated but uninitialized on disk */ 2181 BH_Uninit /* blocks are allocated but uninitialized on disk */
diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c
new file mode 100644
index 000000000000..9bdef3f537c5
--- /dev/null
+++ b/fs/ext4/mmp.c
@@ -0,0 +1,351 @@
1#include <linux/fs.h>
2#include <linux/random.h>
3#include <linux/buffer_head.h>
4#include <linux/utsname.h>
5#include <linux/kthread.h>
6
7#include "ext4.h"
8
9/*
10 * Write the MMP block using WRITE_SYNC to try to get the block on-disk
11 * faster.
12 */
13static int write_mmp_block(struct buffer_head *bh)
14{
15 mark_buffer_dirty(bh);
16 lock_buffer(bh);
17 bh->b_end_io = end_buffer_write_sync;
18 get_bh(bh);
19 submit_bh(WRITE_SYNC, bh);
20 wait_on_buffer(bh);
21 if (unlikely(!buffer_uptodate(bh)))
22 return 1;
23
24 return 0;
25}
26
27/*
28 * Read the MMP block. It _must_ be read from disk and hence we clear the
29 * uptodate flag on the buffer.
30 */
31static int read_mmp_block(struct super_block *sb, struct buffer_head **bh,
32 ext4_fsblk_t mmp_block)
33{
34 struct mmp_struct *mmp;
35
36 if (*bh)
37 clear_buffer_uptodate(*bh);
38
39 /* This would be sb_bread(sb, mmp_block), except we need to be sure
40 * that the MD RAID device cache has been bypassed, and that the read
41 * is not blocked in the elevator. */
42 if (!*bh)
43 *bh = sb_getblk(sb, mmp_block);
44 if (*bh) {
45 get_bh(*bh);
46 lock_buffer(*bh);
47 (*bh)->b_end_io = end_buffer_read_sync;
48 submit_bh(READ_SYNC, *bh);
49 wait_on_buffer(*bh);
50 if (!buffer_uptodate(*bh)) {
51 brelse(*bh);
52 *bh = NULL;
53 }
54 }
55 if (!*bh) {
56 ext4_warning(sb, "Error while reading MMP block %llu",
57 mmp_block);
58 return -EIO;
59 }
60
61 mmp = (struct mmp_struct *)((*bh)->b_data);
62 if (le32_to_cpu(mmp->mmp_magic) != EXT4_MMP_MAGIC)
63 return -EINVAL;
64
65 return 0;
66}
67
68/*
69 * Dump as much information as possible to help the admin.
70 */
71void __dump_mmp_msg(struct super_block *sb, struct mmp_struct *mmp,
72 const char *function, unsigned int line, const char *msg)
73{
74 __ext4_warning(sb, function, line, msg);
75 __ext4_warning(sb, function, line,
76 "MMP failure info: last update time: %llu, last update "
77 "node: %s, last update device: %s\n",
78 (long long unsigned int) le64_to_cpu(mmp->mmp_time),
79 mmp->mmp_nodename, mmp->mmp_bdevname);
80}
81
82/*
83 * kmmpd will update the MMP sequence every s_mmp_update_interval seconds
84 */
85static int kmmpd(void *data)
86{
87 struct super_block *sb = ((struct mmpd_data *) data)->sb;
88 struct buffer_head *bh = ((struct mmpd_data *) data)->bh;
89 struct ext4_super_block *es = EXT4_SB(sb)->s_es;
90 struct mmp_struct *mmp;
91 ext4_fsblk_t mmp_block;
92 u32 seq = 0;
93 unsigned long failed_writes = 0;
94 int mmp_update_interval = le16_to_cpu(es->s_mmp_update_interval);
95 unsigned mmp_check_interval;
96 unsigned long last_update_time;
97 unsigned long diff;
98 int retval;
99
100 mmp_block = le64_to_cpu(es->s_mmp_block);
101 mmp = (struct mmp_struct *)(bh->b_data);
102 mmp->mmp_time = cpu_to_le64(get_seconds());
103 /*
104 * Start with the higher mmp_check_interval and reduce it if
105 * the MMP block is being updated on time.
106 */
107 mmp_check_interval = max(EXT4_MMP_CHECK_MULT * mmp_update_interval,
108 EXT4_MMP_MIN_CHECK_INTERVAL);
109 mmp->mmp_check_interval = cpu_to_le16(mmp_check_interval);
110 bdevname(bh->b_bdev, mmp->mmp_bdevname);
111
112 memcpy(mmp->mmp_nodename, init_utsname()->sysname,
113 sizeof(mmp->mmp_nodename));
114
115 while (!kthread_should_stop()) {
116 if (++seq > EXT4_MMP_SEQ_MAX)
117 seq = 1;
118
119 mmp->mmp_seq = cpu_to_le32(seq);
120 mmp->mmp_time = cpu_to_le64(get_seconds());
121 last_update_time = jiffies;
122
123 retval = write_mmp_block(bh);
124 /*
125 * Don't spew too many error messages. Print one every
126 * (s_mmp_update_interval * 60) seconds.
127 */
128 if (retval && (failed_writes % 60) == 0) {
129 ext4_error(sb, "Error writing to MMP block");
130 failed_writes++;
131 }
132
133 if (!(le32_to_cpu(es->s_feature_incompat) &
134 EXT4_FEATURE_INCOMPAT_MMP)) {
135 ext4_warning(sb, "kmmpd being stopped since MMP feature"
136 " has been disabled.");
137 EXT4_SB(sb)->s_mmp_tsk = NULL;
138 goto failed;
139 }
140
141 if (sb->s_flags & MS_RDONLY) {
142 ext4_warning(sb, "kmmpd being stopped since filesystem "
143 "has been remounted as readonly.");
144 EXT4_SB(sb)->s_mmp_tsk = NULL;
145 goto failed;
146 }
147
148 diff = jiffies - last_update_time;
149 if (diff < mmp_update_interval * HZ)
150 schedule_timeout_interruptible(mmp_update_interval *
151 HZ - diff);
152
153 /*
154 * We need to make sure that more than mmp_check_interval
155 * seconds have not passed since writing. If that has happened
156 * we need to check if the MMP block is as we left it.
157 */
158 diff = jiffies - last_update_time;
159 if (diff > mmp_check_interval * HZ) {
160 struct buffer_head *bh_check = NULL;
161 struct mmp_struct *mmp_check;
162
163 retval = read_mmp_block(sb, &bh_check, mmp_block);
164 if (retval) {
165 ext4_error(sb, "error reading MMP data: %d",
166 retval);
167
168 EXT4_SB(sb)->s_mmp_tsk = NULL;
169 goto failed;
170 }
171
172 mmp_check = (struct mmp_struct *)(bh_check->b_data);
173 if (mmp->mmp_seq != mmp_check->mmp_seq ||
174 memcmp(mmp->mmp_nodename, mmp_check->mmp_nodename,
175 sizeof(mmp->mmp_nodename))) {
176 dump_mmp_msg(sb, mmp_check,
177 "Error while updating MMP info. "
178 "The filesystem seems to have been"
179 " multiply mounted.");
180 ext4_error(sb, "abort");
181 goto failed;
182 }
183 put_bh(bh_check);
184 }
185
186 /*
187 * Adjust the mmp_check_interval depending on how much time
188 * it took for the MMP block to be written.
189 */
190 mmp_check_interval = max(min(EXT4_MMP_CHECK_MULT * diff / HZ,
191 EXT4_MMP_MAX_CHECK_INTERVAL),
192 EXT4_MMP_MIN_CHECK_INTERVAL);
193 mmp->mmp_check_interval = cpu_to_le16(mmp_check_interval);
194 }
195
196 /*
197 * Unmount seems to be clean.
198 */
199 mmp->mmp_seq = cpu_to_le32(EXT4_MMP_SEQ_CLEAN);
200 mmp->mmp_time = cpu_to_le64(get_seconds());
201
202 retval = write_mmp_block(bh);
203
204failed:
205 kfree(data);
206 brelse(bh);
207 return retval;
208}
209
210/*
211 * Get a random new sequence number but make sure it is not greater than
212 * EXT4_MMP_SEQ_MAX.
213 */
214static unsigned int mmp_new_seq(void)
215{
216 u32 new_seq;
217
218 do {
219 get_random_bytes(&new_seq, sizeof(u32));
220 } while (new_seq > EXT4_MMP_SEQ_MAX);
221
222 return new_seq;
223}
224
225/*
226 * Protect the filesystem from being mounted more than once.
227 */
228int ext4_multi_mount_protect(struct super_block *sb,
229 ext4_fsblk_t mmp_block)
230{
231 struct ext4_super_block *es = EXT4_SB(sb)->s_es;
232 struct buffer_head *bh = NULL;
233 struct mmp_struct *mmp = NULL;
234 struct mmpd_data *mmpd_data;
235 u32 seq;
236 unsigned int mmp_check_interval = le16_to_cpu(es->s_mmp_update_interval);
237 unsigned int wait_time = 0;
238 int retval;
239
240 if (mmp_block < le32_to_cpu(es->s_first_data_block) ||
241 mmp_block >= ext4_blocks_count(es)) {
242 ext4_warning(sb, "Invalid MMP block in superblock");
243 goto failed;
244 }
245
246 retval = read_mmp_block(sb, &bh, mmp_block);
247 if (retval)
248 goto failed;
249
250 mmp = (struct mmp_struct *)(bh->b_data);
251
252 if (mmp_check_interval < EXT4_MMP_MIN_CHECK_INTERVAL)
253 mmp_check_interval = EXT4_MMP_MIN_CHECK_INTERVAL;
254
255 /*
256 * If check_interval in MMP block is larger, use that instead of
257 * update_interval from the superblock.
258 */
259 if (mmp->mmp_check_interval > mmp_check_interval)
260 mmp_check_interval = mmp->mmp_check_interval;
261
262 seq = le32_to_cpu(mmp->mmp_seq);
263 if (seq == EXT4_MMP_SEQ_CLEAN)
264 goto skip;
265
266 if (seq == EXT4_MMP_SEQ_FSCK) {
267 dump_mmp_msg(sb, mmp, "fsck is running on the filesystem");
268 goto failed;
269 }
270
271 wait_time = min(mmp_check_interval * 2 + 1,
272 mmp_check_interval + 60);
273
274 /* Print MMP interval if more than 20 secs. */
275 if (wait_time > EXT4_MMP_MIN_CHECK_INTERVAL * 4)
276 ext4_warning(sb, "MMP interval %u higher than expected, please"
277 " wait.\n", wait_time * 2);
278
279 if (schedule_timeout_interruptible(HZ * wait_time) != 0) {
280 ext4_warning(sb, "MMP startup interrupted, failing mount\n");
281 goto failed;
282 }
283
284 retval = read_mmp_block(sb, &bh, mmp_block);
285 if (retval)
286 goto failed;
287 mmp = (struct mmp_struct *)(bh->b_data);
288 if (seq != le32_to_cpu(mmp->mmp_seq)) {
289 dump_mmp_msg(sb, mmp,
290 "Device is already active on another node.");
291 goto failed;
292 }
293
294skip:
295 /*
296 * write a new random sequence number.
297 */
298 mmp->mmp_seq = seq = cpu_to_le32(mmp_new_seq());
299
300 retval = write_mmp_block(bh);
301 if (retval)
302 goto failed;
303
304 /*
305 * wait for MMP interval and check mmp_seq.
306 */
307 if (schedule_timeout_interruptible(HZ * wait_time) != 0) {
308 ext4_warning(sb, "MMP startup interrupted, failing mount\n");
309 goto failed;
310 }
311
312 retval = read_mmp_block(sb, &bh, mmp_block);
313 if (retval)
314 goto failed;
315 mmp = (struct mmp_struct *)(bh->b_data);
316 if (seq != le32_to_cpu(mmp->mmp_seq)) {
317 dump_mmp_msg(sb, mmp,
318 "Device is already active on another node.");
319 goto failed;
320 }
321
322 mmpd_data = kmalloc(sizeof(struct mmpd_data), GFP_KERNEL);
323 if (!mmpd_data) {
324 ext4_warning(sb, "not enough memory for mmpd_data");
325 goto failed;
326 }
327 mmpd_data->sb = sb;
328 mmpd_data->bh = bh;
329
330 /*
331 * Start a kernel thread to update the MMP block periodically.
332 */
333 EXT4_SB(sb)->s_mmp_tsk = kthread_run(kmmpd, mmpd_data, "kmmpd-%s",
334 bdevname(bh->b_bdev,
335 mmp->mmp_bdevname));
336 if (IS_ERR(EXT4_SB(sb)->s_mmp_tsk)) {
337 EXT4_SB(sb)->s_mmp_tsk = NULL;
338 kfree(mmpd_data);
339 ext4_warning(sb, "Unable to create kmmpd thread for %s.",
340 sb->s_id);
341 goto failed;
342 }
343
344 return 0;
345
346failed:
347 brelse(bh);
348 return 1;
349}
350
351
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 266174b268cc..d9937df7f5cf 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -822,6 +822,8 @@ static void ext4_put_super(struct super_block *sb)
822 invalidate_bdev(sbi->journal_bdev); 822 invalidate_bdev(sbi->journal_bdev);
823 ext4_blkdev_remove(sbi); 823 ext4_blkdev_remove(sbi);
824 } 824 }
825 if (sbi->s_mmp_tsk)
826 kthread_stop(sbi->s_mmp_tsk);
825 sb->s_fs_info = NULL; 827 sb->s_fs_info = NULL;
826 /* 828 /*
827 * Now that we are completely done shutting down the 829 * Now that we are completely done shutting down the
@@ -3486,6 +3488,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
3486 EXT4_HAS_INCOMPAT_FEATURE(sb, 3488 EXT4_HAS_INCOMPAT_FEATURE(sb,
3487 EXT4_FEATURE_INCOMPAT_RECOVER)); 3489 EXT4_FEATURE_INCOMPAT_RECOVER));
3488 3490
3491 if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_MMP) &&
3492 !(sb->s_flags & MS_RDONLY))
3493 if (ext4_multi_mount_protect(sb, le64_to_cpu(es->s_mmp_block)))
3494 goto failed_mount3;
3495
3489 /* 3496 /*
3490 * The first inode we look at is the journal inode. Don't try 3497 * The first inode we look at is the journal inode. Don't try
3491 * root first: it may be modified in the journal! 3498 * root first: it may be modified in the journal!
@@ -3733,6 +3740,8 @@ failed_mount3:
3733 percpu_counter_destroy(&sbi->s_freeinodes_counter); 3740 percpu_counter_destroy(&sbi->s_freeinodes_counter);
3734 percpu_counter_destroy(&sbi->s_dirs_counter); 3741 percpu_counter_destroy(&sbi->s_dirs_counter);
3735 percpu_counter_destroy(&sbi->s_dirtyblocks_counter); 3742 percpu_counter_destroy(&sbi->s_dirtyblocks_counter);
3743 if (sbi->s_mmp_tsk)
3744 kthread_stop(sbi->s_mmp_tsk);
3736failed_mount2: 3745failed_mount2:
3737 for (i = 0; i < db_count; i++) 3746 for (i = 0; i < db_count; i++)
3738 brelse(sbi->s_group_desc[i]); 3747 brelse(sbi->s_group_desc[i]);
@@ -4268,7 +4277,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
4268 int enable_quota = 0; 4277 int enable_quota = 0;
4269 ext4_group_t g; 4278 ext4_group_t g;
4270 unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO; 4279 unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO;
4271 int err; 4280 int err = 0;
4272#ifdef CONFIG_QUOTA 4281#ifdef CONFIG_QUOTA
4273 int i; 4282 int i;
4274#endif 4283#endif
@@ -4394,6 +4403,13 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
4394 goto restore_opts; 4403 goto restore_opts;
4395 if (!ext4_setup_super(sb, es, 0)) 4404 if (!ext4_setup_super(sb, es, 0))
4396 sb->s_flags &= ~MS_RDONLY; 4405 sb->s_flags &= ~MS_RDONLY;
4406 if (EXT4_HAS_INCOMPAT_FEATURE(sb,
4407 EXT4_FEATURE_INCOMPAT_MMP))
4408 if (ext4_multi_mount_protect(sb,
4409 le64_to_cpu(es->s_mmp_block))) {
4410 err = -EROFS;
4411 goto restore_opts;
4412 }
4397 enable_quota = 1; 4413 enable_quota = 1;
4398 } 4414 }
4399 } 4415 }