Whamcloud - gitweb
LU-12616 obclass: fix MDS start/stop race
[fs/lustre-release.git] / lustre / osc / osc_quota.c
index 1e14457..a0aaae7 100644 (file)
 /*
  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  *
- * Copyright (c) 2012, 2013, Intel Corporation.
+ * Copyright (c) 2012, 2017, Intel Corporation.
  *
  * Code originally extracted from quota directory
  */
 
 #include <obd.h>
+#include <lustre_osc.h>
+
 #include "osc_internal.h"
 
 static inline struct osc_quota_info *osc_oqi_alloc(u32 id)
@@ -47,7 +49,7 @@ int osc_quota_chkdq(struct client_obd *cli, const unsigned int qid[])
        int type;
        ENTRY;
 
-       for (type = 0; type < MAXQUOTAS; type++) {
+       for (type = 0; type < LL_MAXQUOTAS; type++) {
                struct osc_quota_info *oqi;
 
                oqi = cfs_hash_lookup(cli->cl_quota_hash[type], &qid[type]);
@@ -66,30 +68,65 @@ int osc_quota_chkdq(struct client_obd *cli, const unsigned int qid[])
        RETURN(QUOTA_OK);
 }
 
-#define MD_QUOTA_FLAG(type) ((type == USRQUOTA) ? OBD_MD_FLUSRQUOTA \
-                                               : OBD_MD_FLGRPQUOTA)
-#define FL_QUOTA_FLAG(type) ((type == USRQUOTA) ? OBD_FL_NO_USRQUOTA \
-                                               : OBD_FL_NO_GRPQUOTA)
+static inline u32 md_quota_flag(int qtype)
+{
+       switch (qtype) {
+       case USRQUOTA:
+               return OBD_MD_FLUSRQUOTA;
+       case GRPQUOTA:
+               return OBD_MD_FLGRPQUOTA;
+       case PRJQUOTA:
+               return OBD_MD_FLPRJQUOTA;
+       default:
+               return 0;
+       }
+}
+
+static inline u32 fl_quota_flag(int qtype)
+{
+       switch (qtype) {
+       case USRQUOTA:
+               return OBD_FL_NO_USRQUOTA;
+       case GRPQUOTA:
+               return OBD_FL_NO_GRPQUOTA;
+       case PRJQUOTA:
+               return OBD_FL_NO_PRJQUOTA;
+       default:
+               return 0;
+       }
+}
 
-int osc_quota_setdq(struct client_obd *cli, const unsigned int qid[],
+int osc_quota_setdq(struct client_obd *cli, __u64 xid, const unsigned int qid[],
                    u64 valid, u32 flags)
 {
        int type;
        int rc = 0;
+
         ENTRY;
 
-       if ((valid & (OBD_MD_FLUSRQUOTA | OBD_MD_FLGRPQUOTA)) == 0)
+       if ((valid & (OBD_MD_FLALLQUOTA)) == 0)
                RETURN(0);
 
-       for (type = 0; type < MAXQUOTAS; type++) {
+       mutex_lock(&cli->cl_quota_mutex);
+       /* still mark the quots is running out for the old request, because it
+        * could be processed after the new request at OST, the side effect is
+        * the following request will be processed synchronously, but it will
+        * not break the quota enforcement. */
+       if (cli->cl_quota_last_xid > xid && !(flags & OBD_FL_NO_QUOTA_ALL))
+               GOTO(out_unlock, rc);
+
+       if (cli->cl_quota_last_xid < xid)
+               cli->cl_quota_last_xid = xid;
+
+       for (type = 0; type < LL_MAXQUOTAS; type++) {
                struct osc_quota_info *oqi;
 
-               if ((valid & MD_QUOTA_FLAG(type)) == 0)
+               if ((valid & md_quota_flag(type)) == 0)
                        continue;
 
                /* lookup the ID in the per-type hash table */
                oqi = cfs_hash_lookup(cli->cl_quota_hash[type], &qid[type]);
-               if ((flags & FL_QUOTA_FLAG(type)) != 0) {
+               if ((flags & fl_quota_flag(type)) != 0) {
                        /* This ID is getting close to its quota limit, let's
                         * switch to sync I/O */
                        if (oqi != NULL)
@@ -110,9 +147,7 @@ int osc_quota_setdq(struct client_obd *cli, const unsigned int qid[],
                        }
 
                        CDEBUG(D_QUOTA, "%s: setdq to insert for %s %d (%d)\n",
-                              cli->cl_import->imp_obd->obd_name,
-                              type == USRQUOTA ? "user" : "group",
-                              qid[type], rc);
+                              cli_name(cli), qtype_name(type), qid[type], rc);
                } else {
                        /* This ID is now off the hook, let's remove it from
                         * the hash table */
@@ -125,12 +160,12 @@ int osc_quota_setdq(struct client_obd *cli, const unsigned int qid[],
                                OBD_SLAB_FREE_PTR(oqi, osc_quota_kmem);
 
                        CDEBUG(D_QUOTA, "%s: setdq to remove for %s %d (%p)\n",
-                              cli->cl_import->imp_obd->obd_name,
-                              type == USRQUOTA ? "user" : "group",
-                              qid[type], oqi);
+                              cli_name(cli), qtype_name(type), qid[type], oqi);
                }
        }
 
+out_unlock:
+       mutex_unlock(&cli->cl_quota_mutex);
        RETURN(rc);
 }
 
@@ -210,7 +245,9 @@ int osc_quota_setup(struct obd_device *obd)
        int i, type;
        ENTRY;
 
-       for (type = 0; type < MAXQUOTAS; type++) {
+       mutex_init(&cli->cl_quota_mutex);
+
+       for (type = 0; type < LL_MAXQUOTAS; type++) {
                cli->cl_quota_hash[type] = cfs_hash_create("QUOTA_HASH",
                                                           HASH_QUOTA_CUR_BITS,
                                                           HASH_QUOTA_MAX_BITS,
@@ -224,7 +261,7 @@ int osc_quota_setup(struct obd_device *obd)
                        break;
        }
 
-       if (type == MAXQUOTAS)
+       if (type == LL_MAXQUOTAS)
                RETURN(0);
 
        for (i = 0; i < type; i++)
@@ -239,7 +276,7 @@ int osc_quota_cleanup(struct obd_device *obd)
        int type;
        ENTRY;
 
-       for (type = 0; type < MAXQUOTAS; type++)
+       for (type = 0; type < LL_MAXQUOTAS; type++)
                cfs_hash_putref(cli->cl_quota_hash[type]);
 
        RETURN(0);