quota: Do more fine-grained locking in dquot_acquire()
authorJan Kara <jack@suse.cz>
Thu, 8 Jun 2017 13:00:20 +0000 (15:00 +0200)
committerJan Kara <jack@suse.cz>
Thu, 17 Aug 2017 16:56:07 +0000 (18:56 +0200)
We need dqio_sem held just for reading when calling ->read_dqblk() in
dquot_acquire(). Also dqio_sem is not needed when setting DQ_READ_B and
DQ_ACTIVE_B as concurrent reads and dquot activations are serialized by
dq_lock. So acquire and release dqio_sem closer to the place where it is
needed. This reduces lock hold time and will make locking changes
easier.

Signed-off-by: Jan Kara <jack@suse.cz>
fs/quota/dquot.c

index 29d4475986422da1e1de6c5ac44ffb05c91d4432..21358f31923d86beac01110f5234b57957019178 100644 (file)
@@ -406,9 +406,11 @@ int dquot_acquire(struct dquot *dquot)
        struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
 
        mutex_lock(&dquot->dq_lock);
-       down_write(&dqopt->dqio_sem);
-       if (!test_bit(DQ_READ_B, &dquot->dq_flags))
+       if (!test_bit(DQ_READ_B, &dquot->dq_flags)) {
+               down_read(&dqopt->dqio_sem);
                ret = dqopt->ops[dquot->dq_id.type]->read_dqblk(dquot);
+               up_read(&dqopt->dqio_sem);
+       }
        if (ret < 0)
                goto out_iolock;
        /* Make sure flags update is visible after dquot has been filled */
@@ -416,12 +418,14 @@ int dquot_acquire(struct dquot *dquot)
        set_bit(DQ_READ_B, &dquot->dq_flags);
        /* Instantiate dquot if needed */
        if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && !dquot->dq_off) {
+               down_write(&dqopt->dqio_sem);
                ret = dqopt->ops[dquot->dq_id.type]->commit_dqblk(dquot);
                /* Write the info if needed */
                if (info_dirty(&dqopt->info[dquot->dq_id.type])) {
                        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;
                if (ret2 < 0) {
@@ -436,7 +440,6 @@ int dquot_acquire(struct dquot *dquot)
        smp_mb__before_atomic();
        set_bit(DQ_ACTIVE_B, &dquot->dq_flags);
 out_iolock:
-       up_write(&dqopt->dqio_sem);
        mutex_unlock(&dquot->dq_lock);
        return ret;
 }