Commit db84a820 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] Ext3+quota deadlock fix

From: Jan Kara <jack@ucw.cz>

here's patch which should fix deadlock with quotas+ext3 reported in 2.4
(the same problem existed in 2.6 but nobody found it).
parent b0d8c562
...@@ -344,7 +344,7 @@ static int vfs_quota_sync(struct super_block *sb, int type) ...@@ -344,7 +344,7 @@ static int vfs_quota_sync(struct super_block *sb, int type)
atomic_inc(&dquot->dq_count); atomic_inc(&dquot->dq_count);
dqstats.lookups++; dqstats.lookups++;
spin_unlock(&dq_list_lock); spin_unlock(&dq_list_lock);
sb->dq_op->sync_dquot(dquot); sb->dq_op->write_dquot(dquot);
dqput(dquot); dqput(dquot);
goto restart; goto restart;
} }
...@@ -432,7 +432,7 @@ static void dqput(struct dquot *dquot) ...@@ -432,7 +432,7 @@ static void dqput(struct dquot *dquot)
} }
if (dquot_dirty(dquot)) { if (dquot_dirty(dquot)) {
spin_unlock(&dq_list_lock); spin_unlock(&dq_list_lock);
commit_dqblk(dquot); dquot->dq_sb->dq_op->write_dquot(dquot);
goto we_slept; goto we_slept;
} }
atomic_dec(&dquot->dq_count); atomic_dec(&dquot->dq_count);
...@@ -1088,7 +1088,7 @@ struct dquot_operations dquot_operations = { ...@@ -1088,7 +1088,7 @@ struct dquot_operations dquot_operations = {
.free_space = dquot_free_space, .free_space = dquot_free_space,
.free_inode = dquot_free_inode, .free_inode = dquot_free_inode,
.transfer = dquot_transfer, .transfer = dquot_transfer,
.sync_dquot = commit_dqblk .write_dquot = commit_dqblk
}; };
/* Function used by filesystems for initializing the dquot_operations structure */ /* Function used by filesystems for initializing the dquot_operations structure */
...@@ -1212,9 +1212,9 @@ int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path) ...@@ -1212,9 +1212,9 @@ int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path)
error = -EINVAL; error = -EINVAL;
if (!fmt->qf_ops->check_quota_file(sb, type)) if (!fmt->qf_ops->check_quota_file(sb, type))
goto out_file_init; goto out_file_init;
/* We don't want quota on quota files */ /* We don't want quota and atime on quota files (deadlocks possible) */
dquot_drop_nolock(inode); dquot_drop_nolock(inode);
inode->i_flags |= S_NOQUOTA; inode->i_flags |= S_NOQUOTA | S_NOATIME;
dqopt->ops[type] = fmt->qf_ops; dqopt->ops[type] = fmt->qf_ops;
dqopt->info[type].dqi_format = fmt; dqopt->info[type].dqi_format = fmt;
......
...@@ -1952,9 +1952,9 @@ int ext3_statfs (struct super_block * sb, struct kstatfs * buf) ...@@ -1952,9 +1952,9 @@ int ext3_statfs (struct super_block * sb, struct kstatfs * buf)
/* Blocks: quota info + (4 pointer blocks + 1 entry block) * (3 indirect + 1 descriptor + 1 bitmap) + superblock */ /* Blocks: quota info + (4 pointer blocks + 1 entry block) * (3 indirect + 1 descriptor + 1 bitmap) + superblock */
#define EXT3_V0_QFMT_BLOCKS 27 #define EXT3_V0_QFMT_BLOCKS 27
static int (*old_sync_dquot)(struct dquot *dquot); static int (*old_write_dquot)(struct dquot *dquot);
static int ext3_sync_dquot(struct dquot *dquot) static int ext3_write_dquot(struct dquot *dquot)
{ {
int nblocks; int nblocks;
int ret; int ret;
...@@ -1979,7 +1979,7 @@ static int ext3_sync_dquot(struct dquot *dquot) ...@@ -1979,7 +1979,7 @@ static int ext3_sync_dquot(struct dquot *dquot)
ret = PTR_ERR(handle); ret = PTR_ERR(handle);
goto out; goto out;
} }
ret = old_sync_dquot(dquot); ret = old_write_dquot(dquot);
err = ext3_journal_stop(handle); err = ext3_journal_stop(handle);
if (ret == 0) if (ret == 0)
ret = err; ret = err;
...@@ -2012,8 +2012,8 @@ static int __init init_ext3_fs(void) ...@@ -2012,8 +2012,8 @@ static int __init init_ext3_fs(void)
goto out1; goto out1;
#ifdef CONFIG_QUOTA #ifdef CONFIG_QUOTA
init_dquot_operations(&ext3_qops); init_dquot_operations(&ext3_qops);
old_sync_dquot = ext3_qops.sync_dquot; old_write_dquot = ext3_qops.write_dquot;
ext3_qops.sync_dquot = ext3_sync_dquot; ext3_qops.write_dquot = ext3_write_dquot;
#endif #endif
err = register_filesystem(&ext3_fs_type); err = register_filesystem(&ext3_fs_type);
if (err) if (err)
......
...@@ -250,7 +250,7 @@ struct dquot_operations { ...@@ -250,7 +250,7 @@ struct dquot_operations {
void (*free_space) (struct inode *, qsize_t); void (*free_space) (struct inode *, qsize_t);
void (*free_inode) (const struct inode *, unsigned long); void (*free_inode) (const struct inode *, unsigned long);
int (*transfer) (struct inode *, struct iattr *); int (*transfer) (struct inode *, struct iattr *);
int (*sync_dquot) (struct dquot *); int (*write_dquot) (struct dquot *);
}; };
/* Operations handling requests from userspace */ /* Operations handling requests from userspace */
......
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