From 77d9f4e05a5c366ad0f7c2e97a338c6958676f73 Mon Sep 17 00:00:00 2001 From: Hongchao Zhang Date: Tue, 22 Jan 2019 16:39:21 +0800 Subject: [PATCH] LU-11678 quota: protect quota flags at OSC 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 Reviewed-on: https://review.whamcloud.com/33747 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Wang Shilong Reviewed-by: Oleg Drokin --- lustre/include/obd.h | 3 +++ lustre/osc/osc_internal.h | 2 +- lustre/osc/osc_quota.c | 11 ++++++++++- lustre/osc/osc_request.c | 2 +- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/lustre/include/obd.h b/lustre/include/obd.h index f651de9..de51330 100644 --- a/lustre/include/obd.h +++ b/lustre/include/obd.h @@ -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; }; diff --git a/lustre/osc/osc_internal.h b/lustre/osc/osc_internal.h index fbb933f..6fea870 100644 --- a/lustre/osc/osc_internal.h +++ b/lustre/osc/osc_internal.h @@ -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, diff --git a/lustre/osc/osc_quota.c b/lustre/osc/osc_quota.c index 3325cf9..0a87e9c 100644 --- a/lustre/osc/osc_quota.c +++ b/lustre/osc/osc_quota.c @@ -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, diff --git a/lustre/osc/osc_request.c b/lustre/osc/osc_request.c index e1d0333..a5b1e2a 100644 --- a/lustre/osc/osc_request.c +++ b/lustre/osc/osc_request.c @@ -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); } -- 1.8.3.1