diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/jbd/commit.c | 2 | ||||
-rw-r--r-- | fs/jbd2/commit.c | 2 | ||||
-rw-r--r-- | fs/partitions/check.c | 35 | ||||
-rw-r--r-- | fs/partitions/check.h | 3 | ||||
-rw-r--r-- | fs/partitions/efi.c | 25 |
5 files changed, 62 insertions, 5 deletions
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index 95d8c11c929e..3f030e9efea6 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c | |||
@@ -318,7 +318,7 @@ void journal_commit_transaction(journal_t *journal) | |||
318 | int first_tag = 0; | 318 | int first_tag = 0; |
319 | int tag_flag; | 319 | int tag_flag; |
320 | int i; | 320 | int i; |
321 | int write_op = WRITE; | 321 | int write_op = WRITE_SYNC; |
322 | 322 | ||
323 | /* | 323 | /* |
324 | * First job: lock down the current transaction and wait for | 324 | * First job: lock down the current transaction and wait for |
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 7c068c189d80..80910f51d4b4 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
@@ -360,7 +360,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
360 | int tag_bytes = journal_tag_bytes(journal); | 360 | int tag_bytes = journal_tag_bytes(journal); |
361 | struct buffer_head *cbh = NULL; /* For transactional checksums */ | 361 | struct buffer_head *cbh = NULL; /* For transactional checksums */ |
362 | __u32 crc32_sum = ~0; | 362 | __u32 crc32_sum = ~0; |
363 | int write_op = WRITE; | 363 | int write_op = WRITE_SYNC; |
364 | 364 | ||
365 | /* | 365 | /* |
366 | * First job: lock down the current transaction and wait for | 366 | * First job: lock down the current transaction and wait for |
diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 79fbf3f390f0..30f46c2cb9d5 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 | ||
@@ -364,17 +365,25 @@ struct device_type part_type = { | |||
364 | static void delete_partition_rcu_cb(struct rcu_head *head) | 365 | static void delete_partition_rcu_cb(struct rcu_head *head) |
365 | { | 366 | { |
366 | struct hd_struct *part = container_of(head, struct hd_struct, rcu_head); | 367 | struct hd_struct *part = container_of(head, struct hd_struct, rcu_head); |
368 | struct gendisk *disk = part_to_disk(part); | ||
369 | struct request_queue *q = disk->queue; | ||
370 | unsigned long flags; | ||
367 | 371 | ||
368 | part->start_sect = 0; | 372 | part->start_sect = 0; |
369 | part->nr_sects = 0; | 373 | part->nr_sects = 0; |
370 | part_stat_set_all(part, 0); | 374 | part_stat_set_all(part, 0); |
371 | put_device(part_to_dev(part)); | 375 | put_device(part_to_dev(part)); |
376 | |||
377 | spin_lock_irqsave(q->queue_lock, flags); | ||
378 | elv_quiesce_end(q); | ||
379 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
372 | } | 380 | } |
373 | 381 | ||
374 | void delete_partition(struct gendisk *disk, int partno) | 382 | void delete_partition(struct gendisk *disk, int partno) |
375 | { | 383 | { |
376 | struct disk_part_tbl *ptbl = disk->part_tbl; | 384 | struct disk_part_tbl *ptbl = disk->part_tbl; |
377 | struct hd_struct *part; | 385 | struct hd_struct *part; |
386 | struct request_queue *q = disk->queue; | ||
378 | 387 | ||
379 | if (partno >= ptbl->len) | 388 | if (partno >= ptbl->len) |
380 | return; | 389 | return; |
@@ -389,6 +398,10 @@ void delete_partition(struct gendisk *disk, int partno) | |||
389 | kobject_put(part->holder_dir); | 398 | kobject_put(part->holder_dir); |
390 | device_del(part_to_dev(part)); | 399 | device_del(part_to_dev(part)); |
391 | 400 | ||
401 | spin_lock_irq(q->queue_lock); | ||
402 | elv_quiesce_start(q); | ||
403 | spin_unlock_irq(q->queue_lock); | ||
404 | |||
392 | call_rcu(&part->rcu_head, delete_partition_rcu_cb); | 405 | call_rcu(&part->rcu_head, delete_partition_rcu_cb); |
393 | } | 406 | } |
394 | 407 | ||
@@ -401,7 +414,8 @@ static DEVICE_ATTR(whole_disk, S_IRUSR | S_IRGRP | S_IROTH, | |||
401 | whole_disk_show, NULL); | 414 | whole_disk_show, NULL); |
402 | 415 | ||
403 | struct hd_struct *add_partition(struct gendisk *disk, int partno, | 416 | struct hd_struct *add_partition(struct gendisk *disk, int partno, |
404 | sector_t start, sector_t len, int flags) | 417 | sector_t start, sector_t len, int flags, |
418 | struct partition_meta_info *info) | ||
405 | { | 419 | { |
406 | struct hd_struct *p; | 420 | struct hd_struct *p; |
407 | dev_t devt = MKDEV(0, 0); | 421 | dev_t devt = MKDEV(0, 0); |
@@ -438,6 +452,14 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno, | |||
438 | p->partno = partno; | 452 | p->partno = partno; |
439 | p->policy = get_disk_ro(disk); | 453 | p->policy = get_disk_ro(disk); |
440 | 454 | ||
455 | if (info) { | ||
456 | struct partition_meta_info *pinfo = alloc_part_info(disk); | ||
457 | if (!pinfo) | ||
458 | goto out_free_stats; | ||
459 | memcpy(pinfo, info, sizeof(*info)); | ||
460 | p->info = pinfo; | ||
461 | } | ||
462 | |||
441 | dname = dev_name(ddev); | 463 | dname = dev_name(ddev); |
442 | if (isdigit(dname[strlen(dname) - 1])) | 464 | if (isdigit(dname[strlen(dname) - 1])) |
443 | dev_set_name(pdev, "%sp%d", dname, partno); | 465 | dev_set_name(pdev, "%sp%d", dname, partno); |
@@ -451,7 +473,7 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno, | |||
451 | 473 | ||
452 | err = blk_alloc_devt(p, &devt); | 474 | err = blk_alloc_devt(p, &devt); |
453 | if (err) | 475 | if (err) |
454 | goto out_free_stats; | 476 | goto out_free_info; |
455 | pdev->devt = devt; | 477 | pdev->devt = devt; |
456 | 478 | ||
457 | /* delay uevent until 'holders' subdir is created */ | 479 | /* delay uevent until 'holders' subdir is created */ |
@@ -481,6 +503,8 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno, | |||
481 | 503 | ||
482 | return p; | 504 | return p; |
483 | 505 | ||
506 | out_free_info: | ||
507 | free_part_info(p); | ||
484 | out_free_stats: | 508 | out_free_stats: |
485 | free_part_stats(p); | 509 | free_part_stats(p); |
486 | out_free: | 510 | out_free: |
@@ -642,6 +666,7 @@ rescan: | |||
642 | /* add partitions */ | 666 | /* add partitions */ |
643 | for (p = 1; p < state->limit; p++) { | 667 | for (p = 1; p < state->limit; p++) { |
644 | sector_t size, from; | 668 | sector_t size, from; |
669 | struct partition_meta_info *info = NULL; | ||
645 | 670 | ||
646 | size = state->parts[p].size; | 671 | size = state->parts[p].size; |
647 | if (!size) | 672 | if (!size) |
@@ -675,8 +700,12 @@ rescan: | |||
675 | size = get_capacity(disk) - from; | 700 | size = get_capacity(disk) - from; |
676 | } | 701 | } |
677 | } | 702 | } |
703 | |||
704 | if (state->parts[p].has_info) | ||
705 | info = &state->parts[p].info; | ||
678 | part = add_partition(disk, p, from, size, | 706 | part = add_partition(disk, p, from, size, |
679 | state->parts[p].flags); | 707 | state->parts[p].flags, |
708 | &state->parts[p].info); | ||
680 | if (IS_ERR(part)) { | 709 | if (IS_ERR(part)) { |
681 | printk(KERN_ERR " %s: p%d could not be added: %ld\n", | 710 | printk(KERN_ERR " %s: p%d could not be added: %ld\n", |
682 | disk->disk_name, p, -PTR_ERR(part)); | 711 | 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/fs/partitions/efi.c b/fs/partitions/efi.c index dbb44d4bb8a7..ac0ccb5026a2 100644 --- a/fs/partitions/efi.c +++ b/fs/partitions/efi.c | |||
@@ -94,6 +94,7 @@ | |||
94 | * | 94 | * |
95 | ************************************************************/ | 95 | ************************************************************/ |
96 | #include <linux/crc32.h> | 96 | #include <linux/crc32.h> |
97 | #include <linux/ctype.h> | ||
97 | #include <linux/math64.h> | 98 | #include <linux/math64.h> |
98 | #include <linux/slab.h> | 99 | #include <linux/slab.h> |
99 | #include "check.h" | 100 | #include "check.h" |
@@ -604,6 +605,7 @@ int efi_partition(struct parsed_partitions *state) | |||
604 | gpt_entry *ptes = NULL; | 605 | gpt_entry *ptes = NULL; |
605 | u32 i; | 606 | u32 i; |
606 | unsigned ssz = bdev_logical_block_size(state->bdev) / 512; | 607 | unsigned ssz = bdev_logical_block_size(state->bdev) / 512; |
608 | u8 unparsed_guid[37]; | ||
607 | 609 | ||
608 | if (!find_valid_gpt(state, &gpt, &ptes) || !gpt || !ptes) { | 610 | if (!find_valid_gpt(state, &gpt, &ptes) || !gpt || !ptes) { |
609 | kfree(gpt); | 611 | kfree(gpt); |
@@ -614,6 +616,9 @@ int efi_partition(struct parsed_partitions *state) | |||
614 | pr_debug("GUID Partition Table is valid! Yea!\n"); | 616 | pr_debug("GUID Partition Table is valid! Yea!\n"); |
615 | 617 | ||
616 | for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) { | 618 | for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) { |
619 | struct partition_meta_info *info; | ||
620 | unsigned label_count = 0; | ||
621 | unsigned label_max; | ||
617 | u64 start = le64_to_cpu(ptes[i].starting_lba); | 622 | u64 start = le64_to_cpu(ptes[i].starting_lba); |
618 | u64 size = le64_to_cpu(ptes[i].ending_lba) - | 623 | u64 size = le64_to_cpu(ptes[i].ending_lba) - |
619 | le64_to_cpu(ptes[i].starting_lba) + 1ULL; | 624 | le64_to_cpu(ptes[i].starting_lba) + 1ULL; |
@@ -627,6 +632,26 @@ int efi_partition(struct parsed_partitions *state) | |||
627 | if (!efi_guidcmp(ptes[i].partition_type_guid, | 632 | if (!efi_guidcmp(ptes[i].partition_type_guid, |
628 | PARTITION_LINUX_RAID_GUID)) | 633 | PARTITION_LINUX_RAID_GUID)) |
629 | state->parts[i + 1].flags = ADDPART_FLAG_RAID; | 634 | state->parts[i + 1].flags = ADDPART_FLAG_RAID; |
635 | |||
636 | info = &state->parts[i + 1].info; | ||
637 | /* Instead of doing a manual swap to big endian, reuse the | ||
638 | * common ASCII hex format as the interim. | ||
639 | */ | ||
640 | efi_guid_unparse(&ptes[i].unique_partition_guid, unparsed_guid); | ||
641 | part_pack_uuid(unparsed_guid, info->uuid); | ||
642 | |||
643 | /* Naively convert UTF16-LE to 7 bits. */ | ||
644 | label_max = min(sizeof(info->volname) - 1, | ||
645 | sizeof(ptes[i].partition_name)); | ||
646 | info->volname[label_max] = 0; | ||
647 | while (label_count < label_max) { | ||
648 | u8 c = ptes[i].partition_name[label_count] & 0xff; | ||
649 | if (c && !isprint(c)) | ||
650 | c = '!'; | ||
651 | info->volname[label_count] = c; | ||
652 | label_count++; | ||
653 | } | ||
654 | state->parts[i + 1].has_info = true; | ||
630 | } | 655 | } |
631 | kfree(ptes); | 656 | kfree(ptes); |
632 | kfree(gpt); | 657 | kfree(gpt); |