+ ext4-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
+ ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \
+- ext4_jbd2.o migrate.o mballoc.o block_validity.o move_extent.o
++ ext4_jbd2.o migrate.o mballoc.o block_validity.o move_extent.o \
++ mmp.o
+
+ ext4-$(CONFIG_EXT4_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o
+ ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o
+Index: linux-stage/fs/ext4/ext4.h
+===================================================================
+--- linux-stage.orig/fs/ext4/ext4.h
++++ linux-stage/fs/ext4/ext4.h
+@@ -878,7 +878,7 @@ struct ext4_super_block {
+ __le16 s_want_extra_isize; /* New inodes should reserve # bytes */
+ __le32 s_flags; /* Miscellaneous flags */
+ __le16 s_raid_stride; /* RAID stride */
+- __le16 s_mmp_interval; /* # seconds to wait in MMP checking */
++ __le16 s_mmp_update_interval; /* # seconds to wait in MMP checking */
+ __le64 s_mmp_block; /* Block for multi-mount protection */
+ __le32 s_raid_stripe_width; /* blocks on all data disks (N*stride)*/
+ __u8 s_log_groups_per_flex; /* FLEX_BG group size */
+@@ -1032,6 +1032,9 @@ struct ext4_sb_info {
+
+ /* workqueue for dio unwritten */
+ struct workqueue_struct *dio_unwritten_wq;
++
++ /* Kernel thread for multiple mount protection */
++ struct task_struct *s_mmp_tsk;
+ };
+
+ static inline struct ext4_sb_info *EXT4_SB(struct super_block *sb)
+@@ -1169,7 +1172,8 @@ static inline void ext4_clear_inode_stat
+ EXT4_FEATURE_INCOMPAT_META_BG| \
+ EXT4_FEATURE_INCOMPAT_EXTENTS| \
+ EXT4_FEATURE_INCOMPAT_64BIT| \
+- EXT4_FEATURE_INCOMPAT_FLEX_BG)
++ EXT4_FEATURE_INCOMPAT_FLEX_BG| \
++ EXT4_FEATURE_INCOMPAT_MMP)
+ #define EXT4_FEATURE_RO_COMPAT_SUPP (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \
+ EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM| \
+@@ -1376,6 +1380,67 @@ void ext4_get_group_no_and_offset(struct
+ extern struct proc_dir_entry *ext4_proc_root;
+
+ /*
++ * This structure will be used for multiple mount protection. It will be
++ * written into the block number saved in the s_mmp_block field in the
++ * superblock. Programs that check MMP should assume that if
++ * SEQ_FSCK (or any unknown code above SEQ_MAX) is present then it is NOT safe
++ * to use the filesystem, regardless of how old the timestamp is.
++ */
++#define EXT4_MMP_MAGIC 0x004D4D50U /* ASCII for MMP */
++#define EXT4_MMP_SEQ_CLEAN 0xFF4D4D50U /* mmp_seq value for clean unmount */
++#define EXT4_MMP_SEQ_FSCK 0xE24D4D50U /* mmp_seq value when being fscked */
++#define EXT4_MMP_SEQ_MAX 0xE24D4D4FU /* maximum valid mmp_seq value */
++
++struct mmp_struct {
++ __le32 mmp_magic; /* Magic number for MMP */
++ __le32 mmp_seq; /* Sequence no. updated periodically */
++
++ /*
++ * mmp_time, mmp_nodename & mmp_bdevname are only used for information
++ * purposes and do not affect the correctness of the algorithm
++ */
++ __le64 mmp_time; /* Time last updated */
++ char mmp_nodename[64]; /* Node which last updated MMP block */
++ char mmp_bdevname[32]; /* Bdev which last updated MMP block */
++
++ /*
++ * mmp_check_interval is used to verify if the MMP block has been
++ * updated on the block device. The value is updated based on the
++ * maximum time to write the MMP block during an update cycle.
++ */
++ __le16 mmp_check_interval;
++
++ __le16 mmp_pad1;
++ __le32 mmp_pad2[227];
++};
++
++/* arguments passed to the mmp thread */
++struct mmpd_data {
++ struct buffer_head *bh; /* bh from initial read_mmp_block() */
++ struct super_block *sb; /* super block of the fs */
++};
++
++/*
++ * Check interval multiplier
++ * The MMP block is written every update interval and initially checked every
++ * update interval x the multiplier (the value is then adapted based on the
++ * write latency). The reason is that writes can be delayed under load and we
++ * don't want readers to incorrectly assume that the filesystem is no longer
++ * in use.
++ */
++#define EXT4_MMP_CHECK_MULT 2UL
++
++/*
++ * Minimum interval for MMP checking in seconds.
++ */
++#define EXT4_MMP_MIN_CHECK_INTERVAL 5UL
++
++/*
++ * Maximum interval for MMP checking in seconds.
++ */
++#define EXT4_MMP_MAX_CHECK_INTERVAL 300UL
++
++/*
+ * Function prototypes
+ */
+
+@@ -1547,6 +1612,10 @@ extern void __ext4_warning(struct super_
+ #define ext4_warning(sb, message...) __ext4_warning(sb, __func__, ## message)
+ extern void ext4_msg(struct super_block *, const char *, const char *, ...)
+ __attribute__ ((format (printf, 3, 4)));
++extern void __dump_mmp_msg(struct super_block *, struct mmp_struct *mmp,
++ const char *, const char *);
++#define dump_mmp_msg(sb, mmp, msg) __dump_mmp_msg(sb, mmp, __func__, msg)
++
+ extern void ext4_grp_locked_error(struct super_block *, ext4_group_t,
+ const char *, const char *, ...)
+ __attribute__ ((format (printf, 4, 5)));
+@@ -1784,6 +1853,9 @@ static inline void ext4_unlock_group(str
+ spin_unlock(ext4_group_lock_ptr(sb, group));