Commit 844ef7b9 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] Fix deadlock in journalled quota

From: Jan Kara <jack@ucw.cz>

Attached patch should fix reported deadlock in journalled quota code.
quotactl() call was violating the locking rules and didn't start transaction
when it should.

From: <raven@themaw.net>

  Found a couple of symbols not exported that were needed by the ext3.ko
  module.
parent 74499d32
......@@ -529,7 +529,7 @@ static void dqput(struct dquot *dquot)
clear_dquot_dirty(dquot);
if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) {
spin_unlock(&dq_list_lock);
dquot_release(dquot);
dquot->dq_sb->dq_op->release_dquot(dquot);
goto we_slept;
}
atomic_dec(&dquot->dq_count);
......@@ -605,7 +605,7 @@ static struct dquot *dqget(struct super_block *sb, unsigned int id, int type)
* finished or it will be canceled due to dq_count > 1 test */
wait_on_dquot(dquot);
/* Read the dquot and instantiate it (everything done only if needed) */
if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && dquot_acquire(dquot) < 0) {
if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && sb->dq_op->acquire_dquot(dquot) < 0) {
dqput(dquot);
return NODQUOT;
}
......@@ -1259,6 +1259,8 @@ struct dquot_operations dquot_operations = {
.free_inode = dquot_free_inode,
.transfer = dquot_transfer,
.write_dquot = dquot_commit,
.acquire_dquot = dquot_acquire,
.release_dquot = dquot_release,
.mark_dirty = dquot_mark_dquot_dirty,
.write_info = dquot_commit_info
};
......@@ -1760,6 +1762,8 @@ EXPORT_SYMBOL(vfs_get_dqblk);
EXPORT_SYMBOL(vfs_set_dqblk);
EXPORT_SYMBOL(dquot_commit);
EXPORT_SYMBOL(dquot_commit_info);
EXPORT_SYMBOL(dquot_acquire);
EXPORT_SYMBOL(dquot_release);
EXPORT_SYMBOL(dquot_mark_dquot_dirty);
EXPORT_SYMBOL(dquot_initialize);
EXPORT_SYMBOL(dquot_drop);
......
......@@ -521,6 +521,8 @@ static void ext3_clear_inode(struct inode *inode)
static int ext3_dquot_initialize(struct inode *inode, int type);
static int ext3_dquot_drop(struct inode *inode);
static int ext3_write_dquot(struct dquot *dquot);
static int ext3_acquire_dquot(struct dquot *dquot);
static int ext3_release_dquot(struct dquot *dquot);
static int ext3_mark_dquot_dirty(struct dquot *dquot);
static int ext3_write_info(struct super_block *sb, int type);
static int ext3_quota_on(struct super_block *sb, int type, int format_id, char *path);
......@@ -536,6 +538,8 @@ static struct dquot_operations ext3_quota_operations = {
.free_inode = dquot_free_inode,
.transfer = dquot_transfer,
.write_dquot = ext3_write_dquot,
.acquire_dquot = ext3_acquire_dquot,
.release_dquot = ext3_release_dquot,
.mark_dirty = ext3_mark_dquot_dirty,
.write_info = ext3_write_info
};
......@@ -2181,6 +2185,38 @@ static int ext3_write_dquot(struct dquot *dquot)
return ret;
}
static int ext3_acquire_dquot(struct dquot *dquot)
{
int ret, err;
handle_t *handle;
handle = ext3_journal_start(dquot_to_inode(dquot),
EXT3_QUOTA_INIT_BLOCKS);
if (IS_ERR(handle))
return PTR_ERR(handle);
ret = dquot_acquire(dquot);
err = ext3_journal_stop(handle);
if (!ret)
ret = err;
return ret;
}
static int ext3_release_dquot(struct dquot *dquot)
{
int ret, err;
handle_t *handle;
handle = ext3_journal_start(dquot_to_inode(dquot),
EXT3_QUOTA_INIT_BLOCKS);
if (IS_ERR(handle))
return PTR_ERR(handle);
ret = dquot_release(dquot);
err = ext3_journal_stop(handle);
if (!ret)
ret = err;
return ret;
}
static int ext3_mark_dquot_dirty(struct dquot *dquot)
{
/* Are we journalling quotas? */
......
......@@ -250,6 +250,8 @@ struct dquot_operations {
int (*free_inode) (const struct inode *, unsigned long);
int (*transfer) (struct inode *, struct iattr *);
int (*write_dquot) (struct dquot *); /* Ordinary dquot write */
int (*acquire_dquot) (struct dquot *); /* Quota is going to be created on disk */
int (*release_dquot) (struct dquot *); /* Quota is going to be deleted from disk */
int (*mark_dirty) (struct dquot *); /* Dquot is marked dirty */
int (*write_info) (struct super_block *, int); /* Write of quota "superblock" */
};
......
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