Commit ec0ad730 authored by Linus Torvalds's avatar 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
parents eb97a784 97a2847d
...@@ -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;
} }
......
This diff is collapsed.
...@@ -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;
} }
This diff is collapsed.
...@@ -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;
} }
......
This diff is collapsed.
...@@ -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%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment