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, see
18 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
27 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
30 * Copyright (c) 2011, 2012, Intel Corporation.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 * lustre/ptlrpc/sec_null.c
38 * Author: Eric Mei <ericm@clusterfs.com>
41 #define DEBUG_SUBSYSTEM S_SEC
43 #include "../include/obd_support.h"
44 #include "../include/obd_cksum.h"
45 #include "../include/obd_class.h"
46 #include "../include/lustre_net.h"
47 #include "../include/lustre_sec.h"
49 #include "ptlrpc_internal.h"
51 static struct ptlrpc_sec_policy null_policy
;
52 static struct ptlrpc_sec null_sec
;
53 static struct ptlrpc_cli_ctx null_cli_ctx
;
54 static struct ptlrpc_svc_ctx null_svc_ctx
;
57 * we can temporarily use the topmost 8-bits of lm_secflvr to identify
58 * the source sec part.
61 void null_encode_sec_part(struct lustre_msg
*msg
, enum lustre_sec_part sp
)
63 msg
->lm_secflvr
|= (((__u32
) sp
) & 0xFF) << 24;
67 enum lustre_sec_part
null_decode_sec_part(struct lustre_msg
*msg
)
69 return (msg
->lm_secflvr
>> 24) & 0xFF;
72 static int null_ctx_refresh(struct ptlrpc_cli_ctx
*ctx
)
74 /* should never reach here */
80 int null_ctx_sign(struct ptlrpc_cli_ctx
*ctx
, struct ptlrpc_request
*req
)
82 req
->rq_reqbuf
->lm_secflvr
= SPTLRPC_FLVR_NULL
;
84 if (!req
->rq_import
->imp_dlm_fake
) {
85 struct obd_device
*obd
= req
->rq_import
->imp_obd
;
87 null_encode_sec_part(req
->rq_reqbuf
,
90 req
->rq_reqdata_len
= req
->rq_reqlen
;
95 int null_ctx_verify(struct ptlrpc_cli_ctx
*ctx
, struct ptlrpc_request
*req
)
99 LASSERT(req
->rq_repdata
);
101 req
->rq_repmsg
= req
->rq_repdata
;
102 req
->rq_replen
= req
->rq_repdata_len
;
105 cksums
= lustre_msg_get_cksum(req
->rq_repdata
);
106 cksumc
= lustre_msg_calc_cksum(req
->rq_repmsg
);
107 if (cksumc
!= cksums
) {
109 "early reply checksum mismatch: %08x != %08x\n",
119 struct ptlrpc_sec
*null_create_sec(struct obd_import
*imp
,
120 struct ptlrpc_svc_ctx
*svc_ctx
,
121 struct sptlrpc_flavor
*sf
)
123 LASSERT(SPTLRPC_FLVR_POLICY(sf
->sf_rpc
) == SPTLRPC_POLICY_NULL
);
125 /* general layer has take a module reference for us, because we never
126 * really destroy the sec, simply release the reference here.
128 sptlrpc_policy_put(&null_policy
);
133 void null_destroy_sec(struct ptlrpc_sec
*sec
)
135 LASSERT(sec
== &null_sec
);
139 struct ptlrpc_cli_ctx
*null_lookup_ctx(struct ptlrpc_sec
*sec
,
140 struct vfs_cred
*vcred
,
141 int create
, int remove_dead
)
143 atomic_inc(&null_cli_ctx
.cc_refcount
);
144 return &null_cli_ctx
;
148 int null_flush_ctx_cache(struct ptlrpc_sec
*sec
,
150 int grace
, int force
)
156 int null_alloc_reqbuf(struct ptlrpc_sec
*sec
,
157 struct ptlrpc_request
*req
,
160 if (!req
->rq_reqbuf
) {
161 int alloc_size
= size_roundup_power2(msgsize
);
163 LASSERT(!req
->rq_pool
);
164 req
->rq_reqbuf
= libcfs_kvzalloc(alloc_size
, GFP_NOFS
);
168 req
->rq_reqbuf_len
= alloc_size
;
170 LASSERT(req
->rq_pool
);
171 LASSERT(req
->rq_reqbuf_len
>= msgsize
);
172 memset(req
->rq_reqbuf
, 0, msgsize
);
175 req
->rq_reqmsg
= req
->rq_reqbuf
;
180 void null_free_reqbuf(struct ptlrpc_sec
*sec
,
181 struct ptlrpc_request
*req
)
184 LASSERTF(req
->rq_reqmsg
== req
->rq_reqbuf
,
185 "req %p: reqmsg %p is not reqbuf %p in null sec\n",
186 req
, req
->rq_reqmsg
, req
->rq_reqbuf
);
187 LASSERTF(req
->rq_reqbuf_len
>= req
->rq_reqlen
,
188 "req %p: reqlen %d should smaller than buflen %d\n",
189 req
, req
->rq_reqlen
, req
->rq_reqbuf_len
);
191 kvfree(req
->rq_reqbuf
);
192 req
->rq_reqbuf
= NULL
;
193 req
->rq_reqbuf_len
= 0;
198 int null_alloc_repbuf(struct ptlrpc_sec
*sec
,
199 struct ptlrpc_request
*req
,
202 /* add space for early replied */
203 msgsize
+= lustre_msg_early_size();
205 msgsize
= size_roundup_power2(msgsize
);
207 req
->rq_repbuf
= libcfs_kvzalloc(msgsize
, GFP_NOFS
);
211 req
->rq_repbuf_len
= msgsize
;
216 void null_free_repbuf(struct ptlrpc_sec
*sec
,
217 struct ptlrpc_request
*req
)
219 LASSERT(req
->rq_repbuf
);
221 kvfree(req
->rq_repbuf
);
222 req
->rq_repbuf
= NULL
;
223 req
->rq_repbuf_len
= 0;
227 int null_enlarge_reqbuf(struct ptlrpc_sec
*sec
,
228 struct ptlrpc_request
*req
,
229 int segment
, int newsize
)
231 struct lustre_msg
*newbuf
;
232 struct lustre_msg
*oldbuf
= req
->rq_reqmsg
;
233 int oldsize
, newmsg_size
, alloc_size
;
235 LASSERT(req
->rq_reqbuf
);
236 LASSERT(req
->rq_reqbuf
== req
->rq_reqmsg
);
237 LASSERT(req
->rq_reqbuf_len
>= req
->rq_reqlen
);
238 LASSERT(req
->rq_reqlen
== lustre_packed_msg_size(oldbuf
));
240 /* compute new message size */
241 oldsize
= req
->rq_reqbuf
->lm_buflens
[segment
];
242 req
->rq_reqbuf
->lm_buflens
[segment
] = newsize
;
243 newmsg_size
= lustre_packed_msg_size(oldbuf
);
244 req
->rq_reqbuf
->lm_buflens
[segment
] = oldsize
;
246 /* request from pool should always have enough buffer */
247 LASSERT(!req
->rq_pool
|| req
->rq_reqbuf_len
>= newmsg_size
);
249 if (req
->rq_reqbuf_len
< newmsg_size
) {
250 alloc_size
= size_roundup_power2(newmsg_size
);
252 newbuf
= libcfs_kvzalloc(alloc_size
, GFP_NOFS
);
256 /* Must lock this, so that otherwise unprotected change of
257 * rq_reqmsg is not racing with parallel processing of
258 * imp_replay_list traversing threads. See LU-3333
259 * This is a bandaid at best, we really need to deal with this
260 * in request enlarging code before unpacking that's already
264 spin_lock(&req
->rq_import
->imp_lock
);
265 memcpy(newbuf
, req
->rq_reqbuf
, req
->rq_reqlen
);
267 kvfree(req
->rq_reqbuf
);
268 req
->rq_reqbuf
= req
->rq_reqmsg
= newbuf
;
269 req
->rq_reqbuf_len
= alloc_size
;
272 spin_unlock(&req
->rq_import
->imp_lock
);
275 _sptlrpc_enlarge_msg_inplace(req
->rq_reqmsg
, segment
, newsize
);
276 req
->rq_reqlen
= newmsg_size
;
281 static struct ptlrpc_svc_ctx null_svc_ctx
= {
282 .sc_refcount
= ATOMIC_INIT(1),
283 .sc_policy
= &null_policy
,
287 int null_accept(struct ptlrpc_request
*req
)
289 LASSERT(SPTLRPC_FLVR_POLICY(req
->rq_flvr
.sf_rpc
) ==
290 SPTLRPC_POLICY_NULL
);
292 if (req
->rq_flvr
.sf_rpc
!= SPTLRPC_FLVR_NULL
) {
293 CERROR("Invalid rpc flavor 0x%x\n", req
->rq_flvr
.sf_rpc
);
297 req
->rq_sp_from
= null_decode_sec_part(req
->rq_reqbuf
);
299 req
->rq_reqmsg
= req
->rq_reqbuf
;
300 req
->rq_reqlen
= req
->rq_reqdata_len
;
302 req
->rq_svc_ctx
= &null_svc_ctx
;
303 atomic_inc(&req
->rq_svc_ctx
->sc_refcount
);
309 int null_alloc_rs(struct ptlrpc_request
*req
, int msgsize
)
311 struct ptlrpc_reply_state
*rs
;
312 int rs_size
= sizeof(*rs
) + msgsize
;
314 LASSERT(msgsize
% 8 == 0);
316 rs
= req
->rq_reply_state
;
320 LASSERT(rs
->rs_size
>= rs_size
);
322 rs
= libcfs_kvzalloc(rs_size
, GFP_NOFS
);
326 rs
->rs_size
= rs_size
;
329 rs
->rs_svc_ctx
= req
->rq_svc_ctx
;
330 atomic_inc(&req
->rq_svc_ctx
->sc_refcount
);
332 rs
->rs_repbuf
= (struct lustre_msg
*) (rs
+ 1);
333 rs
->rs_repbuf_len
= rs_size
- sizeof(*rs
);
334 rs
->rs_msg
= rs
->rs_repbuf
;
336 req
->rq_reply_state
= rs
;
341 void null_free_rs(struct ptlrpc_reply_state
*rs
)
343 LASSERT_ATOMIC_GT(&rs
->rs_svc_ctx
->sc_refcount
, 1);
344 atomic_dec(&rs
->rs_svc_ctx
->sc_refcount
);
346 if (!rs
->rs_prealloc
)
351 int null_authorize(struct ptlrpc_request
*req
)
353 struct ptlrpc_reply_state
*rs
= req
->rq_reply_state
;
357 rs
->rs_repbuf
->lm_secflvr
= SPTLRPC_FLVR_NULL
;
358 rs
->rs_repdata_len
= req
->rq_replen
;
360 if (likely(req
->rq_packed_final
)) {
361 if (lustre_msghdr_get_flags(req
->rq_reqmsg
) & MSGHDR_AT_SUPPORT
)
362 req
->rq_reply_off
= lustre_msg_early_size();
364 req
->rq_reply_off
= 0;
368 cksum
= lustre_msg_calc_cksum(rs
->rs_repbuf
);
369 lustre_msg_set_cksum(rs
->rs_repbuf
, cksum
);
370 req
->rq_reply_off
= 0;
376 static struct ptlrpc_ctx_ops null_ctx_ops
= {
377 .refresh
= null_ctx_refresh
,
378 .sign
= null_ctx_sign
,
379 .verify
= null_ctx_verify
,
382 static struct ptlrpc_sec_cops null_sec_cops
= {
383 .create_sec
= null_create_sec
,
384 .destroy_sec
= null_destroy_sec
,
385 .lookup_ctx
= null_lookup_ctx
,
386 .flush_ctx_cache
= null_flush_ctx_cache
,
387 .alloc_reqbuf
= null_alloc_reqbuf
,
388 .alloc_repbuf
= null_alloc_repbuf
,
389 .free_reqbuf
= null_free_reqbuf
,
390 .free_repbuf
= null_free_repbuf
,
391 .enlarge_reqbuf
= null_enlarge_reqbuf
,
394 static struct ptlrpc_sec_sops null_sec_sops
= {
395 .accept
= null_accept
,
396 .alloc_rs
= null_alloc_rs
,
397 .authorize
= null_authorize
,
398 .free_rs
= null_free_rs
,
401 static struct ptlrpc_sec_policy null_policy
= {
402 .sp_owner
= THIS_MODULE
,
403 .sp_name
= "sec.null",
404 .sp_policy
= SPTLRPC_POLICY_NULL
,
405 .sp_cops
= &null_sec_cops
,
406 .sp_sops
= &null_sec_sops
,
409 static void null_init_internal(void)
411 static HLIST_HEAD(__list
);
413 null_sec
.ps_policy
= &null_policy
;
414 atomic_set(&null_sec
.ps_refcount
, 1); /* always busy */
416 null_sec
.ps_import
= NULL
;
417 null_sec
.ps_flvr
.sf_rpc
= SPTLRPC_FLVR_NULL
;
418 null_sec
.ps_flvr
.sf_flags
= 0;
419 null_sec
.ps_part
= LUSTRE_SP_ANY
;
420 null_sec
.ps_dying
= 0;
421 spin_lock_init(&null_sec
.ps_lock
);
422 atomic_set(&null_sec
.ps_nctx
, 1); /* for "null_cli_ctx" */
423 INIT_LIST_HEAD(&null_sec
.ps_gc_list
);
424 null_sec
.ps_gc_interval
= 0;
425 null_sec
.ps_gc_next
= 0;
427 hlist_add_head(&null_cli_ctx
.cc_cache
, &__list
);
428 atomic_set(&null_cli_ctx
.cc_refcount
, 1); /* for hash */
429 null_cli_ctx
.cc_sec
= &null_sec
;
430 null_cli_ctx
.cc_ops
= &null_ctx_ops
;
431 null_cli_ctx
.cc_expire
= 0;
432 null_cli_ctx
.cc_flags
= PTLRPC_CTX_CACHED
| PTLRPC_CTX_ETERNAL
|
434 null_cli_ctx
.cc_vcred
.vc_uid
= 0;
435 spin_lock_init(&null_cli_ctx
.cc_lock
);
436 INIT_LIST_HEAD(&null_cli_ctx
.cc_req_list
);
437 INIT_LIST_HEAD(&null_cli_ctx
.cc_gc_chain
);
440 int sptlrpc_null_init(void)
444 null_init_internal();
446 rc
= sptlrpc_register_policy(&null_policy
);
448 CERROR("failed to register %s: %d\n", null_policy
.sp_name
, rc
);
453 void sptlrpc_null_fini(void)
457 rc
= sptlrpc_unregister_policy(&null_policy
);
459 CERROR("failed to unregister %s: %d\n",
460 null_policy
.sp_name
, rc
);