⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ext3-mmp-2.6-sles10.patch

📁 非常经典的一个分布式系统
💻 PATCH
字号:
Index: linux-2.6.16.46-0.14/fs/ext3/super.c===================================================================--- linux-2.6.16.46-0.14.orig/fs/ext3/super.c+++ linux-2.6.16.46-0.14/fs/ext3/super.c@@ -36,6 +36,8 @@ #include <linux/namei.h> #include <linux/quotaops.h> #include <linux/seq_file.h>+#include <linux/kthread.h>+#include <linux/utsname.h>  #include <asm/uaccess.h> @@ -436,6 +438,9 @@ static void ext3_put_super (struct super 		invalidate_bdev(sbi->journal_bdev, 0); 		ext3_blkdev_remove(sbi); 	}+	if (sbi->s_mmp_tsk)+		kthread_stop(sbi->s_mmp_tsk);+ 	sb->s_fs_info = NULL; 	kfree(sbi); 	return;@@ -1521,6 +1526,313 @@ static unsigned long descriptor_loc(stru 	return (first_data_block + has_super + (bg * sbi->s_blocks_per_group)); } +/*+ * Write the MMP block using WRITE_SYNC to try to get the block on-disk+ * faster.+ */+static int write_mmp_block(struct buffer_head *bh)+{+	mark_buffer_dirty(bh);+	lock_buffer(bh);+	bh->b_end_io = end_buffer_write_sync;+	get_bh(bh);+	submit_bh(WRITE_SYNC, bh);+	wait_on_buffer(bh);+	if (unlikely(!buffer_uptodate(bh)))+		return 1;++	return 0;+}++/*+ * Read the MMP block. It _must_ be read from disk and hence we clear the+ * uptodate flag on the buffer.+ */+static int read_mmp_block(struct super_block *sb, struct buffer_head **bh,+			  unsigned long mmp_block)+{+	struct mmp_struct *mmp;++	if (*bh)+		clear_buffer_uptodate(*bh);++	brelse(*bh);++	*bh = sb_bread(sb, mmp_block);+	if (!*bh) {+		ext3_warning(sb, __FUNCTION__,+			     "Error while reading MMP block %lu", mmp_block);+		return -EIO;+	}++	mmp = (struct mmp_struct *)((*bh)->b_data);+	if (le32_to_cpu(mmp->mmp_magic) != EXT3_MMP_MAGIC)+		return -EINVAL;++	return 0;+}++/*+ * Dump as much information as possible to help the admin.+ */+static void dump_mmp_msg(struct super_block *sb, struct mmp_struct *mmp,+			 const char *function, const char *msg)+{+	ext3_warning(sb, function, msg);+	ext3_warning(sb, function, "MMP failure info: last update time: %llu, "+		     "last update node: %s, last update device: %s\n",+		     le64_to_cpu(mmp->mmp_time), mmp->mmp_nodename,+		     mmp->mmp_bdevname);+}++/*+ * kmmpd will update the MMP sequence every s_mmp_update_interval seconds+ */+static int kmmpd(void *data)+{+	struct super_block *sb = (struct super_block *) data;+	struct ext3_super_block *es = EXT3_SB(sb)->s_es;+	struct buffer_head *bh = NULL;+	struct mmp_struct *mmp;+	unsigned long mmp_block;+	u32 seq = 0;+	unsigned long failed_writes = 0;+	int mmp_update_interval = le16_to_cpu(es->s_mmp_update_interval);+	unsigned mmp_check_interval;+	unsigned long last_update_time;+	unsigned long diff;+	int retval;++	mmp_block = le64_to_cpu(es->s_mmp_block);+	retval = read_mmp_block(sb, &bh, mmp_block);+	if (retval)+		goto failed;++	mmp = (struct mmp_struct *)(bh->b_data);+	mmp->mmp_time = cpu_to_le64(get_seconds());+	/*+	 * Start with the higher mmp_check_interval and reduce it if+	 * the MMP block is being updated on time.+	 */+	mmp_check_interval = max(5 * mmp_update_interval,+				 EXT3_MMP_MIN_CHECK_INTERVAL);+	mmp->mmp_check_interval = cpu_to_le16(mmp_check_interval);+	bdevname(bh->b_bdev, mmp->mmp_bdevname);++	down_read(&uts_sem);+	memcpy(mmp->mmp_nodename, system_utsname.nodename,+	       sizeof(mmp->mmp_nodename));+	up_read(&uts_sem);++	while (!kthread_should_stop()) {+		if (++seq > EXT3_MMP_SEQ_MAX)+			seq = 1;++		mmp->mmp_seq = cpu_to_le32(seq);+		mmp->mmp_time = cpu_to_le64(get_seconds());+		last_update_time = jiffies;++		retval = write_mmp_block(bh);+		/*+		 * Don't spew too many error messages. Print one every+		 * (s_mmp_update_interval * 60) seconds.+		 */+		if (retval && (failed_writes % 60) == 0) {+			ext3_error(sb, __FUNCTION__,+				   "Error writing to MMP block");+			failed_writes++;+		}++		if (!(le32_to_cpu(es->s_feature_incompat) &+		    EXT3_FEATURE_INCOMPAT_MMP)) {+			ext3_warning(sb, __FUNCTION__, "kmmpd being stopped "+				     "since MMP feature has been disabled.");+			EXT3_SB(sb)->s_mmp_tsk = 0;+			goto failed;+		}++		if (sb->s_flags & MS_RDONLY) {+			ext3_warning(sb, __FUNCTION__, "kmmpd being stopped "+				     "since filesystem has been remounted as "+				     "readonly.");+			EXT3_SB(sb)->s_mmp_tsk = 0;+			goto failed;+		}++		diff = jiffies - last_update_time;+		if (diff < mmp_update_interval * HZ)+			schedule_timeout_interruptible(EXT3_MMP_UPDATE_INTERVAL*+						       HZ - diff);++		/*+		 * We need to make sure that more than mmp_check_interval+		 * seconds have not passed since writing. If that has happened+		 * we need to check if the MMP block is as we left it.+		 */+		diff = jiffies - last_update_time;+		if (diff > mmp_check_interval * HZ) {+			struct buffer_head *bh_check = NULL;+			struct mmp_struct *mmp_check;++			retval = read_mmp_block(sb, &bh_check, mmp_block);+			if (retval) {+				EXT3_SB(sb)->s_mmp_tsk = 0;+				goto failed;+			}++			mmp_check = (struct mmp_struct *)(bh_check->b_data);+			if (mmp->mmp_time != mmp_check->mmp_time ||+			    memcmp(mmp->mmp_nodename, mmp_check->mmp_nodename,+				   sizeof(mmp->mmp_nodename)))+				dump_mmp_msg(sb, mmp_check, __FUNCTION__,+					     "Error while updating MMP info. "+					     "The filesystem seems to have "+					     "been multiply mounted.");++			put_bh(bh_check);+		}++		/*+		 * Adjust the mmp_check_interval depending on how much time+		 * it took for the MMP block to be written.+		 */+		mmp_check_interval = max(5 * diff / HZ,+				 (unsigned long) EXT3_MMP_MIN_CHECK_INTERVAL);+		mmp->mmp_check_interval = cpu_to_le16(mmp_check_interval);+	}++	/*+	 * Unmount seems to be clean.+	 */+	mmp->mmp_seq = cpu_to_le32(EXT3_MMP_SEQ_CLEAN);+	mmp->mmp_time = cpu_to_le64(get_seconds());++	retval = write_mmp_block(bh);++failed:+	brelse(bh);+	return retval;+}++/*+ * Get a random new sequence number but make sure it is not greater than+ * EXT3_MMP_SEQ_MAX.+ */+static unsigned int mmp_new_seq(void)+{+	u32 new_seq;++	do {+		get_random_bytes(&new_seq, sizeof(u32));+	} while (new_seq > EXT3_MMP_SEQ_MAX);++	return new_seq;+}++/*+ * Protect the filesystem from being mounted more than once.+ */+static int ext3_multi_mount_protect(struct super_block *sb,+				    unsigned long mmp_block)+{+	struct ext3_super_block *es = EXT3_SB(sb)->s_es;+	struct buffer_head *bh = NULL;+	struct mmp_struct *mmp = NULL;+	u32 seq;+	unsigned int mmp_check_interval = le16_to_cpu(es->s_mmp_update_interval);+	int retval;++	if (mmp_block < le32_to_cpu(es->s_first_data_block) ||+	    mmp_block >= le32_to_cpu(es->s_blocks_count)) {+		ext3_warning(sb, __FUNCTION__,+			     "Invalid MMP block in superblock");+		goto failed;+	}++	retval = read_mmp_block(sb, &bh, mmp_block);+	if (retval)+		goto failed;++	mmp = (struct mmp_struct *)(bh->b_data);++	if (mmp_check_interval < EXT3_MMP_MIN_CHECK_INTERVAL)+		mmp_check_interval = EXT3_MMP_MIN_CHECK_INTERVAL;++	/*+	 * If check_interval in MMP block is larger, use that instead of+	 * update_interval from the superblock.+	 */+	if (mmp->mmp_check_interval > mmp_check_interval)+		mmp_check_interval = mmp->mmp_check_interval;++	seq = le32_to_cpu(mmp->mmp_seq);+	if (seq == EXT3_MMP_SEQ_CLEAN)+		goto skip;++	if (seq == EXT3_MMP_SEQ_FSCK) {+		dump_mmp_msg(sb, mmp, __FUNCTION__,+			     "fsck is running on the filesystem");+		goto failed;+	}++	schedule_timeout_uninterruptible(HZ * (2 * mmp_check_interval + 1));++	retval = read_mmp_block(sb, &bh, mmp_block);+	if (retval)+		goto failed;+	mmp = (struct mmp_struct *)(bh->b_data);+	if (seq != le32_to_cpu(mmp->mmp_seq)) {+		dump_mmp_msg(sb, mmp, __FUNCTION__,+			     "Device is already active on another node.");+		goto failed;+	}++skip:+	/*+	 * write a new random sequence number.+	 */+	mmp->mmp_seq = seq = cpu_to_le32(mmp_new_seq());++	retval = write_mmp_block(bh);+	if (retval)+		goto failed;++	/*+	 * wait for MMP interval and check mmp_seq.+	 */+	schedule_timeout_uninterruptible(HZ * (2 * mmp_check_interval + 1));++	retval = read_mmp_block(sb, &bh, mmp_block);+	if (retval)+		goto failed;+	mmp = (struct mmp_struct *)(bh->b_data);+	if (seq != le32_to_cpu(mmp->mmp_seq)) {+		dump_mmp_msg(sb, mmp, __FUNCTION__,+			     "Device is already active on another node.");+		goto failed;+	}++	/*+	 * Start a kernel thread to update the MMP block periodically.+	 */+	EXT3_SB(sb)->s_mmp_tsk = kthread_run(kmmpd, sb, "kmmpd-%02x:%02x",+					     MAJOR(sb->s_dev),+					     MINOR(sb->s_dev));+	if (IS_ERR(EXT3_SB(sb)->s_mmp_tsk)) {+		EXT3_SB(sb)->s_mmp_tsk = 0;+		ext3_warning(sb, __FUNCTION__, "Unable to create kmmpd thread "+			     "for %s.", sb->s_id);+		goto failed;+	}++	brelse(bh);+	return 0;++failed:+	brelse(bh);+	return 1;+}+  static int ext3_fill_super (struct super_block *sb, void *data, int silent) {@@ -1828,6 +2140,11 @@ static int ext3_fill_super (struct super 			  EXT3_HAS_INCOMPAT_FEATURE(sb, 				    EXT3_FEATURE_INCOMPAT_RECOVER)); +	if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_MMP) &&+	    !(sb->s_flags & MS_RDONLY))+		if (ext3_multi_mount_protect(sb, le64_to_cpu(es->s_mmp_block)))+			goto failed_mount3;+ 	/* 	 * The first inode we look at is the journal inode.  Don't try 	 * root first: it may be modified in the journal!@@ -2438,7 +2755,7 @@ static int ext3_remount (struct super_bl 	unsigned long n_blocks_count = 0; 	unsigned long old_sb_flags; 	struct ext3_mount_options old_opts;-	int err;+	int err = 0; #ifdef CONFIG_QUOTA 	int i; #endif@@ -2522,6 +2839,11 @@ static int ext3_remount (struct super_bl 			} 			if (!ext3_setup_super (sb, es, 0)) 				sb->s_flags &= ~MS_RDONLY;+			if (EXT3_HAS_INCOMPAT_FEATURE(sb,+						    EXT3_FEATURE_INCOMPAT_MMP))+				if (ext3_multi_mount_protect(sb,+						le64_to_cpu(es->s_mmp_block)))+					goto restore_opts; 		} 	} #ifdef CONFIG_QUOTAIndex: linux-2.6.16.46-0.14/include/linux/ext3_fs.h===================================================================--- linux-2.6.16.46-0.14.orig/include/linux/ext3_fs.h+++ linux-2.6.16.46-0.14/include/linux/ext3_fs.h@@ -599,13 +599,17 @@ struct ext3_super_block { 	__le32	s_first_meta_bg;	/* First metablock block group */ 	__le32	s_mkfs_time;		/* When the filesystem was created */ 	__le32	s_jnl_blocks[17];	/* Backup of the journal inode */-	__le32	s_blocks_count_hi;	/* Blocks count high 32 bits */+/*150*/ __le32	s_blocks_count_hi;	/* Blocks count high 32 bits */ 	__le32	s_r_blocks_count_hi;	/* Reserved blocks count high 32 bits*/ 	__le32	s_free_blocks_hi;	/* Free blocks count high 32 bits */ 	__le16	s_min_extra_isize;	/* All inodes have at least # bytes */ 	__le16	s_want_extra_isize;	/* New inodes should reserve # bytes */-	__le32	s_flags;		/* Miscellaneous flags */-	__u32	s_reserved[167];	/* Padding to the end of the block */+/*160*/ __le32	s_flags;		/* Miscellaneous flags */+	__le16  s_raid_stride;		/* RAID stride */+	__le16  s_mmp_update_interval;  /* # seconds to wait in MMP checking */+	__le64  s_mmp_block;		/* Block for multi-mount protection */+/*170*/ __le32  s_raid_stripe_width;    /* blocks on all data disks (N*stride)*/+	__le32  s_reserved[163];	/* Padding to the end of the block */ };  #ifdef __KERNEL__@@ -699,12 +703,14 @@ static inline int ext3_valid_inum(struct #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV	0x0008 /* Journal device */ #define EXT3_FEATURE_INCOMPAT_META_BG		0x0010 #define EXT3_FEATURE_INCOMPAT_EXTENTS		0x0040 /* extents support */+#define EXT3_FEATURE_INCOMPAT_MMP		0x0100  #define EXT3_FEATURE_COMPAT_SUPP	EXT2_FEATURE_COMPAT_EXT_ATTR #define EXT3_FEATURE_INCOMPAT_SUPP	(EXT3_FEATURE_INCOMPAT_FILETYPE| \ 					 EXT3_FEATURE_INCOMPAT_RECOVER| \ 					 EXT3_FEATURE_INCOMPAT_META_BG| \-					 EXT3_FEATURE_INCOMPAT_EXTENTS)+					 EXT3_FEATURE_INCOMPAT_EXTENTS| \+					 EXT3_FEATURE_INCOMPAT_MMP) #define EXT3_FEATURE_RO_COMPAT_SUPP	(EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \ 					 EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \ 					 EXT4_FEATURE_RO_COMPAT_GDT_CSUM| \@@ -864,6 +870,39 @@ struct dir_private_info { #define ERR_BAD_DX_DIR	-75000  /*+ * 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 EXT3_MMP_MAGIC     0x004D4D50U /* ASCII for MMP */+#define EXT3_MMP_SEQ_CLEAN 0xFF4D4D50U /* mmp_seq value for clean unmount */+#define EXT3_MMP_SEQ_FSCK  0xE24D4D50U /* mmp_seq value when being fscked */+#define EXT3_MMP_SEQ_MAX   0xE24D4D4FU /* maximum valid mmp_seq value */++struct mmp_struct {+	__le32	mmp_magic;+	__le32	mmp_seq;+	__le64	mmp_time;+	char	mmp_nodename[64];+	char	mmp_bdevname[32];+	__le16	mmp_check_interval;+	__le16	mmp_pad1;+	__le32	mmp_pad2[227];+};++/*+ * Default interval in seconds to update the MMP sequence number.+ */+#define EXT3_MMP_UPDATE_INTERVAL   1++/*+ * Minimum interval for MMP checking in seconds.+ */+#define EXT3_MMP_MIN_CHECK_INTERVAL	5++/*  * Function prototypes  */ Index: linux-2.6.16.46-0.14/include/linux/ext3_fs_sb.h===================================================================--- linux-2.6.16.46-0.14.orig/include/linux/ext3_fs_sb.h+++ linux-2.6.16.46-0.14/include/linux/ext3_fs_sb.h@@ -140,6 +140,7 @@ struct ext3_sb_info { 	/* locality groups */ 	struct ext3_locality_group *s_locality_groups; +	struct task_struct *s_mmp_tsk;	/* Kernel thread for multiple mount protection */ };  #define EXT3_GROUP_INFO(sb, group)					   \

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -