Whamcloud - gitweb
b=21564 Print mmp_check_interval in kmmpd
[fs/lustre-release.git] / ldiskfs / kernel_patches / patches / ext3-mmp-2.6-sles10.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 @@ -36,6 +36,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 @@ -84,7 +86,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 @@ -436,6 +438,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 @@ -1357,7 +1361,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 @@ -1446,7 +1450,7 @@ static void ext3_orphan_cleanup (struct 
51                 if (inode->i_nlink) {
52                         printk(KERN_DEBUG
53                                 "%s: truncating inode %ld 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 %ld to %Ld bytes\n",
57                                   inode->i_ino, inode->i_size);
58                         ext3_truncate(inode);
59 @@ -1454,7 +1458,7 @@ static void ext3_orphan_cleanup (struct 
60                 } else {
61                         printk(KERN_DEBUG
62                                 "%s: deleting unreferenced inode %ld\n",
63 -                               __FUNCTION__, inode->i_ino);
64 +                               __func__, inode->i_ino);
65                         jbd_debug(2, "deleting unreferenced inode %ld\n",
66                                   inode->i_ino);
67                         nr_orphans++;
68 @@ -1525,6 +1529,346 @@ static unsigned long descriptor_loc(stru
69         return (first_data_block + has_super + (bg * sbi->s_blocks_per_group));
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, msg);
141 +       ext3_warning(sb, function, "MMP failure info: last update time: %llu, "
142 +                    "last update node: %s, last update device: %s\n",
143 +                    le64_to_cpu(mmp->mmp_time), mmp->mmp_nodename,
144 +                    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 super_block *) data;
153 +       struct ext3_super_block *es = EXT3_SB(sb)->s_es;
154 +       struct buffer_head *bh = NULL;
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 +       retval = read_mmp_block(sb, &bh, mmp_block);
167 +       if (retval)
168 +               goto failed;
169 +
170 +       mmp = (struct mmp_struct *)(bh->b_data);
171 +       mmp->mmp_time = cpu_to_le64(get_seconds());
172 +       /*
173 +        * Start with the higher mmp_check_interval and reduce it if
174 +        * the MMP block is being updated on time.
175 +        */
176 +       mmp_check_interval = max(5 * mmp_update_interval,
177 +                                EXT3_MMP_MIN_CHECK_INTERVAL);
178 +       mmp->mmp_check_interval = cpu_to_le16(mmp_check_interval);
179 +       bdevname(bh->b_bdev, mmp->mmp_bdevname);
180 +
181 +       down_read(&uts_sem);
182 +       memcpy(mmp->mmp_nodename, system_utsname.nodename,
183 +              sizeof(mmp->mmp_nodename));
184 +       up_read(&uts_sem);
185 +
186 +       while (!kthread_should_stop()) {
187 +               if (++seq > EXT3_MMP_SEQ_MAX)
188 +                       seq = 1;
189 +
190 +               mmp->mmp_seq = cpu_to_le32(seq);
191 +               mmp->mmp_time = cpu_to_le64(get_seconds());
192 +               last_update_time = jiffies;
193 +
194 +               retval = write_mmp_block(bh);
195 +               /*
196 +                * Don't spew too many error messages. Print one every
197 +                * (s_mmp_update_interval * 60) seconds.
198 +                */
199 +               if (retval && (failed_writes % 60) == 0) {
200 +                       ext3_error(sb, __func__,
201 +                                  "Error writing to MMP block");
202 +                       failed_writes++;
203 +               }
204 +
205 +               if (!(le32_to_cpu(es->s_feature_incompat) &
206 +                   EXT3_FEATURE_INCOMPAT_MMP)) {
207 +                       ext3_warning(sb, __func__, "kmmpd being stopped "
208 +                                    "since MMP feature has been disabled.");
209 +                       EXT3_SB(sb)->s_mmp_tsk = 0;
210 +                       goto failed;
211 +               }
212 +
213 +               if (sb->s_flags & MS_RDONLY) {
214 +                       ext3_warning(sb, __func__, "kmmpd being stopped "
215 +                                    "since filesystem has been remounted as "
216 +                                    "readonly.");
217 +                       EXT3_SB(sb)->s_mmp_tsk = 0;
218 +                       goto failed;
219 +               }
220 +
221 +               diff = jiffies - last_update_time;
222 +               if (diff < mmp_update_interval * HZ)
223 +                       schedule_timeout_interruptible(EXT3_MMP_UPDATE_INTERVAL*
224 +                                                      HZ - diff);
225 +
226 +               /*
227 +                * We need to make sure that more than mmp_check_interval
228 +                * seconds have not passed since writing. If that has happened
229 +                * we need to check if the MMP block is as we left it.
230 +                */
231 +               diff = jiffies - last_update_time;
232 +               if (diff > mmp_check_interval * HZ) {
233 +                       struct buffer_head *bh_check = NULL;
234 +                       struct mmp_struct *mmp_check;
235 +
236 +                       retval = read_mmp_block(sb, &bh_check, mmp_block);
237 +                       if (retval) {
238 +                               EXT3_SB(sb)->s_mmp_tsk = 0;
239 +                               goto failed;
240 +                       }
241 +
242 +                       mmp_check = (struct mmp_struct *)(bh_check->b_data);
243 +                       if (mmp->mmp_time != mmp_check->mmp_time ||
244 +                           memcmp(mmp->mmp_nodename, mmp_check->mmp_nodename,
245 +                                  sizeof(mmp->mmp_nodename)))
246 +                               dump_mmp_msg(sb, mmp_check, __func__,
247 +                                            "Error while updating MMP info. "
248 +                                            "The filesystem seems to have "
249 +                                            "been multiply mounted.");
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(5 * diff / HZ,
259 +                                (unsigned long) EXT3_MMP_MIN_CHECK_INTERVAL);
260 +               mmp->mmp_check_interval = cpu_to_le16(mmp_check_interval);
261 +       }
262 +
263 +       /*
264 +        * Unmount seems to be clean.
265 +        */
266 +       mmp->mmp_seq = cpu_to_le32(EXT3_MMP_SEQ_CLEAN);
267 +       mmp->mmp_time = cpu_to_le64(get_seconds());
268 +
269 +       retval = write_mmp_block(bh);
270 +
271 +failed:
272 +       brelse(bh);
273 +       return retval;
274 +}
275 +
276 +/*
277 + * Get a random new sequence number but make sure it is not greater than
278 + * EXT3_MMP_SEQ_MAX.
279 + */
280 +static unsigned int mmp_new_seq(void)
281 +{
282 +       u32 new_seq;
283 +
284 +       do {
285 +               get_random_bytes(&new_seq, sizeof(u32));
286 +       } while (new_seq > EXT3_MMP_SEQ_MAX);
287 +
288 +       return new_seq;
289 +}
290 +
291 +/*
292 + * Protect the filesystem from being mounted more than once.
293 + */
294 +static int ext3_multi_mount_protect(struct super_block *sb,
295 +                                   unsigned long mmp_block)
296 +{
297 +       struct ext3_super_block *es = EXT3_SB(sb)->s_es;
298 +       struct buffer_head *bh = NULL;
299 +       struct mmp_struct *mmp = NULL;
300 +       u32 seq;
301 +       unsigned int mmp_check_interval = le16_to_cpu(es->s_mmp_update_interval);
302 +       unsigned int wait_time = 0;
303 +       int retval;
304 +
305 +       if (mmp_block < le32_to_cpu(es->s_first_data_block) ||
306 +           mmp_block >= le32_to_cpu(es->s_blocks_count)) {
307 +               ext3_warning(sb, __func__,
308 +                            "Invalid MMP block in superblock");
309 +               goto failed;
310 +       }
311 +
312 +       retval = read_mmp_block(sb, &bh, mmp_block);
313 +       if (retval)
314 +               goto failed;
315 +
316 +       mmp = (struct mmp_struct *)(bh->b_data);
317 +
318 +       if (mmp_check_interval < EXT3_MMP_MIN_CHECK_INTERVAL)
319 +               mmp_check_interval = EXT3_MMP_MIN_CHECK_INTERVAL;
320 +
321 +       /*
322 +        * If check_interval in MMP block is larger, use that instead of
323 +        * update_interval from the superblock.
324 +        */
325 +       if (mmp->mmp_check_interval > mmp_check_interval)
326 +               mmp_check_interval = mmp->mmp_check_interval;
327 +
328 +       seq = le32_to_cpu(mmp->mmp_seq);
329 +       if (seq == EXT3_MMP_SEQ_CLEAN)
330 +               goto skip;
331 +
332 +       if (seq == EXT3_MMP_SEQ_FSCK) {
333 +               dump_mmp_msg(sb, mmp, __func__,
334 +                            "fsck is running on the filesystem");
335 +               goto failed;
336 +       }
337 +
338 +       wait_time = min(mmp_check_interval * 2 + 1,
339 +               mmp_check_interval + 60);
340 +
341 +       /* Print MMP interval if more than 20 secs. */
342 +       if (wait_time > EXT3_MMP_MIN_CHECK_INTERVAL * 4)
343 +               ext3_warning(sb, __func__, "MMP interval %u higher than "
344 +                            "expected, please wait.\n", wait_time * 2);
345 +
346 +       if (schedule_timeout_interruptible(HZ * wait_time) != 0) {
347 +               ext3_warning(sb, __func__, "MMP startup interrupted, failing "
348 +                            "mount\n");
349 +               goto failed;
350 +       }
351 +
352 +       retval = read_mmp_block(sb, &bh, mmp_block);
353 +       if (retval)
354 +               goto failed;
355 +       mmp = (struct mmp_struct *)(bh->b_data);
356 +       if (seq != le32_to_cpu(mmp->mmp_seq)) {
357 +               dump_mmp_msg(sb, mmp, __func__,
358 +                            "Device is already active on another node.");
359 +               goto failed;
360 +       }
361 +
362 +skip:
363 +       /*
364 +        * write a new random sequence number.
365 +        */
366 +       mmp->mmp_seq = seq = cpu_to_le32(mmp_new_seq());
367 +
368 +       retval = write_mmp_block(bh);
369 +       if (retval)
370 +               goto failed;
371 +
372 +       /*
373 +        * wait for MMP interval and check mmp_seq.
374 +        */
375 +       if (schedule_timeout_interruptible(HZ * wait_time) != 0) {
376 +               ext3_warning(sb, __func__, "MMP startup interrupted, failing "
377 +                            "mount\n");
378 +               goto failed;
379 +       }
380 +
381 +       retval = read_mmp_block(sb, &bh, mmp_block);
382 +       if (retval)
383 +               goto failed;
384 +       mmp = (struct mmp_struct *)(bh->b_data);
385 +       if (seq != le32_to_cpu(mmp->mmp_seq)) {
386 +               dump_mmp_msg(sb, mmp, __func__,
387 +                            "Device is already active on another node.");
388 +               goto failed;
389 +       }
390 +
391 +       /*
392 +        * Start a kernel thread to update the MMP block periodically.
393 +        */
394 +       EXT3_SB(sb)->s_mmp_tsk = kthread_run(kmmpd, sb, "kmmpd-%02x:%02x",
395 +                                            MAJOR(sb->s_dev),
396 +                                            MINOR(sb->s_dev));
397 +       if (IS_ERR(EXT3_SB(sb)->s_mmp_tsk)) {
398 +               EXT3_SB(sb)->s_mmp_tsk = 0;
399 +               ext3_warning(sb, __func__, "Unable to create kmmpd thread "
400 +                            "for %s.", sb->s_id);
401 +               goto failed;
402 +       }
403 +
404 +       brelse(bh);
405 +       return 0;
406 +
407 +failed:
408 +       brelse(bh);
409 +       return 1;
410 +}
411 +
412  
413  static int ext3_fill_super (struct super_block *sb, void *data, int silent)
414  {
415 @@ -1848,6 +2192,11 @@ static int ext3_fill_super (struct super
416                           EXT3_HAS_INCOMPAT_FEATURE(sb,
417                                     EXT3_FEATURE_INCOMPAT_RECOVER));
418  
419 +       if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_MMP) &&
420 +           !(sb->s_flags & MS_RDONLY))
421 +               if (ext3_multi_mount_protect(sb, le64_to_cpu(es->s_mmp_block)))
422 +                       goto failed_mount2;
423 +
424         /*
425          * The first inode we look at is the journal inode.  Don't try
426          * root first: it may be modified in the journal!
427 @@ -1992,6 +2341,8 @@ cantfind_ext3:
428  failed_mount3:
429         journal_destroy(sbi->s_journal);
430  failed_mount2:
431 +       if (sbi->s_mmp_tsk)
432 +               kthread_stop(sbi->s_mmp_tsk);
433         for (i = 0; i < db_count; i++)
434                 brelse(sbi->s_group_desc[i]);
435         kfree(sbi->s_group_desc);
436 @@ -2357,9 +2708,9 @@ static void ext3_clear_journal_err(struc
437                 char nbuf[16];
438  
439                 errstr = ext3_decode_error(sb, j_errno, nbuf);
440 -               ext3_warning(sb, __FUNCTION__, "Filesystem error recorded "
441 +               ext3_warning(sb, __func__, "Filesystem error recorded "
442                              "from previous mount: %s", errstr);
443 -               ext3_warning(sb, __FUNCTION__, "Marking fs in need of "
444 +               ext3_warning(sb, __func__, "Marking fs in need of "
445                              "filesystem check.");
446  
447                 EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS;
448 @@ -2462,7 +2813,7 @@ static int ext3_remount (struct super_bl
449         unsigned long n_blocks_count = 0;
450         unsigned long old_sb_flags;
451         struct ext3_mount_options old_opts;
452 -       int err;
453 +       int err = 0;
454  #ifdef CONFIG_QUOTA
455         int i;
456  #endif
457 @@ -2488,7 +2839,7 @@ static int ext3_remount (struct super_bl
458         }
459  
460         if (sbi->s_mount_opt & EXT3_MOUNT_ABORT)
461 -               ext3_abort(sb, __FUNCTION__, "Abort forced by user");
462 +               ext3_abort(sb, __func__, "Abort forced by user");
463  
464         sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
465                 ((sbi->s_mount_opt & EXT3_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
466 @@ -2546,6 +2897,13 @@ static int ext3_remount (struct super_bl
467                         }
468                         if (!ext3_setup_super (sb, es, 0))
469                                 sb->s_flags &= ~MS_RDONLY;
470 +                       if (EXT3_HAS_INCOMPAT_FEATURE(sb,
471 +                                                   EXT3_FEATURE_INCOMPAT_MMP))
472 +                               if (ext3_multi_mount_protect(sb,
473 +                                               le64_to_cpu(es->s_mmp_block))) {
474 +                                       err = -EROFS;
475 +                                       goto restore_opts;
476 +                               }
477                 }
478         }
479  #ifdef CONFIG_QUOTA
480 Index: linux-stage/include/linux/ext3_fs.h
481 ===================================================================
482 --- linux-stage.orig/include/linux/ext3_fs.h
483 +++ linux-stage/include/linux/ext3_fs.h
484 @@ -597,13 +597,17 @@ struct ext3_super_block {
485         __le32  s_first_meta_bg;        /* First metablock block group */
486         __le32  s_mkfs_time;            /* When the filesystem was created */
487         __le32  s_jnl_blocks[17];       /* Backup of the journal inode */
488 -       __le32  s_blocks_count_hi;      /* Blocks count high 32 bits */
489 +/*150*/ __le32 s_blocks_count_hi;      /* Blocks count high 32 bits */
490         __le32  s_r_blocks_count_hi;    /* Reserved blocks count high 32 bits*/
491         __le32  s_free_blocks_hi;       /* Free blocks count high 32 bits */
492         __le16  s_min_extra_isize;      /* All inodes have at least # bytes */
493         __le16  s_want_extra_isize;     /* New inodes should reserve # bytes */
494 -       __le32  s_flags;                /* Miscellaneous flags */
495 -       __u32   s_reserved[167];        /* Padding to the end of the block */
496 +/*160*/ __le32 s_flags;                /* Miscellaneous flags */
497 +       __le16  s_raid_stride;          /* RAID stride */
498 +       __le16  s_mmp_update_interval;  /* # seconds to wait in MMP checking */
499 +       __le64  s_mmp_block;            /* Block for multi-mount protection */
500 +/*170*/ __le32  s_raid_stripe_width;    /* blocks on all data disks (N*stride)*/
501 +       __le32  s_reserved[163];        /* Padding to the end of the block */
502  };
503  
504  #ifdef __KERNEL__
505 @@ -697,12 +701,14 @@ static inline int ext3_valid_inum(struct
506  #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV      0x0008 /* Journal device */
507  #define EXT3_FEATURE_INCOMPAT_META_BG          0x0010
508  #define EXT3_FEATURE_INCOMPAT_EXTENTS          0x0040 /* extents support */
509 +#define EXT3_FEATURE_INCOMPAT_MMP              0x0100
510  
511  #define EXT3_FEATURE_COMPAT_SUPP       EXT2_FEATURE_COMPAT_EXT_ATTR
512  #define EXT3_FEATURE_INCOMPAT_SUPP     (EXT3_FEATURE_INCOMPAT_FILETYPE| \
513                                          EXT3_FEATURE_INCOMPAT_RECOVER| \
514                                          EXT3_FEATURE_INCOMPAT_META_BG| \
515 -                                        EXT3_FEATURE_INCOMPAT_EXTENTS)
516 +                                        EXT3_FEATURE_INCOMPAT_EXTENTS| \
517 +                                        EXT3_FEATURE_INCOMPAT_MMP)
518  #define EXT3_FEATURE_RO_COMPAT_SUPP    (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
519                                          EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \
520                                          EXT4_FEATURE_RO_COMPAT_GDT_CSUM| \
521 @@ -862,6 +868,39 @@ struct dir_private_info {
522  #define ERR_BAD_DX_DIR -75000
523  
524  /*
525 + * This structure will be used for multiple mount protection. It will be
526 + * written into the block number saved in the s_mmp_block field in the
527 + * superblock. Programs that check MMP should assume that if
528 + * SEQ_FSCK (or any unknown code above SEQ_MAX) is present then it is NOT safe
529 + * to use the filesystem, regardless of how old the timestamp is.
530 + */
531 +#define EXT3_MMP_MAGIC     0x004D4D50U /* ASCII for MMP */
532 +#define EXT3_MMP_SEQ_CLEAN 0xFF4D4D50U /* mmp_seq value for clean unmount */
533 +#define EXT3_MMP_SEQ_FSCK  0xE24D4D50U /* mmp_seq value when being fscked */
534 +#define EXT3_MMP_SEQ_MAX   0xE24D4D4FU /* maximum valid mmp_seq value */
535 +
536 +struct mmp_struct {
537 +       __le32  mmp_magic;
538 +       __le32  mmp_seq;
539 +       __le64  mmp_time;
540 +       char    mmp_nodename[64];
541 +       char    mmp_bdevname[32];
542 +       __le16  mmp_check_interval;
543 +       __le16  mmp_pad1;
544 +       __le32  mmp_pad2[227];
545 +};
546 +
547 +/*
548 + * Default interval in seconds to update the MMP sequence number.
549 + */
550 +#define EXT3_MMP_UPDATE_INTERVAL   1
551 +
552 +/*
553 + * Minimum interval for MMP checking in seconds.
554 + */
555 +#define EXT3_MMP_MIN_CHECK_INTERVAL    5
556 +
557 +/*
558   * Function prototypes
559   */
560  
561 Index: linux-stage/include/linux/ext3_fs_sb.h
562 ===================================================================
563 --- linux-stage.orig/include/linux/ext3_fs_sb.h
564 +++ linux-stage/include/linux/ext3_fs_sb.h
565 @@ -145,6 +145,7 @@ struct ext3_sb_info {
566         /* locality groups */
567         struct ext3_locality_group *s_locality_groups;
568  
569 +       struct task_struct *s_mmp_tsk;  /* Kernel thread for multiple mount protection */
570  };
571  
572  #define EXT3_GROUP_INFO(sb, group)                                        \