diff options
-rw-r--r-- | block/genhd.c | 1 | ||||
-rw-r--r-- | block/ioctl.c | 2 | ||||
-rw-r--r-- | fs/partitions/check.c | 23 | ||||
-rw-r--r-- | fs/partitions/check.h | 3 | ||||
-rw-r--r-- | include/linux/genhd.h | 53 |
5 files changed, 76 insertions, 6 deletions
diff --git a/block/genhd.c b/block/genhd.c index 59a2db6fecef..c8da12055264 100644 --- a/block/genhd.c +++ b/block/genhd.c | |||
@@ -1004,6 +1004,7 @@ static void disk_release(struct device *dev) | |||
1004 | kfree(disk->random); | 1004 | kfree(disk->random); |
1005 | disk_replace_part_tbl(disk, NULL); | 1005 | disk_replace_part_tbl(disk, NULL); |
1006 | free_part_stats(&disk->part0); | 1006 | free_part_stats(&disk->part0); |
1007 | free_part_info(&disk->part0); | ||
1007 | kfree(disk); | 1008 | kfree(disk); |
1008 | } | 1009 | } |
1009 | struct class block_class = { | 1010 | struct class block_class = { |
diff --git a/block/ioctl.c b/block/ioctl.c index d8052f0dabd3..2c15fe0912c4 100644 --- a/block/ioctl.c +++ b/block/ioctl.c | |||
@@ -62,7 +62,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user | |||
62 | 62 | ||
63 | /* all seems OK */ | 63 | /* all seems OK */ |
64 | part = add_partition(disk, partno, start, length, | 64 | part = add_partition(disk, partno, start, length, |
65 | ADDPART_FLAG_NONE); | 65 | ADDPART_FLAG_NONE, NULL); |
66 | mutex_unlock(&bdev->bd_mutex); | 66 | mutex_unlock(&bdev->bd_mutex); |
67 | return IS_ERR(part) ? PTR_ERR(part) : 0; | 67 | return IS_ERR(part) ? PTR_ERR(part) : 0; |
68 | case BLKPG_DEL_PARTITION: | 68 | case BLKPG_DEL_PARTITION: |
diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 79fbf3f390f0..6dfbee03ccc6 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c | |||
@@ -352,6 +352,7 @@ static void part_release(struct device *dev) | |||
352 | { | 352 | { |
353 | struct hd_struct *p = dev_to_part(dev); | 353 | struct hd_struct *p = dev_to_part(dev); |
354 | free_part_stats(p); | 354 | free_part_stats(p); |
355 | free_part_info(p); | ||
355 | kfree(p); | 356 | kfree(p); |
356 | } | 357 | } |
357 | 358 | ||
@@ -401,7 +402,8 @@ static DEVICE_ATTR(whole_disk, S_IRUSR | S_IRGRP | S_IROTH, | |||
401 | whole_disk_show, NULL); | 402 | whole_disk_show, NULL); |
402 | 403 | ||
403 | struct hd_struct *add_partition(struct gendisk *disk, int partno, | 404 | struct hd_struct *add_partition(struct gendisk *disk, int partno, |
404 | sector_t start, sector_t len, int flags) | 405 | sector_t start, sector_t len, int flags, |
406 | struct partition_meta_info *info) | ||
405 | { | 407 | { |
406 | struct hd_struct *p; | 408 | struct hd_struct *p; |
407 | dev_t devt = MKDEV(0, 0); | 409 | dev_t devt = MKDEV(0, 0); |
@@ -438,6 +440,14 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno, | |||
438 | p->partno = partno; | 440 | p->partno = partno; |
439 | p->policy = get_disk_ro(disk); | 441 | p->policy = get_disk_ro(disk); |
440 | 442 | ||
443 | if (info) { | ||
444 | struct partition_meta_info *pinfo = alloc_part_info(disk); | ||
445 | if (!pinfo) | ||
446 | goto out_free_stats; | ||
447 | memcpy(pinfo, info, sizeof(*info)); | ||
448 | p->info = pinfo; | ||
449 | } | ||
450 | |||
441 | dname = dev_name(ddev); | 451 | dname = dev_name(ddev); |
442 | if (isdigit(dname[strlen(dname) - 1])) | 452 | if (isdigit(dname[strlen(dname) - 1])) |
443 | dev_set_name(pdev, "%sp%d", dname, partno); | 453 | dev_set_name(pdev, "%sp%d", dname, partno); |
@@ -451,7 +461,7 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno, | |||
451 | 461 | ||
452 | err = blk_alloc_devt(p, &devt); | 462 | err = blk_alloc_devt(p, &devt); |
453 | if (err) | 463 | if (err) |
454 | goto out_free_stats; | 464 | goto out_free_info; |
455 | pdev->devt = devt; | 465 | pdev->devt = devt; |
456 | 466 | ||
457 | /* delay uevent until 'holders' subdir is created */ | 467 | /* delay uevent until 'holders' subdir is created */ |
@@ -481,6 +491,8 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno, | |||
481 | 491 | ||
482 | return p; | 492 | return p; |
483 | 493 | ||
494 | out_free_info: | ||
495 | free_part_info(p); | ||
484 | out_free_stats: | 496 | out_free_stats: |
485 | free_part_stats(p); | 497 | free_part_stats(p); |
486 | out_free: | 498 | out_free: |
@@ -642,6 +654,7 @@ rescan: | |||
642 | /* add partitions */ | 654 | /* add partitions */ |
643 | for (p = 1; p < state->limit; p++) { | 655 | for (p = 1; p < state->limit; p++) { |
644 | sector_t size, from; | 656 | sector_t size, from; |
657 | struct partition_meta_info *info = NULL; | ||
645 | 658 | ||
646 | size = state->parts[p].size; | 659 | size = state->parts[p].size; |
647 | if (!size) | 660 | if (!size) |
@@ -675,8 +688,12 @@ rescan: | |||
675 | size = get_capacity(disk) - from; | 688 | size = get_capacity(disk) - from; |
676 | } | 689 | } |
677 | } | 690 | } |
691 | |||
692 | if (state->parts[p].has_info) | ||
693 | info = &state->parts[p].info; | ||
678 | part = add_partition(disk, p, from, size, | 694 | part = add_partition(disk, p, from, size, |
679 | state->parts[p].flags); | 695 | state->parts[p].flags, |
696 | &state->parts[p].info); | ||
680 | if (IS_ERR(part)) { | 697 | if (IS_ERR(part)) { |
681 | printk(KERN_ERR " %s: p%d could not be added: %ld\n", | 698 | printk(KERN_ERR " %s: p%d could not be added: %ld\n", |
682 | disk->disk_name, p, -PTR_ERR(part)); | 699 | disk->disk_name, p, -PTR_ERR(part)); |
diff --git a/fs/partitions/check.h b/fs/partitions/check.h index 8e4e103ba216..d68bf4dc3bc2 100644 --- a/fs/partitions/check.h +++ b/fs/partitions/check.h | |||
@@ -1,5 +1,6 @@ | |||
1 | #include <linux/pagemap.h> | 1 | #include <linux/pagemap.h> |
2 | #include <linux/blkdev.h> | 2 | #include <linux/blkdev.h> |
3 | #include <linux/genhd.h> | ||
3 | 4 | ||
4 | /* | 5 | /* |
5 | * add_gd_partition adds a partitions details to the devices partition | 6 | * add_gd_partition adds a partitions details to the devices partition |
@@ -12,6 +13,8 @@ struct parsed_partitions { | |||
12 | sector_t from; | 13 | sector_t from; |
13 | sector_t size; | 14 | sector_t size; |
14 | int flags; | 15 | int flags; |
16 | bool has_info; | ||
17 | struct partition_meta_info info; | ||
15 | } parts[DISK_MAX_PARTS]; | 18 | } parts[DISK_MAX_PARTS]; |
16 | int next; | 19 | int next; |
17 | int limit; | 20 | int limit; |
diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 5f2f4c4d8fb0..66e26b5a1537 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
13 | #include <linux/kdev_t.h> | 13 | #include <linux/kdev_t.h> |
14 | #include <linux/rcupdate.h> | 14 | #include <linux/rcupdate.h> |
15 | #include <linux/slab.h> | ||
15 | 16 | ||
16 | #ifdef CONFIG_BLOCK | 17 | #ifdef CONFIG_BLOCK |
17 | 18 | ||
@@ -86,7 +87,15 @@ struct disk_stats { | |||
86 | unsigned long io_ticks; | 87 | unsigned long io_ticks; |
87 | unsigned long time_in_queue; | 88 | unsigned long time_in_queue; |
88 | }; | 89 | }; |
89 | 90 | ||
91 | #define PARTITION_META_INFO_VOLNAMELTH 64 | ||
92 | #define PARTITION_META_INFO_UUIDLTH 16 | ||
93 | |||
94 | struct partition_meta_info { | ||
95 | u8 uuid[PARTITION_META_INFO_UUIDLTH]; /* always big endian */ | ||
96 | u8 volname[PARTITION_META_INFO_VOLNAMELTH]; | ||
97 | }; | ||
98 | |||
90 | struct hd_struct { | 99 | struct hd_struct { |
91 | sector_t start_sect; | 100 | sector_t start_sect; |
92 | sector_t nr_sects; | 101 | sector_t nr_sects; |
@@ -95,6 +104,7 @@ struct hd_struct { | |||
95 | struct device __dev; | 104 | struct device __dev; |
96 | struct kobject *holder_dir; | 105 | struct kobject *holder_dir; |
97 | int policy, partno; | 106 | int policy, partno; |
107 | struct partition_meta_info *info; | ||
98 | #ifdef CONFIG_FAIL_MAKE_REQUEST | 108 | #ifdef CONFIG_FAIL_MAKE_REQUEST |
99 | int make_it_fail; | 109 | int make_it_fail; |
100 | #endif | 110 | #endif |
@@ -181,6 +191,30 @@ static inline struct gendisk *part_to_disk(struct hd_struct *part) | |||
181 | return NULL; | 191 | return NULL; |
182 | } | 192 | } |
183 | 193 | ||
194 | static inline void part_pack_uuid(const u8 *uuid_str, u8 *to) | ||
195 | { | ||
196 | int i; | ||
197 | for (i = 0; i < 16; ++i) { | ||
198 | *to++ = (hex_to_bin(*uuid_str) << 4) | | ||
199 | (hex_to_bin(*(uuid_str + 1))); | ||
200 | uuid_str += 2; | ||
201 | switch (i) { | ||
202 | case 3: | ||
203 | case 5: | ||
204 | case 7: | ||
205 | case 9: | ||
206 | uuid_str++; | ||
207 | continue; | ||
208 | } | ||
209 | } | ||
210 | } | ||
211 | |||
212 | static inline char *part_unpack_uuid(const u8 *uuid, char *out) | ||
213 | { | ||
214 | sprintf(out, "%pU", uuid); | ||
215 | return out; | ||
216 | } | ||
217 | |||
184 | static inline int disk_max_parts(struct gendisk *disk) | 218 | static inline int disk_max_parts(struct gendisk *disk) |
185 | { | 219 | { |
186 | if (disk->flags & GENHD_FL_EXT_DEVT) | 220 | if (disk->flags & GENHD_FL_EXT_DEVT) |
@@ -342,6 +376,19 @@ static inline int part_in_flight(struct hd_struct *part) | |||
342 | return part->in_flight[0] + part->in_flight[1]; | 376 | return part->in_flight[0] + part->in_flight[1]; |
343 | } | 377 | } |
344 | 378 | ||
379 | static inline struct partition_meta_info *alloc_part_info(struct gendisk *disk) | ||
380 | { | ||
381 | if (disk) | ||
382 | return kzalloc_node(sizeof(struct partition_meta_info), | ||
383 | GFP_KERNEL, disk->node_id); | ||
384 | return kzalloc(sizeof(struct partition_meta_info), GFP_KERNEL); | ||
385 | } | ||
386 | |||
387 | static inline void free_part_info(struct hd_struct *part) | ||
388 | { | ||
389 | kfree(part->info); | ||
390 | } | ||
391 | |||
345 | /* block/blk-core.c */ | 392 | /* block/blk-core.c */ |
346 | extern void part_round_stats(int cpu, struct hd_struct *part); | 393 | extern void part_round_stats(int cpu, struct hd_struct *part); |
347 | 394 | ||
@@ -533,7 +580,9 @@ extern int disk_expand_part_tbl(struct gendisk *disk, int target); | |||
533 | extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev); | 580 | extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev); |
534 | extern struct hd_struct * __must_check add_partition(struct gendisk *disk, | 581 | extern struct hd_struct * __must_check add_partition(struct gendisk *disk, |
535 | int partno, sector_t start, | 582 | int partno, sector_t start, |
536 | sector_t len, int flags); | 583 | sector_t len, int flags, |
584 | struct partition_meta_info | ||
585 | *info); | ||
537 | extern void delete_partition(struct gendisk *, int); | 586 | extern void delete_partition(struct gendisk *, int); |
538 | extern void printk_all_partitions(void); | 587 | extern void printk_all_partitions(void); |
539 | 588 | ||