+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)
+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