Skip to content

Commit

Permalink
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/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
  • Loading branch information
Linus Torvalds committed Sep 6, 2013
2 parents eb97a78 + 97a2847 commit ec0ad73
Show file tree
Hide file tree
Showing 22 changed files with 609 additions and 445 deletions.
7 changes: 4 additions & 3 deletions Documentation/filesystems/ext3.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@ journal=inum When a journal already exists, this option is ignored.
Otherwise, it specifies the number of the inode which
will represent the ext3 file system's journal file.

journal_path=path
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
identified through its new major/minor numbers encoded
in devnum.
identified through either its new major/minor numbers
encoded in devnum, or via a path to the device.

norecovery Don't load the journal on mounting. Note that this forces
noload mount of inconsistent filesystem, which can lead to
Expand Down
43 changes: 43 additions & 0 deletions fs/ext3/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <linux/seq_file.h>
#include <linux/log2.h>
#include <linux/cleancache.h>
#include <linux/namei.h>

#include <asm/uaccess.h>

Expand Down Expand Up @@ -819,6 +820,7 @@ enum {
Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl,
Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, Opt_bh,
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_data_err_abort, Opt_data_err_ignore,
Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
Expand Down Expand Up @@ -860,6 +862,7 @@ static const match_table_t tokens = {
{Opt_journal_update, "journal=update"},
{Opt_journal_inum, "journal=%u"},
{Opt_journal_dev, "journal_dev=%u"},
{Opt_journal_path, "journal_path=%s"},
{Opt_abort, "abort"},
{Opt_data_journal, "data=journal"},
{Opt_data_ordered, "data=ordered"},
Expand Down Expand Up @@ -975,6 +978,11 @@ static int parse_options (char *options, struct super_block *sb,
int option;
kuid_t uid;
kgid_t gid;
char *journal_path;
struct inode *journal_inode;
struct path path;
int error;

#ifdef CONFIG_QUOTA
int qfmt;
#endif
Expand Down Expand Up @@ -1129,6 +1137,41 @@ static int parse_options (char *options, struct super_block *sb,
return 0;
*journal_devnum = option;
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:
set_opt (sbi->s_mount_opt, NOLOAD);
break;
Expand Down
16 changes: 5 additions & 11 deletions fs/isofs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@ static void destroy_inodecache(void)

static int isofs_remount(struct super_block *sb, int *flags, char *data)
{
/* we probably want a lot more here */
*flags |= MS_RDONLY;
if (!(*flags & MS_RDONLY))
return -EROFS;
return 0;
}

Expand Down Expand Up @@ -763,15 +763,6 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
*/
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
which we don't have .. */

Expand Down Expand Up @@ -1530,6 +1521,9 @@ struct inode *isofs_iget(struct super_block *sb,
static struct dentry *isofs_mount(struct file_system_type *fs_type,
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);
}

Expand Down
2 changes: 1 addition & 1 deletion fs/jbd/commit.c
Original file line number Diff line number Diff line change
Expand Up @@ -340,13 +340,13 @@ void journal_commit_transaction(journal_t *journal)
J_ASSERT(journal->j_committing_transaction == NULL);

commit_transaction = journal->j_running_transaction;
J_ASSERT(commit_transaction->t_state == T_RUNNING);

trace_jbd_start_commit(journal, commit_transaction);
jbd_debug(1, "JBD: starting commit of transaction %d\n",
commit_transaction->t_tid);

spin_lock(&journal->j_state_lock);
J_ASSERT(commit_transaction->t_state == T_RUNNING);
commit_transaction->t_state = T_LOCKED;

trace_jbd_commit_locking(journal, commit_transaction);
Expand Down
18 changes: 18 additions & 0 deletions fs/jbd/journal.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 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
*/
Expand Down
22 changes: 18 additions & 4 deletions fs/reiserfs/bitmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -423,8 +423,11 @@ static void _reiserfs_free_block(struct reiserfs_transaction_handle *th,
set_sb_free_blocks(rs, sb_free_blocks(rs) + 1);

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);
reiserfs_write_lock_nested(s, depth);
}
}

void reiserfs_free_block(struct reiserfs_transaction_handle *th,
Expand Down Expand Up @@ -1128,6 +1131,7 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start
b_blocknr_t finish = SB_BLOCK_COUNT(s) - 1;
int passno = 0;
int nr_allocated = 0;
int depth;

determine_prealloc_size(hint);
if (!hint->formatted_node) {
Expand All @@ -1137,10 +1141,13 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start
"reiserquota: allocating %d blocks id=%u",
amount_needed, hint->inode->i_uid);
#endif
depth = reiserfs_write_unlock_nested(s);
quota_ret =
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;
}
if (hint->preallocate && hint->prealloc_size) {
#ifdef REISERQUOTA_DEBUG
reiserfs_debug(s, REISERFS_DEBUG_CODE,
Expand All @@ -1153,6 +1160,7 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start
hint->preallocate = hint->prealloc_size = 0;
}
/* for unformatted nodes, force large allocations */
reiserfs_write_lock_nested(s, depth);
}

do {
Expand Down Expand Up @@ -1181,9 +1189,11 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start
hint->inode->i_uid);
#endif
/* Free not allocated blocks */
depth = reiserfs_write_unlock_nested(s);
dquot_free_block_nodirty(hint->inode,
amount_needed + hint->prealloc_size -
nr_allocated);
reiserfs_write_lock_nested(s, depth);
}
while (nr_allocated--)
reiserfs_free_block(hint->th, hint->inode,
Expand Down Expand Up @@ -1214,10 +1224,13 @@ static inline int blocknrs_and_prealloc_arrays_from_search_start
REISERFS_I(hint->inode)->i_prealloc_count,
hint->inode->i_uid);
#endif

depth = reiserfs_write_unlock_nested(s);
dquot_free_block_nodirty(hint->inode, amount_needed +
hint->prealloc_size - nr_allocated -
REISERFS_I(hint->inode)->
i_prealloc_count);
reiserfs_write_lock_nested(s, depth);
}

