|
@@ -298,7 +298,9 @@ static int finish_unfinished(struct super_block *s)
|
|
|
retval = remove_save_link_only(s, &save_link_key, 0);
|
|
|
continue;
|
|
|
}
|
|
|
+ reiserfs_write_unlock(s);
|
|
|
dquot_initialize(inode);
|
|
|
+ reiserfs_write_lock(s);
|
|
|
|
|
|
if (truncate && S_ISDIR(inode->i_mode)) {
|
|
|
/* We got a truncate request for a dir which is impossible.
|
|
@@ -1335,7 +1337,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
|
|
|
kfree(qf_names[i]);
|
|
|
#endif
|
|
|
err = -EINVAL;
|
|
|
- goto out_err;
|
|
|
+ goto out_unlock;
|
|
|
}
|
|
|
#ifdef CONFIG_QUOTA
|
|
|
handle_quota_files(s, qf_names, &qfmt);
|
|
@@ -1379,7 +1381,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
|
|
|
if (blocks) {
|
|
|
err = reiserfs_resize(s, blocks);
|
|
|
if (err != 0)
|
|
|
- goto out_err;
|
|
|
+ goto out_unlock;
|
|
|
}
|
|
|
|
|
|
if (*mount_flags & MS_RDONLY) {
|
|
@@ -1389,9 +1391,15 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
|
|
|
/* it is read-only already */
|
|
|
goto out_ok;
|
|
|
|
|
|
+ /*
|
|
|
+ * 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);
|
|
|
if (err < 0)
|
|
|
goto out_err;
|
|
|
+ reiserfs_write_lock(s);
|
|
|
|
|
|
/* try to remount file system with read-only permissions */
|
|
|
if (sb_umount_state(rs) == REISERFS_VALID_FS
|
|
@@ -1401,7 +1409,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
|
|
|
|
|
|
err = journal_begin(&th, s, 10);
|
|
|
if (err)
|
|
|
- goto out_err;
|
|
|
+ goto out_unlock;
|
|
|
|
|
|
/* Mounting a rw partition read-only. */
|
|
|
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
|
|
@@ -1416,7 +1424,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
|
|
|
|
|
|
if (reiserfs_is_journal_aborted(journal)) {
|
|
|
err = journal->j_errno;
|
|
|
- goto out_err;
|
|
|
+ goto out_unlock;
|
|
|
}
|
|
|
|
|
|
handle_data_mode(s, mount_options);
|
|
@@ -1425,7 +1433,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 */
|
|
|
err = journal_begin(&th, s, 10);
|
|
|
if (err)
|
|
|
- goto out_err;
|
|
|
+ goto out_unlock;
|
|
|
|
|
|
/* Mount a partition which is read-only, read-write */
|
|
|
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
|
|
@@ -1442,10 +1450,16 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
|
|
|
SB_JOURNAL(s)->j_must_wait = 1;
|
|
|
err = journal_end(&th, s, 10);
|
|
|
if (err)
|
|
|
- goto out_err;
|
|
|
+ goto out_unlock;
|
|
|
|
|
|
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);
|
|
|
+ reiserfs_write_lock(s);
|
|
|
finish_unfinished(s);
|
|
|
reiserfs_xattr_init(s, *mount_flags);
|
|
|
}
|
|
@@ -1455,9 +1469,10 @@ out_ok:
|
|
|
reiserfs_write_unlock(s);
|
|
|
return 0;
|
|
|
|
|
|
+out_unlock:
|
|
|
+ reiserfs_write_unlock(s);
|
|
|
out_err:
|
|
|
kfree(new_opts);
|
|
|
- reiserfs_write_unlock(s);
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -2095,13 +2110,15 @@ static int reiserfs_write_dquot(struct dquot *dquot)
|
|
|
REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
|
|
|
if (ret)
|
|
|
goto out;
|
|
|
+ reiserfs_write_unlock(dquot->dq_sb);
|
|
|
ret = dquot_commit(dquot);
|
|
|
+ reiserfs_write_lock(dquot->dq_sb);
|
|
|
err =
|
|
|
journal_end(&th, dquot->dq_sb,
|
|
|
REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
|
|
|
if (!ret && err)
|
|
|
ret = err;
|
|
|
- out:
|
|
|
+out:
|
|
|
reiserfs_write_unlock(dquot->dq_sb);
|
|
|
return ret;
|
|
|
}
|
|
@@ -2117,13 +2134,15 @@ static int reiserfs_acquire_dquot(struct dquot *dquot)
|
|
|
REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));
|
|
|
if (ret)
|
|
|
goto out;
|
|
|
+ reiserfs_write_unlock(dquot->dq_sb);
|
|
|
ret = dquot_acquire(dquot);
|
|
|
+ reiserfs_write_lock(dquot->dq_sb);
|
|
|
err =
|
|
|
journal_end(&th, dquot->dq_sb,
|
|
|
REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));
|
|
|
if (!ret && err)
|
|
|
ret = err;
|
|
|
- out:
|
|
|
+out:
|
|
|
reiserfs_write_unlock(dquot->dq_sb);
|
|
|
return ret;
|
|
|
}
|
|
@@ -2137,19 +2156,21 @@ static int reiserfs_release_dquot(struct dquot *dquot)
|
|
|
ret =
|
|
|
journal_begin(&th, dquot->dq_sb,
|
|
|
REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));
|
|
|
+ reiserfs_write_unlock(dquot->dq_sb);
|
|
|
if (ret) {
|
|
|
/* Release dquot anyway to avoid endless cycle in dqput() */
|
|
|
dquot_release(dquot);
|
|
|
goto out;
|
|
|
}
|
|
|
ret = dquot_release(dquot);
|
|
|
+ reiserfs_write_lock(dquot->dq_sb);
|
|
|
err =
|
|
|
journal_end(&th, dquot->dq_sb,
|
|
|
REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));
|
|
|
if (!ret && err)
|
|
|
ret = err;
|
|
|
- out:
|
|
|
reiserfs_write_unlock(dquot->dq_sb);
|
|
|
+out:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -2174,11 +2195,13 @@ static int reiserfs_write_info(struct super_block *sb, int type)
|
|
|
ret = journal_begin(&th, sb, 2);
|
|
|
if (ret)
|
|
|
goto out;
|
|
|
+ reiserfs_write_unlock(sb);
|
|
|
ret = dquot_commit_info(sb, type);
|
|
|
+ reiserfs_write_lock(sb);
|
|
|
err = journal_end(&th, sb, 2);
|
|
|
if (!ret && err)
|
|
|
ret = err;
|
|
|
- out:
|
|
|
+out:
|
|
|
reiserfs_write_unlock(sb);
|
|
|
return ret;
|
|
|
}
|
|
@@ -2203,8 +2226,11 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
|
|
|
struct reiserfs_transaction_handle th;
|
|
|
int opt = type == USRQUOTA ? REISERFS_USRQUOTA : REISERFS_GRPQUOTA;
|
|
|
|
|
|
- if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt)))
|
|
|
- return -EINVAL;
|
|
|
+ reiserfs_write_lock(sb);
|
|
|
+ if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt))) {
|
|
|
+ err = -EINVAL;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
|
|
|
/* Quotafile not on the same filesystem? */
|
|
|
if (path->dentry->d_sb != sb) {
|
|
@@ -2246,8 +2272,10 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
|
|
|
if (err)
|
|
|
goto out;
|
|
|
}
|
|
|
- err = dquot_quota_on(sb, type, format_id, path);
|
|
|
+ reiserfs_write_unlock(sb);
|
|
|
+ return dquot_quota_on(sb, type, format_id, path);
|
|
|
out:
|
|
|
+ reiserfs_write_unlock(sb);
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -2320,7 +2348,9 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type,
|
|
|
tocopy = sb->s_blocksize - offset < towrite ?
|
|
|
sb->s_blocksize - offset : towrite;
|
|
|
tmp_bh.b_state = 0;
|
|
|
+ reiserfs_write_lock(sb);
|
|
|
err = reiserfs_get_block(inode, blk, &tmp_bh, GET_BLOCK_CREATE);
|
|
|
+ reiserfs_write_unlock(sb);
|
|
|
if (err)
|
|
|
goto out;
|
|
|
if (offset || tocopy != sb->s_blocksize)
|
|
@@ -2336,10 +2366,12 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type,
|
|
|
flush_dcache_page(bh->b_page);
|
|
|
set_buffer_uptodate(bh);
|
|
|
unlock_buffer(bh);
|
|
|
+ reiserfs_write_lock(sb);
|
|
|
reiserfs_prepare_for_journal(sb, bh, 1);
|
|
|
journal_mark_dirty(current->journal_info, sb, bh);
|
|
|
if (!journal_quota)
|
|
|
reiserfs_add_ordered_list(inode, bh);
|
|
|
+ reiserfs_write_unlock(sb);
|
|
|
brelse(bh);
|
|
|
offset = 0;
|
|
|
towrite -= tocopy;
|