diff options
author | Sage Weil <sage@newdream.net> | 2009-10-27 14:50:50 -0400 |
---|---|---|
committer | Sage Weil <sage@newdream.net> | 2009-10-27 14:57:03 -0400 |
commit | 6b8051855d983db8480ff1ea1b02ef2b49203c22 (patch) | |
tree | afb72be534ddd4c474a2ec9b7cf2ea5ab86799bc /fs/ceph/super.c | |
parent | e53c2fe075feda1fd4f009956ac026dc24c3a199 (diff) |
ceph: allocate and parse mount args before client instance
This simplifies much of the error handling during mount. It also means
that we have the mount args before client creation, and we can initialize
based on those options.
Signed-off-by: Sage Weil <sage@newdream.net>
Diffstat (limited to 'fs/ceph/super.c')
-rw-r--r-- | fs/ceph/super.c | 106 |
1 files changed, 48 insertions, 58 deletions
diff --git a/fs/ceph/super.c b/fs/ceph/super.c index b094f5003ef8..9b7815dfc035 100644 --- a/fs/ceph/super.c +++ b/fs/ceph/super.c | |||
@@ -110,7 +110,7 @@ static int ceph_syncfs(struct super_block *sb, int wait) | |||
110 | static int ceph_show_options(struct seq_file *m, struct vfsmount *mnt) | 110 | static int ceph_show_options(struct seq_file *m, struct vfsmount *mnt) |
111 | { | 111 | { |
112 | struct ceph_client *client = ceph_sb_to_client(mnt->mnt_sb); | 112 | struct ceph_client *client = ceph_sb_to_client(mnt->mnt_sb); |
113 | struct ceph_mount_args *args = &client->mount_args; | 113 | struct ceph_mount_args *args = client->mount_args; |
114 | 114 | ||
115 | if (args->flags & CEPH_OPT_FSID) | 115 | if (args->flags & CEPH_OPT_FSID) |
116 | seq_printf(m, ",fsidmajor=%llu,fsidminor%llu", | 116 | seq_printf(m, ",fsidmajor=%llu,fsidminor%llu", |
@@ -307,24 +307,24 @@ static match_table_t arg_tokens = { | |||
307 | }; | 307 | }; |
308 | 308 | ||
309 | 309 | ||
310 | static int parse_mount_args(struct ceph_client *client, | 310 | static struct ceph_mount_args *parse_mount_args(int flags, char *options, |
311 | int flags, char *options, const char *dev_name, | 311 | const char *dev_name, |
312 | const char **path) | 312 | const char **path) |
313 | { | 313 | { |
314 | struct ceph_mount_args *args = &client->mount_args; | 314 | struct ceph_mount_args *args; |
315 | const char *c; | 315 | const char *c; |
316 | int err; | 316 | int err = -ENOMEM; |
317 | substring_t argstr[MAX_OPT_ARGS]; | 317 | substring_t argstr[MAX_OPT_ARGS]; |
318 | int num_mon; | ||
319 | struct ceph_entity_addr *mon_addr; | ||
320 | int i; | ||
321 | 318 | ||
322 | dout("parse_mount_args dev_name '%s'\n", dev_name); | 319 | args = kzalloc(sizeof(*args), GFP_KERNEL); |
323 | memset(args, 0, sizeof(*args)); | 320 | if (!args) |
321 | return ERR_PTR(-ENOMEM); | ||
322 | args->mon_addr = kcalloc(CEPH_MAX_MON, sizeof(*args->mon_addr), | ||
323 | GFP_KERNEL); | ||
324 | if (!args->mon_addr) | ||
325 | goto out; | ||
324 | 326 | ||
325 | mon_addr = kcalloc(CEPH_MAX_MON, sizeof(*mon_addr), GFP_KERNEL); | 327 | dout("parse_mount_args %p, dev_name '%s'\n", args, dev_name); |
326 | if (!mon_addr) | ||
327 | return -ENOMEM; | ||
328 | 328 | ||
329 | /* start with defaults */ | 329 | /* start with defaults */ |
330 | args->sb_flags = flags; | 330 | args->sb_flags = flags; |
@@ -350,29 +350,11 @@ static int parse_mount_args(struct ceph_client *client, | |||
350 | } | 350 | } |
351 | 351 | ||
352 | /* get mon ip(s) */ | 352 | /* get mon ip(s) */ |
353 | err = ceph_parse_ips(dev_name, *path, mon_addr, | 353 | err = ceph_parse_ips(dev_name, *path, args->mon_addr, |
354 | CEPH_MAX_MON, &num_mon); | 354 | CEPH_MAX_MON, &args->num_mon); |
355 | if (err < 0) | 355 | if (err < 0) |
356 | goto out; | 356 | goto out; |
357 | 357 | ||
358 | /* build initial monmap */ | ||
359 | err = -ENOMEM; | ||
360 | client->monc.monmap = kzalloc(sizeof(*client->monc.monmap) + | ||
361 | num_mon*sizeof(client->monc.monmap->mon_inst[0]), | ||
362 | GFP_KERNEL); | ||
363 | if (!client->monc.monmap) | ||
364 | goto out; | ||
365 | for (i = 0; i < num_mon; i++) { | ||
366 | client->monc.monmap->mon_inst[i].addr = mon_addr[i]; | ||
367 | client->monc.monmap->mon_inst[i].addr.erank = 0; | ||
368 | client->monc.monmap->mon_inst[i].addr.nonce = 0; | ||
369 | client->monc.monmap->mon_inst[i].name.type = | ||
370 | CEPH_ENTITY_TYPE_MON; | ||
371 | client->monc.monmap->mon_inst[i].name.num = cpu_to_le64(i); | ||
372 | } | ||
373 | client->monc.monmap->num_mon = num_mon; | ||
374 | memset(&args->my_addr.in_addr, 0, sizeof(args->my_addr.in_addr)); | ||
375 | |||
376 | /* path on server */ | 358 | /* path on server */ |
377 | *path += 2; | 359 | *path += 2; |
378 | dout("server path '%s'\n", *path); | 360 | dout("server path '%s'\n", *path); |
@@ -415,7 +397,7 @@ static int parse_mount_args(struct ceph_client *client, | |||
415 | &args->my_addr, | 397 | &args->my_addr, |
416 | 1, NULL); | 398 | 1, NULL); |
417 | if (err < 0) | 399 | if (err < 0) |
418 | return err; | 400 | goto out; |
419 | args->flags |= CEPH_OPT_MYIP; | 401 | args->flags |= CEPH_OPT_MYIP; |
420 | break; | 402 | break; |
421 | 403 | ||
@@ -481,25 +463,28 @@ static int parse_mount_args(struct ceph_client *client, | |||
481 | BUG_ON(token); | 463 | BUG_ON(token); |
482 | } | 464 | } |
483 | } | 465 | } |
484 | err = 0; | 466 | return args; |
485 | 467 | ||
486 | out: | 468 | out: |
487 | kfree(mon_addr); | 469 | kfree(args->mon_addr); |
488 | return err; | 470 | kfree(args); |
471 | return ERR_PTR(err); | ||
489 | } | 472 | } |
490 | 473 | ||
491 | static void release_mount_args(struct ceph_mount_args *args) | 474 | static void destroy_mount_args(struct ceph_mount_args *args) |
492 | { | 475 | { |
476 | dout("destroy_mount_args %p\n", args); | ||
493 | kfree(args->snapdir_name); | 477 | kfree(args->snapdir_name); |
494 | args->snapdir_name = NULL; | 478 | args->snapdir_name = NULL; |
495 | kfree(args->secret); | 479 | kfree(args->secret); |
496 | args->secret = NULL; | 480 | args->secret = NULL; |
481 | kfree(args); | ||
497 | } | 482 | } |
498 | 483 | ||
499 | /* | 484 | /* |
500 | * create a fresh client instance | 485 | * create a fresh client instance |
501 | */ | 486 | */ |
502 | static struct ceph_client *ceph_create_client(void) | 487 | static struct ceph_client *ceph_create_client(struct ceph_mount_args *args) |
503 | { | 488 | { |
504 | struct ceph_client *client; | 489 | struct ceph_client *client; |
505 | int err = -ENOMEM; | 490 | int err = -ENOMEM; |
@@ -515,6 +500,7 @@ static struct ceph_client *ceph_create_client(void) | |||
515 | client->sb = NULL; | 500 | client->sb = NULL; |
516 | client->mount_state = CEPH_MOUNT_MOUNTING; | 501 | client->mount_state = CEPH_MOUNT_MOUNTING; |
517 | client->whoami = -1; | 502 | client->whoami = -1; |
503 | client->mount_args = args; | ||
518 | 504 | ||
519 | client->msgr = NULL; | 505 | client->msgr = NULL; |
520 | 506 | ||
@@ -577,7 +563,7 @@ static void ceph_destroy_client(struct ceph_client *client) | |||
577 | if (client->wb_pagevec_pool) | 563 | if (client->wb_pagevec_pool) |
578 | mempool_destroy(client->wb_pagevec_pool); | 564 | mempool_destroy(client->wb_pagevec_pool); |
579 | 565 | ||
580 | release_mount_args(&client->mount_args); | 566 | destroy_mount_args(client->mount_args); |
581 | 567 | ||
582 | kfree(client); | 568 | kfree(client); |
583 | dout("destroy_client %p done\n", client); | 569 | dout("destroy_client %p done\n", client); |
@@ -613,7 +599,7 @@ static struct dentry *open_root_dentry(struct ceph_client *client, | |||
613 | req->r_ino1.ino = CEPH_INO_ROOT; | 599 | req->r_ino1.ino = CEPH_INO_ROOT; |
614 | req->r_ino1.snap = CEPH_NOSNAP; | 600 | req->r_ino1.snap = CEPH_NOSNAP; |
615 | req->r_started = started; | 601 | req->r_started = started; |
616 | req->r_timeout = client->mount_args.mount_timeout * HZ; | 602 | req->r_timeout = client->mount_args->mount_timeout * HZ; |
617 | req->r_args.getattr.mask = cpu_to_le32(CEPH_STAT_CAP_INODE); | 603 | req->r_args.getattr.mask = cpu_to_le32(CEPH_STAT_CAP_INODE); |
618 | req->r_num_caps = 2; | 604 | req->r_num_caps = 2; |
619 | err = ceph_mdsc_do_request(mdsc, NULL, req); | 605 | err = ceph_mdsc_do_request(mdsc, NULL, req); |
@@ -641,7 +627,7 @@ static int ceph_mount(struct ceph_client *client, struct vfsmount *mnt, | |||
641 | { | 627 | { |
642 | struct ceph_entity_addr *myaddr = NULL; | 628 | struct ceph_entity_addr *myaddr = NULL; |
643 | int err; | 629 | int err; |
644 | unsigned long timeout = client->mount_args.mount_timeout * HZ; | 630 | unsigned long timeout = client->mount_args->mount_timeout * HZ; |
645 | unsigned long started = jiffies; /* note the start time */ | 631 | unsigned long started = jiffies; /* note the start time */ |
646 | struct dentry *root; | 632 | struct dentry *root; |
647 | 633 | ||
@@ -651,7 +637,7 @@ static int ceph_mount(struct ceph_client *client, struct vfsmount *mnt, | |||
651 | /* initialize the messenger */ | 637 | /* initialize the messenger */ |
652 | if (client->msgr == NULL) { | 638 | if (client->msgr == NULL) { |
653 | if (ceph_test_opt(client, MYIP)) | 639 | if (ceph_test_opt(client, MYIP)) |
654 | myaddr = &client->mount_args.my_addr; | 640 | myaddr = &client->mount_args->my_addr; |
655 | client->msgr = ceph_messenger_create(myaddr); | 641 | client->msgr = ceph_messenger_create(myaddr); |
656 | if (IS_ERR(client->msgr)) { | 642 | if (IS_ERR(client->msgr)) { |
657 | err = PTR_ERR(client->msgr); | 643 | err = PTR_ERR(client->msgr); |
@@ -727,7 +713,7 @@ static int ceph_set_super(struct super_block *s, void *data) | |||
727 | 713 | ||
728 | dout("set_super %p data %p\n", s, data); | 714 | dout("set_super %p data %p\n", s, data); |
729 | 715 | ||
730 | s->s_flags = client->mount_args.sb_flags; | 716 | s->s_flags = client->mount_args->sb_flags; |
731 | s->s_maxbytes = 1ULL << 40; /* temp value until we get mdsmap */ | 717 | s->s_maxbytes = 1ULL << 40; /* temp value until we get mdsmap */ |
732 | 718 | ||
733 | s->s_fs_info = client; | 719 | s->s_fs_info = client; |
@@ -756,7 +742,7 @@ fail: | |||
756 | static int ceph_compare_super(struct super_block *sb, void *data) | 742 | static int ceph_compare_super(struct super_block *sb, void *data) |
757 | { | 743 | { |
758 | struct ceph_client *new = data; | 744 | struct ceph_client *new = data; |
759 | struct ceph_mount_args *args = &new->mount_args; | 745 | struct ceph_mount_args *args = new->mount_args; |
760 | struct ceph_client *other = ceph_sb_to_client(sb); | 746 | struct ceph_client *other = ceph_sb_to_client(sb); |
761 | int i; | 747 | int i; |
762 | 748 | ||
@@ -778,7 +764,7 @@ static int ceph_compare_super(struct super_block *sb, void *data) | |||
778 | } | 764 | } |
779 | dout("mon ip matches existing sb %p\n", sb); | 765 | dout("mon ip matches existing sb %p\n", sb); |
780 | } | 766 | } |
781 | if (args->sb_flags != other->mount_args.sb_flags) { | 767 | if (args->sb_flags != other->mount_args->sb_flags) { |
782 | dout("flags differ\n"); | 768 | dout("flags differ\n"); |
783 | return 0; | 769 | return 0; |
784 | } | 770 | } |
@@ -798,9 +784,9 @@ static int ceph_init_bdi(struct super_block *sb, struct ceph_client *client) | |||
798 | sb->s_bdi = &client->backing_dev_info; | 784 | sb->s_bdi = &client->backing_dev_info; |
799 | 785 | ||
800 | /* set ra_pages based on rsize mount option? */ | 786 | /* set ra_pages based on rsize mount option? */ |
801 | if (client->mount_args.rsize >= PAGE_CACHE_SIZE) | 787 | if (client->mount_args->rsize >= PAGE_CACHE_SIZE) |
802 | client->backing_dev_info.ra_pages = | 788 | client->backing_dev_info.ra_pages = |
803 | (client->mount_args.rsize + PAGE_CACHE_SIZE - 1) | 789 | (client->mount_args->rsize + PAGE_CACHE_SIZE - 1) |
804 | >> PAGE_SHIFT; | 790 | >> PAGE_SHIFT; |
805 | 791 | ||
806 | err = bdi_register_dev(&client->backing_dev_info, sb->s_dev); | 792 | err = bdi_register_dev(&client->backing_dev_info, sb->s_dev); |
@@ -816,19 +802,23 @@ static int ceph_get_sb(struct file_system_type *fs_type, | |||
816 | int err; | 802 | int err; |
817 | int (*compare_super)(struct super_block *, void *) = ceph_compare_super; | 803 | int (*compare_super)(struct super_block *, void *) = ceph_compare_super; |
818 | const char *path = 0; | 804 | const char *path = 0; |
805 | struct ceph_mount_args *args; | ||
819 | 806 | ||
820 | dout("ceph_get_sb\n"); | 807 | dout("ceph_get_sb\n"); |
808 | args = parse_mount_args(flags, data, dev_name, &path); | ||
809 | if (IS_ERR(args)) { | ||
810 | err = PTR_ERR(args); | ||
811 | goto out_final; | ||
812 | } | ||
821 | 813 | ||
822 | /* create client (which we may/may not use) */ | 814 | /* create client (which we may/may not use) */ |
823 | client = ceph_create_client(); | 815 | client = ceph_create_client(args); |
824 | if (IS_ERR(client)) | 816 | if (IS_ERR(client)) { |
825 | return PTR_ERR(client); | 817 | err = PTR_ERR(client); |
826 | 818 | goto out_final; | |
827 | err = parse_mount_args(client, flags, data, dev_name, &path); | 819 | } |
828 | if (err < 0) | ||
829 | goto out; | ||
830 | 820 | ||
831 | if (client->mount_args.flags & CEPH_OPT_NOSHARE) | 821 | if (client->mount_args->flags & CEPH_OPT_NOSHARE) |
832 | compare_super = NULL; | 822 | compare_super = NULL; |
833 | sb = sget(fs_type, compare_super, ceph_set_super, client); | 823 | sb = sget(fs_type, compare_super, ceph_set_super, client); |
834 | if (IS_ERR(sb)) { | 824 | if (IS_ERR(sb)) { |
@@ -846,7 +836,7 @@ static int ceph_get_sb(struct file_system_type *fs_type, | |||
846 | /* set up mempools */ | 836 | /* set up mempools */ |
847 | err = -ENOMEM; | 837 | err = -ENOMEM; |
848 | client->wb_pagevec_pool = mempool_create_kmalloc_pool(10, | 838 | client->wb_pagevec_pool = mempool_create_kmalloc_pool(10, |
849 | client->mount_args.wsize >> PAGE_CACHE_SHIFT); | 839 | client->mount_args->wsize >> PAGE_CACHE_SHIFT); |
850 | if (!client->wb_pagevec_pool) | 840 | if (!client->wb_pagevec_pool) |
851 | goto out_splat; | 841 | goto out_splat; |
852 | 842 | ||