hc
2024-05-10 23fa18eaa71266feff7ba8d83022d9e1cc83c65a
kernel/fs/ext4/mmp.c
....@@ -39,26 +39,34 @@
3939 * Write the MMP block using REQ_SYNC to try to get the block on-disk
4040 * faster.
4141 */
42
-static int write_mmp_block(struct super_block *sb, struct buffer_head *bh)
42
+static int write_mmp_block_thawed(struct super_block *sb,
43
+ struct buffer_head *bh)
4344 {
4445 struct mmp_struct *mmp = (struct mmp_struct *)(bh->b_data);
4546
46
- /*
47
- * We protect against freezing so that we don't create dirty buffers
48
- * on frozen filesystem.
49
- */
50
- sb_start_write(sb);
5147 ext4_mmp_csum_set(sb, mmp);
5248 lock_buffer(bh);
5349 bh->b_end_io = end_buffer_write_sync;
5450 get_bh(bh);
5551 submit_bh(REQ_OP_WRITE, REQ_SYNC | REQ_META | REQ_PRIO, bh);
5652 wait_on_buffer(bh);
57
- sb_end_write(sb);
5853 if (unlikely(!buffer_uptodate(bh)))
59
- return 1;
60
-
54
+ return -EIO;
6155 return 0;
56
+}
57
+
58
+static int write_mmp_block(struct super_block *sb, struct buffer_head *bh)
59
+{
60
+ int err;
61
+
62
+ /*
63
+ * We protect against freezing so that we don't create dirty buffers
64
+ * on frozen filesystem.
65
+ */
66
+ sb_start_write(sb);
67
+ err = write_mmp_block_thawed(sb, bh);
68
+ sb_end_write(sb);
69
+ return err;
6270 }
6371
6472 /*
....@@ -85,15 +93,11 @@
8593 }
8694 }
8795
88
- get_bh(*bh);
8996 lock_buffer(*bh);
90
- (*bh)->b_end_io = end_buffer_read_sync;
91
- submit_bh(REQ_OP_READ, REQ_META | REQ_PRIO, *bh);
92
- wait_on_buffer(*bh);
93
- if (!buffer_uptodate(*bh)) {
94
- ret = -EIO;
97
+ ret = ext4_read_bh(*bh, REQ_META | REQ_PRIO, NULL);
98
+ if (ret)
9599 goto warn_exit;
96
- }
100
+
97101 mmp = (struct mmp_struct *)((*bh)->b_data);
98102 if (le32_to_cpu(mmp->mmp_magic) != EXT4_MMP_MAGIC) {
99103 ret = -EFSCORRUPTED;
....@@ -131,9 +135,9 @@
131135 */
132136 static int kmmpd(void *data)
133137 {
134
- struct super_block *sb = ((struct mmpd_data *) data)->sb;
135
- struct buffer_head *bh = ((struct mmpd_data *) data)->bh;
138
+ struct super_block *sb = (struct super_block *) data;
136139 struct ext4_super_block *es = EXT4_SB(sb)->s_es;
140
+ struct buffer_head *bh = EXT4_SB(sb)->s_mmp_bh;
137141 struct mmp_struct *mmp;
138142 ext4_fsblk_t mmp_block;
139143 u32 seq = 0;
....@@ -160,7 +164,12 @@
160164 memcpy(mmp->mmp_nodename, init_utsname()->nodename,
161165 sizeof(mmp->mmp_nodename));
162166
163
- while (!kthread_should_stop()) {
167
+ while (!kthread_should_stop() && !sb_rdonly(sb)) {
168
+ if (!ext4_has_feature_mmp(sb)) {
169
+ ext4_warning(sb, "kmmpd being stopped since MMP feature"
170
+ " has been disabled.");
171
+ goto wait_to_exit;
172
+ }
164173 if (++seq > EXT4_MMP_SEQ_MAX)
165174 seq = 1;
166175
....@@ -174,20 +183,12 @@
174183 * (s_mmp_update_interval * 60) seconds.
175184 */
176185 if (retval) {
177
- if ((failed_writes % 60) == 0)
178
- ext4_error(sb, "Error writing to MMP block");
186
+ if ((failed_writes % 60) == 0) {
187
+ ext4_error_err(sb, -retval,
188
+ "Error writing to MMP block");
189
+ }
179190 failed_writes++;
180191 }
181
-
182
- if (!(le32_to_cpu(es->s_feature_incompat) &
183
- EXT4_FEATURE_INCOMPAT_MMP)) {
184
- ext4_warning(sb, "kmmpd being stopped since MMP feature"
185
- " has been disabled.");
186
- goto exit_thread;
187
- }
188
-
189
- if (sb_rdonly(sb))
190
- break;
191192
192193 diff = jiffies - last_update_time;
193194 if (diff < mmp_update_interval * HZ)
....@@ -206,9 +207,10 @@
206207
207208 retval = read_mmp_block(sb, &bh_check, mmp_block);
208209 if (retval) {
209
- ext4_error(sb, "error reading MMP data: %d",
210
- retval);
211
- goto exit_thread;
210
+ ext4_error_err(sb, -retval,
211
+ "error reading MMP data: %d",
212
+ retval);
213
+ goto wait_to_exit;
212214 }
213215
214216 mmp_check = (struct mmp_struct *)(bh_check->b_data);
....@@ -219,10 +221,10 @@
219221 "Error while updating MMP info. "
220222 "The filesystem seems to have been"
221223 " multiply mounted.");
222
- ext4_error(sb, "abort");
224
+ ext4_error_err(sb, EBUSY, "abort");
223225 put_bh(bh_check);
224226 retval = -EBUSY;
225
- goto exit_thread;
227
+ goto wait_to_exit;
226228 }
227229 put_bh(bh_check);
228230 }
....@@ -245,11 +247,23 @@
245247
246248 retval = write_mmp_block(sb, bh);
247249
248
-exit_thread:
249
- EXT4_SB(sb)->s_mmp_tsk = NULL;
250
- kfree(data);
251
- brelse(bh);
250
+wait_to_exit:
251
+ while (!kthread_should_stop()) {
252
+ set_current_state(TASK_INTERRUPTIBLE);
253
+ if (!kthread_should_stop())
254
+ schedule();
255
+ }
256
+ set_current_state(TASK_RUNNING);
252257 return retval;
258
+}
259
+
260
+void ext4_stop_mmpd(struct ext4_sb_info *sbi)
261
+{
262
+ if (sbi->s_mmp_tsk) {
263
+ kthread_stop(sbi->s_mmp_tsk);
264
+ brelse(sbi->s_mmp_bh);
265
+ sbi->s_mmp_tsk = NULL;
266
+ }
253267 }
254268
255269 /*
....@@ -276,7 +290,6 @@
276290 struct ext4_super_block *es = EXT4_SB(sb)->s_es;
277291 struct buffer_head *bh = NULL;
278292 struct mmp_struct *mmp = NULL;
279
- struct mmpd_data *mmpd_data;
280293 u32 seq;
281294 unsigned int mmp_check_interval = le16_to_cpu(es->s_mmp_update_interval);
282295 unsigned int wait_time = 0;
....@@ -285,6 +298,7 @@
285298 if (mmp_block < le32_to_cpu(es->s_first_data_block) ||
286299 mmp_block >= ext4_blocks_count(es)) {
287300 ext4_warning(sb, "Invalid MMP block in superblock");
301
+ retval = -EINVAL;
288302 goto failed;
289303 }
290304
....@@ -310,6 +324,7 @@
310324
311325 if (seq == EXT4_MMP_SEQ_FSCK) {
312326 dump_mmp_msg(sb, mmp, "fsck is running on the filesystem");
327
+ retval = -EBUSY;
313328 goto failed;
314329 }
315330
....@@ -323,6 +338,7 @@
323338
324339 if (schedule_timeout_interruptible(HZ * wait_time) != 0) {
325340 ext4_warning(sb, "MMP startup interrupted, failing mount\n");
341
+ retval = -ETIMEDOUT;
326342 goto failed;
327343 }
328344
....@@ -333,6 +349,7 @@
333349 if (seq != le32_to_cpu(mmp->mmp_seq)) {
334350 dump_mmp_msg(sb, mmp,
335351 "Device is already active on another node.");
352
+ retval = -EBUSY;
336353 goto failed;
337354 }
338355
....@@ -343,7 +360,11 @@
343360 seq = mmp_new_seq();
344361 mmp->mmp_seq = cpu_to_le32(seq);
345362
346
- retval = write_mmp_block(sb, bh);
363
+ /*
364
+ * On mount / remount we are protected against fs freezing (by s_umount
365
+ * semaphore) and grabbing freeze protection upsets lockdep
366
+ */
367
+ retval = write_mmp_block_thawed(sb, bh);
347368 if (retval)
348369 goto failed;
349370
....@@ -352,6 +373,7 @@
352373 */
353374 if (schedule_timeout_interruptible(HZ * wait_time) != 0) {
354375 ext4_warning(sb, "MMP startup interrupted, failing mount");
376
+ retval = -ETIMEDOUT;
355377 goto failed;
356378 }
357379
....@@ -362,29 +384,24 @@
362384 if (seq != le32_to_cpu(mmp->mmp_seq)) {
363385 dump_mmp_msg(sb, mmp,
364386 "Device is already active on another node.");
387
+ retval = -EBUSY;
365388 goto failed;
366389 }
367390
368
- mmpd_data = kmalloc(sizeof(*mmpd_data), GFP_KERNEL);
369
- if (!mmpd_data) {
370
- ext4_warning(sb, "not enough memory for mmpd_data");
371
- goto failed;
372
- }
373
- mmpd_data->sb = sb;
374
- mmpd_data->bh = bh;
391
+ EXT4_SB(sb)->s_mmp_bh = bh;
375392
376393 /*
377394 * Start a kernel thread to update the MMP block periodically.
378395 */
379
- EXT4_SB(sb)->s_mmp_tsk = kthread_run(kmmpd, mmpd_data, "kmmpd-%.*s",
396
+ EXT4_SB(sb)->s_mmp_tsk = kthread_run(kmmpd, sb, "kmmpd-%.*s",
380397 (int)sizeof(mmp->mmp_bdevname),
381398 bdevname(bh->b_bdev,
382399 mmp->mmp_bdevname));
383400 if (IS_ERR(EXT4_SB(sb)->s_mmp_tsk)) {
384401 EXT4_SB(sb)->s_mmp_tsk = NULL;
385
- kfree(mmpd_data);
386402 ext4_warning(sb, "Unable to create kmmpd thread for %s.",
387403 sb->s_id);
404
+ retval = -ENOMEM;
388405 goto failed;
389406 }
390407
....@@ -392,7 +409,5 @@
392409
393410 failed:
394411 brelse(bh);
395
- return 1;
412
+ return retval;
396413 }
397
-
398
-