Whamcloud - gitweb
LU-11678 quota: protect quota flags at OSC 47/33747/3
authorHongchao Zhang <hongchao@whamcloud.com>
Tue, 22 Jan 2019 08:39:21 +0000 (16:39 +0800)
committerOleg Drokin <green@whamcloud.com>
Thu, 21 Mar 2019 03:43:07 +0000 (03:43 +0000)
There is no protection in OSC quota hash tracking the quota flags of
different qid, which could cause the previous request to modify the
quota flags which was set by the current request because the replies
could be out of order.

This patch also adds a lock to protect the operations on the quota
hash from different requests.

Test-Parameters: testlist=sanity-quota,sanity-quota,sanity-quota,sanity-quota

Change-Id: Ia6e5141265beacb9401dd533081fa0b85fd5ea6a
Signed-off-by: Hongchao Zhang <hongchao@whamcloud.com>
Reviewed-on: https://review.whamcloud.com/33747
Tested-by: Jenkins
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Wang Shilong <wshilong@ddn.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/include/obd.h
lustre/osc/osc_internal.h
lustre/osc/osc_quota.c
lustre/osc/osc_request.c

index f651de9..de51330 100644 (file)
@@ -346,8 +346,11 @@ struct client_obd {
        /* ptlrpc work for writeback in ptlrpcd context */
        void                    *cl_writeback_work;
        void                    *cl_lru_work;
+       struct mutex              cl_quota_mutex;
        /* hash tables for osc_quota_info */
        struct cfs_hash         *cl_quota_hash[LL_MAXQUOTAS];
+       /* the xid of the request updating the hash tables */
+       __u64                    cl_quota_last_xid;
        /* Links to the global list of registered changelog devices */
        struct list_head         cl_chg_dev_linkage;
 };
index fbb933f..6fea870 100644 (file)
@@ -148,7 +148,7 @@ struct osc_async_args {
 
 int osc_quota_setup(struct obd_device *obd);
 int osc_quota_cleanup(struct obd_device *obd);
-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 osc_quota_chkdq(struct client_obd *cli, const unsigned int qid[]);
 int osc_quotactl(struct obd_device *unused, struct obd_export *exp,
index 3325cf9..0a87e9c 100644 (file)
@@ -96,7 +96,7 @@ static inline u32 fl_quota_flag(int qtype)
        }
 }
 
-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;
@@ -107,6 +107,11 @@ int osc_quota_setdq(struct client_obd *cli, const unsigned int qid[],
        if ((valid & (OBD_MD_FLALLQUOTA)) == 0)
                RETURN(0);
 
+       mutex_lock(&cli->cl_quota_mutex);
+       if (cli->cl_quota_last_xid > xid)
+               GOTO(out_unlock, rc);
+
+       cli->cl_quota_last_xid = xid;
        for (type = 0; type < LL_MAXQUOTAS; type++) {
                struct osc_quota_info *oqi;
 
@@ -153,6 +158,8 @@ int osc_quota_setdq(struct client_obd *cli, const unsigned int qid[],
                }
        }
 
+out_unlock:
+       mutex_unlock(&cli->cl_quota_mutex);
        RETURN(rc);
 }
 
@@ -232,6 +239,8 @@ int osc_quota_setup(struct obd_device *obd)
        int i, type;
        ENTRY;
 
+       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,
index e1d0333..a5b1e2a 100644 (file)
@@ -1751,7 +1751,7 @@ static int osc_brw_fini_request(struct ptlrpc_request *req, int rc)
                CDEBUG(D_QUOTA, "setdq for [%u %u %u] with valid %#llx, flags %x\n",
                       body->oa.o_uid, body->oa.o_gid, body->oa.o_projid,
                       body->oa.o_valid, body->oa.o_flags);
-                      osc_quota_setdq(cli, qid, body->oa.o_valid,
+                      osc_quota_setdq(cli, req->rq_xid, qid, body->oa.o_valid,
                                       body->oa.o_flags);
         }