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, Intel Corporation.
28 * Code originally extracted from quota directory
31 # include <liblustre.h>
35 #include "osc_internal.h"
37 static inline struct osc_quota_info *osc_oqi_alloc(obd_uid id)
39 struct osc_quota_info *oqi;
41 OBD_SLAB_ALLOC_PTR(oqi, osc_quota_kmem);
48 int osc_quota_chkdq(struct client_obd *cli, const unsigned int qid[])
53 for (type = 0; type < MAXQUOTAS; type++) {
54 struct osc_quota_info *oqi;
56 oqi = cfs_hash_lookup(cli->cl_quota_hash[type], &qid[type]);
58 obd_uid id = oqi->oqi_id;
60 LASSERTF(id == qid[type],
61 "The ids don't match %u != %u\n",
64 /* the slot is busy, the user is about to run out of
65 * quota space on this OST */
66 CDEBUG(D_QUOTA, "chkdq found noquota for %s %d\n",
67 type == USRQUOTA ? "user" : "grout", qid[type]);
75 #define MD_QUOTA_FLAG(type) ((type == USRQUOTA) ? OBD_MD_FLUSRQUOTA \
77 #define FL_QUOTA_FLAG(type) ((type == USRQUOTA) ? OBD_FL_NO_USRQUOTA \
80 int osc_quota_setdq(struct client_obd *cli, const unsigned int qid[],
81 obd_flag valid, obd_flag flags)
87 if ((valid & (OBD_MD_FLUSRQUOTA | OBD_MD_FLGRPQUOTA)) == 0)
90 for (type = 0; type < MAXQUOTAS; type++) {
91 struct osc_quota_info *oqi;
93 if ((valid & MD_QUOTA_FLAG(type)) == 0)
96 /* lookup the ID in the per-type hash table */
97 oqi = cfs_hash_lookup(cli->cl_quota_hash[type], &qid[type]);
98 if ((flags & FL_QUOTA_FLAG(type)) != 0) {
99 /* This ID is getting close to its quota limit, let's
100 * switch to sync I/O */
104 oqi = osc_oqi_alloc(qid[type]);
110 rc = cfs_hash_add_unique(cli->cl_quota_hash[type],
111 &qid[type], &oqi->oqi_hash);
112 /* race with others? */
113 if (rc == -EALREADY) {
115 OBD_SLAB_FREE_PTR(oqi, osc_quota_kmem);
118 CDEBUG(D_QUOTA, "%s: setdq to insert for %s %d (%d)\n",
119 cli->cl_import->imp_obd->obd_name,
120 type == USRQUOTA ? "user" : "group",
123 /* This ID is now off the hook, let's remove it from
128 oqi = cfs_hash_del_key(cli->cl_quota_hash[type],
131 OBD_SLAB_FREE_PTR(oqi, osc_quota_kmem);
133 CDEBUG(D_QUOTA, "%s: setdq to remove for %s %d (%p)\n",
134 cli->cl_import->imp_obd->obd_name,
135 type == USRQUOTA ? "user" : "group",
144 * Hash operations for uid/gid <-> osc_quota_info
147 oqi_hashfn(cfs_hash_t *hs, const void *key, unsigned mask)
149 return cfs_hash_u32_hash(*((__u32*)key), mask);
153 oqi_keycmp(const void *key, cfs_hlist_node_t *hnode)
155 struct osc_quota_info *oqi;
158 LASSERT(key != NULL);
159 uid = *((obd_uid*)key);
160 oqi = cfs_hlist_entry(hnode, struct osc_quota_info, oqi_hash);
162 return uid == oqi->oqi_id;
166 oqi_key(cfs_hlist_node_t *hnode)
168 struct osc_quota_info *oqi;
169 oqi = cfs_hlist_entry(hnode, struct osc_quota_info, oqi_hash);
174 oqi_object(cfs_hlist_node_t *hnode)
176 return cfs_hlist_entry(hnode, struct osc_quota_info, oqi_hash);
180 oqi_get(cfs_hash_t *hs, cfs_hlist_node_t *hnode)
185 oqi_put_locked(cfs_hash_t *hs, cfs_hlist_node_t *hnode)
190 oqi_exit(cfs_hash_t *hs, cfs_hlist_node_t *hnode)
192 struct osc_quota_info *oqi;
194 oqi = cfs_hlist_entry(hnode, struct osc_quota_info, oqi_hash);
196 OBD_SLAB_FREE_PTR(oqi, osc_quota_kmem);
199 #define HASH_QUOTA_BKT_BITS 5
200 #define HASH_QUOTA_CUR_BITS 5
201 #define HASH_QUOTA_MAX_BITS 15
203 static cfs_hash_ops_t quota_hash_ops = {
204 .hs_hash = oqi_hashfn,
205 .hs_keycmp = oqi_keycmp,
207 .hs_object = oqi_object,
209 .hs_put_locked = oqi_put_locked,
213 int osc_quota_setup(struct obd_device *obd)
215 struct client_obd *cli = &obd->u.cli;
219 for (type = 0; type < MAXQUOTAS; type++) {
220 cli->cl_quota_hash[type] = cfs_hash_create("QUOTA_HASH",
229 if (cli->cl_quota_hash[type] == NULL)
233 if (type == MAXQUOTAS)
236 for (i = 0; i < type; i++)
237 cfs_hash_putref(cli->cl_quota_hash[i]);
242 int osc_quota_cleanup(struct obd_device *obd)
244 struct client_obd *cli = &obd->u.cli;
248 for (type = 0; type < MAXQUOTAS; type++)
249 cfs_hash_putref(cli->cl_quota_hash[type]);
254 int osc_quotactl(struct obd_device *unused, struct obd_export *exp,
255 struct obd_quotactl *oqctl)
257 struct ptlrpc_request *req;
258 struct obd_quotactl *oqc;
262 req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp),
263 &RQF_OST_QUOTACTL, LUSTRE_OST_VERSION,
268 oqc = req_capsule_client_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
271 ptlrpc_request_set_replen(req);
272 ptlrpc_at_set_req_timeout(req);
273 req->rq_no_resend = 1;
275 rc = ptlrpc_queue_wait(req);
277 CERROR("ptlrpc_queue_wait failed, rc: %d\n", rc);
279 if (req->rq_repmsg &&
280 (oqc = req_capsule_server_get(&req->rq_pill, &RMF_OBD_QUOTACTL))) {
283 CERROR ("Can't unpack obd_quotactl\n");
286 ptlrpc_req_finished(req);
291 int osc_quotacheck(struct obd_device *unused, struct obd_export *exp,
292 struct obd_quotactl *oqctl)
294 struct client_obd *cli = &exp->exp_obd->u.cli;
295 struct ptlrpc_request *req;
296 struct obd_quotactl *body;
300 req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp),
301 &RQF_OST_QUOTACHECK, LUSTRE_OST_VERSION,
306 body = req_capsule_client_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
309 ptlrpc_request_set_replen(req);
311 /* the next poll will find -ENODATA, that means quotacheck is
313 cli->cl_qchk_stat = -ENODATA;
314 rc = ptlrpc_queue_wait(req);
316 cli->cl_qchk_stat = rc;
317 ptlrpc_req_finished(req);
321 int osc_quota_poll_check(struct obd_export *exp, struct if_quotacheck *qchk)
323 struct client_obd *cli = &exp->exp_obd->u.cli;
327 qchk->obd_uuid = cli->cl_target_uuid;
328 memcpy(qchk->obd_type, LUSTRE_OST_NAME, strlen(LUSTRE_OST_NAME));
330 rc = cli->cl_qchk_stat;
331 /* the client is not the previous one */
332 if (rc == CL_NOT_QUOTACHECKED)