diff options
author | Jan Kara <jack@suse.cz> | 2017-05-21 22:31:23 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2017-05-21 22:31:23 -0400 |
commit | 964edf66bf9ab70cb387b27946c0aef7b94c4d1b (patch) | |
tree | 1c7bc7711f0199abf6ccf5f87a9c45fbc1f261a8 | |
parent | 08332893e37af6ae779367e78e444f8f9571511d (diff) |
ext4: clear lockdep subtype for quota files on quota off
Quota files have special ranking of i_data_sem lock. We inform lockdep
about it when turning on quotas however when turning quotas off, we
don't clear the lockdep subclass from i_data_sem lock and thus when the
inode gets later reused for a normal file or directory, lockdep gets
confused and complains about possible deadlocks. Fix the problem by
resetting lockdep subclass of i_data_sem on quota off.
Cc: stable@vger.kernel.org
Fixes: daf647d2dd58cec59570d7698a45b98e580f2076
Reported-and-tested-by: Ross Zwisler <ross.zwisler@linux.intel.com>
Reviewed-by: Andreas Dilger <adilger@dilger.ca>
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r-- | fs/ext4/super.c | 14 |
1 files changed, 5 insertions, 9 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 0b177da9ea82..8f05c72bc4ec 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -848,14 +848,9 @@ static inline void ext4_quota_off_umount(struct super_block *sb) | |||
848 | { | 848 | { |
849 | int type; | 849 | int type; |
850 | 850 | ||
851 | if (ext4_has_feature_quota(sb)) { | 851 | /* Use our quota_off function to clear inode flags etc. */ |
852 | dquot_disable(sb, -1, | 852 | for (type = 0; type < EXT4_MAXQUOTAS; type++) |
853 | DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED); | 853 | ext4_quota_off(sb, type); |
854 | } else { | ||
855 | /* Use our quota_off function to clear inode flags etc. */ | ||
856 | for (type = 0; type < EXT4_MAXQUOTAS; type++) | ||
857 | ext4_quota_off(sb, type); | ||
858 | } | ||
859 | } | 854 | } |
860 | #else | 855 | #else |
861 | static inline void ext4_quota_off_umount(struct super_block *sb) | 856 | static inline void ext4_quota_off_umount(struct super_block *sb) |
@@ -5485,7 +5480,7 @@ static int ext4_quota_off(struct super_block *sb, int type) | |||
5485 | goto out; | 5480 | goto out; |
5486 | 5481 | ||
5487 | err = dquot_quota_off(sb, type); | 5482 | err = dquot_quota_off(sb, type); |
5488 | if (err) | 5483 | if (err || ext4_has_feature_quota(sb)) |
5489 | goto out_put; | 5484 | goto out_put; |
5490 | 5485 | ||
5491 | inode_lock(inode); | 5486 | inode_lock(inode); |
@@ -5505,6 +5500,7 @@ static int ext4_quota_off(struct super_block *sb, int type) | |||
5505 | out_unlock: | 5500 | out_unlock: |
5506 | inode_unlock(inode); | 5501 | inode_unlock(inode); |
5507 | out_put: | 5502 | out_put: |
5503 | lockdep_set_quota_inode(inode, I_DATA_SEM_NORMAL); | ||
5508 | iput(inode); | 5504 | iput(inode); |
5509 | return err; | 5505 | return err; |
5510 | out: | 5506 | out: |