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

📄 quota-umount-race-fix.patch

📁 非常经典的一个分布式系统
💻 PATCH
字号:
From: Jan Kara <jack@suse.cz>Fix possible races between umount and quota on/off.Finally I decided to take a reference to vfsmount during vfs_quota_on() andto drop it after the final cleanup in the vfs_quota_off().  This way weshould be all the time guarded against umount.  This way was protected alsothe old code which used filp_open() for opening quota files.  I was alsothinking about other ways of protection but there would be always a window(provided I don't want to play much with namespace locks) wherevfs_quota_on() could be called while umount() is in progress resulting inthe "Busy inodes after unmount" messages...Get a reference to vfsmount during quotaon() so that we are guarded againstumount (as was the old code using filp_open()).Signed-off-by: Jan Kara <jack@suse.cz>Signed-off-by: Andrew Morton <akpm@osdl.org>--- 25-akpm/fs/dquot.c               |   45 ++++++++++++++++++++++++++++----------- 25-akpm/include/linux/quota.h    |    1  25-akpm/include/linux/quotaops.h |    2 - 3 files changed, 35 insertions(+), 13 deletions(-)diff -puN fs/dquot.c~quota-umount-race-fix fs/dquot.c--- 25/fs/dquot.c~quota-umount-race-fix	Tue Nov 23 17:11:34 2004+++ 25-akpm/fs/dquot.c	Tue Nov 23 17:11:34 2004@@ -1314,12 +1314,14 @@ int vfs_quota_off(struct super_block *sb { 	int cnt; 	struct quota_info *dqopt = sb_dqopt(sb);-	struct inode *toput[MAXQUOTAS];+	struct inode *toputinode[MAXQUOTAS];+	struct vfsmount *toputmnt[MAXQUOTAS];  	/* We need to serialize quota_off() for device */ 	down(&dqopt->dqonoff_sem); 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {-		toput[cnt] = NULL;+		toputinode[cnt] = NULL;+		toputmnt[cnt] = NULL; 		if (type != -1 && cnt != type) 			continue; 		if (!sb_has_quota_enabled(sb, cnt))@@ -1339,8 +1341,10 @@ int vfs_quota_off(struct super_block *sb 			dqopt->ops[cnt]->free_file_info(sb, cnt); 		put_quota_format(dqopt->info[cnt].dqi_format); -		toput[cnt] = dqopt->files[cnt];+		toputinode[cnt] = dqopt->files[cnt];+		toputmnt[cnt] = dqopt->mnt[cnt]; 		dqopt->files[cnt] = NULL;+		dqopt->mnt[cnt] = NULL; 		dqopt->info[cnt].dqi_flags = 0; 		dqopt->info[cnt].dqi_igrace = 0; 		dqopt->info[cnt].dqi_bgrace = 0;@@ -1348,7 +1352,10 @@ int vfs_quota_off(struct super_block *sb 	} 	up(&dqopt->dqonoff_sem); 	/* Sync the superblock so that buffers with quota data are written to-         * disk (and so userspace sees correct data afterwards) */+	 * disk (and so userspace sees correct data afterwards).+	 * The reference to vfsmnt we are still holding protects us from+	 * umount (we don't have it only when quotas are turned on/off for+	 * journal replay but in that case we are guarded by the fs anyway). */ 	if (sb->s_op->sync_fs) 		sb->s_op->sync_fs(sb, 1); 	sync_blockdev(sb->s_bdev);@@ -1358,13 +1365,24 @@ int vfs_quota_off(struct super_block *sb	 * must also discard the blockdev buffers so that we see the	 * changes done by userspace on the next quotaon() */	for (cnt = 0; cnt < MAXQUOTAS; cnt++)-		if (toput[cnt]) {-			down(&toput[cnt]->i_sem);-			toput[cnt]->i_flags &= ~(S_IMMUTABLE | S_NOATIME | S_NOQUOTA);-			truncate_inode_pages(&toput[cnt]->i_data, 0);-			up(&toput[cnt]->i_sem);-			mark_inode_dirty(toput[cnt]);-			iput(toput[cnt]);+		if (toputinode[cnt]) {+			down(&dqopt->dqonoff_sem);+			/* If quota was reenabled in the meantime, we have+			 * nothing to do */+			if (!sb_has_quota_enabled(sb, cnt)) {+				down(&toputinode[cnt]->i_sem);+				toputinode[cnt]->i_flags &= ~(S_IMMUTABLE |+				  S_NOATIME | S_NOQUOTA);+				truncate_inode_pages(&toputinode[cnt]->i_data, 0);+				up(&toputinode[cnt]->i_sem);+				mark_inode_dirty(toputinode[cnt]);+				iput(toputinode[cnt]);+			}+			up(&dqopt->dqonoff_sem);+			/* We don't hold the reference when we turned on quotas+			 * just for the journal replay... */+			if (toputmnt[cnt])+				mntput(toputmnt[cnt]);		}	invalidate_bdev(sb->s_bdev, 0);	return 0;@@ -1478,8 +1496,11 @@ int vfs_quota_on(struct super_block *sb, 	/* Quota file not on the same filesystem? */ 	if (nd.mnt->mnt_sb != sb) 		error = -EXDEV;-	else+	else { 		error = vfs_quota_on_inode(nd.dentry->d_inode, type, format_id);+		if (!error)+			sb_dqopt(sb)->mnt[type] = mntget(nd.mnt);+	} out_path: 	path_release(&nd); 	return error;diff -puN include/linux/quota.h~quota-umount-race-fix include/linux/quota.h--- 25/include/linux/quota.h~quota-umount-race-fix	Tue Nov 23 17:11:34 2004+++ 25-akpm/include/linux/quota.h	Tue Nov 23 17:11:34 2004@@ -286,6 +286,7 @@ struct quota_info { 	struct semaphore dqonoff_sem;		/* Serialize quotaon & quotaoff */ 	struct rw_semaphore dqptr_sem;		/* serialize ops using quota_info struct, pointers from inode to dquots */ 	struct inode *files[MAXQUOTAS];		/* inodes of quotafiles */+	struct vfsmount *mnt[MAXQUOTAS];	/* mountpoint entries of filesystems with quota files */ 	struct mem_dqinfo info[MAXQUOTAS];	/* Information for each quota type */ 	struct quota_format_ops *ops[MAXQUOTAS];	/* Operations for each type */ };diff -puN include/linux/quotaops.h~quota-umount-race-fix include/linux/quotaops.h--- 25/include/linux/quotaops.h~quota-umount-race-fix	Tue Nov 23 17:11:34 2004+++ 25-akpm/include/linux/quotaops.h	Tue Nov 23 17:11:34 2004@@ -177,7 +177,7 @@ static __inline__ int DQUOT_OFF(struct s { 	int ret = -ENOSYS; -	if (sb->s_qcop && sb->s_qcop->quota_off)+	if (sb_any_quota_enabled(sb) && sb->s_qcop && sb->s_qcop->quota_off) 		ret = sb->s_qcop->quota_off(sb, -1); 	return ret; }_

⌨️ 快捷键说明

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