Merge tag 'linux-kselftest-fixes-6.6-rc5' of git://git.kernel.org/pub/scm/linux/kerne...
[platform/kernel/linux-rpi.git] / fs / gfs2 / quota.c
index 21100fe..171b271 100644 (file)
@@ -130,7 +130,7 @@ static void gfs2_qd_dispose(struct gfs2_quota_data *qd)
 
        if (!gfs2_withdrawn(sdp)) {
                gfs2_assert_warn(sdp, !qd->qd_change);
-               gfs2_assert_warn(sdp, !qd->qd_slot_count);
+               gfs2_assert_warn(sdp, !qd->qd_slot_ref);
                gfs2_assert_warn(sdp, !qd->qd_bh_count);
        }
 
@@ -213,12 +213,7 @@ static u64 qd2index(struct gfs2_quota_data *qd)
 
 static u64 qd2offset(struct gfs2_quota_data *qd)
 {
-       u64 offset;
-
-       offset = qd2index(qd);
-       offset *= sizeof(struct gfs2_quota);
-
-       return offset;
+       return qd2index(qd) * sizeof(struct gfs2_quota);
 }
 
 static struct gfs2_quota_data *qd_alloc(unsigned hash, struct gfs2_sbd *sdp, struct kqid qid)
@@ -347,20 +342,19 @@ static int slot_get(struct gfs2_quota_data *qd)
        int error = 0;
 
        spin_lock(&sdp->sd_bitmap_lock);
-       if (qd->qd_slot_count != 0)
-               goto out;
-
-       error = -ENOSPC;
-       bit = find_first_zero_bit(sdp->sd_quota_bitmap, sdp->sd_quota_slots);
-       if (bit < sdp->sd_quota_slots) {
+       if (qd->qd_slot_ref == 0) {
+               bit = find_first_zero_bit(sdp->sd_quota_bitmap,
+                                         sdp->sd_quota_slots);
+               if (bit >= sdp->sd_quota_slots) {
+                       error = -ENOSPC;
+                       goto out;
+               }
                set_bit(bit, sdp->sd_quota_bitmap);
                qd->qd_slot = bit;
-               error = 0;
-out:
-               qd->qd_slot_count++;
        }
+       qd->qd_slot_ref++;
+out:
        spin_unlock(&sdp->sd_bitmap_lock);
-
        return error;
 }
 
@@ -369,8 +363,8 @@ static void slot_hold(struct gfs2_quota_data *qd)
        struct gfs2_sbd *sdp = qd->qd_sbd;
 
        spin_lock(&sdp->sd_bitmap_lock);
-       gfs2_assert(sdp, qd->qd_slot_count);
-       qd->qd_slot_count++;
+       gfs2_assert(sdp, qd->qd_slot_ref);
+       qd->qd_slot_ref++;
        spin_unlock(&sdp->sd_bitmap_lock);
 }
 
@@ -379,8 +373,8 @@ static void slot_put(struct gfs2_quota_data *qd)
        struct gfs2_sbd *sdp = qd->qd_sbd;
 
        spin_lock(&sdp->sd_bitmap_lock);
-       gfs2_assert(sdp, qd->qd_slot_count);
-       if (!--qd->qd_slot_count) {
+       gfs2_assert(sdp, qd->qd_slot_ref);
+       if (!--qd->qd_slot_ref) {
                BUG_ON(!test_and_clear_bit(qd->qd_slot, sdp->sd_quota_bitmap));
                qd->qd_slot = -1;
        }
@@ -473,6 +467,20 @@ static int qd_check_sync(struct gfs2_sbd *sdp, struct gfs2_quota_data *qd,
        return 1;
 }
 
+static int qd_bh_get_or_undo(struct gfs2_sbd *sdp, struct gfs2_quota_data *qd)
+{
+       int error;
+
+       error = bh_get(qd);
+       if (!error)
+               return 0;
+
+       clear_bit(QDF_LOCKED, &qd->qd_flags);
+       slot_put(qd);
+       qd_put(qd);
+       return error;
+}
+
 static int qd_fish(struct gfs2_sbd *sdp, struct gfs2_quota_data **qdp)
 {
        struct gfs2_quota_data *qd = NULL, *iter;
@@ -495,17 +503,12 @@ static int qd_fish(struct gfs2_sbd *sdp, struct gfs2_quota_data **qdp)
        spin_unlock(&qd_lock);
 
        if (qd) {
-               error = bh_get(qd);
-               if (error) {
-                       clear_bit(QDF_LOCKED, &qd->qd_flags);
-                       slot_put(qd);
-                       qd_put(qd);
+               error = qd_bh_get_or_undo(sdp, qd);
+               if (error)
                        return error;
-               }
+               *qdp = qd;
        }
 
-       *qdp = qd;
-
        return 0;
 }
 
@@ -859,7 +862,6 @@ static int gfs2_adjust_quota(struct gfs2_sbd *sdp, loff_t loc,
                return err;
 
        loc -= sizeof(q); /* gfs2_internal_read would've advanced the loc ptr */
-       err = -EIO;
        be64_add_cpu(&q.qu_value, change);
        if (((s64)be64_to_cpu(q.qu_value)) < 0)
                q.qu_value = 0; /* Never go negative on quota usage */
@@ -884,7 +886,7 @@ static int gfs2_adjust_quota(struct gfs2_sbd *sdp, loff_t loc,
                size = loc + sizeof(struct gfs2_quota);
                if (size > inode->i_size)
                        i_size_write(inode, size);
-               inode->i_mtime = inode->i_atime = current_time(inode);
+               inode->i_mtime = inode_set_ctime_current(inode);
                mark_inode_dirty(inode);
                set_bit(QDF_REFRESH, &qd->qd_flags);
        }
@@ -906,18 +908,12 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
        unsigned int nalloc = 0, blocks;
        int error;
 
-       error = gfs2_qa_get(ip);
-       if (error)
-               return error;
-
        gfs2_write_calc_reserv(ip, sizeof(struct gfs2_quota),
                              &data_blocks, &ind_blocks);
 
        ghs = kmalloc_array(num_qd, sizeof(struct gfs2_holder), GFP_NOFS);
-       if (!ghs) {
-               error = -ENOMEM;
-               goto out;
-       }
+       if (!ghs)
+               return -ENOMEM;
 
        sort(qda, num_qd, sizeof(struct gfs2_quota_data *), sort_qd, NULL);
        inode_lock(&ip->i_inode);
@@ -975,8 +971,6 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
                set_bit(QDF_REFRESH, &qd->qd_flags);
        }
 
-       error = 0;
-
 out_end_trans:
        gfs2_trans_end(sdp);
 out_ipres:
@@ -990,8 +984,10 @@ out_dq:
        kfree(ghs);
        gfs2_log_flush(ip->i_gl->gl_name.ln_sbd, ip->i_gl,
                       GFS2_LOG_HEAD_FLUSH_NORMAL | GFS2_LFC_DO_SYNC);
-out:
-       gfs2_qa_put(ip);
+       if (!error) {
+               for (x = 0; x < num_qd; x++)
+                       qda[x]->qd_sync_gen = sdp->sd_quota_sync_gen;
+       }
        return error;
 }
 
