diff options
author | Jan Kara <jack@suse.cz> | 2012-04-25 15:15:53 -0400 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2012-05-15 17:34:39 -0400 |
commit | a80b12c3d08dbbf15e6a551e481c32a2df4911f3 (patch) | |
tree | 364989f0fc990496820296b5fc6b655e29416c14 /fs/quota | |
parent | f9ef178412cab442719c9ffdc659933f5f2fa87e (diff) |
quota: Get rid of nested I_MUTEX_QUOTA locking subclass
So far i_mutex was ranking above dqonoff_mutex and i_mutex on quota files
was special and ranking below dqonoff_mutex (and several other locks).
However there's no real need for i_mutex on quota files to be special.
IO on quota files is serialized by dqio_mutex anyway so we don't need to
take i_mutex when writing to quota files. Other places where we take i_mutex
on quota file can accomodate standard i_mutex lock ranking, we only need
to change the lock ranking to be dqonoff_mutex > i_mutex which is a matter
of changing documentation because there's no place which would enforce
ordering in the other direction.
Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/quota')
-rw-r--r-- | fs/quota/dquot.c | 14 |
1 files changed, 6 insertions, 8 deletions
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 6e429fdda17d..10cbe841cb7e 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c | |||
@@ -116,15 +116,15 @@ | |||
116 | * spinlock to internal buffers before writing. | 116 | * spinlock to internal buffers before writing. |
117 | * | 117 | * |
118 | * Lock ordering (including related VFS locks) is the following: | 118 | * Lock ordering (including related VFS locks) is the following: |
119 | * i_mutex > dqonoff_sem > journal_lock > dqptr_sem > dquot->dq_lock > | 119 | * dqonoff_mutex > i_mutex > journal_lock > dqptr_sem > dquot->dq_lock > |
120 | * dqio_mutex | 120 | * dqio_mutex |
121 | * dqonoff_mutex > i_mutex comes from dquot_quota_sync, dquot_enable, etc. | ||
121 | * The lock ordering of dqptr_sem imposed by quota code is only dqonoff_sem > | 122 | * The lock ordering of dqptr_sem imposed by quota code is only dqonoff_sem > |
122 | * dqptr_sem. But filesystem has to count with the fact that functions such as | 123 | * dqptr_sem. But filesystem has to count with the fact that functions such as |
123 | * dquot_alloc_space() acquire dqptr_sem and they usually have to be called | 124 | * dquot_alloc_space() acquire dqptr_sem and they usually have to be called |
124 | * from inside a transaction to keep filesystem consistency after a crash. Also | 125 | * from inside a transaction to keep filesystem consistency after a crash. Also |
125 | * filesystems usually want to do some IO on dquot from ->mark_dirty which is | 126 | * filesystems usually want to do some IO on dquot from ->mark_dirty which is |
126 | * called with dqptr_sem held. | 127 | * called with dqptr_sem held. |
127 | * i_mutex on quota files is special (it's below dqio_mutex) | ||
128 | */ | 128 | */ |
129 | 129 | ||
130 | static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_list_lock); | 130 | static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_list_lock); |
@@ -658,8 +658,7 @@ int dquot_quota_sync(struct super_block *sb, int type, int wait) | |||
658 | continue; | 658 | continue; |
659 | if (!sb_has_quota_active(sb, cnt)) | 659 | if (!sb_has_quota_active(sb, cnt)) |
660 | continue; | 660 | continue; |
661 | mutex_lock_nested(&dqopt->files[cnt]->i_mutex, | 661 | mutex_lock(&dqopt->files[cnt]->i_mutex); |
662 | I_MUTEX_QUOTA); | ||
663 | truncate_inode_pages(&dqopt->files[cnt]->i_data, 0); | 662 | truncate_inode_pages(&dqopt->files[cnt]->i_data, 0); |
664 | mutex_unlock(&dqopt->files[cnt]->i_mutex); | 663 | mutex_unlock(&dqopt->files[cnt]->i_mutex); |
665 | } | 664 | } |
@@ -2037,8 +2036,7 @@ int dquot_disable(struct super_block *sb, int type, unsigned int flags) | |||
2037 | /* If quota was reenabled in the meantime, we have | 2036 | /* If quota was reenabled in the meantime, we have |
2038 | * nothing to do */ | 2037 | * nothing to do */ |
2039 | if (!sb_has_quota_loaded(sb, cnt)) { | 2038 | if (!sb_has_quota_loaded(sb, cnt)) { |
2040 | mutex_lock_nested(&toputinode[cnt]->i_mutex, | 2039 | mutex_lock(&toputinode[cnt]->i_mutex); |
2041 | I_MUTEX_QUOTA); | ||
2042 | toputinode[cnt]->i_flags &= ~(S_IMMUTABLE | | 2040 | toputinode[cnt]->i_flags &= ~(S_IMMUTABLE | |
2043 | S_NOATIME | S_NOQUOTA); | 2041 | S_NOATIME | S_NOQUOTA); |
2044 | truncate_inode_pages(&toputinode[cnt]->i_data, | 2042 | truncate_inode_pages(&toputinode[cnt]->i_data, |
@@ -2133,7 +2131,7 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, | |||
2133 | /* We don't want quota and atime on quota files (deadlocks | 2131 | /* We don't want quota and atime on quota files (deadlocks |
2134 | * possible) Also nobody should write to the file - we use | 2132 | * possible) Also nobody should write to the file - we use |
2135 | * special IO operations which ignore the immutable bit. */ | 2133 | * special IO operations which ignore the immutable bit. */ |
2136 | mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA); | 2134 | mutex_lock(&inode->i_mutex); |
2137 | oldflags = inode->i_flags & (S_NOATIME | S_IMMUTABLE | | 2135 | oldflags = inode->i_flags & (S_NOATIME | S_IMMUTABLE | |
2138 | S_NOQUOTA); | 2136 | S_NOQUOTA); |
2139 | inode->i_flags |= S_NOQUOTA | S_NOATIME | S_IMMUTABLE; | 2137 | inode->i_flags |= S_NOQUOTA | S_NOATIME | S_IMMUTABLE; |
@@ -2180,7 +2178,7 @@ out_file_init: | |||
2180 | iput(inode); | 2178 | iput(inode); |
2181 | out_lock: | 2179 | out_lock: |
2182 | if (oldflags != -1) { | 2180 | if (oldflags != -1) { |
2183 | mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA); | 2181 | mutex_lock(&inode->i_mutex); |
2184 | /* Set the flags back (in the case of accidental quotaon() | 2182 | /* Set the flags back (in the case of accidental quotaon() |
2185 | * on a wrong file we don't want to mess up the flags) */ | 2183 | * on a wrong file we don't want to mess up the flags) */ |
2186 | inode->i_flags &= ~(S_NOATIME | S_NOQUOTA | S_IMMUTABLE); | 2184 | inode->i_flags &= ~(S_NOATIME | S_NOQUOTA | S_IMMUTABLE); |