1 In dquot_initialize(), we'd call dqget() only when i_dquot not
2 initialized, which can avoid 2 pair of dqget()/dqput() in most
3 case. It could relieve the global locks contenion caused by
5 --- linux-3.0/fs/quota/dquot.c.orig 2013-07-18 09:46:28.000000000 -0400
6 +++ linux-3.0/fs/quota/dquot.c 2013-07-18 09:49:20.000000000 -0400
8 static void __dquot_initialize(struct inode *inode, int type)
12 - struct dquot *got[MAXQUOTAS];
13 + int cnt, ret = 0, dq_get = 0;
14 + struct dquot *got[MAXQUOTAS] = { NULL, NULL };
15 struct super_block *sb = inode->i_sb;
18 @@ -1352,7 +1352,14 @@
19 if (!dquot_active(inode))
22 - /* First get references to structures we might need. */
23 + /* In most case, the i_dquot should have been initialized, except
24 + * the newly allocated one. We'd always try to skip the dqget() and
25 + * dqput() calls to avoid unnecessary global lock contention. */
26 + if (!(inode->i_state & I_NEW))
31 for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
33 if (type != -1 && cnt != type)
36 got[cnt] = dqget(sb, id, cnt);
40 spin_lock(&inode->i_lock);
41 if (IS_NOQUOTA(inode))
43 @@ -1381,10 +1388,14 @@
44 /* Avoid races with quotaoff() */
45 if (!sb_has_quota_active(sb, cnt))
47 - /* We could race with quotaon or dqget() could have failed */
50 if (!inode->i_dquot[cnt]) {
52 + spin_unlock(&inode->i_lock);
55 + /* We could race with quotaon or dqget() could have failed */
58 inode->i_dquot[cnt] = got[cnt];
62 * did a write before quota was turned on
64 rsv = inode_get_rsv_space(inode);
65 - if (unlikely(rsv)) {
66 + if (unlikely(rsv) && likely(inode->i_dquot[cnt])) {
67 spin_lock(&dq_data_lock);
68 dquot_resv_space(inode->i_dquot[cnt], rsv);
69 spin_unlock(&dq_data_lock);
71 spin_unlock(&inode->i_lock);
73 /* Drop unused references */
79 void dquot_initialize(struct inode *inode)