diff options
Diffstat (limited to 'block/partitions/check.c')
-rw-r--r-- | block/partitions/check.c | 37 |
1 files changed, 32 insertions, 5 deletions
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 | } |