mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 11:41:38 -04:00
Merge branch 'quota_scaling' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs
Pull quota scaling updates from Jan Kara:
"This contains changes to make the quota subsystem more scalable.
Reportedly it improves number of files created per second on ext4
filesystem on fast storage by about a factor of 2x"
* 'quota_scaling' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs: (28 commits)
quota: Add lock annotations to struct members
quota: Reduce contention on dq_data_lock
fs: Provide __inode_get_bytes()
quota: Inline dquot_[re]claim_reserved_space() into callsite
quota: Inline inode_{incr,decr}_space() into callsites
quota: Inline functions into their callsites
ext4: Disable dirty list tracking of dquots when journalling quotas
quota: Allow disabling tracking of dirty dquots in a list
quota: Remove dq_wait_unused from dquot
quota: Move locking into clear_dquot_dirty()
quota: Do not dirty bad dquots
quota: Fix possible corruption of dqi_flags
quota: Propagate ->quota_read errors from v2_read_file_info()
quota: Fix error codes in v2_read_file_info()
quota: Push dqio_sem down to ->read_file_info()
quota: Push dqio_sem down to ->write_file_info()
quota: Push dqio_sem down to ->get_next_id()
quota: Push dqio_sem down to ->release_dqblk()
quota: Remove locking for writing to the old quota format
quota: Do not acquire dqio_sem for dquot overwrites in v2 format
...
This commit is contained in:
commit
ae8ac6b7db
12 changed files with 413 additions and 330 deletions
|
|
@ -33,7 +33,7 @@
|
|||
* Locking of quotas with OCFS2 is rather complex. Here are rules that
|
||||
* should be obeyed by all the functions:
|
||||
* - any write of quota structure (either to local or global file) is protected
|
||||
* by dqio_mutex or dquot->dq_lock.
|
||||
* by dqio_sem or dquot->dq_lock.
|
||||
* - any modification of global quota file holds inode cluster lock, i_mutex,
|
||||
* and ip_alloc_sem of the global quota file (achieved by
|
||||
* ocfs2_lock_global_qf). It also has to hold qinfo_lock.
|
||||
|
|
@ -42,9 +42,9 @@
|
|||
*
|
||||
* A rough sketch of locking dependencies (lf = local file, gf = global file):
|
||||
* Normal filesystem operation:
|
||||
* start_trans -> dqio_mutex -> write to lf
|
||||
* start_trans -> dqio_sem -> write to lf
|
||||
* Syncing of local and global file:
|
||||
* ocfs2_lock_global_qf -> start_trans -> dqio_mutex -> qinfo_lock ->
|
||||
* ocfs2_lock_global_qf -> start_trans -> dqio_sem -> qinfo_lock ->
|
||||
* write to gf
|
||||
* -> write to lf
|
||||
* Acquire dquot for the first time:
|
||||
|
|
@ -60,7 +60,7 @@
|
|||
* Recovery:
|
||||
* inode cluster lock of recovered lf
|
||||
* -> read bitmaps -> ip_alloc_sem of lf
|
||||
* -> ocfs2_lock_global_qf -> start_trans -> dqio_mutex -> qinfo_lock ->
|
||||
* -> ocfs2_lock_global_qf -> start_trans -> dqio_sem -> qinfo_lock ->
|
||||
* write to gf
|
||||
*/
|
||||
|
||||
|
|
@ -443,13 +443,17 @@ static int __ocfs2_global_write_info(struct super_block *sb, int type)
|
|||
int ocfs2_global_write_info(struct super_block *sb, int type)
|
||||
{
|
||||
int err;
|
||||
struct ocfs2_mem_dqinfo *info = sb_dqinfo(sb, type)->dqi_priv;
|
||||
struct quota_info *dqopt = sb_dqopt(sb);
|
||||
struct ocfs2_mem_dqinfo *info = dqopt->info[type].dqi_priv;
|
||||
|
||||
down_write(&dqopt->dqio_sem);
|
||||
err = ocfs2_qinfo_lock(info, 1);
|
||||
if (err < 0)
|
||||
return err;
|
||||
goto out_sem;
|
||||
err = __ocfs2_global_write_info(sb, type);
|
||||
ocfs2_qinfo_unlock(info, 1);
|
||||
out_sem:
|
||||
up_write(&dqopt->dqio_sem);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -500,7 +504,7 @@ int __ocfs2_sync_dquot(struct dquot *dquot, int freeing)
|
|||
/* Update space and inode usage. Get also other information from
|
||||
* global quota file so that we don't overwrite any changes there.
|
||||
* We are */
|
||||
spin_lock(&dq_data_lock);
|
||||
spin_lock(&dquot->dq_dqb_lock);
|
||||
spacechange = dquot->dq_dqb.dqb_curspace -
|
||||
OCFS2_DQUOT(dquot)->dq_origspace;
|
||||
inodechange = dquot->dq_dqb.dqb_curinodes -
|
||||
|
|
@ -556,7 +560,7 @@ int __ocfs2_sync_dquot(struct dquot *dquot, int freeing)
|
|||
__clear_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags);
|
||||
OCFS2_DQUOT(dquot)->dq_origspace = dquot->dq_dqb.dqb_curspace;
|
||||
OCFS2_DQUOT(dquot)->dq_originodes = dquot->dq_dqb.dqb_curinodes;
|
||||
spin_unlock(&dq_data_lock);
|
||||
spin_unlock(&dquot->dq_dqb_lock);
|
||||
err = ocfs2_qinfo_lock(info, freeing);
|
||||
if (err < 0) {
|
||||
mlog(ML_ERROR, "Failed to lock quota info, losing quota write"
|
||||
|
|
@ -611,7 +615,7 @@ static int ocfs2_sync_dquot_helper(struct dquot *dquot, unsigned long type)
|
|||
mlog_errno(status);
|
||||
goto out_ilock;
|
||||
}
|
||||
mutex_lock(&sb_dqopt(sb)->dqio_mutex);
|
||||
down_write(&sb_dqopt(sb)->dqio_sem);
|
||||
status = ocfs2_sync_dquot(dquot);
|
||||
if (status < 0)
|
||||
mlog_errno(status);
|
||||
|
|
@ -619,7 +623,7 @@ static int ocfs2_sync_dquot_helper(struct dquot *dquot, unsigned long type)
|
|||
status = ocfs2_local_write_dquot(dquot);
|
||||
if (status < 0)
|
||||
mlog_errno(status);
|
||||
mutex_unlock(&sb_dqopt(sb)->dqio_mutex);
|
||||
up_write(&sb_dqopt(sb)->dqio_sem);
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
out_ilock:
|
||||
ocfs2_unlock_global_qf(oinfo, 1);
|
||||
|
|
@ -666,9 +670,9 @@ static int ocfs2_write_dquot(struct dquot *dquot)
|
|||
mlog_errno(status);
|
||||
goto out;
|
||||
}
|
||||
mutex_lock(&sb_dqopt(dquot->dq_sb)->dqio_mutex);
|
||||
down_write(&sb_dqopt(dquot->dq_sb)->dqio_sem);
|
||||
status = ocfs2_local_write_dquot(dquot);
|
||||
mutex_unlock(&sb_dqopt(dquot->dq_sb)->dqio_mutex);
|
||||
up_write(&sb_dqopt(dquot->dq_sb)->dqio_sem);
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
out:
|
||||
return status;
|
||||
|
|
@ -920,10 +924,10 @@ static int ocfs2_mark_dquot_dirty(struct dquot *dquot)
|
|||
|
||||
/* In case user set some limits, sync dquot immediately to global
|
||||
* quota file so that information propagates quicker */
|
||||
spin_lock(&dq_data_lock);
|
||||
spin_lock(&dquot->dq_dqb_lock);
|
||||
if (dquot->dq_flags & mask)
|
||||
sync = 1;
|
||||
spin_unlock(&dq_data_lock);
|
||||
spin_unlock(&dquot->dq_dqb_lock);
|
||||
/* This is a slight hack but we can't afford getting global quota
|
||||
* lock if we already have a transaction started. */
|
||||
if (!sync || journal_current_handle()) {
|
||||
|
|
@ -939,7 +943,7 @@ static int ocfs2_mark_dquot_dirty(struct dquot *dquot)
|
|||
mlog_errno(status);
|
||||
goto out_ilock;
|
||||
}
|
||||
mutex_lock(&sb_dqopt(sb)->dqio_mutex);
|
||||
down_write(&sb_dqopt(sb)->dqio_sem);
|
||||
status = ocfs2_sync_dquot(dquot);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
|
|
@ -948,7 +952,7 @@ static int ocfs2_mark_dquot_dirty(struct dquot *dquot)
|
|||
/* Now write updated local dquot structure */
|
||||
status = ocfs2_local_write_dquot(dquot);
|
||||
out_dlock:
|
||||
mutex_unlock(&sb_dqopt(sb)->dqio_mutex);
|
||||
up_write(&sb_dqopt(sb)->dqio_sem);
|
||||
ocfs2_commit_trans(osb, handle);
|
||||
out_ilock:
|
||||
ocfs2_unlock_global_qf(oinfo, 1);
|
||||
|
|
|
|||
|
|
@ -520,8 +520,8 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode,
|
|||
mlog_errno(status);
|
||||
goto out_drop_lock;
|
||||
}
|
||||
mutex_lock(&sb_dqopt(sb)->dqio_mutex);
|
||||
spin_lock(&dq_data_lock);
|
||||
down_write(&sb_dqopt(sb)->dqio_sem);
|
||||
spin_lock(&dquot->dq_dqb_lock);
|
||||
/* Add usage from quota entry into quota changes
|
||||
* of our node. Auxiliary variables are important
|
||||
* due to signedness */
|
||||
|
|
@ -529,7 +529,7 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode,
|
|||
inodechange = le64_to_cpu(dqblk->dqb_inodemod);
|
||||
dquot->dq_dqb.dqb_curspace += spacechange;
|
||||
dquot->dq_dqb.dqb_curinodes += inodechange;
|
||||
spin_unlock(&dq_data_lock);
|
||||
spin_unlock(&dquot->dq_dqb_lock);
|
||||
/* We want to drop reference held by the crashed
|
||||
* node. Since we have our own reference we know
|
||||
* global structure actually won't be freed. */
|
||||
|
|
@ -553,7 +553,7 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode,
|
|||
unlock_buffer(qbh);
|
||||
ocfs2_journal_dirty(handle, qbh);
|
||||
out_commit:
|
||||
mutex_unlock(&sb_dqopt(sb)->dqio_mutex);
|
||||
up_write(&sb_dqopt(sb)->dqio_sem);
|
||||
ocfs2_commit_trans(OCFS2_SB(sb), handle);
|
||||
out_drop_lock:
|
||||
ocfs2_unlock_global_qf(oinfo, 1);
|
||||
|
|
@ -691,9 +691,6 @@ static int ocfs2_local_read_info(struct super_block *sb, int type)
|
|||
struct ocfs2_quota_recovery *rec;
|
||||
int locked = 0;
|
||||
|
||||
/* We don't need the lock and we have to acquire quota file locks
|
||||
* which will later depend on this lock */
|
||||
mutex_unlock(&sb_dqopt(sb)->dqio_mutex);
|
||||
info->dqi_max_spc_limit = 0x7fffffffffffffffLL;
|
||||
info->dqi_max_ino_limit = 0x7fffffffffffffffLL;
|
||||
oinfo = kmalloc(sizeof(struct ocfs2_mem_dqinfo), GFP_NOFS);
|
||||
|
|
@ -772,7 +769,6 @@ static int ocfs2_local_read_info(struct super_block *sb, int type)
|
|||
goto out_err;
|
||||
}
|
||||
|
||||
mutex_lock(&sb_dqopt(sb)->dqio_mutex);
|
||||
return 0;
|
||||
out_err:
|
||||
if (oinfo) {
|
||||
|
|
@ -786,7 +782,6 @@ out_err:
|
|||
kfree(oinfo);
|
||||
}
|
||||
brelse(bh);
|
||||
mutex_lock(&sb_dqopt(sb)->dqio_mutex);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -882,12 +877,12 @@ static void olq_set_dquot(struct buffer_head *bh, void *private)
|
|||
|
||||
dqblk->dqb_id = cpu_to_le64(from_kqid(&init_user_ns,
|
||||
od->dq_dquot.dq_id));
|
||||
spin_lock(&dq_data_lock);
|
||||
spin_lock(&od->dq_dquot.dq_dqb_lock);
|
||||
dqblk->dqb_spacemod = cpu_to_le64(od->dq_dquot.dq_dqb.dqb_curspace -
|
||||
od->dq_origspace);
|
||||
dqblk->dqb_inodemod = cpu_to_le64(od->dq_dquot.dq_dqb.dqb_curinodes -
|
||||
od->dq_originodes);
|
||||
spin_unlock(&dq_data_lock);
|
||||
spin_unlock(&od->dq_dquot.dq_dqb_lock);
|
||||
trace_olq_set_dquot(
|
||||
(unsigned long long)le64_to_cpu(dqblk->dqb_spacemod),
|
||||
(unsigned long long)le64_to_cpu(dqblk->dqb_inodemod),
|
||||
|
|
|
|||
Loading…
Reference in a new issue