GNU Linux-libre 4.9.304-gnu1
[releases.git] / drivers / staging / lustre / lustre / ptlrpc / sec_config.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) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright (c) 2011, 2015, 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
33 #define DEBUG_SUBSYSTEM S_SEC
34
35 #include "../../include/linux/libcfs/libcfs.h"
36 #include <linux/crypto.h>
37 #include <linux/key.h>
38
39 #include "../include/obd.h"
40 #include "../include/obd_support.h"
41 #include "../include/lustre_import.h"
42 #include "../include/lustre_param.h"
43 #include "../include/lustre_sec.h"
44
45 #include "ptlrpc_internal.h"
46
47 enum lustre_sec_part sptlrpc_target_sec_part(struct obd_device *obd)
48 {
49         const char *type = obd->obd_type->typ_name;
50
51         if (!strcmp(type, LUSTRE_MDT_NAME))
52                 return LUSTRE_SP_MDT;
53         if (!strcmp(type, LUSTRE_OST_NAME))
54                 return LUSTRE_SP_OST;
55         if (!strcmp(type, LUSTRE_MGS_NAME))
56                 return LUSTRE_SP_MGS;
57
58         CERROR("unknown target %p(%s)\n", obd, type);
59         return LUSTRE_SP_ANY;
60 }
61
62 /****************************************
63  * user supplied flavor string parsing  *
64  ****************************************/
65
66 /*
67  * format: <base_flavor>[-<bulk_type:alg_spec>]
68  */
69 int sptlrpc_parse_flavor(const char *str, struct sptlrpc_flavor *flvr)
70 {
71         char buf[32];
72         char *bulk, *alg;
73
74         memset(flvr, 0, sizeof(*flvr));
75
76         if (!str || str[0] == '\0') {
77                 flvr->sf_rpc = SPTLRPC_FLVR_INVALID;
78                 return 0;
79         }
80
81         strlcpy(buf, str, sizeof(buf));
82
83         bulk = strchr(buf, '-');
84         if (bulk)
85                 *bulk++ = '\0';
86
87         flvr->sf_rpc = sptlrpc_name2flavor_base(buf);
88         if (flvr->sf_rpc == SPTLRPC_FLVR_INVALID)
89                 goto err_out;
90
91         /*
92          * currently only base flavor "plain" can have bulk specification.
93          */
94         if (flvr->sf_rpc == SPTLRPC_FLVR_PLAIN) {
95                 flvr->u_bulk.hash.hash_alg = BULK_HASH_ALG_ADLER32;
96                 if (bulk) {
97                         /*
98                          * format: plain-hash:<hash_alg>
99                          */
100                         alg = strchr(bulk, ':');
101                         if (!alg)
102                                 goto err_out;
103                         *alg++ = '\0';
104
105                         if (strcmp(bulk, "hash"))
106                                 goto err_out;
107
108                         flvr->u_bulk.hash.hash_alg = sptlrpc_get_hash_alg(alg);
109                         if (flvr->u_bulk.hash.hash_alg >= BULK_HASH_ALG_MAX)
110                                 goto err_out;
111                 }
112
113                 if (flvr->u_bulk.hash.hash_alg == BULK_HASH_ALG_NULL)
114                         flvr_set_bulk_svc(&flvr->sf_rpc, SPTLRPC_BULK_SVC_NULL);
115                 else
116                         flvr_set_bulk_svc(&flvr->sf_rpc, SPTLRPC_BULK_SVC_INTG);
117         } else {
118                 if (bulk)
119                         goto err_out;
120         }
121
122         flvr->sf_flags = 0;
123         return 0;
124
125 err_out:
126         CERROR("invalid flavor string: %s\n", str);
127         return -EINVAL;
128 }
129 EXPORT_SYMBOL(sptlrpc_parse_flavor);
130
131 /****************************************
132  * configure rules                    *
133  ****************************************/
134
135 static void get_default_flavor(struct sptlrpc_flavor *sf)
136 {
137         memset(sf, 0, sizeof(*sf));
138
139         sf->sf_rpc = SPTLRPC_FLVR_NULL;
140         sf->sf_flags = 0;
141 }
142
143 static void sptlrpc_rule_init(struct sptlrpc_rule *rule)
144 {
145         rule->sr_netid = LNET_NIDNET(LNET_NID_ANY);
146         rule->sr_from = LUSTRE_SP_ANY;
147         rule->sr_to = LUSTRE_SP_ANY;
148         rule->sr_padding = 0;
149
150         get_default_flavor(&rule->sr_flvr);
151 }
152
153 /*
154  * format: network[.direction]=flavor
155  */
156 static int sptlrpc_parse_rule(char *param, struct sptlrpc_rule *rule)
157 {
158         char *flavor, *dir;
159         int rc;
160
161         sptlrpc_rule_init(rule);
162
163         flavor = strchr(param, '=');
164         if (!flavor) {
165                 CERROR("invalid param, no '='\n");
166                 return -EINVAL;
167         }
168         *flavor++ = '\0';
169
170         dir = strchr(param, '.');
171         if (dir)
172                 *dir++ = '\0';
173
174         /* 1.1 network */
175         if (strcmp(param, "default")) {
176                 rule->sr_netid = libcfs_str2net(param);
177                 if (rule->sr_netid == LNET_NIDNET(LNET_NID_ANY)) {
178                         CERROR("invalid network name: %s\n", param);
179                         return -EINVAL;
180                 }
181         }
182
183         /* 1.2 direction */
184         if (dir) {
185                 if (!strcmp(dir, "mdt2ost")) {
186                         rule->sr_from = LUSTRE_SP_MDT;
187                         rule->sr_to = LUSTRE_SP_OST;
188                 } else if (!strcmp(dir, "mdt2mdt")) {
189                         rule->sr_from = LUSTRE_SP_MDT;
190                         rule->sr_to = LUSTRE_SP_MDT;
191                 } else if (!strcmp(dir, "cli2ost")) {
192                         rule->sr_from = LUSTRE_SP_CLI;
193                         rule->sr_to = LUSTRE_SP_OST;
194                 } else if (!strcmp(dir, "cli2mdt")) {
195                         rule->sr_from = LUSTRE_SP_CLI;
196                         rule->sr_to = LUSTRE_SP_MDT;
197                 } else {
198                         CERROR("invalid rule dir segment: %s\n", dir);
199                         return -EINVAL;
200                 }
201         }
202
203         /* 2.1 flavor */
204         rc = sptlrpc_parse_flavor(flavor, &rule->sr_flvr);
205         if (rc)
206                 return -EINVAL;
207
208         return 0;
209 }
210
211 static void sptlrpc_rule_set_free(struct sptlrpc_rule_set *rset)
212 {
213         LASSERT(rset->srs_nslot ||
214                 (rset->srs_nrule == 0 && !rset->srs_rules));
215
216         if (rset->srs_nslot) {
217                 kfree(rset->srs_rules);
218                 sptlrpc_rule_set_init(rset);
219         }
220 }
221
222 /*
223  * return 0 if the rule set could accommodate one more rule.
224  */
225 static int sptlrpc_rule_set_expand(struct sptlrpc_rule_set *rset)
226 {
227         struct sptlrpc_rule *rules;
228         int nslot;
229
230         might_sleep();
231
232         if (rset->srs_nrule < rset->srs_nslot)
233                 return 0;
234
235         nslot = rset->srs_nslot + 8;
236
237         /* better use realloc() if available */
238         rules = kcalloc(nslot, sizeof(*rset->srs_rules), GFP_NOFS);
239         if (!rules)
240                 return -ENOMEM;
241
242         if (rset->srs_nrule) {
243                 LASSERT(rset->srs_nslot && rset->srs_rules);
244                 memcpy(rules, rset->srs_rules,
245                        rset->srs_nrule * sizeof(*rset->srs_rules));
246
247                 kfree(rset->srs_rules);
248         }
249
250         rset->srs_rules = rules;
251         rset->srs_nslot = nslot;
252         return 0;
253 }
254
255 static inline int rule_spec_dir(struct sptlrpc_rule *rule)
256 {
257         return (rule->sr_from != LUSTRE_SP_ANY ||
258                 rule->sr_to != LUSTRE_SP_ANY);
259 }
260
261 static inline int rule_spec_net(struct sptlrpc_rule *rule)
262 {
263         return (rule->sr_netid != LNET_NIDNET(LNET_NID_ANY));
264 }
265
266 static inline int rule_match_dir(struct sptlrpc_rule *r1,
267                                  struct sptlrpc_rule *r2)
268 {
269         return (r1->sr_from == r2->sr_from && r1->sr_to == r2->sr_to);
270 }
271
272 static inline int rule_match_net(struct sptlrpc_rule *r1,
273                                  struct sptlrpc_rule *r2)
274 {
275         return (r1->sr_netid == r2->sr_netid);
276 }
277
278 /*
279  * merge @rule into @rset.
280  * the @rset slots might be expanded.
281  */
282 static int sptlrpc_rule_set_merge(struct sptlrpc_rule_set *rset,
283                                   struct sptlrpc_rule *rule)
284 {
285         struct sptlrpc_rule *p = rset->srs_rules;
286         int spec_dir, spec_net;
287         int rc, n, match = 0;
288
289         might_sleep();
290
291         spec_net = rule_spec_net(rule);
292         spec_dir = rule_spec_dir(rule);
293
294         for (n = 0; n < rset->srs_nrule; n++) {
295                 p = &rset->srs_rules[n];
296
297                 /* test network match, if failed:
298                  * - spec rule: skip rules which is also spec rule match, until
299                  *   we hit a wild rule, which means no more chance
300                  * - wild rule: skip until reach the one which is also wild
301                  *   and matches
302                  */
303                 if (!rule_match_net(p, rule)) {
304                         if (spec_net) {
305                                 if (rule_spec_net(p))
306                                         continue;
307                                 else
308                                         break;
309                         } else {
310                                 continue;
311                         }
312                 }
313
314                 /* test dir match, same logic as net matching */
315                 if (!rule_match_dir(p, rule)) {
316                         if (spec_dir) {
317                                 if (rule_spec_dir(p))
318                                         continue;
319                                 else
320                                         break;
321                         } else {
322                                 continue;
323                         }
324                 }
325
326                 /* find a match */
327                 match = 1;
328                 break;
329         }
330
331         if (match) {
332                 LASSERT(n >= 0 && n < rset->srs_nrule);
333
334                 if (rule->sr_flvr.sf_rpc == SPTLRPC_FLVR_INVALID) {
335                         /* remove this rule */
336                         if (n < rset->srs_nrule - 1)
337                                 memmove(&rset->srs_rules[n],
338                                         &rset->srs_rules[n + 1],
339                                         (rset->srs_nrule - n - 1) *
340                                         sizeof(*rule));
341                         rset->srs_nrule--;
342                 } else {
343                         /* override the rule */
344                         memcpy(&rset->srs_rules[n], rule, sizeof(*rule));
345                 }
346         } else {
347                 LASSERT(n >= 0 && n <= rset->srs_nrule);
348
349                 if (rule->sr_flvr.sf_rpc != SPTLRPC_FLVR_INVALID) {
350                         rc = sptlrpc_rule_set_expand(rset);
351                         if (rc)
352                                 return rc;
353
354                         if (n < rset->srs_nrule)
355                                 memmove(&rset->srs_rules[n + 1],
356                                         &rset->srs_rules[n],
357                                         (rset->srs_nrule - n) * sizeof(*rule));
358                         memcpy(&rset->srs_rules[n], rule, sizeof(*rule));
359                         rset->srs_nrule++;
360                 } else {
361                         CDEBUG(D_CONFIG, "ignore the unmatched deletion\n");
362                 }
363         }
364
365         return 0;
366 }
367
368 /**
369  * given from/to/nid, determine a matching flavor in ruleset.
370  * return 1 if a match found, otherwise return 0.
371  */
372 static int sptlrpc_rule_set_choose(struct sptlrpc_rule_set *rset,
373                                    enum lustre_sec_part from,
374                                    enum lustre_sec_part to,
375                                    lnet_nid_t nid,
376                                    struct sptlrpc_flavor *sf)
377 {
378         struct sptlrpc_rule *r;
379         int n;
380
381         for (n = 0; n < rset->srs_nrule; n++) {
382                 r = &rset->srs_rules[n];
383
384                 if (LNET_NIDNET(nid) != LNET_NIDNET(LNET_NID_ANY) &&
385                     r->sr_netid != LNET_NIDNET(LNET_NID_ANY) &&
386                     LNET_NIDNET(nid) != r->sr_netid)
387                         continue;
388
389                 if (from != LUSTRE_SP_ANY && r->sr_from != LUSTRE_SP_ANY &&
390                     from != r->sr_from)
391                         continue;
392
393                 if (to != LUSTRE_SP_ANY && r->sr_to != LUSTRE_SP_ANY &&
394                     to != r->sr_to)
395                         continue;
396
397                 *sf = r->sr_flvr;
398                 return 1;
399         }
400
401         return 0;
402 }
403
404 /**********************************
405  * sptlrpc configuration support  *
406  **********************************/
407
408 struct sptlrpc_conf_tgt {
409         struct list_head              sct_list;
410         char                sct_name[MAX_OBD_NAME];
411         struct sptlrpc_rule_set sct_rset;
412 };
413
414 struct sptlrpc_conf {
415         struct list_head              sc_list;
416         char                sc_fsname[MTI_NAME_MAXLEN];
417         unsigned int        sc_modified;  /* modified during updating */
418         unsigned int        sc_updated:1, /* updated copy from MGS */
419                                 sc_local:1;   /* local copy from target */
420         struct sptlrpc_rule_set sc_rset;      /* fs general rules */
421         struct list_head              sc_tgts;      /* target-specific rules */
422 };
423
424 static struct mutex sptlrpc_conf_lock;
425 static LIST_HEAD(sptlrpc_confs);
426
427 static inline int is_hex(char c)
428 {
429         return ((c >= '0' && c <= '9') ||
430                 (c >= 'a' && c <= 'f'));
431 }
432
433 static void target2fsname(const char *tgt, char *fsname, int buflen)
434 {
435         const char *ptr;
436         int len;
437
438         ptr = strrchr(tgt, '-');
439         if (ptr) {
440                 if ((strncmp(ptr, "-MDT", 4) != 0 &&
441                      strncmp(ptr, "-OST", 4) != 0) ||
442                     !is_hex(ptr[4]) || !is_hex(ptr[5]) ||
443                     !is_hex(ptr[6]) || !is_hex(ptr[7]))
444                         ptr = NULL;
445         }
446
447         /* if we didn't find the pattern, treat the whole string as fsname */
448         if (!ptr)
449                 len = strlen(tgt);
450         else
451                 len = ptr - tgt;
452
453         len = min(len, buflen - 1);
454         memcpy(fsname, tgt, len);
455         fsname[len] = '\0';
456 }
457
458 static void sptlrpc_conf_free_rsets(struct sptlrpc_conf *conf)
459 {
460         struct sptlrpc_conf_tgt *conf_tgt, *conf_tgt_next;
461
462         sptlrpc_rule_set_free(&conf->sc_rset);
463
464         list_for_each_entry_safe(conf_tgt, conf_tgt_next,
465                                  &conf->sc_tgts, sct_list) {
466                 sptlrpc_rule_set_free(&conf_tgt->sct_rset);
467                 list_del(&conf_tgt->sct_list);
468                 kfree(conf_tgt);
469         }
470         LASSERT(list_empty(&conf->sc_tgts));
471
472         conf->sc_updated = 0;
473         conf->sc_local = 0;
474 }
475
476 static void sptlrpc_conf_free(struct sptlrpc_conf *conf)
477 {
478         CDEBUG(D_SEC, "free sptlrpc conf %s\n", conf->sc_fsname);
479
480         sptlrpc_conf_free_rsets(conf);
481         list_del(&conf->sc_list);
482         kfree(conf);
483 }
484
485 static
486 struct sptlrpc_conf_tgt *sptlrpc_conf_get_tgt(struct sptlrpc_conf *conf,
487                                               const char *name,
488                                               int create)
489 {
490         struct sptlrpc_conf_tgt *conf_tgt;
491
492         list_for_each_entry(conf_tgt, &conf->sc_tgts, sct_list) {
493                 if (strcmp(conf_tgt->sct_name, name) == 0)
494                         return conf_tgt;
495         }
496
497         if (!create)
498                 return NULL;
499
500         conf_tgt = kzalloc(sizeof(*conf_tgt), GFP_NOFS);
501         if (conf_tgt) {
502                 strlcpy(conf_tgt->sct_name, name, sizeof(conf_tgt->sct_name));
503                 sptlrpc_rule_set_init(&conf_tgt->sct_rset);
504                 list_add(&conf_tgt->sct_list, &conf->sc_tgts);
505         }
506
507         return conf_tgt;
508 }
509
510 static
511 struct sptlrpc_conf *sptlrpc_conf_get(const char *fsname,
512                                       int create)
513 {
514         struct sptlrpc_conf *conf;
515         size_t len;
516
517         list_for_each_entry(conf, &sptlrpc_confs, sc_list) {
518                 if (strcmp(conf->sc_fsname, fsname) == 0)
519                         return conf;
520         }
521
522         if (!create)
523                 return NULL;
524
525         conf = kzalloc(sizeof(*conf), GFP_NOFS);
526         if (!conf)
527                 return NULL;
528
529         len = strlcpy(conf->sc_fsname, fsname, sizeof(conf->sc_fsname));
530         if (len >= sizeof(conf->sc_fsname)) {
531                 kfree(conf);
532                 return NULL;
533         }
534         sptlrpc_rule_set_init(&conf->sc_rset);
535         INIT_LIST_HEAD(&conf->sc_tgts);
536         list_add(&conf->sc_list, &sptlrpc_confs);
537
538         CDEBUG(D_SEC, "create sptlrpc conf %s\n", conf->sc_fsname);
539         return conf;
540 }
541
542 /**
543  * caller must hold conf_lock already.
544  */
545 static int sptlrpc_conf_merge_rule(struct sptlrpc_conf *conf,
546                                    const char *target,
547                                    struct sptlrpc_rule *rule)
548 {
549         struct sptlrpc_conf_tgt *conf_tgt;
550         struct sptlrpc_rule_set *rule_set;
551
552         /* fsname == target means general rules for the whole fs */
553         if (strcmp(conf->sc_fsname, target) == 0) {
554                 rule_set = &conf->sc_rset;
555         } else {
556                 conf_tgt = sptlrpc_conf_get_tgt(conf, target, 1);
557                 if (conf_tgt) {
558                         rule_set = &conf_tgt->sct_rset;
559                 } else {
560                         CERROR("out of memory, can't merge rule!\n");
561                         return -ENOMEM;
562                 }
563         }
564
565         return sptlrpc_rule_set_merge(rule_set, rule);
566 }
567
568 /**
569  * process one LCFG_SPTLRPC_CONF record. if \a conf is NULL, we
570  * find one through the target name in the record inside conf_lock;
571  * otherwise means caller already hold conf_lock.
572  */
573 static int __sptlrpc_process_config(struct lustre_cfg *lcfg,
574                                     struct sptlrpc_conf *conf)
575 {
576         char *target, *param;
577         char fsname[MTI_NAME_MAXLEN];
578         struct sptlrpc_rule rule;
579         int rc;
580
581         target = lustre_cfg_string(lcfg, 1);
582         if (!target) {
583                 CERROR("missing target name\n");
584                 return -EINVAL;
585         }
586
587         param = lustre_cfg_string(lcfg, 2);
588         if (!param) {
589                 CERROR("missing parameter\n");
590                 return -EINVAL;
591         }
592
593         CDEBUG(D_SEC, "processing rule: %s.%s\n", target, param);
594
595         /* parse rule to make sure the format is correct */
596         if (strncmp(param, PARAM_SRPC_FLVR, sizeof(PARAM_SRPC_FLVR) - 1) != 0) {
597                 CERROR("Invalid sptlrpc parameter: %s\n", param);
598                 return -EINVAL;
599         }
600         param += sizeof(PARAM_SRPC_FLVR) - 1;
601
602         rc = sptlrpc_parse_rule(param, &rule);
603         if (rc)
604                 return -EINVAL;
605
606         if (!conf) {
607                 target2fsname(target, fsname, sizeof(fsname));
608
609                 mutex_lock(&sptlrpc_conf_lock);
610                 conf = sptlrpc_conf_get(fsname, 0);
611                 if (!conf) {
612                         CERROR("can't find conf\n");
613                         rc = -ENOMEM;
614                 } else {
615                         rc = sptlrpc_conf_merge_rule(conf, target, &rule);
616                 }
617                 mutex_unlock(&sptlrpc_conf_lock);
618         } else {
619                 LASSERT(mutex_is_locked(&sptlrpc_conf_lock));
620                 rc = sptlrpc_conf_merge_rule(conf, target, &rule);
621         }
622
623         if (rc == 0)
624                 conf->sc_modified++;
625
626         return rc;
627 }
628
629 int sptlrpc_process_config(struct lustre_cfg *lcfg)
630 {
631         return __sptlrpc_process_config(lcfg, NULL);
632 }
633 EXPORT_SYMBOL(sptlrpc_process_config);
634
635 static int logname2fsname(const char *logname, char *buf, int buflen)
636 {
637         char *ptr;
638         int len;
639
640         ptr = strrchr(logname, '-');
641         if (!ptr || strcmp(ptr, "-sptlrpc")) {
642                 CERROR("%s is not a sptlrpc config log\n", logname);
643                 return -EINVAL;
644         }
645
646         len = min((int)(ptr - logname), buflen - 1);
647
648         memcpy(buf, logname, len);
649         buf[len] = '\0';
650         return 0;
651 }
652
653 void sptlrpc_conf_log_update_begin(const char *logname)
654 {
655         struct sptlrpc_conf *conf;
656         char fsname[16];
657
658         if (logname2fsname(logname, fsname, sizeof(fsname)))
659                 return;
660
661         mutex_lock(&sptlrpc_conf_lock);
662
663         conf = sptlrpc_conf_get(fsname, 0);
664         if (conf) {
665                 if (conf->sc_local) {
666                         LASSERT(conf->sc_updated == 0);
667                         sptlrpc_conf_free_rsets(conf);
668                 }
669                 conf->sc_modified = 0;
670         }
671
672         mutex_unlock(&sptlrpc_conf_lock);
673 }
674 EXPORT_SYMBOL(sptlrpc_conf_log_update_begin);
675
676 /**
677  * mark a config log has been updated
678  */
679 void sptlrpc_conf_log_update_end(const char *logname)
680 {
681         struct sptlrpc_conf *conf;
682         char fsname[16];
683
684         if (logname2fsname(logname, fsname, sizeof(fsname)))
685                 return;
686
687         mutex_lock(&sptlrpc_conf_lock);
688
689         conf = sptlrpc_conf_get(fsname, 0);
690         if (conf) {
691                 /*
692                  * if original state is not updated, make sure the
693                  * modified counter > 0 to enforce updating local copy.
694                  */
695                 if (conf->sc_updated == 0)
696                         conf->sc_modified++;
697
698                 conf->sc_updated = 1;
699         }
700
701         mutex_unlock(&sptlrpc_conf_lock);
702 }
703 EXPORT_SYMBOL(sptlrpc_conf_log_update_end);
704
705 void sptlrpc_conf_log_start(const char *logname)
706 {
707         char fsname[16];
708
709         if (logname2fsname(logname, fsname, sizeof(fsname)))
710                 return;
711
712         mutex_lock(&sptlrpc_conf_lock);
713         sptlrpc_conf_get(fsname, 1);
714         mutex_unlock(&sptlrpc_conf_lock);
715 }
716 EXPORT_SYMBOL(sptlrpc_conf_log_start);
717
718 void sptlrpc_conf_log_stop(const char *logname)
719 {
720         struct sptlrpc_conf *conf;
721         char fsname[16];
722
723         if (logname2fsname(logname, fsname, sizeof(fsname)))
724                 return;
725
726         mutex_lock(&sptlrpc_conf_lock);
727         conf = sptlrpc_conf_get(fsname, 0);
728         if (conf)
729                 sptlrpc_conf_free(conf);
730         mutex_unlock(&sptlrpc_conf_lock);
731 }
732 EXPORT_SYMBOL(sptlrpc_conf_log_stop);
733
734 static inline void flavor_set_flags(struct sptlrpc_flavor *sf,
735                                     enum lustre_sec_part from,
736                                     enum lustre_sec_part to,
737                                     unsigned int fl_udesc)
738 {
739         /*
740          * null flavor doesn't need to set any flavor, and in fact
741          * we'd better not do that because everybody share a single sec.
742          */
743         if (sf->sf_rpc == SPTLRPC_FLVR_NULL)
744                 return;
745
746         if (from == LUSTRE_SP_MDT) {
747                 /* MDT->MDT; MDT->OST */
748                 sf->sf_flags |= PTLRPC_SEC_FL_ROOTONLY;
749         } else if (from == LUSTRE_SP_CLI && to == LUSTRE_SP_OST) {
750                 /* CLI->OST */
751                 sf->sf_flags |= PTLRPC_SEC_FL_ROOTONLY | PTLRPC_SEC_FL_BULK;
752         } else if (from == LUSTRE_SP_CLI && to == LUSTRE_SP_MDT) {
753                 /* CLI->MDT */
754                 if (fl_udesc && sf->sf_rpc != SPTLRPC_FLVR_NULL)
755                         sf->sf_flags |= PTLRPC_SEC_FL_UDESC;
756         }
757 }
758
759 void sptlrpc_conf_choose_flavor(enum lustre_sec_part from,
760                                 enum lustre_sec_part to,
761                                 struct obd_uuid *target,
762                                 lnet_nid_t nid,
763                                 struct sptlrpc_flavor *sf)
764 {
765         struct sptlrpc_conf *conf;
766         struct sptlrpc_conf_tgt *conf_tgt;
767         char name[MTI_NAME_MAXLEN];
768         int len, rc = 0;
769
770         target2fsname(target->uuid, name, sizeof(name));
771
772         mutex_lock(&sptlrpc_conf_lock);
773
774         conf = sptlrpc_conf_get(name, 0);
775         if (!conf)
776                 goto out;
777
778         /* convert uuid name (supposed end with _UUID) to target name */
779         len = strlen(target->uuid);
780         LASSERT(len > 5);
781         memcpy(name, target->uuid, len - 5);
782         name[len - 5] = '\0';
783
784         conf_tgt = sptlrpc_conf_get_tgt(conf, name, 0);
785         if (conf_tgt) {
786                 rc = sptlrpc_rule_set_choose(&conf_tgt->sct_rset,
787                                              from, to, nid, sf);
788                 if (rc)
789                         goto out;
790         }
791
792         rc = sptlrpc_rule_set_choose(&conf->sc_rset, from, to, nid, sf);
793 out:
794         mutex_unlock(&sptlrpc_conf_lock);
795
796         if (rc == 0)
797                 get_default_flavor(sf);
798
799         flavor_set_flags(sf, from, to, 1);
800 }
801
802 #define SEC_ADAPT_DELAY  (10)
803
804 /**
805  * called by client devices, notify the sptlrpc config has changed and
806  * do import_sec_adapt later.
807  */
808 void sptlrpc_conf_client_adapt(struct obd_device *obd)
809 {
810         struct obd_import *imp;
811
812         LASSERT(strcmp(obd->obd_type->typ_name, LUSTRE_MDC_NAME) == 0 ||
813                 strcmp(obd->obd_type->typ_name, LUSTRE_OSC_NAME) == 0);
814         CDEBUG(D_SEC, "obd %s\n", obd->u.cli.cl_target_uuid.uuid);
815
816         /* serialize with connect/disconnect import */
817         down_read_nested(&obd->u.cli.cl_sem, OBD_CLI_SEM_MDCOSC);
818
819         imp = obd->u.cli.cl_import;
820         if (imp) {
821                 spin_lock(&imp->imp_lock);
822                 if (imp->imp_sec)
823                         imp->imp_sec_expire = ktime_get_real_seconds() +
824                                 SEC_ADAPT_DELAY;
825                 spin_unlock(&imp->imp_lock);
826         }
827
828         up_read(&obd->u.cli.cl_sem);
829 }
830 EXPORT_SYMBOL(sptlrpc_conf_client_adapt);
831
832 int sptlrpc_conf_init(void)
833 {
834         mutex_init(&sptlrpc_conf_lock);
835         return 0;
836 }
837
838 void sptlrpc_conf_fini(void)
839 {
840         struct sptlrpc_conf *conf, *conf_next;
841
842         mutex_lock(&sptlrpc_conf_lock);
843         list_for_each_entry_safe(conf, conf_next, &sptlrpc_confs, sc_list) {
844                 sptlrpc_conf_free(conf);
845         }
846         LASSERT(list_empty(&sptlrpc_confs));
847         mutex_unlock(&sptlrpc_conf_lock);
848 }