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

📄 quota-deadlock-on-pagelock-ext3.patch

📁 非常经典的一个分布式系统
💻 PATCH
字号:
Index: linux-2.6.9/fs/ext3/inode.c===================================================================--- linux-2.6.9.orig/fs/ext3/inode.c	2006-08-25 16:39:10.000000000 +0800+++ linux-2.6.9/fs/ext3/inode.c	2006-09-14 11:44:29.000000000 +0800@@ -1028,7 +1028,7 @@ 	return ret; } -static int+int ext3_journal_dirty_data(handle_t *handle, struct buffer_head *bh) { 	int err = journal_dirty_data(handle, bh);Index: linux-2.6.9/fs/ext3/super.c===================================================================--- linux-2.6.9.orig/fs/ext3/super.c	2006-08-25 16:39:48.000000000 +0800+++ linux-2.6.9/fs/ext3/super.c	2006-09-14 11:51:48.000000000 +0800@@ -529,7 +529,10 @@ static int ext3_write_info(struct super_block *sb, int type); static int ext3_quota_on(struct super_block *sb, int type, int format_id, char *path); static int ext3_quota_on_mount(struct super_block *sb, int type);-static int ext3_quota_off_mount(struct super_block *sb, int type);+static ssize_t ext3_quota_read(struct super_block *sb, int type, char *data,+			       size_t len, loff_t off);+static ssize_t ext3_quota_write(struct super_block *sb, int type,+				const char *data, size_t len, loff_t off);  static struct dquot_operations ext3_quota_operations = { 	.initialize	= ext3_dquot_initialize,@@ -572,6 +575,10 @@ 	.statfs		= ext3_statfs, 	.remount_fs	= ext3_remount, 	.clear_inode	= ext3_clear_inode,+#ifdef CONFIG_QUOTA+	.quota_read	= ext3_quota_read,+	.quota_write	= ext3_quota_write,+#endif };  static struct dentry *ext3_get_dentry(struct super_block *sb, void *vobjp)@@ -713,6 +720,7 @@ 	int option; #ifdef CONFIG_QUOTA 	int qtype;+	char *qname; #endif  	if (!options)@@ -891,19 +899,22 @@ 					"quota options when quota turned on.\n"); 				return 0; 			}-			if (sbi->s_qf_names[qtype]) {+			qname = match_strdup(&args[0]);+			if (!qname) { 				printk(KERN_ERR-					"EXT3-fs: %s quota file already "-					"specified.\n", QTYPE2NAME(qtype));+					"EXT3-fs: not enough memory for "+					"storing quotafile name.\n"); 				return 0; 			}-			sbi->s_qf_names[qtype] = match_strdup(&args[0]);-			if (!sbi->s_qf_names[qtype]) {+			if (sbi->s_qf_names[qtype] &&+			    strcmp(sbi->s_qf_names[qtype], qname)) { 				printk(KERN_ERR-					"EXT3-fs: not enough memory for "-					"storing quotafile name.\n");+					"EXT3-fs: %s quota file already "+					"specified.\n", QTYPE2NAME(qtype));+				kfree(qname); 				return 0; 			}+			sbi->s_qf_names[qtype] = qname; 			if (strchr(sbi->s_qf_names[qtype], '/')) { 				printk(KERN_ERR 					"EXT3-fs: quotafile must be on "@@ -1223,7 +1234,7 @@ 	/* Turn quotas off */ 	for (i = 0; i < MAXQUOTAS; i++) { 		if (sb_dqopt(sb)->files[i])-			ext3_quota_off_mount(sb, i);+			vfs_quota_off(sb, i); 	} #endif 	sb->s_flags = s_flags; /* Restore MS_RDONLY status */@@ -2240,7 +2251,7 @@  static inline struct inode *dquot_to_inode(struct dquot *dquot) {-	return sb_dqopt(dquot->dq_sb)->files[dquot->dq_type]->f_dentry->d_inode;+	return sb_dqopt(dquot->dq_sb)->files[dquot->dq_type]; }  static int ext3_dquot_initialize(struct inode *inode, int type)@@ -2279,8 +2290,10 @@ { 	int ret, err; 	handle_t *handle;+	struct inode *inode; -	handle = ext3_journal_start(dquot_to_inode(dquot),+	inode = dquot_to_inode(dquot);+	handle = ext3_journal_start(inode, 					EXT3_QUOTA_TRANS_BLOCKS); 	if (IS_ERR(handle)) 		return PTR_ERR(handle);@@ -2367,22 +2380,9 @@ 	if (IS_ERR(dentry)) 		return PTR_ERR(dentry); 	err = vfs_quota_on_mount(type, EXT3_SB(sb)->s_jquota_fmt, dentry);-	if (err)-		dput(dentry);-	/* We keep the dentry reference if everything went ok - we drop it-	 * on quota_off time */-	return err;-}--/* Turn quotas off during mount time */-static int ext3_quota_off_mount(struct super_block *sb, int type)-{-	int err;-	struct dentry *dentry;--	dentry = sb_dqopt(sb)->files[type]->f_dentry;-	err = vfs_quota_off_mount(sb, type);-	/* We invalidate dentry - it has at least wrong hash... */+	/* Now invalidate and put the dentry - quota got its own reference+	 * to inode and dentry has at least wrong hash so we had better+	 * throw it away */ 	d_invalidate(dentry); 	dput(dentry); 	return err;@@ -2405,20 +2405,121 @@ 	if (err) 		return err; 	/* Quotafile not on the same filesystem? */-	if (nd.mnt->mnt_sb != sb)+	if (nd.mnt->mnt_sb != sb) {+		path_release(&nd); 		return -EXDEV;+	} 	/* Quotafile not of fs root? */ 	if (nd.dentry->d_parent->d_inode != sb->s_root->d_inode) 		printk(KERN_WARNING 			"EXT3-fs: Quota file not on filesystem root. " 			"Journalled quota will not work.\n");-	if (!ext3_should_journal_data(nd.dentry->d_inode))-		printk(KERN_WARNING "EXT3-fs: Quota file does not have "-			"data-journalling. Journalled quota will not work.\n"); 	path_release(&nd); 	return vfs_quota_on(sb, type, format_id, path); } +/* Read data from quotafile - avoid pagecache and such because we cannot afford+ * acquiring the locks... As quota files are never truncated and quota code+ * itself serializes the operations (and noone else should touch the files)+ * we don't have to be afraid of races */+static ssize_t ext3_quota_read(struct super_block *sb, int type, char *data,+			       size_t len, loff_t off)+{+	struct inode *inode = sb_dqopt(sb)->files[type];+	sector_t blk = off >> EXT3_BLOCK_SIZE_BITS(sb);+	int err = 0;+	int offset = off & (sb->s_blocksize - 1);+	int tocopy;+	size_t toread;+	struct buffer_head *bh;+	loff_t i_size = i_size_read(inode);++	if (off > i_size)+		return 0;+	if (off+len > i_size)+		len = i_size-off;+	toread = len;+	while (toread > 0) {+		tocopy = sb->s_blocksize - offset < toread ?+				sb->s_blocksize - offset : toread;+		bh = ext3_bread(NULL, inode, blk, 0, &err);+		if (err)+			return err;+		if (!bh)	/* A hole? */+			memset(data, 0, tocopy);+		else+			memcpy(data, bh->b_data+offset, tocopy);+		brelse(bh);+		offset = 0;+		toread -= tocopy;+		data += tocopy;+		blk++;+	}+	return len;+}++/* Write to quotafile (we know the transaction is already started and has+ * enough credits) */+static ssize_t ext3_quota_write(struct super_block *sb, int type,+				const char *data, size_t len, loff_t off)+{+	struct inode *inode = sb_dqopt(sb)->files[type];+	sector_t blk = off >> EXT3_BLOCK_SIZE_BITS(sb);+	int err = 0;+	int offset = off & (sb->s_blocksize - 1);+	int tocopy;+	int journal_quota = EXT3_SB(sb)->s_qf_names[type] != NULL;+	size_t towrite = len;+	struct buffer_head *bh;+	handle_t *handle = journal_current_handle();++	down(&inode->i_sem);+	while (towrite > 0) {+		tocopy = sb->s_blocksize - offset < towrite ?+				sb->s_blocksize - offset : towrite;+		bh = ext3_bread(handle, inode, blk, 1, &err);+		if (!bh)+			goto out;+		if (journal_quota) {+			err = ext3_journal_get_write_access(handle, bh);+			if (err) {+				brelse(bh);+				goto out;+			}+		}+		lock_buffer(bh);+		memcpy(bh->b_data+offset, data, tocopy);+		flush_dcache_page(bh->b_page);+		unlock_buffer(bh);+		if (journal_quota)+			err = ext3_journal_dirty_metadata(handle, bh);+		else {+			/* Always do at least ordered writes for quotas */+			err = ext3_journal_dirty_data(handle, bh);+			mark_buffer_dirty(bh);+		}+		brelse(bh);+		if (err)+			goto out;+		offset = 0;+		towrite -= tocopy;+		data += tocopy;+		blk++;+	}+out:+	if (len == towrite)+		return err;+	if (inode->i_size < off+len-towrite) {+		i_size_write(inode, off+len-towrite);+		EXT3_I(inode)->i_disksize = inode->i_size;+	}+	inode->i_version++;+	inode->i_mtime = inode->i_ctime = CURRENT_TIME;+	ext3_mark_inode_dirty(handle, inode);+	up(&inode->i_sem);+	return len - towrite;+}+ #endif  static struct super_block *ext3_get_sb(struct file_system_type *fs_type,Index: linux-2.6.9/include/linux/ext3_jbd.h===================================================================--- linux-2.6.9.orig/include/linux/ext3_jbd.h	2006-08-25 16:39:09.000000000 +0800+++ linux-2.6.9/include/linux/ext3_jbd.h	2006-09-14 11:44:29.000000000 +0800@@ -193,6 +193,8 @@ #define ext3_journal_forget(handle, bh) \ 	__ext3_journal_forget(__FUNCTION__, (handle), (bh)) +int ext3_journal_dirty_data(handle_t *handle, struct buffer_head *bh);+ handle_t *ext3_journal_start_sb(struct super_block *sb, int nblocks); int __ext3_journal_stop(const char *where, handle_t *handle); 

⌨️ 快捷键说明

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