Commit 8ebc4232 authored by Frederic Weisbecker's avatar Frederic Weisbecker

reiserfs: kill-the-BKL

This patch is an attempt to remove the Bkl based locking scheme from
reiserfs and is intended.

It is a bit inspired from an old attempt by Peter Zijlstra:

   http://lkml.indiana.edu/hypermail/linux/kernel/0704.2/2174.html

The bkl is heavily used in this filesystem to prevent from
concurrent write accesses on the filesystem.

Reiserfs makes a deep use of the specific properties of the Bkl:

- It can be acqquired recursively by a same task
- It is released on the schedule() calls and reacquired when schedule() returns

The two properties above are a roadmap for the reiserfs write locking so it's
very hard to simply replace it with a common mutex.

- We need a recursive-able locking unless we want to restructure several blocks
  of the code.
- We need to identify the sites where the bkl was implictly relaxed
  (schedule, wait, sync, etc...) so that we can in turn release and
  reacquire our new lock explicitly.
  Such implicit releases of the lock are often required to let other
  resources producer/consumer do their job or we can suffer unexpected
  starvations or deadlocks.

So the new lock that replaces the bkl here is a per superblock mutex with a
specific property: it can be acquired recursively by a same task, like the
bkl.

For such purpose, we integrate a lock owner and a lock depth field on the
superblock information structure.

The first axis on this patch is to turn reiserfs_write_(un)lock() function
into a wrapper to manage this mutex. Also some explicit calls to
lock_kernel() have been converted to reiserfs_write_lock() helpers.

The second axis is to find the important blocking sites (schedule...(),
wait_on_buffer(), sync_dirty_buffer(), etc...) and then apply an explicit
release of the write lock on these locations before blocking. Then we can
safely wait for those who can give us resources or those who need some.
Typically this is a fight between the current writer, the reiserfs workqueue
(aka the async commiter) and the pdflush threads.

The third axis is a consequence of the second. The write lock is usually
on top of a lock dependency chain which can include the journal lock, the
flush lock or the commit lock. So it's dangerous to release and trying to
reacquire the write lock while we still hold other locks.

This is fine with the bkl:

      T1                       T2

lock_kernel()
    mutex_lock(A)
    unlock_kernel()
    // do something
                            lock_kernel()
                                mutex_lock(A) -> already locked by T1
                                schedule() (and then unlock_kernel())
    lock_kernel()
    mutex_unlock(A)
    ....

This is not fine with a mutex:

      T1                       T2

mutex_lock(write)
    mutex_lock(A)
    mutex_unlock(write)
    // do something
                           mutex_lock(write)
                              mutex_lock(A) -> already locked by T1
                              schedule()

    mutex_lock(write) -> already locked by T2
    deadlock

The solution in this patch is to provide a helper which releases the write
lock and sleep a bit if we can't lock a mutex that depend on it. It's another
simulation of the bkl behaviour.

The last axis is to locate the fs callbacks that are called with the bkl held,
according to Documentation/filesystem/Locking.

Those are:

- reiserfs_remount
- reiserfs_fill_super
- reiserfs_put_super

Reiserfs didn't need to explicitly lock because of the context of these callbacks.
But now we must take care of that with the new locking.

