Whamcloud - gitweb
LU-4285 kernel: fix uninitialized access of quota got[] array
[fs/lustre-release.git] / lustre / kernel_patches / patches / quota-avoid-dqget-calls-sles11sp2.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
 --- 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;
  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;
 +      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;
        struct super_block *sb = inode->i_sb;
        qsize_t rsv;
 @@ -1352,7 +1352,14 @@
        if (!dquot_active(inode))
                return;
 @@ -1352,7 +1352,14 @@
        if (!dquot_active(inode))
                return;
        spin_lock(&inode->i_lock);
        if (IS_NOQUOTA(inode))
                goto out_err;
        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;
                        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;
 +                      }
                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;
                        /*
                        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);
                                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)