aboutsummaryrefslogtreecommitdiffstats
path: root/fs/reiserfs/inode.c
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2009-04-13 23:34:24 -0400
committerFrederic Weisbecker <fweisbec@gmail.com>2009-09-14 01:18:03 -0400
commit22c963addcf426bef97a43f6e601f985f8082ed5 (patch)
treef71ae95fd1eee899c446ebb03a3cc02fe24daf3c /fs/reiserfs/inode.c
parentdaf88c898312a22b5385655bc6e0b064eaa2efba (diff)
kill-the-BKL/reiserfs: lock only once in reiserfs_truncate_file
Impact: fix a deadlock reiserfs_truncate_file() can be called from multiple context where the write lock can be already hold or not. This function also acquire (possibly recursively) the write lock. Subsequent releases before sleeping will not actually release the lock because we may be in more than one lock depth degree. A typical case is: reiserfs_file_release { acquire_the_lock() reiserfs_truncate_file() reacquire_the_lock() journal_begin() { do_journal_begin_r() { reiserfs_wait_on_write_block() { /* * Not released because still one * depth owned */ release_lock() wait_for_event() At this stage the event never happen because the one which provides it needs the write lock. We use reiserfs_write_lock_once() here to ensure that we don't acquire the write lock recursively. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Alessio Igor Bogani <abogani@texware.it> Cc: Jeff Mahoney <jeffm@suse.com> Cc: Alexander Beregalov <a.beregalov@gmail.com> Cc: Chris Mason <chris.mason@oracle.com> LKML-Reference: <1239680065-25013-3-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'fs/reiserfs/inode.c')
-rw-r--r--fs/reiserfs/inode.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 1893c8198439..cc70b56bf6f2 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -2079,8 +2079,9 @@ int reiserfs_truncate_file(struct inode *inode, int update_timestamps)
2079 int error; 2079 int error;
2080 struct buffer_head *bh = NULL; 2080 struct buffer_head *bh = NULL;
2081 int err2; 2081 int err2;
2082 int lock_depth;
2082 2083
2083 reiserfs_write_lock(inode->i_sb); 2084 lock_depth = reiserfs_write_lock_once(inode->i_sb);
2084 2085
2085 if (inode->i_size > 0) { 2086 if (inode->i_size > 0) {
2086 error = grab_tail_page(inode, &page, &bh); 2087 error = grab_tail_page(inode, &page, &bh);
@@ -2149,14 +2150,17 @@ int reiserfs_truncate_file(struct inode *inode, int update_timestamps)
2149 page_cache_release(page); 2150 page_cache_release(page);
2150 } 2151 }
2151 2152
2152 reiserfs_write_unlock(inode->i_sb); 2153 reiserfs_write_unlock_once(inode->i_sb, lock_depth);
2154
2153 return 0; 2155 return 0;
2154 out: 2156 out:
2155 if (page) { 2157 if (page) {
2156 unlock_page(page); 2158 unlock_page(page);
2157 page_cache_release(page); 2159 page_cache_release(page);
2158 } 2160 }
2159 reiserfs_write_unlock(inode->i_sb); 2161
2162 reiserfs_write_unlock_once(inode->i_sb, lock_depth);
2163
2160 return error; 2164 return error;
2161} 2165}
2162 2166