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 +++ linux-2.6.32-358.0.1.el6/fs/quota/dquot.c @@ -1230,7 +1230,7 @@ static int info_bdq_free(struct dquot *d int dquot_initialize(struct inode *inode, int type) { unsigned int id = 0; - int cnt, ret = 0; + int cnt, ret = 0, dq_get = 0; struct dquot *got[MAXQUOTAS] = { NULL, NULL }; struct super_block *sb = inode->i_sb; qsize_t rsv; @@ -1240,7 +1240,14 @@ int dquot_initialize(struct inode *inode if (IS_NOQUOTA(inode)) return 0; - /* First get references to structures we might need. */ + /* In most case, the i_dquot should have been initialized, except + * the newly allocated one. We'd always try to skip the dqget() and + * dqput() calls to avoid unnecessary global lock contention. */ + if (!(inode->i_state & I_NEW)) + goto init_idquot; + +get_dquots: + dq_get = 1; for (cnt = 0; cnt < MAXQUOTAS; cnt++) { if (type != -1 && cnt != type) continue; @@ -1254,7 +1261,7 @@ int dquot_initialize(struct inode *inode } got[cnt] = dqget(sb, id, cnt); } - +init_idquot: spin_lock(&inode->i_lock); if (IS_NOQUOTA(inode)) goto out_err; @@ -1265,6 +1272,10 @@ int dquot_initialize(struct inode *inode if (!sb_has_quota_active(sb, cnt)) continue; if (!inode->i_dquot[cnt]) { + if (dq_get == 0) { + spin_unlock(&inode->i_lock); + goto get_dquots; + } inode->i_dquot[cnt] = got[cnt]; got[cnt] = NULL; /* @@ -1272,7 +1283,7 @@ int dquot_initialize(struct inode *inode * did a write before quota was turned on */ rsv = inode_get_rsv_space(inode); - if (unlikely(rsv)) { + if (unlikely(rsv) && likely(inode->i_dquot[cnt])) { spin_lock(&dq_data_lock); dquot_resv_space(inode->i_dquot[cnt], rsv); spin_unlock(&dq_data_lock);