quota: Do not dirty bad dquots
[sfrench/cifs-2.6.git] / fs / quota / dquot.c
index 562f5978488ff1d944affa6d381799eddf5ba578..0393581fe1a3aefa2851862b4fbd189ec4c389b9 100644 (file)
@@ -339,6 +339,9 @@ int dquot_mark_dquot_dirty(struct dquot *dquot)
 {
        int ret = 1;
 
+       if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags))
+               return 0;
+
        /* If quota is dirty already, we don't have to acquire dq_list_lock */
        if (test_bit(DQ_MOD_B, &dquot->dq_flags))
                return 1;
@@ -389,7 +392,9 @@ static inline int clear_dquot_dirty(struct dquot *dquot)
 
 void mark_info_dirty(struct super_block *sb, int type)
 {
-       set_bit(DQF_INFO_DIRTY_B, &sb_dqopt(sb)->info[type].dqi_flags);
+       spin_lock(&dq_data_lock);
+       sb_dqopt(sb)->info[type].dqi_flags |= DQF_INFO_DIRTY;
+       spin_unlock(&dq_data_lock);
 }
 EXPORT_SYMBOL(mark_info_dirty);
 
@@ -415,10 +420,8 @@ int dquot_acquire(struct dquot *dquot)
                ret = dqopt->ops[dquot->dq_id.type]->commit_dqblk(dquot);
                /* Write the info if needed */
                if (info_dirty(&dqopt->info[dquot->dq_id.type])) {
-                       down_write(&dqopt->dqio_sem);
                        ret2 = dqopt->ops[dquot->dq_id.type]->write_file_info(
                                        dquot->dq_sb, dquot->dq_id.type);
-                       up_write(&dqopt->dqio_sem);
                }
                if (ret < 0)
                        goto out_iolock;
@@ -478,7 +481,6 @@ int dquot_release(struct dquot *dquot)
        /* Check whether we are not racing with some other dqget() */
        if (atomic_read(&dquot->dq_count) > 1)
                goto out_dqlock;
-       down_write(&dqopt->dqio_sem);
        if (dqopt->ops[dquot->dq_id.type]->release_dqblk) {
                ret = dqopt->ops[dquot->dq_id.type]->release_dqblk(dquot);
                /* Write the info */
@@ -490,7 +492,6 @@ int dquot_release(struct dquot *dquot)
                        ret = ret2;
        }
        clear_bit(DQ_ACTIVE_B, &dquot->dq_flags);
-       up_write(&dqopt->dqio_sem);
 out_dqlock:
        mutex_unlock(&dquot->dq_lock);
        return ret;
@@ -626,11 +627,9 @@ int dquot_writeback_dquots(struct super_block *sb, int type)
                while (!list_empty(dirty)) {
                        dquot = list_first_entry(dirty, struct dquot,
                                                 dq_dirty);
-                       /* Dirty and inactive can be only bad dquot... */
-                       if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) {
-                               clear_dquot_dirty(dquot);
-                               continue;
-                       }
+
+                       WARN_ON(!test_bit(DQ_ACTIVE_B, &dquot->dq_flags));
+
                        /* Now we have active dquot from which someone is
                         * holding reference so we can safely just increase
                         * use count */
@@ -761,7 +760,7 @@ we_slept:
                return;
        }
        /* Need to release dquot? */
-       if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && dquot_dirty(dquot)) {
+       if (dquot_dirty(dquot)) {
                spin_unlock(&dq_list_lock);
                /* Commit dquot before releasing */
                ret = dquot->dq_sb->dq_op->write_dquot(dquot);
@@ -779,8 +778,6 @@ we_slept:
                }
                goto we_slept;
        }
-       /* Clear flag in case dquot was inactive (something bad happened) */
-       clear_dquot_dirty(dquot);
        if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) {
                spin_unlock(&dq_list_lock);
                dquot->dq_sb->dq_op->release_dquot(dquot);
@@ -2054,29 +2051,21 @@ EXPORT_SYMBOL(dquot_transfer);
  */
 int dquot_commit_info(struct super_block *sb, int type)
 {
-       int ret;
        struct quota_info *dqopt = sb_dqopt(sb);
 
-       down_write(&dqopt->dqio_sem);
-       ret = dqopt->ops[type]->write_file_info(sb, type);
-       up_write(&dqopt->dqio_sem);
-       return ret;
+       return dqopt->ops[type]->write_file_info(sb, type);
 }
 EXPORT_SYMBOL(dquot_commit_info);
 
 int dquot_get_next_id(struct super_block *sb, struct kqid *qid)
 {
        struct quota_info *dqopt = sb_dqopt(sb);
-       int err;
 
        if (!sb_has_quota_active(sb, qid->type))
                return -ESRCH;
        if (!dqopt->ops[qid->type]->get_next_id)
                return -ENOSYS;
-       down_read(&dqopt->dqio_sem);
-       err = dqopt->ops[qid->type]->get_next_id(sb, qid);
-       up_read(&dqopt->dqio_sem);
-       return err;
+       return dqopt->ops[qid->type]->get_next_id(sb, qid);
 }
 EXPORT_SYMBOL(dquot_get_next_id);
 
@@ -2325,15 +2314,14 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
        dqopt->info[type].dqi_format = fmt;
        dqopt->info[type].dqi_fmt_id = format_id;
        INIT_LIST_HEAD(&dqopt->info[type].dqi_dirty_list);
-       down_read(&dqopt->dqio_sem);
        error = dqopt->ops[type]->read_file_info(sb, type);
-       if (error < 0) {
-               up_read(&dqopt->dqio_sem);
+       if (error < 0)
                goto out_file_init;
-       }
-       if (dqopt->flags & DQUOT_QUOTA_SYS_FILE)
+       if (dqopt->flags & DQUOT_QUOTA_SYS_FILE) {
+               spin_lock(&dq_data_lock);
                dqopt->info[type].dqi_flags |= DQF_SYS_FILE;
-       up_read(&dqopt->dqio_sem);
+               spin_unlock(&dq_data_lock);
+       }
        spin_lock(&dq_state_lock);
        dqopt->flags |= dquot_state_flag(flags, type);
        spin_unlock(&dq_state_lock);