mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
quota: Convert dqio_mutex to rwsem
Convert dqio_mutex to rwsem and call it dqio_sem. No functional changes yet. Signed-off-by: Jan Kara <jack@suse.cz>
This commit is contained in:
parent
aae4e7a8bc
commit
bc8230ee8e
@ -5263,18 +5263,13 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Helper function for writing quotas on sync - we need to start transaction
|
||||
* before quota file is locked for write. Otherwise the are possible deadlocks:
|
||||
* Process 1 Process 2
|
||||
* ext4_create() quota_sync()
|
||||
* jbd2_journal_start() write_dquot()
|
||||
* dquot_initialize() down(dqio_mutex)
|
||||
* down(dqio_mutex) jbd2_journal_start()
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_QUOTA
|
||||
|
||||
/*
|
||||
* Helper functions so that transaction is started before we acquire dqio_sem
|
||||
* to keep correct lock ordering of transaction > dqio_sem
|
||||
*/
|
||||
static inline struct inode *dquot_to_inode(struct dquot *dquot)
|
||||
{
|
||||
return sb_dqopt(dquot->dq_sb)->files[dquot->dq_id.type];
|
||||
|
@ -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
|
||||
*/
|
||||
|
||||
@ -611,7 +611,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 +619,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 +666,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;
|
||||
@ -939,7 +939,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 +948,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,7 +520,7 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode,
|
||||
mlog_errno(status);
|
||||
goto out_drop_lock;
|
||||
}
|
||||
mutex_lock(&sb_dqopt(sb)->dqio_mutex);
|
||||
down_write(&sb_dqopt(sb)->dqio_sem);
|
||||
spin_lock(&dq_data_lock);
|
||||
/* Add usage from quota entry into quota changes
|
||||
* of our node. Auxiliary variables are important
|
||||
@ -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);
|
||||
@ -693,7 +693,7 @@ static int ocfs2_local_read_info(struct super_block *sb, int type)
|
||||
|
||||
/* 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);
|
||||
up_write(&sb_dqopt(sb)->dqio_sem);
|
||||
info->dqi_max_spc_limit = 0x7fffffffffffffffLL;
|
||||
info->dqi_max_ino_limit = 0x7fffffffffffffffLL;
|
||||
oinfo = kmalloc(sizeof(struct ocfs2_mem_dqinfo), GFP_NOFS);
|
||||
@ -772,7 +772,7 @@ static int ocfs2_local_read_info(struct super_block *sb, int type)
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
mutex_lock(&sb_dqopt(sb)->dqio_mutex);
|
||||
down_write(&sb_dqopt(sb)->dqio_sem);
|
||||
return 0;
|
||||
out_err:
|
||||
if (oinfo) {
|
||||
@ -786,7 +786,7 @@ out_err:
|
||||
kfree(oinfo);
|
||||
}
|
||||
brelse(bh);
|
||||
mutex_lock(&sb_dqopt(sb)->dqio_mutex);
|
||||
down_write(&sb_dqopt(sb)->dqio_sem);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -120,7 +120,7 @@
|
||||
* spinlock to internal buffers before writing.
|
||||
*
|
||||
* Lock ordering (including related VFS locks) is the following:
|
||||
* s_umount > i_mutex > journal_lock > dquot->dq_lock > dqio_mutex
|
||||
* s_umount > i_mutex > journal_lock > dquot->dq_lock > dqio_sem
|
||||
*/
|
||||
|
||||
static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_list_lock);
|
||||
@ -406,7 +406,7 @@ int dquot_acquire(struct dquot *dquot)
|
||||
struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
|
||||
|
||||
mutex_lock(&dquot->dq_lock);
|
||||
mutex_lock(&dqopt->dqio_mutex);
|
||||
down_write(&dqopt->dqio_sem);
|
||||
if (!test_bit(DQ_READ_B, &dquot->dq_flags))
|
||||
ret = dqopt->ops[dquot->dq_id.type]->read_dqblk(dquot);
|
||||
if (ret < 0)
|
||||
@ -436,7 +436,7 @@ int dquot_acquire(struct dquot *dquot)
|
||||
smp_mb__before_atomic();
|
||||
set_bit(DQ_ACTIVE_B, &dquot->dq_flags);
|
||||
out_iolock:
|
||||
mutex_unlock(&dqopt->dqio_mutex);
|
||||
up_write(&dqopt->dqio_sem);
|
||||
mutex_unlock(&dquot->dq_lock);
|
||||
return ret;
|
||||
}
|
||||
@ -450,7 +450,7 @@ int dquot_commit(struct dquot *dquot)
|
||||
int ret = 0;
|
||||
struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
|
||||
|
||||
mutex_lock(&dqopt->dqio_mutex);
|
||||
down_write(&dqopt->dqio_sem);
|
||||
spin_lock(&dq_list_lock);
|
||||
if (!clear_dquot_dirty(dquot)) {
|
||||
spin_unlock(&dq_list_lock);
|
||||
@ -464,7 +464,7 @@ int dquot_commit(struct dquot *dquot)
|
||||
else
|
||||
ret = -EIO;
|
||||
out_sem:
|
||||
mutex_unlock(&dqopt->dqio_mutex);
|
||||
up_write(&dqopt->dqio_sem);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(dquot_commit);
|
||||
@ -481,7 +481,7 @@ int dquot_release(struct dquot *dquot)
|
||||
/* Check whether we are not racing with some other dqget() */
|
||||
if (atomic_read(&dquot->dq_count) > 1)
|
||||
goto out_dqlock;
|
||||
mutex_lock(&dqopt->dqio_mutex);
|
||||
down_write(&dqopt->dqio_sem);
|
||||
if (dqopt->ops[dquot->dq_id.type]->release_dqblk) {
|
||||
ret = dqopt->ops[dquot->dq_id.type]->release_dqblk(dquot);
|
||||
/* Write the info */
|
||||
@ -493,7 +493,7 @@ int dquot_release(struct dquot *dquot)
|
||||
ret = ret2;
|
||||
}
|
||||
clear_bit(DQ_ACTIVE_B, &dquot->dq_flags);
|
||||
mutex_unlock(&dqopt->dqio_mutex);
|
||||
up_write(&dqopt->dqio_sem);
|
||||
out_dqlock:
|
||||
mutex_unlock(&dquot->dq_lock);
|
||||
return ret;
|
||||
@ -2060,9 +2060,9 @@ int dquot_commit_info(struct super_block *sb, int type)
|
||||
int ret;
|
||||
struct quota_info *dqopt = sb_dqopt(sb);
|
||||
|
||||
mutex_lock(&dqopt->dqio_mutex);
|
||||
down_write(&dqopt->dqio_sem);
|
||||
ret = dqopt->ops[type]->write_file_info(sb, type);
|
||||
mutex_unlock(&dqopt->dqio_mutex);
|
||||
up_write(&dqopt->dqio_sem);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(dquot_commit_info);
|
||||
@ -2076,9 +2076,9 @@ int dquot_get_next_id(struct super_block *sb, struct kqid *qid)
|
||||
return -ESRCH;
|
||||
if (!dqopt->ops[qid->type]->get_next_id)
|
||||
return -ENOSYS;
|
||||
mutex_lock(&dqopt->dqio_mutex);
|
||||
down_write(&dqopt->dqio_sem);
|
||||
err = dqopt->ops[qid->type]->get_next_id(sb, qid);
|
||||
mutex_unlock(&dqopt->dqio_mutex);
|
||||
up_write(&dqopt->dqio_sem);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(dquot_get_next_id);
|
||||
@ -2328,15 +2328,15 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
|
||||
dqopt->info[type].dqi_format = fmt;
|
||||
dqopt->info[type].dqi_fmt_id = format_id;
|
||||
INIT_LIST_HEAD(&dqopt->info[type].dqi_dirty_list);
|
||||
mutex_lock(&dqopt->dqio_mutex);
|
||||
down_write(&dqopt->dqio_sem);
|
||||
error = dqopt->ops[type]->read_file_info(sb, type);
|
||||
if (error < 0) {
|
||||
mutex_unlock(&dqopt->dqio_mutex);
|
||||
up_write(&dqopt->dqio_sem);
|
||||
goto out_file_init;
|
||||
}
|
||||
if (dqopt->flags & DQUOT_QUOTA_SYS_FILE)
|
||||
dqopt->info[type].dqi_flags |= DQF_SYS_FILE;
|
||||
mutex_unlock(&dqopt->dqio_mutex);
|
||||
up_write(&dqopt->dqio_sem);
|
||||
spin_lock(&dq_state_lock);
|
||||
dqopt->flags |= dquot_state_flag(flags, type);
|
||||
spin_unlock(&dq_state_lock);
|
||||
|
@ -379,7 +379,7 @@ int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
|
||||
if (!ddquot)
|
||||
return -ENOMEM;
|
||||
|
||||
/* dq_off is guarded by dqio_mutex */
|
||||
/* dq_off is guarded by dqio_sem */
|
||||
if (!dquot->dq_off) {
|
||||
ret = dq_insert_tree(info, dquot);
|
||||
if (ret < 0) {
|
||||
|
@ -242,7 +242,7 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags,
|
||||
atomic_set(&s->s_active, 1);
|
||||
mutex_init(&s->s_vfs_rename_mutex);
|
||||
lockdep_set_class(&s->s_vfs_rename_mutex, &type->s_vfs_rename_key);
|
||||
mutex_init(&s->s_dquot.dqio_mutex);
|
||||
init_rwsem(&s->s_dquot.dqio_sem);
|
||||
s->s_maxbytes = MAX_NON_LFS;
|
||||
s->s_op = &default_op;
|
||||
s->s_time_gran = 1000000000;
|
||||
|
@ -521,7 +521,7 @@ static inline void quota_send_warning(struct kqid qid, dev_t dev,
|
||||
|
||||
struct quota_info {
|
||||
unsigned int flags; /* Flags for diskquotas on this device */
|
||||
struct mutex dqio_mutex; /* lock device while I/O in progress */
|
||||
struct rw_semaphore dqio_sem; /* Lock quota file while I/O in progress */
|
||||
struct inode *files[MAXQUOTAS]; /* inodes of quotafiles */
|
||||
struct mem_dqinfo info[MAXQUOTAS]; /* Information for each quota type */
|
||||
const struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */
|
||||
|
Loading…
Reference in New Issue
Block a user