Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / staging / lustre / 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) 2011, 2012, Intel Corporation.
27  *
28  * Code originally extracted from quota directory
29  */
30
31 #include "../include/obd_class.h"
32 #include "osc_internal.h"
33
34 static inline struct osc_quota_info *osc_oqi_alloc(u32 id)
35 {
36         struct osc_quota_info *oqi;
37
38         OBD_SLAB_ALLOC_PTR(oqi, osc_quota_kmem);
39         if (oqi != NULL)
40                 oqi->oqi_id = id;
41
42         return oqi;
43 }
44
45 int osc_quota_chkdq(struct client_obd *cli, const unsigned int qid[])
46 {
47         int type;
48
49         for (type = 0; type < MAXQUOTAS; type++) {
50                 struct osc_quota_info *oqi;
51
52                 oqi = cfs_hash_lookup(cli->cl_quota_hash[type], &qid[type]);
53                 if (oqi) {
54                         /* do not try to access oqi here, it could have been
55                          * freed by osc_quota_setdq() */
56
57                         /* the slot is busy, the user is about to run out of
58                          * quota space on this OST */
59                         CDEBUG(D_QUOTA, "chkdq found noquota for %s %d\n",
60                                type == USRQUOTA ? "user" : "grout", qid[type]);
61                         return NO_QUOTA;
62                 }
63         }
64
65         return QUOTA_OK;
66 }
67
68 #define MD_QUOTA_FLAG(type) ((type == USRQUOTA) ? OBD_MD_FLUSRQUOTA \
69                                                 : OBD_MD_FLGRPQUOTA)
70 #define FL_QUOTA_FLAG(type) ((type == USRQUOTA) ? OBD_FL_NO_USRQUOTA \
71                                                 : OBD_FL_NO_GRPQUOTA)
72
73 int osc_quota_setdq(struct client_obd *cli, const unsigned int qid[],
74                     u32 valid, u32 flags)
75 {
76         int type;
77         int rc = 0;
78
79         if ((valid & (OBD_MD_FLUSRQUOTA | OBD_MD_FLGRPQUOTA)) == 0)
80                 return 0;
81
82         for (type = 0; type < MAXQUOTAS; type++) {
83                 struct osc_quota_info *oqi;
84
85                 if ((valid & MD_QUOTA_FLAG(type)) == 0)
86                         continue;
87
88                 /* lookup the ID in the per-type hash table */
89                 oqi = cfs_hash_lookup(cli->cl_quota_hash[type], &qid[type]);
90                 if ((flags & FL_QUOTA_FLAG(type)) != 0) {
91                         /* This ID is getting close to its quota limit, let's
92                          * switch to sync I/O */
93                         if (oqi != NULL)
94                                 continue;
95
96                         oqi = osc_oqi_alloc(qid[type]);
97                         if (oqi == NULL) {
98                                 rc = -ENOMEM;
99                                 break;
100                         }
101
102                         rc = cfs_hash_add_unique(cli->cl_quota_hash[type],
103                                                  &qid[type], &oqi->oqi_hash);
104                         /* race with others? */
105                         if (rc == -EALREADY) {
106                                 rc = 0;
107                                 OBD_SLAB_FREE_PTR(oqi, osc_quota_kmem);
108                         }
109
110                         CDEBUG(D_QUOTA, "%s: setdq to insert for %s %d (%d)\n",
111                                cli->cl_import->imp_obd->obd_name,
112                                type == USRQUOTA ? "user" : "group",
113                                qid[type], rc);
114                 } else {
115                         /* This ID is now off the hook, let's remove it from
116                          * the hash table */
117                         if (oqi == NULL)
118                                 continue;
119
120                         oqi = cfs_hash_del_key(cli->cl_quota_hash[type],
121                                                &qid[type]);
122                         if (oqi)
123                                 OBD_SLAB_FREE_PTR(oqi, osc_quota_kmem);
124
125                         CDEBUG(D_QUOTA, "%s: setdq to remove for %s %d (%p)\n",
126                                cli->cl_import->imp_obd->obd_name,
127                                type == USRQUOTA ? "user" : "group",
128                                qid[type], oqi);
129                 }
130         }
131
132         return rc;
133 }
134
135 /*
136  * Hash operations for uid/gid <-> osc_quota_info
137  */
138 static unsigned
139 oqi_hashfn(struct cfs_hash *hs, const void *key, unsigned mask)
140 {
141         return cfs_hash_u32_hash(*((__u32 *)key), mask);
142 }
143
144 static int
145 oqi_keycmp(const void *key, struct hlist_node *hnode)
146 {
147         struct osc_quota_info *oqi;
148         u32 uid;
149
150         LASSERT(key != NULL);
151         uid = *((u32 *)key);
152         oqi = hlist_entry(hnode, struct osc_quota_info, oqi_hash);
153
154         return uid == oqi->oqi_id;
155 }
156
157 static void *
158 oqi_key(struct hlist_node *hnode)
159 {
160         struct osc_quota_info *oqi;
161         oqi = hlist_entry(hnode, struct osc_quota_info, oqi_hash);
162         return &oqi->oqi_id;
163 }
164
165 static void *
166 oqi_object(struct hlist_node *hnode)
167 {
168         return hlist_entry(hnode, struct osc_quota_info, oqi_hash);
169 }
170
171 static void
172 oqi_get(struct cfs_hash *hs, struct hlist_node *hnode)
173 {
174 }
175
176 static void
177 oqi_put_locked(struct cfs_hash *hs, struct hlist_node *hnode)
178 {
179 }
180
181 static void
182 oqi_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         OBD_SLAB_FREE_PTR(oqi, osc_quota_kmem);
189 }
190
191 #define HASH_QUOTA_BKT_BITS 5
192 #define HASH_QUOTA_CUR_BITS 5
193 #define HASH_QUOTA_MAX_BITS 15
194
195 static cfs_hash_ops_t 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
205 int 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                                                            &quota_hash_ops,
219                                                            CFS_HASH_DEFAULT);
220                 if (cli->cl_quota_hash[type] == NULL)
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
233 int 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
244 int 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 == NULL)
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
285 int 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 == NULL)
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         /* the next poll will find -ENODATA, that means quotacheck is
305          * going on */
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
314 int 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         /* the client is not the previous one */
324         if (rc == CL_NOT_QUOTACHECKED)
325                 rc = -EINTR;
326         return rc;
327 }