diff options
-rw-r--r-- | block/partition-generic.c | 4 | ||||
-rw-r--r-- | block/partitions/check.c | 37 | ||||
-rw-r--r-- | block/partitions/check.h | 4 |
3 files changed, 37 insertions, 8 deletions
diff --git a/block/partition-generic.c b/block/partition-generic.c index 1cb4deca1324..789cdea05893 100644 --- a/block/partition-generic.c +++ b/block/partition-generic.c | |||
@@ -418,7 +418,7 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev) | |||
418 | int p, highest, res; | 418 | int p, highest, res; |
419 | rescan: | 419 | rescan: |
420 | if (state && !IS_ERR(state)) { | 420 | if (state && !IS_ERR(state)) { |
421 | kfree(state); | 421 | free_partitions(state); |
422 | state = NULL; | 422 | state = NULL; |
423 | } | 423 | } |
424 | 424 | ||
@@ -525,7 +525,7 @@ rescan: | |||
525 | md_autodetect_dev(part_to_dev(part)->devt); | 525 | md_autodetect_dev(part_to_dev(part)->devt); |
526 | #endif | 526 | #endif |
527 | } | 527 | } |
528 | kfree(state); | 528 | free_partitions(state); |
529 | return 0; | 529 | return 0; |
530 | } | 530 | } |
531 | 531 | ||
diff --git a/block/partitions/check.c b/block/partitions/check.c index bc908672c976..19ba207ea7d1 100644 --- a/block/partitions/check.c +++ b/block/partitions/check.c | |||
@@ -14,6 +14,7 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/vmalloc.h> | ||
17 | #include <linux/ctype.h> | 18 | #include <linux/ctype.h> |
18 | #include <linux/genhd.h> | 19 | #include <linux/genhd.h> |
19 | 20 | ||
@@ -106,18 +107,45 @@ static int (*check_part[])(struct parsed_partitions *) = { | |||
106 | NULL | 107 | NULL |
107 | }; | 108 | }; |
108 | 109 | ||
110 | static struct parsed_partitions *allocate_partitions(struct gendisk *hd) | ||
111 | { | ||
112 | struct parsed_partitions *state; | ||
113 | int nr; | ||
114 | |||
115 | state = kzalloc(sizeof(*state), GFP_KERNEL); | ||
116 | if (!state) | ||
117 | return NULL; | ||
118 | |||
119 | nr = disk_max_parts(hd); | ||
120 | state->parts = vzalloc(nr * sizeof(state->parts[0])); | ||
121 | if (!state->parts) { | ||
122 | kfree(state); | ||
123 | return NULL; | ||
124 | } | ||
125 | |||
126 | state->limit = nr; | ||
127 | |||
128 | return state; | ||
129 | } | ||
130 | |||
131 | void free_partitions(struct parsed_partitions *state) | ||
132 | { | ||
133 | vfree(state->parts); | ||
134 | kfree(state); | ||
135 | } | ||
136 | |||
109 | struct parsed_partitions * | 137 | struct parsed_partitions * |
110 | check_partition(struct gendisk *hd, struct block_device *bdev) | 138 | check_partition(struct gendisk *hd, struct block_device *bdev) |
111 | { | 139 | { |
112 | struct parsed_partitions *state; | 140 | struct parsed_partitions *state; |
113 | int i, res, err; | 141 | int i, res, err; |
114 | 142 | ||
115 | state = kzalloc(sizeof(struct parsed_partitions), GFP_KERNEL); | 143 | state = allocate_partitions(hd); |
116 | if (!state) | 144 | if (!state) |
117 | return NULL; | 145 | return NULL; |
118 | state->pp_buf = (char *)__get_free_page(GFP_KERNEL); | 146 | state->pp_buf = (char *)__get_free_page(GFP_KERNEL); |
119 | if (!state->pp_buf) { | 147 | if (!state->pp_buf) { |
120 | kfree(state); | 148 | free_partitions(state); |
121 | return NULL; | 149 | return NULL; |
122 | } | 150 | } |
123 | state->pp_buf[0] = '\0'; | 151 | state->pp_buf[0] = '\0'; |
@@ -128,10 +156,9 @@ check_partition(struct gendisk *hd, struct block_device *bdev) | |||
128 | if (isdigit(state->name[strlen(state->name)-1])) | 156 | if (isdigit(state->name[strlen(state->name)-1])) |
129 | sprintf(state->name, "p"); | 157 | sprintf(state->name, "p"); |
130 | 158 | ||
131 | state->limit = disk_max_parts(hd); | ||
132 | i = res = err = 0; | 159 | i = res = err = 0; |
133 | while (!res && check_part[i]) { | 160 | while (!res && check_part[i]) { |
134 | memset(&state->parts, 0, sizeof(state->parts)); | 161 | memset(state->parts, 0, state->limit * sizeof(state->parts[0])); |
135 | res = check_part[i++](state); | 162 | res = check_part[i++](state); |
136 | if (res < 0) { | 163 | if (res < 0) { |
137 | /* We have hit an I/O error which we don't report now. | 164 | /* We have hit an I/O error which we don't report now. |
@@ -161,6 +188,6 @@ check_partition(struct gendisk *hd, struct block_device *bdev) | |||
161 | printk(KERN_INFO "%s", state->pp_buf); | 188 | printk(KERN_INFO "%s", state->pp_buf); |
162 | 189 | ||
163 | free_page((unsigned long)state->pp_buf); | 190 | free_page((unsigned long)state->pp_buf); |
164 | kfree(state); | 191 | free_partitions(state); |
165 | return ERR_PTR(res); | 192 | return ERR_PTR(res); |
166 | } | 193 | } |
diff --git a/block/partitions/check.h b/block/partitions/check.h index 52b100311ec3..eade17ea910b 100644 --- a/block/partitions/check.h +++ b/block/partitions/check.h | |||
@@ -15,13 +15,15 @@ struct parsed_partitions { | |||
15 | int flags; | 15 | int flags; |
16 | bool has_info; | 16 | bool has_info; |
17 | struct partition_meta_info info; | 17 | struct partition_meta_info info; |
18 | } parts[DISK_MAX_PARTS]; | 18 | } *parts; |
19 | int next; | 19 | int next; |
20 | int limit; | 20 | int limit; |
21 | bool access_beyond_eod; | 21 | bool access_beyond_eod; |
22 | char *pp_buf; | 22 | char *pp_buf; |
23 | }; | 23 | }; |
24 | 24 | ||
25 | void free_partitions(struct parsed_partitions *state); | ||
26 | |||
25 | struct parsed_partitions * | 27 | struct parsed_partitions * |
26 | check_partition(struct gendisk *, struct block_device *); | 28 | check_partition(struct gendisk *, struct block_device *); |
27 | 29 | ||