@@ -1074,7 +1070,7 @@ int gfs2_quota_lock(struct gfs2_inode *ip, kuid_t uid, kgid_t gid)
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
        struct gfs2_quota_data *qd;
        u32 x;
-       int error = 0;
+       int error;
 
        if (sdp->sd_args.ar_quota != GFS2_QUOTA_ON &&
            sdp->sd_args.ar_quota != GFS2_QUOTA_QUIET)
@@ -1143,7 +1139,7 @@ static bool need_sync(struct gfs2_quota_data *qd)
 void gfs2_quota_unlock(struct gfs2_inode *ip)
 {
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
-       struct gfs2_quota_data *qda[4];
+       struct gfs2_quota_data *qda[2 * GFS2_MAXQUOTAS];
        unsigned int count = 0;
        u32 x;
        int found;
@@ -1169,15 +1165,8 @@ void gfs2_quota_unlock(struct gfs2_inode *ip)
                if (!found)
                        continue;
 
-               gfs2_assert_warn(sdp, qd->qd_change_sync);
-               if (bh_get(qd)) {
-                       clear_bit(QDF_LOCKED, &qd->qd_flags);
-                       slot_put(qd);
-                       qd_put(qd);
-                       continue;
-               }
-
-               qda[count++] = qd;
+               if (!qd_bh_get_or_undo(sdp, qd))
+                       qda[count++] = qd;
        }
 
        if (count) {
@@ -1305,6 +1294,24 @@ void gfs2_quota_change(struct gfs2_inode *ip, s64 change,
        }
 }
 
+static bool qd_changed(struct gfs2_sbd *sdp)
+{
+       struct gfs2_quota_data *qd;
+       bool changed = false;
+
+       spin_lock(&qd_lock);
+       list_for_each_entry(qd, &sdp->sd_quota_list, qd_list) {
+               if (test_bit(QDF_LOCKED, &qd->qd_flags) ||
+                   !test_bit(QDF_CHANGE, &qd->qd_flags))
+                       continue;
+
+               changed = true;
+               break;
+       }
+       spin_unlock(&qd_lock);
+       return changed;
+}
+
 int gfs2_quota_sync(struct super_block *sb, int type)
 {
        struct gfs2_sbd *sdp = sb->s_fs_info;
@@ -1314,6 +1321,9 @@ int gfs2_quota_sync(struct super_block *sb, int type)
        unsigned int x;
        int error = 0;
 
+       if (!qd_changed(sdp))
+               return 0;
+
        qda = kcalloc(max_qd, sizeof(struct gfs2_quota_data *), GFP_KERNEL);
        if (!qda)
                return -ENOMEM;
@@ -1335,10 +1345,6 @@ int gfs2_quota_sync(struct super_block *sb, int type)
                if (num_qd) {
                        if (!error)
                                error = do_sync(num_qd, qda);
-                       if (!error)
-                               for (x = 0; x < num_qd; x++)
-                                       qda[x]->qd_sync_gen =
-                                               sdp->sd_quota_sync_gen;
 
                        for (x = 0; x < num_qd; x++)
                                qd_unlock(qda[x]);
@@ -1440,7 +1446,7 @@ int gfs2_quota_init(struct gfs2_sbd *sdp)
                        set_bit(QDF_CHANGE, &qd->qd_flags);
                        qd->qd_change = qc_change;
                        qd->qd_slot = slot;
-                       qd->qd_slot_count = 1;
+                       qd->qd_slot_ref = 1;
 
                        spin_lock(&qd_lock);
                        BUG_ON(test_and_set_bit(slot, sdp->sd_quota_bitmap));