]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] Ext3+quota deadlock fix
authorAndrew Morton <akpm@osdl.org>
Mon, 29 Dec 2003 13:51:19 +0000 (05:51 -0800)
committerLinus Torvalds <torvalds@home.osdl.org>
Mon, 29 Dec 2003 13:51:19 +0000 (05:51 -0800)
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).

fs/dquot.c
fs/ext3/super.c
include/linux/quota.h

index 2e4d1f9e3fe617a580c4ad0f1a095ddd1095d6a6..b2108080c841855f41a412b17b071815e81b25c0 100644 (file)
@@ -344,7 +344,7 @@ restart:
                atomic_inc(&dquot->dq_count);
                dqstats.lookups++;
                spin_unlock(&dq_list_lock);
-               sb->dq_op->sync_dquot(dquot);
+               sb->dq_op->write_dquot(dquot);
                dqput(dquot);
                goto restart;
        }
@@ -432,7 +432,7 @@ we_slept:
        }
        if (dquot_dirty(dquot)) {
                spin_unlock(&dq_list_lock);
-               commit_dqblk(dquot);
+               dquot->dq_sb->dq_op->write_dquot(dquot);
                goto we_slept;
        }
        atomic_dec(&dquot->dq_count);
@@ -1088,7 +1088,7 @@ struct dquot_operations dquot_operations = {
        .free_space     = dquot_free_space,
        .free_inode     = dquot_free_inode,
        .transfer       = dquot_transfer,
-       .sync_dquot     = commit_dqblk
+       .write_dquot    = commit_dqblk
 };
 
 /* 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)
        error = -EINVAL;
        if (!fmt->qf_ops->check_quota_file(sb, type))
                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);
-       inode->i_flags |= S_NOQUOTA;
+       inode->i_flags |= S_NOQUOTA | S_NOATIME;
 
        dqopt->ops[type] = fmt->qf_ops;
        dqopt->info[type].dqi_format = fmt;
index d92187197f68e7e0dde1523d8c2cbb2106b0b3a8..e2b4a68ccd1a69daa4c1bd11028ec8ad0ff9cd96 100644 (file)
@@ -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 */
 #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 ret;
@@ -1979,7 +1979,7 @@ static int ext3_sync_dquot(struct dquot *dquot)
                ret = PTR_ERR(handle);
                goto out;
        }
-       ret = old_sync_dquot(dquot);
+       ret = old_write_dquot(dquot);
        err = ext3_journal_stop(handle);
        if (ret == 0)
                ret = err;
@@ -2012,8 +2012,8 @@ static int __init init_ext3_fs(void)
                goto out1;
 #ifdef CONFIG_QUOTA
        init_dquot_operations(&ext3_qops);
-       old_sync_dquot = ext3_qops.sync_dquot;
-       ext3_qops.sync_dquot = ext3_sync_dquot;
+       old_write_dquot = ext3_qops.write_dquot;
+       ext3_qops.write_dquot = ext3_write_dquot;
 #endif
         err = register_filesystem(&ext3_fs_type);
        if (err)
index 447b5e192a7469274cc8c9fb0e83c348eebc49d6..2f65eb56738463ea91b69beb699b6b5e27b0dfa2 100644 (file)
@@ -250,7 +250,7 @@ struct dquot_operations {
        void (*free_space) (struct inode *, qsize_t);
        void (*free_inode) (const struct inode *, unsigned long);
        int (*transfer) (struct inode *, struct iattr *);
-       int (*sync_dquot) (struct dquot *);
+       int (*write_dquot) (struct dquot *);
 };
 
 /* Operations handling requests from userspace */