提交 ec0ad730 编写于 作者: L Linus Torvalds

Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs

Pull ext3, reiserfs, udf & isofs fixes from Jan Kara:
 "The contains a bunch of ext3 cleanups and minor improvements, major
  reiserfs locking changes which should hopefully fix deadlocks
  introduced by BKL removal, and udf/isofs changes to refuse mounting fs
  rw instead of mounting it ro automatically which makes eject button
  work as expected for all media (see the changelog for why userspace
  should be ok with this change)"

* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
  jbd: use a single printk for jbd_debug()
  reiserfs: locking, release lock around quota operations
  reiserfs: locking, handle nested locks properly
  reiserfs: locking, push write lock out of xattr code
  jbd: relocate assert after state lock in journal_commit_transaction()
  udf: Refuse RW mount of the filesystem instead of making it RO
  udf: Standardize return values in mount sequence
  isofs: Refuse RW mount of the filesystem instead of making it RO
  ext3: allow specifying external journal by pathname mount option
  jbd: remove unneeded semicolon
...@@ -26,11 +26,12 @@ journal=inum When a journal already exists, this option is ignored. ...@@ -26,11 +26,12 @@ journal=inum When a journal already exists, this option is ignored.
Otherwise, it specifies the number of the inode which Otherwise, it specifies the number of the inode which
will represent the ext3 file system's journal file. will represent the ext3 file system's journal file.
journal_path=path
journal_dev=devnum When the external journal device's major/minor numbers journal_dev=devnum When the external journal device's major/minor numbers
have changed, this option allows the user to specify have changed, these options allow the user to specify
the new journal location. The journal device is the new journal location. The journal device is
identified through its new major/minor numbers encoded identified through either its new major/minor numbers
in devnum. encoded in devnum, or via a path to the device.
norecovery Don't load the journal on mounting. Note that this forces norecovery Don't load the journal on mounting. Note that this forces
noload mount of inconsistent filesystem, which can lead to noload mount of inconsistent filesystem, which can lead to
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/log2.h> #include <linux/log2.h>
#include <linux/cleancache.h> #include <linux/cleancache.h>
#include <linux/namei.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -819,6 +820,7 @@ enum { ...@@ -819,6 +820,7 @@ enum {
Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl,
Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, Opt_bh, Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, Opt_bh,
Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev, Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev,
Opt_journal_path,
Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
Opt_data_err_abort, Opt_data_err_ignore, Opt_data_err_abort, Opt_data_err_ignore,
Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
...@@ -860,6 +862,7 @@ static const match_table_t tokens = { ...@@ -860,6 +862,7 @@ static const match_table_t tokens = {
{Opt_journal_update, "journal=update"}, {Opt_journal_update, "journal=update"},
{Opt_journal_inum, "journal=%u"}, {Opt_journal_inum, "journal=%u"},
{Opt_journal_dev, "journal_dev=%u"}, {Opt_journal_dev, "journal_dev=%u"},
{Opt_journal_path, "journal_path=%s"},
{Opt_abort, "abort"}, {Opt_abort, "abort"},
{Opt_data_journal, "data=journal"}, {Opt_data_journal, "data=journal"},
{Opt_data_ordered, "data=ordered"}, {Opt_data_ordered, "data=ordered"},
...@@ -975,6 +978,11 @@ static int parse_options (char *options, struct super_block *sb, ...@@ -975,6 +978,11 @@ static int parse_options (char *options, struct super_block *sb,
int option; int option;
kuid_t uid; kuid_t uid;
kgid_t gid; kgid_t gid;
char *journal_path;
struct inode *journal_inode;
struct path path;
int error;
#ifdef CONFIG_QUOTA #ifdef CONFIG_QUOTA
int qfmt; int qfmt;
#endif #endif
...@@ -1129,6 +1137,41 @@ static int parse_options (char *options, struct super_block *sb, ...@@ -1129,6 +1137,41 @@ static int parse_options (char *options, struct super_block *sb,
return 0; return 0;
*journal_devnum = option; *journal_devnum = option;
break; break;
case Opt_journal_path:
if (is_remount) {
ext3_msg(sb, KERN_ERR, "error: cannot specify "
"journal on remount");
return 0;
}
journal_path = match_strdup(&args[0]);
if (!journal_path) {
ext3_msg(sb, KERN_ERR, "error: could not dup "
"journal device string");
return 0;
}
error = kern_path(journal_path, LOOKUP_FOLLOW, &path);
if (error) {
ext3_msg(sb, KERN_ERR, "error: could not find "
"journal device path: error %d", error);
kfree(journal_path);
return 0;
}
journal_inode = path.dentry->d_inode;
if (!S_ISBLK(journal_inode->i_mode)) {
ext3_msg(sb, KERN_ERR, "error: journal path %s "
"is not a block device", journal_path);
path_put(&path);
kfree(journal_path);
return 0;
}
*journal_devnum = new_encode_dev(journal_inode->i_rdev);
path_put(&path);
kfree(journal_path);
break;
case Opt_noload: case Opt_noload:
set_opt (sbi->s_mount_opt, NOLOAD); set_opt (sbi->s_mount_opt, NOLOAD);
break; break;
......
...@@ -117,8 +117,8 @@ static void destroy_inodecache(void) ...@@ -117,8 +117,8 @@ static void destroy_inodecache(void)
static int isofs_remount(struct super_block *sb, int *flags, char *data) static int isofs_remount(struct super_block *sb, int *flags, char *data)
{ {
/* we probably want a lot more here */ if (!(*flags & MS_RDONLY))
*flags |= MS_RDONLY; return -EROFS;
return 0; return 0;
} }
...@@ -763,15 +763,6 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent) ...@@ -763,15 +763,6 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
*/ */
s->s_maxbytes = 0x80000000000LL; s->s_maxbytes = 0x80000000000LL;
/*
* The CDROM is read-only, has no nodes (devices) on it, and since
* all of the files appear to be owned by root, we really do not want
* to allow suid. (suid or devices will not show up unless we have
* Rock Ridge extensions)
*/
s->s_flags |= MS_RDONLY /* | MS_NODEV | MS_NOSUID */;
/* Set this for reference. Its not currently used except on write /* Set this for reference. Its not currently used except on write
which we don't have .. */ which we don't have .. */
...@@ -1530,6 +1521,9 @@ struct inode *isofs_iget(struct super_block *sb, ...@@ -1530,6 +1521,9 @@ struct inode *isofs_iget(struct super_block *sb,
static struct dentry *isofs_mount(struct file_system_type *fs_type, static struct dentry *isofs_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data) int flags, const char *dev_name, void *data)
{ {
/* We don't support read-write mounts */
if (!(flags & MS_RDONLY))
return ERR_PTR(-EACCES);
return mount_bdev(fs_type, flags, dev_name, data, isofs_fill_super); return mount_bdev(fs_type, flags, dev_name, data, isofs_fill_super);
} }
......
...@@ -340,13 +340,13 @@ void journal_commit_transaction(journal_t *journal) ...@@ -340,13 +340,13 @@ void journal_commit_transaction(journal_t *journal)
J_ASSERT(journal->j_committing_transaction == NULL); J_ASSERT(journal->j_committing_transaction == NULL);
commit_transaction = journal->j_running_transaction; commit_transaction = journal->j_running_transaction;
J_ASSERT(commit_transaction->t_state == T_RUNNING);
trace_jbd_start_commit(journal, commit_transaction); trace_jbd_start_commit(journal, commit_transaction);
jbd_debug(1, "JBD: starting commit of transaction %d\n", jbd_debug(1, "JBD: starting commit of transaction %d\n",
commit_transaction->t_tid); commit_transaction->t_tid);
spin_lock(&journal->j_state_lock); spin_lock(&journal->j_state_lock);
J_ASSERT(commit_transaction->t_state == T_RUNNING);
commit_transaction->t_state = T_LOCKED; commit_transaction->t_state = T_LOCKED;
trace_jbd_commit_locking(journal, commit_transaction); trace_jbd_commit_locking(journal, commit_transaction);
......
...@@ -90,6 +90,24 @@ static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *); ...@@ -90,6 +90,24 @@ static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *);
static void __journal_abort_soft (journal_t *journal, int errno); static void __journal_abort_soft (journal_t *journal, int errno);
static const char *journal_dev_name(journal_t *journal, char *buffer); static const char *journal_dev_name(journal_t *journal, char *buffer);
#ifdef CONFIG_JBD_DEBUG
void __jbd_debug(int level, const char *file, const char *func,
unsigned int line, const char *fmt, ...)
{
struct va_format vaf;
va_list args;
if (level > journal_enable_debug)
return;
va_start(args, fmt);
vaf.fmt = fmt;
vaf.va = &args;
printk(KERN_DEBUG "%s: (%s, %u): %pV\n", file, func, line, &vaf);
va_end(args);
}
EXPORT_SYMBOL(__jbd_debug);
#endif
/* /*
* Helper function used to manage commit timeouts * Helper function used to manage commit timeouts
*/ */
......
...@@ -423,8 +423,11 @@ static void _reiserfs_free_block(struct reiserfs_transaction_handle *th, ...@@ -423,8 +423,11 @@ static void _reiserfs_free_block(struct reiserfs_transaction_handle *th,
set_sb_free_blocks(rs, sb_free_blocks(rs) + 1); set_sb_free_blocks(rs, sb_free_blocks(rs) + 1);
journal_mark_dirty(th, s, sbh); journal_mark_dirty(th, s, sbh);
if (for_unformatted) if (for_unformatted) {
int depth = reiserfs_write_unlock_nested(s);
dquot_free_block_nodirty(inode, 1); dquot_free_block_nodirty(inode, 1);
reiserfs_write_lock_nested(s, depth);
}
} }
void reiserfs_free_block(struct reiserfs_transaction_handle *th, void reiserfs_free_block(struct reiserfs_transaction_handle *th,
...@@ -1128,6 +1131,7 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start ...@@ -1128,6 +1131,7 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start
b_blocknr_t finish = SB_BLOCK_COUNT(s) - 1; b_blocknr_t finish = SB_BLOCK_COUNT(s) - 1;
int passno = 0; int passno = 0;
int nr_allocated = 0; int nr_allocated = 0;
int depth;
determine_prealloc_size(hint); determine_prealloc_size(hint);
if (!hint->formatted_node) { if (!hint->formatted_node) {
...@@ -1137,10 +1141,13 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start ...@@ -1137,10 +1141,13 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start
"reiserquota: allocating %d blocks id=%u", "reiserquota: allocating %d blocks id=%u",
amount_needed, hint->inode->i_uid); amount_needed, hint->inode->i_uid);
#endif #endif
depth = reiserfs_write_unlock_nested(s);
quota_ret = quota_ret =
dquot_alloc_block_nodirty(hint->inode, amount_needed); dquot_alloc_block_nodirty(hint->inode, amount_needed);
if (quota_ret) /* Quota exceeded? */ if (quota_ret) { /* Quota exceeded? */
reiserfs_write_lock_nested(s, depth);
return QUOTA_EXCEEDED; return QUOTA_EXCEEDED;
}
if (hint->preallocate && hint->prealloc_size) { if (hint->preallocate && hint->prealloc_size) {
#ifdef REISERQUOTA_DEBUG #ifdef REISERQUOTA_DEBUG
reiserfs_debug(s, REISERFS_DEBUG_CODE, reiserfs_debug(s, REISERFS_DEBUG_CODE,
...@@ -1153,6 +1160,7 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start ...@@ -1153,6 +1160,7 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start
hint->preallocate = hint->prealloc_size = 0; hint->preallocate = hint->prealloc_size = 0;
} }
/* for unformatted nodes, force large allocations */ /* for unformatted nodes, force large allocations */
reiserfs_write_lock_nested(s, depth);
} }
do { do {
...@@ -1181,9 +1189,11 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start ...@@ -1181,9 +1189,11 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start
hint->inode->i_uid); hint->inode->i_uid);
#endif #endif
/* Free not allocated blocks */ /* Free not allocated blocks */
depth = reiserfs_write_unlock_nested(s);
dquot_free_block_nodirty(hint->inode, dquot_free_block_nodirty(hint->inode,
amount_needed + hint->prealloc_size - amount_needed + hint->prealloc_size -
nr_allocated); nr_allocated);
reiserfs_write_lock_nested(s, depth);
} }
while (nr_allocated--) while (nr_allocated--)
reiserfs_free_block(hint->th, hint->inode, reiserfs_free_block(hint->th, hint->inode,
...@@ -1214,10 +1224,13 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start ...@@ -1214,10 +1224,13 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start
REISERFS_I(hint->inode)->i_prealloc_count, REISERFS_I(hint->inode)->i_prealloc_count,
hint->inode->i_uid); hint->inode->i_uid);
#endif #endif
depth = reiserfs_write_unlock_nested(s);
dquot_free_block_nodirty(hint->inode, amount_needed + dquot_free_block_nodirty(hint->inode, amount_needed +
hint->prealloc_size - nr_allocated - hint->prealloc_size - nr_allocated -
REISERFS_I(hint->inode)-> REISERFS_I(hint->inode)->
i_prealloc_count); i_prealloc_count);
reiserfs_write_lock_nested(s, depth);
} }
return CARRY_ON; return CARRY_ON;
...@@ -1340,10 +1353,11 @@ struct buffer_head *reiserfs_read_bitmap_block(struct super_block *sb, ...@@ -1340,10 +1353,11 @@ struct buffer_head *reiserfs_read_bitmap_block(struct super_block *sb,
"reading failed", __func__, block); "reading failed", __func__, block);
else { else {
if (buffer_locked(bh)) { if (buffer_locked(bh)) {
int depth;
PROC_INFO_INC(sb, scan_bitmap.wait); PROC_INFO_INC(sb, scan_bitmap.wait);
reiserfs_write_unlock(sb); depth = reiserfs_write_unlock_nested(sb);
__wait_on_buffer(bh); __wait_on_buffer(bh);
reiserfs_write_lock(sb); reiserfs_write_lock_nested(sb, depth);
} }
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);
......
...@@ -71,6 +71,7 @@ int reiserfs_readdir_inode(struct inode *inode, struct dir_context *ctx) ...@@ -71,6 +71,7 @@ int reiserfs_readdir_inode(struct inode *inode, struct dir_context *ctx)
char small_buf[32]; /* avoid kmalloc if we can */ char small_buf[32]; /* avoid kmalloc if we can */
struct reiserfs_dir_entry de; struct reiserfs_dir_entry de;
int ret = 0; int ret = 0;
int depth;
reiserfs_write_lock(inode->i_sb); reiserfs_write_lock(inode->i_sb);
...@@ -181,17 +182,17 @@ int reiserfs_readdir_inode(struct inode *inode, struct dir_context *ctx) ...@@ -181,17 +182,17 @@ int reiserfs_readdir_inode(struct inode *inode, struct dir_context *ctx)
* Since filldir might sleep, we can release * Since filldir might sleep, we can release
* the write lock here for other waiters * the write lock here for other waiters
*/ */
reiserfs_write_unlock(inode->i_sb); depth = reiserfs_write_unlock_nested(inode->i_sb);
if (!dir_emit if (!dir_emit
(ctx, local_buf, d_reclen, d_ino, (ctx, local_buf, d_reclen, d_ino,
DT_UNKNOWN)) { DT_UNKNOWN)) {
reiserfs_write_lock(inode->i_sb); reiserfs_write_lock_nested(inode->i_sb, depth);
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); reiserfs_write_lock_nested(inode->i_sb, depth);
if (local_buf != small_buf) { if (local_buf != small_buf) {
kfree(local_buf); kfree(local_buf);
} }
......
...@@ -1022,9 +1022,9 @@ static int get_far_parent(struct tree_balance *tb, ...@@ -1022,9 +1022,9 @@ static int get_far_parent(struct tree_balance *tb,
if (buffer_locked(*pcom_father)) { if (buffer_locked(*pcom_father)) {
/* Release the write lock while the buffer is busy */ /* Release the write lock while the buffer is busy */
reiserfs_write_unlock(tb->tb_sb); int depth = reiserfs_write_unlock_nested(tb->tb_sb);
__wait_on_buffer(*pcom_father); __wait_on_buffer(*pcom_father);
reiserfs_write_lock(tb->tb_sb); reiserfs_write_lock_nested(tb->tb_sb, depth);
if (FILESYSTEM_CHANGED_TB(tb)) { if (FILESYSTEM_CHANGED_TB(tb)) {
brelse(*pcom_father); brelse(*pcom_father);
return REPEAT_SEARCH; return REPEAT_SEARCH;
...@@ -1929,9 +1929,9 @@ static int get_direct_parent(struct tree_balance *tb, int h) ...@@ -1929,9 +1929,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); int depth = reiserfs_write_unlock_nested(tb->tb_sb);
__wait_on_buffer(bh); __wait_on_buffer(bh);
reiserfs_write_lock(tb->tb_sb); reiserfs_write_lock_nested(tb->tb_sb, depth);
if (FILESYSTEM_CHANGED_TB(tb)) if (FILESYSTEM_CHANGED_TB(tb))
return REPEAT_SEARCH; return REPEAT_SEARCH;
} }
...@@ -1952,6 +1952,7 @@ static int get_neighbors(struct tree_balance *tb, int h) ...@@ -1952,6 +1952,7 @@ static int get_neighbors(struct tree_balance *tb, int h)
unsigned long son_number; unsigned long son_number;
struct super_block *sb = tb->tb_sb; struct super_block *sb = tb->tb_sb;
struct buffer_head *bh; struct buffer_head *bh;
int depth;
PROC_INFO_INC(sb, get_neighbors[h]); PROC_INFO_INC(sb, get_neighbors[h]);
...@@ -1969,9 +1970,9 @@ static int get_neighbors(struct tree_balance *tb, int h) ...@@ -1969,9 +1970,9 @@ static int get_neighbors(struct tree_balance *tb, int h)
tb->FL[h]) ? tb->lkey[h] : B_NR_ITEMS(tb-> tb->FL[h]) ? tb->lkey[h] : B_NR_ITEMS(tb->
FL[h]); FL[h]);
son_number = B_N_CHILD_NUM(tb->FL[h], child_position); son_number = B_N_CHILD_NUM(tb->FL[h], child_position);
reiserfs_write_unlock(sb); depth = reiserfs_write_unlock_nested(tb->tb_sb);
bh = sb_bread(sb, son_number); bh = sb_bread(sb, son_number);
reiserfs_write_lock(sb); reiserfs_write_lock_nested(tb->tb_sb, depth);
if (!bh) if (!bh)
return IO_ERROR; return IO_ERROR;
if (FILESYSTEM_CHANGED_TB(tb)) { if (FILESYSTEM_CHANGED_TB(tb)) {
...@@ -2009,9 +2010,9 @@ static int get_neighbors(struct tree_balance *tb, int h) ...@@ -2009,9 +2010,9 @@ static int get_neighbors(struct tree_balance *tb, int h)
child_position = child_position =
(bh == tb->FR[h]) ? tb->rkey[h] + 1 : 0; (bh == tb->FR[h]) ? tb->rkey[h] + 1 : 0;
son_number = B_N_CHILD_NUM(tb->FR[h], child_position); son_number = B_N_CHILD_NUM(tb->FR[h], child_position);
reiserfs_write_unlock(sb); depth = reiserfs_write_unlock_nested(tb->tb_sb);
bh = sb_bread(sb, son_number); bh = sb_bread(sb, son_number);
reiserfs_write_lock(sb); reiserfs_write_lock_nested(tb->tb_sb, depth);
if (!bh) if (!bh)
return IO_ERROR; return IO_ERROR;
if (FILESYSTEM_CHANGED_TB(tb)) { if (FILESYSTEM_CHANGED_TB(tb)) {
...@@ -2272,6 +2273,7 @@ static int wait_tb_buffers_until_unlocked(struct tree_balance *tb) ...@@ -2272,6 +2273,7 @@ static int wait_tb_buffers_until_unlocked(struct tree_balance *tb)
} }
if (locked) { if (locked) {
int depth;
#ifdef CONFIG_REISERFS_CHECK #ifdef CONFIG_REISERFS_CHECK
repeat_counter++; repeat_counter++;
if ((repeat_counter % 10000) == 0) { if ((repeat_counter % 10000) == 0) {
...@@ -2286,9 +2288,9 @@ static int wait_tb_buffers_until_unlocked(struct tree_balance *tb) ...@@ -2286,9 +2288,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); depth = reiserfs_write_unlock_nested(tb->tb_sb);
__wait_on_buffer(locked); __wait_on_buffer(locked);
reiserfs_write_lock(tb->tb_sb); reiserfs_write_lock_nested(tb->tb_sb, depth);
if (FILESYSTEM_CHANGED_TB(tb)) if (FILESYSTEM_CHANGED_TB(tb))
return REPEAT_SEARCH; return REPEAT_SEARCH;
} }
...@@ -2359,9 +2361,9 @@ int fix_nodes(int op_mode, struct tree_balance *tb, ...@@ -2359,9 +2361,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); int depth = reiserfs_write_unlock_nested(tb->tb_sb);
__wait_on_buffer(tbS0); __wait_on_buffer(tbS0);
reiserfs_write_lock(tb->tb_sb); reiserfs_write_lock_nested(tb->tb_sb, depth);
if (FILESYSTEM_CHANGED_TB(tb)) if (FILESYSTEM_CHANGED_TB(tb))
return REPEAT_SEARCH; return REPEAT_SEARCH;
} }
......
...@@ -30,7 +30,6 @@ void reiserfs_evict_inode(struct inode *inode) ...@@ -30,7 +30,6 @@ void reiserfs_evict_inode(struct inode *inode)
JOURNAL_PER_BALANCE_CNT * 2 + JOURNAL_PER_BALANCE_CNT * 2 +
2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb); 2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb);
struct reiserfs_transaction_handle th; struct reiserfs_transaction_handle th;
int depth;
int err; int err;
if (!inode->i_nlink && !is_bad_inode(inode)) if (!inode->i_nlink && !is_bad_inode(inode))
...@@ -40,12 +39,13 @@ void reiserfs_evict_inode(struct inode *inode) ...@@ -40,12 +39,13 @@ void reiserfs_evict_inode(struct inode *inode)
if (inode->i_nlink) if (inode->i_nlink)
goto no_delete; goto no_delete;
depth = reiserfs_write_lock_once(inode->i_sb);
/* The = 0 happens when we abort creating a new inode for some reason like lack of space.. */ /* The = 0 happens when we abort creating a new inode for some reason like lack of space.. */
if (!(inode->i_state & I_NEW) && INODE_PKEY(inode)->k_objectid != 0) { /* also handles bad_inode case */ if (!(inode->i_state & I_NEW) && INODE_PKEY(inode)->k_objectid != 0) { /* also handles bad_inode case */
reiserfs_delete_xattrs(inode); reiserfs_delete_xattrs(inode);
reiserfs_write_lock(inode->i_sb);
if (journal_begin(&th, inode->i_sb, jbegin_count)) if (journal_begin(&th, inode->i_sb, jbegin_count))
goto out; goto out;
reiserfs_update_inode_transaction(inode); reiserfs_update_inode_transaction(inode);
...@@ -57,8 +57,11 @@ void reiserfs_evict_inode(struct inode *inode) ...@@ -57,8 +57,11 @@ void reiserfs_evict_inode(struct inode *inode)
/* Do quota update inside a transaction for journaled quotas. We must do that /* Do quota update inside a transaction for journaled quotas. We must do that
* after delete_object so that quota updates go into the same transaction as * after delete_object so that quota updates go into the same transaction as
* stat data deletion */ * stat data deletion */
if (!err) if (!err) {
int depth = reiserfs_write_unlock_nested(inode->i_sb);
dquot_free_inode(inode); dquot_free_inode(inode);
reiserfs_write_lock_nested(inode->i_sb, depth);
}
if (journal_end(&th, inode->i_sb, jbegin_count)) if (journal_end(&th, inode->i_sb, jbegin_count))
goto out; goto out;
...@@ -72,12 +75,12 @@ void reiserfs_evict_inode(struct inode *inode) ...@@ -72,12 +75,12 @@ void reiserfs_evict_inode(struct inode *inode)
/* all items of file are deleted, so we can remove "save" link */ /* all items of file are deleted, so we can remove "save" link */
remove_save_link(inode, 0 /* not truncate */ ); /* we can't do anything remove_save_link(inode, 0 /* not truncate */ ); /* we can't do anything
* about an error here */ * about an error here */
out:
reiserfs_write_unlock(inode->i_sb);
} else { } else {
/* no object items are in the tree */ /* no object items are in the tree */
; ;
} }
out:
reiserfs_write_unlock_once(inode->i_sb, depth);
clear_inode(inode); /* note this must go after the journal_end to prevent deadlock */ clear_inode(inode); /* note this must go after the journal_end to prevent deadlock */
dquot_drop(inode); dquot_drop(inode);
inode->i_blocks = 0; inode->i_blocks = 0;
...@@ -610,7 +613,6 @@ int reiserfs_get_block(struct inode *inode, sector_t block, ...@@ -610,7 +613,6 @@ int reiserfs_get_block(struct inode *inode, sector_t block,
__le32 *item; __le32 *item;
int done; int done;
int fs_gen; int fs_gen;
int lock_depth;
struct reiserfs_transaction_handle *th = NULL; struct reiserfs_transaction_handle *th = NULL;
/* space reserved in transaction batch: /* space reserved in transaction batch:
. 3 balancings in direct->indirect conversion . 3 balancings in direct->indirect conversion
...@@ -626,11 +628,11 @@ int reiserfs_get_block(struct inode *inode, sector_t block, ...@@ -626,11 +628,11 @@ 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;
lock_depth = reiserfs_write_lock_once(inode->i_sb); reiserfs_write_lock(inode->i_sb);
version = get_inode_item_key_version(inode); version = get_inode_item_key_version(inode);
if (!file_capable(inode, block)) { if (!file_capable(inode, block)) {
reiserfs_write_unlock_once(inode->i_sb, lock_depth); reiserfs_write_unlock(inode->i_sb);
return -EFBIG; return -EFBIG;
} }
...@@ -642,7 +644,7 @@ int reiserfs_get_block(struct inode *inode, sector_t block, ...@@ -642,7 +644,7 @@ int reiserfs_get_block(struct inode *inode, sector_t block,
/* find number of block-th logical block of the file */ /* find number of block-th logical block of the file */
ret = _get_block_create_0(inode, block, bh_result, ret = _get_block_create_0(inode, block, bh_result,
create | GET_BLOCK_READ_DIRECT); create | GET_BLOCK_READ_DIRECT);
reiserfs_write_unlock_once(inode->i_sb, lock_depth); reiserfs_write_unlock(inode->i_sb);
return ret; return ret;
} }
/* /*
...@@ -760,7 +762,7 @@ int reiserfs_get_block(struct inode *inode, sector_t block, ...@@ -760,7 +762,7 @@ int reiserfs_get_block(struct inode *inode, sector_t block,
if (!dangle && th) if (!dangle && th)
retval = reiserfs_end_persistent_transaction(th); retval = reiserfs_end_persistent_transaction(th);
reiserfs_write_unlock_once(inode->i_sb, lock_depth); reiserfs_write_unlock(inode->i_sb);
/* the item was found, so new blocks were not added to the file /* the item was found, so new blocks were not added to the file
** there is no need to make sure the inode is updated with this ** there is no need to make sure the inode is updated with this
...@@ -1011,11 +1013,7 @@ int reiserfs_get_block(struct inode *inode, sector_t block, ...@@ -1011,11 +1013,7 @@ int reiserfs_get_block(struct inode *inode, sector_t block,
* long time. reschedule if needed and also release the write * long time. reschedule if needed and also release the write
* lock for others. * lock for others.
*/ */
if (need_resched()) { reiserfs_cond_resched(inode->i_sb);
reiserfs_write_unlock_once(inode->i_sb, lock_depth);
schedule();
lock_depth = reiserfs_write_lock_once(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) {
...@@ -1050,7 +1048,7 @@ int reiserfs_get_block(struct inode *inode, sector_t block, ...@@ -1050,7 +1048,7 @@ int reiserfs_get_block(struct inode *inode, sector_t block,
retval = err; retval = err;
} }
reiserfs_write_unlock_once(inode->i_sb, lock_depth); reiserfs_write_unlock(inode->i_sb);
reiserfs_check_path(&path); reiserfs_check_path(&path);
return retval; return retval;
} }
...@@ -1509,14 +1507,15 @@ struct inode *reiserfs_iget(struct super_block *s, const struct cpu_key *key) ...@@ -1509,14 +1507,15 @@ struct inode *reiserfs_iget(struct super_block *s, const struct cpu_key *key)
{ {
struct inode *inode; struct inode *inode;
struct reiserfs_iget_args args; struct reiserfs_iget_args args;
int depth;
args.objectid = key->on_disk_key.k_objectid; args.objectid = key->on_disk_key.k_objectid;
args.dirid = key->on_disk_key.k_dir_id; args.dirid = key->on_disk_key.k_dir_id;
reiserfs_write_unlock(s); depth = reiserfs_write_unlock_nested(s);
inode = iget5_locked(s, key->on_disk_key.k_objectid, inode = iget5_locked(s, key->on_disk_key.k_objectid,
reiserfs_find_actor, reiserfs_init_locked_inode, reiserfs_find_actor, reiserfs_init_locked_inode,
(void *)(&args)); (void *)(&args));
reiserfs_write_lock(s); reiserfs_write_lock_nested(s, depth);
if (!inode) if (!inode)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
...@@ -1772,7 +1771,7 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, ...@@ -1772,7 +1771,7 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
struct inode *inode, struct inode *inode,
struct reiserfs_security_handle *security) struct reiserfs_security_handle *security)
{ {
struct super_block *sb; struct super_block *sb = dir->i_sb;
struct reiserfs_iget_args args; struct reiserfs_iget_args args;
INITIALIZE_PATH(path_to_key); INITIALIZE_PATH(path_to_key);
struct cpu_key key; struct cpu_key key;
...@@ -1780,12 +1779,13 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, ...@@ -1780,12 +1779,13 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
struct stat_data sd; struct stat_data sd;
int retval; int retval;
int err; int err;
int depth;
BUG_ON(!th->t_trans_id); BUG_ON(!th->t_trans_id);
reiserfs_write_unlock(inode->i_sb); depth = reiserfs_write_unlock_nested(sb);
err = dquot_alloc_inode(inode); err = dquot_alloc_inode(inode);
reiserfs_write_lock(inode->i_sb); reiserfs_write_lock_nested(sb, depth);
if (err) if (err)
goto out_end_trans; goto out_end_trans;
if (!dir->i_nlink) { if (!dir->i_nlink) {
...@@ -1793,8 +1793,6 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, ...@@ -1793,8 +1793,6 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
goto out_bad_inode; goto out_bad_inode;
} }
sb = dir->i_sb;
/* item head of new item */ /* item head of new item */
ih.ih_key.k_dir_id = reiserfs_choose_packing(dir); ih.ih_key.k_dir_id = reiserfs_choose_packing(dir);
ih.ih_key.k_objectid = cpu_to_le32(reiserfs_get_unused_objectid(th)); ih.ih_key.k_objectid = cpu_to_le32(reiserfs_get_unused_objectid(th));
...@@ -1812,10 +1810,10 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, ...@@ -1812,10 +1810,10 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
memcpy(INODE_PKEY(inode), &(ih.ih_key), KEY_SIZE); memcpy(INODE_PKEY(inode), &(ih.ih_key), KEY_SIZE);
args.dirid = le32_to_cpu(ih.ih_key.k_dir_id); args.dirid = le32_to_cpu(ih.ih_key.k_dir_id);
reiserfs_write_unlock(inode->i_sb); depth = reiserfs_write_unlock_nested(inode->i_sb);
err = insert_inode_locked4(inode, args.objectid, err = insert_inode_locked4(inode, args.objectid,
reiserfs_find_actor, &args); reiserfs_find_actor, &args);
reiserfs_write_lock(inode->i_sb); reiserfs_write_lock_nested(inode->i_sb, depth);
if (err) { if (err) {
err = -EINVAL; err = -EINVAL;
goto out_bad_inode; goto out_bad_inode;
...@@ -1941,7 +1939,9 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, ...@@ -1941,7 +1939,9 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
} }
if (reiserfs_posixacl(inode->i_sb)) { if (reiserfs_posixacl(inode->i_sb)) {
reiserfs_write_unlock(inode->i_sb);
retval = reiserfs_inherit_default_acl(th, dir, dentry, inode); retval = reiserfs_inherit_default_acl(th, dir, dentry, inode);
reiserfs_write_lock(inode->i_sb);
if (retval) { if (retval) {
err = retval; err = retval;
reiserfs_check_path(&path_to_key); reiserfs_check_path(&path_to_key);
...@@ -1956,7 +1956,9 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, ...@@ -1956,7 +1956,9 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
inode->i_flags |= S_PRIVATE; inode->i_flags |= S_PRIVATE;
if (security->name) { if (security->name) {
reiserfs_write_unlock(inode->i_sb);
retval = reiserfs_security_write(th, inode, security); retval = reiserfs_security_write(th, inode, security);
reiserfs_write_lock(inode->i_sb);
if (retval) { if (retval) {
err = retval; err = retval;
reiserfs_check_path(&path_to_key); reiserfs_check_path(&path_to_key);
...@@ -1982,14 +1984,16 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, ...@@ -1982,14 +1984,16 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
INODE_PKEY(inode)->k_objectid = 0; INODE_PKEY(inode)->k_objectid = 0;
/* Quota change must be inside a transaction for journaling */ /* Quota change must be inside a transaction for journaling */
depth = reiserfs_write_unlock_nested(inode->i_sb);
dquot_free_inode(inode); dquot_free_inode(inode);
reiserfs_write_lock_nested(inode->i_sb, depth);
out_end_trans: out_end_trans:
journal_end(th, th->t_super, th->t_blocks_allocated); journal_end(th, th->t_super, th->t_blocks_allocated);
reiserfs_write_unlock(inode->i_sb);
/* Drop can be outside and it needs more credits so it's better to have it outside */ /* Drop can be outside and it needs more credits so it's better to have it outside */
depth = reiserfs_write_unlock_nested(inode->i_sb);
dquot_drop(inode); dquot_drop(inode);
reiserfs_write_lock(inode->i_sb); reiserfs_write_lock_nested(inode->i_sb, depth);
inode->i_flags |= S_NOQUOTA; inode->i_flags |= S_NOQUOTA;
make_bad_inode(inode); make_bad_inode(inode);
...@@ -2103,9 +2107,8 @@ int reiserfs_truncate_file(struct inode *inode, int update_timestamps) ...@@ -2103,9 +2107,8 @@ int reiserfs_truncate_file(struct inode *inode, int update_timestamps)
int error; int error;
struct buffer_head *bh = NULL; struct buffer_head *bh = NULL;
int err2; int err2;
int lock_depth;
lock_depth = reiserfs_write_lock_once(inode->i_sb); reiserfs_write_lock(inode->i_sb);
if (inode->i_size > 0) { if (inode->i_size > 0) {
error = grab_tail_page(inode, &page, &bh); error = grab_tail_page(inode, &page, &bh);
...@@ -2174,7 +2177,7 @@ int reiserfs_truncate_file(struct inode *inode, int update_timestamps) ...@@ -2174,7 +2177,7 @@ int reiserfs_truncate_file(struct inode *inode, int update_timestamps)
page_cache_release(page); page_cache_release(page);
} }
reiserfs_write_unlock_once(inode->i_sb, lock_depth); reiserfs_write_unlock(inode->i_sb);
return 0; return 0;
out: out:
...@@ -2183,7 +2186,7 @@ int reiserfs_truncate_file(struct inode *inode, int update_timestamps) ...@@ -2183,7 +2186,7 @@ int reiserfs_truncate_file(struct inode *inode, int update_timestamps)
page_cache_release(page); page_cache_release(page);
} }
reiserfs_write_unlock_once(inode->i_sb, lock_depth); reiserfs_write_unlock(inode->i_sb);
return error; return error;
} }
...@@ -2648,10 +2651,11 @@ int __reiserfs_write_begin(struct page *page, unsigned from, unsigned len) ...@@ -2648,10 +2651,11 @@ int __reiserfs_write_begin(struct page *page, unsigned from, unsigned len)
struct inode *inode = page->mapping->host; struct inode *inode = page->mapping->host;
int ret; int ret;
int old_ref = 0; int old_ref = 0;
int depth;
reiserfs_write_unlock(inode->i_sb); depth = reiserfs_write_unlock_nested(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); reiserfs_write_lock_nested(inode->i_sb, depth);
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)) {
...@@ -2708,7 +2712,6 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping, ...@@ -2708,7 +2712,6 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping,
int update_sd = 0; int update_sd = 0;
struct reiserfs_transaction_handle *th; struct reiserfs_transaction_handle *th;
unsigned start; unsigned start;
int lock_depth = 0;
bool locked = false; bool locked = false;
if ((unsigned long)fsdata & AOP_FLAG_CONT_EXPAND) if ((unsigned long)fsdata & AOP_FLAG_CONT_EXPAND)
...@@ -2737,7 +2740,7 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping, ...@@ -2737,7 +2740,7 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping,
*/ */
if (pos + copied > inode->i_size) { if (pos + copied > inode->i_size) {
struct reiserfs_transaction_handle myth; struct reiserfs_transaction_handle myth;
lock_depth = reiserfs_write_lock_once(inode->i_sb); reiserfs_write_lock(inode->i_sb);
locked = true; locked = true;
/* If the file have grown beyond the border where it /* If the file have grown beyond the border where it
can have a tail, unmark it as needing a tail can have a tail, unmark it as needing a tail
...@@ -2768,7 +2771,7 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping, ...@@ -2768,7 +2771,7 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping,
} }
if (th) { if (th) {
if (!locked) { if (!locked) {
lock_depth = reiserfs_write_lock_once(inode->i_sb); reiserfs_write_lock(inode->i_sb);
locked = true; locked = true;
} }
if (!update_sd) if (!update_sd)
...@@ -2780,7 +2783,7 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping, ...@@ -2780,7 +2783,7 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping,
out: out:
if (locked) if (locked)
reiserfs_write_unlock_once(inode->i_sb, lock_depth); reiserfs_write_unlock(inode->i_sb);
unlock_page(page); unlock_page(page);
page_cache_release(page); page_cache_release(page);
...@@ -2790,7 +2793,7 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping, ...@@ -2790,7 +2793,7 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping,
return ret == 0 ? copied : ret; return ret == 0 ? copied : ret;
journal_error: journal_error:
reiserfs_write_unlock_once(inode->i_sb, lock_depth); reiserfs_write_unlock(inode->i_sb);
locked = false; locked = false;
if (th) { if (th) {
if (!update_sd) if (!update_sd)
...@@ -2808,10 +2811,11 @@ int reiserfs_commit_write(struct file *f, struct page *page, ...@@ -2808,10 +2811,11 @@ int reiserfs_commit_write(struct file *f, struct page *page,
int ret = 0; int ret = 0;
int update_sd = 0; int update_sd = 0;
struct reiserfs_transaction_handle *th = NULL; struct reiserfs_transaction_handle *th = NULL;
int depth;
reiserfs_write_unlock(inode->i_sb); depth = reiserfs_write_unlock_nested(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); reiserfs_write_lock_nested(inode->i_sb, depth);
if (reiserfs_transaction_running(inode->i_sb)) { if (reiserfs_transaction_running(inode->i_sb)) {
th = current->journal_info; th = current->journal_info;
...@@ -3110,7 +3114,6 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -3110,7 +3114,6 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
{ {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
unsigned int ia_valid; unsigned int ia_valid;
int depth;
int error; int error;
error = inode_change_ok(inode, attr); error = inode_change_ok(inode, attr);
...@@ -3122,13 +3125,14 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -3122,13 +3125,14 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
if (is_quota_modification(inode, attr)) if (is_quota_modification(inode, attr))
dquot_initialize(inode); dquot_initialize(inode);
depth = reiserfs_write_lock_once(inode->i_sb); reiserfs_write_lock(inode->i_sb);
if (attr->ia_valid & ATTR_SIZE) { if (attr->ia_valid & ATTR_SIZE) {
/* version 2 items will be caught by the s_maxbytes check /* version 2 items will be caught by the s_maxbytes check
** done for us in vmtruncate ** done for us in vmtruncate
*/ */
if (get_inode_item_key_version(inode) == KEY_FORMAT_3_5 && if (get_inode_item_key_version(inode) == KEY_FORMAT_3_5 &&
attr->ia_size > MAX_NON_LFS) { attr->ia_size > MAX_NON_LFS) {
reiserfs_write_unlock(inode->i_sb);
error = -EFBIG; error = -EFBIG;
goto out; goto out;
} }
...@@ -3150,8 +3154,10 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -3150,8 +3154,10 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
if (err) if (err)
error = err; error = err;
} }
if (error) if (error) {
reiserfs_write_unlock(inode->i_sb);
goto out; goto out;
}
/* /*
* file size is changed, ctime and mtime are * file size is changed, ctime and mtime are
* to be updated * to be updated
...@@ -3159,6 +3165,7 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -3159,6 +3165,7 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
attr->ia_valid |= (ATTR_MTIME | ATTR_CTIME); attr->ia_valid |= (ATTR_MTIME | ATTR_CTIME);
} }
} }
reiserfs_write_unlock(inode->i_sb);
if ((((attr->ia_valid & ATTR_UID) && (from_kuid(&init_user_ns, attr->ia_uid) & ~0xffff)) || if ((((attr->ia_valid & ATTR_UID) && (from_kuid(&init_user_ns, attr->ia_uid) & ~0xffff)) ||
((attr->ia_valid & ATTR_GID) && (from_kgid(&init_user_ns, attr->ia_gid) & ~0xffff))) && ((attr->ia_valid & ATTR_GID) && (from_kgid(&init_user_ns, attr->ia_gid) & ~0xffff))) &&
...@@ -3183,14 +3190,16 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -3183,14 +3190,16 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
return error; return error;
/* (user+group)*(old+new) structure - we count quota info and , inode write (sb, inode) */ /* (user+group)*(old+new) structure - we count quota info and , inode write (sb, inode) */
reiserfs_write_lock(inode->i_sb);
error = journal_begin(&th, inode->i_sb, jbegin_count); error = journal_begin(&th, inode->i_sb, jbegin_count);
reiserfs_write_unlock(inode->i_sb);
if (error) if (error)
goto out; goto out;
reiserfs_write_unlock_once(inode->i_sb, depth);
error = dquot_transfer(inode, attr); error = dquot_transfer(inode, attr);
depth = reiserfs_write_lock_once(inode->i_sb); reiserfs_write_lock(inode->i_sb);
if (error) { if (error) {
journal_end(&th, inode->i_sb, jbegin_count); journal_end(&th, inode->i_sb, jbegin_count);
reiserfs_write_unlock(inode->i_sb);
goto out; goto out;
} }
...@@ -3202,17 +3211,11 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -3202,17 +3211,11 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
inode->i_gid = attr->ia_gid; inode->i_gid = attr->ia_gid;
mark_inode_dirty(inode); mark_inode_dirty(inode);
error = journal_end(&th, inode->i_sb, jbegin_count); error = journal_end(&th, inode->i_sb, jbegin_count);
reiserfs_write_unlock(inode->i_sb);
if (error) if (error)
goto out; goto out;
} }
/*
* Relax the lock here, as it might truncate the
* inode pages and wait for inode pages locks.
* To release such page lock, the owner needs the
* reiserfs lock
*/
reiserfs_write_unlock_once(inode->i_sb, depth);
if ((attr->ia_valid & ATTR_SIZE) && if ((attr->ia_valid & ATTR_SIZE) &&
attr->ia_size != i_size_read(inode)) { attr->ia_size != i_size_read(inode)) {
error = inode_newsize_ok(inode, attr->ia_size); error = inode_newsize_ok(inode, attr->ia_size);
...@@ -3226,16 +3229,13 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -3226,16 +3229,13 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
setattr_copy(inode, attr); setattr_copy(inode, attr);
mark_inode_dirty(inode); mark_inode_dirty(inode);
} }
depth = reiserfs_write_lock_once(inode->i_sb);
if (!error && reiserfs_posixacl(inode->i_sb)) { if (!error && reiserfs_posixacl(inode->i_sb)) {
if (attr->ia_valid & ATTR_MODE) if (attr->ia_valid & ATTR_MODE)
error = reiserfs_acl_chmod(inode); error = reiserfs_acl_chmod(inode);
} }
out: out:
reiserfs_write_unlock_once(inode->i_sb, depth);
return error; return error;
} }
......
...@@ -167,7 +167,6 @@ int reiserfs_commit_write(struct file *f, struct page *page, ...@@ -167,7 +167,6 @@ int reiserfs_commit_write(struct file *f, struct page *page,
int reiserfs_unpack(struct inode *inode, struct file *filp) int reiserfs_unpack(struct inode *inode, struct file *filp)
{ {
int retval = 0; int retval = 0;
int depth;
int index; int index;
struct page *page; struct page *page;
struct address_space *mapping; struct address_space *mapping;
...@@ -183,11 +182,11 @@ int reiserfs_unpack(struct inode *inode, struct file *filp) ...@@ -183,11 +182,11 @@ int reiserfs_unpack(struct inode *inode, struct file *filp)
return 0; return 0;
} }
depth = reiserfs_write_lock_once(inode->i_sb);
/* we need to make sure nobody is changing the file size beneath us */ /* we need to make sure nobody is changing the file size beneath us */
reiserfs_mutex_lock_safe(&inode->i_mutex, inode->i_sb); reiserfs_mutex_lock_safe(&inode->i_mutex, inode->i_sb);
reiserfs_write_lock(inode->i_sb);
write_from = inode->i_size & (blocksize - 1); write_from = inode->i_size & (blocksize - 1);
/* if we are on a block boundary, we are already unpacked. */ /* if we are on a block boundary, we are already unpacked. */
if (write_from == 0) { if (write_from == 0) {
...@@ -221,6 +220,6 @@ int reiserfs_unpack(struct inode *inode, struct file *filp) ...@@ -221,6 +220,6 @@ int reiserfs_unpack(struct inode *inode, struct file *filp)
out: out:
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
reiserfs_write_unlock_once(inode->i_sb, depth); reiserfs_write_unlock(inode->i_sb);
return retval; return retval;
} }
...@@ -947,9 +947,11 @@ static int reiserfs_async_progress_wait(struct super_block *s) ...@@ -947,9 +947,11 @@ static int reiserfs_async_progress_wait(struct super_block *s)
struct reiserfs_journal *j = SB_JOURNAL(s); struct reiserfs_journal *j = SB_JOURNAL(s);
if (atomic_read(&j->j_async_throttle)) { if (atomic_read(&j->j_async_throttle)) {
reiserfs_write_unlock(s); int depth;
depth = reiserfs_write_unlock_nested(s);
congestion_wait(BLK_RW_ASYNC, HZ / 10); congestion_wait(BLK_RW_ASYNC, HZ / 10);
reiserfs_write_lock(s); reiserfs_write_lock_nested(s, depth);
} }
return 0; return 0;
...@@ -972,6 +974,7 @@ static int flush_commit_list(struct super_block *s, ...@@ -972,6 +974,7 @@ static int flush_commit_list(struct super_block *s,
struct reiserfs_journal *journal = SB_JOURNAL(s); struct reiserfs_journal *journal = SB_JOURNAL(s);
int retval = 0; int retval = 0;
int write_len; int write_len;
int depth;
reiserfs_check_lock_depth(s, "flush_commit_list"); reiserfs_check_lock_depth(s, "flush_commit_list");
...@@ -1018,12 +1021,12 @@ static int flush_commit_list(struct super_block *s, ...@@ -1018,12 +1021,12 @@ static int flush_commit_list(struct super_block *s,
* We might sleep in numerous places inside * We might sleep in numerous places inside
* write_ordered_buffers. Relax the write lock. * write_ordered_buffers. Relax the write lock.
*/ */
reiserfs_write_unlock(s); depth = reiserfs_write_unlock_nested(s);
ret = write_ordered_buffers(&journal->j_dirty_buffers_lock, ret = write_ordered_buffers(&journal->j_dirty_buffers_lock,
journal, jl, &jl->j_bh_list); journal, jl, &jl->j_bh_list);
if (ret < 0 && retval == 0) if (ret < 0 && retval == 0)
retval = ret; retval = ret;
reiserfs_write_lock(s); reiserfs_write_lock_nested(s, depth);
} }
BUG_ON(!list_empty(&jl->j_bh_list)); BUG_ON(!list_empty(&jl->j_bh_list));
/* /*
...@@ -1043,9 +1046,9 @@ static int flush_commit_list(struct super_block *s, ...@@ -1043,9 +1046,9 @@ static int flush_commit_list(struct super_block *s,
tbh = journal_find_get_block(s, bn); tbh = journal_find_get_block(s, bn);
if (tbh) { if (tbh) {
if (buffer_dirty(tbh)) { if (buffer_dirty(tbh)) {
reiserfs_write_unlock(s); depth = reiserfs_write_unlock_nested(s);
ll_rw_block(WRITE, 1, &tbh); ll_rw_block(WRITE, 1, &tbh);
reiserfs_write_lock(s); reiserfs_write_lock_nested(s, depth);
} }
put_bh(tbh) ; put_bh(tbh) ;
} }
...@@ -1057,17 +1060,17 @@ static int flush_commit_list(struct super_block *s, ...@@ -1057,17 +1060,17 @@ static int flush_commit_list(struct super_block *s,
(jl->j_start + i) % SB_ONDISK_JOURNAL_SIZE(s); (jl->j_start + i) % SB_ONDISK_JOURNAL_SIZE(s);
tbh = journal_find_get_block(s, bn); tbh = journal_find_get_block(s, bn);
reiserfs_write_unlock(s); depth = reiserfs_write_unlock_nested(s);
wait_on_buffer(tbh); __wait_on_buffer(tbh);
reiserfs_write_lock(s); reiserfs_write_lock_nested(s, depth);
// since we're using ll_rw_blk above, it might have skipped over // since we're using ll_rw_blk above, it might have skipped over
// a locked buffer. Double check here // a locked buffer. Double check here
// //
/* redundant, sync_dirty_buffer() checks */ /* redundant, sync_dirty_buffer() checks */
if (buffer_dirty(tbh)) { if (buffer_dirty(tbh)) {
reiserfs_write_unlock(s); depth = reiserfs_write_unlock_nested(s);
sync_dirty_buffer(tbh); sync_dirty_buffer(tbh);
reiserfs_write_lock(s); reiserfs_write_lock_nested(s, depth);
} }
if (unlikely(!buffer_uptodate(tbh))) { if (unlikely(!buffer_uptodate(tbh))) {
#ifdef CONFIG_REISERFS_CHECK #ifdef CONFIG_REISERFS_CHECK
...@@ -1091,12 +1094,12 @@ static int flush_commit_list(struct super_block *s, ...@@ -1091,12 +1094,12 @@ static int flush_commit_list(struct super_block *s,
if (buffer_dirty(jl->j_commit_bh)) if (buffer_dirty(jl->j_commit_bh))
BUG(); BUG();
mark_buffer_dirty(jl->j_commit_bh) ; mark_buffer_dirty(jl->j_commit_bh) ;
reiserfs_write_unlock(s); depth = reiserfs_write_unlock_nested(s);
if (reiserfs_barrier_flush(s)) if (reiserfs_barrier_flush(s))
__sync_dirty_buffer(jl->j_commit_bh, WRITE_FLUSH_FUA); __sync_dirty_buffer(jl->j_commit_bh, WRITE_FLUSH_FUA);
else else
sync_dirty_buffer(jl->j_commit_bh); sync_dirty_buffer(jl->j_commit_bh);
reiserfs_write_lock(s); reiserfs_write_lock_nested(s, depth);
} }
/* If there was a write error in the journal - we can't commit this /* If there was a write error in the journal - we can't commit this
...@@ -1228,15 +1231,16 @@ static int _update_journal_header_block(struct super_block *sb, ...@@ -1228,15 +1231,16 @@ static int _update_journal_header_block(struct super_block *sb,
{ {
struct reiserfs_journal_header *jh; struct reiserfs_journal_header *jh;
struct reiserfs_journal *journal = SB_JOURNAL(sb); struct reiserfs_journal *journal = SB_JOURNAL(sb);
int depth;
if (reiserfs_is_journal_aborted(journal)) if (reiserfs_is_journal_aborted(journal))
return -EIO; return -EIO;
if (trans_id >= journal->j_last_flush_trans_id) { if (trans_id >= journal->j_last_flush_trans_id) {
if (buffer_locked((journal->j_header_bh))) { if (buffer_locked((journal->j_header_bh))) {
reiserfs_write_unlock(sb); depth = reiserfs_write_unlock_nested(sb);
wait_on_buffer((journal->j_header_bh)); __wait_on_buffer(journal->j_header_bh);
reiserfs_write_lock(sb); reiserfs_write_lock_nested(sb, depth);
if (unlikely(!buffer_uptodate(journal->j_header_bh))) { if (unlikely(!buffer_uptodate(journal->j_header_bh))) {
#ifdef CONFIG_REISERFS_CHECK #ifdef CONFIG_REISERFS_CHECK
reiserfs_warning(sb, "journal-699", reiserfs_warning(sb, "journal-699",
...@@ -1254,14 +1258,14 @@ static int _update_journal_header_block(struct super_block *sb, ...@@ -1254,14 +1258,14 @@ static int _update_journal_header_block(struct super_block *sb,
jh->j_mount_id = cpu_to_le32(journal->j_mount_id); jh->j_mount_id = cpu_to_le32(journal->j_mount_id);
set_buffer_dirty(journal->j_header_bh); set_buffer_dirty(journal->j_header_bh);
reiserfs_write_unlock(sb); depth = reiserfs_write_unlock_nested(sb);
if (reiserfs_barrier_flush(sb)) if (reiserfs_barrier_flush(sb))
__sync_dirty_buffer(journal->j_header_bh, WRITE_FLUSH_FUA); __sync_dirty_buffer(journal->j_header_bh, WRITE_FLUSH_FUA);
else else
sync_dirty_buffer(journal->j_header_bh); sync_dirty_buffer(journal->j_header_bh);
reiserfs_write_lock(sb); reiserfs_write_lock_nested(sb, depth);
if (!buffer_uptodate(journal->j_header_bh)) { if (!buffer_uptodate(journal->j_header_bh)) {
reiserfs_warning(sb, "journal-837", reiserfs_warning(sb, "journal-837",
"IO error during journal replay"); "IO error during journal replay");
...@@ -1341,6 +1345,7 @@ static int flush_journal_list(struct super_block *s, ...@@ -1341,6 +1345,7 @@ static int flush_journal_list(struct super_block *s,
unsigned long j_len_saved = jl->j_len; unsigned long j_len_saved = jl->j_len;
struct reiserfs_journal *journal = SB_JOURNAL(s); struct reiserfs_journal *journal = SB_JOURNAL(s);
int err = 0; int err = 0;
int depth;
BUG_ON(j_len_saved <= 0); BUG_ON(j_len_saved <= 0);
...@@ -1495,9 +1500,9 @@ static int flush_journal_list(struct super_block *s, ...@@ -1495,9 +1500,9 @@ static int flush_journal_list(struct super_block *s,
"cn->bh is NULL"); "cn->bh is NULL");
} }
reiserfs_write_unlock(s); depth = reiserfs_write_unlock_nested(s);
wait_on_buffer(cn->bh); __wait_on_buffer(cn->bh);
reiserfs_write_lock(s); reiserfs_write_lock_nested(s, depth);
if (!cn->bh) { if (!cn->bh) {
reiserfs_panic(s, "journal-1012", reiserfs_panic(s, "journal-1012",
...@@ -1974,6 +1979,7 @@ static int journal_compare_desc_commit(struct super_block *sb, ...@@ -1974,6 +1979,7 @@ static int journal_compare_desc_commit(struct super_block *sb,
/* returns 0 if it did not find a description block /* returns 0 if it did not find a description block
** returns -1 if it found a corrupt commit block ** returns -1 if it found a corrupt commit block
** returns 1 if both desc and commit were valid ** returns 1 if both desc and commit were valid
** NOTE: only called during fs mount
*/ */
static int journal_transaction_is_valid(struct super_block *sb, static int journal_transaction_is_valid(struct super_block *sb,
struct buffer_head *d_bh, struct buffer_head *d_bh,
...@@ -2073,8 +2079,9 @@ static void brelse_array(struct buffer_head **heads, int num) ...@@ -2073,8 +2079,9 @@ static void brelse_array(struct buffer_head **heads, int num)
/* /*
** given the start, and values for the oldest acceptable transactions, ** given the start, and values for the oldest acceptable transactions,
** this either reads in a replays a transaction, or returns because the transaction ** this either reads in a replays a transaction, or returns because the
** is invalid, or too old. ** transaction is invalid, or too old.
** NOTE: only called during fs mount
*/ */
static int journal_read_transaction(struct super_block *sb, static int journal_read_transaction(struct super_block *sb,
unsigned long cur_dblock, unsigned long cur_dblock,
...@@ -2208,10 +2215,7 @@ static int journal_read_transaction(struct super_block *sb, ...@@ -2208,10 +2215,7 @@ static int journal_read_transaction(struct super_block *sb,
ll_rw_block(READ, get_desc_trans_len(desc), log_blocks); ll_rw_block(READ, get_desc_trans_len(desc), log_blocks);
for (i = 0; i < get_desc_trans_len(desc); i++) { for (i = 0; i < get_desc_trans_len(desc); i++) {
reiserfs_write_unlock(sb);
wait_on_buffer(log_blocks[i]); wait_on_buffer(log_blocks[i]);
reiserfs_write_lock(sb);
if (!buffer_uptodate(log_blocks[i])) { if (!buffer_uptodate(log_blocks[i])) {
reiserfs_warning(sb, "journal-1212", reiserfs_warning(sb, "journal-1212",
"REPLAY FAILURE fsck required! " "REPLAY FAILURE fsck required! "
...@@ -2318,12 +2322,13 @@ static struct buffer_head *reiserfs_breada(struct block_device *dev, ...@@ -2318,12 +2322,13 @@ static struct buffer_head *reiserfs_breada(struct block_device *dev,
/* /*
** read and replay the log ** read and replay the log
** on a clean unmount, the journal header's next unflushed pointer will be to an invalid ** on a clean unmount, the journal header's next unflushed pointer will
** transaction. This tests that before finding all the transactions in the log, which makes normal mount times fast. ** be to an invalid transaction. This tests that before finding all the
** ** transactions in the log, which makes normal mount times fast.
** After a crash, this starts with the next unflushed transaction, and replays until it finds one too old, or invalid. ** After a crash, this starts with the next unflushed transaction, and
** ** replays until it finds one too old, or invalid.
** On exit, it sets things up so the first transaction will work correctly. ** On exit, it sets things up so the first transaction will work correctly.
** NOTE: only called during fs mount
*/ */
static int journal_read(struct super_block *sb) static int journal_read(struct super_block *sb)
{ {
...@@ -2501,14 +2506,18 @@ static int journal_read(struct super_block *sb) ...@@ -2501,14 +2506,18 @@ static int journal_read(struct super_block *sb)
"replayed %d transactions in %lu seconds\n", "replayed %d transactions in %lu seconds\n",
replay_count, get_seconds() - start); replay_count, get_seconds() - start);
} }
/* needed to satisfy the locking in _update_journal_header_block */
reiserfs_write_lock(sb);
if (!bdev_read_only(sb->s_bdev) && if (!bdev_read_only(sb->s_bdev) &&
_update_journal_header_block(sb, journal->j_start, _update_journal_header_block(sb, journal->j_start,
journal->j_last_flush_trans_id)) { journal->j_last_flush_trans_id)) {
reiserfs_write_unlock(sb);
/* replay failed, caller must call free_journal_ram and abort /* replay failed, caller must call free_journal_ram and abort
** the mount ** the mount
*/ */
return -1; return -1;
} }
reiserfs_write_unlock(sb);
return 0; return 0;
} }
...@@ -2828,13 +2837,7 @@ int journal_init(struct super_block *sb, const char *j_dev_name, ...@@ -2828,13 +2837,7 @@ int journal_init(struct super_block *sb, const char *j_dev_name,
goto free_and_return; goto free_and_return;
} }
/*
* Journal_read needs to be inspected in order to push down
* the lock further inside (or even remove it).
*/
reiserfs_write_lock(sb);
ret = journal_read(sb); ret = journal_read(sb);
reiserfs_write_unlock(sb);
if (ret < 0) { if (ret < 0) {
reiserfs_warning(sb, "reiserfs-2006", reiserfs_warning(sb, "reiserfs-2006",
"Replay Failure, unable to mount"); "Replay Failure, unable to mount");
...@@ -2923,9 +2926,9 @@ static void queue_log_writer(struct super_block *s) ...@@ -2923,9 +2926,9 @@ static void queue_log_writer(struct super_block *s)
add_wait_queue(&journal->j_join_wait, &wait); add_wait_queue(&journal->j_join_wait, &wait);
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
if (test_bit(J_WRITERS_QUEUED, &journal->j_state)) { if (test_bit(J_WRITERS_QUEUED, &journal->j_state)) {
reiserfs_write_unlock(s); int depth = reiserfs_write_unlock_nested(s);
schedule(); schedule();
reiserfs_write_lock(s); reiserfs_write_lock_nested(s, depth);
} }
__set_current_state(TASK_RUNNING); __set_current_state(TASK_RUNNING);
remove_wait_queue(&journal->j_join_wait, &wait); remove_wait_queue(&journal->j_join_wait, &wait);
...@@ -2943,9 +2946,12 @@ static void let_transaction_grow(struct super_block *sb, unsigned int trans_id) ...@@ -2943,9 +2946,12 @@ static void let_transaction_grow(struct super_block *sb, unsigned int trans_id)
struct reiserfs_journal *journal = SB_JOURNAL(sb); struct reiserfs_journal *journal = SB_JOURNAL(sb);
unsigned long bcount = journal->j_bcount; unsigned long bcount = journal->j_bcount;
while (1) { while (1) {
reiserfs_write_unlock(sb); int depth;
depth = reiserfs_write_unlock_nested(sb);
schedule_timeout_uninterruptible(1); schedule_timeout_uninterruptible(1);
reiserfs_write_lock(sb); reiserfs_write_lock_nested(sb, depth);
journal->j_current_jl->j_state |= LIST_COMMIT_PENDING; journal->j_current_jl->j_state |= LIST_COMMIT_PENDING;
while ((atomic_read(&journal->j_wcount) > 0 || while ((atomic_read(&journal->j_wcount) > 0 ||
atomic_read(&journal->j_jlock)) && atomic_read(&journal->j_jlock)) &&
...@@ -2976,6 +2982,7 @@ static int do_journal_begin_r(struct reiserfs_transaction_handle *th, ...@@ -2976,6 +2982,7 @@ static int do_journal_begin_r(struct reiserfs_transaction_handle *th,
struct reiserfs_transaction_handle myth; struct reiserfs_transaction_handle myth;
int sched_count = 0; int sched_count = 0;
int retval; int retval;
int depth;
reiserfs_check_lock_depth(sb, "journal_begin"); reiserfs_check_lock_depth(sb, "journal_begin");
BUG_ON(nblocks > journal->j_trans_max); BUG_ON(nblocks > journal->j_trans_max);
...@@ -2996,9 +3003,9 @@ static int do_journal_begin_r(struct reiserfs_transaction_handle *th, ...@@ -2996,9 +3003,9 @@ static int do_journal_begin_r(struct reiserfs_transaction_handle *th,
if (test_bit(J_WRITERS_BLOCKED, &journal->j_state)) { if (test_bit(J_WRITERS_BLOCKED, &journal->j_state)) {
unlock_journal(sb); unlock_journal(sb);
reiserfs_write_unlock(sb); depth = reiserfs_write_unlock_nested(sb);
reiserfs_wait_on_write_block(sb); reiserfs_wait_on_write_block(sb);
reiserfs_write_lock(sb); reiserfs_write_lock_nested(sb, depth);
PROC_INFO_INC(sb, journal.journal_relock_writers); PROC_INFO_INC(sb, journal.journal_relock_writers);
goto relock; goto relock;
} }
...@@ -3821,6 +3828,7 @@ void reiserfs_restore_prepared_buffer(struct super_block *sb, ...@@ -3821,6 +3828,7 @@ void reiserfs_restore_prepared_buffer(struct super_block *sb,
if (test_clear_buffer_journal_restore_dirty(bh) && if (test_clear_buffer_journal_restore_dirty(bh) &&
buffer_journal_dirty(bh)) { buffer_journal_dirty(bh)) {
struct reiserfs_journal_cnode *cn; struct reiserfs_journal_cnode *cn;
reiserfs_write_lock(sb);
cn = get_journal_hash_dev(sb, cn = get_journal_hash_dev(sb,
journal->j_list_hash_table, journal->j_list_hash_table,
bh->b_blocknr); bh->b_blocknr);
...@@ -3828,6 +3836,7 @@ void reiserfs_restore_prepared_buffer(struct super_block *sb, ...@@ -3828,6 +3836,7 @@ void reiserfs_restore_prepared_buffer(struct super_block *sb,
set_buffer_journal_test(bh); set_buffer_journal_test(bh);
mark_buffer_dirty(bh); mark_buffer_dirty(bh);
} }
reiserfs_write_unlock(sb);
} }
clear_buffer_journal_prepared(bh); clear_buffer_journal_prepared(bh);
} }
...@@ -3911,6 +3920,7 @@ static int do_journal_end(struct reiserfs_transaction_handle *th, ...@@ -3911,6 +3920,7 @@ static int do_journal_end(struct reiserfs_transaction_handle *th,
unsigned long jindex; unsigned long jindex;
unsigned int commit_trans_id; unsigned int commit_trans_id;
int trans_half; int trans_half;
int depth;
BUG_ON(th->t_refcount > 1); BUG_ON(th->t_refcount > 1);
BUG_ON(!th->t_trans_id); BUG_ON(!th->t_trans_id);
...@@ -4116,9 +4126,7 @@ static int do_journal_end(struct reiserfs_transaction_handle *th, ...@@ -4116,9 +4126,7 @@ static int do_journal_end(struct reiserfs_transaction_handle *th,
next = cn->next; next = cn->next;
free_cnode(sb, cn); free_cnode(sb, cn);
cn = next; cn = next;
reiserfs_write_unlock(sb); reiserfs_cond_resched(sb);
cond_resched();
reiserfs_write_lock(sb);
} }
/* we are done with both the c_bh and d_bh, but /* we are done with both the c_bh and d_bh, but
...@@ -4165,10 +4173,10 @@ static int do_journal_end(struct reiserfs_transaction_handle *th, ...@@ -4165,10 +4173,10 @@ static int do_journal_end(struct reiserfs_transaction_handle *th,
* is lost. * is lost.
*/ */
if (!list_empty(&jl->j_tail_bh_list)) { if (!list_empty(&jl->j_tail_bh_list)) {
reiserfs_write_unlock(sb); depth = reiserfs_write_unlock_nested(sb);
write_ordered_buffers(&journal->j_dirty_buffers_lock, write_ordered_buffers(&journal->j_dirty_buffers_lock,
journal, jl, &jl->j_tail_bh_list); journal, jl, &jl->j_tail_bh_list);
reiserfs_write_lock(sb); reiserfs_write_lock_nested(sb, depth);
} }
BUG_ON(!list_empty(&jl->j_tail_bh_list)); BUG_ON(!list_empty(&jl->j_tail_bh_list));
mutex_unlock(&jl->j_commit_mutex); mutex_unlock(&jl->j_commit_mutex);
......
...@@ -48,30 +48,35 @@ void reiserfs_write_unlock(struct super_block *s) ...@@ -48,30 +48,35 @@ void reiserfs_write_unlock(struct super_block *s)
} }
} }
/* int __must_check reiserfs_write_unlock_nested(struct super_block *s)
* If we already own the lock, just exit and don't increase the depth.
* Useful when we don't want to lock more than once.
*
* We always return the lock_depth we had before calling
* this function.
*/
int reiserfs_write_lock_once(struct super_block *s)
{ {
struct reiserfs_sb_info *sb_i = REISERFS_SB(s); struct reiserfs_sb_info *sb_i = REISERFS_SB(s);
int depth;
if (sb_i->lock_owner != current) { /* this can happen when the lock isn't always held */
mutex_lock(&sb_i->lock); if (sb_i->lock_owner != current)
sb_i->lock_owner = current; return -1;
return sb_i->lock_depth++;
} depth = sb_i->lock_depth;
sb_i->lock_depth = -1;
sb_i->lock_owner = NULL;
mutex_unlock(&sb_i->lock);
return sb_i->lock_depth; return depth;
} }
void reiserfs_write_unlock_once(struct super_block *s, int lock_depth) void reiserfs_write_lock_nested(struct super_block *s, int depth)
{ {
if (lock_depth == -1) struct reiserfs_sb_info *sb_i = REISERFS_SB(s);
reiserfs_write_unlock(s);
/* this can happen when the lock isn't always held */
if (depth == -1)
return;
mutex_lock(&sb_i->lock);
sb_i->lock_owner = current;
sb_i->lock_depth = depth;
} }
/* /*
...@@ -82,9 +87,7 @@ void reiserfs_check_lock_depth(struct super_block *sb, char *caller) ...@@ -82,9 +87,7 @@ void reiserfs_check_lock_depth(struct super_block *sb, char *caller)
{ {
struct reiserfs_sb_info *sb_i = REISERFS_SB(sb); struct reiserfs_sb_info *sb_i = REISERFS_SB(sb);
if (sb_i->lock_depth < 0) WARN_ON(sb_i->lock_depth < 0);
reiserfs_panic(sb, "%s called without kernel lock held %d",
caller);
} }
#ifdef CONFIG_REISERFS_CHECK #ifdef CONFIG_REISERFS_CHECK
......
...@@ -325,7 +325,6 @@ static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry, ...@@ -325,7 +325,6 @@ static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry,
unsigned int flags) unsigned int flags)
{ {
int retval; int retval;
int lock_depth;
struct inode *inode = NULL; struct inode *inode = NULL;
struct reiserfs_dir_entry de; struct reiserfs_dir_entry de;
INITIALIZE_PATH(path_to_entry); INITIALIZE_PATH(path_to_entry);
...@@ -333,12 +332,7 @@ static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry, ...@@ -333,12 +332,7 @@ static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry,
if (REISERFS_MAX_NAME(dir->i_sb->s_blocksize) < dentry->d_name.len) if (REISERFS_MAX_NAME(dir->i_sb->s_blocksize) < dentry->d_name.len)
return ERR_PTR(-ENAMETOOLONG); return ERR_PTR(-ENAMETOOLONG);
/* reiserfs_write_lock(dir->i_sb);
* Might be called with or without the write lock, must be careful
* to not recursively hold it in case we want to release the lock
* before rescheduling.
*/
lock_depth = reiserfs_write_lock_once(dir->i_sb);
de.de_gen_number_bit_string = NULL; de.de_gen_number_bit_string = NULL;
retval = retval =
...@@ -349,7 +343,7 @@ static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry, ...@@ -349,7 +343,7 @@ static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry,
inode = reiserfs_iget(dir->i_sb, inode = reiserfs_iget(dir->i_sb,
(struct cpu_key *)&(de.de_dir_id)); (struct cpu_key *)&(de.de_dir_id));
if (!inode || IS_ERR(inode)) { if (!inode || IS_ERR(inode)) {
reiserfs_write_unlock_once(dir->i_sb, lock_depth); reiserfs_write_unlock(dir->i_sb);
return ERR_PTR(-EACCES); return ERR_PTR(-EACCES);
} }
...@@ -358,7 +352,7 @@ static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry, ...@@ -358,7 +352,7 @@ static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry,
if (IS_PRIVATE(dir)) if (IS_PRIVATE(dir))
inode->i_flags |= S_PRIVATE; inode->i_flags |= S_PRIVATE;
} }
reiserfs_write_unlock_once(dir->i_sb, lock_depth); reiserfs_write_unlock(dir->i_sb);
if (retval == IO_ERROR) { if (retval == IO_ERROR) {
return ERR_PTR(-EIO); return ERR_PTR(-EIO);
} }
...@@ -727,7 +721,6 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode ...@@ -727,7 +721,6 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
struct inode *inode; struct inode *inode;
struct reiserfs_transaction_handle th; struct reiserfs_transaction_handle th;
struct reiserfs_security_handle security; struct reiserfs_security_handle security;
int lock_depth;
/* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */
int jbegin_count = int jbegin_count =
JOURNAL_PER_BALANCE_CNT * 3 + JOURNAL_PER_BALANCE_CNT * 3 +
...@@ -753,7 +746,7 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode ...@@ -753,7 +746,7 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
return retval; return retval;
} }
jbegin_count += retval; jbegin_count += retval;
lock_depth = reiserfs_write_lock_once(dir->i_sb); reiserfs_write_lock(dir->i_sb);
retval = journal_begin(&th, dir->i_sb, jbegin_count); retval = journal_begin(&th, dir->i_sb, jbegin_count);
if (retval) { if (retval) {
...@@ -804,7 +797,7 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode ...@@ -804,7 +797,7 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
retval = journal_end(&th, dir->i_sb, jbegin_count); retval = journal_end(&th, dir->i_sb, jbegin_count);
out_failed: out_failed:
reiserfs_write_unlock_once(dir->i_sb, lock_depth); reiserfs_write_unlock(dir->i_sb);
return retval; return retval;
} }
...@@ -920,7 +913,6 @@ static int reiserfs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -920,7 +913,6 @@ static int reiserfs_unlink(struct inode *dir, struct dentry *dentry)
struct reiserfs_transaction_handle th; struct reiserfs_transaction_handle th;
int jbegin_count; int jbegin_count;
unsigned long savelink; unsigned long savelink;
int depth;
dquot_initialize(dir); dquot_initialize(dir);
...@@ -934,7 +926,7 @@ static int reiserfs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -934,7 +926,7 @@ static int reiserfs_unlink(struct inode *dir, struct dentry *dentry)
JOURNAL_PER_BALANCE_CNT * 2 + 2 + JOURNAL_PER_BALANCE_CNT * 2 + 2 +
4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb); 4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);
depth = reiserfs_write_lock_once(dir->i_sb); reiserfs_write_lock(dir->i_sb);
retval = journal_begin(&th, dir->i_sb, jbegin_count); retval = journal_begin(&th, dir->i_sb, jbegin_count);
if (retval) if (retval)
goto out_unlink; goto out_unlink;
...@@ -995,7 +987,7 @@ static int reiserfs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -995,7 +987,7 @@ static int reiserfs_unlink(struct inode *dir, struct dentry *dentry)
retval = journal_end(&th, dir->i_sb, jbegin_count); retval = journal_end(&th, dir->i_sb, jbegin_count);
reiserfs_check_path(&path); reiserfs_check_path(&path);
reiserfs_write_unlock_once(dir->i_sb, depth); reiserfs_write_unlock(dir->i_sb);
return retval; return retval;
end_unlink: end_unlink:
...@@ -1005,7 +997,7 @@ static int reiserfs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -1005,7 +997,7 @@ static int reiserfs_unlink(struct inode *dir, struct dentry *dentry)
if (err) if (err)
retval = err; retval = err;
out_unlink: out_unlink:
reiserfs_write_unlock_once(dir->i_sb, depth); reiserfs_write_unlock(dir->i_sb);
return retval; return retval;
} }
......
...@@ -358,12 +358,13 @@ void __reiserfs_panic(struct super_block *sb, const char *id, ...@@ -358,12 +358,13 @@ void __reiserfs_panic(struct super_block *sb, const char *id,
dump_stack(); dump_stack();
#endif #endif
if (sb) if (sb)
panic(KERN_WARNING "REISERFS panic (device %s): %s%s%s: %s\n", printk(KERN_WARNING "REISERFS panic (device %s): %s%s%s: %s\n",
sb->s_id, id ? id : "", id ? " " : "", sb->s_id, id ? id : "", id ? " " : "",
function, error_buf); function, error_buf);
else else
panic(KERN_WARNING "REISERFS panic: %s%s%s: %s\n", printk(KERN_WARNING "REISERFS panic: %s%s%s: %s\n",
id ? id : "", id ? " " : "", function, error_buf); id ? id : "", id ? " " : "", function, error_buf);
BUG();
} }
void __reiserfs_error(struct super_block *sb, const char *id, void __reiserfs_error(struct super_block *sb, const char *id,
......
...@@ -630,8 +630,8 @@ static inline int __reiserfs_is_journal_aborted(struct reiserfs_journal ...@@ -630,8 +630,8 @@ static inline int __reiserfs_is_journal_aborted(struct reiserfs_journal
*/ */
void reiserfs_write_lock(struct super_block *s); void reiserfs_write_lock(struct super_block *s);
void reiserfs_write_unlock(struct super_block *s); void reiserfs_write_unlock(struct super_block *s);
int reiserfs_write_lock_once(struct super_block *s); int __must_check reiserfs_write_unlock_nested(struct super_block *s);
void reiserfs_write_unlock_once(struct super_block *s, int lock_depth); void reiserfs_write_lock_nested(struct super_block *s, int depth);
#ifdef CONFIG_REISERFS_CHECK #ifdef CONFIG_REISERFS_CHECK
void reiserfs_lock_check_recursive(struct super_block *s); void reiserfs_lock_check_recursive(struct super_block *s);
...@@ -667,31 +667,33 @@ static inline void reiserfs_lock_check_recursive(struct super_block *s) { } ...@@ -667,31 +667,33 @@ static inline void reiserfs_lock_check_recursive(struct super_block *s) { }
* - The inode mutex * - The inode mutex
*/ */
static inline void reiserfs_mutex_lock_safe(struct mutex *m, static inline void reiserfs_mutex_lock_safe(struct mutex *m,
struct super_block *s) struct super_block *s)
{ {
reiserfs_lock_check_recursive(s); int depth;
reiserfs_write_unlock(s);
depth = reiserfs_write_unlock_nested(s);
mutex_lock(m); mutex_lock(m);
reiserfs_write_lock(s); reiserfs_write_lock_nested(s, depth);
} }
static inline void static inline void
reiserfs_mutex_lock_nested_safe(struct mutex *m, unsigned int subclass, reiserfs_mutex_lock_nested_safe(struct mutex *m, unsigned int subclass,
struct super_block *s) struct super_block *s)
{ {
reiserfs_lock_check_recursive(s); int depth;
reiserfs_write_unlock(s);
depth = reiserfs_write_unlock_nested(s);
mutex_lock_nested(m, subclass); mutex_lock_nested(m, subclass);
reiserfs_write_lock(s); reiserfs_write_lock_nested(s, depth);
} }
static inline void static inline void
reiserfs_down_read_safe(struct rw_semaphore *sem, struct super_block *s) reiserfs_down_read_safe(struct rw_semaphore *sem, struct super_block *s)
{ {
reiserfs_lock_check_recursive(s); int depth;
reiserfs_write_unlock(s); depth = reiserfs_write_unlock_nested(s);
down_read(sem); down_read(sem);
reiserfs_write_lock(s); reiserfs_write_lock_nested(s, depth);
} }
/* /*
...@@ -701,9 +703,11 @@ reiserfs_down_read_safe(struct rw_semaphore *sem, struct super_block *s) ...@@ -701,9 +703,11 @@ reiserfs_down_read_safe(struct rw_semaphore *sem, struct super_block *s)
static inline void reiserfs_cond_resched(struct super_block *s) static inline void reiserfs_cond_resched(struct super_block *s)
{ {
if (need_resched()) { if (need_resched()) {
reiserfs_write_unlock(s); int depth;
depth = reiserfs_write_unlock_nested(s);
schedule(); schedule();
reiserfs_write_lock(s); reiserfs_write_lock_nested(s, depth);
} }
} }
......
...@@ -34,6 +34,7 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new) ...@@ -34,6 +34,7 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
unsigned long int block_count, free_blocks; unsigned long int block_count, free_blocks;
int i; int i;
int copy_size; int copy_size;
int depth;
sb = SB_DISK_SUPER_BLOCK(s); sb = SB_DISK_SUPER_BLOCK(s);
...@@ -43,7 +44,9 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new) ...@@ -43,7 +44,9 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
} }
/* check the device size */ /* check the device size */
depth = reiserfs_write_unlock_nested(s);
bh = sb_bread(s, block_count_new - 1); bh = sb_bread(s, block_count_new - 1);
reiserfs_write_lock_nested(s, depth);
if (!bh) { if (!bh) {
printk("reiserfs_resize: can\'t read last block\n"); printk("reiserfs_resize: can\'t read last block\n");
return -EINVAL; return -EINVAL;
...@@ -125,9 +128,12 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new) ...@@ -125,9 +128,12 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
* transaction begins, and the new bitmaps don't matter if the * transaction begins, and the new bitmaps don't matter if the
* transaction fails. */ * transaction fails. */
for (i = bmap_nr; i < bmap_nr_new; i++) { for (i = bmap_nr; i < bmap_nr_new; i++) {
int depth;
/* don't use read_bitmap_block since it will cache /* don't use read_bitmap_block since it will cache
* the uninitialized bitmap */ * the uninitialized bitmap */
depth = reiserfs_write_unlock_nested(s);
bh = sb_bread(s, i * s->s_blocksize * 8); bh = sb_bread(s, i * s->s_blocksize * 8);
reiserfs_write_lock_nested(s, depth);
if (!bh) { if (!bh) {
vfree(bitmap); vfree(bitmap);
return -EIO; return -EIO;
...@@ -138,9 +144,9 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new) ...@@ -138,9 +144,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); depth = reiserfs_write_unlock_nested(s);
sync_dirty_buffer(bh); sync_dirty_buffer(bh);
reiserfs_write_lock(s); reiserfs_write_lock_nested(s, depth);
// 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);
......
...@@ -524,14 +524,14 @@ static int is_tree_node(struct buffer_head *bh, int level) ...@@ -524,14 +524,14 @@ static int is_tree_node(struct buffer_head *bh, int level)
* the caller (search_by_key) will perform other schedule-unsafe * the caller (search_by_key) will perform other schedule-unsafe
* operations just after calling this function. * operations just after calling this function.
* *
* @return true if we have unlocked * @return depth of lock to be restored after read completes
*/ */
static bool search_by_key_reada(struct super_block *s, static int search_by_key_reada(struct super_block *s,
struct buffer_head **bh, struct buffer_head **bh,
b_blocknr_t *b, int num) b_blocknr_t *b, int num)
{ {
int i, j; int i, j;
bool unlocked = false; int depth = -1;
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
bh[i] = sb_getblk(s, b[i]); bh[i] = sb_getblk(s, b[i]);
...@@ -549,15 +549,13 @@ static bool search_by_key_reada(struct super_block *s, ...@@ -549,15 +549,13 @@ static bool search_by_key_reada(struct super_block *s,
* you have to make sure the prepared bit isn't set on this buffer * you have to make sure the prepared bit isn't set on this buffer
*/ */
if (!buffer_uptodate(bh[j])) { if (!buffer_uptodate(bh[j])) {
if (!unlocked) { if (depth == -1)
reiserfs_write_unlock(s); depth = reiserfs_write_unlock_nested(s);
unlocked = true;
}
ll_rw_block(READA, 1, bh + j); ll_rw_block(READA, 1, bh + j);
} }
brelse(bh[j]); brelse(bh[j]);
} }
return unlocked; return depth;
} }
/************************************************************************** /**************************************************************************
...@@ -645,26 +643,26 @@ int search_by_key(struct super_block *sb, const struct cpu_key *key, /* Key to s ...@@ -645,26 +643,26 @@ int search_by_key(struct super_block *sb, const struct cpu_key *key, /* Key to s
have a pointer to it. */ have a pointer to it. */
if ((bh = last_element->pe_buffer = if ((bh = last_element->pe_buffer =
sb_getblk(sb, block_number))) { sb_getblk(sb, block_number))) {
bool unlocked = false;
if (!buffer_uptodate(bh) && reada_count > 1)
/* may unlock the write lock */
unlocked = search_by_key_reada(sb, reada_bh,
reada_blocks, reada_count);
/* /*
* If we haven't already unlocked the write lock, * We'll need to drop the lock if we encounter any
* then we need to do that here before reading * buffers that need to be read. If all of them are
* the current block * already up to date, we don't need to drop the lock.
*/ */
if (!buffer_uptodate(bh) && !unlocked) { int depth = -1;
reiserfs_write_unlock(sb);
unlocked = true; if (!buffer_uptodate(bh) && reada_count > 1)
} depth = search_by_key_reada(sb, reada_bh,
reada_blocks, reada_count);
if (!buffer_uptodate(bh) && depth == -1)
depth = reiserfs_write_unlock_nested(sb);
ll_rw_block(READ, 1, &bh); ll_rw_block(READ, 1, &bh);
wait_on_buffer(bh); wait_on_buffer(bh);
if (unlocked) if (depth != -1)
reiserfs_write_lock(sb); reiserfs_write_lock_nested(sb, depth);
if (!buffer_uptodate(bh)) if (!buffer_uptodate(bh))
goto io_error; goto io_error;
} else { } else {
...@@ -1059,9 +1057,7 @@ static char prepare_for_delete_or_cut(struct reiserfs_transaction_handle *th, st ...@@ -1059,9 +1057,7 @@ static char prepare_for_delete_or_cut(struct reiserfs_transaction_handle *th, st
reiserfs_free_block(th, inode, block, 1); reiserfs_free_block(th, inode, block, 1);
} }
reiserfs_write_unlock(sb); reiserfs_cond_resched(sb);
cond_resched();
reiserfs_write_lock(sb);
if (item_moved (&s_ih, path)) { if (item_moved (&s_ih, path)) {
need_re_search = 1; need_re_search = 1;
...@@ -1190,6 +1186,7 @@ int reiserfs_delete_item(struct reiserfs_transaction_handle *th, ...@@ -1190,6 +1186,7 @@ int reiserfs_delete_item(struct reiserfs_transaction_handle *th,
struct item_head *q_ih; struct item_head *q_ih;
int quota_cut_bytes; int quota_cut_bytes;
int ret_value, del_size, removed; int ret_value, del_size, removed;
int depth;
#ifdef CONFIG_REISERFS_CHECK #ifdef CONFIG_REISERFS_CHECK
char mode; char mode;
...@@ -1299,7 +1296,9 @@ int reiserfs_delete_item(struct reiserfs_transaction_handle *th, ...@@ -1299,7 +1296,9 @@ int reiserfs_delete_item(struct reiserfs_transaction_handle *th,
"reiserquota delete_item(): freeing %u, id=%u type=%c", "reiserquota delete_item(): freeing %u, id=%u type=%c",
quota_cut_bytes, inode->i_uid, head2type(&s_ih)); quota_cut_bytes, inode->i_uid, head2type(&s_ih));
#endif #endif
depth = reiserfs_write_unlock_nested(inode->i_sb);
dquot_free_space_nodirty(inode, quota_cut_bytes); dquot_free_space_nodirty(inode, quota_cut_bytes);
reiserfs_write_lock_nested(inode->i_sb, depth);
/* Return deleted body length */ /* Return deleted body length */
return ret_value; return ret_value;
...@@ -1325,6 +1324,7 @@ int reiserfs_delete_item(struct reiserfs_transaction_handle *th, ...@@ -1325,6 +1324,7 @@ int reiserfs_delete_item(struct reiserfs_transaction_handle *th,
void reiserfs_delete_solid_item(struct reiserfs_transaction_handle *th, void reiserfs_delete_solid_item(struct reiserfs_transaction_handle *th,
struct inode *inode, struct reiserfs_key *key) struct inode *inode, struct reiserfs_key *key)
{ {
struct super_block *sb = th->t_super;
struct tree_balance tb; struct tree_balance tb;
INITIALIZE_PATH(path); INITIALIZE_PATH(path);
int item_len = 0; int item_len = 0;
...@@ -1377,14 +1377,17 @@ void reiserfs_delete_solid_item(struct reiserfs_transaction_handle *th, ...@@ -1377,14 +1377,17 @@ void reiserfs_delete_solid_item(struct reiserfs_transaction_handle *th,
if (retval == CARRY_ON) { if (retval == CARRY_ON) {
do_balance(&tb, NULL, NULL, M_DELETE); do_balance(&tb, NULL, NULL, M_DELETE);
if (inode) { /* Should we count quota for item? (we don't count quotas for save-links) */ if (inode) { /* Should we count quota for item? (we don't count quotas for save-links) */
int depth;
#ifdef REISERQUOTA_DEBUG #ifdef REISERQUOTA_DEBUG
reiserfs_debug(th->t_super, REISERFS_DEBUG_CODE, reiserfs_debug(th->t_super, REISERFS_DEBUG_CODE,
"reiserquota delete_solid_item(): freeing %u id=%u type=%c", "reiserquota delete_solid_item(): freeing %u id=%u type=%c",
quota_cut_bytes, inode->i_uid, quota_cut_bytes, inode->i_uid,
key2type(key)); key2type(key));
#endif #endif
depth = reiserfs_write_unlock_nested(sb);
dquot_free_space_nodirty(inode, dquot_free_space_nodirty(inode,
quota_cut_bytes); quota_cut_bytes);
reiserfs_write_lock_nested(sb, depth);
} }
break; break;
} }
...@@ -1561,6 +1564,7 @@ int reiserfs_cut_from_item(struct reiserfs_transaction_handle *th, ...@@ -1561,6 +1564,7 @@ int reiserfs_cut_from_item(struct reiserfs_transaction_handle *th,
int retval2 = -1; int retval2 = -1;
int quota_cut_bytes; int quota_cut_bytes;
loff_t tail_pos = 0; loff_t tail_pos = 0;
int depth;
BUG_ON(!th->t_trans_id); BUG_ON(!th->t_trans_id);
...@@ -1733,7 +1737,9 @@ int reiserfs_cut_from_item(struct reiserfs_transaction_handle *th, ...@@ -1733,7 +1737,9 @@ int reiserfs_cut_from_item(struct reiserfs_transaction_handle *th,
"reiserquota cut_from_item(): freeing %u id=%u type=%c", "reiserquota cut_from_item(): freeing %u id=%u type=%c",
quota_cut_bytes, inode->i_uid, '?'); quota_cut_bytes, inode->i_uid, '?');
#endif #endif
depth = reiserfs_write_unlock_nested(sb);
dquot_free_space_nodirty(inode, quota_cut_bytes); dquot_free_space_nodirty(inode, quota_cut_bytes);
reiserfs_write_lock_nested(sb, depth);
return ret_value; return ret_value;
} }
...@@ -1953,9 +1959,11 @@ int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct tree ...@@ -1953,9 +1959,11 @@ int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct tree
const char *body, /* Pointer to the bytes to paste. */ const char *body, /* Pointer to the bytes to paste. */
int pasted_size) int pasted_size)
{ /* Size of pasted bytes. */ { /* Size of pasted bytes. */
struct super_block *sb = inode->i_sb;
struct tree_balance s_paste_balance; struct tree_balance s_paste_balance;
int retval; int retval;
int fs_gen; int fs_gen;
int depth;
BUG_ON(!th->t_trans_id); BUG_ON(!th->t_trans_id);
...@@ -1968,9 +1976,9 @@ int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct tree ...@@ -1968,9 +1976,9 @@ int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct tree
key2type(&(key->on_disk_key))); key2type(&(key->on_disk_key)));
#endif #endif
reiserfs_write_unlock(inode->i_sb); depth = reiserfs_write_unlock_nested(sb);
retval = dquot_alloc_space_nodirty(inode, pasted_size); retval = dquot_alloc_space_nodirty(inode, pasted_size);
reiserfs_write_lock(inode->i_sb); reiserfs_write_lock_nested(sb, depth);
if (retval) { if (retval) {
pathrelse(search_path); pathrelse(search_path);
return retval; return retval;
...@@ -2027,7 +2035,9 @@ int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct tree ...@@ -2027,7 +2035,9 @@ int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct tree
pasted_size, inode->i_uid, pasted_size, inode->i_uid,
key2type(&(key->on_disk_key))); key2type(&(key->on_disk_key)));
#endif #endif
depth = reiserfs_write_unlock_nested(sb);
dquot_free_space_nodirty(inode, pasted_size); dquot_free_space_nodirty(inode, pasted_size);
reiserfs_write_lock_nested(sb, depth);
return retval; return retval;
} }
...@@ -2050,6 +2060,7 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th, ...@@ -2050,6 +2060,7 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th,
BUG_ON(!th->t_trans_id); BUG_ON(!th->t_trans_id);
if (inode) { /* Do we count quotas for item? */ if (inode) { /* Do we count quotas for item? */
int depth;
fs_gen = get_generation(inode->i_sb); fs_gen = get_generation(inode->i_sb);
quota_bytes = ih_item_len(ih); quota_bytes = ih_item_len(ih);
...@@ -2063,11 +2074,11 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th, ...@@ -2063,11 +2074,11 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th,
"reiserquota insert_item(): allocating %u id=%u type=%c", "reiserquota insert_item(): allocating %u id=%u type=%c",
quota_bytes, inode->i_uid, head2type(ih)); quota_bytes, inode->i_uid, head2type(ih));
#endif #endif
reiserfs_write_unlock(inode->i_sb);
/* We can't dirty inode here. It would be immediately written but /* We can't dirty inode here. It would be immediately written but
* appropriate stat item isn't inserted yet... */ * appropriate stat item isn't inserted yet... */
depth = reiserfs_write_unlock_nested(inode->i_sb);
retval = dquot_alloc_space_nodirty(inode, quota_bytes); retval = dquot_alloc_space_nodirty(inode, quota_bytes);
reiserfs_write_lock(inode->i_sb); reiserfs_write_lock_nested(inode->i_sb, depth);
if (retval) { if (retval) {
pathrelse(path); pathrelse(path);
return retval; return retval;
...@@ -2118,7 +2129,10 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th, ...@@ -2118,7 +2129,10 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th,
"reiserquota insert_item(): freeing %u id=%u type=%c", "reiserquota insert_item(): freeing %u id=%u type=%c",
quota_bytes, inode->i_uid, head2type(ih)); quota_bytes, inode->i_uid, head2type(ih));
#endif #endif
if (inode) if (inode) {
int depth = reiserfs_write_unlock_nested(inode->i_sb);
dquot_free_space_nodirty(inode, quota_bytes); dquot_free_space_nodirty(inode, quota_bytes);
reiserfs_write_lock_nested(inode->i_sb, depth);
}
return retval; return retval;
} }
...@@ -243,6 +243,7 @@ static int finish_unfinished(struct super_block *s) ...@@ -243,6 +243,7 @@ static int finish_unfinished(struct super_block *s)
done = 0; done = 0;
REISERFS_SB(s)->s_is_unlinked_ok = 1; REISERFS_SB(s)->s_is_unlinked_ok = 1;
while (!retval) { while (!retval) {
int depth;
retval = search_item(s, &max_cpu_key, &path); retval = search_item(s, &max_cpu_key, &path);
if (retval != ITEM_NOT_FOUND) { if (retval != ITEM_NOT_FOUND) {
reiserfs_error(s, "vs-2140", reiserfs_error(s, "vs-2140",
...@@ -298,9 +299,9 @@ static int finish_unfinished(struct super_block *s) ...@@ -298,9 +299,9 @@ static int finish_unfinished(struct super_block *s)
retval = remove_save_link_only(s, &save_link_key, 0); retval = remove_save_link_only(s, &save_link_key, 0);
continue; continue;
} }
reiserfs_write_unlock(s); depth = reiserfs_write_unlock_nested(inode->i_sb);
dquot_initialize(inode); dquot_initialize(inode);
reiserfs_write_lock(s); reiserfs_write_lock_nested(inode->i_sb, depth);
if (truncate && S_ISDIR(inode->i_mode)) { if (truncate && S_ISDIR(inode->i_mode)) {
/* We got a truncate request for a dir which is impossible. /* We got a truncate request for a dir which is impossible.
...@@ -356,10 +357,12 @@ static int finish_unfinished(struct super_block *s) ...@@ -356,10 +357,12 @@ static int finish_unfinished(struct super_block *s)
#ifdef CONFIG_QUOTA #ifdef CONFIG_QUOTA
/* Turn quotas off */ /* Turn quotas off */
reiserfs_write_unlock(s);
for (i = 0; i < MAXQUOTAS; i++) { for (i = 0; i < MAXQUOTAS; i++) {
if (sb_dqopt(s)->files[i] && quota_enabled[i]) if (sb_dqopt(s)->files[i] && quota_enabled[i])
dquot_quota_off(s, i); dquot_quota_off(s, i);
} }
reiserfs_write_lock(s);
if (ms_active_set) if (ms_active_set)
/* Restore the flag back */ /* Restore the flag back */
s->s_flags &= ~MS_ACTIVE; s->s_flags &= ~MS_ACTIVE;
...@@ -623,7 +626,6 @@ static void reiserfs_dirty_inode(struct inode *inode, int flags) ...@@ -623,7 +626,6 @@ static void reiserfs_dirty_inode(struct inode *inode, int flags)
struct reiserfs_transaction_handle th; struct reiserfs_transaction_handle th;
int err = 0; int err = 0;
int lock_depth;
if (inode->i_sb->s_flags & MS_RDONLY) { if (inode->i_sb->s_flags & MS_RDONLY) {
reiserfs_warning(inode->i_sb, "clm-6006", reiserfs_warning(inode->i_sb, "clm-6006",
...@@ -631,7 +633,7 @@ static void reiserfs_dirty_inode(struct inode *inode, int flags) ...@@ -631,7 +633,7 @@ static void reiserfs_dirty_inode(struct inode *inode, int flags)
inode->i_ino); inode->i_ino);
return; return;
} }
lock_depth = reiserfs_write_lock_once(inode->i_sb); reiserfs_write_lock(inode->i_sb);
/* this is really only used for atime updates, so they don't have /* this is really only used for atime updates, so they don't have
** to be included in O_SYNC or fsync ** to be included in O_SYNC or fsync
...@@ -644,7 +646,7 @@ static void reiserfs_dirty_inode(struct inode *inode, int flags) ...@@ -644,7 +646,7 @@ static void reiserfs_dirty_inode(struct inode *inode, int flags)
journal_end(&th, inode->i_sb, 1); journal_end(&th, inode->i_sb, 1);
out: out:
reiserfs_write_unlock_once(inode->i_sb, lock_depth); reiserfs_write_unlock(inode->i_sb);
} }
static int reiserfs_show_options(struct seq_file *seq, struct dentry *root) static int reiserfs_show_options(struct seq_file *seq, struct dentry *root)
...@@ -1334,7 +1336,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) ...@@ -1334,7 +1336,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
kfree(qf_names[i]); kfree(qf_names[i]);
#endif #endif
err = -EINVAL; err = -EINVAL;
goto out_unlock; goto out_err_unlock;
} }
#ifdef CONFIG_QUOTA #ifdef CONFIG_QUOTA
handle_quota_files(s, qf_names, &qfmt); handle_quota_files(s, qf_names, &qfmt);
...@@ -1378,35 +1380,32 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) ...@@ -1378,35 +1380,32 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
if (blocks) { if (blocks) {
err = reiserfs_resize(s, blocks); err = reiserfs_resize(s, blocks);
if (err != 0) if (err != 0)
goto out_unlock; goto out_err_unlock;
} }
if (*mount_flags & MS_RDONLY) { if (*mount_flags & MS_RDONLY) {
reiserfs_write_unlock(s);
reiserfs_xattr_init(s, *mount_flags); reiserfs_xattr_init(s, *mount_flags);
/* remount read-only */ /* remount read-only */
if (s->s_flags & MS_RDONLY) if (s->s_flags & MS_RDONLY)
/* it is read-only already */ /* it is read-only already */
goto out_ok; goto out_ok_unlocked;
/*
* Drop write lock. Quota will retake it when needed and lock
* ordering requires calling dquot_suspend() without it.
*/
reiserfs_write_unlock(s);
err = dquot_suspend(s, -1); err = dquot_suspend(s, -1);
if (err < 0) if (err < 0)
goto out_err; goto out_err;
reiserfs_write_lock(s);
/* try to remount file system with read-only permissions */ /* try to remount file system with read-only permissions */
if (sb_umount_state(rs) == REISERFS_VALID_FS if (sb_umount_state(rs) == REISERFS_VALID_FS
|| REISERFS_SB(s)->s_mount_state != REISERFS_VALID_FS) { || REISERFS_SB(s)->s_mount_state != REISERFS_VALID_FS) {
goto out_ok; goto out_ok_unlocked;
} }
reiserfs_write_lock(s);
err = journal_begin(&th, s, 10); err = journal_begin(&th, s, 10);
if (err) if (err)
goto out_unlock; goto out_err_unlock;
/* Mounting a rw partition read-only. */ /* Mounting a rw partition read-only. */
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
...@@ -1415,13 +1414,14 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) ...@@ -1415,13 +1414,14 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
} else { } else {
/* remount read-write */ /* remount read-write */
if (!(s->s_flags & MS_RDONLY)) { if (!(s->s_flags & MS_RDONLY)) {
reiserfs_write_unlock(s);
reiserfs_xattr_init(s, *mount_flags); reiserfs_xattr_init(s, *mount_flags);
goto out_ok; /* We are read-write already */ goto out_ok_unlocked; /* We are read-write already */
} }
if (reiserfs_is_journal_aborted(journal)) { if (reiserfs_is_journal_aborted(journal)) {
err = journal->j_errno; err = journal->j_errno;
goto out_unlock; goto out_err_unlock;
} }
handle_data_mode(s, mount_options); handle_data_mode(s, mount_options);
...@@ -1430,7 +1430,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) ...@@ -1430,7 +1430,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
s->s_flags &= ~MS_RDONLY; /* now it is safe to call journal_begin */ s->s_flags &= ~MS_RDONLY; /* now it is safe to call journal_begin */
err = journal_begin(&th, s, 10); err = journal_begin(&th, s, 10);
if (err) if (err)
goto out_unlock; goto out_err_unlock;
/* Mount a partition which is read-only, read-write */ /* Mount a partition which is read-only, read-write */
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
...@@ -1447,26 +1447,22 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) ...@@ -1447,26 +1447,22 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
SB_JOURNAL(s)->j_must_wait = 1; SB_JOURNAL(s)->j_must_wait = 1;
err = journal_end(&th, s, 10); err = journal_end(&th, s, 10);
if (err) if (err)
goto out_unlock; goto out_err_unlock;
reiserfs_write_unlock(s);
if (!(*mount_flags & MS_RDONLY)) { if (!(*mount_flags & MS_RDONLY)) {
/*
* Drop write lock. Quota will retake it when needed and lock
* ordering requires calling dquot_resume() without it.
*/
reiserfs_write_unlock(s);
dquot_resume(s, -1); dquot_resume(s, -1);
reiserfs_write_lock(s); reiserfs_write_lock(s);
finish_unfinished(s); finish_unfinished(s);
reiserfs_write_unlock(s);
reiserfs_xattr_init(s, *mount_flags); reiserfs_xattr_init(s, *mount_flags);
} }
out_ok: out_ok_unlocked:
replace_mount_options(s, new_opts); replace_mount_options(s, new_opts);
reiserfs_write_unlock(s);
return 0; return 0;
out_unlock: out_err_unlock:
reiserfs_write_unlock(s); reiserfs_write_unlock(s);
out_err: out_err:
kfree(new_opts); kfree(new_opts);
...@@ -2013,12 +2009,14 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) ...@@ -2013,12 +2009,14 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
goto error; goto error;
} }
reiserfs_write_unlock(s);
if ((errval = reiserfs_lookup_privroot(s)) || if ((errval = reiserfs_lookup_privroot(s)) ||
(errval = reiserfs_xattr_init(s, s->s_flags))) { (errval = reiserfs_xattr_init(s, s->s_flags))) {
dput(s->s_root); dput(s->s_root);
s->s_root = NULL; s->s_root = NULL;
goto error; goto error_unlocked;
} }
reiserfs_write_lock(s);
/* look for files which were to be removed in previous session */ /* look for files which were to be removed in previous session */
finish_unfinished(s); finish_unfinished(s);
...@@ -2027,12 +2025,14 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) ...@@ -2027,12 +2025,14 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
reiserfs_info(s, "using 3.5.x disk format\n"); reiserfs_info(s, "using 3.5.x disk format\n");
} }
reiserfs_write_unlock(s);
if ((errval = reiserfs_lookup_privroot(s)) || if ((errval = reiserfs_lookup_privroot(s)) ||
(errval = reiserfs_xattr_init(s, s->s_flags))) { (errval = reiserfs_xattr_init(s, s->s_flags))) {
dput(s->s_root); dput(s->s_root);
s->s_root = NULL; s->s_root = NULL;
goto error; goto error_unlocked;
} }
reiserfs_write_lock(s);
} }
// mark hash in super block: it could be unset. overwrite should be ok // mark hash in super block: it could be unset. overwrite should be ok
set_sb_hash_function_code(rs, function2code(sbi->s_hash_function)); set_sb_hash_function_code(rs, function2code(sbi->s_hash_function));
...@@ -2100,6 +2100,7 @@ static int reiserfs_write_dquot(struct dquot *dquot) ...@@ -2100,6 +2100,7 @@ static int reiserfs_write_dquot(struct dquot *dquot)
{ {
struct reiserfs_transaction_handle th; struct reiserfs_transaction_handle th;
int ret, err; int ret, err;
int depth;
reiserfs_write_lock(dquot->dq_sb); reiserfs_write_lock(dquot->dq_sb);
ret = ret =
...@@ -2107,9 +2108,9 @@ static int reiserfs_write_dquot(struct dquot *dquot) ...@@ -2107,9 +2108,9 @@ static int reiserfs_write_dquot(struct dquot *dquot)
REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb)); REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
if (ret) if (ret)
goto out; goto out;
reiserfs_write_unlock(dquot->dq_sb); depth = reiserfs_write_unlock_nested(dquot->dq_sb);
ret = dquot_commit(dquot); ret = dquot_commit(dquot);
reiserfs_write_lock(dquot->dq_sb); reiserfs_write_lock_nested(dquot->dq_sb, depth);
err = err =
journal_end(&th, dquot->dq_sb, journal_end(&th, dquot->dq_sb,
REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb)); REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
...@@ -2124,6 +2125,7 @@ static int reiserfs_acquire_dquot(struct dquot *dquot) ...@@ -2124,6 +2125,7 @@ static int reiserfs_acquire_dquot(struct dquot *dquot)
{ {
struct reiserfs_transaction_handle th; struct reiserfs_transaction_handle th;
int ret, err; int ret, err;
int depth;
reiserfs_write_lock(dquot->dq_sb); reiserfs_write_lock(dquot->dq_sb);
ret = ret =
...@@ -2131,9 +2133,9 @@ static int reiserfs_acquire_dquot(struct dquot *dquot) ...@@ -2131,9 +2133,9 @@ static int reiserfs_acquire_dquot(struct dquot *dquot)
REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb)); REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));
if (ret) if (ret)
goto out; goto out;
reiserfs_write_unlock(dquot->dq_sb); depth = reiserfs_write_unlock_nested(dquot->dq_sb);
ret = dquot_acquire(dquot); ret = dquot_acquire(dquot);
reiserfs_write_lock(dquot->dq_sb); reiserfs_write_lock_nested(dquot->dq_sb, depth);
err = err =
journal_end(&th, dquot->dq_sb, journal_end(&th, dquot->dq_sb,
REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb)); REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));
...@@ -2186,15 +2188,16 @@ static int reiserfs_write_info(struct super_block *sb, int type) ...@@ -2186,15 +2188,16 @@ static int reiserfs_write_info(struct super_block *sb, int type)
{ {
struct reiserfs_transaction_handle th; struct reiserfs_transaction_handle th;
int ret, err; int ret, err;
int depth;
/* Data block + inode block */ /* Data block + inode block */
reiserfs_write_lock(sb); reiserfs_write_lock(sb);
ret = journal_begin(&th, sb, 2); ret = journal_begin(&th, sb, 2);
if (ret) if (ret)
goto out; goto out;
reiserfs_write_unlock(sb); depth = reiserfs_write_unlock_nested(sb);
ret = dquot_commit_info(sb, type); ret = dquot_commit_info(sb, type);
reiserfs_write_lock(sb); reiserfs_write_lock_nested(sb, depth);
err = journal_end(&th, sb, 2); err = journal_end(&th, sb, 2);
if (!ret && err) if (!ret && err)
ret = err; ret = err;
......
...@@ -81,8 +81,7 @@ static int xattr_unlink(struct inode *dir, struct dentry *dentry) ...@@ -81,8 +81,7 @@ static int xattr_unlink(struct inode *dir, struct dentry *dentry)
int error; int error;
BUG_ON(!mutex_is_locked(&dir->i_mutex)); BUG_ON(!mutex_is_locked(&dir->i_mutex));
reiserfs_mutex_lock_nested_safe(&dentry->d_inode->i_mutex, mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD);
I_MUTEX_CHILD, dir->i_sb);
error = dir->i_op->unlink(dir, dentry); error = dir->i_op->unlink(dir, dentry);
mutex_unlock(&dentry->d_inode->i_mutex); mutex_unlock(&dentry->d_inode->i_mutex);
...@@ -96,8 +95,7 @@ static int xattr_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -96,8 +95,7 @@ static int xattr_rmdir(struct inode *dir, struct dentry *dentry)
int error; int error;
BUG_ON(!mutex_is_locked(&dir->i_mutex)); BUG_ON(!mutex_is_locked(&dir->i_mutex));
reiserfs_mutex_lock_nested_safe(&dentry->d_inode->i_mutex, mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD);
I_MUTEX_CHILD, dir->i_sb);
error = dir->i_op->rmdir(dir, dentry); error = dir->i_op->rmdir(dir, dentry);
if (!error) if (!error)
dentry->d_inode->i_flags |= S_DEAD; dentry->d_inode->i_flags |= S_DEAD;
...@@ -232,22 +230,17 @@ static int reiserfs_for_each_xattr(struct inode *inode, ...@@ -232,22 +230,17 @@ static int reiserfs_for_each_xattr(struct inode *inode,
if (IS_PRIVATE(inode) || get_inode_sd_version(inode) == STAT_DATA_V1) if (IS_PRIVATE(inode) || get_inode_sd_version(inode) == STAT_DATA_V1)
return 0; return 0;
reiserfs_write_unlock(inode->i_sb);
dir = open_xa_dir(inode, XATTR_REPLACE); dir = open_xa_dir(inode, XATTR_REPLACE);
if (IS_ERR(dir)) { if (IS_ERR(dir)) {
err = PTR_ERR(dir); err = PTR_ERR(dir);
reiserfs_write_lock(inode->i_sb);
goto out; goto out;
} else if (!dir->d_inode) { } else if (!dir->d_inode) {
err = 0; err = 0;
reiserfs_write_lock(inode->i_sb);
goto out_dir; goto out_dir;
} }
mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR); mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR);
reiserfs_write_lock(inode->i_sb);
buf.xadir = dir; buf.xadir = dir;
while (1) { while (1) {
err = reiserfs_readdir_inode(dir->d_inode, &buf.ctx); err = reiserfs_readdir_inode(dir->d_inode, &buf.ctx);
...@@ -281,14 +274,17 @@ static int reiserfs_for_each_xattr(struct inode *inode, ...@@ -281,14 +274,17 @@ static int reiserfs_for_each_xattr(struct inode *inode,
int blocks = JOURNAL_PER_BALANCE_CNT * 2 + 2 + int blocks = JOURNAL_PER_BALANCE_CNT * 2 + 2 +
4 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb); 4 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb);
struct reiserfs_transaction_handle th; struct reiserfs_transaction_handle th;
reiserfs_write_lock(inode->i_sb);
err = journal_begin(&th, inode->i_sb, blocks); err = journal_begin(&th, inode->i_sb, blocks);
reiserfs_write_unlock(inode->i_sb);
if (!err) { if (!err) {
int jerror; int jerror;
reiserfs_mutex_lock_nested_safe( mutex_lock_nested(&dir->d_parent->d_inode->i_mutex,
&dir->d_parent->d_inode->i_mutex, I_MUTEX_XATTR);
I_MUTEX_XATTR, inode->i_sb);
err = action(dir, data); err = action(dir, data);
reiserfs_write_lock(inode->i_sb);
jerror = journal_end(&th, inode->i_sb, blocks); jerror = journal_end(&th, inode->i_sb, blocks);
reiserfs_write_unlock(inode->i_sb);
mutex_unlock(&dir->d_parent->d_inode->i_mutex); mutex_unlock(&dir->d_parent->d_inode->i_mutex);
err = jerror ?: err; err = jerror ?: err;
} }
...@@ -455,9 +451,7 @@ static int lookup_and_delete_xattr(struct inode *inode, const char *name) ...@@ -455,9 +451,7 @@ static int lookup_and_delete_xattr(struct inode *inode, const char *name)
} }
if (dentry->d_inode) { if (dentry->d_inode) {
reiserfs_write_lock(inode->i_sb);
err = xattr_unlink(xadir->d_inode, dentry); err = xattr_unlink(xadir->d_inode, dentry);
reiserfs_write_unlock(inode->i_sb);
update_ctime(inode); update_ctime(inode);
} }
...@@ -491,24 +485,17 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th, ...@@ -491,24 +485,17 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th,
if (get_inode_sd_version(inode) == STAT_DATA_V1) if (get_inode_sd_version(inode) == STAT_DATA_V1)
return -EOPNOTSUPP; return -EOPNOTSUPP;
reiserfs_write_unlock(inode->i_sb);
if (!buffer) { if (!buffer) {
err = lookup_and_delete_xattr(inode, name); err = lookup_and_delete_xattr(inode, name);
reiserfs_write_lock(inode->i_sb);
return err; return err;
} }
dentry = xattr_lookup(inode, name, flags); dentry = xattr_lookup(inode, name, flags);
if (IS_ERR(dentry)) { if (IS_ERR(dentry))
reiserfs_write_lock(inode->i_sb);
return PTR_ERR(dentry); return PTR_ERR(dentry);
}
down_write(&REISERFS_I(inode)->i_xattr_sem); down_write(&REISERFS_I(inode)->i_xattr_sem);
reiserfs_write_lock(inode->i_sb);
xahash = xattr_hash(buffer, buffer_size); xahash = xattr_hash(buffer, buffer_size);
while (buffer_pos < buffer_size || buffer_pos == 0) { while (buffer_pos < buffer_size || buffer_pos == 0) {
size_t chunk; size_t chunk;
...@@ -538,6 +525,7 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th, ...@@ -538,6 +525,7 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th,
rxh->h_hash = cpu_to_le32(xahash); rxh->h_hash = cpu_to_le32(xahash);
} }
reiserfs_write_lock(inode->i_sb);
err = __reiserfs_write_begin(page, page_offset, chunk + skip); err = __reiserfs_write_begin(page, page_offset, chunk + skip);
if (!err) { if (!err) {
if (buffer) if (buffer)
...@@ -546,6 +534,7 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th, ...@@ -546,6 +534,7 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th,
page_offset + chunk + page_offset + chunk +
skip); skip);
} }
reiserfs_write_unlock(inode->i_sb);
unlock_page(page); unlock_page(page);
reiserfs_put_page(page); reiserfs_put_page(page);
buffer_pos += chunk; buffer_pos += chunk;
...@@ -563,10 +552,8 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th, ...@@ -563,10 +552,8 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th,
.ia_valid = ATTR_SIZE | ATTR_CTIME, .ia_valid = ATTR_SIZE | ATTR_CTIME,
}; };
reiserfs_write_unlock(inode->i_sb);
mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_XATTR); mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_XATTR);
inode_dio_wait(dentry->d_inode); inode_dio_wait(dentry->d_inode);
reiserfs_write_lock(inode->i_sb);
err = reiserfs_setattr(dentry, &newattrs); err = reiserfs_setattr(dentry, &newattrs);
mutex_unlock(&dentry->d_inode->i_mutex); mutex_unlock(&dentry->d_inode->i_mutex);
...@@ -592,18 +579,19 @@ int reiserfs_xattr_set(struct inode *inode, const char *name, ...@@ -592,18 +579,19 @@ int reiserfs_xattr_set(struct inode *inode, const char *name,
reiserfs_write_lock(inode->i_sb); reiserfs_write_lock(inode->i_sb);
error = journal_begin(&th, inode->i_sb, jbegin_count); error = journal_begin(&th, inode->i_sb, jbegin_count);
reiserfs_write_unlock(inode->i_sb);
if (error) { if (error) {
reiserfs_write_unlock(inode->i_sb);
return error; return error;
} }
error = reiserfs_xattr_set_handle(&th, inode, name, error = reiserfs_xattr_set_handle(&th, inode, name,
buffer, buffer_size, flags); buffer, buffer_size, flags);
reiserfs_write_lock(inode->i_sb);
error2 = journal_end(&th, inode->i_sb, jbegin_count); error2 = journal_end(&th, inode->i_sb, jbegin_count);
reiserfs_write_unlock(inode->i_sb);
if (error == 0) if (error == 0)
error = error2; error = error2;
reiserfs_write_unlock(inode->i_sb);
return error; return error;
} }
...@@ -968,7 +956,7 @@ int reiserfs_lookup_privroot(struct super_block *s) ...@@ -968,7 +956,7 @@ int reiserfs_lookup_privroot(struct super_block *s)
int err = 0; int err = 0;
/* If we don't have the privroot located yet - go find it */ /* If we don't have the privroot located yet - go find it */
reiserfs_mutex_lock_safe(&s->s_root->d_inode->i_mutex, s); mutex_lock(&s->s_root->d_inode->i_mutex);
dentry = lookup_one_len(PRIVROOT_NAME, s->s_root, dentry = lookup_one_len(PRIVROOT_NAME, s->s_root,
strlen(PRIVROOT_NAME)); strlen(PRIVROOT_NAME));
if (!IS_ERR(dentry)) { if (!IS_ERR(dentry)) {
...@@ -996,14 +984,14 @@ int reiserfs_xattr_init(struct super_block *s, int mount_flags) ...@@ -996,14 +984,14 @@ int reiserfs_xattr_init(struct super_block *s, int mount_flags)
goto error; goto error;
if (!privroot->d_inode && !(mount_flags & MS_RDONLY)) { if (!privroot->d_inode && !(mount_flags & MS_RDONLY)) {
reiserfs_mutex_lock_safe(&s->s_root->d_inode->i_mutex, s); mutex_lock(&s->s_root->d_inode->i_mutex);
err = create_privroot(REISERFS_SB(s)->priv_root); err = create_privroot(REISERFS_SB(s)->priv_root);
mutex_unlock(&s->s_root->d_inode->i_mutex); mutex_unlock(&s->s_root->d_inode->i_mutex);
} }
if (privroot->d_inode) { if (privroot->d_inode) {
s->s_xattr = reiserfs_xattr_handlers; s->s_xattr = reiserfs_xattr_handlers;
reiserfs_mutex_lock_safe(&privroot->d_inode->i_mutex, s); mutex_lock(&privroot->d_inode->i_mutex);
if (!REISERFS_SB(s)->xattr_root) { if (!REISERFS_SB(s)->xattr_root) {
struct dentry *dentry; struct dentry *dentry;
dentry = lookup_one_len(XAROOT_NAME, privroot, dentry = lookup_one_len(XAROOT_NAME, privroot,
......
...@@ -49,13 +49,15 @@ posix_acl_set(struct dentry *dentry, const char *name, const void *value, ...@@ -49,13 +49,15 @@ posix_acl_set(struct dentry *dentry, const char *name, const void *value,
reiserfs_write_lock(inode->i_sb); reiserfs_write_lock(inode->i_sb);
error = journal_begin(&th, inode->i_sb, jcreate_blocks); error = journal_begin(&th, inode->i_sb, jcreate_blocks);
reiserfs_write_unlock(inode->i_sb);
if (error == 0) { if (error == 0) {
error = reiserfs_set_acl(&th, inode, type, acl); error = reiserfs_set_acl(&th, inode, type, acl);
reiserfs_write_lock(inode->i_sb);
error2 = journal_end(&th, inode->i_sb, jcreate_blocks); error2 = journal_end(&th, inode->i_sb, jcreate_blocks);
reiserfs_write_unlock(inode->i_sb);
if (error2) if (error2)
error = error2; error = error2;
} }
reiserfs_write_unlock(inode->i_sb);
release_and_out: release_and_out:
posix_acl_release(acl); posix_acl_release(acl);
...@@ -435,12 +437,14 @@ int reiserfs_cache_default_acl(struct inode *inode) ...@@ -435,12 +437,14 @@ int reiserfs_cache_default_acl(struct inode *inode)
return nblocks; return nblocks;
} }
/*
* Called under i_mutex
*/
int reiserfs_acl_chmod(struct inode *inode) int reiserfs_acl_chmod(struct inode *inode)
{ {
struct reiserfs_transaction_handle th; struct reiserfs_transaction_handle th;
struct posix_acl *acl; struct posix_acl *acl;
size_t size; size_t size;
int depth;
int error; int error;
if (IS_PRIVATE(inode)) if (IS_PRIVATE(inode))
...@@ -454,9 +458,7 @@ int reiserfs_acl_chmod(struct inode *inode) ...@@ -454,9 +458,7 @@ int reiserfs_acl_chmod(struct inode *inode)
return 0; return 0;
} }
reiserfs_write_unlock(inode->i_sb);
acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS); acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS);
reiserfs_write_lock(inode->i_sb);
if (!acl) if (!acl)
return 0; return 0;
if (IS_ERR(acl)) if (IS_ERR(acl))
...@@ -466,16 +468,18 @@ int reiserfs_acl_chmod(struct inode *inode) ...@@ -466,16 +468,18 @@ int reiserfs_acl_chmod(struct inode *inode)
return error; return error;
size = reiserfs_xattr_nblocks(inode, reiserfs_acl_size(acl->a_count)); size = reiserfs_xattr_nblocks(inode, reiserfs_acl_size(acl->a_count));
depth = reiserfs_write_lock_once(inode->i_sb); reiserfs_write_lock(inode->i_sb);
error = journal_begin(&th, inode->i_sb, size * 2); error = journal_begin(&th, inode->i_sb, size * 2);
reiserfs_write_unlock(inode->i_sb);
if (!error) { if (!error) {
int error2; int error2;
error = reiserfs_set_acl(&th, inode, ACL_TYPE_ACCESS, acl); error = reiserfs_set_acl(&th, inode, ACL_TYPE_ACCESS, acl);
reiserfs_write_lock(inode->i_sb);
error2 = journal_end(&th, inode->i_sb, size * 2); error2 = journal_end(&th, inode->i_sb, size * 2);
reiserfs_write_unlock(inode->i_sb);
if (error2) if (error2)
error = error2; error = error2;
} }
reiserfs_write_unlock_once(inode->i_sb, depth);
posix_acl_release(acl); posix_acl_release(acl);
return error; return error;
} }
......
此差异已折叠。
...@@ -57,16 +57,13 @@ ...@@ -57,16 +57,13 @@
#define JBD_EXPENSIVE_CHECKING #define JBD_EXPENSIVE_CHECKING
extern u8 journal_enable_debug; extern u8 journal_enable_debug;
#define jbd_debug(n, f, a...) \ void __jbd_debug(int level, const char *file, const char *func,
do { \ unsigned int line, const char *fmt, ...);
if ((n) <= journal_enable_debug) { \
printk (KERN_DEBUG "(%s, %d): %s: ", \ #define jbd_debug(n, fmt, a...) \
__FILE__, __LINE__, __func__); \ __jbd_debug((n), __FILE__, __func__, __LINE__, (fmt), ##a)
printk (f, ## a); \
} \
} while (0)
#else #else
#define jbd_debug(f, a...) /**/ #define jbd_debug(n, fmt, a...) /**/
#endif #endif
static inline void *jbd_alloc(size_t size, gfp_t flags) static inline void *jbd_alloc(size_t size, gfp_t flags)
...@@ -77,7 +74,7 @@ static inline void *jbd_alloc(size_t size, gfp_t flags) ...@@ -77,7 +74,7 @@ static inline void *jbd_alloc(size_t size, gfp_t flags)
static inline void jbd_free(void *ptr, size_t size) static inline void jbd_free(void *ptr, size_t size)
{ {
free_pages((unsigned long)ptr, get_order(size)); free_pages((unsigned long)ptr, get_order(size));
}; }
#define JFS_MIN_JOURNAL_BLOCKS 1024 #define JFS_MIN_JOURNAL_BLOCKS 1024
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册