Commit 3307fbd1 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] ext3: move lock_kernel() down into the JBD layer.

This is the start of the ext3 scalability rework.  It basically comes in two
halves:

- ext3 BKL/lock_super removal and scalable inode/block allocators

- JBD locking rework.

The ext3 scalability work was completed a couple of months ago.

The JBD rework has been stable for a couple of weeks now.  My gut feeling is
that there should be one, maybe two bugs left in it, but no problems have
been discovered...


Performance-wise, throughput is increased by up to 2x on dual CPU.  10x on
16-way has been measured.  Given that current ext3 is able to chew two whole
CPUs spinning on locks on a 4-way, that wasn't especially suprising.

These patches were prepared by Alex Tomas <bzzz@tmi.comex.ru> and myself.


First patch: ext3 lock_kernel() removal.

The only reason why ext3 takes lock_kernel() is because it is requires by the
JBD API.

The patch removes the lock_kernels() from ext3 and pushes them down into JBD
itself.
parent 0d0d8534
......@@ -199,7 +199,6 @@ void ext3_delete_inode (struct inode * inode)
if (is_bad_inode(inode))
goto no_delete;
lock_kernel();
handle = start_transaction(inode);
if (IS_ERR(handle)) {
/* If we're going to skip the normal cleanup, we still
......@@ -208,7 +207,6 @@ void ext3_delete_inode (struct inode * inode)
ext3_orphan_del(NULL, inode);
ext3_std_error(inode->i_sb, PTR_ERR(handle));
unlock_kernel();
goto no_delete;
}
......@@ -241,7 +239,6 @@ void ext3_delete_inode (struct inode * inode)
else
ext3_free_inode(handle, inode);
ext3_journal_stop(handle);
unlock_kernel();
return;
no_delete:
clear_inode(inode); /* We must guarantee clearing of inode... */
......@@ -251,7 +248,6 @@ void ext3_discard_prealloc (struct inode * inode)
{
#ifdef EXT3_PREALLOCATE
struct ext3_inode_info *ei = EXT3_I(inode);
lock_kernel();
/* Writer: ->i_prealloc* */
if (ei->i_prealloc_count) {
unsigned short total = ei->i_prealloc_count;
......@@ -261,7 +257,6 @@ void ext3_discard_prealloc (struct inode * inode)
/* Writer: end */
ext3_free_blocks (inode, block, total);
}
unlock_kernel();
#endif
}
......@@ -781,7 +776,6 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock,
if (depth == 0)
goto out;
lock_kernel();
reread:
partial = ext3_get_branch(inode, depth, offsets, chain, &err);
......@@ -806,7 +800,6 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock,
partial--;
}
BUFFER_TRACE(bh_result, "returned");
unlock_kernel();
out:
return err;
}
......@@ -894,7 +887,6 @@ ext3_direct_io_get_blocks(struct inode *inode, sector_t iblock,
handle_t *handle = journal_current_handle();
int ret = 0;
lock_kernel();
if (handle && handle->h_buffer_credits <= EXT3_RESERVE_TRANS_BLOCKS) {
/*
* Getting low on buffer credits...
......@@ -911,7 +903,6 @@ ext3_direct_io_get_blocks(struct inode *inode, sector_t iblock,
bh_result, create, 0);
if (ret == 0)
bh_result->b_size = (1 << inode->i_blkbits);
unlock_kernel();
return ret;
}
......@@ -944,7 +935,6 @@ struct buffer_head *ext3_getblk(handle_t *handle, struct inode * inode,
For now, regular file writes use
ext3_get_block instead, so it's not a
problem. */
lock_kernel();
lock_buffer(bh);
BUFFER_TRACE(bh, "call get_create_access");
fatal = ext3_journal_get_create_access(handle, bh);
......@@ -957,7 +947,6 @@ struct buffer_head *ext3_getblk(handle_t *handle, struct inode * inode,
BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
err = ext3_journal_dirty_metadata(handle, bh);
if (!fatal) fatal = err;
unlock_kernel();
} else {
BUFFER_TRACE(bh, "not a new buffer");
}
......@@ -1094,15 +1083,12 @@ static int ext3_prepare_write(struct file *file, struct page *page,
int ret, needed_blocks = ext3_writepage_trans_blocks(inode);
handle_t *handle;
lock_kernel();
handle = ext3_journal_start(inode, needed_blocks);
if (IS_ERR(handle)) {
ret = PTR_ERR(handle);
goto out;
}
unlock_kernel();
ret = block_prepare_write(page, from, to, ext3_get_block);
lock_kernel();
if (ret != 0)
goto prepare_write_failed;
......@@ -1114,7 +1100,6 @@ static int ext3_prepare_write(struct file *file, struct page *page,
if (ret)
ext3_journal_stop(handle);
out:
unlock_kernel();
return ret;
}
......@@ -1150,7 +1135,6 @@ static int ext3_commit_write(struct file *file, struct page *page,
struct inode *inode = page->mapping->host;
int ret = 0, ret2;
lock_kernel();
if (ext3_should_journal_data(inode)) {
/*
* Here we duplicate the generic_commit_write() functionality
......@@ -1192,7 +1176,6 @@ static int ext3_commit_write(struct file *file, struct page *page,
}
}
ret2 = ext3_journal_stop(handle);
unlock_kernel();
if (!ret)
ret = ret2;
return ret;
......@@ -1334,7 +1317,6 @@ static int ext3_writepage(struct page *page, struct writeback_control *wbc)
* for a different filesystem. One *could* look for a
* nested transaction opportunity.
*/
lock_kernel();
if (ext3_journal_current_handle())
goto out_fail;
......@@ -1349,8 +1331,6 @@ static int ext3_writepage(struct page *page, struct writeback_control *wbc)
order_data = ext3_should_order_data(inode) ||
ext3_should_journal_data(inode);
unlock_kernel();
page_bufs = NULL; /* Purely to prevent compiler warning */
/* bget() all the buffers */
......@@ -1377,7 +1357,6 @@ static int ext3_writepage(struct page *page, struct writeback_control *wbc)
*/
handle = ext3_journal_current_handle();
lock_kernel();
/*
* And attach them to the current transaction. But only if
......@@ -1399,13 +1378,10 @@ static int ext3_writepage(struct page *page, struct writeback_control *wbc)
err = ext3_journal_stop(handle);
if (!ret)
ret = err;
unlock_kernel();
return ret;
out_fail:
unlock_kernel();
/*
* We have to fail this writepage to avoid cross-fs transactions.
* Put the page back on mapping->dirty_pages. The page's buffers'
......@@ -1463,17 +1439,13 @@ static int ext3_direct_IO(int rw, struct kiocb *iocb,
if (rw == WRITE) {
loff_t final_size = offset + count;
lock_kernel();
handle = ext3_journal_start(inode, DIO_CREDITS);
unlock_kernel();
if (IS_ERR(handle)) {
ret = PTR_ERR(handle);
goto out;
}
if (final_size > inode->i_size) {
lock_kernel();
ret = ext3_orphan_add(handle, inode);
unlock_kernel();
if (ret)
goto out_stop;
orphan = 1;
......@@ -1488,7 +1460,6 @@ static int ext3_direct_IO(int rw, struct kiocb *iocb,
if (handle) {
int err;
lock_kernel();
if (orphan)
ext3_orphan_del(handle, inode);
if (orphan && ret > 0) {
......@@ -1504,7 +1475,6 @@ static int ext3_direct_IO(int rw, struct kiocb *iocb,
err = ext3_journal_stop(handle);
if (ret == 0)
ret = err;
unlock_kernel();
}
out:
return ret;
......@@ -2034,12 +2004,10 @@ void ext3_truncate(struct inode * inode)
if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
return;
lock_kernel();
ext3_discard_prealloc(inode);
handle = start_transaction(inode);
if (IS_ERR(handle)) {
unlock_kernel();
return; /* AKPM: return what? */
}
......@@ -2163,7 +2131,6 @@ void ext3_truncate(struct inode * inode)
ext3_orphan_del(handle, inode);
ext3_journal_stop(handle);
unlock_kernel();
}
/*
......@@ -2560,8 +2527,6 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr)
return error;
}
lock_kernel();
if (S_ISREG(inode->i_mode) &&
attr->ia_valid & ATTR_SIZE && attr->ia_size < inode->i_size) {
handle_t *handle;
......@@ -2593,7 +2558,6 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr)
err_out:
ext3_std_error(inode->i_sb, error);
unlock_kernel();
if (!error)
error = rc;
return error;
......@@ -2739,7 +2703,6 @@ void ext3_dirty_inode(struct inode *inode)
handle_t *current_handle = ext3_journal_current_handle();
handle_t *handle;
lock_kernel();
handle = ext3_journal_start(inode, 2);
if (IS_ERR(handle))
goto out;
......@@ -2755,7 +2718,7 @@ void ext3_dirty_inode(struct inode *inode)
}
ext3_journal_stop(handle);
out:
unlock_kernel();
return;
}
#ifdef AKPM
......
......@@ -981,7 +981,6 @@ static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry)
if (dentry->d_name.len > EXT3_NAME_LEN)
return ERR_PTR(-ENAMETOOLONG);
lock_kernel();
bh = ext3_find_entry(dentry, &de);
inode = NULL;
if (bh) {
......@@ -989,12 +988,9 @@ static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry)
brelse (bh);
inode = iget(dir->i_sb, ino);
if (!inode) {
unlock_kernel();
if (!inode)
return ERR_PTR(-EACCES);
}
}
unlock_kernel();
if (inode)
return d_splice_alias(inode, dentry);
d_add(dentry, inode);
......@@ -1015,17 +1011,13 @@ struct dentry *ext3_get_parent(struct dentry *child)
dotdot.d_name.len = 2;
dotdot.d_parent = child; /* confusing, isn't it! */
lock_kernel();
bh = ext3_find_entry(&dotdot, &de);
inode = NULL;
if (!bh) {
unlock_kernel();
if (!bh)
return ERR_PTR(-ENOENT);
}
ino = le32_to_cpu(de->inode);
brelse(bh);
inode = iget(child->d_inode->i_sb, ino);
unlock_kernel();
if (!inode)
return ERR_PTR(-EACCES);
......@@ -1639,13 +1631,10 @@ static int ext3_create (struct inode * dir, struct dentry * dentry, int mode)
struct inode * inode;
int err;
lock_kernel();
handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3);
if (IS_ERR(handle)) {
unlock_kernel();
if (IS_ERR(handle))
return PTR_ERR(handle);
}
if (IS_DIRSYNC(dir))
handle->h_sync = 1;
......@@ -1662,7 +1651,6 @@ static int ext3_create (struct inode * dir, struct dentry * dentry, int mode)
err = ext3_add_nondir(handle, dentry, inode);
}
ext3_journal_stop(handle);
unlock_kernel();
return err;
}
......@@ -1673,13 +1661,10 @@ static int ext3_mknod (struct inode * dir, struct dentry *dentry,
struct inode *inode;
int err;
lock_kernel();
handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3);
if (IS_ERR(handle)) {
unlock_kernel();
if (IS_ERR(handle))
return PTR_ERR(handle);
}
if (IS_DIRSYNC(dir))
handle->h_sync = 1;
......@@ -1694,7 +1679,6 @@ static int ext3_mknod (struct inode * dir, struct dentry *dentry,
err = ext3_add_nondir(handle, dentry, inode);
}
ext3_journal_stop(handle);
unlock_kernel();
return err;
}
......@@ -1709,13 +1693,10 @@ static int ext3_mkdir(struct inode * dir, struct dentry * dentry, int mode)
if (dir->i_nlink >= EXT3_LINK_MAX)
return -EMLINK;
lock_kernel();
handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3);
if (IS_ERR(handle)) {
unlock_kernel();
if (IS_ERR(handle))
return PTR_ERR(handle);
}
if (IS_DIRSYNC(dir))
handle->h_sync = 1;
......@@ -1768,7 +1749,6 @@ static int ext3_mkdir(struct inode * dir, struct dentry * dentry, int mode)
d_instantiate(dentry, inode);
out_stop:
ext3_journal_stop(handle);
unlock_kernel();
return err;
}
......@@ -1993,12 +1973,9 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry)
struct ext3_dir_entry_2 * de;
handle_t *handle;
lock_kernel();
handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS);
if (IS_ERR(handle)) {
unlock_kernel();
if (IS_ERR(handle))
return PTR_ERR(handle);
}
retval = -ENOENT;
bh = ext3_find_entry (dentry, &de);
......@@ -2042,7 +2019,6 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry)
end_rmdir:
ext3_journal_stop(handle);
brelse (bh);
unlock_kernel();
return retval;
}
......@@ -2054,12 +2030,9 @@ static int ext3_unlink(struct inode * dir, struct dentry *dentry)
struct ext3_dir_entry_2 * de;
handle_t *handle;
lock_kernel();
handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS);
if (IS_ERR(handle)) {
unlock_kernel();
if (IS_ERR(handle))
return PTR_ERR(handle);
}
if (IS_DIRSYNC(dir))
handle->h_sync = 1;
......@@ -2097,7 +2070,6 @@ static int ext3_unlink(struct inode * dir, struct dentry *dentry)
end_unlink:
ext3_journal_stop(handle);
unlock_kernel();
brelse (bh);
return retval;
}
......@@ -2113,13 +2085,10 @@ static int ext3_symlink (struct inode * dir,
if (l > dir->i_sb->s_blocksize)
return -ENAMETOOLONG;
lock_kernel();
handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5);
if (IS_ERR(handle)) {
unlock_kernel();
if (IS_ERR(handle))
return PTR_ERR(handle);
}
if (IS_DIRSYNC(dir))
handle->h_sync = 1;
......@@ -2156,7 +2125,6 @@ static int ext3_symlink (struct inode * dir,
err = ext3_add_nondir(handle, dentry, inode);
out_stop:
ext3_journal_stop(handle);
unlock_kernel();
return err;
}
......@@ -2167,18 +2135,13 @@ static int ext3_link (struct dentry * old_dentry,
struct inode *inode = old_dentry->d_inode;
int err;
lock_kernel();
if (inode->i_nlink >= EXT3_LINK_MAX) {
unlock_kernel();
if (inode->i_nlink >= EXT3_LINK_MAX)
return -EMLINK;
}
handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
EXT3_INDEX_EXTRA_TRANS_BLOCKS);
if (IS_ERR(handle)) {
unlock_kernel();
if (IS_ERR(handle))
return PTR_ERR(handle);
}
if (IS_DIRSYNC(dir))
handle->h_sync = 1;
......@@ -2189,7 +2152,6 @@ static int ext3_link (struct dentry * old_dentry,
err = ext3_add_nondir(handle, dentry, inode);
ext3_journal_stop(handle);
unlock_kernel();
return err;
}
......@@ -2212,13 +2174,10 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
old_bh = new_bh = dir_bh = NULL;
lock_kernel();
handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS +
EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2);
if (IS_ERR(handle)) {
unlock_kernel();
if (IS_ERR(handle))
return PTR_ERR(handle);
}
if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir))
handle->h_sync = 1;
......@@ -2346,7 +2305,6 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
brelse (old_bh);
brelse (new_bh);
ext3_journal_stop(handle);
unlock_kernel();
return retval;
}
......@@ -2378,6 +2336,4 @@ struct inode_operations ext3_special_inode_operations = {
.listxattr = ext3_listxattr,
.removexattr = ext3_removexattr,
.permission = ext3_permission,
};
};
......@@ -1777,9 +1777,7 @@ int ext3_force_commit(struct super_block *sb)
journal = EXT3_SB(sb)->s_journal;
sb->s_dirt = 0;
lock_kernel(); /* important: lock down j_running_transaction */
ret = ext3_journal_force_commit(journal);
unlock_kernel();
return ret;
}
......@@ -1794,24 +1792,20 @@ int ext3_force_commit(struct super_block *sb)
void ext3_write_super (struct super_block * sb)
{
lock_kernel();
if (down_trylock(&sb->s_lock) == 0)
BUG();
sb->s_dirt = 0;
log_start_commit(EXT3_SB(sb)->s_journal, NULL);
unlock_kernel();
}
static int ext3_sync_fs(struct super_block *sb, int wait)
{
tid_t target;
lock_kernel();
sb->s_dirt = 0;
target = log_start_commit(EXT3_SB(sb)->s_journal, NULL);
if (wait)
log_wait_commit(EXT3_SB(sb)->s_journal, target);
unlock_kernel();
return 0;
}
......@@ -1823,7 +1817,6 @@ void ext3_write_super_lockfs(struct super_block *sb)
{
sb->s_dirt = 0;
lock_kernel(); /* 2.4.5 forgot to do this for us */
if (!(sb->s_flags & MS_RDONLY)) {
journal_t *journal = EXT3_SB(sb)->s_journal;
......@@ -1835,7 +1828,6 @@ void ext3_write_super_lockfs(struct super_block *sb)
EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
ext3_commit_super(sb, EXT3_SB(sb)->s_es, 1);
}
unlock_kernel();
}
/*
......@@ -1845,14 +1837,12 @@ void ext3_write_super_lockfs(struct super_block *sb)
void ext3_unlockfs(struct super_block *sb)
{
if (!(sb->s_flags & MS_RDONLY)) {
lock_kernel();
lock_super(sb);
/* Reser the needs_recovery flag before the fs is unlocked. */
EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
ext3_commit_super(sb, EXT3_SB(sb)->s_es, 1);
unlock_super(sb);
journal_unlock_updates(EXT3_SB(sb)->s_journal);
unlock_kernel();
}
}
......@@ -1997,7 +1987,9 @@ static int (*old_sync_dquot)(struct dquot *dquot);
static int ext3_sync_dquot(struct dquot *dquot)
{
int nblocks, ret;
int nblocks;
int ret;
int err;
handle_t *handle;
struct quota_info *dqops = sb_dqopt(dquot->dq_sb);
struct inode *qinode;
......@@ -2012,18 +2004,17 @@ static int ext3_sync_dquot(struct dquot *dquot)
default:
nblocks = EXT3_MAX_TRANS_DATA;
}
lock_kernel();
qinode = dqops->files[dquot->dq_type]->f_dentry->d_inode;
handle = ext3_journal_start(qinode, nblocks);
if (IS_ERR(handle)) {
unlock_kernel();
return PTR_ERR(handle);
ret = PTR_ERR(handle);
goto out;
}
unlock_kernel();
ret = old_sync_dquot(dquot);
lock_kernel();
ret = ext3_journal_stop(handle);
unlock_kernel();
err = ext3_journal_stop(handle);
if (ret == 0)
ret = err;
out:
return ret;
}
#endif
......
......@@ -849,7 +849,6 @@ ext3_xattr_set(struct inode *inode, int name_index, const char *name,
handle_t *handle;
int error, error2;
lock_kernel();
handle = ext3_journal_start(inode, EXT3_XATTR_TRANS_BLOCKS);
if (IS_ERR(handle))
error = PTR_ERR(handle);
......@@ -857,7 +856,6 @@ ext3_xattr_set(struct inode *inode, int name_index, const char *name,
error = ext3_xattr_set_handle(handle, inode, name_index, name,
value, value_len, flags);
error2 = ext3_journal_stop(handle);
unlock_kernel();
return error ? error : error2;
}
......
......@@ -531,9 +531,11 @@ int log_space_left (journal_t *journal)
*/
tid_t log_start_commit (journal_t *journal, transaction_t *transaction)
{
tid_t target = journal->j_commit_request;
tid_t target;
lock_kernel(); /* Protect journal->j_running_transaction */
target = journal->j_commit_request;
/*
* A NULL transaction asks us to commit the currently running
......@@ -968,10 +970,12 @@ void journal_update_superblock(journal_t *journal, int wait)
* any future commit will have to be careful to update the
* superblock again to re-record the true start of the log. */
lock_kernel();
if (sb->s_start)
journal->j_flags &= ~JFS_FLUSHED;
else
journal->j_flags |= JFS_FLUSHED;
unlock_kernel();
}
......@@ -1437,10 +1441,12 @@ void __journal_abort_hard (journal_t *journal)
printk (KERN_ERR "Aborting journal on device %s.\n",
journal_dev_name(journal, b));
lock_kernel();
journal->j_flags |= JFS_ABORT;
transaction = journal->j_running_transaction;
if (transaction)
log_start_commit(journal, transaction);
unlock_kernel();
}
/* Soft abort: record the abort error status in the journal superblock,
......@@ -1450,6 +1456,7 @@ void __journal_abort_soft (journal_t *journal, int errno)
if (journal->j_flags & JFS_ABORT)
return;
lock_kernel();
if (!journal->j_errno)
journal->j_errno = errno;
......@@ -1457,6 +1464,7 @@ void __journal_abort_soft (journal_t *journal, int errno)
if (errno)
journal_update_superblock(journal, 1);
unlock_kernel();
}
/**
......@@ -1528,10 +1536,12 @@ int journal_errno (journal_t *journal)
int err;
lock_journal(journal);
lock_kernel();
if (journal->j_flags & JFS_ABORT)
err = -EROFS;
else
err = journal->j_errno;
unlock_kernel();
unlock_journal(journal);
return err;
}
......@@ -1549,10 +1559,12 @@ int journal_clear_err (journal_t *journal)
int err = 0;
lock_journal(journal);
lock_kernel();
if (journal->j_flags & JFS_ABORT)
err = -EROFS;
else
journal->j_errno = 0;
unlock_kernel();
unlock_journal(journal);
return err;
}
......@@ -1567,8 +1579,10 @@ int journal_clear_err (journal_t *journal)
void journal_ack_err (journal_t *journal)
{
lock_journal(journal);
lock_kernel();
if (journal->j_errno)
journal->j_flags |= JFS_ACK_ERR;
unlock_kernel();
unlock_journal(journal);
}
......
......@@ -256,13 +256,14 @@ handle_t *journal_start(journal_t *journal, int nblocks)
current->journal_info = handle;
lock_kernel();
err = start_this_handle(journal, handle);
unlock_kernel();
if (err < 0) {
jbd_free_handle(handle);
current->journal_info = NULL;
return ERR_PTR(err);
handle = ERR_PTR(err);
}
return handle;
}
......@@ -307,19 +308,20 @@ int journal_extend (handle_t *handle, int nblocks)
"transaction not running\n", handle, nblocks);
goto error_out;
}
lock_kernel();
wanted = transaction->t_outstanding_credits + nblocks;
if (wanted > journal->j_max_transaction_buffers) {
jbd_debug(3, "denied handle %p %d blocks: "
"transaction too large\n", handle, nblocks);
goto error_out;
goto unlock;
}
if (wanted > log_space_left(journal)) {
jbd_debug(3, "denied handle %p %d blocks: "
"insufficient log space\n", handle, nblocks);
goto error_out;
goto unlock;
}
handle->h_buffer_credits += nblocks;
......@@ -327,7 +329,8 @@ int journal_extend (handle_t *handle, int nblocks)
result = 0;
jbd_debug(3, "extended handle %p by %d\n", handle, nblocks);
unlock:
unlock_kernel();
error_out:
unlock_journal (journal);
return result;
......@@ -366,6 +369,7 @@ int journal_restart(handle_t *handle, int nblocks)
J_ASSERT (transaction->t_updates > 0);
J_ASSERT (journal_current_handle() == handle);
lock_kernel();
transaction->t_outstanding_credits -= handle->h_buffer_credits;
transaction->t_updates--;
......@@ -377,6 +381,7 @@ int journal_restart(handle_t *handle, int nblocks)
handle->h_buffer_credits = nblocks;
ret = start_this_handle(journal, handle);
unlock_kernel();
return ret;
}
......@@ -394,7 +399,10 @@ int journal_restart(handle_t *handle, int nblocks)
void journal_lock_updates (journal_t *journal)
{
lock_journal(journal);
lock_kernel();
++journal->j_barrier_count;
unlock_kernel();
/* Wait until there are no running updates */
while (1) {
......@@ -433,7 +441,9 @@ void journal_unlock_updates (journal_t *journal)
J_ASSERT (journal->j_barrier_count != 0);
up(&journal->j_barrier);
lock_kernel();
--journal->j_barrier_count;
unlock_kernel();
wake_up(&journal->j_wait_transaction_locked);
unlock_journal(journal);
}
......@@ -710,7 +720,9 @@ int journal_get_write_access (handle_t *handle, struct buffer_head *bh)
* log thread also manipulates. Make sure that the buffer
* completes any outstanding IO before proceeding. */
lock_journal(journal);
lock_kernel();
rc = do_get_write_access(handle, jh, 0);
unlock_kernel();
journal_unlock_journal_head(jh);
unlock_journal(journal);
return rc;
......@@ -786,8 +798,10 @@ int journal_get_create_access (handle_t *handle, struct buffer_head *bh)
* which hits an assertion error.
*/
JBUFFER_TRACE(jh, "cancelling revoke");
lock_kernel();
journal_cancel_revoke(handle, jh);
journal_unlock_journal_head(jh);
unlock_kernel();
out:
unlock_journal(journal);
return err;
......@@ -832,6 +846,7 @@ int journal_get_undo_access (handle_t *handle, struct buffer_head *bh)
/* Do this first --- it can drop the journal lock, so we want to
* make sure that obtaining the committed_data is done
* atomically wrt. completion of any outstanding commits. */
lock_kernel();
err = do_get_write_access (handle, jh, 1);
if (err)
goto out;
......@@ -855,6 +870,7 @@ int journal_get_undo_access (handle_t *handle, struct buffer_head *bh)
}
out:
unlock_kernel();
if (!err)
J_ASSERT_JH(jh, jh->b_committed_data);
journal_unlock_journal_head(jh);
......@@ -1302,8 +1318,10 @@ void journal_callback_set(handle_t *handle,
void (*func)(struct journal_callback *jcb, int error),
struct journal_callback *jcb)
{
lock_kernel();
list_add_tail(&jcb->jcb_list, &handle->h_jcb);
jcb->jcb_func = func;
unlock_kernel();
}
......@@ -1366,6 +1384,7 @@ int journal_stop(handle_t *handle)
}
current->journal_info = NULL;
lock_kernel();
transaction->t_outstanding_credits -= handle->h_buffer_credits;
transaction->t_updates--;
if (!transaction->t_updates) {
......@@ -1404,6 +1423,7 @@ int journal_stop(handle_t *handle)
if (handle->h_sync && !(current->flags & PF_MEMALLOC))
err = log_wait_commit(journal, tid);
}
unlock_kernel();
jbd_free_handle(handle);
return err;
}
......@@ -1985,7 +2005,6 @@ void __journal_refile_buffer(struct journal_head *jh)
int was_dirty;
assert_spin_locked(&journal_datalist_lock);
J_ASSERT_JH(jh, kernel_locked());
/* If the buffer is now unused, just drop it. */
if (jh->b_next_transaction == NULL) {
......
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