From 4b5651bae5be6a0315d525836281b54d643f88c0 Mon Sep 17 00:00:00 2001 From: yangsheng Date: Thu, 28 Nov 2013 02:31:52 +0800 Subject: [PATCH] LU-4285 kernel: fix uninitialized access of quota got[] array The pointer maybe uninitialized when dqput be called. Signed-off-by: yang sheng Change-Id: I94c138664c2f0a2404f2dafda25f3ee968a981fb Reviewed-on: http://review.whamcloud.com/8418 Tested-by: Jenkins Reviewed-by: Niu Yawei Reviewed-by: Bob Glossman Tested-by: Maloo Reviewed-by: James Simmons Reviewed-by: Oleg Drokin --- .../quota-avoid-dqget-calls-sles11sp2.patch | 31 +++++++++++++++++++--- .../patches/quota-avoid-dqget-calls.patch | 4 +++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/lustre/kernel_patches/patches/quota-avoid-dqget-calls-sles11sp2.patch b/lustre/kernel_patches/patches/quota-avoid-dqget-calls-sles11sp2.patch index cd39fe1..1e23116 100644 --- a/lustre/kernel_patches/patches/quota-avoid-dqget-calls-sles11sp2.patch +++ b/lustre/kernel_patches/patches/quota-avoid-dqget-calls-sles11sp2.patch @@ -1,14 +1,20 @@ +In dquot_initialize(), we'd call dqget() only when i_dquot not +initialized, which can avoid 2 pair of dqget()/dqput() in most +case. It could relieve the global locks contenion caused by +dqget()/dqput(). --- linux-3.0/fs/quota/dquot.c.orig 2013-07-18 09:46:28.000000000 -0400 +++ linux-3.0/fs/quota/dquot.c 2013-07-18 09:49:20.000000000 -0400 -@@ -1342,7 +1342,7 @@ +@@ -1342,8 +1342,8 @@ static void __dquot_initialize(struct inode *inode, int type) { unsigned int id = 0; - int cnt; +- struct dquot *got[MAXQUOTAS]; + int cnt, ret = 0, dq_get = 0; - struct dquot *got[MAXQUOTAS]; ++ struct dquot *got[MAXQUOTAS] = { NULL, NULL }; struct super_block *sb = inode->i_sb; qsize_t rsv; + @@ -1352,7 +1352,14 @@ if (!dquot_active(inode)) return; @@ -34,14 +40,21 @@ spin_lock(&inode->i_lock); if (IS_NOQUOTA(inode)) goto out_err; -@@ -1381,6 +1388,10 @@ - if (!got[cnt]) +@@ -1381,10 +1388,14 @@ + /* Avoid races with quotaoff() */ + if (!sb_has_quota_active(sb, cnt)) continue; +- /* We could race with quotaon or dqget() could have failed */ +- if (!got[cnt]) +- continue; if (!inode->i_dquot[cnt]) { + if (dq_get == 0) { + spin_unlock(&inode->i_lock); + goto get_dquots; + } ++ /* We could race with quotaon or dqget() could have failed */ ++ if (!got[cnt]) ++ continue; inode->i_dquot[cnt] = got[cnt]; got[cnt] = NULL; /* @@ -54,3 +67,13 @@ spin_lock(&dq_data_lock); dquot_resv_space(inode->i_dquot[cnt], rsv); spin_unlock(&dq_data_lock); +@@ -1488,7 +1399,8 @@ + spin_unlock(&inode->i_lock); + + /* Drop unused references */ +- dqput_all(got); ++ if (dq_get) ++ dqput_all(got); + } + + void dquot_initialize(struct inode *inode) diff --git a/lustre/kernel_patches/patches/quota-avoid-dqget-calls.patch b/lustre/kernel_patches/patches/quota-avoid-dqget-calls.patch index 83d0272..0a0c6cc 100644 --- a/lustre/kernel_patches/patches/quota-avoid-dqget-calls.patch +++ b/lustre/kernel_patches/patches/quota-avoid-dqget-calls.patch @@ -1,3 +1,7 @@ +In dquot_initialize(), we'd call dqget() only when i_dquot not +initialized, which can avoid 2 pair of dqget()/dqput() in most +case. It could relieve the global locks contenion caused by +dqget()/dqput(). Index: linux-2.6.32-358.0.1.el6/fs/quota/dquot.c =================================================================== --- linux-2.6.32-358.0.1.el6.orig/fs/quota/dquot.c -- 1.8.3.1