Whamcloud - gitweb
LU-4285 kernel: fix uninitialized access of quota got[] array 18/8418/5
authoryangsheng <yang.sheng@intel.com>
Wed, 27 Nov 2013 18:31:52 +0000 (02:31 +0800)
committerOleg Drokin <oleg.drokin@intel.com>
Fri, 6 Dec 2013 06:42:15 +0000 (06:42 +0000)
The pointer maybe uninitialized when dqput be called.

Signed-off-by: yang sheng <yang.sheng@intel.com>
Change-Id: I94c138664c2f0a2404f2dafda25f3ee968a981fb
Reviewed-on: http://review.whamcloud.com/8418
Tested-by: Jenkins
Reviewed-by: Niu Yawei <yawei.niu@intel.com>
Reviewed-by: Bob Glossman <bob.glossman@intel.com>
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: James Simmons <uja.ornl@gmail.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/kernel_patches/patches/quota-avoid-dqget-calls-sles11sp2.patch
lustre/kernel_patches/patches/quota-avoid-dqget-calls.patch

index cd39fe1..1e23116 100644 (file)
@@ -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;
        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;
                        /*
                                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)
index 83d0272..0a0c6cc 100644 (file)
@@ -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