From: Dmitry Monakhov <dmonakhov@xxxxxxxxx> Currently dq_state_lock is global, which is bad for scalability. In fact different super_blocks have no shared quota data. So we may simply convert the global lock to per-sb locks. Signed-off-by: Dmitry Monakhov <dmonakhov@xxxxxxxxxx> --- fs/quota/dquot.c | 30 +++++++++++++++--------------- include/linux/quota.h | 1 + 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index b87435d..5dfbf9c 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -128,7 +128,6 @@ */ static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_list_lock); -static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_state_lock); __cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_data_lock); EXPORT_SYMBOL(dq_data_lock); @@ -821,13 +820,13 @@ struct dquot *dqget(struct super_block *sb, unsigned int id, int type) return NULL; we_slept: spin_lock(&dq_list_lock); - spin_lock(&dq_state_lock); + spin_lock(&dqopts(sb)->dq_state_lock); if (!sb_has_quota_active(sb, type)) { - spin_unlock(&dq_state_lock); + spin_unlock(&dqopts(sb)->dq_state_lock); spin_unlock(&dq_list_lock); goto out; } - spin_unlock(&dq_state_lock); + spin_unlock(&dqopts(sb)->dq_state_lock); dquot = find_dquot(hashent, sb, id, type); if (!dquot) { @@ -1903,6 +1902,7 @@ static int alloc_quota_info(struct quota_ctl_info *dqctl) { return err; mutex_init(&dqopt->dqio_mutex); + spin_lock_init(&dqopt->dq_state_lock); dqctl->dq_opt = dqopt; return 0; } @@ -1952,24 +1952,24 @@ int dquot_disable(struct super_block *sb, int type, unsigned int flags) continue; if (flags & DQUOT_SUSPENDED) { - spin_lock(&dq_state_lock); + spin_lock(&dqopt->dq_state_lock); qctl->flags |= dquot_state_flag(DQUOT_SUSPENDED, cnt); - spin_unlock(&dq_state_lock); + spin_unlock(&dqopt->dq_state_lock); } else { - spin_lock(&dq_state_lock); + spin_lock(&dqopt->dq_state_lock); qctl->flags &= ~dquot_state_flag(flags, cnt); /* Turning off suspended quotas? */ if (!sb_has_quota_loaded(sb, cnt) && sb_has_quota_suspended(sb, cnt)) { qctl->flags &= ~dquot_state_flag( DQUOT_SUSPENDED, cnt); - spin_unlock(&dq_state_lock); + spin_unlock(&dqopt->dq_state_lock); iput(dqopt->files[cnt]); dqopt->files[cnt] = NULL; continue; } - spin_unlock(&dq_state_lock); + spin_unlock(&dqopt->dq_state_lock); } /* We still have to keep quota loaded? */ @@ -2152,9 +2152,9 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, goto out_file_init; } mutex_unlock(&dqopt->dqio_mutex); - spin_lock(&dq_state_lock); + spin_lock(&dqopt->dq_state_lock); dqctl(sb)->flags |= dquot_state_flag(flags, type); - spin_unlock(&dq_state_lock); + spin_unlock(&dqopt->dq_state_lock); add_dquot_ref(sb, type); mutex_unlock(&dqctl(sb)->dqonoff_mutex); @@ -2199,12 +2199,12 @@ int dquot_resume(struct super_block *sb, int type) } inode = qctl->dq_opt->files[cnt]; qctl->dq_opt->files[cnt] = NULL; - spin_lock(&dq_state_lock); + spin_lock(&dqopts(sb)->dq_state_lock); flags = qctl->flags & dquot_state_flag(DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED, cnt); qctl->flags &= ~dquot_state_flag(DQUOT_STATE_FLAGS, cnt); - spin_unlock(&dq_state_lock); + spin_unlock(&dqopts(sb)->dq_state_lock); mutex_unlock(&qctl->dqonoff_mutex); flags = dquot_generic_flag(flags, cnt); @@ -2283,9 +2283,9 @@ int dquot_enable(struct inode *inode, int type, int format_id, ret = -EBUSY; goto out_lock; } - spin_lock(&dq_state_lock); + spin_lock(&dqopts(sb)->dq_state_lock); qctl->flags |= dquot_state_flag(flags, type); - spin_unlock(&dq_state_lock); + spin_unlock(&dqopts(sb)->dq_state_lock); out_lock: mutex_unlock(&qctl->dqonoff_mutex); return ret; diff --git a/include/linux/quota.h b/include/linux/quota.h index 6803834..3fca71f 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h @@ -404,6 +404,7 @@ struct quota_ctl_info { struct quota_info { struct mutex dqio_mutex; /* lock device while I/O in progress */ struct mem_dqinfo info[MAXQUOTAS]; /* Information for each quota type */ + spinlock_t dq_state_lock; /* serialize quota state changes*/ struct inode *files[MAXQUOTAS]; /* inodes of quotafiles */ const struct quota_format_ops *fmt_ops[MAXQUOTAS]; /* Operations for each type */ }; -- 1.6.5.2 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html