diff options
Diffstat (limited to 'fs/reiserfs')
| -rw-r--r-- | fs/reiserfs/Kconfig | 1 | ||||
| -rw-r--r-- | fs/reiserfs/Makefile | 2 | ||||
| -rw-r--r-- | fs/reiserfs/bitmap.c | 4 | ||||
| -rw-r--r-- | fs/reiserfs/dir.c | 10 | ||||
| -rw-r--r-- | fs/reiserfs/do_balan.c | 17 | ||||
| -rw-r--r-- | fs/reiserfs/file.c | 2 | ||||
| -rw-r--r-- | fs/reiserfs/fix_node.c | 21 | ||||
| -rw-r--r-- | fs/reiserfs/inode.c | 97 | ||||
| -rw-r--r-- | fs/reiserfs/ioctl.c | 77 | ||||
| -rw-r--r-- | fs/reiserfs/journal.c | 130 | ||||
| -rw-r--r-- | fs/reiserfs/lock.c | 88 | ||||
| -rw-r--r-- | fs/reiserfs/namei.c | 20 | ||||
| -rw-r--r-- | fs/reiserfs/prints.c | 4 | ||||
| -rw-r--r-- | fs/reiserfs/resize.c | 2 | ||||
| -rw-r--r-- | fs/reiserfs/stree.c | 53 | ||||
| -rw-r--r-- | fs/reiserfs/super.c | 52 | ||||
| -rw-r--r-- | fs/reiserfs/xattr.c | 6 |
17 files changed, 422 insertions, 164 deletions
diff --git a/fs/reiserfs/Kconfig b/fs/reiserfs/Kconfig index 513f431038f9..ac7cd75c86f8 100644 --- a/fs/reiserfs/Kconfig +++ b/fs/reiserfs/Kconfig | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | config REISERFS_FS | 1 | config REISERFS_FS |
| 2 | tristate "Reiserfs support" | 2 | tristate "Reiserfs support" |
| 3 | select CRC32 | 3 | select CRC32 |
| 4 | select FS_JOURNAL_INFO | ||
| 4 | help | 5 | help |
| 5 | Stores not just filenames but the files themselves in a balanced | 6 | Stores not just filenames but the files themselves in a balanced |
| 6 | tree. Uses journalling. | 7 | tree. Uses journalling. |
diff --git a/fs/reiserfs/Makefile b/fs/reiserfs/Makefile index 7c5ab6330dd6..6a9e30c041dd 100644 --- a/fs/reiserfs/Makefile +++ b/fs/reiserfs/Makefile | |||
| @@ -7,7 +7,7 @@ obj-$(CONFIG_REISERFS_FS) += reiserfs.o | |||
| 7 | reiserfs-objs := bitmap.o do_balan.o namei.o inode.o file.o dir.o fix_node.o \ | 7 | reiserfs-objs := bitmap.o do_balan.o namei.o inode.o file.o dir.o fix_node.o \ |
| 8 | super.o prints.o objectid.o lbalance.o ibalance.o stree.o \ | 8 | super.o prints.o objectid.o lbalance.o ibalance.o stree.o \ |
| 9 | hashes.o tail_conversion.o journal.o resize.o \ | 9 | hashes.o tail_conversion.o journal.o resize.o \ |
| 10 | item_ops.o ioctl.o procfs.o xattr.o | 10 | item_ops.o ioctl.o procfs.o xattr.o lock.o |
| 11 | 11 | ||
| 12 | ifeq ($(CONFIG_REISERFS_FS_XATTR),y) | 12 | ifeq ($(CONFIG_REISERFS_FS_XATTR),y) |
| 13 | reiserfs-objs += xattr_user.o xattr_trusted.o | 13 | reiserfs-objs += xattr_user.o xattr_trusted.o |
diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c index e716161ab325..685495707181 100644 --- a/fs/reiserfs/bitmap.c +++ b/fs/reiserfs/bitmap.c | |||
| @@ -1249,14 +1249,18 @@ struct buffer_head *reiserfs_read_bitmap_block(struct super_block *sb, | |||
| 1249 | else if (bitmap == 0) | 1249 | else if (bitmap == 0) |
| 1250 | block = (REISERFS_DISK_OFFSET_IN_BYTES >> sb->s_blocksize_bits) + 1; | 1250 | block = (REISERFS_DISK_OFFSET_IN_BYTES >> sb->s_blocksize_bits) + 1; |
| 1251 | 1251 | ||
| 1252 | reiserfs_write_unlock(sb); | ||
| 1252 | bh = sb_bread(sb, block); | 1253 | bh = sb_bread(sb, block); |
| 1254 | reiserfs_write_lock(sb); | ||
| 1253 | if (bh == NULL) | 1255 | if (bh == NULL) |
| 1254 | reiserfs_warning(sb, "sh-2029: %s: bitmap block (#%u) " | 1256 | reiserfs_warning(sb, "sh-2029: %s: bitmap block (#%u) " |
| 1255 | "reading failed", __func__, block); | 1257 | "reading failed", __func__, block); |
| 1256 | else { | 1258 | else { |
| 1257 | if (buffer_locked(bh)) { | 1259 | if (buffer_locked(bh)) { |
| 1258 | PROC_INFO_INC(sb, scan_bitmap.wait); | 1260 | PROC_INFO_INC(sb, scan_bitmap.wait); |
| 1261 | reiserfs_write_unlock(sb); | ||
| 1259 | __wait_on_buffer(bh); | 1262 | __wait_on_buffer(bh); |
| 1263 | reiserfs_write_lock(sb); | ||
| 1260 | } | 1264 | } |
| 1261 | BUG_ON(!buffer_uptodate(bh)); | 1265 | BUG_ON(!buffer_uptodate(bh)); |
| 1262 | BUG_ON(atomic_read(&bh->b_count) == 0); | 1266 | BUG_ON(atomic_read(&bh->b_count) == 0); |
diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c index 6d2668fdc384..c094f58c7448 100644 --- a/fs/reiserfs/dir.c +++ b/fs/reiserfs/dir.c | |||
| @@ -20,7 +20,7 @@ const struct file_operations reiserfs_dir_operations = { | |||
| 20 | .read = generic_read_dir, | 20 | .read = generic_read_dir, |
| 21 | .readdir = reiserfs_readdir, | 21 | .readdir = reiserfs_readdir, |
| 22 | .fsync = reiserfs_dir_fsync, | 22 | .fsync = reiserfs_dir_fsync, |
| 23 | .ioctl = reiserfs_ioctl, | 23 | .unlocked_ioctl = reiserfs_ioctl, |
| 24 | #ifdef CONFIG_COMPAT | 24 | #ifdef CONFIG_COMPAT |
| 25 | .compat_ioctl = reiserfs_compat_ioctl, | 25 | .compat_ioctl = reiserfs_compat_ioctl, |
| 26 | #endif | 26 | #endif |
| @@ -174,14 +174,22 @@ int reiserfs_readdir_dentry(struct dentry *dentry, void *dirent, | |||
| 174 | // user space buffer is swapped out. At that time | 174 | // user space buffer is swapped out. At that time |
| 175 | // entry can move to somewhere else | 175 | // entry can move to somewhere else |
| 176 | memcpy(local_buf, d_name, d_reclen); | 176 | memcpy(local_buf, d_name, d_reclen); |
| 177 | |||
| 178 | /* | ||
| 179 | * Since filldir might sleep, we can release | ||
| 180 | * the write lock here for other waiters | ||
| 181 | */ | ||
| 182 | reiserfs_write_unlock(inode->i_sb); | ||
| 177 | if (filldir | 183 | if (filldir |
| 178 | (dirent, local_buf, d_reclen, d_off, d_ino, | 184 | (dirent, local_buf, d_reclen, d_off, d_ino, |
| 179 | DT_UNKNOWN) < 0) { | 185 | DT_UNKNOWN) < 0) { |
| 186 | reiserfs_write_lock(inode->i_sb); | ||
| 180 | if (local_buf != small_buf) { | 187 | if (local_buf != small_buf) { |
| 181 | kfree(local_buf); | 188 | kfree(local_buf); |
| 182 | } | 189 | } |
| 183 | goto end; | 190 | goto end; |
| 184 | } | 191 | } |
| 192 | reiserfs_write_lock(inode->i_sb); | ||
| 185 | if (local_buf != small_buf) { | 193 | if (local_buf != small_buf) { |
| 186 | kfree(local_buf); | 194 | kfree(local_buf); |
| 187 | } | 195 | } |
diff --git a/fs/reiserfs/do_balan.c b/fs/reiserfs/do_balan.c index 128d3f7c8aa5..60c080440661 100644 --- a/fs/reiserfs/do_balan.c +++ b/fs/reiserfs/do_balan.c | |||
| @@ -21,14 +21,6 @@ | |||
| 21 | #include <linux/buffer_head.h> | 21 | #include <linux/buffer_head.h> |
| 22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
| 23 | 23 | ||
| 24 | #ifdef CONFIG_REISERFS_CHECK | ||
| 25 | |||
| 26 | struct tree_balance *cur_tb = NULL; /* detects whether more than one | ||
| 27 | copy of tb exists as a means | ||
| 28 | of checking whether schedule | ||
| 29 | is interrupting do_balance */ | ||
| 30 | #endif | ||
| 31 | |||
| 32 | static inline void buffer_info_init_left(struct tree_balance *tb, | 24 | static inline void buffer_info_init_left(struct tree_balance *tb, |
| 33 | struct buffer_info *bi) | 25 | struct buffer_info *bi) |
| 34 | { | 26 | { |
| @@ -1840,11 +1832,12 @@ static int check_before_balancing(struct tree_balance *tb) | |||
| 1840 | { | 1832 | { |
| 1841 | int retval = 0; | 1833 | int retval = 0; |
| 1842 | 1834 | ||
| 1843 | if (cur_tb) { | 1835 | if (REISERFS_SB(tb->tb_sb)->cur_tb) { |
| 1844 | reiserfs_panic(tb->tb_sb, "vs-12335", "suspect that schedule " | 1836 | reiserfs_panic(tb->tb_sb, "vs-12335", "suspect that schedule " |
| 1845 | "occurred based on cur_tb not being null at " | 1837 | "occurred based on cur_tb not being null at " |
| 1846 | "this point in code. do_balance cannot properly " | 1838 | "this point in code. do_balance cannot properly " |
| 1847 | "handle schedule occurring while it runs."); | 1839 | "handle concurrent tree accesses on a same " |
| 1840 | "mount point."); | ||
| 1848 | } | 1841 | } |
| 1849 | 1842 | ||
| 1850 | /* double check that buffers that we will modify are unlocked. (fix_nodes should already have | 1843 | /* double check that buffers that we will modify are unlocked. (fix_nodes should already have |
| @@ -1986,7 +1979,7 @@ static inline void do_balance_starts(struct tree_balance *tb) | |||
| 1986 | "check");*/ | 1979 | "check");*/ |
| 1987 | RFALSE(check_before_balancing(tb), "PAP-12340: locked buffers in TB"); | 1980 | RFALSE(check_before_balancing(tb), "PAP-12340: locked buffers in TB"); |
| 1988 | #ifdef CONFIG_REISERFS_CHECK | 1981 | #ifdef CONFIG_REISERFS_CHECK |
| 1989 | cur_tb = tb; | 1982 | REISERFS_SB(tb->tb_sb)->cur_tb = tb; |
| 1990 | #endif | 1983 | #endif |
| 1991 | } | 1984 | } |
| 1992 | 1985 | ||
| @@ -1996,7 +1989,7 @@ static inline void do_balance_completed(struct tree_balance *tb) | |||
| 1996 | #ifdef CONFIG_REISERFS_CHECK | 1989 | #ifdef CONFIG_REISERFS_CHECK |
| 1997 | check_leaf_level(tb); | 1990 | check_leaf_level(tb); |
| 1998 | check_internal_levels(tb); | 1991 | check_internal_levels(tb); |
| 1999 | cur_tb = NULL; | 1992 | REISERFS_SB(tb->tb_sb)->cur_tb = NULL; |
| 2000 | #endif | 1993 | #endif |
| 2001 | 1994 | ||
| 2002 | /* reiserfs_free_block is no longer schedule safe. So, we need to | 1995 | /* reiserfs_free_block is no longer schedule safe. So, we need to |
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c index 9f436668b7f8..da2dba082e2d 100644 --- a/fs/reiserfs/file.c +++ b/fs/reiserfs/file.c | |||
| @@ -284,7 +284,7 @@ static ssize_t reiserfs_file_write(struct file *file, /* the file we are going t | |||
| 284 | const struct file_operations reiserfs_file_operations = { | 284 | const struct file_operations reiserfs_file_operations = { |
| 285 | .read = do_sync_read, | 285 | .read = do_sync_read, |
| 286 | .write = reiserfs_file_write, | 286 | .write = reiserfs_file_write, |
| 287 | .ioctl = reiserfs_ioctl, | 287 | .unlocked_ioctl = reiserfs_ioctl, |
| 288 | #ifdef CONFIG_COMPAT | 288 | #ifdef CONFIG_COMPAT |
| 289 | .compat_ioctl = reiserfs_compat_ioctl, | 289 | .compat_ioctl = reiserfs_compat_ioctl, |
| 290 | #endif | 290 | #endif |
diff --git a/fs/reiserfs/fix_node.c b/fs/reiserfs/fix_node.c index 5e5a4e6fbaf8..6591cb21edf6 100644 --- a/fs/reiserfs/fix_node.c +++ b/fs/reiserfs/fix_node.c | |||
| @@ -563,9 +563,6 @@ static int get_num_ver(int mode, struct tree_balance *tb, int h, | |||
| 563 | return needed_nodes; | 563 | return needed_nodes; |
| 564 | } | 564 | } |
| 565 | 565 | ||
| 566 | #ifdef CONFIG_REISERFS_CHECK | ||
| 567 | extern struct tree_balance *cur_tb; | ||
| 568 | #endif | ||
| 569 | 566 | ||
| 570 | /* Set parameters for balancing. | 567 | /* Set parameters for balancing. |
| 571 | * Performs write of results of analysis of balancing into structure tb, | 568 | * Performs write of results of analysis of balancing into structure tb, |
| @@ -834,7 +831,7 @@ static int get_empty_nodes(struct tree_balance *tb, int h) | |||
| 834 | RFALSE(buffer_dirty(new_bh) || | 831 | RFALSE(buffer_dirty(new_bh) || |
| 835 | buffer_journaled(new_bh) || | 832 | buffer_journaled(new_bh) || |
| 836 | buffer_journal_dirty(new_bh), | 833 | buffer_journal_dirty(new_bh), |
| 837 | "PAP-8140: journlaled or dirty buffer %b for the new block", | 834 | "PAP-8140: journaled or dirty buffer %b for the new block", |
| 838 | new_bh); | 835 | new_bh); |
| 839 | 836 | ||
| 840 | /* Put empty buffers into the array. */ | 837 | /* Put empty buffers into the array. */ |
| @@ -1022,7 +1019,11 @@ static int get_far_parent(struct tree_balance *tb, | |||
| 1022 | /* Check whether the common parent is locked. */ | 1019 | /* Check whether the common parent is locked. */ |
| 1023 | 1020 | ||
| 1024 | if (buffer_locked(*pcom_father)) { | 1021 | if (buffer_locked(*pcom_father)) { |
| 1022 | |||
| 1023 | /* Release the write lock while the buffer is busy */ | ||
| 1024 | reiserfs_write_unlock(tb->tb_sb); | ||
| 1025 | __wait_on_buffer(*pcom_father); | 1025 | __wait_on_buffer(*pcom_father); |
| 1026 | reiserfs_write_lock(tb->tb_sb); | ||
| 1026 | if (FILESYSTEM_CHANGED_TB(tb)) { | 1027 | if (FILESYSTEM_CHANGED_TB(tb)) { |
| 1027 | brelse(*pcom_father); | 1028 | brelse(*pcom_father); |
| 1028 | return REPEAT_SEARCH; | 1029 | return REPEAT_SEARCH; |
| @@ -1927,7 +1928,9 @@ static int get_direct_parent(struct tree_balance *tb, int h) | |||
| 1927 | return REPEAT_SEARCH; | 1928 | return REPEAT_SEARCH; |
| 1928 | 1929 | ||
| 1929 | if (buffer_locked(bh)) { | 1930 | if (buffer_locked(bh)) { |
| 1931 | reiserfs_write_unlock(tb->tb_sb); | ||
| 1930 | __wait_on_buffer(bh); | 1932 | __wait_on_buffer(bh); |
| 1933 | reiserfs_write_lock(tb->tb_sb); | ||
| 1931 | if (FILESYSTEM_CHANGED_TB(tb)) | 1934 | if (FILESYSTEM_CHANGED_TB(tb)) |
| 1932 | return REPEAT_SEARCH; | 1935 | return REPEAT_SEARCH; |
| 1933 | } | 1936 | } |
| @@ -1965,7 +1968,9 @@ static int get_neighbors(struct tree_balance *tb, int h) | |||
| 1965 | tb->FL[h]) ? tb->lkey[h] : B_NR_ITEMS(tb-> | 1968 | tb->FL[h]) ? tb->lkey[h] : B_NR_ITEMS(tb-> |
| 1966 | FL[h]); | 1969 | FL[h]); |
| 1967 | son_number = B_N_CHILD_NUM(tb->FL[h], child_position); | 1970 | son_number = B_N_CHILD_NUM(tb->FL[h], child_position); |
| 1971 | reiserfs_write_unlock(sb); | ||
| 1968 | bh = sb_bread(sb, son_number); | 1972 | bh = sb_bread(sb, son_number); |
| 1973 | reiserfs_write_lock(sb); | ||
| 1969 | if (!bh) | 1974 | if (!bh) |
| 1970 | return IO_ERROR; | 1975 | return IO_ERROR; |
| 1971 | if (FILESYSTEM_CHANGED_TB(tb)) { | 1976 | if (FILESYSTEM_CHANGED_TB(tb)) { |
| @@ -2003,7 +2008,9 @@ static int get_neighbors(struct tree_balance *tb, int h) | |||
| 2003 | child_position = | 2008 | child_position = |
| 2004 | (bh == tb->FR[h]) ? tb->rkey[h] + 1 : 0; | 2009 | (bh == tb->FR[h]) ? tb->rkey[h] + 1 : 0; |
| 2005 | son_number = B_N_CHILD_NUM(tb->FR[h], child_position); | 2010 | son_number = B_N_CHILD_NUM(tb->FR[h], child_position); |
| 2011 | reiserfs_write_unlock(sb); | ||
| 2006 | bh = sb_bread(sb, son_number); | 2012 | bh = sb_bread(sb, son_number); |
| 2013 | reiserfs_write_lock(sb); | ||
| 2007 | if (!bh) | 2014 | if (!bh) |
| 2008 | return IO_ERROR; | 2015 | return IO_ERROR; |
| 2009 | if (FILESYSTEM_CHANGED_TB(tb)) { | 2016 | if (FILESYSTEM_CHANGED_TB(tb)) { |
| @@ -2278,7 +2285,9 @@ static int wait_tb_buffers_until_unlocked(struct tree_balance *tb) | |||
| 2278 | REPEAT_SEARCH : CARRY_ON; | 2285 | REPEAT_SEARCH : CARRY_ON; |
| 2279 | } | 2286 | } |
| 2280 | #endif | 2287 | #endif |
| 2288 | reiserfs_write_unlock(tb->tb_sb); | ||
| 2281 | __wait_on_buffer(locked); | 2289 | __wait_on_buffer(locked); |
| 2290 | reiserfs_write_lock(tb->tb_sb); | ||
| 2282 | if (FILESYSTEM_CHANGED_TB(tb)) | 2291 | if (FILESYSTEM_CHANGED_TB(tb)) |
| 2283 | return REPEAT_SEARCH; | 2292 | return REPEAT_SEARCH; |
| 2284 | } | 2293 | } |
| @@ -2349,12 +2358,14 @@ int fix_nodes(int op_mode, struct tree_balance *tb, | |||
| 2349 | 2358 | ||
| 2350 | /* if it possible in indirect_to_direct conversion */ | 2359 | /* if it possible in indirect_to_direct conversion */ |
| 2351 | if (buffer_locked(tbS0)) { | 2360 | if (buffer_locked(tbS0)) { |
| 2361 | reiserfs_write_unlock(tb->tb_sb); | ||
| 2352 | __wait_on_buffer(tbS0); | 2362 | __wait_on_buffer(tbS0); |
| 2363 | reiserfs_write_lock(tb->tb_sb); | ||
| 2353 | if (FILESYSTEM_CHANGED_TB(tb)) | 2364 | if (FILESYSTEM_CHANGED_TB(tb)) |
| 2354 | return REPEAT_SEARCH; | 2365 | return REPEAT_SEARCH; |
| 2355 | } | 2366 | } |
| 2356 | #ifdef CONFIG_REISERFS_CHECK | 2367 | #ifdef CONFIG_REISERFS_CHECK |
| 2357 | if (cur_tb) { | 2368 | if (REISERFS_SB(tb->tb_sb)->cur_tb) { |
| 2358 | print_cur_tb("fix_nodes"); | 2369 | print_cur_tb("fix_nodes"); |
| 2359 | reiserfs_panic(tb->tb_sb, "PAP-8305", | 2370 | reiserfs_panic(tb->tb_sb, "PAP-8305", |
| 2360 | "there is pending do_balance"); | 2371 | "there is pending do_balance"); |
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index a14d6cd9eeda..3a28e7751b3c 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c | |||
| @@ -251,7 +251,6 @@ static int _get_block_create_0(struct inode *inode, sector_t block, | |||
| 251 | struct cpu_key key; | 251 | struct cpu_key key; |
| 252 | struct buffer_head *bh; | 252 | struct buffer_head *bh; |
| 253 | struct item_head *ih, tmp_ih; | 253 | struct item_head *ih, tmp_ih; |
| 254 | int fs_gen; | ||
| 255 | b_blocknr_t blocknr; | 254 | b_blocknr_t blocknr; |
| 256 | char *p = NULL; | 255 | char *p = NULL; |
| 257 | int chars; | 256 | int chars; |
| @@ -265,7 +264,6 @@ static int _get_block_create_0(struct inode *inode, sector_t block, | |||
| 265 | (loff_t) block * inode->i_sb->s_blocksize + 1, TYPE_ANY, | 264 | (loff_t) block * inode->i_sb->s_blocksize + 1, TYPE_ANY, |
| 266 | 3); | 265 | 3); |
| 267 | 266 | ||
| 268 | research: | ||
| 269 | result = search_for_position_by_key(inode->i_sb, &key, &path); | 267 | result = search_for_position_by_key(inode->i_sb, &key, &path); |
| 270 | if (result != POSITION_FOUND) { | 268 | if (result != POSITION_FOUND) { |
| 271 | pathrelse(&path); | 269 | pathrelse(&path); |
| @@ -340,7 +338,6 @@ static int _get_block_create_0(struct inode *inode, sector_t block, | |||
| 340 | } | 338 | } |
| 341 | // read file tail into part of page | 339 | // read file tail into part of page |
| 342 | offset = (cpu_key_k_offset(&key) - 1) & (PAGE_CACHE_SIZE - 1); | 340 | offset = (cpu_key_k_offset(&key) - 1) & (PAGE_CACHE_SIZE - 1); |
| 343 | fs_gen = get_generation(inode->i_sb); | ||
| 344 | copy_item_head(&tmp_ih, ih); | 341 | copy_item_head(&tmp_ih, ih); |
| 345 | 342 | ||
| 346 | /* we only want to kmap if we are reading the tail into the page. | 343 | /* we only want to kmap if we are reading the tail into the page. |
| @@ -348,13 +345,9 @@ static int _get_block_create_0(struct inode *inode, sector_t block, | |||
| 348 | ** sure we need to. But, this means the item might move if | 345 | ** sure we need to. But, this means the item might move if |
| 349 | ** kmap schedules | 346 | ** kmap schedules |
| 350 | */ | 347 | */ |
| 351 | if (!p) { | 348 | if (!p) |
| 352 | p = (char *)kmap(bh_result->b_page); | 349 | p = (char *)kmap(bh_result->b_page); |
| 353 | if (fs_changed(fs_gen, inode->i_sb) | 350 | |
| 354 | && item_moved(&tmp_ih, &path)) { | ||
| 355 | goto research; | ||
| 356 | } | ||
| 357 | } | ||
| 358 | p += offset; | 351 | p += offset; |
| 359 | memset(p, 0, inode->i_sb->s_blocksize); | 352 | memset(p, 0, inode->i_sb->s_blocksize); |
| 360 | do { | 353 | do { |
| @@ -489,10 +482,14 @@ static int reiserfs_get_blocks_direct_io(struct inode *inode, | |||
| 489 | disappeared */ | 482 | disappeared */ |
| 490 | if (REISERFS_I(inode)->i_flags & i_pack_on_close_mask) { | 483 | if (REISERFS_I(inode)->i_flags & i_pack_on_close_mask) { |
| 491 | int err; | 484 | int err; |
| 492 | lock_kernel(); | 485 | |
| 486 | reiserfs_write_lock(inode->i_sb); | ||
| 487 | |||
| 493 | err = reiserfs_commit_for_inode(inode); | 488 | err = reiserfs_commit_for_inode(inode); |
| 494 | REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask; | 489 | REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask; |
| 495 | unlock_kernel(); | 490 | |
| 491 | reiserfs_write_unlock(inode->i_sb); | ||
| 492 | |||
| 496 | if (err < 0) | 493 | if (err < 0) |
| 497 | ret = err; | 494 | ret = err; |
| 498 | } | 495 | } |
| @@ -601,6 +598,7 @@ int reiserfs_get_block(struct inode *inode, sector_t block, | |||
| 601 | __le32 *item; | 598 | __le32 *item; |
| 602 | int done; | 599 | int done; |
| 603 | int fs_gen; | 600 | int fs_gen; |
| 601 | int lock_depth; | ||
| 604 | struct reiserfs_transaction_handle *th = NULL; | 602 | struct reiserfs_transaction_handle *th = NULL; |
| 605 | /* space reserved in transaction batch: | 603 | /* space reserved in transaction batch: |
| 606 | . 3 balancings in direct->indirect conversion | 604 | . 3 balancings in direct->indirect conversion |
| @@ -616,12 +614,11 @@ int reiserfs_get_block(struct inode *inode, sector_t block, | |||
| 616 | loff_t new_offset = | 614 | loff_t new_offset = |
| 617 | (((loff_t) block) << inode->i_sb->s_blocksize_bits) + 1; | 615 | (((loff_t) block) << inode->i_sb->s_blocksize_bits) + 1; |
| 618 | 616 | ||
| 619 | /* bad.... */ | 617 | lock_depth = reiserfs_write_lock_once(inode->i_sb); |
| 620 | reiserfs_write_lock(inode->i_sb); | ||
| 621 | version = get_inode_item_key_version(inode); | 618 | version = get_inode_item_key_version(inode); |
| 622 | 619 | ||
| 623 | if (!file_capable(inode, block)) { | 620 | if (!file_capable(inode, block)) { |
| 624 | reiserfs_write_unlock(inode->i_sb); | 621 | reiserfs_write_unlock_once(inode->i_sb, lock_depth); |
| 625 | return -EFBIG; | 622 | return -EFBIG; |
| 626 | } | 623 | } |
| 627 | 624 | ||
| @@ -633,7 +630,7 @@ int reiserfs_get_block(struct inode *inode, sector_t block, | |||
| 633 | /* find number of block-th logical block of the file */ | 630 | /* find number of block-th logical block of the file */ |
| 634 | ret = _get_block_create_0(inode, block, bh_result, | 631 | ret = _get_block_create_0(inode, block, bh_result, |
| 635 | create | GET_BLOCK_READ_DIRECT); | 632 | create | GET_BLOCK_READ_DIRECT); |
| 636 | reiserfs_write_unlock(inode->i_sb); | 633 | reiserfs_write_unlock_once(inode->i_sb, lock_depth); |
| 637 | return ret; | 634 | return ret; |
| 638 | } | 635 | } |
| 639 | /* | 636 | /* |
| @@ -751,7 +748,7 @@ int reiserfs_get_block(struct inode *inode, sector_t block, | |||
| 751 | if (!dangle && th) | 748 | if (!dangle && th) |
| 752 | retval = reiserfs_end_persistent_transaction(th); | 749 | retval = reiserfs_end_persistent_transaction(th); |
| 753 | 750 | ||
| 754 | reiserfs_write_unlock(inode->i_sb); | 751 | reiserfs_write_unlock_once(inode->i_sb, lock_depth); |
| 755 | 752 | ||
| 756 | /* the item was found, so new blocks were not added to the file | 753 | /* the item was found, so new blocks were not added to the file |
| 757 | ** there is no need to make sure the inode is updated with this | 754 | ** there is no need to make sure the inode is updated with this |
| @@ -935,7 +932,7 @@ int reiserfs_get_block(struct inode *inode, sector_t block, | |||
| 935 | if (blocks_needed == 1) { | 932 | if (blocks_needed == 1) { |
| 936 | un = &unf_single; | 933 | un = &unf_single; |
| 937 | } else { | 934 | } else { |
| 938 | un = kzalloc(min(blocks_needed, max_to_insert) * UNFM_P_SIZE, GFP_ATOMIC); // We need to avoid scheduling. | 935 | un = kzalloc(min(blocks_needed, max_to_insert) * UNFM_P_SIZE, GFP_NOFS); |
| 939 | if (!un) { | 936 | if (!un) { |
| 940 | un = &unf_single; | 937 | un = &unf_single; |
| 941 | blocks_needed = 1; | 938 | blocks_needed = 1; |
| @@ -997,10 +994,16 @@ int reiserfs_get_block(struct inode *inode, sector_t block, | |||
| 997 | if (retval) | 994 | if (retval) |
| 998 | goto failure; | 995 | goto failure; |
| 999 | } | 996 | } |
| 1000 | /* inserting indirect pointers for a hole can take a | 997 | /* |
| 1001 | ** long time. reschedule if needed | 998 | * inserting indirect pointers for a hole can take a |
| 999 | * long time. reschedule if needed and also release the write | ||
| 1000 | * lock for others. | ||
| 1002 | */ | 1001 | */ |
| 1003 | cond_resched(); | 1002 | if (need_resched()) { |
| 1003 | reiserfs_write_unlock_once(inode->i_sb, lock_depth); | ||
| 1004 | schedule(); | ||
| 1005 | lock_depth = reiserfs_write_lock_once(inode->i_sb); | ||
| 1006 | } | ||
| 1004 | 1007 | ||
| 1005 | retval = search_for_position_by_key(inode->i_sb, &key, &path); | 1008 | retval = search_for_position_by_key(inode->i_sb, &key, &path); |
| 1006 | if (retval == IO_ERROR) { | 1009 | if (retval == IO_ERROR) { |
| @@ -1035,7 +1038,7 @@ int reiserfs_get_block(struct inode *inode, sector_t block, | |||
| 1035 | retval = err; | 1038 | retval = err; |
| 1036 | } | 1039 | } |
| 1037 | 1040 | ||
| 1038 | reiserfs_write_unlock(inode->i_sb); | 1041 | reiserfs_write_unlock_once(inode->i_sb, lock_depth); |
| 1039 | reiserfs_check_path(&path); | 1042 | reiserfs_check_path(&path); |
| 1040 | return retval; | 1043 | return retval; |
| 1041 | } | 1044 | } |
| @@ -2072,8 +2075,9 @@ int reiserfs_truncate_file(struct inode *inode, int update_timestamps) | |||
| 2072 | int error; | 2075 | int error; |
| 2073 | struct buffer_head *bh = NULL; | 2076 | struct buffer_head *bh = NULL; |
| 2074 | int err2; | 2077 | int err2; |
| 2078 | int lock_depth; | ||
| 2075 | 2079 | ||
| 2076 | reiserfs_write_lock(inode->i_sb); | 2080 | lock_depth = reiserfs_write_lock_once(inode->i_sb); |
| 2077 | 2081 | ||
| 2078 | if (inode->i_size > 0) { | 2082 | if (inode->i_size > 0) { |
| 2079 | error = grab_tail_page(inode, &page, &bh); | 2083 | error = grab_tail_page(inode, &page, &bh); |
| @@ -2142,14 +2146,17 @@ int reiserfs_truncate_file(struct inode *inode, int update_timestamps) | |||
| 2142 | page_cache_release(page); | 2146 | page_cache_release(page); |
| 2143 | } | 2147 | } |
| 2144 | 2148 | ||
| 2145 | reiserfs_write_unlock(inode->i_sb); | 2149 | reiserfs_write_unlock_once(inode->i_sb, lock_depth); |
| 2150 | |||
| 2146 | return 0; | 2151 | return 0; |
| 2147 | out: | 2152 | out: |
| 2148 | if (page) { | 2153 | if (page) { |
| 2149 | unlock_page(page); | 2154 | unlock_page(page); |
| 2150 | page_cache_release(page); | 2155 | page_cache_release(page); |
| 2151 | } | 2156 | } |
| 2152 | reiserfs_write_unlock(inode->i_sb); | 2157 | |
| 2158 | reiserfs_write_unlock_once(inode->i_sb, lock_depth); | ||
| 2159 | |||
| 2153 | return error; | 2160 | return error; |
| 2154 | } | 2161 | } |
| 2155 | 2162 | ||
| @@ -2608,7 +2615,10 @@ int reiserfs_prepare_write(struct file *f, struct page *page, | |||
| 2608 | int ret; | 2615 | int ret; |
| 2609 | int old_ref = 0; | 2616 | int old_ref = 0; |
| 2610 | 2617 | ||
| 2618 | reiserfs_write_unlock(inode->i_sb); | ||
| 2611 | reiserfs_wait_on_write_block(inode->i_sb); | 2619 | reiserfs_wait_on_write_block(inode->i_sb); |
| 2620 | reiserfs_write_lock(inode->i_sb); | ||
| 2621 | |||
| 2612 | fix_tail_page_for_writing(page); | 2622 | fix_tail_page_for_writing(page); |
| 2613 | if (reiserfs_transaction_running(inode->i_sb)) { | 2623 | if (reiserfs_transaction_running(inode->i_sb)) { |
| 2614 | struct reiserfs_transaction_handle *th; | 2624 | struct reiserfs_transaction_handle *th; |
| @@ -2664,6 +2674,8 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping, | |||
| 2664 | int update_sd = 0; | 2674 | int update_sd = 0; |
| 2665 | struct reiserfs_transaction_handle *th; | 2675 | struct reiserfs_transaction_handle *th; |
| 2666 | unsigned start; | 2676 | unsigned start; |
| 2677 | int lock_depth = 0; | ||
| 2678 | bool locked = false; | ||
| 2667 | 2679 | ||
| 2668 | if ((unsigned long)fsdata & AOP_FLAG_CONT_EXPAND) | 2680 | if ((unsigned long)fsdata & AOP_FLAG_CONT_EXPAND) |
| 2669 | pos ++; | 2681 | pos ++; |
| @@ -2690,9 +2702,11 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping, | |||
| 2690 | ** to do the i_size updates here. | 2702 | ** to do the i_size updates here. |
| 2691 | */ | 2703 | */ |
| 2692 | pos += copied; | 2704 | pos += copied; |
| 2705 | |||
| 2693 | if (pos > inode->i_size) { | 2706 | if (pos > inode->i_size) { |
| 2694 | struct reiserfs_transaction_handle myth; | 2707 | struct reiserfs_transaction_handle myth; |
| 2695 | reiserfs_write_lock(inode->i_sb); | 2708 | lock_depth = reiserfs_write_lock_once(inode->i_sb); |
| 2709 | locked = true; | ||
| 2696 | /* If the file have grown beyond the border where it | 2710 | /* If the file have grown beyond the border where it |
| 2697 | can have a tail, unmark it as needing a tail | 2711 | can have a tail, unmark it as needing a tail |
| 2698 | packing */ | 2712 | packing */ |
| @@ -2703,10 +2717,9 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping, | |||
| 2703 | REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask; | 2717 | REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask; |
| 2704 | 2718 | ||
| 2705 | ret = journal_begin(&myth, inode->i_sb, 1); | 2719 | ret = journal_begin(&myth, inode->i_sb, 1); |
| 2706 | if (ret) { | 2720 | if (ret) |
| 2707 | reiserfs_write_unlock(inode->i_sb); | ||
| 2708 | goto journal_error; | 2721 | goto journal_error; |
| 2709 | } | 2722 | |
| 2710 | reiserfs_update_inode_transaction(inode); | 2723 | reiserfs_update_inode_transaction(inode); |
| 2711 | inode->i_size = pos; | 2724 | inode->i_size = pos; |
| 2712 | /* | 2725 | /* |
| @@ -2718,34 +2731,36 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping, | |||
| 2718 | reiserfs_update_sd(&myth, inode); | 2731 | reiserfs_update_sd(&myth, inode); |
| 2719 | update_sd = 1; | 2732 | update_sd = 1; |
| 2720 | ret = journal_end(&myth, inode->i_sb, 1); | 2733 | ret = journal_end(&myth, inode->i_sb, 1); |
| 2721 | reiserfs_write_unlock(inode->i_sb); | ||
| 2722 | if (ret) | 2734 | if (ret) |
| 2723 | goto journal_error; | 2735 | goto journal_error; |
| 2724 | } | 2736 | } |
| 2725 | if (th) { | 2737 | if (th) { |
| 2726 | reiserfs_write_lock(inode->i_sb); | 2738 | if (!locked) { |
| 2739 | lock_depth = reiserfs_write_lock_once(inode->i_sb); | ||
| 2740 | locked = true; | ||
| 2741 | } | ||
| 2727 | if (!update_sd) | 2742 | if (!update_sd) |
| 2728 | mark_inode_dirty(inode); | 2743 | mark_inode_dirty(inode); |
| 2729 | ret = reiserfs_end_persistent_transaction(th); | 2744 | ret = reiserfs_end_persistent_transaction(th); |
| 2730 | reiserfs_write_unlock(inode->i_sb); | ||
| 2731 | if (ret) | 2745 | if (ret) |
| 2732 | goto out; | 2746 | goto out; |
| 2733 | } | 2747 | } |
| 2734 | 2748 | ||
| 2735 | out: | 2749 | out: |
| 2750 | if (locked) | ||
| 2751 | reiserfs_write_unlock_once(inode->i_sb, lock_depth); | ||
| 2736 | unlock_page(page); | 2752 | unlock_page(page); |
| 2737 | page_cache_release(page); | 2753 | page_cache_release(page); |
| 2738 | return ret == 0 ? copied : ret; | 2754 | return ret == 0 ? copied : ret; |
| 2739 | 2755 | ||
| 2740 | journal_error: | 2756 | journal_error: |
| 2757 | reiserfs_write_unlock_once(inode->i_sb, lock_depth); | ||
| 2758 | locked = false; | ||
| 2741 | if (th) { | 2759 | if (th) { |
| 2742 | reiserfs_write_lock(inode->i_sb); | ||
| 2743 | if (!update_sd) | 2760 | if (!update_sd) |
| 2744 | reiserfs_update_sd(th, inode); | 2761 | reiserfs_update_sd(th, inode); |
| 2745 | ret = reiserfs_end_persistent_transaction(th); | 2762 | ret = reiserfs_end_persistent_transaction(th); |
| 2746 | reiserfs_write_unlock(inode->i_sb); | ||
| 2747 | } | 2763 | } |
| 2748 | |||
| 2749 | goto out; | 2764 | goto out; |
| 2750 | } | 2765 | } |
| 2751 | 2766 | ||
| @@ -2758,7 +2773,10 @@ int reiserfs_commit_write(struct file *f, struct page *page, | |||
| 2758 | int update_sd = 0; | 2773 | int update_sd = 0; |
| 2759 | struct reiserfs_transaction_handle *th = NULL; | 2774 | struct reiserfs_transaction_handle *th = NULL; |
| 2760 | 2775 | ||
| 2776 | reiserfs_write_unlock(inode->i_sb); | ||
| 2761 | reiserfs_wait_on_write_block(inode->i_sb); | 2777 | reiserfs_wait_on_write_block(inode->i_sb); |
| 2778 | reiserfs_write_lock(inode->i_sb); | ||
| 2779 | |||
| 2762 | if (reiserfs_transaction_running(inode->i_sb)) { | 2780 | if (reiserfs_transaction_running(inode->i_sb)) { |
| 2763 | th = current->journal_info; | 2781 | th = current->journal_info; |
| 2764 | } | 2782 | } |
| @@ -2770,7 +2788,6 @@ int reiserfs_commit_write(struct file *f, struct page *page, | |||
| 2770 | */ | 2788 | */ |
| 2771 | if (pos > inode->i_size) { | 2789 | if (pos > inode->i_size) { |
| 2772 | struct reiserfs_transaction_handle myth; | 2790 | struct reiserfs_transaction_handle myth; |
| 2773 | reiserfs_write_lock(inode->i_sb); | ||
| 2774 | /* If the file have grown beyond the border where it | 2791 | /* If the file have grown beyond the border where it |
| 2775 | can have a tail, unmark it as needing a tail | 2792 | can have a tail, unmark it as needing a tail |
| 2776 | packing */ | 2793 | packing */ |
| @@ -2781,10 +2798,9 @@ int reiserfs_commit_write(struct file *f, struct page *page, | |||
| 2781 | REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask; | 2798 | REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask; |
| 2782 | 2799 | ||
| 2783 | ret = journal_begin(&myth, inode->i_sb, 1); | 2800 | ret = journal_begin(&myth, inode->i_sb, 1); |
| 2784 | if (ret) { | 2801 | if (ret) |
| 2785 | reiserfs_write_unlock(inode->i_sb); | ||
| 2786 | goto journal_error; | 2802 | goto journal_error; |
| 2787 | } | 2803 | |
| 2788 | reiserfs_update_inode_transaction(inode); | 2804 | reiserfs_update_inode_transaction(inode); |
| 2789 | inode->i_size = pos; | 2805 | inode->i_size = pos; |
| 2790 | /* | 2806 | /* |
| @@ -2796,16 +2812,13 @@ int reiserfs_commit_write(struct file *f, struct page *page, | |||
| 2796 | reiserfs_update_sd(&myth, inode); | 2812 | reiserfs_update_sd(&myth, inode); |
| 2797 | update_sd = 1; | 2813 | update_sd = 1; |
| 2798 | ret = journal_end(&myth, inode->i_sb, 1); | 2814 | ret = journal_end(&myth, inode->i_sb, 1); |
| 2799 | reiserfs_write_unlock(inode->i_sb); | ||
| 2800 | if (ret) | 2815 | if (ret) |
| 2801 | goto journal_error; | 2816 | goto journal_error; |
| 2802 | } | 2817 | } |
| 2803 | if (th) { | 2818 | if (th) { |
| 2804 | reiserfs_write_lock(inode->i_sb); | ||
| 2805 | if (!update_sd) | 2819 | if (!update_sd) |
| 2806 | mark_inode_dirty(inode); | 2820 | mark_inode_dirty(inode); |
| 2807 | ret = reiserfs_end_persistent_transaction(th); | 2821 | ret = reiserfs_end_persistent_transaction(th); |
| 2808 | reiserfs_write_unlock(inode->i_sb); | ||
| 2809 | if (ret) | 2822 | if (ret) |
| 2810 | goto out; | 2823 | goto out; |
| 2811 | } | 2824 | } |
| @@ -2815,11 +2828,9 @@ int reiserfs_commit_write(struct file *f, struct page *page, | |||
| 2815 | 2828 | ||
| 2816 | journal_error: | 2829 | journal_error: |
| 2817 | if (th) { | 2830 | if (th) { |
| 2818 | reiserfs_write_lock(inode->i_sb); | ||
| 2819 | if (!update_sd) | 2831 | if (!update_sd) |
| 2820 | reiserfs_update_sd(th, inode); | 2832 | reiserfs_update_sd(th, inode); |
| 2821 | ret = reiserfs_end_persistent_transaction(th); | 2833 | ret = reiserfs_end_persistent_transaction(th); |
| 2822 | reiserfs_write_unlock(inode->i_sb); | ||
| 2823 | } | 2834 | } |
| 2824 | 2835 | ||
| 2825 | return ret; | 2836 | return ret; |
diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c index 0ccc3fdda7bf..ace77451ceb1 100644 --- a/fs/reiserfs/ioctl.c +++ b/fs/reiserfs/ioctl.c | |||
| @@ -13,44 +13,52 @@ | |||
| 13 | #include <linux/compat.h> | 13 | #include <linux/compat.h> |
| 14 | 14 | ||
| 15 | /* | 15 | /* |
| 16 | ** reiserfs_ioctl - handler for ioctl for inode | 16 | * reiserfs_ioctl - handler for ioctl for inode |
| 17 | ** supported commands: | 17 | * supported commands: |
| 18 | ** 1) REISERFS_IOC_UNPACK - try to unpack tail from direct item into indirect | 18 | * 1) REISERFS_IOC_UNPACK - try to unpack tail from direct item into indirect |
| 19 | ** and prevent packing file (argument arg has to be non-zero) | 19 | * and prevent packing file (argument arg has to be non-zero) |
| 20 | ** 2) REISERFS_IOC_[GS]ETFLAGS, REISERFS_IOC_[GS]ETVERSION | 20 | * 2) REISERFS_IOC_[GS]ETFLAGS, REISERFS_IOC_[GS]ETVERSION |
| 21 | ** 3) That's all for a while ... | 21 | * 3) That's all for a while ... |
| 22 | */ | 22 | */ |
| 23 | int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | 23 | long reiserfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
| 24 | unsigned long arg) | ||
| 25 | { | 24 | { |
| 25 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
| 26 | unsigned int flags; | 26 | unsigned int flags; |
| 27 | int err = 0; | 27 | int err = 0; |
| 28 | 28 | ||
| 29 | reiserfs_write_lock(inode->i_sb); | ||
| 30 | |||
| 29 | switch (cmd) { | 31 | switch (cmd) { |
| 30 | case REISERFS_IOC_UNPACK: | 32 | case REISERFS_IOC_UNPACK: |
| 31 | if (S_ISREG(inode->i_mode)) { | 33 | if (S_ISREG(inode->i_mode)) { |
| 32 | if (arg) | 34 | if (arg) |
| 33 | return reiserfs_unpack(inode, filp); | 35 | err = reiserfs_unpack(inode, filp); |
| 34 | else | ||
| 35 | return 0; | ||
| 36 | } else | 36 | } else |
| 37 | return -ENOTTY; | 37 | err = -ENOTTY; |
| 38 | /* following two cases are taken from fs/ext2/ioctl.c by Remy | 38 | break; |
| 39 | Card (card@masi.ibp.fr) */ | 39 | /* |
| 40 | * following two cases are taken from fs/ext2/ioctl.c by Remy | ||
| 41 | * Card (card@masi.ibp.fr) | ||
| 42 | */ | ||
| 40 | case REISERFS_IOC_GETFLAGS: | 43 | case REISERFS_IOC_GETFLAGS: |
| 41 | if (!reiserfs_attrs(inode->i_sb)) | 44 | if (!reiserfs_attrs(inode->i_sb)) { |
| 42 | return -ENOTTY; | 45 | err = -ENOTTY; |
| 46 | break; | ||
| 47 | } | ||
| 43 | 48 | ||
| 44 | flags = REISERFS_I(inode)->i_attrs; | 49 | flags = REISERFS_I(inode)->i_attrs; |
| 45 | i_attrs_to_sd_attrs(inode, (__u16 *) & flags); | 50 | i_attrs_to_sd_attrs(inode, (__u16 *) & flags); |
| 46 | return put_user(flags, (int __user *)arg); | 51 | err = put_user(flags, (int __user *)arg); |
| 52 | break; | ||
| 47 | case REISERFS_IOC_SETFLAGS:{ | 53 | case REISERFS_IOC_SETFLAGS:{ |
| 48 | if (!reiserfs_attrs(inode->i_sb)) | 54 | if (!reiserfs_attrs(inode->i_sb)) { |
| 49 | return -ENOTTY; | 55 | err = -ENOTTY; |
| 56 | break; | ||
| 57 | } | ||
| 50 | 58 | ||
| 51 | err = mnt_want_write(filp->f_path.mnt); | 59 | err = mnt_want_write(filp->f_path.mnt); |
| 52 | if (err) | 60 | if (err) |
| 53 | return err; | 61 | break; |
| 54 | 62 | ||
| 55 | if (!is_owner_or_cap(inode)) { | 63 | if (!is_owner_or_cap(inode)) { |
| 56 | err = -EPERM; | 64 | err = -EPERM; |
| @@ -90,16 +98,18 @@ int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | |||
| 90 | mark_inode_dirty(inode); | 98 | mark_inode_dirty(inode); |
| 91 | setflags_out: | 99 | setflags_out: |
| 92 | mnt_drop_write(filp->f_path.mnt); | 100 | mnt_drop_write(filp->f_path.mnt); |
| 93 | return err; | 101 | break; |
| 94 | } | 102 | } |
| 95 | case REISERFS_IOC_GETVERSION: | 103 | case REISERFS_IOC_GETVERSION: |
| 96 | return put_user(inode->i_generation, (int __user *)arg); | 104 | err = put_user(inode->i_generation, (int __user *)arg); |
| 105 | break; | ||
| 97 | case REISERFS_IOC_SETVERSION: | 106 | case REISERFS_IOC_SETVERSION: |
| 98 | if (!is_owner_or_cap(inode)) | 107 | if (!is_owner_or_cap(inode)) |
| 99 | return -EPERM; | 108 | err = -EPERM; |
| 109 | break; | ||
| 100 | err = mnt_want_write(filp->f_path.mnt); | 110 | err = mnt_want_write(filp->f_path.mnt); |
| 101 | if (err) | 111 | if (err) |
| 102 | return err; | 112 | break; |
| 103 | if (get_user(inode->i_generation, (int __user *)arg)) { | 113 | if (get_user(inode->i_generation, (int __user *)arg)) { |
| 104 | err = -EFAULT; | 114 | err = -EFAULT; |
| 105 | goto setversion_out; | 115 | goto setversion_out; |
| @@ -108,19 +118,20 @@ setflags_out: | |||
| 108 | mark_inode_dirty(inode); | 118 | mark_inode_dirty(inode); |
| 109 | setversion_out: | 119 | setversion_out: |
| 110 | mnt_drop_write(filp->f_path.mnt); | 120 | mnt_drop_write(filp->f_path.mnt); |
| 111 | return err; | 121 | break; |
| 112 | default: | 122 | default: |
| 113 | return -ENOTTY; | 123 | err = -ENOTTY; |
| 114 | } | 124 | } |
| 125 | |||
| 126 | reiserfs_write_unlock(inode->i_sb); | ||
| 127 | |||
| 128 | return err; | ||
| 115 | } | 129 | } |
| 116 | 130 | ||
| 117 | #ifdef CONFIG_COMPAT | 131 | #ifdef CONFIG_COMPAT |
| 118 | long reiserfs_compat_ioctl(struct file *file, unsigned int cmd, | 132 | long reiserfs_compat_ioctl(struct file *file, unsigned int cmd, |
| 119 | unsigned long arg) | 133 | unsigned long arg) |
| 120 | { | 134 | { |
| 121 | struct inode *inode = file->f_path.dentry->d_inode; | ||
| 122 | int ret; | ||
| 123 | |||
| 124 | /* These are just misnamed, they actually get/put from/to user an int */ | 135 | /* These are just misnamed, they actually get/put from/to user an int */ |
| 125 | switch (cmd) { | 136 | switch (cmd) { |
| 126 | case REISERFS_IOC32_UNPACK: | 137 | case REISERFS_IOC32_UNPACK: |
| @@ -141,10 +152,8 @@ long reiserfs_compat_ioctl(struct file *file, unsigned int cmd, | |||
| 141 | default: | 152 | default: |
| 142 | return -ENOIOCTLCMD; | 153 | return -ENOIOCTLCMD; |
| 143 | } | 154 | } |
| 144 | lock_kernel(); | 155 | |
| 145 | ret = reiserfs_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg)); | 156 | return reiserfs_ioctl(file, cmd, (unsigned long) compat_ptr(arg)); |
| 146 | unlock_kernel(); | ||
| 147 | return ret; | ||
| 148 | } | 157 | } |
| 149 | #endif | 158 | #endif |
| 150 | 159 | ||
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index 90622200b39c..2f8a7e7b8dab 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c | |||
| @@ -429,21 +429,6 @@ static void clear_prepared_bits(struct buffer_head *bh) | |||
| 429 | clear_buffer_journal_restore_dirty(bh); | 429 | clear_buffer_journal_restore_dirty(bh); |
| 430 | } | 430 | } |
| 431 | 431 | ||
| 432 | /* utility function to force a BUG if it is called without the big | ||
| 433 | ** kernel lock held. caller is the string printed just before calling BUG() | ||
| 434 | */ | ||
| 435 | void reiserfs_check_lock_depth(struct super_block *sb, char *caller) | ||
| 436 | { | ||
| 437 | #ifdef CONFIG_SMP | ||
| 438 | if (current->lock_depth < 0) { | ||
| 439 | reiserfs_panic(sb, "journal-1", "%s called without kernel " | ||
| 440 | "lock held", caller); | ||
| 441 | } | ||
| 442 | #else | ||
| 443 | ; | ||
| 444 | #endif | ||
| 445 | } | ||
| 446 | |||
| 447 | /* return a cnode with same dev, block number and size in table, or null if not found */ | 432 | /* return a cnode with same dev, block number and size in table, or null if not found */ |
| 448 | static inline struct reiserfs_journal_cnode *get_journal_hash_dev(struct | 433 | static inline struct reiserfs_journal_cnode *get_journal_hash_dev(struct |
| 449 | super_block | 434 | super_block |
| @@ -556,7 +541,8 @@ static inline void insert_journal_hash(struct reiserfs_journal_cnode **table, | |||
| 556 | static inline void lock_journal(struct super_block *sb) | 541 | static inline void lock_journal(struct super_block *sb) |
| 557 | { | 542 | { |
| 558 | PROC_INFO_INC(sb, journal.lock_journal); | 543 | PROC_INFO_INC(sb, journal.lock_journal); |
| 559 | mutex_lock(&SB_JOURNAL(sb)->j_mutex); | 544 | |
| 545 | reiserfs_mutex_lock_safe(&SB_JOURNAL(sb)->j_mutex, sb); | ||
| 560 | } | 546 | } |
| 561 | 547 | ||
| 562 | /* unlock the current transaction */ | 548 | /* unlock the current transaction */ |
| @@ -708,7 +694,9 @@ static void check_barrier_completion(struct super_block *s, | |||
| 708 | disable_barrier(s); | 694 | disable_barrier(s); |
| 709 | set_buffer_uptodate(bh); | 695 | set_buffer_uptodate(bh); |
| 710 | set_buffer_dirty(bh); | 696 | set_buffer_dirty(bh); |
| 697 | reiserfs_write_unlock(s); | ||
| 711 | sync_dirty_buffer(bh); | 698 | sync_dirty_buffer(bh); |
| 699 | reiserfs_write_lock(s); | ||
| 712 | } | 700 | } |
| 713 | } | 701 | } |
| 714 | 702 | ||
| @@ -996,8 +984,13 @@ static int reiserfs_async_progress_wait(struct super_block *s) | |||
| 996 | { | 984 | { |
| 997 | DEFINE_WAIT(wait); | 985 | DEFINE_WAIT(wait); |
| 998 | struct reiserfs_journal *j = SB_JOURNAL(s); | 986 | struct reiserfs_journal *j = SB_JOURNAL(s); |
| 999 | if (atomic_read(&j->j_async_throttle)) | 987 | |
| 988 | if (atomic_read(&j->j_async_throttle)) { | ||
| 989 | reiserfs_write_unlock(s); | ||
| 1000 | congestion_wait(BLK_RW_ASYNC, HZ / 10); | 990 | congestion_wait(BLK_RW_ASYNC, HZ / 10); |
| 991 | reiserfs_write_lock(s); | ||
| 992 | } | ||
| 993 | |||
| 1001 | return 0; | 994 | return 0; |
| 1002 | } | 995 | } |
| 1003 | 996 | ||
| @@ -1043,7 +1036,8 @@ static int flush_commit_list(struct super_block *s, | |||
| 1043 | } | 1036 | } |
| 1044 | 1037 | ||
| 1045 | /* make sure nobody is trying to flush this one at the same time */ | 1038 | /* make sure nobody is trying to flush this one at the same time */ |
| 1046 | mutex_lock(&jl->j_commit_mutex); | 1039 | reiserfs_mutex_lock_safe(&jl->j_commit_mutex, s); |
| 1040 | |||
| 1047 | if (!journal_list_still_alive(s, trans_id)) { | 1041 | if (!journal_list_still_alive(s, trans_id)) { |
| 1048 | mutex_unlock(&jl->j_commit_mutex); | 1042 | mutex_unlock(&jl->j_commit_mutex); |
| 1049 | goto put_jl; | 1043 | goto put_jl; |
| @@ -1061,12 +1055,17 @@ static int flush_commit_list(struct super_block *s, | |||
| 1061 | 1055 | ||
| 1062 | if (!list_empty(&jl->j_bh_list)) { | 1056 | if (!list_empty(&jl->j_bh_list)) { |
| 1063 | int ret; | 1057 | int ret; |
| 1064 | unlock_kernel(); | 1058 | |
| 1059 | /* | ||
| 1060 | * We might sleep in numerous places inside | ||
| 1061 | * write_ordered_buffers. Relax the write lock. | ||
| 1062 | */ | ||
| 1063 | reiserfs_write_unlock(s); | ||
| 1065 | ret = write_ordered_buffers(&journal->j_dirty_buffers_lock, | 1064 | ret = write_ordered_buffers(&journal->j_dirty_buffers_lock, |
| 1066 | journal, jl, &jl->j_bh_list); | 1065 | journal, jl, &jl->j_bh_list); |
| 1067 | if (ret < 0 && retval == 0) | 1066 | if (ret < 0 && retval == 0) |
| 1068 | retval = ret; | 1067 | retval = ret; |
| 1069 | lock_kernel(); | 1068 | reiserfs_write_lock(s); |
| 1070 | } | 1069 | } |
| 1071 | BUG_ON(!list_empty(&jl->j_bh_list)); | 1070 | BUG_ON(!list_empty(&jl->j_bh_list)); |
| 1072 | /* | 1071 | /* |
| @@ -1085,8 +1084,11 @@ static int flush_commit_list(struct super_block *s, | |||
| 1085 | SB_ONDISK_JOURNAL_SIZE(s); | 1084 | SB_ONDISK_JOURNAL_SIZE(s); |
| 1086 | tbh = journal_find_get_block(s, bn); | 1085 | tbh = journal_find_get_block(s, bn); |
| 1087 | if (tbh) { | 1086 | if (tbh) { |
| 1088 | if (buffer_dirty(tbh)) | 1087 | if (buffer_dirty(tbh)) { |
| 1089 | ll_rw_block(WRITE, 1, &tbh) ; | 1088 | reiserfs_write_unlock(s); |
| 1089 | ll_rw_block(WRITE, 1, &tbh); | ||
| 1090 | reiserfs_write_lock(s); | ||
| 1091 | } | ||
| 1090 | put_bh(tbh) ; | 1092 | put_bh(tbh) ; |
| 1091 | } | 1093 | } |
| 1092 | } | 1094 | } |
| @@ -1114,12 +1116,19 @@ static int flush_commit_list(struct super_block *s, | |||
| 1114 | bn = SB_ONDISK_JOURNAL_1st_BLOCK(s) + | 1116 | bn = SB_ONDISK_JOURNAL_1st_BLOCK(s) + |
| 1115 | (jl->j_start + i) % SB_ONDISK_JOURNAL_SIZE(s); | 1117 | (jl->j_start + i) % SB_ONDISK_JOURNAL_SIZE(s); |
| 1116 | tbh = journal_find_get_block(s, bn); | 1118 | tbh = journal_find_get_block(s, bn); |
| 1119 | |||
| 1120 | reiserfs_write_unlock(s); | ||
| 1117 | wait_on_buffer(tbh); | 1121 | wait_on_buffer(tbh); |
| 1122 | reiserfs_write_lock(s); | ||
| 1118 | // since we're using ll_rw_blk above, it might have skipped over | 1123 | // since we're using ll_rw_blk above, it might have skipped over |
| 1119 | // a locked buffer. Double check here | 1124 | // a locked buffer. Double check here |
| 1120 | // | 1125 | // |
| 1121 | if (buffer_dirty(tbh)) /* redundant, sync_dirty_buffer() checks */ | 1126 | /* redundant, sync_dirty_buffer() checks */ |
| 1127 | if (buffer_dirty(tbh)) { | ||
| 1128 | reiserfs_write_unlock(s); | ||
| 1122 | sync_dirty_buffer(tbh); | 1129 | sync_dirty_buffer(tbh); |
| 1130 | reiserfs_write_lock(s); | ||
| 1131 | } | ||
| 1123 | if (unlikely(!buffer_uptodate(tbh))) { | 1132 | if (unlikely(!buffer_uptodate(tbh))) { |
| 1124 | #ifdef CONFIG_REISERFS_CHECK | 1133 | #ifdef CONFIG_REISERFS_CHECK |
| 1125 | reiserfs_warning(s, "journal-601", | 1134 | reiserfs_warning(s, "journal-601", |
| @@ -1143,10 +1152,15 @@ static int flush_commit_list(struct super_block *s, | |||
| 1143 | if (buffer_dirty(jl->j_commit_bh)) | 1152 | if (buffer_dirty(jl->j_commit_bh)) |
| 1144 | BUG(); | 1153 | BUG(); |
| 1145 | mark_buffer_dirty(jl->j_commit_bh) ; | 1154 | mark_buffer_dirty(jl->j_commit_bh) ; |
| 1155 | reiserfs_write_unlock(s); | ||
| 1146 | sync_dirty_buffer(jl->j_commit_bh) ; | 1156 | sync_dirty_buffer(jl->j_commit_bh) ; |
| 1157 | reiserfs_write_lock(s); | ||
| 1147 | } | 1158 | } |
| 1148 | } else | 1159 | } else { |
| 1160 | reiserfs_write_unlock(s); | ||
| 1149 | wait_on_buffer(jl->j_commit_bh); | 1161 | wait_on_buffer(jl->j_commit_bh); |
| 1162 | reiserfs_write_lock(s); | ||
| 1163 | } | ||
| 1150 | 1164 | ||
| 1151 | check_barrier_completion(s, jl->j_commit_bh); | 1165 | check_barrier_completion(s, jl->j_commit_bh); |
| 1152 | 1166 | ||
| @@ -1286,7 +1300,9 @@ static int _update_journal_header_block(struct super_block *sb, | |||
| 1286 | 1300 | ||
| 1287 | if (trans_id >= journal->j_last_flush_trans_id) { | 1301 | if (trans_id >= journal->j_last_flush_trans_id) { |
| 1288 | if (buffer_locked((journal->j_header_bh))) { | 1302 | if (buffer_locked((journal->j_header_bh))) { |
| 1303 | reiserfs_write_unlock(sb); | ||
| 1289 | wait_on_buffer((journal->j_header_bh)); | 1304 | wait_on_buffer((journal->j_header_bh)); |
| 1305 | reiserfs_write_lock(sb); | ||
| 1290 | if (unlikely(!buffer_uptodate(journal->j_header_bh))) { | 1306 | if (unlikely(!buffer_uptodate(journal->j_header_bh))) { |
| 1291 | #ifdef CONFIG_REISERFS_CHECK | 1307 | #ifdef CONFIG_REISERFS_CHECK |
| 1292 | reiserfs_warning(sb, "journal-699", | 1308 | reiserfs_warning(sb, "journal-699", |
| @@ -1312,12 +1328,16 @@ static int _update_journal_header_block(struct super_block *sb, | |||
| 1312 | disable_barrier(sb); | 1328 | disable_barrier(sb); |
| 1313 | goto sync; | 1329 | goto sync; |
| 1314 | } | 1330 | } |
| 1331 | reiserfs_write_unlock(sb); | ||
| 1315 | wait_on_buffer(journal->j_header_bh); | 1332 | wait_on_buffer(journal->j_header_bh); |
| 1333 | reiserfs_write_lock(sb); | ||
| 1316 | check_barrier_completion(sb, journal->j_header_bh); | 1334 | check_barrier_completion(sb, journal->j_header_bh); |
| 1317 | } else { | 1335 | } else { |
| 1318 | sync: | 1336 | sync: |
| 1319 | set_buffer_dirty(journal->j_header_bh); | 1337 | set_buffer_dirty(journal->j_header_bh); |
| 1338 | reiserfs_write_unlock(sb); | ||
| 1320 | sync_dirty_buffer(journal->j_header_bh); | 1339 | sync_dirty_buffer(journal->j_header_bh); |
| 1340 | reiserfs_write_lock(sb); | ||
| 1321 | } | 1341 | } |
| 1322 | if (!buffer_uptodate(journal->j_header_bh)) { | 1342 | if (!buffer_uptodate(journal->j_header_bh)) { |
| 1323 | reiserfs_warning(sb, "journal-837", | 1343 | reiserfs_warning(sb, "journal-837", |
| @@ -1409,7 +1429,7 @@ static int flush_journal_list(struct super_block *s, | |||
| 1409 | 1429 | ||
| 1410 | /* if flushall == 0, the lock is already held */ | 1430 | /* if flushall == 0, the lock is already held */ |
| 1411 | if (flushall) { | 1431 | if (flushall) { |
| 1412 | mutex_lock(&journal->j_flush_mutex); | 1432 | reiserfs_mutex_lock_safe(&journal->j_flush_mutex, s); |
| 1413 | } else if (mutex_trylock(&journal->j_flush_mutex)) { | 1433 | } else if (mutex_trylock(&journal->j_flush_mutex)) { |
| 1414 | BUG(); | 1434 | BUG(); |
| 1415 | } | 1435 | } |
| @@ -1553,7 +1573,11 @@ static int flush_journal_list(struct super_block *s, | |||
| 1553 | reiserfs_panic(s, "journal-1011", | 1573 | reiserfs_panic(s, "journal-1011", |
| 1554 | "cn->bh is NULL"); | 1574 | "cn->bh is NULL"); |
| 1555 | } | 1575 | } |
| 1576 | |||
| 1577 | reiserfs_write_unlock(s); | ||
| 1556 | wait_on_buffer(cn->bh); | 1578 | wait_on_buffer(cn->bh); |
| 1579 | reiserfs_write_lock(s); | ||
| 1580 | |||
| 1557 | if (!cn->bh) { | 1581 | if (!cn->bh) { |
| 1558 | reiserfs_panic(s, "journal-1012", | 1582 | reiserfs_panic(s, "journal-1012", |
| 1559 | "cn->bh is NULL"); | 1583 | "cn->bh is NULL"); |
| @@ -1769,7 +1793,7 @@ static int kupdate_transactions(struct super_block *s, | |||
| 1769 | struct reiserfs_journal *journal = SB_JOURNAL(s); | 1793 | struct reiserfs_journal *journal = SB_JOURNAL(s); |
| 1770 | chunk.nr = 0; | 1794 | chunk.nr = 0; |
| 1771 | 1795 | ||
| 1772 | mutex_lock(&journal->j_flush_mutex); | 1796 | reiserfs_mutex_lock_safe(&journal->j_flush_mutex, s); |
| 1773 | if (!journal_list_still_alive(s, orig_trans_id)) { | 1797 | if (!journal_list_still_alive(s, orig_trans_id)) { |
| 1774 | goto done; | 1798 | goto done; |
| 1775 | } | 1799 | } |
| @@ -1973,11 +1997,19 @@ static int do_journal_release(struct reiserfs_transaction_handle *th, | |||
| 1973 | reiserfs_mounted_fs_count--; | 1997 | reiserfs_mounted_fs_count--; |
| 1974 | /* wait for all commits to finish */ | 1998 | /* wait for all commits to finish */ |
| 1975 | cancel_delayed_work(&SB_JOURNAL(sb)->j_work); | 1999 | cancel_delayed_work(&SB_JOURNAL(sb)->j_work); |
| 2000 | |||
| 2001 | /* | ||
| 2002 | * We must release the write lock here because | ||
| 2003 | * the workqueue job (flush_async_commit) needs this lock | ||
| 2004 | */ | ||
| 2005 | reiserfs_write_unlock(sb); | ||
| 1976 | flush_workqueue(commit_wq); | 2006 | flush_workqueue(commit_wq); |
| 2007 | |||
| 1977 | if (!reiserfs_mounted_fs_count) { | 2008 | if (!reiserfs_mounted_fs_count) { |
| 1978 | destroy_workqueue(commit_wq); | 2009 | destroy_workqueue(commit_wq); |
| 1979 | commit_wq = NULL; | 2010 | commit_wq = NULL; |
| 1980 | } | 2011 | } |
| 2012 | reiserfs_write_lock(sb); | ||
| 1981 | 2013 | ||
| 1982 | free_journal_ram(sb); | 2014 | free_journal_ram(sb); |
| 1983 | 2015 | ||
| @@ -2243,7 +2275,11 @@ static int journal_read_transaction(struct super_block *sb, | |||
| 2243 | /* read in the log blocks, memcpy to the corresponding real block */ | 2275 | /* read in the log blocks, memcpy to the corresponding real block */ |
| 2244 | ll_rw_block(READ, get_desc_trans_len(desc), log_blocks); | 2276 | ll_rw_block(READ, get_desc_trans_len(desc), log_blocks); |
| 2245 | for (i = 0; i < get_desc_trans_len(desc); i++) { | 2277 | for (i = 0; i < get_desc_trans_len(desc); i++) { |
| 2278 | |||
| 2279 | reiserfs_write_unlock(sb); | ||
| 2246 | wait_on_buffer(log_blocks[i]); | 2280 | wait_on_buffer(log_blocks[i]); |
| 2281 | reiserfs_write_lock(sb); | ||
| 2282 | |||
| 2247 | if (!buffer_uptodate(log_blocks[i])) { | 2283 | if (!buffer_uptodate(log_blocks[i])) { |
| 2248 | reiserfs_warning(sb, "journal-1212", | 2284 | reiserfs_warning(sb, "journal-1212", |
| 2249 | "REPLAY FAILURE fsck required! " | 2285 | "REPLAY FAILURE fsck required! " |
| @@ -2765,11 +2801,27 @@ int journal_init(struct super_block *sb, const char *j_dev_name, | |||
| 2765 | goto free_and_return; | 2801 | goto free_and_return; |
| 2766 | } | 2802 | } |
| 2767 | 2803 | ||
| 2804 | /* | ||
| 2805 | * We need to unlock here to avoid creating the following | ||
| 2806 | * dependency: | ||
| 2807 | * reiserfs_lock -> sysfs_mutex | ||
| 2808 | * Because the reiserfs mmap path creates the following dependency: | ||
| 2809 | * mm->mmap -> reiserfs_lock, hence we have | ||
| 2810 | * mm->mmap -> reiserfs_lock ->sysfs_mutex | ||
| 2811 | * This would ends up in a circular dependency with sysfs readdir path | ||
| 2812 | * which does sysfs_mutex -> mm->mmap_sem | ||
| 2813 | * This is fine because the reiserfs lock is useless in mount path, | ||
| 2814 | * at least until we call journal_begin. We keep it for paranoid | ||
| 2815 | * reasons. | ||
| 2816 | */ | ||
| 2817 | reiserfs_write_unlock(sb); | ||
| 2768 | if (journal_init_dev(sb, journal, j_dev_name) != 0) { | 2818 | if (journal_init_dev(sb, journal, j_dev_name) != 0) { |
| 2819 | reiserfs_write_lock(sb); | ||
| 2769 | reiserfs_warning(sb, "sh-462", | 2820 | reiserfs_warning(sb, "sh-462", |
| 2770 | "unable to initialize jornal device"); | 2821 | "unable to initialize jornal device"); |
| 2771 | goto free_and_return; | 2822 | goto free_and_return; |
| 2772 | } | 2823 | } |
| 2824 | reiserfs_write_lock(sb); | ||
| 2773 | 2825 | ||
| 2774 | rs = SB_DISK_SUPER_BLOCK(sb); | 2826 | rs = SB_DISK_SUPER_BLOCK(sb); |
| 2775 | 2827 | ||
| @@ -2881,8 +2933,11 @@ int journal_init(struct super_block *sb, const char *j_dev_name, | |||
| 2881 | } | 2933 | } |
| 2882 | 2934 | ||
| 2883 | reiserfs_mounted_fs_count++; | 2935 | reiserfs_mounted_fs_count++; |
| 2884 | if (reiserfs_mounted_fs_count <= 1) | 2936 | if (reiserfs_mounted_fs_count <= 1) { |
| 2937 | reiserfs_write_unlock(sb); | ||
| 2885 | commit_wq = create_workqueue("reiserfs"); | 2938 | commit_wq = create_workqueue("reiserfs"); |
| 2939 | reiserfs_write_lock(sb); | ||
| 2940 | } | ||
| 2886 | 2941 | ||
| 2887 | INIT_DELAYED_WORK(&journal->j_work, flush_async_commits); | 2942 | INIT_DELAYED_WORK(&journal->j_work, flush_async_commits); |
| 2888 | journal->j_work_sb = sb; | 2943 | journal->j_work_sb = sb; |
| @@ -2964,8 +3019,11 @@ static void queue_log_writer(struct super_block *s) | |||
| 2964 | init_waitqueue_entry(&wait, current); | 3019 | init_waitqueue_entry(&wait, current); |
| 2965 | add_wait_queue(&journal->j_join_wait, &wait); | 3020 | add_wait_queue(&journal->j_join_wait, &wait); |
| 2966 | set_current_state(TASK_UNINTERRUPTIBLE); | 3021 | set_current_state(TASK_UNINTERRUPTIBLE); |
| 2967 | if (test_bit(J_WRITERS_QUEUED, &journal->j_state)) | 3022 | if (test_bit(J_WRITERS_QUEUED, &journal->j_state)) { |
| 3023 | reiserfs_write_unlock(s); | ||
| 2968 | schedule(); | 3024 | schedule(); |
| 3025 | reiserfs_write_lock(s); | ||
| 3026 | } | ||
| 2969 | __set_current_state(TASK_RUNNING); | 3027 | __set_current_state(TASK_RUNNING); |
| 2970 | remove_wait_queue(&journal->j_join_wait, &wait); | 3028 | remove_wait_queue(&journal->j_join_wait, &wait); |
| 2971 | } | 3029 | } |
| @@ -2982,7 +3040,9 @@ static void let_transaction_grow(struct super_block *sb, unsigned int trans_id) | |||
| 2982 | struct reiserfs_journal *journal = SB_JOURNAL(sb); | 3040 | struct reiserfs_journal *journal = SB_JOURNAL(sb); |
| 2983 | unsigned long bcount = journal->j_bcount; | 3041 | unsigned long bcount = journal->j_bcount; |
| 2984 | while (1) { | 3042 | while (1) { |
| 3043 | reiserfs_write_unlock(sb); | ||
| 2985 | schedule_timeout_uninterruptible(1); | 3044 | schedule_timeout_uninterruptible(1); |
| 3045 | reiserfs_write_lock(sb); | ||
| 2986 | journal->j_current_jl->j_state |= LIST_COMMIT_PENDING; | 3046 | journal->j_current_jl->j_state |= LIST_COMMIT_PENDING; |
| 2987 | while ((atomic_read(&journal->j_wcount) > 0 || | 3047 | while ((atomic_read(&journal->j_wcount) > 0 || |
| 2988 | atomic_read(&journal->j_jlock)) && | 3048 | atomic_read(&journal->j_jlock)) && |
| @@ -3033,7 +3093,9 @@ static int do_journal_begin_r(struct reiserfs_transaction_handle *th, | |||
| 3033 | 3093 | ||
| 3034 | if (test_bit(J_WRITERS_BLOCKED, &journal->j_state)) { | 3094 | if (test_bit(J_WRITERS_BLOCKED, &journal->j_state)) { |
| 3035 | unlock_journal(sb); | 3095 | unlock_journal(sb); |
| 3096 | reiserfs_write_unlock(sb); | ||
| 3036 | reiserfs_wait_on_write_block(sb); | 3097 | reiserfs_wait_on_write_block(sb); |
| 3098 | reiserfs_write_lock(sb); | ||
| 3037 | PROC_INFO_INC(sb, journal.journal_relock_writers); | 3099 | PROC_INFO_INC(sb, journal.journal_relock_writers); |
| 3038 | goto relock; | 3100 | goto relock; |
| 3039 | } | 3101 | } |
| @@ -3506,14 +3568,14 @@ static void flush_async_commits(struct work_struct *work) | |||
| 3506 | struct reiserfs_journal_list *jl; | 3568 | struct reiserfs_journal_list *jl; |
| 3507 | struct list_head *entry; | 3569 | struct list_head *entry; |
| 3508 | 3570 | ||
| 3509 | lock_kernel(); | 3571 | reiserfs_write_lock(sb); |
| 3510 | if (!list_empty(&journal->j_journal_list)) { | 3572 | if (!list_empty(&journal->j_journal_list)) { |
| 3511 | /* last entry is the youngest, commit it and you get everything */ | 3573 | /* last entry is the youngest, commit it and you get everything */ |
| 3512 | entry = journal->j_journal_list.prev; | 3574 | entry = journal->j_journal_list.prev; |
| 3513 | jl = JOURNAL_LIST_ENTRY(entry); | 3575 | jl = JOURNAL_LIST_ENTRY(entry); |
| 3514 | flush_commit_list(sb, jl, 1); | 3576 | flush_commit_list(sb, jl, 1); |
| 3515 | } | 3577 | } |
| 3516 | unlock_kernel(); | 3578 | reiserfs_write_unlock(sb); |
| 3517 | } | 3579 | } |
| 3518 | 3580 | ||
| 3519 | /* | 3581 | /* |
| @@ -4041,7 +4103,7 @@ static int do_journal_end(struct reiserfs_transaction_handle *th, | |||
| 4041 | * the new transaction is fully setup, and we've already flushed the | 4103 | * the new transaction is fully setup, and we've already flushed the |
| 4042 | * ordered bh list | 4104 | * ordered bh list |
| 4043 | */ | 4105 | */ |
| 4044 | mutex_lock(&jl->j_commit_mutex); | 4106 | reiserfs_mutex_lock_safe(&jl->j_commit_mutex, sb); |
| 4045 | 4107 | ||
| 4046 | /* save the transaction id in case we need to commit it later */ | 4108 | /* save the transaction id in case we need to commit it later */ |
| 4047 | commit_trans_id = jl->j_trans_id; | 4109 | commit_trans_id = jl->j_trans_id; |
| @@ -4156,7 +4218,9 @@ static int do_journal_end(struct reiserfs_transaction_handle *th, | |||
| 4156 | next = cn->next; | 4218 | next = cn->next; |
| 4157 | free_cnode(sb, cn); | 4219 | free_cnode(sb, cn); |
| 4158 | cn = next; | 4220 | cn = next; |
| 4221 | reiserfs_write_unlock(sb); | ||
| 4159 | cond_resched(); | 4222 | cond_resched(); |
| 4223 | reiserfs_write_lock(sb); | ||
| 4160 | } | 4224 | } |
| 4161 | 4225 | ||
| 4162 | /* we are done with both the c_bh and d_bh, but | 4226 | /* we are done with both the c_bh and d_bh, but |
| @@ -4203,10 +4267,10 @@ static int do_journal_end(struct reiserfs_transaction_handle *th, | |||
| 4203 | * is lost. | 4267 | * is lost. |
| 4204 | */ | 4268 | */ |
| 4205 | if (!list_empty(&jl->j_tail_bh_list)) { | 4269 | if (!list_empty(&jl->j_tail_bh_list)) { |
| 4206 | unlock_kernel(); | 4270 | reiserfs_write_unlock(sb); |
| 4207 | write_ordered_buffers(&journal->j_dirty_buffers_lock, | 4271 | write_ordered_buffers(&journal->j_dirty_buffers_lock, |
| 4208 | journal, jl, &jl->j_tail_bh_list); | 4272 | journal, jl, &jl->j_tail_bh_list); |
| 4209 | lock_kernel(); | 4273 | reiserfs_write_lock(sb); |
| 4210 | } | 4274 | } |
| 4211 | BUG_ON(!list_empty(&jl->j_tail_bh_list)); | 4275 | BUG_ON(!list_empty(&jl->j_tail_bh_list)); |
| 4212 | mutex_unlock(&jl->j_commit_mutex); | 4276 | mutex_unlock(&jl->j_commit_mutex); |
diff --git a/fs/reiserfs/lock.c b/fs/reiserfs/lock.c new file mode 100644 index 000000000000..ee2cfc0fd8a7 --- /dev/null +++ b/fs/reiserfs/lock.c | |||
| @@ -0,0 +1,88 @@ | |||
| 1 | #include <linux/reiserfs_fs.h> | ||
| 2 | #include <linux/mutex.h> | ||
| 3 | |||
| 4 | /* | ||
| 5 | * The previous reiserfs locking scheme was heavily based on | ||
| 6 | * the tricky properties of the Bkl: | ||
| 7 | * | ||
| 8 | * - it was acquired recursively by a same task | ||
| 9 | * - the performances relied on the release-while-schedule() property | ||
| 10 | * | ||
| 11 | * Now that we replace it by a mutex, we still want to keep the same | ||
| 12 | * recursive property to avoid big changes in the code structure. | ||
| 13 | * We use our own lock_owner here because the owner field on a mutex | ||
| 14 | * is only available in SMP or mutex debugging, also we only need this field | ||
| 15 | * for this mutex, no need for a system wide mutex facility. | ||
| 16 | * | ||
| 17 | * Also this lock is often released before a call that could block because | ||
| 18 | * reiserfs performances were partialy based on the release while schedule() | ||
| 19 | * property of the Bkl. | ||
| 20 | */ | ||
| 21 | void reiserfs_write_lock(struct super_block *s) | ||
| 22 | { | ||
| 23 | struct reiserfs_sb_info *sb_i = REISERFS_SB(s); | ||
| 24 | |||
| 25 | if (sb_i->lock_owner != current) { | ||
| 26 | mutex_lock(&sb_i->lock); | ||
| 27 | sb_i->lock_owner = current; | ||
| 28 | } | ||
| 29 | |||
| 30 | /* No need to protect it, only the current task touches it */ | ||
| 31 | sb_i->lock_depth++; | ||
| 32 | } | ||
| 33 | |||
| 34 | void reiserfs_write_unlock(struct super_block *s) | ||
| 35 | { | ||
| 36 | struct reiserfs_sb_info *sb_i = REISERFS_SB(s); | ||
| 37 | |||
| 38 | /* | ||
| 39 | * Are we unlocking without even holding the lock? | ||
| 40 | * Such a situation must raise a BUG() if we don't want | ||
| 41 | * to corrupt the data. | ||
| 42 | */ | ||
| 43 | BUG_ON(sb_i->lock_owner != current); | ||
| 44 | |||
| 45 | if (--sb_i->lock_depth == -1) { | ||
| 46 | sb_i->lock_owner = NULL; | ||
| 47 | mutex_unlock(&sb_i->lock); | ||
| 48 | } | ||
| 49 | } | ||
| 50 | |||
| 51 | /* | ||
| 52 | * If we already own the lock, just exit and don't increase the depth. | ||
| 53 | * Useful when we don't want to lock more than once. | ||
| 54 | * | ||
| 55 | * We always return the lock_depth we had before calling | ||
| 56 | * this function. | ||
| 57 | */ | ||
| 58 | int reiserfs_write_lock_once(struct super_block *s) | ||
| 59 | { | ||
| 60 | struct reiserfs_sb_info *sb_i = REISERFS_SB(s); | ||
| 61 | |||
| 62 | if (sb_i->lock_owner != current) { | ||
| 63 | mutex_lock(&sb_i->lock); | ||
| 64 | sb_i->lock_owner = current; | ||
| 65 | return sb_i->lock_depth++; | ||
| 66 | } | ||
| 67 | |||
| 68 | return sb_i->lock_depth; | ||
| 69 | } | ||
| 70 | |||
| 71 | void reiserfs_write_unlock_once(struct super_block *s, int lock_depth) | ||
| 72 | { | ||
| 73 | if (lock_depth == -1) | ||
| 74 | reiserfs_write_unlock(s); | ||
| 75 | } | ||
| 76 | |||
| 77 | /* | ||
| 78 | * Utility function to force a BUG if it is called without the superblock | ||
| 79 | * write lock held. caller is the string printed just before calling BUG() | ||
| 80 | */ | ||
| 81 | void reiserfs_check_lock_depth(struct super_block *sb, char *caller) | ||
| 82 | { | ||
| 83 | struct reiserfs_sb_info *sb_i = REISERFS_SB(sb); | ||
| 84 | |||
| 85 | if (sb_i->lock_depth < 0) | ||
| 86 | reiserfs_panic(sb, "%s called without kernel lock held %d", | ||
| 87 | caller); | ||
| 88 | } | ||
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index 271579128634..e296ff72a6cc 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c | |||
| @@ -324,6 +324,7 @@ static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry, | |||
| 324 | struct nameidata *nd) | 324 | struct nameidata *nd) |
| 325 | { | 325 | { |
| 326 | int retval; | 326 | int retval; |
| 327 | int lock_depth; | ||
| 327 | struct inode *inode = NULL; | 328 | struct inode *inode = NULL; |
| 328 | struct reiserfs_dir_entry de; | 329 | struct reiserfs_dir_entry de; |
| 329 | INITIALIZE_PATH(path_to_entry); | 330 | INITIALIZE_PATH(path_to_entry); |
| @@ -331,7 +332,13 @@ static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry, | |||
| 331 | if (REISERFS_MAX_NAME(dir->i_sb->s_blocksize) < dentry->d_name.len) | 332 | if (REISERFS_MAX_NAME(dir->i_sb->s_blocksize) < dentry->d_name.len) |
| 332 | return ERR_PTR(-ENAMETOOLONG); | 333 | return ERR_PTR(-ENAMETOOLONG); |
| 333 | 334 | ||
| 334 | reiserfs_write_lock(dir->i_sb); | 335 | /* |
| 336 | * Might be called with or without the write lock, must be careful | ||
| 337 | * to not recursively hold it in case we want to release the lock | ||
| 338 | * before rescheduling. | ||
| 339 | */ | ||
| 340 | lock_depth = reiserfs_write_lock_once(dir->i_sb); | ||
| 341 | |||
| 335 | de.de_gen_number_bit_string = NULL; | 342 | de.de_gen_number_bit_string = NULL; |
| 336 | retval = | 343 | retval = |
| 337 | reiserfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, | 344 | reiserfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, |
| @@ -341,7 +348,7 @@ static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry, | |||
| 341 | inode = reiserfs_iget(dir->i_sb, | 348 | inode = reiserfs_iget(dir->i_sb, |
| 342 | (struct cpu_key *)&(de.de_dir_id)); | 349 | (struct cpu_key *)&(de.de_dir_id)); |
| 343 | if (!inode || IS_ERR(inode)) { | 350 | if (!inode || IS_ERR(inode)) { |
| 344 | reiserfs_write_unlock(dir->i_sb); | 351 | reiserfs_write_unlock_once(dir->i_sb, lock_depth); |
| 345 | return ERR_PTR(-EACCES); | 352 | return ERR_PTR(-EACCES); |
| 346 | } | 353 | } |
| 347 | 354 | ||
| @@ -350,7 +357,7 @@ static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry, | |||
| 350 | if (IS_PRIVATE(dir)) | 357 | if (IS_PRIVATE(dir)) |
| 351 | inode->i_flags |= S_PRIVATE; | 358 | inode->i_flags |= S_PRIVATE; |
| 352 | } | 359 | } |
| 353 | reiserfs_write_unlock(dir->i_sb); | 360 | reiserfs_write_unlock_once(dir->i_sb, lock_depth); |
| 354 | if (retval == IO_ERROR) { | 361 | if (retval == IO_ERROR) { |
| 355 | return ERR_PTR(-EIO); | 362 | return ERR_PTR(-EIO); |
| 356 | } | 363 | } |
| @@ -725,6 +732,7 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 725 | struct inode *inode; | 732 | struct inode *inode; |
| 726 | struct reiserfs_transaction_handle th; | 733 | struct reiserfs_transaction_handle th; |
| 727 | struct reiserfs_security_handle security; | 734 | struct reiserfs_security_handle security; |
| 735 | int lock_depth; | ||
| 728 | /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ | 736 | /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ |
| 729 | int jbegin_count = | 737 | int jbegin_count = |
| 730 | JOURNAL_PER_BALANCE_CNT * 3 + | 738 | JOURNAL_PER_BALANCE_CNT * 3 + |
| @@ -748,7 +756,7 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 748 | return retval; | 756 | return retval; |
| 749 | } | 757 | } |
| 750 | jbegin_count += retval; | 758 | jbegin_count += retval; |
| 751 | reiserfs_write_lock(dir->i_sb); | 759 | lock_depth = reiserfs_write_lock_once(dir->i_sb); |
| 752 | 760 | ||
| 753 | retval = journal_begin(&th, dir->i_sb, jbegin_count); | 761 | retval = journal_begin(&th, dir->i_sb, jbegin_count); |
| 754 | if (retval) { | 762 | if (retval) { |
| @@ -798,8 +806,8 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 798 | d_instantiate(dentry, inode); | 806 | d_instantiate(dentry, inode); |
| 799 | unlock_new_inode(inode); | 807 | unlock_new_inode(inode); |
| 800 | retval = journal_end(&th, dir->i_sb, jbegin_count); | 808 | retval = journal_end(&th, dir->i_sb, jbegin_count); |
| 801 | out_failed: | 809 | out_failed: |
| 802 | reiserfs_write_unlock(dir->i_sb); | 810 | reiserfs_write_unlock_once(dir->i_sb, lock_depth); |
| 803 | return retval; | 811 | return retval; |
| 804 | } | 812 | } |
| 805 | 813 | ||
diff --git a/fs/reiserfs/prints.c b/fs/reiserfs/prints.c index 536eacaeb710..adbc6f538515 100644 --- a/fs/reiserfs/prints.c +++ b/fs/reiserfs/prints.c | |||
| @@ -349,10 +349,6 @@ void reiserfs_debug(struct super_block *s, int level, const char *fmt, ...) | |||
| 349 | 349 | ||
| 350 | . */ | 350 | . */ |
| 351 | 351 | ||
| 352 | #ifdef CONFIG_REISERFS_CHECK | ||
| 353 | extern struct tree_balance *cur_tb; | ||
| 354 | #endif | ||
| 355 | |||
| 356 | void __reiserfs_panic(struct super_block *sb, const char *id, | 352 | void __reiserfs_panic(struct super_block *sb, const char *id, |
| 357 | const char *function, const char *fmt, ...) | 353 | const char *function, const char *fmt, ...) |
| 358 | { | 354 | { |
diff --git a/fs/reiserfs/resize.c b/fs/reiserfs/resize.c index 18b315d3d104..b3a94d20f0fc 100644 --- a/fs/reiserfs/resize.c +++ b/fs/reiserfs/resize.c | |||
| @@ -141,7 +141,9 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new) | |||
| 141 | 141 | ||
| 142 | set_buffer_uptodate(bh); | 142 | set_buffer_uptodate(bh); |
| 143 | mark_buffer_dirty(bh); | 143 | mark_buffer_dirty(bh); |
| 144 | reiserfs_write_unlock(s); | ||
| 144 | sync_dirty_buffer(bh); | 145 | sync_dirty_buffer(bh); |
| 146 | reiserfs_write_lock(s); | ||
| 145 | // update bitmap_info stuff | 147 | // update bitmap_info stuff |
| 146 | bitmap[i].free_count = sb_blocksize(sb) * 8 - 1; | 148 | bitmap[i].free_count = sb_blocksize(sb) * 8 - 1; |
| 147 | brelse(bh); | 149 | brelse(bh); |
diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c index d036ee5b1c81..5fa7118f04e1 100644 --- a/fs/reiserfs/stree.c +++ b/fs/reiserfs/stree.c | |||
| @@ -222,9 +222,6 @@ static inline int bin_search(const void *key, /* Key to search for. */ | |||
| 222 | return ITEM_NOT_FOUND; | 222 | return ITEM_NOT_FOUND; |
| 223 | } | 223 | } |
| 224 | 224 | ||
| 225 | #ifdef CONFIG_REISERFS_CHECK | ||
| 226 | extern struct tree_balance *cur_tb; | ||
| 227 | #endif | ||
| 228 | 225 | ||
| 229 | /* Minimal possible key. It is never in the tree. */ | 226 | /* Minimal possible key. It is never in the tree. */ |
| 230 | const struct reiserfs_key MIN_KEY = { 0, 0, {{0, 0},} }; | 227 | const struct reiserfs_key MIN_KEY = { 0, 0, {{0, 0},} }; |
| @@ -519,25 +516,48 @@ static int is_tree_node(struct buffer_head *bh, int level) | |||
| 519 | 516 | ||
| 520 | #define SEARCH_BY_KEY_READA 16 | 517 | #define SEARCH_BY_KEY_READA 16 |
| 521 | 518 | ||
| 522 | /* The function is NOT SCHEDULE-SAFE! */ | 519 | /* |
| 523 | static void search_by_key_reada(struct super_block *s, | 520 | * The function is NOT SCHEDULE-SAFE! |
| 521 | * It might unlock the write lock if we needed to wait for a block | ||
| 522 | * to be read. Note that in this case it won't recover the lock to avoid | ||
| 523 | * high contention resulting from too much lock requests, especially | ||
| 524 | * the caller (search_by_key) will perform other schedule-unsafe | ||
| 525 | * operations just after calling this function. | ||
| 526 | * | ||
| 527 | * @return true if we have unlocked | ||
| 528 | */ | ||
| 529 | static bool search_by_key_reada(struct super_block *s, | ||
| 524 | struct buffer_head **bh, | 530 | struct buffer_head **bh, |
| 525 | b_blocknr_t *b, int num) | 531 | b_blocknr_t *b, int num) |
| 526 | { | 532 | { |
| 527 | int i, j; | 533 | int i, j; |
| 534 | bool unlocked = false; | ||
| 528 | 535 | ||
| 529 | for (i = 0; i < num; i++) { | 536 | for (i = 0; i < num; i++) { |
| 530 | bh[i] = sb_getblk(s, b[i]); | 537 | bh[i] = sb_getblk(s, b[i]); |
| 531 | } | 538 | } |
| 539 | /* | ||
| 540 | * We are going to read some blocks on which we | ||
| 541 | * have a reference. It's safe, though we might be | ||
| 542 | * reading blocks concurrently changed if we release | ||
| 543 | * the lock. But it's still fine because we check later | ||
| 544 | * if the tree changed | ||
| 545 | */ | ||
| 532 | for (j = 0; j < i; j++) { | 546 | for (j = 0; j < i; j++) { |
| 533 | /* | 547 | /* |
| 534 | * note, this needs attention if we are getting rid of the BKL | 548 | * note, this needs attention if we are getting rid of the BKL |
| 535 | * you have to make sure the prepared bit isn't set on this buffer | 549 | * you have to make sure the prepared bit isn't set on this buffer |
| 536 | */ | 550 | */ |
| 537 | if (!buffer_uptodate(bh[j])) | 551 | if (!buffer_uptodate(bh[j])) { |
| 552 | if (!unlocked) { | ||
| 553 | reiserfs_write_unlock(s); | ||
| 554 | unlocked = true; | ||
| 555 | } | ||
| 538 | ll_rw_block(READA, 1, bh + j); | 556 | ll_rw_block(READA, 1, bh + j); |
| 557 | } | ||
| 539 | brelse(bh[j]); | 558 | brelse(bh[j]); |
| 540 | } | 559 | } |
| 560 | return unlocked; | ||
| 541 | } | 561 | } |
| 542 | 562 | ||
| 543 | /************************************************************************** | 563 | /************************************************************************** |
| @@ -625,11 +645,26 @@ int search_by_key(struct super_block *sb, const struct cpu_key *key, /* Key to s | |||
| 625 | have a pointer to it. */ | 645 | have a pointer to it. */ |
| 626 | if ((bh = last_element->pe_buffer = | 646 | if ((bh = last_element->pe_buffer = |
| 627 | sb_getblk(sb, block_number))) { | 647 | sb_getblk(sb, block_number))) { |
| 648 | bool unlocked = false; | ||
| 649 | |||
| 628 | if (!buffer_uptodate(bh) && reada_count > 1) | 650 | if (!buffer_uptodate(bh) && reada_count > 1) |
| 629 | search_by_key_reada(sb, reada_bh, | 651 | /* may unlock the write lock */ |
| 652 | unlocked = search_by_key_reada(sb, reada_bh, | ||
| 630 | reada_blocks, reada_count); | 653 | reada_blocks, reada_count); |
| 654 | /* | ||
| 655 | * If we haven't already unlocked the write lock, | ||
| 656 | * then we need to do that here before reading | ||
| 657 | * the current block | ||
| 658 | */ | ||
| 659 | if (!buffer_uptodate(bh) && !unlocked) { | ||
| 660 | reiserfs_write_unlock(sb); | ||
| 661 | unlocked = true; | ||
| 662 | } | ||
| 631 | ll_rw_block(READ, 1, &bh); | 663 | ll_rw_block(READ, 1, &bh); |
| 632 | wait_on_buffer(bh); | 664 | wait_on_buffer(bh); |
| 665 | |||
| 666 | if (unlocked) | ||
| 667 | reiserfs_write_lock(sb); | ||
| 633 | if (!buffer_uptodate(bh)) | 668 | if (!buffer_uptodate(bh)) |
| 634 | goto io_error; | 669 | goto io_error; |
| 635 | } else { | 670 | } else { |
| @@ -673,7 +708,7 @@ int search_by_key(struct super_block *sb, const struct cpu_key *key, /* Key to s | |||
| 673 | !key_in_buffer(search_path, key, sb), | 708 | !key_in_buffer(search_path, key, sb), |
| 674 | "PAP-5130: key is not in the buffer"); | 709 | "PAP-5130: key is not in the buffer"); |
| 675 | #ifdef CONFIG_REISERFS_CHECK | 710 | #ifdef CONFIG_REISERFS_CHECK |
| 676 | if (cur_tb) { | 711 | if (REISERFS_SB(sb)->cur_tb) { |
| 677 | print_cur_tb("5140"); | 712 | print_cur_tb("5140"); |
| 678 | reiserfs_panic(sb, "PAP-5140", | 713 | reiserfs_panic(sb, "PAP-5140", |
| 679 | "schedule occurred in do_balance!"); | 714 | "schedule occurred in do_balance!"); |
| @@ -1024,7 +1059,9 @@ static char prepare_for_delete_or_cut(struct reiserfs_transaction_handle *th, st | |||
| 1024 | reiserfs_free_block(th, inode, block, 1); | 1059 | reiserfs_free_block(th, inode, block, 1); |
| 1025 | } | 1060 | } |
| 1026 | 1061 | ||
| 1062 | reiserfs_write_unlock(sb); | ||
| 1027 | cond_resched(); | 1063 | cond_resched(); |
| 1064 | reiserfs_write_lock(sb); | ||
| 1028 | 1065 | ||
| 1029 | if (item_moved (&s_ih, path)) { | 1066 | if (item_moved (&s_ih, path)) { |
| 1030 | need_re_search = 1; | 1067 | need_re_search = 1; |
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index f0ad05f38022..339b0baf2af6 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c | |||
| @@ -465,7 +465,7 @@ static void reiserfs_put_super(struct super_block *s) | |||
| 465 | struct reiserfs_transaction_handle th; | 465 | struct reiserfs_transaction_handle th; |
| 466 | th.t_trans_id = 0; | 466 | th.t_trans_id = 0; |
| 467 | 467 | ||
| 468 | lock_kernel(); | 468 | reiserfs_write_lock(s); |
| 469 | 469 | ||
| 470 | if (s->s_dirt) | 470 | if (s->s_dirt) |
| 471 | reiserfs_write_super(s); | 471 | reiserfs_write_super(s); |
| @@ -499,10 +499,10 @@ static void reiserfs_put_super(struct super_block *s) | |||
| 499 | 499 | ||
| 500 | reiserfs_proc_info_done(s); | 500 | reiserfs_proc_info_done(s); |
| 501 | 501 | ||
| 502 | reiserfs_write_unlock(s); | ||
| 503 | mutex_destroy(&REISERFS_SB(s)->lock); | ||
| 502 | kfree(s->s_fs_info); | 504 | kfree(s->s_fs_info); |
| 503 | s->s_fs_info = NULL; | 505 | s->s_fs_info = NULL; |
| 504 | |||
| 505 | unlock_kernel(); | ||
| 506 | } | 506 | } |
| 507 | 507 | ||
| 508 | static struct kmem_cache *reiserfs_inode_cachep; | 508 | static struct kmem_cache *reiserfs_inode_cachep; |
| @@ -554,25 +554,28 @@ static void reiserfs_dirty_inode(struct inode *inode) | |||
| 554 | struct reiserfs_transaction_handle th; | 554 | struct reiserfs_transaction_handle th; |
| 555 | 555 | ||
| 556 | int err = 0; | 556 | int err = 0; |
| 557 | int lock_depth; | ||
| 558 | |||
| 557 | if (inode->i_sb->s_flags & MS_RDONLY) { | 559 | if (inode->i_sb->s_flags & MS_RDONLY) { |
| 558 | reiserfs_warning(inode->i_sb, "clm-6006", | 560 | reiserfs_warning(inode->i_sb, "clm-6006", |
| 559 | "writing inode %lu on readonly FS", | 561 | "writing inode %lu on readonly FS", |
| 560 | inode->i_ino); | 562 | inode->i_ino); |
| 561 | return; | 563 | return; |
| 562 | } | 564 | } |
| 563 | reiserfs_write_lock(inode->i_sb); | 565 | lock_depth = reiserfs_write_lock_once(inode->i_sb); |
| 564 | 566 | ||
| 565 | /* this is really only used for atime updates, so they don't have | 567 | /* this is really only used for atime updates, so they don't have |
| 566 | ** to be included in O_SYNC or fsync | 568 | ** to be included in O_SYNC or fsync |
| 567 | */ | 569 | */ |
| 568 | err = journal_begin(&th, inode->i_sb, 1); | 570 | err = journal_begin(&th, inode->i_sb, 1); |
| 569 | if (err) { | 571 | if (err) |
| 570 | reiserfs_write_unlock(inode->i_sb); | 572 | goto out; |
| 571 | return; | 573 | |
| 572 | } | ||
| 573 | reiserfs_update_sd(&th, inode); | 574 | reiserfs_update_sd(&th, inode); |
| 574 | journal_end(&th, inode->i_sb, 1); | 575 | journal_end(&th, inode->i_sb, 1); |
| 575 | reiserfs_write_unlock(inode->i_sb); | 576 | |
| 577 | out: | ||
| 578 | reiserfs_write_unlock_once(inode->i_sb, lock_depth); | ||
| 576 | } | 579 | } |
| 577 | 580 | ||
| 578 | #ifdef CONFIG_QUOTA | 581 | #ifdef CONFIG_QUOTA |
| @@ -1168,11 +1171,14 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) | |||
| 1168 | unsigned int qfmt = 0; | 1171 | unsigned int qfmt = 0; |
| 1169 | #ifdef CONFIG_QUOTA | 1172 | #ifdef CONFIG_QUOTA |
| 1170 | int i; | 1173 | int i; |
| 1174 | #endif | ||
| 1175 | |||
| 1176 | reiserfs_write_lock(s); | ||
| 1171 | 1177 | ||
| 1178 | #ifdef CONFIG_QUOTA | ||
| 1172 | memcpy(qf_names, REISERFS_SB(s)->s_qf_names, sizeof(qf_names)); | 1179 | memcpy(qf_names, REISERFS_SB(s)->s_qf_names, sizeof(qf_names)); |
| 1173 | #endif | 1180 | #endif |
| 1174 | 1181 | ||
| 1175 | lock_kernel(); | ||
| 1176 | rs = SB_DISK_SUPER_BLOCK(s); | 1182 | rs = SB_DISK_SUPER_BLOCK(s); |
| 1177 | 1183 | ||
| 1178 | if (!reiserfs_parse_options | 1184 | if (!reiserfs_parse_options |
| @@ -1295,12 +1301,12 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) | |||
| 1295 | 1301 | ||
| 1296 | out_ok: | 1302 | out_ok: |
| 1297 | replace_mount_options(s, new_opts); | 1303 | replace_mount_options(s, new_opts); |
| 1298 | unlock_kernel(); | 1304 | reiserfs_write_unlock(s); |
| 1299 | return 0; | 1305 | return 0; |
| 1300 | 1306 | ||
| 1301 | out_err: | 1307 | out_err: |
| 1302 | kfree(new_opts); | 1308 | kfree(new_opts); |
| 1303 | unlock_kernel(); | 1309 | reiserfs_write_unlock(s); |
| 1304 | return err; | 1310 | return err; |
| 1305 | } | 1311 | } |
| 1306 | 1312 | ||
| @@ -1404,7 +1410,9 @@ static int read_super_block(struct super_block *s, int offset) | |||
| 1404 | static int reread_meta_blocks(struct super_block *s) | 1410 | static int reread_meta_blocks(struct super_block *s) |
| 1405 | { | 1411 | { |
| 1406 | ll_rw_block(READ, 1, &(SB_BUFFER_WITH_SB(s))); | 1412 | ll_rw_block(READ, 1, &(SB_BUFFER_WITH_SB(s))); |
| 1413 | reiserfs_write_unlock(s); | ||
| 1407 | wait_on_buffer(SB_BUFFER_WITH_SB(s)); | 1414 | wait_on_buffer(SB_BUFFER_WITH_SB(s)); |
| 1415 | reiserfs_write_lock(s); | ||
| 1408 | if (!buffer_uptodate(SB_BUFFER_WITH_SB(s))) { | 1416 | if (!buffer_uptodate(SB_BUFFER_WITH_SB(s))) { |
| 1409 | reiserfs_warning(s, "reiserfs-2504", "error reading the super"); | 1417 | reiserfs_warning(s, "reiserfs-2504", "error reading the super"); |
| 1410 | return 1; | 1418 | return 1; |
| @@ -1613,7 +1621,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) | |||
| 1613 | sbi = kzalloc(sizeof(struct reiserfs_sb_info), GFP_KERNEL); | 1621 | sbi = kzalloc(sizeof(struct reiserfs_sb_info), GFP_KERNEL); |
| 1614 | if (!sbi) { | 1622 | if (!sbi) { |
| 1615 | errval = -ENOMEM; | 1623 | errval = -ENOMEM; |
| 1616 | goto error; | 1624 | goto error_alloc; |
| 1617 | } | 1625 | } |
| 1618 | s->s_fs_info = sbi; | 1626 | s->s_fs_info = sbi; |
| 1619 | /* Set default values for options: non-aggressive tails, RO on errors */ | 1627 | /* Set default values for options: non-aggressive tails, RO on errors */ |
| @@ -1627,6 +1635,20 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) | |||
| 1627 | /* setup default block allocator options */ | 1635 | /* setup default block allocator options */ |
| 1628 | reiserfs_init_alloc_options(s); | 1636 | reiserfs_init_alloc_options(s); |
| 1629 | 1637 | ||
| 1638 | mutex_init(&REISERFS_SB(s)->lock); | ||
| 1639 | REISERFS_SB(s)->lock_depth = -1; | ||
| 1640 | |||
| 1641 | /* | ||
| 1642 | * This function is called with the bkl, which also was the old | ||
| 1643 | * locking used here. | ||
| 1644 | * do_journal_begin() will soon check if we hold the lock (ie: was the | ||
| 1645 | * bkl). This is likely because do_journal_begin() has several another | ||
| 1646 | * callers because at this time, it doesn't seem to be necessary to | ||
| 1647 | * protect against anything. | ||
| 1648 | * Anyway, let's be conservative and lock for now. | ||
| 1649 | */ | ||
| 1650 | reiserfs_write_lock(s); | ||
| 1651 | |||
| 1630 | jdev_name = NULL; | 1652 | jdev_name = NULL; |
| 1631 | if (reiserfs_parse_options | 1653 | if (reiserfs_parse_options |
| 1632 | (s, (char *)data, &(sbi->s_mount_opt), &blocks, &jdev_name, | 1654 | (s, (char *)data, &(sbi->s_mount_opt), &blocks, &jdev_name, |
| @@ -1852,9 +1874,13 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) | |||
| 1852 | init_waitqueue_head(&(sbi->s_wait)); | 1874 | init_waitqueue_head(&(sbi->s_wait)); |
| 1853 | spin_lock_init(&sbi->bitmap_lock); | 1875 | spin_lock_init(&sbi->bitmap_lock); |
| 1854 | 1876 | ||
| 1877 | reiserfs_write_unlock(s); | ||
| 1878 | |||
| 1855 | return (0); | 1879 | return (0); |
| 1856 | 1880 | ||
| 1857 | error: | 1881 | error: |
| 1882 | reiserfs_write_unlock(s); | ||
| 1883 | error_alloc: | ||
| 1858 | if (jinit_done) { /* kill the commit thread, free journal ram */ | 1884 | if (jinit_done) { /* kill the commit thread, free journal ram */ |
| 1859 | journal_release_error(NULL, s); | 1885 | journal_release_error(NULL, s); |
| 1860 | } | 1886 | } |
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index 6925b835a43b..58aa8e75f7f5 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c | |||
| @@ -975,7 +975,7 @@ int reiserfs_lookup_privroot(struct super_block *s) | |||
| 975 | int err = 0; | 975 | int err = 0; |
| 976 | 976 | ||
| 977 | /* If we don't have the privroot located yet - go find it */ | 977 | /* If we don't have the privroot located yet - go find it */ |
| 978 | mutex_lock(&s->s_root->d_inode->i_mutex); | 978 | reiserfs_mutex_lock_safe(&s->s_root->d_inode->i_mutex, s); |
| 979 | dentry = lookup_one_len(PRIVROOT_NAME, s->s_root, | 979 | dentry = lookup_one_len(PRIVROOT_NAME, s->s_root, |
| 980 | strlen(PRIVROOT_NAME)); | 980 | strlen(PRIVROOT_NAME)); |
| 981 | if (!IS_ERR(dentry)) { | 981 | if (!IS_ERR(dentry)) { |
| @@ -1004,14 +1004,14 @@ int reiserfs_xattr_init(struct super_block *s, int mount_flags) | |||
| 1004 | goto error; | 1004 | goto error; |
| 1005 | 1005 | ||
| 1006 | if (!privroot->d_inode && !(mount_flags & MS_RDONLY)) { | 1006 | if (!privroot->d_inode && !(mount_flags & MS_RDONLY)) { |
| 1007 | mutex_lock(&s->s_root->d_inode->i_mutex); | 1007 | reiserfs_mutex_lock_safe(&s->s_root->d_inode->i_mutex, s); |
| 1008 | err = create_privroot(REISERFS_SB(s)->priv_root); | 1008 | err = create_privroot(REISERFS_SB(s)->priv_root); |
| 1009 | mutex_unlock(&s->s_root->d_inode->i_mutex); | 1009 | mutex_unlock(&s->s_root->d_inode->i_mutex); |
| 1010 | } | 1010 | } |
| 1011 | 1011 | ||
| 1012 | if (privroot->d_inode) { | 1012 | if (privroot->d_inode) { |
| 1013 | s->s_xattr = reiserfs_xattr_handlers; | 1013 | s->s_xattr = reiserfs_xattr_handlers; |
| 1014 | mutex_lock(&privroot->d_inode->i_mutex); | 1014 | reiserfs_mutex_lock_safe(&privroot->d_inode->i_mutex, s); |
| 1015 | if (!REISERFS_SB(s)->xattr_root) { | 1015 | if (!REISERFS_SB(s)->xattr_root) { |
| 1016 | struct dentry *dentry; | 1016 | struct dentry *dentry; |
| 1017 | dentry = lookup_one_len(XAROOT_NAME, privroot, | 1017 | dentry = lookup_one_len(XAROOT_NAME, privroot, |
