Whamcloud - gitweb
LU-17744 ldiskfs: mballoc stats fixes
[fs/lustre-release.git] / lustre / ptlrpc / sec_null.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, see
18  * http://www.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright (c) 2011, 2014, Intel Corporation.
27  */
28 /*
29  * This file is part of Lustre, http://www.lustre.org/
30  * Lustre is a trademark of Sun Microsystems, Inc.
31  *
32  * lustre/ptlrpc/sec_null.c
33  *
34  * Author: Eric Mei <ericm@clusterfs.com>
35  */
36
37 #define DEBUG_SUBSYSTEM S_SEC
38
39
40 #include <obd_support.h>
41 #include <obd_cksum.h>
42 #include <obd_class.h>
43 #include <lustre_net.h>
44 #include <lustre_sec.h>
45
46 #include "ptlrpc_internal.h"
47
48 static struct ptlrpc_sec_policy null_policy;
49 static struct ptlrpc_sec        null_sec;
50 static struct ptlrpc_cli_ctx    null_cli_ctx;
51 static struct ptlrpc_svc_ctx    null_svc_ctx;
52
53 /*
54  * we can temporarily use the topmost 8-bits of lm_secflvr to identify
55  * the source sec part.
56  */
57 static inline
58 void null_encode_sec_part(struct lustre_msg *msg, enum lustre_sec_part sp)
59 {
60         msg->lm_secflvr |= (((__u32) sp) & 0xFF) << 24;
61 }
62
63 static inline
64 enum lustre_sec_part null_decode_sec_part(struct lustre_msg *msg)
65 {
66         return (msg->lm_secflvr >> 24) & 0xFF;
67 }
68
69 static
70 int null_ctx_sign(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req)
71 {
72         req->rq_reqbuf->lm_secflvr = SPTLRPC_FLVR_NULL;
73
74         if (!req->rq_import->imp_dlm_fake) {
75                 struct obd_device *obd = req->rq_import->imp_obd;
76
77                 null_encode_sec_part(req->rq_reqbuf,
78                                      obd->u.cli.cl_sp_me);
79         }
80         req->rq_reqdata_len = req->rq_reqlen;
81         return 0;
82 }
83
84 static
85 int null_ctx_verify(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req)
86 {
87         __u32   cksums, cksumc;
88
89         LASSERT(req->rq_repdata);
90
91         req->rq_repmsg = req->rq_repdata;
92         req->rq_replen = req->rq_repdata_len;
93
94         if (req->rq_early) {
95                 cksums = lustre_msg_get_cksum(req->rq_repdata);
96                 cksumc = lustre_msg_calc_cksum(req->rq_repmsg,
97                                                MSG_PTLRPC_BODY_OFF);
98
99                 if (cksumc != cksums) {
100                         CDEBUG(D_SEC,
101                                "early reply checksum mismatch: %08x != %08x\n",
102                                cksumc, cksums);
103                         return -EINVAL;
104                 }
105         }
106
107         return 0;
108 }
109
110 static
111 struct ptlrpc_sec *null_create_sec(struct obd_import *imp,
112                                    struct ptlrpc_svc_ctx *svc_ctx,
113                                    struct sptlrpc_flavor *sf)
114 {
115         LASSERT(SPTLRPC_FLVR_POLICY(sf->sf_rpc) == SPTLRPC_POLICY_NULL);
116
117         /*
118          * general layer has take a module reference for us, because we never
119          * really destroy the sec, simply release the reference here.
120          */
121         sptlrpc_policy_put(&null_policy);
122         return &null_sec;
123 }
124
125 static
126 void null_destroy_sec(struct ptlrpc_sec *sec)
127 {
128         LASSERT(sec == &null_sec);
129 }
130
131 static
132 struct ptlrpc_cli_ctx *null_lookup_ctx(struct ptlrpc_sec *sec,
133                                        struct vfs_cred *vcred,
134                                        int create, int remove_dead)
135 {
136         atomic_inc(&null_cli_ctx.cc_refcount);
137         return &null_cli_ctx;
138 }
139
140 static
141 int null_flush_ctx_cache(struct ptlrpc_sec *sec, uid_t uid, int grace,
142                          int force)
143 {
144         return 0;
145 }
146
147 static
148 int null_alloc_reqbuf(struct ptlrpc_sec *sec,
149                       struct ptlrpc_request *req,
150                       int msgsize)
151 {
152         if (!req->rq_reqbuf) {
153                 int alloc_size = size_roundup_power2(msgsize);
154
155                 LASSERT(!req->rq_pool);
156                 OBD_ALLOC_LARGE(req->rq_reqbuf, alloc_size);
157                 if (!req->rq_reqbuf)
158                         return -ENOMEM;
159
160                 req->rq_reqbuf_len = alloc_size;
161         } else {
162                 LASSERT(req->rq_pool);
163                 LASSERT(req->rq_reqbuf_len >= msgsize);
164                 memset(req->rq_reqbuf, 0, msgsize);
165         }
166
167         req->rq_reqmsg = req->rq_reqbuf;
168         return 0;
169 }
170
171 static
172 void null_free_reqbuf(struct ptlrpc_sec *sec,
173                       struct ptlrpc_request *req)
174 {
175         if (!req->rq_pool) {
176                 LASSERTF(req->rq_reqmsg == req->rq_reqbuf,
177                          "req %p: reqmsg %p is not reqbuf %p in null sec\n",
178                          req, req->rq_reqmsg, req->rq_reqbuf);
179                 LASSERTF(req->rq_reqbuf_len >= req->rq_reqlen,
180                          "req %p: reqlen %d should smaller than buflen %d\n",
181                          req, req->rq_reqlen, req->rq_reqbuf_len);
182
183                 OBD_FREE_LARGE(req->rq_reqbuf, req->rq_reqbuf_len);
184                 req->rq_reqbuf = NULL;
185                 req->rq_reqbuf_len = 0;
186         }
187 }
188
189 static
190 int null_alloc_repbuf(struct ptlrpc_sec *sec,
191                       struct ptlrpc_request *req,
192                       int msgsize)
193 {
194         /* add space for early replied */
195         msgsize += lustre_msg_early_size();
196
197         msgsize = size_roundup_power2(msgsize);
198
199         OBD_ALLOC_LARGE(req->rq_repbuf, msgsize);
200         if (!req->rq_repbuf)
201                 return -ENOMEM;
202
203         req->rq_repbuf_len = msgsize;
204         return 0;
205 }
206
207 static
208 void null_free_repbuf(struct ptlrpc_sec *sec,
209                       struct ptlrpc_request *req)
210 {
211         LASSERT(req->rq_repbuf);
212
213         OBD_FREE_LARGE(req->rq_repbuf, req->rq_repbuf_len);
214         req->rq_repbuf = NULL;
215         req->rq_repbuf_len = 0;
216 }
217
218 static
219 int null_enlarge_reqbuf(struct ptlrpc_sec *sec,
220                         struct ptlrpc_request *req,
221                         int segment, int newsize)
222 {
223         struct lustre_msg      *newbuf;
224         struct lustre_msg      *oldbuf = req->rq_reqmsg;
225         int                     oldsize, newmsg_size, alloc_size;
226
227         LASSERT(req->rq_reqbuf);
228         LASSERT(req->rq_reqbuf == req->rq_reqmsg);
229         LASSERT(req->rq_reqbuf_len >= req->rq_reqlen);
230         LASSERT(req->rq_reqlen == lustre_packed_msg_size(oldbuf));
231
232         /* compute new message size */
233         oldsize = req->rq_reqbuf->lm_buflens[segment];
234         req->rq_reqbuf->lm_buflens[segment] = newsize;
235         newmsg_size = lustre_packed_msg_size(oldbuf);
236         req->rq_reqbuf->lm_buflens[segment] = oldsize;
237
238         /* request from pool should always have enough buffer */
239         LASSERT(!req->rq_pool || req->rq_reqbuf_len >= newmsg_size);
240
241         if (req->rq_reqbuf_len < newmsg_size) {
242                 alloc_size = size_roundup_power2(newmsg_size);
243
244                 OBD_ALLOC_LARGE(newbuf, alloc_size);
245                 if (newbuf == NULL)
246                         return -ENOMEM;
247
248                 /*
249                  * Must lock this, so that otherwise unprotected change of
250                  * rq_reqmsg is not racing with parallel processing of
251                  * imp_replay_list traversing threads. See LU-3333
252                  * This is a bandaid at best, we really need to deal with this
253                  * in request enlarging code before unpacking that's already
254                  * there
255                  */
256                 if (req->rq_import)
257                         spin_lock(&req->rq_import->imp_lock);
258                 memcpy(newbuf, req->rq_reqbuf, req->rq_reqlen);
259
260                 OBD_FREE_LARGE(req->rq_reqbuf, req->rq_reqbuf_len);
261                 req->rq_reqbuf = req->rq_reqmsg = newbuf;
262                 req->rq_reqbuf_len = alloc_size;
263
264                 if (req->rq_import)
265                         spin_unlock(&req->rq_import->imp_lock);
266         }
267
268         _sptlrpc_enlarge_msg_inplace(req->rq_reqmsg, segment, newsize);
269         req->rq_reqlen = newmsg_size;
270
271         return 0;
272 }
273
274 static struct ptlrpc_svc_ctx null_svc_ctx = {
275         .sc_refcount    = ATOMIC_INIT(1),
276         .sc_policy      = &null_policy,
277 };
278
279 static
280 int null_accept(struct ptlrpc_request *req)
281 {
282         LASSERT(SPTLRPC_FLVR_POLICY(req->rq_flvr.sf_rpc) ==
283                 SPTLRPC_POLICY_NULL);
284
285         if (req->rq_flvr.sf_rpc != SPTLRPC_FLVR_NULL) {
286                 CERROR("Invalid rpc flavor 0x%x\n", req->rq_flvr.sf_rpc);
287                 return SECSVC_DROP;
288         }
289
290         req->rq_sp_from = null_decode_sec_part(req->rq_reqbuf);
291
292         req->rq_reqmsg = req->rq_reqbuf;
293         req->rq_reqlen = req->rq_reqdata_len;
294
295         req->rq_svc_ctx = &null_svc_ctx;
296         atomic_inc(&req->rq_svc_ctx->sc_refcount);
297
298         return SECSVC_OK;
299 }
300
301 static
302 int null_alloc_rs(struct ptlrpc_request *req, int msgsize)
303 {
304         struct ptlrpc_reply_state *rs;
305         int rs_size = sizeof(*rs) + msgsize;
306
307         LASSERT(msgsize % 8 == 0);
308
309         rs = req->rq_reply_state;
310
311         if (rs) {
312                 /* pre-allocated */
313                 LASSERT(rs->rs_size >= rs_size);
314         } else {
315                 OBD_ALLOC_LARGE(rs, rs_size);
316                 if (rs == NULL)
317                         return -ENOMEM;
318
319                 rs->rs_size = rs_size;
320         }
321
322         rs->rs_svc_ctx = req->rq_svc_ctx;
323         atomic_inc(&req->rq_svc_ctx->sc_refcount);
324
325         rs->rs_repbuf = (struct lustre_msg *) (rs + 1);
326         rs->rs_repbuf_len = rs_size - sizeof(*rs);
327         rs->rs_msg = rs->rs_repbuf;
328
329         req->rq_reply_state = rs;
330         return 0;
331 }
332
333 static
334 void null_free_rs(struct ptlrpc_reply_state *rs)
335 {
336         LASSERT_ATOMIC_GT(&rs->rs_svc_ctx->sc_refcount, 1);
337         atomic_dec(&rs->rs_svc_ctx->sc_refcount);
338
339         if (!rs->rs_prealloc)
340                 OBD_FREE_LARGE(rs, rs->rs_size);
341 }
342
343 static
344 int null_authorize(struct ptlrpc_request *req)
345 {
346         struct ptlrpc_reply_state *rs = req->rq_reply_state;
347
348         LASSERT(rs);
349
350         rs->rs_repbuf->lm_secflvr = SPTLRPC_FLVR_NULL;
351         rs->rs_repdata_len = req->rq_replen;
352         req->rq_reply_off = 0;
353
354         if (likely(req->rq_packed_final)) {
355                 if (lustre_msghdr_get_flags(req->rq_reqmsg) & MSGHDR_AT_SUPPORT)
356                         req->rq_reply_off = lustre_msg_early_size();
357         } else {
358                 __u32 cksum;
359
360                 cksum = lustre_msg_calc_cksum(rs->rs_repbuf,
361                                               MSG_PTLRPC_BODY_OFF);
362                 lustre_msg_set_cksum(rs->rs_repbuf, cksum);
363         }
364
365         return 0;
366 }
367
368 static struct ptlrpc_ctx_ops null_ctx_ops = {
369         .sign                   = null_ctx_sign,
370         .verify                 = null_ctx_verify,
371 };
372
373 static struct ptlrpc_sec_cops null_sec_cops = {
374         .create_sec             = null_create_sec,
375         .destroy_sec            = null_destroy_sec,
376         .lookup_ctx             = null_lookup_ctx,
377         .flush_ctx_cache        = null_flush_ctx_cache,
378         .alloc_reqbuf           = null_alloc_reqbuf,
379         .alloc_repbuf           = null_alloc_repbuf,
380         .free_reqbuf            = null_free_reqbuf,
381         .free_repbuf            = null_free_repbuf,
382         .enlarge_reqbuf         = null_enlarge_reqbuf,
383 };
384
385 static struct ptlrpc_sec_sops null_sec_sops = {
386         .accept                 = null_accept,
387         .alloc_rs               = null_alloc_rs,
388         .authorize              = null_authorize,
389         .free_rs                = null_free_rs,
390 };
391
392 static struct ptlrpc_sec_policy null_policy = {
393         .sp_owner               = THIS_MODULE,
394         .sp_name                = "sec.null",
395         .sp_policy              = SPTLRPC_POLICY_NULL,
396         .sp_cops                = &null_sec_cops,
397         .sp_sops                = &null_sec_sops,
398 };
399
400 static void null_init_internal(void)
401 {
402         static HLIST_HEAD(__list);
403
404         null_sec.ps_policy = &null_policy;
405         atomic_set(&null_sec.ps_refcount, 1);   /* always busy */
406         null_sec.ps_id = -1;
407         null_sec.ps_import = NULL;
408         null_sec.ps_flvr.sf_rpc = SPTLRPC_FLVR_NULL;
409         null_sec.ps_flvr.sf_flags = 0;
410         null_sec.ps_part = LUSTRE_SP_ANY;
411         null_sec.ps_dying = 0;
412         spin_lock_init(&null_sec.ps_lock);
413         atomic_set(&null_sec.ps_nctx, 1);       /* for "null_cli_ctx" */
414         INIT_LIST_HEAD(&null_sec.ps_gc_list);
415         null_sec.ps_gc_interval = 0;
416         null_sec.ps_gc_next = 0;
417
418         hlist_add_head(&null_cli_ctx.cc_cache, &__list);
419         atomic_set(&null_cli_ctx.cc_refcount, 1);       /* for hash */
420         null_cli_ctx.cc_sec = &null_sec;
421         null_cli_ctx.cc_ops = &null_ctx_ops;
422         null_cli_ctx.cc_expire = 0;
423         null_cli_ctx.cc_flags = PTLRPC_CTX_CACHED | PTLRPC_CTX_ETERNAL |
424                                 PTLRPC_CTX_UPTODATE;
425         null_cli_ctx.cc_vcred.vc_uid = 0;
426         spin_lock_init(&null_cli_ctx.cc_lock);
427         INIT_LIST_HEAD(&null_cli_ctx.cc_req_list);
428         INIT_LIST_HEAD(&null_cli_ctx.cc_gc_chain);
429 }
430
431 int sptlrpc_null_init(void)
432 {
433         int rc;
434
435         null_init_internal();
436
437         rc = sptlrpc_register_policy(&null_policy);
438         if (rc)
439                 CERROR("failed to register %s: %d\n", null_policy.sp_name, rc);
440
441         return rc;
442 }
443
444 void sptlrpc_null_fini(void)
445 {
446         int rc;
447
448         rc = sptlrpc_unregister_policy(&null_policy);
449         if (rc)
450                 CERROR("failed to unregister %s: %d\n", null_policy.sp_name,
451                        rc);
452 }