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).
19 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
21 * Copyright (c) 2011, 2015, Intel Corporation.
23 * Code originally extracted from quota directory
26 #include <obd_class.h>
27 #include "osc_internal.h"
29 static inline struct osc_quota_info *osc_oqi_alloc(u32 id)
31 struct osc_quota_info *oqi;
33 oqi = kmem_cache_zalloc(osc_quota_kmem, GFP_NOFS);
40 int osc_quota_chkdq(struct client_obd *cli, const unsigned int qid[])
44 for (type = 0; type < MAXQUOTAS; type++) {
45 struct osc_quota_info *oqi;
47 oqi = cfs_hash_lookup(cli->cl_quota_hash[type], &qid[type]);
49 /* do not try to access oqi here, it could have been
50 * freed by osc_quota_setdq()
53 /* the slot is busy, the user is about to run out of
54 * quota space on this OST
56 CDEBUG(D_QUOTA, "chkdq found noquota for %s %d\n",
57 type == USRQUOTA ? "user" : "grout", qid[type]);
65 #define MD_QUOTA_FLAG(type) ((type == USRQUOTA) ? OBD_MD_FLUSRQUOTA \
67 #define FL_QUOTA_FLAG(type) ((type == USRQUOTA) ? OBD_FL_NO_USRQUOTA \
70 int osc_quota_setdq(struct client_obd *cli, const unsigned int qid[],
76 if ((valid & (OBD_MD_FLUSRQUOTA | OBD_MD_FLGRPQUOTA)) == 0)
79 for (type = 0; type < MAXQUOTAS; type++) {
80 struct osc_quota_info *oqi;
82 if ((valid & MD_QUOTA_FLAG(type)) == 0)
85 /* lookup the ID in the per-type hash table */
86 oqi = cfs_hash_lookup(cli->cl_quota_hash[type], &qid[type]);
87 if ((flags & FL_QUOTA_FLAG(type)) != 0) {
88 /* This ID is getting close to its quota limit, let's
94 oqi = osc_oqi_alloc(qid[type]);
100 rc = cfs_hash_add_unique(cli->cl_quota_hash[type],
101 &qid[type], &oqi->oqi_hash);
102 /* race with others? */
103 if (rc == -EALREADY) {
105 kmem_cache_free(osc_quota_kmem, oqi);
108 CDEBUG(D_QUOTA, "%s: setdq to insert for %s %d (%d)\n",
110 type == USRQUOTA ? "user" : "group",
113 /* This ID is now off the hook, let's remove it from
119 oqi = cfs_hash_del_key(cli->cl_quota_hash[type],
122 kmem_cache_free(osc_quota_kmem, oqi);
124 CDEBUG(D_QUOTA, "%s: setdq to remove for %s %d (%p)\n",
126 type == USRQUOTA ? "user" : "group",
135 * Hash operations for uid/gid <-> osc_quota_info
138 oqi_hashfn(struct cfs_hash *hs, const void *key, unsigned int mask)
140 return cfs_hash_u32_hash(*((__u32 *)key), mask);
144 oqi_keycmp(const void *key, struct hlist_node *hnode)
146 struct osc_quota_info *oqi;
151 oqi = hlist_entry(hnode, struct osc_quota_info, oqi_hash);
153 return uid == oqi->oqi_id;
157 oqi_key(struct hlist_node *hnode)
159 struct osc_quota_info *oqi;
161 oqi = hlist_entry(hnode, struct osc_quota_info, oqi_hash);
166 oqi_object(struct hlist_node *hnode)
168 return hlist_entry(hnode, struct osc_quota_info, oqi_hash);
172 oqi_get(struct cfs_hash *hs, struct hlist_node *hnode)
177 oqi_put_locked(struct cfs_hash *hs, struct hlist_node *hnode)
182 oqi_exit(struct cfs_hash *hs, struct hlist_node *hnode)
184 struct osc_quota_info *oqi;
186 oqi = hlist_entry(hnode, struct osc_quota_info, oqi_hash);
188 kmem_cache_free(osc_quota_kmem, oqi);
191 #define HASH_QUOTA_BKT_BITS 5
192 #define HASH_QUOTA_CUR_BITS 5
193 #define HASH_QUOTA_MAX_BITS 15
195 static struct cfs_hash_ops quota_hash_ops = {
196 .hs_hash = oqi_hashfn,
197 .hs_keycmp = oqi_keycmp,
199 .hs_object = oqi_object,
201 .hs_put_locked = oqi_put_locked,
205 int osc_quota_setup(struct obd_device *obd)
207 struct client_obd *cli = &obd->u.cli;
210 for (type = 0; type < MAXQUOTAS; type++) {
211 cli->cl_quota_hash[type] = cfs_hash_create("QUOTA_HASH",
220 if (!cli->cl_quota_hash[type])
224 if (type == MAXQUOTAS)
227 for (i = 0; i < type; i++)
228 cfs_hash_putref(cli->cl_quota_hash[i]);
233 int osc_quota_cleanup(struct obd_device *obd)
235 struct client_obd *cli = &obd->u.cli;
238 for (type = 0; type < MAXQUOTAS; type++)
239 cfs_hash_putref(cli->cl_quota_hash[type]);
244 int osc_quotactl(struct obd_device *unused, struct obd_export *exp,
245 struct obd_quotactl *oqctl)
247 struct ptlrpc_request *req;
248 struct obd_quotactl *oqc;
251 req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp),
252 &RQF_OST_QUOTACTL, LUSTRE_OST_VERSION,
257 oqc = req_capsule_client_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
260 ptlrpc_request_set_replen(req);
261 ptlrpc_at_set_req_timeout(req);
262 req->rq_no_resend = 1;
264 rc = ptlrpc_queue_wait(req);
266 CERROR("ptlrpc_queue_wait failed, rc: %d\n", rc);
268 if (req->rq_repmsg) {
269 oqc = req_capsule_server_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
273 CERROR("Can't unpack obd_quotactl\n");
277 CERROR("Can't unpack obd_quotactl\n");
280 ptlrpc_req_finished(req);