Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7af11686 authored by Jan Kara's avatar Jan Kara
Browse files

reiserfs: Move quota calls out of write lock



Calls into highlevel quota code cannot happen under the write lock. These
calls take dqio_mutex which ranks above write lock. So drop write lock
before calling back into quota code.

CC: stable@vger.kernel.org # >= 3.0
Signed-off-by: default avatarJan Kara <jack@suse.cz>
parent 361d94a3
Loading
Loading
Loading
Loading
+7 −3
Original line number Diff line number Diff line
@@ -1782,8 +1782,9 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,

	BUG_ON(!th->t_trans_id);

	dquot_initialize(inode);
	reiserfs_write_unlock(inode->i_sb);
	err = dquot_alloc_inode(inode);
	reiserfs_write_lock(inode->i_sb);
	if (err)
		goto out_end_trans;
	if (!dir->i_nlink) {
@@ -1979,8 +1980,10 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,

      out_end_trans:
	journal_end(th, th->t_super, th->t_blocks_allocated);
	reiserfs_write_unlock(inode->i_sb);
	/* Drop can be outside and it needs more credits so it's better to have it outside */
	dquot_drop(inode);
	reiserfs_write_lock(inode->i_sb);
	inode->i_flags |= S_NOQUOTA;
	make_bad_inode(inode);

@@ -3103,10 +3106,9 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
	/* must be turned off for recursive notify_change calls */
	ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID);

	depth = reiserfs_write_lock_once(inode->i_sb);
	if (is_quota_modification(inode, attr))
		dquot_initialize(inode);

	depth = reiserfs_write_lock_once(inode->i_sb);
	if (attr->ia_valid & ATTR_SIZE) {
		/* version 2 items will be caught by the s_maxbytes check
		 ** done for us in vmtruncate
@@ -3170,7 +3172,9 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
		error = journal_begin(&th, inode->i_sb, jbegin_count);
		if (error)
			goto out;
		reiserfs_write_unlock_once(inode->i_sb, depth);
		error = dquot_transfer(inode, attr);
		depth = reiserfs_write_lock_once(inode->i_sb);
		if (error) {
			journal_end(&th, inode->i_sb, jbegin_count);
			goto out;
+4 −0
Original line number Diff line number Diff line
@@ -1968,7 +1968,9 @@ int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct tree
		       key2type(&(key->on_disk_key)));
#endif

	reiserfs_write_unlock(inode->i_sb);
	retval = dquot_alloc_space_nodirty(inode, pasted_size);
	reiserfs_write_lock(inode->i_sb);
	if (retval) {
		pathrelse(search_path);
		return retval;
@@ -2061,9 +2063,11 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th,
			       "reiserquota insert_item(): allocating %u id=%u type=%c",
			       quota_bytes, inode->i_uid, head2type(ih));
#endif
		reiserfs_write_unlock(inode->i_sb);
		/* We can't dirty inode here. It would be immediately written but
		 * appropriate stat item isn't inserted yet... */
		retval = dquot_alloc_space_nodirty(inode, quota_bytes);
		reiserfs_write_lock(inode->i_sb);
		if (retval) {
			pathrelse(path);
			return retval;
+14 −4
Original line number Diff line number Diff line
@@ -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.
@@ -2108,7 +2110,9 @@ 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));
@@ -2130,7 +2134,9 @@ 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));
@@ -2150,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;
}

@@ -2187,7 +2195,9 @@ 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;