Whamcloud - gitweb
b=22117 Patch to limit mmp interval
[fs/lustre-release.git] / ldiskfs / kernel_patches / patches / ext3-mmp-2.6.18-vanilla.patch
1 Index: linux-stage/fs/ext3/super.c
2 ===================================================================
3 --- linux-stage.orig/fs/ext3/super.c
4 +++ linux-stage/fs/ext3/super.c
5 @@ -35,6 +35,8 @@
6  #include <linux/namei.h>
7  #include <linux/quotaops.h>
8  #include <linux/seq_file.h>
9 +#include <linux/kthread.h>
10 +#include <linux/utsname.h>
11  
12  #include <asm/uaccess.h>
13  
14 @@ -83,7 +85,7 @@ handle_t *ext3_journal_start_sb(struct s
15          * take the FS itself readonly cleanly. */
16         journal = EXT3_SB(sb)->s_journal;
17         if (is_journal_aborted(journal)) {
18 -               ext3_abort(sb, __FUNCTION__,
19 +               ext3_abort(sb, __func__,
20                            "Detected aborted journal");
21                 return ERR_PTR(-EROFS);
22         }
23 @@ -305,7 +307,7 @@ void ext3_update_dynamic_rev(struct supe
24         if (le32_to_cpu(es->s_rev_level) > EXT3_GOOD_OLD_REV)
25                 return;
26  
27 -       ext3_warning(sb, __FUNCTION__,
28 +       ext3_warning(sb, __func__,
29                      "updating to rev %d because of new feature flag, "
30                      "running e2fsck is recommended",
31                      EXT3_DYNAMIC_REV);
32 @@ -440,6 +442,8 @@ static void ext3_put_super (struct super
33                 invalidate_bdev(sbi->journal_bdev, 0);
34                 ext3_blkdev_remove(sbi);
35         }
36 +       if (sbi->s_mmp_tsk)
37 +               kthread_stop(sbi->s_mmp_tsk);
38         if (sbi->s_dev_proc) {
39                 remove_proc_entry(sbi->s_dev_proc->name, proc_root_ext3);
40                 sbi->s_dev_proc = NULL;
41 @@ -1395,7 +1399,7 @@ static int ext3_check_descriptors (struc
42                         return 0;
43                 }
44                 if (!ext3_group_desc_csum_verify(sbi, i, gdp)) {
45 -                       ext3_error(sb, __FUNCTION__,
46 +                       ext3_error(sb, __func__,
47                                    "Checksum for group %d failed (%u!=%u)\n", i,
48                                    le16_to_cpu(ext3_group_desc_csum(sbi,i,gdp)),
49                                    le16_to_cpu(gdp->bg_checksum));
50 @@ -1490,7 +1494,7 @@ static void ext3_orphan_cleanup (struct 
51                 if (inode->i_nlink) {
52                         printk(KERN_DEBUG
53                                 "%s: truncating inode %lu to %Ld bytes\n",
54 -                               __FUNCTION__, inode->i_ino, inode->i_size);
55 +                               __func__, inode->i_ino, inode->i_size);
56                         jbd_debug(2, "truncating inode %lu to %Ld bytes\n",
57                                   inode->i_ino, inode->i_size);
58                         ext3_truncate(inode);
59 @@ -1498,7 +1502,7 @@ static void ext3_orphan_cleanup (struct 
60                 } else {
61                         printk(KERN_DEBUG
62                                 "%s: deleting unreferenced inode %lu\n",
63 -                               __FUNCTION__, inode->i_ino);
64 +                               __func__, inode->i_ino);
65                         jbd_debug(2, "deleting unreferenced inode %lu\n",
66                                   inode->i_ino);
67                         nr_orphans++;
68 @@ -1568,6 +1572,355 @@ static ext3_fsblk_t descriptor_loc(struc
69         return (has_super + ext3_group_first_block_no(sb, bg));
70  }
71  
72 +/*
73 + * Write the MMP block using WRITE_SYNC to try to get the block on-disk
74 + * faster.
75 + */
76 +static int write_mmp_block(struct buffer_head *bh)
77 +{
78 +       mark_buffer_dirty(bh);
79 +       lock_buffer(bh);
80 +       bh->b_end_io = end_buffer_write_sync;
81 +       get_bh(bh);
82 +       submit_bh(WRITE_SYNC, bh);
83 +       wait_on_buffer(bh);
84 +       if (unlikely(!buffer_uptodate(bh)))
85 +               return 1;
86 +
87 +       return 0;
88 +}
89 +
90 +/*
91 + * Read the MMP block. It _must_ be read from disk and hence we clear the
92 + * uptodate flag on the buffer.
93 + */
94 +static int read_mmp_block(struct super_block *sb, struct buffer_head **bh,
95 +                         unsigned long mmp_block)
96 +{
97 +       struct mmp_struct *mmp;
98 +
99 +       if (*bh)
100 +               clear_buffer_uptodate(*bh);
101 +
102 +#if 0
103 +       brelse(*bh);
104 +
105 +       *bh = sb_bread(sb, mmp_block);
106 +#else
107 +       if (!*bh)
108 +               *bh = sb_getblk(sb, mmp_block);
109 +       if (*bh) {
110 +               get_bh(*bh);
111 +               lock_buffer(*bh);
112 +               (*bh)->b_end_io = end_buffer_read_sync;
113 +               submit_bh(READ_SYNC, *bh);
114 +               wait_on_buffer(*bh);
115 +               if (!buffer_uptodate(*bh)) {
116 +                       brelse(*bh);
117 +                       *bh = NULL;
118 +               }
119 +       }
120 +#endif
121 +       if (!*bh) {
122 +               ext3_warning(sb, __func__,
123 +                            "Error while reading MMP block %lu", mmp_block);
124 +               return -EIO;
125 +       }
126 +
127 +       mmp = (struct mmp_struct *)((*bh)->b_data);
128 +       if (le32_to_cpu(mmp->mmp_magic) != EXT3_MMP_MAGIC)
129 +               return -EINVAL;
130 +
131 +       return 0;
132 +}
133 +
134 +/*
135 + * Dump as much information as possible to help the admin.
136 + */
137 +static void dump_mmp_msg(struct super_block *sb, struct mmp_struct *mmp,
138 +                        const char *function, const char *msg)
139 +{
140 +       ext3_warning(sb, function, "%s", msg);
141 +       ext3_warning(sb, function, "MMP failure info: last update time: %llu, "
142 +                    "last update node: %s, last update device: %s\n",
143 +                    (long long unsigned int)le64_to_cpu(mmp->mmp_time),
144 +                    mmp->mmp_nodename, mmp->mmp_bdevname);
145 +}
146 +
147 +/*
148 + * kmmpd will update the MMP sequence every s_mmp_update_interval seconds
149 + */
150 +static int kmmpd(void *data)
151 +{
152 +       struct super_block *sb = ((struct mmpd_data *) data)->sb;
153 +       struct buffer_head *bh = ((struct mmpd_data *) data)->bh;
154 +       struct ext3_super_block *es = EXT3_SB(sb)->s_es;
155 +       struct mmp_struct *mmp;
156 +       unsigned long mmp_block;
157 +       u32 seq = 0;
158 +       unsigned long failed_writes = 0;
159 +       int mmp_update_interval = le16_to_cpu(es->s_mmp_update_interval);
160 +       unsigned mmp_check_interval;
161 +       unsigned long last_update_time;
162 +       unsigned long diff;
163 +       int retval;
164 +
165 +       mmp_block = le64_to_cpu(es->s_mmp_block);
166 +       mmp = (struct mmp_struct *)(bh->b_data);
167 +       mmp->mmp_time = cpu_to_le64(get_seconds());
168 +       /*
169 +        * Start with the higher mmp_check_interval and reduce it if
170 +        * the MMP block is being updated on time.
171 +        */
172 +       mmp_check_interval = max(5UL * mmp_update_interval,
173 +                                EXT3_MMP_MIN_CHECK_INTERVAL);
174 +       mmp->mmp_check_interval = cpu_to_le16(mmp_check_interval);
175 +       bdevname(bh->b_bdev, mmp->mmp_bdevname);
176 +
177 +       down_read(&uts_sem);
178 +       memcpy(mmp->mmp_nodename, system_utsname.nodename,
179 +              sizeof(mmp->mmp_nodename));
180 +       up_read(&uts_sem);
181 +
182 +       while (!kthread_should_stop()) {
183 +               if (++seq > EXT3_MMP_SEQ_MAX)
184 +                       seq = 1;
185 +
186 +               mmp->mmp_seq = cpu_to_le32(seq);
187 +               mmp->mmp_time = cpu_to_le64(get_seconds());
188 +               last_update_time = jiffies;
189 +
190 +               retval = write_mmp_block(bh);
191 +               /*
192 +                * Don't spew too many error messages. Print one every
193 +                * (s_mmp_update_interval * 60) seconds.
194 +                */
195 +               if (retval && (failed_writes % 60) == 0) {
196 +                       ext3_error(sb, __func__,
197 +                                  "Error writing to MMP block");
198 +                       failed_writes++;
199 +               }
200 +
201 +               if (!(le32_to_cpu(es->s_feature_incompat) &
202 +                   EXT3_FEATURE_INCOMPAT_MMP)) {
203 +                       ext3_warning(sb, __func__, "kmmpd being stopped "
204 +                                    "since MMP feature has been disabled.");
205 +                       EXT3_SB(sb)->s_mmp_tsk = NULL;
206 +                       goto failed;
207 +               }
208 +
209 +               if (sb->s_flags & MS_RDONLY) {
210 +                       ext3_warning(sb, __func__, "kmmpd being stopped "
211 +                                    "since filesystem has been remounted as "
212 +                                    "readonly.");
213 +                       EXT3_SB(sb)->s_mmp_tsk = NULL;
214 +                       goto failed;
215 +               }
216 +
217 +               diff = jiffies - last_update_time;
218 +               if (diff < mmp_update_interval * HZ)
219 +                       schedule_timeout_interruptible(mmp_update_interval*
220 +                                                      HZ - diff);
221 +
222 +               /*
223 +                * We need to make sure that more than mmp_check_interval
224 +                * seconds have not passed since writing. If that has happened
225 +                * we need to check if the MMP block is as we left it.
226 +                */
227 +               diff = jiffies - last_update_time;
228 +               if (diff > mmp_check_interval * HZ) {
229 +                       struct buffer_head *bh_check = NULL;
230 +                       struct mmp_struct *mmp_check;
231 +
232 +                       retval = read_mmp_block(sb, &bh_check, mmp_block);
233 +                       if (retval) {
234 +                               ext3_error(sb, __func__, "error reading MMP"
235 +                                          "data: %d", retval);
236 +                               EXT3_SB(sb)->s_mmp_tsk = NULL;
237 +                               goto failed;
238 +                       }
239 +
240 +                       mmp_check = (struct mmp_struct *)(bh_check->b_data);
241 +                       if (mmp->mmp_seq != mmp_check->mmp_seq ||
242 +                           memcmp(mmp->mmp_nodename, mmp_check->mmp_nodename,
243 +                                  sizeof(mmp->mmp_nodename))) {
244 +                               dump_mmp_msg(sb, mmp_check, __func__,
245 +                                            "Error while updating MMP info. "
246 +                                            "The filesystem seems to have "
247 +                                            "been multiply mounted.");
248 +                               ext3_error(sb, __func__, "abort");
249 +                               goto failed;
250 +                       }
251 +                       put_bh(bh_check);
252 +               }
253 +
254 +               /*
255 +                * Adjust the mmp_check_interval depending on how much time
256 +                * it took for the MMP block to be written.
257 +                */
258 +               mmp_check_interval = max(min(5 * diff / HZ,
259 +                                            EXT3_MMP_MAX_CHECK_INTERVAL),
260 +                                        EXT3_MMP_MIN_CHECK_INTERVAL);
261 +               mmp->mmp_check_interval = cpu_to_le16(mmp_check_interval);
262 +       }
263 +
264 +       /*
265 +        * Unmount seems to be clean.
266 +        */
267 +       mmp->mmp_seq = cpu_to_le32(EXT3_MMP_SEQ_CLEAN);
268 +       mmp->mmp_time = cpu_to_le64(get_seconds());
269 +
270 +       retval = write_mmp_block(bh);
271 +
272 +failed:
273 +       brelse(bh);
274 +       return retval;
275 +}
276 +
277 +/*
278 + * Get a random new sequence number but make sure it is not greater than
279 + * EXT3_MMP_SEQ_MAX.
280 + */
281 +static unsigned int mmp_new_seq(void)
282 +{
283 +       u32 new_seq;
284 +
285 +       do {
286 +               get_random_bytes(&new_seq, sizeof(u32));
287 +       } while (new_seq > EXT3_MMP_SEQ_MAX);
288 +
289 +       return new_seq;
290 +}
291 +
292 +/*
293 + * Protect the filesystem from being mounted more than once.
294 + */
295 +static int ext3_multi_mount_protect(struct super_block *sb,
296 +                                   unsigned long mmp_block)
297 +{
298 +       struct ext3_super_block *es = EXT3_SB(sb)->s_es;
299 +       struct buffer_head *bh = NULL;
300 +       struct mmp_struct *mmp = NULL;
301 +       struct mmpd_data *mmpd_data;
302 +       u32 seq;
303 +       unsigned int mmp_check_interval = le16_to_cpu(es->s_mmp_update_interval);
304 +       unsigned int wait_time = 0;
305 +       int retval;
306 +
307 +       if (mmp_block < le32_to_cpu(es->s_first_data_block) ||
308 +           mmp_block >= le32_to_cpu(es->s_blocks_count)) {
309 +               ext3_warning(sb, __func__,
310 +                            "Invalid MMP block in superblock");
311 +               goto failed;
312 +       }
313 +
314 +       retval = read_mmp_block(sb, &bh, mmp_block);
315 +       if (retval)
316 +               goto failed;
317 +
318 +       mmp = (struct mmp_struct *)(bh->b_data);
319 +
320 +       if (mmp_check_interval < EXT3_MMP_MIN_CHECK_INTERVAL)
321 +               mmp_check_interval = EXT3_MMP_MIN_CHECK_INTERVAL;
322 +
323 +       /*
324 +        * If check_interval in MMP block is larger, use that instead of
325 +        * update_interval from the superblock.
326 +        */
327 +       if (mmp->mmp_check_interval > mmp_check_interval)
328 +               mmp_check_interval = mmp->mmp_check_interval;
329 +
330 +       seq = le32_to_cpu(mmp->mmp_seq);
331 +       if (seq == EXT3_MMP_SEQ_CLEAN)
332 +               goto skip;
333 +
334 +       if (seq == EXT3_MMP_SEQ_FSCK) {
335 +               dump_mmp_msg(sb, mmp, __func__,
336 +                            "fsck is running on the filesystem");
337 +               goto failed;
338 +       }
339 +
340 +       wait_time = min(mmp_check_interval * 2 + 1,
341 +               mmp_check_interval + 60);
342 +
343 +       /* Print MMP interval if more than 20 secs. */
344 +       if (wait_time > EXT3_MMP_MIN_CHECK_INTERVAL * 4)
345 +               ext3_warning(sb, __func__, "MMP interval %u higher than "
346 +                            "expected, please wait.\n", wait_time * 2);
347 +
348 +       if (schedule_timeout_interruptible(HZ * wait_time) != 0) {
349 +               ext3_warning(sb, __func__, "MMP startup interrupted, failing "
350 +                            "mount\n");
351 +               goto failed;
352 +       }
353 +
354 +       retval = read_mmp_block(sb, &bh, mmp_block);
355 +       if (retval)
356 +               goto failed;
357 +       mmp = (struct mmp_struct *)(bh->b_data);
358 +       if (seq != le32_to_cpu(mmp->mmp_seq)) {
359 +               dump_mmp_msg(sb, mmp, __func__,
360 +                            "Device is already active on another node.");
361 +               goto failed;
362 +       }
363 +
364 +skip:
365 +       /*
366 +        * write a new random sequence number.
367 +        */
368 +       mmp->mmp_seq = seq = cpu_to_le32(mmp_new_seq());
369 +
370 +       retval = write_mmp_block(bh);
371 +       if (retval)
372 +               goto failed;
373 +
374 +       /*
375 +        * wait for MMP interval and check mmp_seq.
376 +        */
377 +       if (schedule_timeout_interruptible(HZ * wait_time) != 0) {
378 +               ext3_warning(sb, __func__, "MMP startup interrupted, failing "
379 +                            "mount\n");
380 +               goto failed;
381 +       }
382 +
383 +       retval = read_mmp_block(sb, &bh, mmp_block);
384 +       if (retval)
385 +               goto failed;
386 +       mmp = (struct mmp_struct *)(bh->b_data);
387 +       if (seq != le32_to_cpu(mmp->mmp_seq)) {
388 +               dump_mmp_msg(sb, mmp, __func__,
389 +                            "Device is already active on another node.");
390 +               goto failed;
391 +       }
392 +
393 +       mmpd_data = kmalloc(sizeof(struct mmpd_data *), GFP_KERNEL);
394 +       if (!mmpd_data) {
395 +               ext3_warning(sb, KERN_ERR, "not enough memory for mmpd_data");
396 +               goto failed;
397 +       }
398 +       mmpd_data->sb = sb;
399 +       mmpd_data->bh = bh;
400 +
401 +       /*
402 +        * Start a kernel thread to update the MMP block periodically.
403 +        */
404 +       EXT3_SB(sb)->s_mmp_tsk = kthread_run(kmmpd, mmpd_data, "kmmpd-%s",
405 +                                            bdevname(bh->b_bdev,
406 +                                                     mmp->mmp_bdevname));
407 +       if (IS_ERR(EXT3_SB(sb)->s_mmp_tsk)) {
408 +               EXT3_SB(sb)->s_mmp_tsk = NULL;
409 +               ext3_warning(sb, __func__, "Unable to create kmmpd thread "
410 +                            "for %s.", sb->s_id);
411 +               goto failed;
412 +       }
413 +
414 +       return 0;
415 +
416 +failed:
417 +       brelse(bh);
418 +       return 1;
419 +}
420 +
421  
422  static int ext3_fill_super (struct super_block *sb, void *data, int silent)
423  {
424 @@ -1901,6 +2254,11 @@ static int ext3_fill_super (struct super
425                           EXT3_HAS_INCOMPAT_FEATURE(sb,
426                                     EXT3_FEATURE_INCOMPAT_RECOVER));
427  
428 +       if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_MMP) &&
429 +           !(sb->s_flags & MS_RDONLY))
430 +               if (ext3_multi_mount_protect(sb, le64_to_cpu(es->s_mmp_block)))
431 +                       goto failed_mount3;
432 +
433         /*
434          * The first inode we look at is the journal inode.  Don't try
435          * root first: it may be modified in the journal!
436 @@ -2033,6 +2391,8 @@ cantfind_ext3:
437  failed_mount4:
438         journal_destroy(sbi->s_journal);
439  failed_mount3:
440 +       if (sbi->s_mmp_tsk)
441 +               kthread_stop(sbi->s_mmp_tsk);
442         percpu_counter_destroy(&sbi->s_freeblocks_counter);
443         percpu_counter_destroy(&sbi->s_freeinodes_counter);
444         percpu_counter_destroy(&sbi->s_dirs_counter);
445 @@ -2409,9 +2769,9 @@ static void ext3_clear_journal_err(struc
446                 char nbuf[16];
447  
448                 errstr = ext3_decode_error(sb, j_errno, nbuf);
449 -               ext3_warning(sb, __FUNCTION__, "Filesystem error recorded "
450 +               ext3_warning(sb, __func__, "Filesystem error recorded "
451                              "from previous mount: %s", errstr);
452 -               ext3_warning(sb, __FUNCTION__, "Marking fs in need of "
453 +               ext3_warning(sb, __func__, "Marking fs in need of "
454                              "filesystem check.");
455  
456                 EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS;
457 @@ -2531,7 +2891,7 @@ static int ext3_remount (struct super_bl
458         ext3_fsblk_t n_blocks_count = 0;
459         unsigned long old_sb_flags;
460         struct ext3_mount_options old_opts;
461 -       int err;
462 +       int err = 0;
463  #ifdef CONFIG_QUOTA
464         int i;
465  #endif
466 @@ -2557,7 +2917,7 @@ static int ext3_remount (struct super_bl
467         }
468  
469         if (sbi->s_mount_opt & EXT3_MOUNT_ABORT)
470 -               ext3_abort(sb, __FUNCTION__, "Abort forced by user");
471 +               ext3_abort(sb, __func__, "Abort forced by user");
472  
473         sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
474                 ((sbi->s_mount_opt & EXT3_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
475 @@ -2630,6 +2990,13 @@ static int ext3_remount (struct super_bl
476                         }
477                         if (!ext3_setup_super (sb, es, 0))
478                                 sb->s_flags &= ~MS_RDONLY;
479 +                       if (EXT3_HAS_INCOMPAT_FEATURE(sb,
480 +                                                   EXT3_FEATURE_INCOMPAT_MMP))
481 +                               if (ext3_multi_mount_protect(sb,
482 +                                               le64_to_cpu(es->s_mmp_block))) {
483 +                                       err = -EROFS;
484 +                                       goto restore_opts;
485 +                               }
486                 }
487         }
488  #ifdef CONFIG_QUOTA
489 Index: linux-stage/include/linux/ext3_fs.h
490 ===================================================================
491 --- linux-stage.orig/include/linux/ext3_fs.h
492 +++ linux-stage/include/linux/ext3_fs.h
493 @@ -594,13 +594,17 @@ struct ext3_super_block {
494         __le32  s_first_meta_bg;        /* First metablock block group */
495         __le32  s_mkfs_time;            /* When the filesystem was created */
496         __le32  s_jnl_blocks[17];       /* Backup of the journal inode */
497 -       __le32  s_blocks_count_hi;      /* Blocks count high 32 bits */
498 +/*150*/        __le32  s_blocks_count_hi;      /* Blocks count high 32 bits */
499         __le32  s_r_blocks_count_hi;    /* Reserved blocks count high 32 bits*/
500         __le32  s_free_blocks_count_hi; /* Free blocks count high 32 bits */
501         __le16  s_min_extra_isize;      /* All inodes have at least # bytes */
502         __le16  s_want_extra_isize;     /* New inodes should reserve # bytes */
503 -       __le32  s_flags;                /* Miscellaneous flags */
504 -       __u32   s_reserved[167];        /* Padding to the end of the block */
505 +/*160*/        __le32  s_flags;                /* Miscellaneous flags */
506 +       __le16  s_raid_stride;          /* RAID stride */
507 +       __le16  s_mmp_update_interval;  /* # seconds to wait in MMP checking */
508 +       __le64  s_mmp_block;            /* Block for multi-mount protection */
509 +/*170*/        __le32  s_raid_stripe_width;    /* blocks on all data disks (N*stride)*/
510 +       __le32  s_reserved[163];        /* Padding to the end of the block */
511  };
512  
513  #ifdef __KERNEL__
514 @@ -703,12 +707,14 @@ static inline int ext3_valid_inum(struct
515  #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV      0x0008 /* Journal device */
516  #define EXT3_FEATURE_INCOMPAT_META_BG          0x0010
517  #define EXT3_FEATURE_INCOMPAT_EXTENTS          0x0040 /* extents support */
518 +#define EXT3_FEATURE_INCOMPAT_MMP              0x0100
519  
520  #define EXT3_FEATURE_COMPAT_SUPP       EXT2_FEATURE_COMPAT_EXT_ATTR
521  #define EXT3_FEATURE_INCOMPAT_SUPP     (EXT3_FEATURE_INCOMPAT_FILETYPE| \
522                                          EXT3_FEATURE_INCOMPAT_RECOVER| \
523                                          EXT3_FEATURE_INCOMPAT_META_BG| \
524 -                                        EXT3_FEATURE_INCOMPAT_EXTENTS)
525 +                                        EXT3_FEATURE_INCOMPAT_EXTENTS| \
526 +                                        EXT3_FEATURE_INCOMPAT_MMP)
527  #define EXT3_FEATURE_RO_COMPAT_SUPP    (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
528                                          EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \
529                                          EXT4_FEATURE_RO_COMPAT_GDT_CSUM| \
530 @@ -871,6 +877,50 @@ ext3_group_first_block_no(struct super_b
531  #define ERR_BAD_DX_DIR -75000
532  
533  /*
534 + * This structure will be used for multiple mount protection. It will be
535 + * written into the block number saved in the s_mmp_block field in the
536 + * superblock. Programs that check MMP should assume that if
537 + * SEQ_FSCK (or any unknown code above SEQ_MAX) is present then it is NOT safe
538 + * to use the filesystem, regardless of how old the timestamp is.
539 + */
540 +#define EXT3_MMP_MAGIC     0x004D4D50U /* ASCII for MMP */
541 +#define EXT3_MMP_SEQ_CLEAN 0xFF4D4D50U /* mmp_seq value for clean unmount */
542 +#define EXT3_MMP_SEQ_FSCK  0xE24D4D50U /* mmp_seq value when being fscked */
543 +#define EXT3_MMP_SEQ_MAX   0xE24D4D4FU /* maximum valid mmp_seq value */
544 +
545 +struct mmp_struct {
546 +       __le32  mmp_magic;
547 +       __le32  mmp_seq;
548 +       __le64  mmp_time;
549 +       char    mmp_nodename[64];
550 +       char    mmp_bdevname[32];
551 +       __le16  mmp_check_interval;
552 +       __le16  mmp_pad1;
553 +       __le32  mmp_pad2[227];
554 +};
555 +
556 +/* arguments passed to the mmp thread */
557 +struct mmpd_data {
558 +       struct buffer_head *bh; /* bh from initial read_mmp_block() */
559 +       struct super_block *sb;  /* super block of the fs */
560 +};
561 +
562 +/*
563 + * Default interval in seconds to update the MMP sequence number.
564 + */
565 +#define EXT3_MMP_UPDATE_INTERVAL   1
566 +
567 +/*
568 + * Minimum interval for MMP checking in seconds.
569 + */
570 +#define EXT3_MMP_MIN_CHECK_INTERVAL    5UL
571 +
572 +/*
573 + * Maximum interval for MMP checking in seconds.
574 + */
575 +#define EXT3_MMP_MAX_CHECK_INTERVAL    300UL
576 +
577 +/*
578   * Function prototypes
579   */
580  
581 Index: linux-stage/include/linux/ext3_fs_sb.h
582 ===================================================================
583 --- linux-stage.orig/include/linux/ext3_fs_sb.h
584 +++ linux-stage/include/linux/ext3_fs_sb.h
585 @@ -157,6 +157,8 @@ struct ext3_sb_info {
586         /* locality groups */
587         struct ext3_locality_group *s_locality_groups;
588  
589 +       /* Kernel thread for multiple mount protection */
590 +       struct task_struct *s_mmp_tsk;
591  };
592  
593  #define EXT3_GROUP_INFO(sb, group)                                        \