diff options
author | Jan Kara <jack@suse.cz> | 2013-12-23 16:02:16 -0500 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2013-12-23 16:02:16 -0500 |
commit | 4ea7772f828a2f1cf6fbf96a3e6f99ae149d2724 (patch) | |
tree | 2515839eb42739317490f2365ea303435ea236f3 /fs/udf | |
parent | 301d4c9a286bc7dc4fb3cda21131be91a582fa79 (diff) |
udf: Fix lockdep warning from udf_symlink()
Lockdep is complaining about UDF:
=============================================
[ INFO: possible recursive locking detected ]
3.12.0+ #16 Not tainted
---------------------------------------------
ln/7386 is trying to acquire lock:
(&ei->i_data_sem){+.+...}, at: [<ffffffff8142f06d>] udf_get_block+0x8d/0x130
but task is already holding lock:
(&ei->i_data_sem){+.+...}, at: [<ffffffff81431a8d>] udf_symlink+0x8d/0x690
other info that might help us debug this:
Possible unsafe locking scenario:
CPU0
----
lock(&ei->i_data_sem);
lock(&ei->i_data_sem);
*** DEADLOCK ***
This is because we hold i_data_sem of the symlink inode while calling
udf_add_entry() for the directory. I don't think this can ever lead to
deadlocks since we never hold i_data_sem for two inodes in any other
place.
The fix is simple - move unlock of i_data_sem for symlink inode up. We
don't need it for anything when linking symlink inode to directory.
Reported-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/udf')
-rw-r--r-- | fs/udf/namei.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/fs/udf/namei.c b/fs/udf/namei.c index 5f6fc17d6bc5..9737cba1357d 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c | |||
@@ -1010,6 +1010,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry, | |||
1010 | else | 1010 | else |
1011 | udf_truncate_tail_extent(inode); | 1011 | udf_truncate_tail_extent(inode); |
1012 | mark_inode_dirty(inode); | 1012 | mark_inode_dirty(inode); |
1013 | up_write(&iinfo->i_data_sem); | ||
1013 | 1014 | ||
1014 | fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); | 1015 | fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); |
1015 | if (!fi) | 1016 | if (!fi) |
@@ -1023,7 +1024,6 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry, | |||
1023 | udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL); | 1024 | udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL); |
1024 | if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) | 1025 | if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) |
1025 | mark_inode_dirty(dir); | 1026 | mark_inode_dirty(dir); |
1026 | up_write(&iinfo->i_data_sem); | ||
1027 | if (fibh.sbh != fibh.ebh) | 1027 | if (fibh.sbh != fibh.ebh) |
1028 | brelse(fibh.ebh); | 1028 | brelse(fibh.ebh); |
1029 | brelse(fibh.sbh); | 1029 | brelse(fibh.sbh); |