1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40#define DEBUG_SUBSYSTEM S_CLASS
41#define D_MOUNT (D_SUPER | D_CONFIG)
42#define PRINT_CMD CDEBUG
43
44#include <obd.h>
45#include <lustre_compat.h>
46#include <obd_class.h>
47#include <uapi/linux/lustre/lustre_idl.h>
48#include <lustre_log.h>
49#include <lustre_disk.h>
50#include <uapi/linux/lustre/lustre_param.h>
51
52static DEFINE_SPINLOCK(client_lock);
53static struct module *client_mod;
54static int (*client_fill_super)(struct super_block *sb);
55static void (*kill_super_cb)(struct super_block *sb);
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71int lustre_process_log(struct super_block *sb, char *logname,
72 struct config_llog_instance *cfg)
73{
74 struct lustre_cfg *lcfg;
75 struct lustre_cfg_bufs *bufs;
76 struct lustre_sb_info *lsi = s2lsi(sb);
77 struct obd_device *mgc = lsi->lsi_mgc;
78 int rc;
79
80 LASSERT(mgc);
81 LASSERT(cfg);
82
83 bufs = kzalloc(sizeof(*bufs), GFP_NOFS);
84 if (!bufs)
85 return -ENOMEM;
86
87
88 lustre_cfg_bufs_reset(bufs, mgc->obd_name);
89 lustre_cfg_bufs_set_string(bufs, 1, logname);
90 lustre_cfg_bufs_set(bufs, 2, cfg, sizeof(*cfg));
91 lustre_cfg_bufs_set(bufs, 3, &sb, sizeof(sb));
92 lcfg = kzalloc(lustre_cfg_len(bufs->lcfg_bufcount, bufs->lcfg_buflen),
93 GFP_NOFS);
94 if (!lcfg) {
95 rc = -ENOMEM;
96 goto out;
97 }
98 lustre_cfg_init(lcfg, LCFG_LOG_START, bufs);
99
100 rc = obd_process_config(mgc, sizeof(*lcfg), lcfg);
101 kfree(lcfg);
102out:
103 kfree(bufs);
104
105 if (rc == -EINVAL)
106 LCONSOLE_ERROR_MSG(0x15b, "%s: The configuration from log '%s' failed from the MGS (%d). Make sure this client and the MGS are running compatible versions of Lustre.\n",
107 mgc->obd_name, logname, rc);
108
109 else if (rc)
110 LCONSOLE_ERROR_MSG(0x15c, "%s: The configuration from log '%s' failed (%d). This may be the result of communication errors between this node and the MGS, a bad configuration, or other errors. See the syslog for more information.\n",
111 mgc->obd_name, logname,
112 rc);
113
114
115 return rc;
116}
117EXPORT_SYMBOL(lustre_process_log);
118
119
120int lustre_end_log(struct super_block *sb, char *logname,
121 struct config_llog_instance *cfg)
122{
123 struct lustre_cfg *lcfg;
124 struct lustre_cfg_bufs bufs;
125 struct lustre_sb_info *lsi = s2lsi(sb);
126 struct obd_device *mgc = lsi->lsi_mgc;
127 int rc;
128
129 if (!mgc)
130 return -ENOENT;
131
132
133 lustre_cfg_bufs_reset(&bufs, mgc->obd_name);
134 lustre_cfg_bufs_set_string(&bufs, 1, logname);
135 if (cfg)
136 lustre_cfg_bufs_set(&bufs, 2, cfg, sizeof(*cfg));
137 lcfg = kzalloc(lustre_cfg_len(bufs.lcfg_bufcount, bufs.lcfg_buflen),
138 GFP_NOFS);
139 if (!lcfg)
140 return -ENOMEM;
141 lustre_cfg_init(lcfg, LCFG_LOG_END, &bufs);
142
143 rc = obd_process_config(mgc, sizeof(*lcfg), lcfg);
144 kfree(lcfg);
145 return rc;
146}
147EXPORT_SYMBOL(lustre_end_log);
148
149
150
151
152
153
154static int do_lcfg(char *cfgname, lnet_nid_t nid, int cmd,
155 char *s1, char *s2, char *s3, char *s4)
156{
157 struct lustre_cfg_bufs bufs;
158 struct lustre_cfg *lcfg = NULL;
159 int rc;
160
161 CDEBUG(D_TRACE, "lcfg %s %#x %s %s %s %s\n", cfgname,
162 cmd, s1, s2, s3, s4);
163
164 lustre_cfg_bufs_reset(&bufs, cfgname);
165 if (s1)
166 lustre_cfg_bufs_set_string(&bufs, 1, s1);
167 if (s2)
168 lustre_cfg_bufs_set_string(&bufs, 2, s2);
169 if (s3)
170 lustre_cfg_bufs_set_string(&bufs, 3, s3);
171 if (s4)
172 lustre_cfg_bufs_set_string(&bufs, 4, s4);
173
174 lcfg = kzalloc(lustre_cfg_len(bufs.lcfg_bufcount, bufs.lcfg_buflen),
175 GFP_NOFS);
176 if (!lcfg)
177 return -ENOMEM;
178 lustre_cfg_init(lcfg, cmd, &bufs);
179 lcfg->lcfg_nid = nid;
180 rc = class_process_config(lcfg);
181 kfree(lcfg);
182 return rc;
183}
184
185
186
187
188static int lustre_start_simple(char *obdname, char *type, char *uuid,
189 char *s1, char *s2, char *s3, char *s4)
190{
191 int rc;
192
193 CDEBUG(D_MOUNT, "Starting obd %s (typ=%s)\n", obdname, type);
194
195 rc = do_lcfg(obdname, 0, LCFG_ATTACH, type, uuid, NULL, NULL);
196 if (rc) {
197 CERROR("%s attach error %d\n", obdname, rc);
198 return rc;
199 }
200 rc = do_lcfg(obdname, 0, LCFG_SETUP, s1, s2, s3, s4);
201 if (rc) {
202 CERROR("%s setup error %d\n", obdname, rc);
203 do_lcfg(obdname, 0, LCFG_DETACH, NULL, NULL, NULL, NULL);
204 }
205 return rc;
206}
207
208static DEFINE_MUTEX(mgc_start_lock);
209
210
211
212
213
214
215
216int lustre_start_mgc(struct super_block *sb)
217{
218 struct obd_connect_data *data = NULL;
219 struct lustre_sb_info *lsi = s2lsi(sb);
220 struct obd_device *obd;
221 struct obd_export *exp;
222 struct obd_uuid *uuid;
223 class_uuid_t uuidc;
224 lnet_nid_t nid;
225 char nidstr[LNET_NIDSTR_SIZE];
226 char *mgcname = NULL, *niduuid = NULL, *mgssec = NULL;
227 char *ptr;
228 int rc = 0, i = 0, j;
229
230 LASSERT(lsi->lsi_lmd);
231
232
233 ptr = lsi->lsi_lmd->lmd_dev;
234 if (class_parse_nid(ptr, &nid, &ptr) == 0)
235 i++;
236 if (i == 0) {
237 CERROR("No valid MGS nids found.\n");
238 return -EINVAL;
239 }
240
241 mutex_lock(&mgc_start_lock);
242
243 libcfs_nid2str_r(nid, nidstr, sizeof(nidstr));
244 mgcname = kasprintf(GFP_NOFS,
245 "%s%s", LUSTRE_MGC_OBDNAME, nidstr);
246 niduuid = kasprintf(GFP_NOFS, "%s_%x", mgcname, 0);
247 if (!mgcname || !niduuid) {
248 rc = -ENOMEM;
249 goto out_free;
250 }
251
252 mgssec = lsi->lsi_lmd->lmd_mgssec ? lsi->lsi_lmd->lmd_mgssec : "";
253
254 data = kzalloc(sizeof(*data), GFP_NOFS);
255 if (!data) {
256 rc = -ENOMEM;
257 goto out_free;
258 }
259
260 obd = class_name2obd(mgcname);
261 if (obd && !obd->obd_stopping) {
262 int recov_bk;
263
264 rc = obd_set_info_async(NULL, obd->obd_self_export,
265 strlen(KEY_MGSSEC), KEY_MGSSEC,
266 strlen(mgssec), mgssec, NULL);
267 if (rc)
268 goto out_free;
269
270
271 atomic_inc(&obd->u.cli.cl_mgc_refcount);
272
273
274 if (lmd_is_client(lsi->lsi_lmd)) {
275 int has_ir;
276 int vallen = sizeof(*data);
277 __u32 *flags = &lsi->lsi_lmd->lmd_flags;
278
279 rc = obd_get_info(NULL, obd->obd_self_export,
280 strlen(KEY_CONN_DATA), KEY_CONN_DATA,
281 &vallen, data);
282 LASSERT(rc == 0);
283 has_ir = OCD_HAS_FLAG(data, IMP_RECOV);
284 if (has_ir ^ !(*flags & LMD_FLG_NOIR)) {
285
286 LCONSOLE_WARN(
287 "Trying to mount a client with IR setting not compatible with current mgc. Force to use current mgc setting that is IR %s.\n",
288 has_ir ? "enabled" : "disabled");
289 if (has_ir)
290 *flags &= ~LMD_FLG_NOIR;
291 else
292 *flags |= LMD_FLG_NOIR;
293 }
294 }
295
296 recov_bk = 0;
297
298
299
300
301
302
303 recov_bk++;
304 CDEBUG(D_MOUNT, "%s: Set MGC reconnect %d\n", mgcname,
305 recov_bk);
306 rc = obd_set_info_async(NULL, obd->obd_self_export,
307 sizeof(KEY_INIT_RECOV_BACKUP),
308 KEY_INIT_RECOV_BACKUP,
309 sizeof(recov_bk), &recov_bk, NULL);
310 rc = 0;
311 goto out;
312 }
313
314 CDEBUG(D_MOUNT, "Start MGC '%s'\n", mgcname);
315
316
317 i = 0;
318
319 ptr = lsi->lsi_lmd->lmd_dev;
320 while (class_parse_nid(ptr, &nid, &ptr) == 0) {
321 rc = do_lcfg(mgcname, nid,
322 LCFG_ADD_UUID, niduuid, NULL, NULL, NULL);
323 if (!rc)
324 i++;
325
326 if (*ptr == ':')
327 break;
328 }
329 if (i == 0) {
330 CERROR("No valid MGS nids found.\n");
331 rc = -EINVAL;
332 goto out_free;
333 }
334 lsi->lsi_lmd->lmd_mgs_failnodes = 1;
335
336
337 uuid = kzalloc(sizeof(*uuid), GFP_NOFS);
338 if (!uuid) {
339 rc = -ENOMEM;
340 goto out_free;
341 }
342
343 ll_generate_random_uuid(uuidc);
344 class_uuid_unparse(uuidc, uuid);
345
346
347 rc = lustre_start_simple(mgcname, LUSTRE_MGC_NAME,
348 (char *)uuid->uuid, LUSTRE_MGS_OBDNAME,
349 niduuid, NULL, NULL);
350 kfree(uuid);
351 if (rc)
352 goto out_free;
353
354
355 i = 1;
356 while (ptr && ((*ptr == ':' ||
357 class_find_param(ptr, PARAM_MGSNODE, &ptr) == 0))) {
358
359 sprintf(niduuid, "%s_%x", mgcname, i);
360 j = 0;
361 while (class_parse_nid_quiet(ptr, &nid, &ptr) == 0) {
362 rc = do_lcfg(mgcname, nid, LCFG_ADD_UUID, niduuid,
363 NULL, NULL, NULL);
364 if (!rc)
365 ++j;
366 if (*ptr == ':')
367 break;
368 }
369 if (j > 0) {
370 rc = do_lcfg(mgcname, 0, LCFG_ADD_CONN,
371 niduuid, NULL, NULL, NULL);
372 if (!rc)
373 i++;
374 } else {
375
376 break;
377 }
378 }
379 lsi->lsi_lmd->lmd_mgs_failnodes = i;
380
381 obd = class_name2obd(mgcname);
382 if (!obd) {
383 CERROR("Can't find mgcobd %s\n", mgcname);
384 rc = -ENOTCONN;
385 goto out_free;
386 }
387
388 rc = obd_set_info_async(NULL, obd->obd_self_export,
389 strlen(KEY_MGSSEC), KEY_MGSSEC,
390 strlen(mgssec), mgssec, NULL);
391 if (rc)
392 goto out_free;
393
394
395
396
397 atomic_set(&obd->u.cli.cl_mgc_refcount, 1);
398
399
400 data->ocd_connect_flags = OBD_CONNECT_VERSION | OBD_CONNECT_AT |
401 OBD_CONNECT_FULL20 | OBD_CONNECT_IMP_RECOV |
402 OBD_CONNECT_LVB_TYPE | OBD_CONNECT_BULK_MBITS;
403
404#if OBD_OCD_VERSION(3, 0, 53, 0) > LUSTRE_VERSION_CODE
405 data->ocd_connect_flags |= OBD_CONNECT_MNE_SWAB;
406#endif
407
408 if (lmd_is_client(lsi->lsi_lmd) &&
409 lsi->lsi_lmd->lmd_flags & LMD_FLG_NOIR)
410 data->ocd_connect_flags &= ~OBD_CONNECT_IMP_RECOV;
411 data->ocd_version = LUSTRE_VERSION_CODE;
412 rc = obd_connect(NULL, &exp, obd, &obd->obd_uuid, data, NULL);
413 if (rc) {
414 CERROR("connect failed %d\n", rc);
415 goto out;
416 }
417
418 obd->u.cli.cl_mgc_mgsexp = exp;
419
420out:
421
422
423
424 lsi->lsi_mgc = obd;
425out_free:
426 mutex_unlock(&mgc_start_lock);
427
428 kfree(data);
429 kfree(mgcname);
430 kfree(niduuid);
431 return rc;
432}
433
434static int lustre_stop_mgc(struct super_block *sb)
435{
436 struct lustre_sb_info *lsi = s2lsi(sb);
437 struct obd_device *obd;
438 char *niduuid = NULL, *ptr = NULL;
439 int i, rc = 0, len = 0;
440
441 if (!lsi)
442 return -ENOENT;
443 obd = lsi->lsi_mgc;
444 if (!obd)
445 return -ENOENT;
446 lsi->lsi_mgc = NULL;
447
448 mutex_lock(&mgc_start_lock);
449 LASSERT(atomic_read(&obd->u.cli.cl_mgc_refcount) > 0);
450 if (!atomic_dec_and_test(&obd->u.cli.cl_mgc_refcount)) {
451
452
453
454 CDEBUG(D_MOUNT, "mgc still has %d references.\n",
455 atomic_read(&obd->u.cli.cl_mgc_refcount));
456 rc = -EBUSY;
457 goto out;
458 }
459
460
461
462
463 obd->obd_no_recov = 1;
464
465 if (obd->u.cli.cl_mgc_mgsexp) {
466
467
468
469 rc = obd_disconnect(obd->u.cli.cl_mgc_mgsexp);
470 if (rc)
471 CDEBUG(D_MOUNT, "disconnect failed %d\n", rc);
472 }
473
474
475 len = strlen(obd->obd_name) + 6;
476 niduuid = kzalloc(len, GFP_NOFS);
477 if (niduuid) {
478 strcpy(niduuid, obd->obd_name);
479 ptr = niduuid + strlen(niduuid);
480 }
481
482 rc = class_manual_cleanup(obd);
483 if (rc)
484 goto out;
485
486
487 if (!niduuid) {
488 rc = -ENOMEM;
489 goto out;
490 }
491
492 for (i = 0; i < lsi->lsi_lmd->lmd_mgs_failnodes; i++) {
493 sprintf(ptr, "_%x", i);
494 rc = do_lcfg(LUSTRE_MGC_OBDNAME, 0, LCFG_DEL_UUID,
495 niduuid, NULL, NULL, NULL);
496 if (rc)
497 CERROR("del MDC UUID %s failed: rc = %d\n",
498 niduuid, rc);
499 }
500out:
501 kfree(niduuid);
502
503
504 mutex_unlock(&mgc_start_lock);
505 return rc;
506}
507
508
509
510static struct lustre_sb_info *lustre_init_lsi(struct super_block *sb)
511{
512 struct lustre_sb_info *lsi;
513
514 lsi = kzalloc(sizeof(*lsi), GFP_NOFS);
515 if (!lsi)
516 return NULL;
517 lsi->lsi_lmd = kzalloc(sizeof(*lsi->lsi_lmd), GFP_NOFS);
518 if (!lsi->lsi_lmd) {
519 kfree(lsi);
520 return NULL;
521 }
522
523 lsi->lsi_lmd->lmd_exclude_count = 0;
524 lsi->lsi_lmd->lmd_recovery_time_soft = 0;
525 lsi->lsi_lmd->lmd_recovery_time_hard = 0;
526 s2lsi_nocast(sb) = lsi;
527
528 atomic_set(&lsi->lsi_mounts, 1);
529
530
531 lsi->lsi_flags = LSI_UMOUNT_FAILOVER;
532
533 return lsi;
534}
535
536static int lustre_free_lsi(struct super_block *sb)
537{
538 struct lustre_sb_info *lsi = s2lsi(sb);
539
540 CDEBUG(D_MOUNT, "Freeing lsi %p\n", lsi);
541
542
543 LASSERT(atomic_read(&lsi->lsi_mounts) == 0);
544
545 if (lsi->lsi_lmd) {
546 kfree(lsi->lsi_lmd->lmd_dev);
547 kfree(lsi->lsi_lmd->lmd_profile);
548 kfree(lsi->lsi_lmd->lmd_mgssec);
549 kfree(lsi->lsi_lmd->lmd_opts);
550 if (lsi->lsi_lmd->lmd_exclude_count)
551 kfree(lsi->lsi_lmd->lmd_exclude);
552 kfree(lsi->lsi_lmd->lmd_mgs);
553 kfree(lsi->lsi_lmd->lmd_osd_type);
554 kfree(lsi->lsi_lmd->lmd_params);
555
556 kfree(lsi->lsi_lmd);
557 }
558
559 LASSERT(!lsi->lsi_llsbi);
560 kfree(lsi);
561 s2lsi_nocast(sb) = NULL;
562
563 return 0;
564}
565
566
567
568
569static int lustre_put_lsi(struct super_block *sb)
570{
571 struct lustre_sb_info *lsi = s2lsi(sb);
572
573 CDEBUG(D_MOUNT, "put %p %d\n", sb, atomic_read(&lsi->lsi_mounts));
574 if (atomic_dec_and_test(&lsi->lsi_mounts)) {
575 lustre_free_lsi(sb);
576 return 1;
577 }
578 return 0;
579}
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597static int server_name2fsname(const char *svname, char *fsname,
598 const char **endptr)
599{
600 const char *dash;
601
602 dash = svname + strnlen(svname, 8);
603 for (; dash > svname && *dash != '-' && *dash != ':'; dash--)
604 ;
605 if (dash == svname)
606 return -EINVAL;
607
608 if (fsname) {
609 strncpy(fsname, svname, dash - svname);
610 fsname[dash - svname] = '\0';
611 }
612
613 if (endptr)
614 *endptr = dash;
615
616 return 0;
617}
618
619
620
621
622
623
624static int server_name2index(const char *svname, __u32 *idx,
625 const char **endptr)
626{
627 unsigned long index;
628 int rc;
629 const char *dash;
630
631
632 rc = server_name2fsname(svname, NULL, &dash);
633 if (rc != 0)
634 return rc;
635
636 dash++;
637
638 if (strncmp(dash, "MDT", 3) == 0)
639 rc = LDD_F_SV_TYPE_MDT;
640 else if (strncmp(dash, "OST", 3) == 0)
641 rc = LDD_F_SV_TYPE_OST;
642 else
643 return -EINVAL;
644
645 dash += 3;
646
647 if (strncmp(dash, "all", 3) == 0) {
648 if (endptr)
649 *endptr = dash + 3;
650 return rc | LDD_F_SV_ALL;
651 }
652
653 index = simple_strtoul(dash, (char **)endptr, 16);
654 if (idx)
655 *idx = index;
656
657
658 if (endptr && strncmp(LUSTRE_MDC_NAME, *endptr + 1,
659 sizeof(LUSTRE_MDC_NAME) - 1) == 0)
660 *endptr += sizeof(LUSTRE_MDC_NAME);
661
662 return rc;
663}
664
665
666
667
668int lustre_common_put_super(struct super_block *sb)
669{
670 int rc;
671
672 CDEBUG(D_MOUNT, "dropping sb %p\n", sb);
673
674
675 rc = lustre_stop_mgc(sb);
676 if (rc && (rc != -ENOENT)) {
677 if (rc != -EBUSY) {
678 CERROR("Can't stop MGC: %d\n", rc);
679 return rc;
680 }
681
682
683
684 CDEBUG(D_MOUNT, "MGC still in use\n");
685 }
686
687 lustre_put_lsi(sb);
688 return rc;
689}
690EXPORT_SYMBOL(lustre_common_put_super);
691
692static void lmd_print(struct lustre_mount_data *lmd)
693{
694 int i;
695
696 PRINT_CMD(D_MOUNT, " mount data:\n");
697 if (lmd_is_client(lmd))
698 PRINT_CMD(D_MOUNT, "profile: %s\n", lmd->lmd_profile);
699 PRINT_CMD(D_MOUNT, "device: %s\n", lmd->lmd_dev);
700 PRINT_CMD(D_MOUNT, "flags: %x\n", lmd->lmd_flags);
701
702 if (lmd->lmd_opts)
703 PRINT_CMD(D_MOUNT, "options: %s\n", lmd->lmd_opts);
704
705 if (lmd->lmd_recovery_time_soft)
706 PRINT_CMD(D_MOUNT, "recovery time soft: %d\n",
707 lmd->lmd_recovery_time_soft);
708
709 if (lmd->lmd_recovery_time_hard)
710 PRINT_CMD(D_MOUNT, "recovery time hard: %d\n",
711 lmd->lmd_recovery_time_hard);
712
713 for (i = 0; i < lmd->lmd_exclude_count; i++) {
714 PRINT_CMD(D_MOUNT, "exclude %d: OST%04x\n", i,
715 lmd->lmd_exclude[i]);
716 }
717}
718
719
720int lustre_check_exclusion(struct super_block *sb, char *svname)
721{
722 struct lustre_sb_info *lsi = s2lsi(sb);
723 struct lustre_mount_data *lmd = lsi->lsi_lmd;
724 __u32 index;
725 int i, rc;
726
727 rc = server_name2index(svname, &index, NULL);
728 if (rc != LDD_F_SV_TYPE_OST)
729
730 return 0;
731
732 CDEBUG(D_MOUNT, "Check exclusion %s (%d) in %d of %s\n", svname,
733 index, lmd->lmd_exclude_count, lmd->lmd_dev);
734
735 for (i = 0; i < lmd->lmd_exclude_count; i++) {
736 if (index == lmd->lmd_exclude[i]) {
737 CWARN("Excluding %s (on exclusion list)\n", svname);
738 return 1;
739 }
740 }
741 return 0;
742}
743
744
745static int lmd_make_exclusion(struct lustre_mount_data *lmd, const char *ptr)
746{
747 const char *s1 = ptr, *s2;
748 __u32 index = 0, *exclude_list;
749 int rc = 0, devmax;
750
751
752
753
754
755 devmax = strlen(ptr) / 8 + 1;
756
757
758 exclude_list = kcalloc(devmax, sizeof(index), GFP_NOFS);
759 if (!exclude_list)
760 return -ENOMEM;
761
762
763 while (*s1 && *s1 != ' ' && *s1 != ',') {
764 s1++;
765 rc = server_name2index(s1, &index, &s2);
766 if (rc < 0) {
767 CERROR("Can't parse server name '%s': rc = %d\n",
768 s1, rc);
769 break;
770 }
771 if (rc == LDD_F_SV_TYPE_OST)
772 exclude_list[lmd->lmd_exclude_count++] = index;
773 else
774 CDEBUG(D_MOUNT, "ignoring exclude %.*s: type = %#x\n",
775 (uint)(s2 - s1), s1, rc);
776 s1 = s2;
777
778
779
780 if (lmd->lmd_exclude_count >= devmax)
781 break;
782 }
783 if (rc >= 0)
784 rc = 0;
785
786 if (lmd->lmd_exclude_count) {
787
788 lmd->lmd_exclude = kcalloc(lmd->lmd_exclude_count,
789 sizeof(index), GFP_NOFS);
790 if (lmd->lmd_exclude) {
791 memcpy(lmd->lmd_exclude, exclude_list,
792 sizeof(index) * lmd->lmd_exclude_count);
793 } else {
794 rc = -ENOMEM;
795 lmd->lmd_exclude_count = 0;
796 }
797 }
798 kfree(exclude_list);
799 return rc;
800}
801
802static int lmd_parse_mgssec(struct lustre_mount_data *lmd, char *ptr)
803{
804 char *tail;
805 int length;
806
807 kfree(lmd->lmd_mgssec);
808 lmd->lmd_mgssec = NULL;
809
810 tail = strchr(ptr, ',');
811 if (!tail)
812 length = strlen(ptr);
813 else
814 length = tail - ptr;
815
816 lmd->lmd_mgssec = kzalloc(length + 1, GFP_NOFS);
817 if (!lmd->lmd_mgssec)
818 return -ENOMEM;
819
820 memcpy(lmd->lmd_mgssec, ptr, length);
821 lmd->lmd_mgssec[length] = '\0';
822 return 0;
823}
824
825static int lmd_parse_string(char **handle, char *ptr)
826{
827 char *tail;
828 int length;
829
830 if (!handle || !ptr)
831 return -EINVAL;
832
833 kfree(*handle);
834 *handle = NULL;
835
836 tail = strchr(ptr, ',');
837 if (!tail)
838 length = strlen(ptr);
839 else
840 length = tail - ptr;
841
842 *handle = kzalloc(length + 1, GFP_NOFS);
843 if (!*handle)
844 return -ENOMEM;
845
846 memcpy(*handle, ptr, length);
847 (*handle)[length] = '\0';
848
849 return 0;
850}
851
852
853static int lmd_parse_mgs(struct lustre_mount_data *lmd, char **ptr)
854{
855 lnet_nid_t nid;
856 char *tail = *ptr;
857 char *mgsnid;
858 int length;
859 int oldlen = 0;
860
861
862 while (class_parse_nid_quiet(tail, &nid, &tail) == 0)
863 ;
864 length = tail - *ptr;
865 if (length == 0) {
866 LCONSOLE_ERROR_MSG(0x159, "Can't parse NID '%s'\n", *ptr);
867 return -EINVAL;
868 }
869
870 if (lmd->lmd_mgs)
871 oldlen = strlen(lmd->lmd_mgs) + 1;
872
873 mgsnid = kzalloc(oldlen + length + 1, GFP_NOFS);
874 if (!mgsnid)
875 return -ENOMEM;
876
877 if (lmd->lmd_mgs) {
878
879 memcpy(mgsnid, lmd->lmd_mgs, oldlen);
880 mgsnid[oldlen - 1] = ':';
881 kfree(lmd->lmd_mgs);
882 }
883 memcpy(mgsnid + oldlen, *ptr, length);
884 mgsnid[oldlen + length] = '\0';
885 lmd->lmd_mgs = mgsnid;
886 *ptr = tail;
887
888 return 0;
889}
890
891
892
893
894
895static int lmd_parse(char *options, struct lustre_mount_data *lmd)
896{
897 char *s1, *s2, *devname = NULL;
898 struct lustre_mount_data *raw = (struct lustre_mount_data *)options;
899 int rc = 0;
900
901 LASSERT(lmd);
902 if (!options) {
903 LCONSOLE_ERROR_MSG(0x162, "Missing mount data: check that /sbin/mount.lustre is installed.\n");
904 return -EINVAL;
905 }
906
907
908 if ((raw->lmd_magic & 0xffffff00) == (LMD_MAGIC & 0xffffff00)) {
909 LCONSOLE_ERROR_MSG(0x163, "You're using an old version of /sbin/mount.lustre. Please install version %s\n",
910 LUSTRE_VERSION_STRING);
911 return -EINVAL;
912 }
913 lmd->lmd_magic = LMD_MAGIC;
914
915 lmd->lmd_params = kzalloc(LMD_PARAMS_MAXLEN, GFP_NOFS);
916 if (!lmd->lmd_params)
917 return -ENOMEM;
918 lmd->lmd_params[0] = '\0';
919
920
921
922 s1 = options;
923 while (*s1) {
924 int clear = 0;
925 int time_min = OBD_RECOVERY_TIME_MIN;
926 char *s3;
927
928
929 while (*s1 == ' ' || *s1 == ',')
930 s1++;
931 s3 = s1;
932
933
934
935
936
937
938
939
940 if (strncmp(s1, "abort_recov", 11) == 0) {
941 lmd->lmd_flags |= LMD_FLG_ABORT_RECOV;
942 clear++;
943 } else if (strncmp(s1, "recovery_time_soft=", 19) == 0) {
944 lmd->lmd_recovery_time_soft = max_t(int,
945 simple_strtoul(s1 + 19, NULL, 10), time_min);
946 clear++;
947 } else if (strncmp(s1, "recovery_time_hard=", 19) == 0) {
948 lmd->lmd_recovery_time_hard = max_t(int,
949 simple_strtoul(s1 + 19, NULL, 10), time_min);
950 clear++;
951 } else if (strncmp(s1, "noir", 4) == 0) {
952 lmd->lmd_flags |= LMD_FLG_NOIR;
953 clear++;
954 } else if (strncmp(s1, "nosvc", 5) == 0) {
955 lmd->lmd_flags |= LMD_FLG_NOSVC;
956 clear++;
957 } else if (strncmp(s1, "nomgs", 5) == 0) {
958 lmd->lmd_flags |= LMD_FLG_NOMGS;
959 clear++;
960 } else if (strncmp(s1, "noscrub", 7) == 0) {
961 lmd->lmd_flags |= LMD_FLG_NOSCRUB;
962 clear++;
963 } else if (strncmp(s1, PARAM_MGSNODE,
964 sizeof(PARAM_MGSNODE) - 1) == 0) {
965 s2 = s1 + sizeof(PARAM_MGSNODE) - 1;
966
967
968
969 rc = lmd_parse_mgs(lmd, &s2);
970 if (rc)
971 goto invalid;
972 clear++;
973 } else if (strncmp(s1, "writeconf", 9) == 0) {
974 lmd->lmd_flags |= LMD_FLG_WRITECONF;
975 clear++;
976 } else if (strncmp(s1, "update", 6) == 0) {
977 lmd->lmd_flags |= LMD_FLG_UPDATE;
978 clear++;
979 } else if (strncmp(s1, "virgin", 6) == 0) {
980 lmd->lmd_flags |= LMD_FLG_VIRGIN;
981 clear++;
982 } else if (strncmp(s1, "noprimnode", 10) == 0) {
983 lmd->lmd_flags |= LMD_FLG_NO_PRIMNODE;
984 clear++;
985 } else if (strncmp(s1, "mgssec=", 7) == 0) {
986 rc = lmd_parse_mgssec(lmd, s1 + 7);
987 if (rc)
988 goto invalid;
989 s3 = s2;
990 clear++;
991
992 } else if (strncmp(s1, "exclude=", 8) == 0) {
993 rc = lmd_make_exclusion(lmd, s1 + 7);
994 if (rc)
995 goto invalid;
996 clear++;
997 } else if (strncmp(s1, "mgs", 3) == 0) {
998
999 lmd->lmd_flags |= LMD_FLG_MGS;
1000 clear++;
1001 } else if (strncmp(s1, "svname=", 7) == 0) {
1002 rc = lmd_parse_string(&lmd->lmd_profile, s1 + 7);
1003 if (rc)
1004 goto invalid;
1005 clear++;
1006 } else if (strncmp(s1, "param=", 6) == 0) {
1007 size_t length, params_length;
1008 char *tail = strchr(s1 + 6, ',');
1009
1010 if (!tail) {
1011 length = strlen(s1);
1012 } else {
1013 lnet_nid_t nid;
1014 char *param_str = tail + 1;
1015 int supplementary = 1;
1016
1017 while (!class_parse_nid_quiet(param_str, &nid,
1018 ¶m_str)) {
1019 supplementary = 0;
1020 }
1021 length = param_str - s1 - supplementary;
1022 }
1023 length -= 6;
1024 params_length = strlen(lmd->lmd_params);
1025 if (params_length + length + 1 >= LMD_PARAMS_MAXLEN)
1026 return -E2BIG;
1027 strncat(lmd->lmd_params, s1 + 6, length);
1028 lmd->lmd_params[params_length + length] = '\0';
1029 strlcat(lmd->lmd_params, " ", LMD_PARAMS_MAXLEN);
1030 s3 = s1 + 6 + length;
1031 clear++;
1032 } else if (strncmp(s1, "osd=", 4) == 0) {
1033 rc = lmd_parse_string(&lmd->lmd_osd_type, s1 + 4);
1034 if (rc)
1035 goto invalid;
1036 clear++;
1037 }
1038
1039
1040
1041 else if (strncmp(s1, "device=", 7) == 0) {
1042 devname = s1 + 7;
1043
1044
1045
1046 *s1 = '\0';
1047 break;
1048 }
1049
1050
1051 s2 = strchr(s1, ',');
1052 if (!s2) {
1053 if (clear)
1054 *s1 = '\0';
1055 break;
1056 }
1057 s2++;
1058 if (clear)
1059 memmove(s1, s2, strlen(s2) + 1);
1060 else
1061 s1 = s2;
1062 }
1063
1064 if (!devname) {
1065 LCONSOLE_ERROR_MSG(0x164, "Can't find the device name (need mount option 'device=...')\n");
1066 goto invalid;
1067 }
1068
1069 s1 = strstr(devname, ":/");
1070 if (s1) {
1071 ++s1;
1072 lmd->lmd_flags |= LMD_FLG_CLIENT;
1073
1074 while (*++s1 == '/')
1075 ;
1076
1077 lmd->lmd_profile = kasprintf(GFP_NOFS, "%s-client", s1);
1078 if (!lmd->lmd_profile)
1079 return -ENOMEM;
1080 }
1081
1082
1083 lmd->lmd_dev = kzalloc(strlen(devname) + 1, GFP_NOFS);
1084 if (!lmd->lmd_dev)
1085 return -ENOMEM;
1086 strcpy(lmd->lmd_dev, devname);
1087
1088
1089 s1 = options + strlen(options) - 1;
1090 while (s1 >= options && (*s1 == ',' || *s1 == ' '))
1091 *s1-- = 0;
1092 if (*options != 0) {
1093
1094 lmd->lmd_opts = kzalloc(strlen(options) + 1, GFP_NOFS);
1095 if (!lmd->lmd_opts)
1096 return -ENOMEM;
1097 strcpy(lmd->lmd_opts, options);
1098 }
1099
1100 lmd_print(lmd);
1101 lmd->lmd_magic = LMD_MAGIC;
1102
1103 return rc;
1104
1105invalid:
1106 CERROR("Bad mount options %s\n", options);
1107 return -EINVAL;
1108}
1109
1110
1111
1112
1113
1114
1115static int lustre_fill_super(struct super_block *sb, void *lmd2_data, int silent)
1116{
1117 struct lustre_mount_data *lmd;
1118 struct lustre_sb_info *lsi;
1119 int rc;
1120
1121 CDEBUG(D_MOUNT | D_VFSTRACE, "VFS Op: sb %p\n", sb);
1122
1123 lsi = lustre_init_lsi(sb);
1124 if (!lsi)
1125 return -ENOMEM;
1126 lmd = lsi->lsi_lmd;
1127
1128
1129
1130
1131
1132 lockdep_off();
1133
1134
1135
1136
1137 obd_zombie_barrier();
1138
1139
1140 if (lmd_parse(lmd2_data, lmd)) {
1141 lustre_put_lsi(sb);
1142 rc = -EINVAL;
1143 goto out;
1144 }
1145
1146 if (lmd_is_client(lmd)) {
1147 bool have_client = false;
1148 CDEBUG(D_MOUNT, "Mounting client %s\n", lmd->lmd_profile);
1149 if (!client_fill_super)
1150 request_module("lustre");
1151 spin_lock(&client_lock);
1152 if (client_fill_super && try_module_get(client_mod))
1153 have_client = true;
1154 spin_unlock(&client_lock);
1155 if (!have_client) {
1156 LCONSOLE_ERROR_MSG(0x165, "Nothing registered for client mount! Is the 'lustre' module loaded?\n");
1157 lustre_put_lsi(sb);
1158 rc = -ENODEV;
1159 } else {
1160 rc = lustre_start_mgc(sb);
1161 if (rc) {
1162 lustre_common_put_super(sb);
1163 goto out;
1164 }
1165
1166
1167 rc = (*client_fill_super)(sb);
1168
1169
1170 module_put(client_mod);
1171 }
1172 } else {
1173 CERROR("This is client-side-only module, cannot handle server mount.\n");
1174 rc = -EINVAL;
1175 }
1176
1177
1178
1179
1180 goto out;
1181out:
1182 if (rc) {
1183 CERROR("Unable to mount %s (%d)\n",
1184 s2lsi(sb) ? lmd->lmd_dev : "", rc);
1185 } else {
1186 CDEBUG(D_SUPER, "Mount %s complete\n",
1187 lmd->lmd_dev);
1188 }
1189 lockdep_on();
1190 return rc;
1191}
1192
1193
1194
1195
1196void lustre_register_super_ops(struct module *mod,
1197 int (*cfs)(struct super_block *sb),
1198 void (*ksc)(struct super_block *sb))
1199{
1200 spin_lock(&client_lock);
1201 client_mod = mod;
1202 client_fill_super = cfs;
1203 kill_super_cb = ksc;
1204 spin_unlock(&client_lock);
1205}
1206EXPORT_SYMBOL(lustre_register_super_ops);
1207
1208
1209static struct dentry *lustre_mount(struct file_system_type *fs_type, int flags,
1210 const char *devname, void *data)
1211{
1212 return mount_nodev(fs_type, flags, data, lustre_fill_super);
1213}
1214
1215static void lustre_kill_super(struct super_block *sb)
1216{
1217 struct lustre_sb_info *lsi = s2lsi(sb);
1218
1219 if (kill_super_cb && lsi)
1220 (*kill_super_cb)(sb);
1221
1222 kill_anon_super(sb);
1223}
1224
1225
1226
1227static struct file_system_type lustre_fs_type = {
1228 .owner = THIS_MODULE,
1229 .name = "lustre",
1230 .mount = lustre_mount,
1231 .kill_sb = lustre_kill_super,
1232 .fs_flags = FS_RENAME_DOES_D_MOVE,
1233};
1234MODULE_ALIAS_FS("lustre");
1235
1236int lustre_register_fs(void)
1237{
1238 return register_filesystem(&lustre_fs_type);
1239}
1240
1241int lustre_unregister_fs(void)
1242{
1243 return unregister_filesystem(&lustre_fs_type);
1244}
1245