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
31 #include <obd_class.h>
32 #include <lustre_osc.h>
33 #include <lustre_quota.h>
35 #include "osc_internal.h"
37 int osc_quota_chkdq(struct client_obd *cli, const unsigned int qid[])
42 for (type = 0; type < LL_MAXQUOTAS; type++) {
45 qtype = xa_load(&cli->cl_quota_exceeded_ids, qid[type]);
46 if (qtype && (xa_to_value(qtype) & BIT(type))) {
47 /* the slot is busy, the user is about to run out of
48 * quota space on this OST
50 CDEBUG(D_QUOTA, "chkdq found noquota for %s %d\n",
51 qtype_name(type), qid[type]);
59 static inline u32 md_quota_flag(int qtype)
63 return OBD_MD_FLUSRQUOTA;
65 return OBD_MD_FLGRPQUOTA;
67 return OBD_MD_FLPRJQUOTA;
73 static inline u32 fl_quota_flag(int qtype)
77 return OBD_FL_NO_USRQUOTA;
79 return OBD_FL_NO_GRPQUOTA;
81 return OBD_FL_NO_PRJQUOTA;
87 int osc_quota_setdq(struct client_obd *cli, u64 xid, const unsigned int qid[],
94 if ((valid & (OBD_MD_FLALLQUOTA)) == 0)
97 mutex_lock(&cli->cl_quota_mutex);
98 cli->cl_root_squash = !!(flags & OBD_FL_ROOT_SQUASH);
99 cli->cl_root_prjquota = !!(flags & OBD_FL_ROOT_PRJQUOTA);
100 /* still mark the quots is running out for the old request, because it
101 * could be processed after the new request at OST, the side effect is
102 * the following request will be processed synchronously, but it will
103 * not break the quota enforcement. */
104 if (cli->cl_quota_last_xid > xid && !(flags & OBD_FL_NO_QUOTA_ALL))
105 GOTO(out_unlock, rc);
107 if (cli->cl_quota_last_xid < xid)
108 cli->cl_quota_last_xid = xid;
110 for (type = 0; type < LL_MAXQUOTAS; type++) {
111 unsigned long bits = 0;
114 if ((valid & md_quota_flag(type)) == 0)
117 /* lookup the quota IDs in the ID xarray */
118 qtypes = xa_load(&cli->cl_quota_exceeded_ids, qid[type]);
119 if ((flags & fl_quota_flag(type)) != 0) {
120 /* This ID is getting close to its quota limit, let's
123 if (qtypes) { /* ID already cached */
124 bits = xa_to_value(qtypes);
125 /* test if ID type already set */
126 if (!(bits & BIT(type))) {
128 rc = xa_err(xa_store(&cli->cl_quota_exceeded_ids,
133 GOTO(out_unlock, rc);
138 /* Only insert if we see the this ID for the
142 rc = ll_xa_insert(&cli->cl_quota_exceeded_ids,
143 qid[type], xa_mk_value(bits),
148 CDEBUG(D_QUOTA, "%s: setdq to insert for %s %d: rc = %d\n",
149 cli_name(cli), qtype_name(type), qid[type], rc);
151 /* This ID is now off the hook, let's remove it from
157 bits = xa_to_value(qtypes);
158 if (!(bits & BIT(type)))
163 rc = xa_err(xa_store(&cli->cl_quota_exceeded_ids,
168 GOTO(out_unlock, rc);
170 xa_erase(&cli->cl_quota_exceeded_ids, qid[type]);
173 CDEBUG(D_QUOTA, "%s: setdq to remove for %s %d\n",
174 cli_name(cli), qtype_name(type), qid[type]);
179 mutex_unlock(&cli->cl_quota_mutex);
183 int osc_quota_setup(struct obd_device *obd)
185 struct client_obd *cli = &obd->u.cli;
187 mutex_init(&cli->cl_quota_mutex);
189 xa_init(&cli->cl_quota_exceeded_ids);
194 void osc_quota_cleanup(struct obd_device *obd)
196 struct client_obd *cli = &obd->u.cli;
200 xa_for_each(&cli->cl_quota_exceeded_ids, qid, qtypes)
201 xa_erase(&cli->cl_quota_exceeded_ids, qid);
203 xa_destroy(&cli->cl_quota_exceeded_ids);
206 int osc_quotactl(struct obd_device *unused, struct obd_export *exp,
207 struct obd_quotactl *oqctl)
209 struct ptlrpc_request *req;
210 struct obd_quotactl *oqc;
215 req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp),
216 &RQF_OST_QUOTACTL, LUSTRE_OST_VERSION,
221 if (oqctl->qc_cmd == LUSTRE_Q_ITEROQUOTA)
222 req_capsule_set_size(&req->rq_pill, &RMF_OBD_QUOTA_ITER,
223 RCL_SERVER, LQUOTA_ITER_BUFLEN);
225 req_capsule_set_size(&req->rq_pill, &RMF_OBD_QUOTA_ITER,
228 oqc = req_capsule_client_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
231 ptlrpc_request_set_replen(req);
232 ptlrpc_at_set_req_timeout(req);
233 req->rq_no_resend = 1;
235 rc = ptlrpc_queue_wait(req);
237 CERROR("ptlrpc_queue_wait failed, rc: %d\n", rc);
239 if (req->rq_repmsg) {
240 struct list_head *lst = (struct list_head *)oqctl->qc_iter_list;
242 oqc = req_capsule_server_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
244 GOTO(out, rc = -EPROTO);
248 if (oqctl->qc_cmd == LUSTRE_Q_ITEROQUOTA) {
250 struct lquota_iter *iter;
252 buffer = req_capsule_server_get(&req->rq_pill,
253 &RMF_OBD_QUOTA_ITER);
255 if (buffer == NULL) {
256 CDEBUG(D_QUOTA, "%s: no buffer in iter req\n",
257 exp->exp_obd->obd_name);
263 OBD_ALLOC_LARGE(iter,
264 sizeof(struct lquota_iter) + LQUOTA_ITER_BUFLEN);
266 GOTO(out, rc = -ENOMEM);
268 INIT_LIST_HEAD(&iter->li_link);
269 list_add(&iter->li_link, lst);
271 memcpy(iter->li_buffer, buffer, LQUOTA_ITER_BUFLEN);
272 iter->li_dt_size = oqctl->qc_iter_dt_buflen;
273 oqctl->qc_iter_md_buflen = 0;
274 oqctl->qc_iter_dt_buflen = 0;
277 CERROR("%s: cannot unpack obd_quotactl: rc = %d\n",
278 exp->exp_obd->obd_name, rc);
284 ptlrpc_req_finished(req);