1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include "../include/obd_class.h"
27#include "osc_internal.h"
28
29static inline struct osc_quota_info *osc_oqi_alloc(u32 id)
30{
31 struct osc_quota_info *oqi;
32
33 oqi = kmem_cache_zalloc(osc_quota_kmem, GFP_NOFS);
34 if (oqi)
35 oqi->oqi_id = id;
36
37 return oqi;
38}
39
40int osc_quota_chkdq(struct client_obd *cli, const unsigned int qid[])
41{
42 int type;
43
44 for (type = 0; type < MAXQUOTAS; type++) {
45 struct osc_quota_info *oqi;
46
47 oqi = cfs_hash_lookup(cli->cl_quota_hash[type], &qid[type]);
48 if (oqi) {
49
50
51
52
53
54
55
56 CDEBUG(D_QUOTA, "chkdq found noquota for %s %d\n",
57 type == USRQUOTA ? "user" : "grout", qid[type]);
58 return NO_QUOTA;
59 }
60 }
61
62 return QUOTA_OK;
63}
64
65#define MD_QUOTA_FLAG(type) ((type == USRQUOTA) ? OBD_MD_FLUSRQUOTA \
66 : OBD_MD_FLGRPQUOTA)
67#define FL_QUOTA_FLAG(type) ((type == USRQUOTA) ? OBD_FL_NO_USRQUOTA \
68 : OBD_FL_NO_GRPQUOTA)
69
70int osc_quota_setdq(struct client_obd *cli, const unsigned int qid[],
71 u32 valid, u32 flags)
72{
73 int type;
74 int rc = 0;
75
76 if ((valid & (OBD_MD_FLUSRQUOTA | OBD_MD_FLGRPQUOTA)) == 0)
77 return 0;
78
79 for (type = 0; type < MAXQUOTAS; type++) {
80 struct osc_quota_info *oqi;
81
82 if ((valid & MD_QUOTA_FLAG(type)) == 0)
83 continue;
84
85
86 oqi = cfs_hash_lookup(cli->cl_quota_hash[type], &qid[type]);
87 if ((flags & FL_QUOTA_FLAG(type)) != 0) {
88
89
90
91 if (oqi)
92 continue;
93
94 oqi = osc_oqi_alloc(qid[type]);
95 if (!oqi) {
96 rc = -ENOMEM;
97 break;
98 }
99
100 rc = cfs_hash_add_unique(cli->cl_quota_hash[type],
101 &qid[type], &oqi->oqi_hash);
102
103 if (rc == -EALREADY) {
104 rc = 0;
105 kmem_cache_free(osc_quota_kmem, oqi);
106 }
107
108 CDEBUG(D_QUOTA, "%s: setdq to insert for %s %d (%d)\n",
109 cli->cl_import->imp_obd->obd_name,
110 type == USRQUOTA ? "user" : "group",
111 qid[type], rc);
112 } else {
113
114
115
116 if (!oqi)
117 continue;
118
119 oqi = cfs_hash_del_key(cli->cl_quota_hash[type],
120 &qid[type]);
121 if (oqi)
122 kmem_cache_free(osc_quota_kmem, oqi);
123
124 CDEBUG(D_QUOTA, "%s: setdq to remove for %s %d (%p)\n",
125 cli->cl_import->imp_obd->obd_name,
126 type == USRQUOTA ? "user" : "group",
127 qid[type], oqi);
128 }
129 }
130
131 return rc;
132}
133
134
135
136
137static unsigned
138oqi_hashfn(struct cfs_hash *hs, const void *key, unsigned mask)
139{
140 return cfs_hash_u32_hash(*((__u32 *)key), mask);
141}
142
143static int
144oqi_keycmp(const void *key, struct hlist_node *hnode)
145{
146 struct osc_quota_info *oqi;
147 u32 uid;
148
149 LASSERT(key);
150 uid = *((u32 *)key);
151 oqi = hlist_entry(hnode, struct osc_quota_info, oqi_hash);
152
153 return uid == oqi->oqi_id;
154}
155
156static void *
157oqi_key(struct hlist_node *hnode)
158{
159 struct osc_quota_info *oqi;
160
161 oqi = hlist_entry(hnode, struct osc_quota_info, oqi_hash);
162 return &oqi->oqi_id;
163}
164
165static void *
166oqi_object(struct hlist_node *hnode)
167{
168 return hlist_entry(hnode, struct osc_quota_info, oqi_hash);
169}
170
171static void
172oqi_get(struct cfs_hash *hs, struct hlist_node *hnode)
173{
174}
175
176static void
177oqi_put_locked(struct cfs_hash *hs, struct hlist_node *hnode)
178{
179}
180
181static void
182oqi_exit(struct cfs_hash *hs, struct hlist_node *hnode)
183{
184 struct osc_quota_info *oqi;
185
186 oqi = hlist_entry(hnode, struct osc_quota_info, oqi_hash);
187
188 kmem_cache_free(osc_quota_kmem, oqi);
189}
190
191#define HASH_QUOTA_BKT_BITS 5
192#define HASH_QUOTA_CUR_BITS 5
193#define HASH_QUOTA_MAX_BITS 15
194
195static struct cfs_hash_ops quota_hash_ops = {
196 .hs_hash = oqi_hashfn,
197 .hs_keycmp = oqi_keycmp,
198 .hs_key = oqi_key,
199 .hs_object = oqi_object,
200 .hs_get = oqi_get,
201 .hs_put_locked = oqi_put_locked,
202 .hs_exit = oqi_exit,
203};
204
205int osc_quota_setup(struct obd_device *obd)
206{
207 struct client_obd *cli = &obd->u.cli;
208 int i, type;
209
210 for (type = 0; type < MAXQUOTAS; type++) {
211 cli->cl_quota_hash[type] = cfs_hash_create("QUOTA_HASH",
212 HASH_QUOTA_CUR_BITS,
213 HASH_QUOTA_MAX_BITS,
214 HASH_QUOTA_BKT_BITS,
215 0,
216 CFS_HASH_MIN_THETA,
217 CFS_HASH_MAX_THETA,
218 "a_hash_ops,
219 CFS_HASH_DEFAULT);
220 if (!cli->cl_quota_hash[type])
221 break;
222 }
223
224 if (type == MAXQUOTAS)
225 return 0;
226
227 for (i = 0; i < type; i++)
228 cfs_hash_putref(cli->cl_quota_hash[i]);
229
230 return -ENOMEM;
231}
232
233int osc_quota_cleanup(struct obd_device *obd)
234{
235 struct client_obd *cli = &obd->u.cli;
236 int type;
237
238 for (type = 0; type < MAXQUOTAS; type++)
239 cfs_hash_putref(cli->cl_quota_hash[type]);
240
241 return 0;
242}
243
244int osc_quotactl(struct obd_device *unused, struct obd_export *exp,
245 struct obd_quotactl *oqctl)
246{
247 struct ptlrpc_request *req;
248 struct obd_quotactl *oqc;
249 int rc;
250
251 req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp),
252 &RQF_OST_QUOTACTL, LUSTRE_OST_VERSION,
253 OST_QUOTACTL);
254 if (!req)
255 return -ENOMEM;
256
257 oqc = req_capsule_client_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
258 *oqc = *oqctl;
259
260 ptlrpc_request_set_replen(req);
261 ptlrpc_at_set_req_timeout(req);
262 req->rq_no_resend = 1;
263
264 rc = ptlrpc_queue_wait(req);
265 if (rc)
266 CERROR("ptlrpc_queue_wait failed, rc: %d\n", rc);
267
268 if (req->rq_repmsg) {
269 oqc = req_capsule_server_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
270 if (oqc) {
271 *oqctl = *oqc;
272 } else if (!rc) {
273 CERROR("Can't unpack obd_quotactl\n");
274 rc = -EPROTO;
275 }
276 } else if (!rc) {
277 CERROR("Can't unpack obd_quotactl\n");
278 rc = -EPROTO;
279 }
280 ptlrpc_req_finished(req);
281
282 return rc;
283}
284
285int osc_quotacheck(struct obd_device *unused, struct obd_export *exp,
286 struct obd_quotactl *oqctl)
287{
288 struct client_obd *cli = &exp->exp_obd->u.cli;
289 struct ptlrpc_request *req;
290 struct obd_quotactl *body;
291 int rc;
292
293 req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp),
294 &RQF_OST_QUOTACHECK, LUSTRE_OST_VERSION,
295 OST_QUOTACHECK);
296 if (!req)
297 return -ENOMEM;
298
299 body = req_capsule_client_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
300 *body = *oqctl;
301
302 ptlrpc_request_set_replen(req);
303
304
305
306 cli->cl_qchk_stat = -ENODATA;
307 rc = ptlrpc_queue_wait(req);
308 if (rc)
309 cli->cl_qchk_stat = rc;
310 ptlrpc_req_finished(req);
311 return rc;
312}
313
314int osc_quota_poll_check(struct obd_export *exp, struct if_quotacheck *qchk)
315{
316 struct client_obd *cli = &exp->exp_obd->u.cli;
317 int rc;
318
319 qchk->obd_uuid = cli->cl_target_uuid;
320 memcpy(qchk->obd_type, LUSTRE_OST_NAME, strlen(LUSTRE_OST_NAME));
321
322 rc = cli->cl_qchk_stat;
323
324 if (rc == CL_NOT_QUOTACHECKED)
325 rc = -EINTR;
326 return rc;
327}
328