After this patch, reiserfs suffers from a slight performance regression (for now).
On UP, a high volume write with dd reports an average of 27 MB/s instead
of 30 MB/s without the patch applied.
Signed-off-by: default avatarFrederic Weisbecker <fweisbec@gmail.com>
Reviewed-by: default avatarIngo Molnar <mingo@elte.hu>
Cc: Jeff Mahoney <jeffm@suse.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Bron Gondwana <brong@fastmail.fm>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
LKML-Reference: <1239070789-13354-1-git-send-email-fweisbec@gmail.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 74fca6a4
...@@ -7,7 +7,7 @@ obj-$(CONFIG_REISERFS_FS) += reiserfs.o ...@@ -7,7 +7,7 @@ obj-$(CONFIG_REISERFS_FS) += reiserfs.o
reiserfs-objs := bitmap.o do_balan.o namei.o inode.o file.o dir.o fix_node.o \ reiserfs-objs := bitmap.o do_balan.o namei.o inode.o file.o dir.o fix_node.o \
super.o prints.o objectid.o lbalance.o ibalance.o stree.o \ super.o prints.o objectid.o lbalance.o ibalance.o stree.o \
hashes.o tail_conversion.o journal.o resize.o \ hashes.o tail_conversion.o journal.o resize.o \
item_ops.o ioctl.o procfs.o xattr.o item_ops.o ioctl.o procfs.o xattr.o lock.o
ifeq ($(CONFIG_REISERFS_FS_XATTR),y) ifeq ($(CONFIG_REISERFS_FS_XATTR),y)
reiserfs-objs += xattr_user.o xattr_trusted.o reiserfs-objs += xattr_user.o xattr_trusted.o
......
...@@ -1256,7 +1256,9 @@ struct buffer_head *reiserfs_read_bitmap_block(struct super_block *sb, ...@@ -1256,7 +1256,9 @@ struct buffer_head *reiserfs_read_bitmap_block(struct super_block *sb,
else { else {
if (buffer_locked(bh)) { if (buffer_locked(bh)) {
PROC_INFO_INC(sb, scan_bitmap.wait); PROC_INFO_INC(sb, scan_bitmap.wait);
reiserfs_write_unlock(sb);
__wait_on_buffer(bh); __wait_on_buffer(bh);
reiserfs_write_lock(sb);
} }
BUG_ON(!buffer_uptodate(bh)); BUG_ON(!buffer_uptodate(bh));
BUG_ON(atomic_read(&bh->b_count) == 0); BUG_ON(atomic_read(&bh->b_count) == 0);
......
...@@ -174,14 +174,22 @@ int reiserfs_readdir_dentry(struct dentry *dentry, void *dirent, ...@@ -174,14 +174,22 @@ int reiserfs_readdir_dentry(struct dentry *dentry, void *dirent,
// user space buffer is swapped out. At that time // user space buffer is swapped out. At that time
// entry can move to somewhere else // entry can move to somewhere else
memcpy(local_buf, d_name, d_reclen); memcpy(local_buf, d_name, d_reclen);
/*
* Since filldir might sleep, we can release
* the write lock here for other waiters
*/
reiserfs_write_unlock(inode->i_sb);
if (filldir if (filldir
(dirent, local_buf, d_reclen, d_off, d_ino, (dirent, local_buf, d_reclen, d_off, d_ino,
DT_UNKNOWN) < 0) { DT_UNKNOWN) < 0) {
reiserfs_write_lock(inode->i_sb);
if (local_buf != small_buf) { if (local_buf != small_buf) {
kfree(local_buf); kfree(local_buf);
} }
goto end; goto end;
} }
reiserfs_write_lock(inode->i_sb);
if (local_buf != small_buf) { if (local_buf != small_buf) {
kfree(local_buf); kfree(local_buf);
} }
......
...@@ -1022,7 +1022,11 @@ static int get_far_parent(struct tree_balance *tb, ...@@ -1022,7 +1022,11 @@ static int get_far_parent(struct tree_balance *tb,
/* Check whether the common parent is locked. */ /* Check whether the common parent is locked. */
if (buffer_locked(*pcom_father)) { if (buffer_locked(*pcom_father)) {
/* Release the write lock while the buffer is busy */
reiserfs_write_unlock(tb->tb_sb);
__wait_on_buffer(*pcom_father); __wait_on_buffer(*pcom_father);
reiserfs_write_lock(tb->tb_sb);
if (FILESYSTEM_CHANGED_TB(tb)) { if (FILESYSTEM_CHANGED_TB(tb)) {
brelse(*pcom_father); brelse(*pcom_father);
return REPEAT_SEARCH; return REPEAT_SEARCH;
...@@ -1927,7 +1931,9 @@ static int get_direct_parent(struct tree_balance *tb, int h) ...@@ -1927,7 +1931,9 @@ static int get_direct_parent(struct tree_balance *tb, int h)
return REPEAT_SEARCH; return REPEAT_SEARCH;
if (buffer_locked(bh)) { if (buffer_locked(bh)) {
reiserfs_write_unlock(tb->tb_sb);
__wait_on_buffer(bh); __wait_on_buffer(bh);
reiserfs_write_lock(tb->tb_sb);
if (FILESYSTEM_CHANGED_TB(tb)) if (FILESYSTEM_CHANGED_TB(tb))
return REPEAT_SEARCH; return REPEAT_SEARCH;
} }
...@@ -2278,7 +2284,9 @@ static int wait_tb_buffers_until_unlocked(struct tree_balance *tb) ...@@ -2278,7 +2284,9 @@ static int wait_tb_buffers_until_unlocked(struct tree_balance *tb)
REPEAT_SEARCH : CARRY_ON; REPEAT_SEARCH : CARRY_ON;
} }
#endif #endif
reiserfs_write_unlock(tb->tb_sb);
__wait_on_buffer(locked); __wait_on_buffer(locked);
reiserfs_write_lock(tb->tb_sb);
if (FILESYSTEM_CHANGED_TB(tb)) if (FILESYSTEM_CHANGED_TB(tb))
return REPEAT_SEARCH; return REPEAT_SEARCH;
} }
...@@ -2349,7 +2357,9 @@ int fix_nodes(int op_mode, struct tree_balance *tb, ...@@ -2349,7 +2357,9 @@ int fix_nodes(int op_mode, struct tree_balance *tb,
/* if it possible in indirect_to_direct conversion */ /* if it possible in indirect_to_direct conversion */
if (buffer_locked(tbS0)) { if (buffer_locked(tbS0)) {
reiserfs_write_unlock(tb->tb_sb);
__wait_on_buffer(tbS0); __wait_on_buffer(tbS0);
reiserfs_write_lock(tb->tb_sb);
if (FILESYSTEM_CHANGED_TB(tb)) if (FILESYSTEM_CHANGED_TB(tb))
return REPEAT_SEARCH; return REPEAT_SEARCH;
} }
......
...@@ -489,10 +489,14 @@ static int reiserfs_get_blocks_direct_io(struct inode *inode, ...@@ -489,10 +489,14 @@ static int reiserfs_get_blocks_direct_io(struct inode *inode,
disappeared */ disappeared */
if (REISERFS_I(inode)->i_flags & i_pack_on_close_mask) { if (REISERFS_I(inode)->i_flags & i_pack_on_close_mask) {
int err; int err;
lock_kernel();
reiserfs_write_lock(inode->i_sb);
err = reiserfs_commit_for_inode(inode); err = reiserfs_commit_for_inode(inode);
REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask; REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask;
unlock_kernel();
reiserfs_write_unlock(inode->i_sb);
if (err < 0) if (err < 0)
ret = err; ret = err;
} }
...@@ -616,7 +620,6 @@ int reiserfs_get_block(struct inode *inode, sector_t block, ...@@ -616,7 +620,6 @@ int reiserfs_get_block(struct inode *inode, sector_t block,
loff_t new_offset = loff_t new_offset =
(((loff_t) block) << inode->i_sb->s_blocksize_bits) + 1; (((loff_t) block) << inode->i_sb->s_blocksize_bits) + 1;
/* bad.... */
reiserfs_write_lock(inode->i_sb); reiserfs_write_lock(inode->i_sb);
version = get_inode_item_key_version(inode); version = get_inode_item_key_version(inode);
...@@ -997,10 +1000,14 @@ int reiserfs_get_block(struct inode *inode, sector_t block, ...@@ -997,10 +1000,14 @@ int reiserfs_get_block(struct inode *inode, sector_t block,
if (retval) if (retval)
goto failure; goto failure;
} }
/* inserting indirect pointers for a hole can take a /*
** long time. reschedule if needed * inserting indirect pointers for a hole can take a
* long time. reschedule if needed and also release the write
* lock for others.
*/ */
reiserfs_write_unlock(inode->i_sb);
cond_resched(); cond_resched();
reiserfs_write_lock(inode->i_sb);
retval = search_for_position_by_key(inode->i_sb, &key, &path); retval = search_for_position_by_key(inode->i_sb, &key, &path);
if (retval == IO_ERROR) { if (retval == IO_ERROR) {
...@@ -2608,7 +2615,10 @@ int reiserfs_prepare_write(struct file *f, struct page *page, ...@@ -2608,7 +2615,10 @@ int reiserfs_prepare_write(struct file *f, struct page *page,
int ret; int ret;
int old_ref = 0; int old_ref = 0;
reiserfs_write_unlock(inode->i_sb);
reiserfs_wait_on_write_block(inode->i_sb); reiserfs_wait_on_write_block(inode->i_sb);
reiserfs_write_lock(inode->i_sb);
fix_tail_page_for_writing(page); fix_tail_page_for_writing(page);
if (reiserfs_transaction_running(inode->i_sb)) { if (reiserfs_transaction_running(inode->i_sb)) {
struct reiserfs_transaction_handle *th; struct reiserfs_transaction_handle *th;
...@@ -2758,7 +2768,10 @@ int reiserfs_commit_write(struct file *f, struct page *page, ...@@ -2758,7 +2768,10 @@ int reiserfs_commit_write(struct file *f, struct page *page,
int update_sd = 0; int update_sd = 0;
struct reiserfs_transaction_handle *th = NULL; struct reiserfs_transaction_handle *th = NULL;
reiserfs_write_unlock(inode->i_sb);
reiserfs_wait_on_write_block(inode->i_sb); reiserfs_wait_on_write_block(inode->i_sb);
reiserfs_write_lock(inode->i_sb);
if (reiserfs_transaction_running(inode->i_sb)) { if (reiserfs_transaction_running(inode->i_sb)) {
th = current->journal_info; th = current->journal_info;
} }
......
...@@ -141,9 +141,11 @@ long reiserfs_compat_ioctl(struct file *file, unsigned int cmd, ...@@ -141,9 +141,11 @@ long reiserfs_compat_ioctl(struct file *file, unsigned int cmd,
default: default:
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
} }
lock_kernel();
reiserfs_write_lock(inode->i_sb);
ret = reiserfs_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg)); ret = reiserfs_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg));
unlock_kernel(); reiserfs_write_unlock(inode->i_sb);
return ret; return ret;
} }
#endif #endif
......
This diff is collapsed.
#include <linux/reiserfs_fs.h>
#include <linux/mutex.h>
/*
* The previous reiserfs locking scheme was heavily based on
* the tricky properties of the Bkl:
*
* - it was acquired recursively by a same task
* - the performances relied on the release-while-schedule() property
*
* Now that we replace it by a mutex, we still want to keep the same
* recursive property to avoid big changes in the code structure.
* We use our own lock_owner here because the owner field on a mutex
* is only available in SMP or mutex debugging, also we only need this field
* for this mutex, no need for a system wide mutex facility.
*
* Also this lock is often released before a call that could block because
* reiserfs performances were partialy based on the release while schedule()
* property of the Bkl.
*/
void reiserfs_write_lock(struct super_block *s)
{
struct reiserfs_sb_info *sb_i = REISERFS_SB(s);
if (sb_i->lock_owner != current) {
mutex_lock(&sb_i->lock);
sb_i->lock_owner = current;
}
/* No need to protect it, only the current task touches it */
sb_i->lock_depth++;
}
void reiserfs_write_unlock(struct super_block *s)
{
struct reiserfs_sb_info *sb_i = REISERFS_SB(s);
/*
* Are we unlocking without even holding the lock?
* Such a situation could even raise a BUG() if we don't
* want the data become corrupted
*/
WARN_ONCE(sb_i->lock_owner != current,
"Superblock write lock imbalance");
if (--sb_i->lock_depth == -1) {
sb_i->lock_owner = NULL;
mutex_unlock(&sb_i->lock);
}
}
/*
* Utility function to force a BUG if it is called without the superblock
* write lock held. caller is the string printed just before calling BUG()
*/
void reiserfs_check_lock_depth(struct super_block *sb, char *caller)
{
struct reiserfs_sb_info *sb_i = REISERFS_SB(sb);
if (sb_i->lock_depth < 0)
reiserfs_panic(sb, "%s called without kernel lock held %d",
caller);
}
...@@ -141,7 +141,9 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new) ...@@ -141,7 +141,9 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
set_buffer_uptodate(bh); set_buffer_uptodate(bh);
mark_buffer_dirty(bh); mark_buffer_dirty(bh);
reiserfs_write_unlock(s);
sync_dirty_buffer(bh); sync_dirty_buffer(bh);
reiserfs_write_lock(s);
// update bitmap_info stuff // update bitmap_info stuff
bitmap[i].free_count = sb_blocksize(sb) * 8 - 1; bitmap[i].free_count = sb_blocksize(sb) * 8 - 1;
brelse(bh); brelse(bh);
......
...@@ -629,7 +629,9 @@ int search_by_key(struct super_block *sb, const struct cpu_key *key, /* Key to s ...@@ -629,7 +629,9 @@ int search_by_key(struct super_block *sb, const struct cpu_key *key, /* Key to s
search_by_key_reada(sb, reada_bh, search_by_key_reada(sb, reada_bh,
reada_blocks, reada_count); reada_blocks, reada_count);
ll_rw_block(READ, 1, &bh); ll_rw_block(READ, 1, &bh);
reiserfs_write_unlock(sb);
wait_on_buffer(bh); wait_on_buffer(bh);
reiserfs_write_lock(sb);
if (!buffer_uptodate(bh)) if (!buffer_uptodate(bh))
goto io_error; goto io_error;
} else { } else {
......
...@@ -465,7 +465,7 @@ static void reiserfs_put_super(struct super_block *s) ...@@ -465,7 +465,7 @@ static void reiserfs_put_super(struct super_block *s)
struct reiserfs_transaction_handle th; struct reiserfs_transaction_handle th;
th.t_trans_id = 0; th.t_trans_id = 0;
lock_kernel(); reiserfs_write_lock(s);
if (s->s_dirt) if (s->s_dirt)
reiserfs_write_super(s); reiserfs_write_super(s);
...@@ -499,10 +499,10 @@ static void reiserfs_put_super(struct super_block *s) ...@@ -499,10 +499,10 @@ static void reiserfs_put_super(struct super_block *s)
reiserfs_proc_info_done(s); reiserfs_proc_info_done(s);
reiserfs_write_unlock(s);
mutex_destroy(&REISERFS_SB(s)->lock);
kfree(s->s_fs_info); kfree(s->s_fs_info);
s->s_fs_info = NULL; s->s_fs_info = NULL;
unlock_kernel();
} }
static struct kmem_cache *reiserfs_inode_cachep; static struct kmem_cache *reiserfs_inode_cachep;
...@@ -1168,11 +1168,14 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) ...@@ -1168,11 +1168,14 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
unsigned int qfmt = 0; unsigned int qfmt = 0;
#ifdef CONFIG_QUOTA #ifdef CONFIG_QUOTA
int i; int i;
#endif
reiserfs_write_lock(s);
#ifdef CONFIG_QUOTA
memcpy(qf_names, REISERFS_SB(s)->s_qf_names, sizeof(qf_names)); memcpy(qf_names, REISERFS_SB(s)->s_qf_names, sizeof(qf_names));
#endif #endif
lock_kernel();
rs = SB_DISK_SUPER_BLOCK(s); rs = SB_DISK_SUPER_BLOCK(s);
if (!reiserfs_parse_options if (!reiserfs_parse_options
...@@ -1295,12 +1298,12 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) ...@@ -1295,12 +1298,12 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
out_ok: out_ok:
replace_mount_options(s, new_opts); replace_mount_options(s, new_opts);
unlock_kernel(); reiserfs_write_unlock(s);
return 0; return 0;
out_err: out_err:
kfree(new_opts); kfree(new_opts);
unlock_kernel(); reiserfs_write_unlock(s);
return err; return err;
} }
...@@ -1404,7 +1407,9 @@ static int read_super_block(struct super_block *s, int offset) ...@@ -1404,7 +1407,9 @@ static int read_super_block(struct super_block *s, int offset)
static int reread_meta_blocks(struct super_block *s) static int reread_meta_blocks(struct super_block *s)
{ {
ll_rw_block(READ, 1, &(SB_BUFFER_WITH_SB(s))); ll_rw_block(READ, 1, &(SB_BUFFER_WITH_SB(s)));
reiserfs_write_unlock(s);
wait_on_buffer(SB_BUFFER_WITH_SB(s)); wait_on_buffer(SB_BUFFER_WITH_SB(s));
reiserfs_write_lock(s);
if (!buffer_uptodate(SB_BUFFER_WITH_SB(s))) { if (!buffer_uptodate(SB_BUFFER_WITH_SB(s))) {
reiserfs_warning(s, "reiserfs-2504", "error reading the super"); reiserfs_warning(s, "reiserfs-2504", "error reading the super");
return 1; return 1;
...@@ -1613,7 +1618,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) ...@@ -1613,7 +1618,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
sbi = kzalloc(sizeof(struct reiserfs_sb_info), GFP_KERNEL); sbi = kzalloc(sizeof(struct reiserfs_sb_info), GFP_KERNEL);
if (!sbi) { if (!sbi) {
errval = -ENOMEM; errval = -ENOMEM;
goto error; goto error_alloc;
} }
s->s_fs_info = sbi; s->s_fs_info = sbi;
/* Set default values for options: non-aggressive tails, RO on errors */ /* Set default values for options: non-aggressive tails, RO on errors */
...@@ -1627,6 +1632,20 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) ...@@ -1627,6 +1632,20 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
/* setup default block allocator options */ /* setup default block allocator options */
reiserfs_init_alloc_options(s); reiserfs_init_alloc_options(s);
mutex_init(&REISERFS_SB(s)->lock);
REISERFS_SB(s)->lock_depth = -1;
/*
* This function is called with the bkl, which also was the old
* locking used here.
* do_journal_begin() will soon check if we hold the lock (ie: was the
* bkl). This is likely because do_journal_begin() has several another
* callers because at this time, it doesn't seem to be necessary to
* protect against anything.
* Anyway, let's be conservative and lock for now.
*/
reiserfs_write_lock(s);
jdev_name = NULL; jdev_name = NULL;
if (reiserfs_parse_options if (reiserfs_parse_options
(s, (char *)data, &(sbi->s_mount_opt), &blocks, &jdev_name, (s, (char *)data, &(sbi->s_mount_opt), &blocks, &jdev_name,
...@@ -1852,9 +1871,13 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) ...@@ -1852,9 +1871,13 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
init_waitqueue_head(&(sbi->s_wait)); init_waitqueue_head(&(sbi->s_wait));
spin_lock_init(&sbi->bitmap_lock); spin_lock_init(&sbi->bitmap_lock);
reiserfs_write_unlock(s);
return (0); return (0);
error: error:
reiserfs_write_unlock(s);
error_alloc:
if (jinit_done) { /* kill the commit thread, free journal ram */ if (jinit_done) { /* kill the commit thread, free journal ram */
journal_release_error(NULL, s); journal_release_error(NULL, s);
} }
......
...@@ -52,11 +52,13 @@ ...@@ -52,11 +52,13 @@
#define REISERFS_IOC32_GETVERSION FS_IOC32_GETVERSION #define REISERFS_IOC32_GETVERSION FS_IOC32_GETVERSION
#define REISERFS_IOC32_SETVERSION FS_IOC32_SETVERSION #define REISERFS_IOC32_SETVERSION FS_IOC32_SETVERSION
/* Locking primitives */ /*
/* Right now we are still falling back to (un)lock_kernel, but eventually that * Locking primitives. The write lock is a per superblock
would evolve into real per-fs locks */ * special mutex that has properties close to the Big Kernel Lock
#define reiserfs_write_lock( sb ) lock_kernel() * which was used in the previous locking scheme.
#define reiserfs_write_unlock( sb ) unlock_kernel() */
void reiserfs_write_lock(struct super_block *s);
void reiserfs_write_unlock(struct super_block *s);
struct fid; struct fid;
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/rwsem.h> #include <linux/rwsem.h>
#include <linux/mutex.h>
#include <linux/sched.h>
#endif #endif
typedef enum { typedef enum {
...@@ -355,6 +357,13 @@ struct reiserfs_sb_info { ...@@ -355,6 +357,13 @@ struct reiserfs_sb_info {
struct reiserfs_journal *s_journal; /* pointer to journal information */ struct reiserfs_journal *s_journal; /* pointer to journal information */
unsigned short s_mount_state; /* reiserfs state (valid, invalid) */ unsigned short s_mount_state; /* reiserfs state (valid, invalid) */
/* Serialize writers access, replace the old bkl */
struct mutex lock;
/* Owner of the lock (can be recursive) */
struct task_struct *lock_owner;
/* Depth of the lock, start from -1 like the bkl */
int lock_depth;
/* Comment? -Hans */ /* Comment? -Hans */
void (*end_io_handler) (struct buffer_head *, int); void (*end_io_handler) (struct buffer_head *, int);
hashf_t s_hash_function; /* pointer to function which is used hashf_t s_hash_function; /* pointer to function which is used
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment