lkml.org 
[lkml]   [2009]   [May]   [31]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    Subject[PATCH 2/4] partitions: add ->set_capacity block device method
    From: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
    Subject: [PATCH] partitions: add ->set_capacity block device method

    * Add ->set_capacity block device method and use it in rescan_partitions()
    to attempt enabling native capacity of the device upon detecting the
    partition which exceeds device capacity.

    * Add GENHD_FL_NATIVE_CAPACITY flag to try limit attempts of enabling
    native capacity during partition scan.

    Together with the consecutive patch implementing ->set_capacity method in
    ide-gd device driver this allows automatic disabling of Host Protected Area
    (HPA) if any partitions overlapping HPA are detected.

    Cc: Robert Hancock <hancockrwd@gmail.com>
    Cc: Frans Pop <elendil@planet.nl>
    Cc: "Andries E. Brouwer" <Andries.Brouwer@cwi.nl>
    Cc: Al Viro <viro@zeniv.linux.org.uk>
    Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
    ---
    fs/partitions/check.c | 43 ++++++++++++++++++++++++++++++++-----------
    include/linux/blkdev.h | 2 ++
    include/linux/genhd.h | 1 +
    3 files changed, 35 insertions(+), 11 deletions(-)

    Index: b/fs/partitions/check.c
    ===================================================================
    --- a/fs/partitions/check.c
    +++ b/fs/partitions/check.c
    @@ -556,28 +556,49 @@ int rescan_partitions(struct gendisk *di

    /* add partitions */
    for (p = 1; p < state->limit; p++) {
    - sector_t size = state->parts[p].size;
    - sector_t from = state->parts[p].from;
    + sector_t size, from;
    +try_scan:
    + size = state->parts[p].size;
    if (!size)
    continue;
    +
    + from = state->parts[p].from;
    if (from >= get_capacity(disk)) {
    printk(KERN_WARNING
    "%s: p%d ignored, start %llu is behind the end of the disk\n",
    disk->disk_name, p, (unsigned long long) from);
    continue;
    }
    +
    if (from + size > get_capacity(disk)) {
    - /*
    - * we can not ignore partitions of broken tables
    - * created by for example camera firmware, but we
    - * limit them to the end of the disk to avoid
    - * creating invalid block devices
    - */
    + struct block_device_operations *bdops = disk->fops;
    + unsigned long long capacity;
    +
    printk(KERN_WARNING
    - "%s: p%d size %llu exceeds device capacity, "
    - "limited to end of disk\n",
    + "%s: p%d size %llu exceeds device capacity, ",
    disk->disk_name, p, (unsigned long long) size);
    - size = get_capacity(disk) - from;
    +
    + if (bdops->set_capacity &&
    + (disk->flags & GENHD_FL_NATIVE_CAPACITY) == 0) {
    + printk(KERN_CONT "enabling native capacity\n");
    + capacity = bdops->set_capacity(disk, ~0ULL);
    + disk->flags |= GENHD_FL_NATIVE_CAPACITY;
    + if (capacity > get_capacity(disk)) {
    + set_capacity(disk, capacity);
    + check_disk_size_change(disk, bdev);
    + bdev->bd_invalidated = 0;
    + }
    + goto try_scan;
    + } else {
    + /*
    + * we can not ignore partitions of broken tables
    + * created by for example camera firmware, but
    + * we limit them to the end of the disk to avoid
    + * creating invalid block devices
    + */
    + printk(KERN_CONT "limited to end of disk\n");
    + size = get_capacity(disk) - from;
    + }
    }
    part = add_partition(disk, p, from, size,
    state->parts[p].flags);
    Index: b/include/linux/blkdev.h
    ===================================================================
    --- a/include/linux/blkdev.h
    +++ b/include/linux/blkdev.h
    @@ -1221,6 +1221,8 @@ struct block_device_operations {
    int (*direct_access) (struct block_device *, sector_t,
    void **, unsigned long *);
    int (*media_changed) (struct gendisk *);
    + unsigned long long (*set_capacity) (struct gendisk *,
    + unsigned long long);
    int (*revalidate_disk) (struct gendisk *);
    int (*getgeo)(struct block_device *, struct hd_geometry *);
    struct module *owner;
    Index: b/include/linux/genhd.h
    ===================================================================
    --- a/include/linux/genhd.h
    +++ b/include/linux/genhd.h
    @@ -114,6 +114,7 @@ struct hd_struct {
    #define GENHD_FL_UP 16
    #define GENHD_FL_SUPPRESS_PARTITION_INFO 32
    #define GENHD_FL_EXT_DEVT 64 /* allow extended devt */
    +#define GENHD_FL_NATIVE_CAPACITY 128

    #define BLK_SCSI_MAX_CMDS (256)
    #define BLK_SCSI_CMD_PER_LONG (BLK_SCSI_MAX_CMDS / (sizeof(long) * 8))

    \
     
     \ /
      Last update: 2009-05-31 16:37    [W:2.807 / U:1.472 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site