4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 021110-1307, USA
24 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
26 * Copyright (c) 2012, 2017, Intel Corporation.
28 * Code originally extracted from quota directory
32 #include <lustre_osc.h>
34 #include "osc_internal.h"
36 static inline struct osc_quota_info *osc_oqi_alloc(u32 id)
38 struct osc_quota_info *oqi;
40 OBD_SLAB_ALLOC_PTR(oqi, osc_quota_kmem);
47 int osc_quota_chkdq(struct client_obd *cli, const unsigned int qid[])
52 for (type = 0; type < LL_MAXQUOTAS; type++) {
53 struct osc_quota_info *oqi;
55 oqi = cfs_hash_lookup(cli->cl_quota_hash[type], &qid[type]);
57 /* do not try to access oqi here, it could have been
58 * freed by osc_quota_setdq() */
60 /* the slot is busy, the user is about to run out of
61 * quota space on this OST */
62 CDEBUG(D_QUOTA, "chkdq found noquota for %s %d\n",
63 type == USRQUOTA ? "user" : "grout", qid[type]);
71 static inline u32 md_quota_flag(int qtype)
75 return OBD_MD_FLUSRQUOTA;
77 return OBD_MD_FLGRPQUOTA;
79 return OBD_MD_FLPRJQUOTA;
85 static inline u32 fl_quota_flag(int qtype)
89 return OBD_FL_NO_USRQUOTA;
91 return OBD_FL_NO_GRPQUOTA;
93 return OBD_FL_NO_PRJQUOTA;
99 int osc_quota_setdq(struct client_obd *cli, __u64 xid, const unsigned int qid[],
100 u64 valid, u32 flags)
107 if ((valid & (OBD_MD_FLALLQUOTA)) == 0)
110 mutex_lock(&cli->cl_quota_mutex);
111 cli->cl_root_squash = !!(flags & OBD_FL_ROOT_SQUASH);
112 cli->cl_root_prjquota = !!(flags & OBD_FL_ROOT_PRJQUOTA);
113 /* still mark the quots is running out for the old request, because it
114 * could be processed after the new request at OST, the side effect is
115 * the following request will be processed synchronously, but it will
116 * not break the quota enforcement. */
117 if (cli->cl_quota_last_xid > xid && !(flags & OBD_FL_NO_QUOTA_ALL))
118 GOTO(out_unlock, rc);
120 if (cli->cl_quota_last_xid < xid)
121 cli->cl_quota_last_xid = xid;
123 for (type = 0; type < LL_MAXQUOTAS; type++) {
124 struct osc_quota_info *oqi;
126 if ((valid & md_quota_flag(type)) == 0)
129 /* lookup the ID in the per-type hash table */
130 oqi = cfs_hash_lookup(cli->cl_quota_hash[type], &qid[type]);
131 if ((flags & fl_quota_flag(type)) != 0) {
132 /* This ID is getting close to its quota limit, let's
133 * switch to sync I/O */
137 oqi = osc_oqi_alloc(qid[type]);
143 rc = cfs_hash_add_unique(cli->cl_quota_hash[type],
144 &qid[type], &oqi->oqi_hash);
145 /* race with others? */
146 if (rc == -EALREADY) {
148 OBD_SLAB_FREE_PTR(oqi, osc_quota_kmem);
151 CDEBUG(D_QUOTA, "%s: setdq to insert for %s %d (%d)\n",
152 cli_name(cli), qtype_name(type), qid[type], rc);
154 /* This ID is now off the hook, let's remove it from
159 oqi = cfs_hash_del_key(cli->cl_quota_hash[type],
162 OBD_SLAB_FREE_PTR(oqi, osc_quota_kmem);
164 CDEBUG(D_QUOTA, "%s: setdq to remove for %s %d (%p)\n",
165 cli_name(cli), qtype_name(type), qid[type], oqi);
170 mutex_unlock(&cli->cl_quota_mutex);
175 * Hash operations for uid/gid <-> osc_quota_info
178 oqi_hashfn(struct cfs_hash *hs, const void *key, unsigned mask)
180 return cfs_hash_32(*((__u32 *)key), 0) & mask;
184 oqi_keycmp(const void *key, struct hlist_node *hnode)
186 struct osc_quota_info *oqi;
189 LASSERT(key != NULL);
191 oqi = hlist_entry(hnode, struct osc_quota_info, oqi_hash);
193 return uid == oqi->oqi_id;
197 oqi_key(struct hlist_node *hnode)
199 struct osc_quota_info *oqi;
200 oqi = hlist_entry(hnode, struct osc_quota_info, oqi_hash);
205 oqi_object(struct hlist_node *hnode)
207 return hlist_entry(hnode, struct osc_quota_info, oqi_hash);
211 oqi_get(struct cfs_hash *hs, struct hlist_node *hnode)
216 oqi_put_locked(struct cfs_hash *hs, struct hlist_node *hnode)
221 oqi_exit(struct cfs_hash *hs, struct hlist_node *hnode)
223 struct osc_quota_info *oqi;
225 oqi = hlist_entry(hnode, struct osc_quota_info, oqi_hash);
227 OBD_SLAB_FREE_PTR(oqi, osc_quota_kmem);
230 #define HASH_QUOTA_BKT_BITS 5
231 #define HASH_QUOTA_CUR_BITS 5
232 #define HASH_QUOTA_MAX_BITS 15
234 static struct cfs_hash_ops quota_hash_ops = {
235 .hs_hash = oqi_hashfn,
236 .hs_keycmp = oqi_keycmp,
238 .hs_object = oqi_object,
240 .hs_put_locked = oqi_put_locked,
244 int osc_quota_setup(struct obd_device *obd)
246 struct client_obd *cli = &obd->u.cli;
250 mutex_init(&cli->cl_quota_mutex);
252 for (type = 0; type < LL_MAXQUOTAS; type++) {
253 cli->cl_quota_hash[type] = cfs_hash_create("QUOTA_HASH",
262 if (cli->cl_quota_hash[type] == NULL)
266 if (type == LL_MAXQUOTAS)
269 for (i = 0; i < type; i++)
270 cfs_hash_putref(cli->cl_quota_hash[i]);
275 int osc_quota_cleanup(struct obd_device *obd)
277 struct client_obd *cli = &obd->u.cli;
281 for (type = 0; type < LL_MAXQUOTAS; type++)
282 cfs_hash_putref(cli->cl_quota_hash[type]);
287 int osc_quotactl(struct obd_device *unused, struct obd_export *exp,
288 struct obd_quotactl *oqctl)
290 struct ptlrpc_request *req;
291 struct obd_quotactl *oqc;
295 req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp),
296 &RQF_OST_QUOTACTL, LUSTRE_OST_VERSION,
301 oqc = req_capsule_client_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
304 ptlrpc_request_set_replen(req);
305 ptlrpc_at_set_req_timeout(req);
306 req->rq_no_resend = 1;
308 rc = ptlrpc_queue_wait(req);
310 CERROR("ptlrpc_queue_wait failed, rc: %d\n", rc);
312 if (req->rq_repmsg &&
313 (oqc = req_capsule_server_get(&req->rq_pill, &RMF_OBD_QUOTACTL))) {
316 CERROR ("Can't unpack obd_quotactl\n");
319 ptlrpc_req_finished(req);