Whamcloud - gitweb
LU-17662 osd-zfs: Support for ZFS 2.2.3
[fs/lustre-release.git] / lustre / osc / osc_quota.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
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.
9  *
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).
15  *
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
20  *
21  * GPL HEADER END
22  */
23 /*
24  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
25  *
26  * Copyright (c) 2012, 2017, Intel Corporation.
27  *
28  * Code originally extracted from quota directory
29  */
30
31 #include <obd_class.h>
32 #include <lustre_osc.h>
33 #include <lustre_quota.h>
34
35 #include "osc_internal.h"
36
37 int osc_quota_chkdq(struct client_obd *cli, const unsigned int qid[])
38 {
39         int type;
40
41         ENTRY;
42         for (type = 0; type < LL_MAXQUOTAS; type++) {
43                 u8 *qtype;
44
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
49                          */
50                         CDEBUG(D_QUOTA, "chkdq found noquota for %s %d\n",
51                                qtype_name(type), qid[type]);
52                         RETURN(-EDQUOT);
53                 }
54         }
55
56         RETURN(0);
57 }
58
59 static inline u32 md_quota_flag(int qtype)
60 {
61         switch (qtype) {
62         case USRQUOTA:
63                 return OBD_MD_FLUSRQUOTA;
64         case GRPQUOTA:
65                 return OBD_MD_FLGRPQUOTA;
66         case PRJQUOTA:
67                 return OBD_MD_FLPRJQUOTA;
68         default:
69                 return 0;
70         }
71 }
72
73 static inline u32 fl_quota_flag(int qtype)
74 {
75         switch (qtype) {
76         case USRQUOTA:
77                 return OBD_FL_NO_USRQUOTA;
78         case GRPQUOTA:
79                 return OBD_FL_NO_GRPQUOTA;
80         case PRJQUOTA:
81                 return OBD_FL_NO_PRJQUOTA;
82         default:
83                 return 0;
84         }
85 }
86
87 int osc_quota_setdq(struct client_obd *cli, u64 xid, const unsigned int qid[],
88                     u64 valid, u32 flags)
89 {
90         int type;
91         int rc = 0;
92
93         ENTRY;
94         if ((valid & (OBD_MD_FLALLQUOTA)) == 0)
95                 RETURN(0);
96
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);
106
107         if (cli->cl_quota_last_xid < xid)
108                 cli->cl_quota_last_xid = xid;
109
110         for (type = 0; type < LL_MAXQUOTAS; type++) {
111                 unsigned long bits = 0;
112                 u8 *qtypes;
113
114                 if ((valid & md_quota_flag(type)) == 0)
115                         continue;
116
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
121                          * switch to sync I/O
122                          */
123                         if (qtypes) { /* ID already cached */
124                                 bits = xa_to_value(qtypes);
125                                 /* test if ID type already set */
126                                 if (!(bits & BIT(type))) {
127                                         bits |= BIT(type);
128                                         rc = xa_err(xa_store(&cli->cl_quota_exceeded_ids,
129                                                              qid[type],
130                                                              xa_mk_value(bits),
131                                                              GFP_KERNEL));
132                                         if (rc < 0)
133                                                 GOTO(out_unlock, rc);
134                                 }
135                                 continue;
136                         }
137
138                         /* Only insert if we see the this ID for the
139                          * very first time.
140                          */
141                         bits |= BIT(type);
142                         rc = ll_xa_insert(&cli->cl_quota_exceeded_ids,
143                                           qid[type], xa_mk_value(bits),
144                                           GFP_KERNEL);
145                         if (rc == -ENOMEM)
146                                 break;
147
148                         CDEBUG(D_QUOTA, "%s: setdq to insert for %s %d: rc = %d\n",
149                                cli_name(cli), qtype_name(type), qid[type], rc);
150                 } else {
151                         /* This ID is now off the hook, let's remove it from
152                          * the xarray
153                          */
154                         if (!qtypes)
155                                 continue;
156
157                         bits = xa_to_value(qtypes);
158                         if (!(bits & BIT(type)))
159                                 continue;
160
161                         bits &= ~BIT(type);
162                         if (bits) {
163                                 rc = xa_err(xa_store(&cli->cl_quota_exceeded_ids,
164                                                      qid[type],
165                                                      xa_mk_value(bits),
166                                                      GFP_KERNEL));
167                                 if (rc < 0)
168                                         GOTO(out_unlock, rc);
169                         } else {
170                                 xa_erase(&cli->cl_quota_exceeded_ids, qid[type]);
171                         }
172
173                         CDEBUG(D_QUOTA, "%s: setdq to remove for %s %d\n",
174                                cli_name(cli), qtype_name(type), qid[type]);
175                 }
176         }
177
178 out_unlock:
179         mutex_unlock(&cli->cl_quota_mutex);
180         RETURN(rc);
181 }
182
183 int osc_quota_setup(struct obd_device *obd)
184 {
185         struct client_obd *cli = &obd->u.cli;
186
187         mutex_init(&cli->cl_quota_mutex);
188
189         xa_init(&cli->cl_quota_exceeded_ids);
190
191         return 0;
192 }
193
194 void osc_quota_cleanup(struct obd_device *obd)
195 {
196         struct client_obd *cli = &obd->u.cli;
197         unsigned long qid;
198         u8 *qtypes;
199
200         xa_for_each(&cli->cl_quota_exceeded_ids, qid, qtypes)
201                 xa_erase(&cli->cl_quota_exceeded_ids, qid);
202
203         xa_destroy(&cli->cl_quota_exceeded_ids);
204 }
205
206 int osc_quotactl(struct obd_device *unused, struct obd_export *exp,
207                  struct obd_quotactl *oqctl)
208 {
209         struct ptlrpc_request   *req;
210         struct obd_quotactl     *oqc;
211         int                      rc;
212
213         ENTRY;
214
215         req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp),
216                                         &RQF_OST_QUOTACTL, LUSTRE_OST_VERSION,
217                                         OST_QUOTACTL);
218         if (req == NULL)
219                 RETURN(-ENOMEM);
220
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);
224         else
225                 req_capsule_set_size(&req->rq_pill, &RMF_OBD_QUOTA_ITER,
226                                      RCL_SERVER, 0);
227
228         oqc = req_capsule_client_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
229         *oqc = *oqctl;
230
231         ptlrpc_request_set_replen(req);
232         ptlrpc_at_set_req_timeout(req);
233         req->rq_no_resend = 1;
234
235         rc = ptlrpc_queue_wait(req);
236         if (rc)
237                 CERROR("ptlrpc_queue_wait failed, rc: %d\n", rc);
238
239         if (req->rq_repmsg) {
240                 struct list_head *lst = (struct list_head *)oqctl->qc_iter_list;
241
242                 oqc = req_capsule_server_get(&req->rq_pill, &RMF_OBD_QUOTACTL);
243                 if (!oqc)
244                         GOTO(out, rc = -EPROTO);
245
246                 *oqctl = *oqc;
247
248                 if (oqctl->qc_cmd == LUSTRE_Q_ITEROQUOTA) {
249                         void *buffer;
250                         struct lquota_iter *iter;
251
252                         buffer = req_capsule_server_get(&req->rq_pill,
253                                                         &RMF_OBD_QUOTA_ITER);
254
255                         if (buffer == NULL) {
256                                 CDEBUG(D_QUOTA, "%s: no buffer in iter req\n",
257                                        exp->exp_obd->obd_name);
258
259                                 rc = -EPROTO;
260                                 GOTO(out, rc);
261                         }
262
263                         OBD_ALLOC_LARGE(iter,
264                                sizeof(struct lquota_iter) + LQUOTA_ITER_BUFLEN);
265                         if (iter == NULL)
266                                 GOTO(out, rc = -ENOMEM);
267
268                         INIT_LIST_HEAD(&iter->li_link);
269                         list_add(&iter->li_link, lst);
270
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;
275                 }
276         } else if (!rc) {
277                 CERROR("%s: cannot unpack obd_quotactl: rc = %d\n",
278                        exp->exp_obd->obd_name, rc);
279
280                 rc = -EPROTO;
281         }
282
283 out:
284         ptlrpc_req_finished(req);
285
286         RETURN(rc);
287 }