aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBoaz Harrosh <bharrosh@panasas.com>2011-07-27 20:51:53 -0400
committerBoaz Harrosh <bharrosh@panasas.com>2011-08-04 15:35:20 -0400
commit6d4073e88132259485ef1b2c88daa5e50c95789c (patch)
tree04876cbe47e462bca7dad51ec33ccb29080d5680
parent26ae93c2dc7152463d319c28768f242a11a54620 (diff)
exofs: BUG: Avoid sbi realloc
Since the beginning we realloced the sbi structure when a bigger then one device table was specified. (I know that was really stupid). Then much later when "register bdi" was added (By Jens) it was registering the pointer to sbi->bdi before the realloc. We never saw this problem because up till now the realloc did not do anything since the device table was small enough to fit in the original allocation. But once we starting testing with large device tables (Bigger then 28) we noticed the crash of writeback operating on a deallocated pointer. * Avoid the all mess by allocating the device-table as a second array and get rid of the variable-sized structure and the rest of this mess. * Take the chance to clean near by structures and comments. * Add a needed dprint on startup to indicate the loaded layout. * Also move the bdi registration to the very end because it will only fail in a low memory, which will probably fail before hand. There are many more likely causes to not load before that. This way the error handling is made simpler. (Just doing this would be enough to fix the BUG) Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
-rw-r--r--fs/exofs/exofs.h9
-rw-r--r--fs/exofs/super.c45
2 files changed, 30 insertions, 24 deletions
diff --git a/fs/exofs/exofs.h b/fs/exofs/exofs.h
index e103dbd86fe1..9f62349a5a5c 100644
--- a/fs/exofs/exofs.h
+++ b/fs/exofs/exofs.h
@@ -66,13 +66,14 @@ struct exofs_layout {
66 enum exofs_inode_layout_gen_functions lay_func; 66 enum exofs_inode_layout_gen_functions lay_func;
67 67
68 unsigned s_numdevs; /* Num of devices in array */ 68 unsigned s_numdevs; /* Num of devices in array */
69 struct osd_dev *s_ods[0]; /* Variable length */ 69 struct osd_dev **s_ods; /* osd_dev array */
70}; 70};
71 71
72/* 72/*
73 * our extension to the in-memory superblock 73 * our extension to the in-memory superblock
74 */ 74 */
75struct exofs_sb_info { 75struct exofs_sb_info {
76 struct backing_dev_info bdi; /* register our bdi with VFS */
76 struct exofs_sb_stats s_ess; /* Written often, pre-allocate*/ 77 struct exofs_sb_stats s_ess; /* Written often, pre-allocate*/
77 int s_timeout; /* timeout for OSD operations */ 78 int s_timeout; /* timeout for OSD operations */
78 uint64_t s_nextid; /* highest object ID used */ 79 uint64_t s_nextid; /* highest object ID used */
@@ -81,15 +82,11 @@ struct exofs_sb_info {
81 u32 s_next_generation; /* next gen # to use */ 82 u32 s_next_generation; /* next gen # to use */
82 atomic_t s_curr_pending; /* number of pending commands */ 83 atomic_t s_curr_pending; /* number of pending commands */
83 uint8_t s_cred[OSD_CAP_LEN]; /* credential for the fscb */ 84 uint8_t s_cred[OSD_CAP_LEN]; /* credential for the fscb */
84 struct backing_dev_info bdi; /* register our bdi with VFS */
85 85
86 struct pnfs_osd_data_map data_map; /* Default raid to use 86 struct pnfs_osd_data_map data_map; /* Default raid to use
87 * FIXME: Needed ? 87 * FIXME: Needed ?
88 */ 88 */
89/* struct exofs_layout dir_layout;*/ /* Default dir layout */ 89 struct exofs_layout layout; /* Default files layout */
90 struct exofs_layout layout; /* Default files layout,
91 * contains the variable osd_dev
92 * array. Keep last */
93 struct osd_dev *_min_one_dev[1]; /* Place holder for one dev */ 90 struct osd_dev *_min_one_dev[1]; /* Place holder for one dev */
94}; 91};
95 92
diff --git a/fs/exofs/super.c b/fs/exofs/super.c
index c57beddcc217..a747c871d313 100644
--- a/fs/exofs/super.c
+++ b/fs/exofs/super.c
@@ -393,6 +393,8 @@ void exofs_free_sbi(struct exofs_sb_info *sbi)
393 osduld_put_device(od); 393 osduld_put_device(od);
394 } 394 }
395 } 395 }
396 if (sbi->layout.s_ods != sbi->_min_one_dev)
397 kfree(sbi->layout.s_ods);
396 kfree(sbi); 398 kfree(sbi);
397} 399}
398 400
@@ -501,6 +503,15 @@ static int _read_and_match_data_map(struct exofs_sb_info *sbi, unsigned numdevs,
501 return -EINVAL; 503 return -EINVAL;
502 } 504 }
503 505
506 EXOFS_DBGMSG("exofs: layout: "
507 "num_comps=%u stripe_unit=0x%x group_width=%u "
508 "group_depth=0x%llx mirrors_p1=%u raid_algorithm=%u\n",
509 numdevs,
510 sbi->layout.stripe_unit,
511 sbi->layout.group_width,
512 _LLU(sbi->layout.group_depth),
513 sbi->layout.mirrors_p1,
514 sbi->data_map.odm_raid_algorithm);
504 return 0; 515 return 0;
505} 516}
506 517
@@ -547,11 +558,10 @@ static int exofs_devs_2_odi(struct exofs_dt_device_info *dt_dev,
547 return !(odi->systemid_len || odi->osdname_len); 558 return !(odi->systemid_len || odi->osdname_len);
548} 559}
549 560
550static int exofs_read_lookup_dev_table(struct exofs_sb_info **psbi, 561static int exofs_read_lookup_dev_table(struct exofs_sb_info *sbi,
562 struct osd_dev *fscb_od,
551 unsigned table_count) 563 unsigned table_count)
552{ 564{
553 struct exofs_sb_info *sbi = *psbi;
554 struct osd_dev *fscb_od;
555 struct osd_obj_id obj = {.partition = sbi->layout.s_pid, 565 struct osd_obj_id obj = {.partition = sbi->layout.s_pid,
556 .id = EXOFS_DEVTABLE_ID}; 566 .id = EXOFS_DEVTABLE_ID};
557 struct exofs_device_table *dt; 567 struct exofs_device_table *dt;
@@ -567,8 +577,6 @@ static int exofs_read_lookup_dev_table(struct exofs_sb_info **psbi,
567 return -ENOMEM; 577 return -ENOMEM;
568 } 578 }
569 579
570 fscb_od = sbi->layout.s_ods[0];
571 sbi->layout.s_ods[0] = NULL;
572 sbi->layout.s_numdevs = 0; 580 sbi->layout.s_numdevs = 0;
573 ret = exofs_read_kern(fscb_od, sbi->s_cred, &obj, 0, dt, table_bytes); 581 ret = exofs_read_kern(fscb_od, sbi->s_cred, &obj, 0, dt, table_bytes);
574 if (unlikely(ret)) { 582 if (unlikely(ret)) {
@@ -590,14 +598,13 @@ static int exofs_read_lookup_dev_table(struct exofs_sb_info **psbi,
590 if (likely(numdevs > 1)) { 598 if (likely(numdevs > 1)) {
591 unsigned size = numdevs * sizeof(sbi->layout.s_ods[0]); 599 unsigned size = numdevs * sizeof(sbi->layout.s_ods[0]);
592 600
593 sbi = krealloc(sbi, sizeof(*sbi) + size, GFP_KERNEL); 601 sbi->layout.s_ods = kzalloc(size, GFP_KERNEL);
594 if (unlikely(!sbi)) { 602 if (unlikely(!sbi->layout.s_ods)) {
603 EXOFS_ERR("ERROR: faild allocating Device array[%d]\n",
604 numdevs);
595 ret = -ENOMEM; 605 ret = -ENOMEM;
596 goto out; 606 goto out;
597 } 607 }
598 memset(&sbi->layout.s_ods[1], 0,
599 size - sizeof(sbi->layout.s_ods[0]));
600 *psbi = sbi;
601 } 608 }
602 609
603 for (i = 0; i < numdevs; i++) { 610 for (i = 0; i < numdevs; i++) {
@@ -684,10 +691,6 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent)
684 if (!sbi) 691 if (!sbi)
685 return -ENOMEM; 692 return -ENOMEM;
686 693
687 ret = bdi_setup_and_register(&sbi->bdi, "exofs", BDI_CAP_MAP_COPY);
688 if (ret)
689 goto free_bdi;
690
691 /* use mount options to fill superblock */ 694 /* use mount options to fill superblock */
692 if (opts->is_osdname) { 695 if (opts->is_osdname) {
693 struct osd_dev_info odi = {.systemid_len = 0}; 696 struct osd_dev_info odi = {.systemid_len = 0};
@@ -709,7 +712,7 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent)
709 sbi->layout.group_width = 1; 712 sbi->layout.group_width = 1;
710 sbi->layout.group_depth = -1; 713 sbi->layout.group_depth = -1;
711 sbi->layout.group_count = 1; 714 sbi->layout.group_count = 1;
712 sbi->layout.s_ods[0] = od; 715 sbi->layout.s_ods = sbi->_min_one_dev;
713 sbi->layout.s_numdevs = 1; 716 sbi->layout.s_numdevs = 1;
714 sbi->layout.s_pid = opts->pid; 717 sbi->layout.s_pid = opts->pid;
715 sbi->s_timeout = opts->timeout; 718 sbi->s_timeout = opts->timeout;
@@ -757,9 +760,11 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent)
757 760
758 table_count = le64_to_cpu(fscb.s_dev_table_count); 761 table_count = le64_to_cpu(fscb.s_dev_table_count);
759 if (table_count) { 762 if (table_count) {
760 ret = exofs_read_lookup_dev_table(&sbi, table_count); 763 ret = exofs_read_lookup_dev_table(sbi, od, table_count);
761 if (unlikely(ret)) 764 if (unlikely(ret))
762 goto free_sbi; 765 goto free_sbi;
766 } else {
767 sbi->layout.s_ods[0] = od;
763 } 768 }
764 769
765 __sbi_read_stats(sbi); 770 __sbi_read_stats(sbi);
@@ -793,6 +798,12 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent)
793 goto free_sbi; 798 goto free_sbi;
794 } 799 }
795 800
801 ret = bdi_setup_and_register(&sbi->bdi, "exofs", BDI_CAP_MAP_COPY);
802 if (ret) {
803 EXOFS_DBGMSG("Failed to bdi_setup_and_register\n");
804 goto free_sbi;
805 }
806
796 _exofs_print_device("Mounting", opts->dev_name, sbi->layout.s_ods[0], 807 _exofs_print_device("Mounting", opts->dev_name, sbi->layout.s_ods[0],
797 sbi->layout.s_pid); 808 sbi->layout.s_pid);
798 if (opts->is_osdname) 809 if (opts->is_osdname)
@@ -800,8 +811,6 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent)
800 return 0; 811 return 0;
801 812
802free_sbi: 813free_sbi:
803 bdi_destroy(&sbi->bdi);
804free_bdi:
805 EXOFS_ERR("Unable to mount exofs on %s pid=0x%llx err=%d\n", 814 EXOFS_ERR("Unable to mount exofs on %s pid=0x%llx err=%d\n",
806 opts->dev_name, sbi->layout.s_pid, ret); 815 opts->dev_name, sbi->layout.s_pid, ret);
807 exofs_free_sbi(sbi); 816 exofs_free_sbi(sbi);