diff options
author | Jan Kara <jack@suse.cz> | 2016-11-23 08:04:55 -0500 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2016-11-30 02:38:07 -0500 |
commit | c3b004460d77bf3f980d877be539016f2df4df12 (patch) | |
tree | 3000d941e7b3ac2fd3ea20d625a384dc4a28a977 | |
parent | 5f530de63cfc6ca8571cbdf58af63fb166cc6517 (diff) |
quota: Remove dqonoff_mutex
The only places that were grabbing dqonoff_mutex are functions turning
quotas on and off and these are properly serialized using s_umount
semaphore. Remove dqonoff_mutex.
Signed-off-by: Jan Kara <jack@suse.cz>
-rw-r--r-- | fs/quota/dquot.c | 80 | ||||
-rw-r--r-- | fs/super.c | 1 | ||||
-rw-r--r-- | include/linux/quota.h | 1 |
3 files changed, 23 insertions, 59 deletions
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index d91aecc939c9..550f78f2b7c7 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c | |||
@@ -119,8 +119,7 @@ | |||
119 | * spinlock to internal buffers before writing. | 119 | * spinlock to internal buffers before writing. |
120 | * | 120 | * |
121 | * Lock ordering (including related VFS locks) is the following: | 121 | * Lock ordering (including related VFS locks) is the following: |
122 | * dqonoff_mutex > i_mutex > journal_lock > dquot->dq_lock > dqio_mutex | 122 | * s_umount > i_mutex > journal_lock > dquot->dq_lock > dqio_mutex |
123 | * dqonoff_mutex > i_mutex comes from dquot_quota_sync, dquot_enable, etc. | ||
124 | */ | 123 | */ |
125 | 124 | ||
126 | static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_list_lock); | 125 | static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_list_lock); |
@@ -933,7 +932,7 @@ static int dqinit_needed(struct inode *inode, int type) | |||
933 | return 0; | 932 | return 0; |
934 | } | 933 | } |
935 | 934 | ||
936 | /* This routine is guarded by dqonoff_mutex mutex */ | 935 | /* This routine is guarded by s_umount semaphore */ |
937 | static void add_dquot_ref(struct super_block *sb, int type) | 936 | static void add_dquot_ref(struct super_block *sb, int type) |
938 | { | 937 | { |
939 | struct inode *inode, *old_inode = NULL; | 938 | struct inode *inode, *old_inode = NULL; |
@@ -2108,18 +2107,14 @@ int dquot_disable(struct super_block *sb, int type, unsigned int flags) | |||
2108 | DQUOT_USAGE_ENABLED))) | 2107 | DQUOT_USAGE_ENABLED))) |
2109 | return -EINVAL; | 2108 | return -EINVAL; |
2110 | 2109 | ||
2111 | /* We need to serialize quota_off() for device */ | ||
2112 | mutex_lock(&dqopt->dqonoff_mutex); | ||
2113 | |||
2114 | /* | 2110 | /* |
2115 | * Skip everything if there's nothing to do. We have to do this because | 2111 | * Skip everything if there's nothing to do. We have to do this because |
2116 | * sometimes we are called when fill_super() failed and calling | 2112 | * sometimes we are called when fill_super() failed and calling |
2117 | * sync_fs() in such cases does no good. | 2113 | * sync_fs() in such cases does no good. |
2118 | */ | 2114 | */ |
2119 | if (!sb_any_quota_loaded(sb)) { | 2115 | if (!sb_any_quota_loaded(sb)) |
2120 | mutex_unlock(&dqopt->dqonoff_mutex); | ||
2121 | return 0; | 2116 | return 0; |
2122 | } | 2117 | |
2123 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 2118 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
2124 | toputinode[cnt] = NULL; | 2119 | toputinode[cnt] = NULL; |
2125 | if (type != -1 && cnt != type) | 2120 | if (type != -1 && cnt != type) |
@@ -2173,7 +2168,6 @@ int dquot_disable(struct super_block *sb, int type, unsigned int flags) | |||
2173 | dqopt->info[cnt].dqi_bgrace = 0; | 2168 | dqopt->info[cnt].dqi_bgrace = 0; |
2174 | dqopt->ops[cnt] = NULL; | 2169 | dqopt->ops[cnt] = NULL; |
2175 | } | 2170 | } |
2176 | mutex_unlock(&dqopt->dqonoff_mutex); | ||
2177 | 2171 | ||
2178 | /* Skip syncing and setting flags if quota files are hidden */ | 2172 | /* Skip syncing and setting flags if quota files are hidden */ |
2179 | if (dqopt->flags & DQUOT_QUOTA_SYS_FILE) | 2173 | if (dqopt->flags & DQUOT_QUOTA_SYS_FILE) |
@@ -2191,19 +2185,13 @@ int dquot_disable(struct super_block *sb, int type, unsigned int flags) | |||
2191 | * changes done by userspace on the next quotaon() */ | 2185 | * changes done by userspace on the next quotaon() */ |
2192 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) | 2186 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) |
2193 | if (toputinode[cnt]) { | 2187 | if (toputinode[cnt]) { |
2194 | mutex_lock(&dqopt->dqonoff_mutex); | 2188 | WARN_ON_ONCE(sb_has_quota_loaded(sb, cnt)); |
2195 | /* If quota was reenabled in the meantime, we have | 2189 | inode_lock(toputinode[cnt]); |
2196 | * nothing to do */ | 2190 | toputinode[cnt]->i_flags &= ~(S_IMMUTABLE | |
2197 | if (!sb_has_quota_loaded(sb, cnt)) { | ||
2198 | inode_lock(toputinode[cnt]); | ||
2199 | toputinode[cnt]->i_flags &= ~(S_IMMUTABLE | | ||
2200 | S_NOATIME | S_NOQUOTA); | 2191 | S_NOATIME | S_NOQUOTA); |
2201 | truncate_inode_pages(&toputinode[cnt]->i_data, | 2192 | truncate_inode_pages(&toputinode[cnt]->i_data, 0); |
2202 | 0); | 2193 | inode_unlock(toputinode[cnt]); |
2203 | inode_unlock(toputinode[cnt]); | 2194 | mark_inode_dirty_sync(toputinode[cnt]); |
2204 | mark_inode_dirty_sync(toputinode[cnt]); | ||
2205 | } | ||
2206 | mutex_unlock(&dqopt->dqonoff_mutex); | ||
2207 | } | 2195 | } |
2208 | if (sb->s_bdev) | 2196 | if (sb->s_bdev) |
2209 | invalidate_bdev(sb->s_bdev); | 2197 | invalidate_bdev(sb->s_bdev); |
@@ -2275,6 +2263,10 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, | |||
2275 | error = -EINVAL; | 2263 | error = -EINVAL; |
2276 | goto out_fmt; | 2264 | goto out_fmt; |
2277 | } | 2265 | } |
2266 | if (sb_has_quota_loaded(sb, type)) { | ||
2267 | error = -EBUSY; | ||
2268 | goto out_fmt; | ||
2269 | } | ||
2278 | 2270 | ||
2279 | if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) { | 2271 | if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) { |
2280 | /* As we bypass the pagecache we must now flush all the | 2272 | /* As we bypass the pagecache we must now flush all the |
@@ -2286,11 +2278,6 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, | |||
2286 | sync_filesystem(sb); | 2278 | sync_filesystem(sb); |
2287 | invalidate_bdev(sb->s_bdev); | 2279 | invalidate_bdev(sb->s_bdev); |
2288 | } | 2280 | } |
2289 | mutex_lock(&dqopt->dqonoff_mutex); | ||
2290 | if (sb_has_quota_loaded(sb, type)) { | ||
2291 | error = -EBUSY; | ||
2292 | goto out_lock; | ||
2293 | } | ||
2294 | 2281 | ||
2295 | if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) { | 2282 | if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) { |
2296 | /* We don't want quota and atime on quota files (deadlocks | 2283 | /* We don't want quota and atime on quota files (deadlocks |
@@ -2311,7 +2298,7 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, | |||
2311 | error = -EIO; | 2298 | error = -EIO; |
2312 | dqopt->files[type] = igrab(inode); | 2299 | dqopt->files[type] = igrab(inode); |
2313 | if (!dqopt->files[type]) | 2300 | if (!dqopt->files[type]) |
2314 | goto out_lock; | 2301 | goto out_file_flags; |
2315 | error = -EINVAL; | 2302 | error = -EINVAL; |
2316 | if (!fmt->qf_ops->check_quota_file(sb, type)) | 2303 | if (!fmt->qf_ops->check_quota_file(sb, type)) |
2317 | goto out_file_init; | 2304 | goto out_file_init; |
@@ -2334,14 +2321,13 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, | |||
2334 | spin_unlock(&dq_state_lock); | 2321 | spin_unlock(&dq_state_lock); |
2335 | 2322 | ||
2336 | add_dquot_ref(sb, type); | 2323 | add_dquot_ref(sb, type); |
2337 | mutex_unlock(&dqopt->dqonoff_mutex); | ||
2338 | 2324 | ||
2339 | return 0; | 2325 | return 0; |
2340 | 2326 | ||
2341 | out_file_init: | 2327 | out_file_init: |
2342 | dqopt->files[type] = NULL; | 2328 | dqopt->files[type] = NULL; |
2343 | iput(inode); | 2329 | iput(inode); |
2344 | out_lock: | 2330 | out_file_flags: |
2345 | if (oldflags != -1) { | 2331 | if (oldflags != -1) { |
2346 | inode_lock(inode); | 2332 | inode_lock(inode); |
2347 | /* Set the flags back (in the case of accidental quotaon() | 2333 | /* Set the flags back (in the case of accidental quotaon() |
@@ -2350,7 +2336,6 @@ out_lock: | |||
2350 | inode->i_flags |= oldflags; | 2336 | inode->i_flags |= oldflags; |
2351 | inode_unlock(inode); | 2337 | inode_unlock(inode); |
2352 | } | 2338 | } |
2353 | mutex_unlock(&dqopt->dqonoff_mutex); | ||
2354 | out_fmt: | 2339 | out_fmt: |
2355 | put_quota_format(fmt); | 2340 | put_quota_format(fmt); |
2356 | 2341 | ||
@@ -2372,12 +2357,9 @@ int dquot_resume(struct super_block *sb, int type) | |||
2372 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 2357 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
2373 | if (type != -1 && cnt != type) | 2358 | if (type != -1 && cnt != type) |
2374 | continue; | 2359 | continue; |
2375 | 2360 | if (!sb_has_quota_suspended(sb, cnt)) | |
2376 | mutex_lock(&dqopt->dqonoff_mutex); | ||
2377 | if (!sb_has_quota_suspended(sb, cnt)) { | ||
2378 | mutex_unlock(&dqopt->dqonoff_mutex); | ||
2379 | continue; | 2361 | continue; |
2380 | } | 2362 | |
2381 | inode = dqopt->files[cnt]; | 2363 | inode = dqopt->files[cnt]; |
2382 | dqopt->files[cnt] = NULL; | 2364 | dqopt->files[cnt] = NULL; |
2383 | spin_lock(&dq_state_lock); | 2365 | spin_lock(&dq_state_lock); |
@@ -2386,7 +2368,6 @@ int dquot_resume(struct super_block *sb, int type) | |||
2386 | cnt); | 2368 | cnt); |
2387 | dqopt->flags &= ~dquot_state_flag(DQUOT_STATE_FLAGS, cnt); | 2369 | dqopt->flags &= ~dquot_state_flag(DQUOT_STATE_FLAGS, cnt); |
2388 | spin_unlock(&dq_state_lock); | 2370 | spin_unlock(&dq_state_lock); |
2389 | mutex_unlock(&dqopt->dqonoff_mutex); | ||
2390 | 2371 | ||
2391 | flags = dquot_generic_flag(flags, cnt); | 2372 | flags = dquot_generic_flag(flags, cnt); |
2392 | ret = vfs_load_quota_inode(inode, cnt, | 2373 | ret = vfs_load_quota_inode(inode, cnt, |
@@ -2422,9 +2403,7 @@ EXPORT_SYMBOL(dquot_quota_on); | |||
2422 | int dquot_enable(struct inode *inode, int type, int format_id, | 2403 | int dquot_enable(struct inode *inode, int type, int format_id, |
2423 | unsigned int flags) | 2404 | unsigned int flags) |
2424 | { | 2405 | { |
2425 | int ret = 0; | ||
2426 | struct super_block *sb = inode->i_sb; | 2406 | struct super_block *sb = inode->i_sb; |
2427 | struct quota_info *dqopt = sb_dqopt(sb); | ||
2428 | 2407 | ||
2429 | /* Just unsuspend quotas? */ | 2408 | /* Just unsuspend quotas? */ |
2430 | BUG_ON(flags & DQUOT_SUSPENDED); | 2409 | BUG_ON(flags & DQUOT_SUSPENDED); |
@@ -2436,31 +2415,18 @@ int dquot_enable(struct inode *inode, int type, int format_id, | |||
2436 | return 0; | 2415 | return 0; |
2437 | /* Just updating flags needed? */ | 2416 | /* Just updating flags needed? */ |
2438 | if (sb_has_quota_loaded(sb, type)) { | 2417 | if (sb_has_quota_loaded(sb, type)) { |
2439 | mutex_lock(&dqopt->dqonoff_mutex); | ||
2440 | /* Now do a reliable test... */ | ||
2441 | if (!sb_has_quota_loaded(sb, type)) { | ||
2442 | mutex_unlock(&dqopt->dqonoff_mutex); | ||
2443 | goto load_quota; | ||
2444 | } | ||
2445 | if (flags & DQUOT_USAGE_ENABLED && | 2418 | if (flags & DQUOT_USAGE_ENABLED && |
2446 | sb_has_quota_usage_enabled(sb, type)) { | 2419 | sb_has_quota_usage_enabled(sb, type)) |
2447 | ret = -EBUSY; | 2420 | return -EBUSY; |
2448 | goto out_lock; | ||
2449 | } | ||
2450 | if (flags & DQUOT_LIMITS_ENABLED && | 2421 | if (flags & DQUOT_LIMITS_ENABLED && |
2451 | sb_has_quota_limits_enabled(sb, type)) { | 2422 | sb_has_quota_limits_enabled(sb, type)) |
2452 | ret = -EBUSY; | 2423 | return -EBUSY; |
2453 | goto out_lock; | ||
2454 | } | ||
2455 | spin_lock(&dq_state_lock); | 2424 | spin_lock(&dq_state_lock); |
2456 | sb_dqopt(sb)->flags |= dquot_state_flag(flags, type); | 2425 | sb_dqopt(sb)->flags |= dquot_state_flag(flags, type); |
2457 | spin_unlock(&dq_state_lock); | 2426 | spin_unlock(&dq_state_lock); |
2458 | out_lock: | 2427 | return 0; |
2459 | mutex_unlock(&dqopt->dqonoff_mutex); | ||
2460 | return ret; | ||
2461 | } | 2428 | } |
2462 | 2429 | ||
2463 | load_quota: | ||
2464 | return vfs_load_quota_inode(inode, type, format_id, flags); | 2430 | return vfs_load_quota_inode(inode, type, format_id, flags); |
2465 | } | 2431 | } |
2466 | EXPORT_SYMBOL(dquot_enable); | 2432 | EXPORT_SYMBOL(dquot_enable); |
diff --git a/fs/super.c b/fs/super.c index f7f724230e2b..1709ed029a2c 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -244,7 +244,6 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags, | |||
244 | mutex_init(&s->s_vfs_rename_mutex); | 244 | mutex_init(&s->s_vfs_rename_mutex); |
245 | lockdep_set_class(&s->s_vfs_rename_mutex, &type->s_vfs_rename_key); | 245 | lockdep_set_class(&s->s_vfs_rename_mutex, &type->s_vfs_rename_key); |
246 | mutex_init(&s->s_dquot.dqio_mutex); | 246 | mutex_init(&s->s_dquot.dqio_mutex); |
247 | mutex_init(&s->s_dquot.dqonoff_mutex); | ||
248 | s->s_maxbytes = MAX_NON_LFS; | 247 | s->s_maxbytes = MAX_NON_LFS; |
249 | s->s_op = &default_op; | 248 | s->s_op = &default_op; |
250 | s->s_time_gran = 1000000000; | 249 | s->s_time_gran = 1000000000; |
diff --git a/include/linux/quota.h b/include/linux/quota.h index 55107a8ff887..b281d198ee5b 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h | |||
@@ -520,7 +520,6 @@ static inline void quota_send_warning(struct kqid qid, dev_t dev, | |||
520 | struct quota_info { | 520 | struct quota_info { |
521 | unsigned int flags; /* Flags for diskquotas on this device */ | 521 | unsigned int flags; /* Flags for diskquotas on this device */ |
522 | struct mutex dqio_mutex; /* lock device while I/O in progress */ | 522 | struct mutex dqio_mutex; /* lock device while I/O in progress */ |
523 | struct mutex dqonoff_mutex; /* Serialize quotaon & quotaoff */ | ||
524 | struct inode *files[MAXQUOTAS]; /* inodes of quotafiles */ | 523 | struct inode *files[MAXQUOTAS]; /* inodes of quotafiles */ |
525 | struct mem_dqinfo info[MAXQUOTAS]; /* Information for each quota type */ | 524 | struct mem_dqinfo info[MAXQUOTAS]; /* Information for each quota type */ |
526 | const struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */ | 525 | const struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */ |