Whamcloud - gitweb
LU-17504 build: fix gcc-13 [-Werror=stringop-overread] error
[fs/lustre-release.git] / lustre / quota / qmt_lock.c
index 9935897..d847529 100644 (file)
@@ -31,6 +31,7 @@
 #define DEBUG_SUBSYSTEM S_LQUOTA
 
 #include <linux/kthread.h>
+#include <linux/workqueue.h>
 
 #include <lustre_dlm.h>
 #include <lustre_swab.h>
@@ -38,6 +39,8 @@
 
 #include "qmt_internal.h"
 
+struct workqueue_struct *qmt_lvbo_free_wq;
+
 /* intent policy function called from mdt_intent_opc() when the intent is of
  * quota type */
 int qmt_intent_policy(const struct lu_env *env, struct lu_device *ld,
@@ -271,48 +274,71 @@ out:
  */
 static bool qmt_clear_lgeg_arr_nu(struct lquota_entry *lqe, int stype, int idx)
 {
-       unsigned long least_qunit = lqe2qpi(lqe)->qpi_least_qunit;
-       struct lqe_glbl_data *lgd = lqe->lqe_glbl_data;
+       unsigned long least = lqe2qpi(lqe)->qpi_least_qunit;
+       bool revoke = false;
 
        /* There is no array to store lge for the case of DOM.
-        * Ignore it until MDT pools will be ready. */
+        * Ignore it until MDT pools will be ready.
+        */
        if (!qmt_dom(lqe_rtype(lqe), stype)) {
-               lqe->lqe_glbl_data->lqeg_arr[idx].lge_qunit_nu = 0;
-               lqe->lqe_glbl_data->lqeg_arr[idx].lge_edquot_nu = 0;
+               struct lqe_glbl_data *lgd;
+
+               mutex_lock(&lqe->lqe_glbl_data_lock);
+               lgd = lqe->lqe_glbl_data;
+               if (lgd) {
+                       int lge_idx = qmt_map_lge_idx(lgd, idx);
 
-               /* We shouldn't call revoke for DOM case, it will be updated
-                * at qmt_id_lock_glimpse. */
-               return (lgd->lqeg_arr[idx].lge_qunit == least_qunit);
+                       lgd->lqeg_arr[lge_idx].lge_qunit_nu = 0;
+                       lgd->lqeg_arr[lge_idx].lge_edquot_nu = 0;
+                       /* We shouldn't call revoke for DOM case, it will be
+                        * updated at qmt_id_lock_glimpse.
+                        */
+                       revoke = lgd->lqeg_arr[lge_idx].lge_qunit == least;
+               }
+               mutex_unlock(&lqe->lqe_glbl_data_lock);
        }
 
-       return false;
+       return revoke;
 }
 
-static bool qmt_set_revoke(struct lu_env *env, struct lquota_entry *lqe,
+static bool qmt_set_revoke(struct lu_env *env, struct lquota_entry *lqe_gl,
                          int stype, int idx)
 {
-       unsigned long least_qunit = lqe2qpi(lqe)->qpi_least_qunit;
-       struct lqe_glbl_data *lgd = lqe->lqe_glbl_data;
+       unsigned long least_qunit = lqe2qpi(lqe_gl)->qpi_least_qunit;
        bool notify = false;
 
-       if (lgd->lqeg_arr[idx].lge_qunit == least_qunit) {
-               int i;
-
-               qti_lqes_write_lock(env);
-               for (i = 0; i < qti_lqes_cnt(env); i++) {
-                       LQUOTA_DEBUG(qti_lqes(env)[i],
-                                    "idx %d lge_qunit %llu least_qunit %lu\n",
-                                    idx, lgd->lqeg_arr[idx].lge_qunit,
-                                    least_qunit);
-                       if (qti_lqes(env)[i]->lqe_qunit == least_qunit) {
-                               qti_lqes(env)[i]->lqe_revoke_time =
+       if (qmt_dom(lqe_rtype(lqe_gl), stype))
+               return false;
+
+       qti_lqes_write_lock(env);
+       mutex_lock(&lqe_gl->lqe_glbl_data_lock);
+       if (lqe_gl->lqe_glbl_data) {
+               struct lqe_glbl_data *lgd = lqe_gl->lqe_glbl_data;
+               int lge_idx;
+
+               lge_idx = qmt_map_lge_idx(lgd, idx);
+               if (lgd->lqeg_arr[lge_idx].lge_qunit == least_qunit) {
+                       struct lquota_entry *lqe;
+                       int i;
+
+                       for (i = 0; i < qti_lqes_cnt(env); i++) {
+                               lqe = qti_lqes(env)[i];
+                               LQUOTA_DEBUG(lqe,
+                                            "lge_qunit %llu least_qunit %lu idx %d\n",
+                                            lgd->lqeg_arr[lge_idx].lge_qunit,
+                                            least_qunit, idx);
+                               if (lqe->lqe_qunit == least_qunit) {
+                                       lqe->lqe_revoke_time =
                                                        ktime_get_seconds();
-                               notify |= qmt_adjust_edquot(qti_lqes(env)[i],
+                                       notify |= qmt_adjust_edquot(lqe,
                                                  ktime_get_real_seconds());
+                               }
                        }
                }
-               qti_lqes_write_unlock(env);
        }
+       mutex_unlock(&lqe_gl->lqe_glbl_data_lock);
+       qti_lqes_write_unlock(env);
+
        return notify;
 }
 
@@ -403,12 +429,16 @@ int qmt_lvbo_update(struct lu_device *ld, struct ldlm_resource *res,
                GOTO(out_exp, rc);
 
        if (need_revoke && qmt_set_revoke(env, lqe, stype, idx)) {
+               int notify = false;
+
                mutex_lock(&lqe->lqe_glbl_data_lock);
                if (lqe->lqe_glbl_data) {
                        qmt_seed_glbe_edquot(env, lqe->lqe_glbl_data);
-                       qmt_id_lock_notify(qmt, lqe);
+                       notify = true;
                }
                mutex_unlock(&lqe->lqe_glbl_data_lock);
+               if (notify)
+                       qmt_id_lock_notify(qmt, lqe);
        }
 
        if (lvb->lvb_id_rel) {
@@ -523,16 +553,8 @@ int qmt_lvbo_free(struct lu_device *ld, struct ldlm_resource *res)
 
        if (res->lr_name.name[LUSTRE_RES_ID_QUOTA_SEQ_OFF] != 0) {
                struct lquota_entry *lqe = res->lr_lvb_data;
-               struct lqe_glbl_data *lgd;
-
-               mutex_lock(&lqe->lqe_glbl_data_lock);
-               lgd = lqe->lqe_glbl_data;
-               lqe->lqe_glbl_data = NULL;
-               mutex_unlock(&lqe->lqe_glbl_data_lock);
-               qmt_free_lqe_gd(lgd);
 
-               /* release lqe reference */
-               lqe_putref(lqe);
+               queue_work(qmt_lvbo_free_wq, &lqe->lqe_work);
        } else {
                struct dt_object *obj = res->lr_lvb_data;
                /* release object reference */
@@ -652,12 +674,14 @@ static void qmt_setup_id_desc(struct ldlm_lock *lock, union ldlm_gl_desc *desc,
                qunit = lqe->lqe_qunit;
        } else {
                struct lqe_glbl_data *lgd;
+               int lge_idx;
 
                mutex_lock(&lqe->lqe_glbl_data_lock);
                lgd = lqe->lqe_glbl_data;
                if (lgd) {
-                       edquot = lgd->lqeg_arr[idx].lge_edquot;
-                       qunit = lgd->lqeg_arr[idx].lge_qunit;
+                       lge_idx = qmt_map_lge_idx(lgd, idx);
+                       edquot = lgd->lqeg_arr[lge_idx].lge_edquot;
+                       qunit = lgd->lqeg_arr[lge_idx].lge_qunit;
                } else {
                        edquot = lqe->lqe_edquot;
                        qunit = lqe->lqe_qunit;
@@ -824,6 +848,11 @@ void qmt_glb_lock_notify(const struct lu_env *env, struct lquota_entry *lqe,
                qti->qti_gl_desc.lquota_desc.gl_softlimit = lqe->lqe_softlimit;
                qti->qti_gl_desc.lquota_desc.gl_time = LQUOTA_GRACE_FLAG(0,
                                                        LQUOTA_FLAG_RESET);
+       } else if (lqe->lqe_granted > lqe->lqe_hardlimit) {
+               qti->qti_gl_desc.lquota_desc.gl_hardlimit = lqe->lqe_hardlimit;
+               qti->qti_gl_desc.lquota_desc.gl_softlimit = lqe->lqe_softlimit;
+               qti->qti_gl_desc.lquota_desc.gl_time = LQUOTA_GRACE_FLAG(0,
+                                                       LQUOTA_FLAG_REVOKE);
        } else {
                qti->qti_gl_desc.lquota_desc.gl_hardlimit = lqe->lqe_hardlimit;
                qti->qti_gl_desc.lquota_desc.gl_softlimit = lqe->lqe_softlimit;
@@ -853,20 +882,32 @@ void qmt_glb_lock_notify(const struct lu_env *env, struct lquota_entry *lqe,
  * broadcasting the new qunit value */
 static int qmt_id_lock_cb(struct ldlm_lock *lock, struct lquota_entry *lqe)
 {
-       struct obd_uuid *uuid = &(lock)->l_export->exp_client_uuid;
+       struct obd_uuid *uuid = &(lock)->l_export->exp_client_uuid;
        struct lqe_glbl_data *lgd = lqe->lqe_glbl_data;
        int idx;
        int stype = qmt_uuid2idx(uuid, &idx);
 
        LASSERT(stype == QMT_STYPE_OST || stype == QMT_STYPE_MDT);
 
+       CDEBUG(D_QUOTA, "stype %d rtype %d idx %d uuid %s\n",
+              stype, lqe_rtype(lqe), idx, uuid->uuid);
        /* Quota pools support only OSTs, despite MDTs also could be registered
         * as LQUOTA_RES_DT devices(DOM). */
        if (qmt_dom(lqe_rtype(lqe), stype))
                return 1;
-       else
-               return lgd ? lgd->lqeg_arr[idx].lge_edquot_nu ||
-                      lgd->lqeg_arr[idx].lge_qunit_nu : 0;
+
+       if (lgd) {
+               int lge_idx = qmt_map_lge_idx(lgd, idx);
+
+               CDEBUG(D_QUOTA,
+                      "tgt idx:%d lge_idx:%d edquot_nu:%d qunit_nu:%d\n",
+                      idx, lge_idx, lgd->lqeg_arr[lge_idx].lge_edquot_nu,
+                      lgd->lqeg_arr[lge_idx].lge_qunit_nu);
+               return lgd->lqeg_arr[lge_idx].lge_edquot_nu ||
+                      lgd->lqeg_arr[lge_idx].lge_qunit_nu;
+       }
+
+       return 0;
 }