return CARRY_ON;
Expand Down Expand Up @@ -1340,10 +1353,11 @@ struct buffer_head *reiserfs_read_bitmap_block(struct super_block *sb,
"reading failed", __func__, block);
else {
if (buffer_locked(bh)) {
int depth;
PROC_INFO_INC(sb, scan_bitmap.wait);
reiserfs_write_unlock(sb);
depth = reiserfs_write_unlock_nested(sb);
__wait_on_buffer(bh);
reiserfs_write_lock(sb);
reiserfs_write_lock_nested(sb, depth);
}
BUG_ON(!buffer_uptodate(bh));
BUG_ON(atomic_read(&bh->b_count) == 0);
Expand Down
7 changes: 4 additions & 3 deletions fs/reiserfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ int reiserfs_readdir_inode(struct inode *inode, struct dir_context *ctx)
char small_buf[32]; /* avoid kmalloc if we can */
struct reiserfs_dir_entry de;
int ret = 0;
int depth;

reiserfs_write_lock(inode->i_sb);

Expand Down Expand Up @@ -181,17 +182,17 @@ int reiserfs_readdir_inode(struct inode *inode, struct dir_context *ctx)
* Since filldir might sleep, we can release
* the write lock here for other waiters
*/
reiserfs_write_unlock(inode->i_sb);
depth = reiserfs_write_unlock_nested(inode->i_sb);
if (!dir_emit
(ctx, local_buf, d_reclen, d_ino,
DT_UNKNOWN)) {
reiserfs_write_lock(inode->i_sb);
reiserfs_write_lock_nested(inode->i_sb, depth);
if (local_buf != small_buf) {
kfree(local_buf);
}
goto end;
}
reiserfs_write_lock(inode->i_sb);
reiserfs_write_lock_nested(inode->i_sb, depth);
if (local_buf != small_buf) {
kfree(local_buf);
}
Expand Down
26 changes: 14 additions & 12 deletions fs/reiserfs/fix_node.c
Original file line number Diff line number Diff line change
Expand Up @@ -1022,9 +1022,9 @@ static int get_far_parent(struct tree_balance *tb,
if (buffer_locked(*pcom_father)) {

/* 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);
reiserfs_write_lock(tb->tb_sb);
reiserfs_write_lock_nested(tb->tb_sb, depth);
if (FILESYSTEM_CHANGED_TB(tb)) {
brelse(*pcom_father);
return REPEAT_SEARCH;
Expand Down Expand Up @@ -1929,9 +1929,9 @@ static int get_direct_parent(struct tree_balance *tb, int h)
return REPEAT_SEARCH;

if (buffer_locked(bh)) {
reiserfs_write_unlock(tb->tb_sb);
int depth = reiserfs_write_unlock_nested(tb->tb_sb);
__wait_on_buffer(bh);
reiserfs_write_lock(tb->tb_sb);
reiserfs_write_lock_nested(tb->tb_sb, depth);
if (FILESYSTEM_CHANGED_TB(tb))
return REPEAT_SEARCH;
}
Expand All @@ -1952,6 +1952,7 @@ static int get_neighbors(struct tree_balance *tb, int h)
unsigned long son_number;
struct super_block *sb = tb->tb_sb;
struct buffer_head *bh;
int depth;

PROC_INFO_INC(sb, get_neighbors[h]);

Expand All @@ -1969,9 +1970,9 @@ static int get_neighbors(struct tree_balance *tb, int h)
tb->FL[h]) ? tb->lkey[h] : B_NR_ITEMS(tb->
FL[h]);
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);
reiserfs_write_lock(sb);
reiserfs_write_lock_nested(tb->tb_sb, depth);
if (!bh)
return IO_ERROR;
if (FILESYSTEM_CHANGED_TB(tb)) {
Expand Down Expand Up @@ -2009,9 +2010,9 @@ static int get_neighbors(struct tree_balance *tb, int h)
child_position =
(bh == tb->FR[h]) ? tb->rkey[h] + 1 : 0;
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);
reiserfs_write_lock(sb);
reiserfs_write_lock_nested(tb->tb_sb, depth);
if (!bh)
return IO_ERROR;
if (FILESYSTEM_CHANGED_TB(tb)) {
Expand Down Expand Up @@ -2272,6 +2273,7 @@ static int wait_tb_buffers_until_unlocked(struct tree_balance *tb)
}

if (locked) {
int depth;
#ifdef CONFIG_REISERFS_CHECK
repeat_counter++;
if ((repeat_counter % 10000) == 0) {
Expand All @@ -2286,9 +2288,9 @@ static int wait_tb_buffers_until_unlocked(struct tree_balance *tb)
REPEAT_SEARCH : CARRY_ON;
}
#endif
reiserfs_write_unlock(tb->tb_sb);
depth = reiserfs_write_unlock_nested(tb->tb_sb);
__wait_on_buffer(locked);
reiserfs_write_lock(tb->tb_sb);
reiserfs_write_lock_nested(tb->tb_sb, depth);
if (FILESYSTEM_CHANGED_TB(tb))
return REPEAT_SEARCH;
}
Expand Down Expand Up @@ -2359,9 +2361,9 @@ int fix_nodes(int op_mode, struct tree_balance *tb,

/* if it possible in indirect_to_direct conversion */
if (buffer_locked(tbS0)) {
reiserfs_write_unlock(tb->tb_sb);
int depth = reiserfs_write_unlock_nested(tb->tb_sb);
__wait_on_buffer(tbS0);
reiserfs_write_lock(tb->tb_sb);
reiserfs_write_lock_nested(tb->tb_sb, depth);
if (FILESYSTEM_CHANGED_TB(tb))
return REPEAT_SEARCH;
}
Expand Down
Loading

0 comments on commit ec0ad73

Please sign in to comment.