mirror of
https://github.com/lkl/linux.git
synced 2025-12-19 08:03:01 +09:00
Merge tag 'for-5.15/block-2021-08-30' of git://git.kernel.dk/linux-block
Pull block updates from Jens Axboe: "Nothing major in here - lots of good cleanups and tech debt handling, which is also evident in the diffstats. In particular: - Add disk sequence numbers (Matteo) - Discard merge fix (Ming) - Relax disk zoned reporting restrictions (Niklas) - Bio error handling zoned leak fix (Pavel) - Start of proper add_disk() error handling (Luis, Christoph) - blk crypto fix (Eric) - Non-standard GPT location support (Dmitry) - IO priority improvements and cleanups (Damien)o - blk-throtl improvements (Chunguang) - diskstats_show() stack reduction (Abd-Alrhman) - Loop scheduler selection (Bart) - Switch block layer to use kmap_local_page() (Christoph) - Remove obsolete disk_name helper (Christoph) - block_device refcounting improvements (Christoph) - Ensure gendisk always has a request queue reference (Christoph) - Misc fixes/cleanups (Shaokun, Oliver, Guoqing)" * tag 'for-5.15/block-2021-08-30' of git://git.kernel.dk/linux-block: (129 commits) sg: pass the device name to blk_trace_setup block, bfq: cleanup the repeated declaration blk-crypto: fix check for too-large dun_bytes blk-zoned: allow BLKREPORTZONE without CAP_SYS_ADMIN blk-zoned: allow zone management send operations without CAP_SYS_ADMIN block: mark blkdev_fsync static block: refine the disk_live check in del_gendisk mmc: sdhci-tegra: Enable MMC_CAP2_ALT_GPT_TEGRA mmc: block: Support alternative_gpt_sector() operation partitions/efi: Support non-standard GPT location block: Add alternative_gpt_sector() operation bio: fix page leak bio_add_hw_page failure block: remove CONFIG_DEBUG_BLOCK_EXT_DEVT block: remove a pointless call to MINOR() in device_add_disk null_blk: add error handling support for add_disk() virtio_blk: add error handling support for add_disk() block: add error handling for device_add_disk / add_disk block: return errors from disk_alloc_events block: return errors from blk_integrity_add block: call blk_register_queue earlier in device_add_disk ...
This commit is contained in:
@@ -264,7 +264,6 @@ config SYSV68_PARTITION
|
||||
|
||||
config CMDLINE_PARTITION
|
||||
bool "Command line partition support" if PARTITION_ADVANCED
|
||||
select BLK_CMDLINE_PARSER
|
||||
help
|
||||
Say Y here if you want to read the partition table from bootargs.
|
||||
The format for the command line is just like mtdparts.
|
||||
|
||||
@@ -275,7 +275,7 @@ int adfspart_check_ADFS(struct parsed_partitions *state)
|
||||
/*
|
||||
* Work out start of non-adfs partition.
|
||||
*/
|
||||
nr_sects = (state->bdev->bd_inode->i_size >> 9) - start_sect;
|
||||
nr_sects = get_capacity(state->disk) - start_sect;
|
||||
|
||||
if (start_sect) {
|
||||
switch (id) {
|
||||
@@ -540,7 +540,7 @@ int adfspart_check_EESOX(struct parsed_partitions *state)
|
||||
if (i != 0) {
|
||||
sector_t size;
|
||||
|
||||
size = get_capacity(state->bdev->bd_disk);
|
||||
size = get_capacity(state->disk);
|
||||
put_partition(state, slot++, start, size - start);
|
||||
strlcat(state->pp_buf, "\n", PAGE_SIZE);
|
||||
}
|
||||
|
||||
@@ -66,22 +66,6 @@ struct pvd {
|
||||
|
||||
#define LVM_MAXLVS 256
|
||||
|
||||
/**
|
||||
* last_lba(): return number of last logical block of device
|
||||
* @bdev: block device
|
||||
*
|
||||
* Description: Returns last LBA value on success, 0 on error.
|
||||
* This is stored (by sd and ide-geometry) in
|
||||
* the part[0] entry for this disk, and is the number of
|
||||
* physical sectors available on the disk.
|
||||
*/
|
||||
static u64 last_lba(struct block_device *bdev)
|
||||
{
|
||||
if (!bdev || !bdev->bd_inode)
|
||||
return 0;
|
||||
return (bdev->bd_inode->i_size >> 9) - 1ULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* read_lba(): Read bytes from disk, starting at given LBA
|
||||
* @state
|
||||
@@ -89,7 +73,7 @@ static u64 last_lba(struct block_device *bdev)
|
||||
* @buffer
|
||||
* @count
|
||||
*
|
||||
* Description: Reads @count bytes from @state->bdev into @buffer.
|
||||
* Description: Reads @count bytes from @state->disk into @buffer.
|
||||
* Returns number of bytes read on success, 0 on error.
|
||||
*/
|
||||
static size_t read_lba(struct parsed_partitions *state, u64 lba, u8 *buffer,
|
||||
@@ -97,7 +81,7 @@ static size_t read_lba(struct parsed_partitions *state, u64 lba, u8 *buffer,
|
||||
{
|
||||
size_t totalreadcount = 0;
|
||||
|
||||
if (!buffer || lba + count / 512 > last_lba(state->bdev))
|
||||
if (!buffer || lba + count / 512 > get_capacity(state->disk) - 1ULL)
|
||||
return 0;
|
||||
|
||||
while (count) {
|
||||
|
||||
@@ -34,7 +34,6 @@ int amiga_partition(struct parsed_partitions *state)
|
||||
int start_sect, nr_sects, blk, part, res = 0;
|
||||
int blksize = 1; /* Multiplier for disk block size */
|
||||
int slot = 1;
|
||||
char b[BDEVNAME_SIZE];
|
||||
|
||||
for (blk = 0; ; blk++, put_dev_sector(sect)) {
|
||||
if (blk == RDB_ALLOCATION_LIMIT)
|
||||
@@ -42,7 +41,7 @@ int amiga_partition(struct parsed_partitions *state)
|
||||
data = read_part_sector(state, blk, §);
|
||||
if (!data) {
|
||||
pr_err("Dev %s: unable to read RDB block %d\n",
|
||||
bdevname(state->bdev, b), blk);
|
||||
state->disk->disk_name, blk);
|
||||
res = -1;
|
||||
goto rdb_done;
|
||||
}
|
||||
@@ -64,7 +63,7 @@ int amiga_partition(struct parsed_partitions *state)
|
||||
}
|
||||
|
||||
pr_err("Dev %s: RDB in block %d has bad checksum\n",
|
||||
bdevname(state->bdev, b), blk);
|
||||
state->disk->disk_name, blk);
|
||||
}
|
||||
|
||||
/* blksize is blocks per 512 byte standard block */
|
||||
@@ -84,7 +83,7 @@ int amiga_partition(struct parsed_partitions *state)
|
||||
data = read_part_sector(state, blk, §);
|
||||
if (!data) {
|
||||
pr_err("Dev %s: unable to read partition block %d\n",
|
||||
bdevname(state->bdev, b), blk);
|
||||
state->disk->disk_name, blk);
|
||||
res = -1;
|
||||
goto rdb_done;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ int atari_partition(struct parsed_partitions *state)
|
||||
* ATARI partition scheme supports 512 lba only. If this is not
|
||||
* the case, bail early to avoid miscalculating hd_size.
|
||||
*/
|
||||
if (bdev_logical_block_size(state->bdev) != 512)
|
||||
if (queue_logical_block_size(state->disk->queue) != 512)
|
||||
return 0;
|
||||
|
||||
rs = read_part_sector(state, 0, §);
|
||||
@@ -55,7 +55,7 @@ int atari_partition(struct parsed_partitions *state)
|
||||
return -1;
|
||||
|
||||
/* Verify this is an Atari rootsector: */
|
||||
hd_size = state->bdev->bd_inode->i_size >> 9;
|
||||
hd_size = get_capacity(state->disk);
|
||||
if (!VALID_PARTITION(&rs->part[0], hd_size) &&
|
||||
!VALID_PARTITION(&rs->part[1], hd_size) &&
|
||||
!VALID_PARTITION(&rs->part[2], hd_size) &&
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* description.
|
||||
*/
|
||||
struct parsed_partitions {
|
||||
struct block_device *bdev;
|
||||
struct gendisk *disk;
|
||||
char name[BDEVNAME_SIZE];
|
||||
struct {
|
||||
sector_t from;
|
||||
|
||||
@@ -14,20 +14,248 @@
|
||||
* For further information, see "Documentation/block/cmdline-partition.rst"
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/cmdline-parser.h>
|
||||
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/slab.h>
|
||||
#include "check.h"
|
||||
|
||||
|
||||
/* partition flags */
|
||||
#define PF_RDONLY 0x01 /* Device is read only */
|
||||
#define PF_POWERUP_LOCK 0x02 /* Always locked after reset */
|
||||
|
||||
struct cmdline_subpart {
|
||||
char name[BDEVNAME_SIZE]; /* partition name, such as 'rootfs' */
|
||||
sector_t from;
|
||||
sector_t size;
|
||||
int flags;
|
||||
struct cmdline_subpart *next_subpart;
|
||||
};
|
||||
|
||||
struct cmdline_parts {
|
||||
char name[BDEVNAME_SIZE]; /* block device, such as 'mmcblk0' */
|
||||
unsigned int nr_subparts;
|
||||
struct cmdline_subpart *subpart;
|
||||
struct cmdline_parts *next_parts;
|
||||
};
|
||||
|
||||
static int parse_subpart(struct cmdline_subpart **subpart, char *partdef)
|
||||
{
|
||||
int ret = 0;
|
||||
struct cmdline_subpart *new_subpart;
|
||||
|
||||
*subpart = NULL;
|
||||
|
||||
new_subpart = kzalloc(sizeof(struct cmdline_subpart), GFP_KERNEL);
|
||||
if (!new_subpart)
|
||||
return -ENOMEM;
|
||||
|
||||
if (*partdef == '-') {
|
||||
new_subpart->size = (sector_t)(~0ULL);
|
||||
partdef++;
|
||||
} else {
|
||||
new_subpart->size = (sector_t)memparse(partdef, &partdef);
|
||||
if (new_subpart->size < (sector_t)PAGE_SIZE) {
|
||||
pr_warn("cmdline partition size is invalid.");
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (*partdef == '@') {
|
||||
partdef++;
|
||||
new_subpart->from = (sector_t)memparse(partdef, &partdef);
|
||||
} else {
|
||||
new_subpart->from = (sector_t)(~0ULL);
|
||||
}
|
||||
|
||||
if (*partdef == '(') {
|
||||
int length;
|
||||
char *next = strchr(++partdef, ')');
|
||||
|
||||
if (!next) {
|
||||
pr_warn("cmdline partition format is invalid.");
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
length = min_t(int, next - partdef,
|
||||
sizeof(new_subpart->name) - 1);
|
||||
strncpy(new_subpart->name, partdef, length);
|
||||
new_subpart->name[length] = '\0';
|
||||
|
||||
partdef = ++next;
|
||||
} else
|
||||
new_subpart->name[0] = '\0';
|
||||
|
||||
new_subpart->flags = 0;
|
||||
|
||||
if (!strncmp(partdef, "ro", 2)) {
|
||||
new_subpart->flags |= PF_RDONLY;
|
||||
partdef += 2;
|
||||
}
|
||||
|
||||
if (!strncmp(partdef, "lk", 2)) {
|
||||
new_subpart->flags |= PF_POWERUP_LOCK;
|
||||
partdef += 2;
|
||||
}
|
||||
|
||||
*subpart = new_subpart;
|
||||
return 0;
|
||||
fail:
|
||||
kfree(new_subpart);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void free_subpart(struct cmdline_parts *parts)
|
||||
{
|
||||
struct cmdline_subpart *subpart;
|
||||
|
||||
while (parts->subpart) {
|
||||
subpart = parts->subpart;
|
||||
parts->subpart = subpart->next_subpart;
|
||||
kfree(subpart);
|
||||
}
|
||||
}
|
||||
|
||||
static int parse_parts(struct cmdline_parts **parts, const char *bdevdef)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
char *next;
|
||||
int length;
|
||||
struct cmdline_subpart **next_subpart;
|
||||
struct cmdline_parts *newparts;
|
||||
char buf[BDEVNAME_SIZE + 32 + 4];
|
||||
|
||||
*parts = NULL;
|
||||
|
||||
newparts = kzalloc(sizeof(struct cmdline_parts), GFP_KERNEL);
|
||||
if (!newparts)
|
||||
return -ENOMEM;
|
||||
|
||||
next = strchr(bdevdef, ':');
|
||||
if (!next) {
|
||||
pr_warn("cmdline partition has no block device.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
length = min_t(int, next - bdevdef, sizeof(newparts->name) - 1);
|
||||
strncpy(newparts->name, bdevdef, length);
|
||||
newparts->name[length] = '\0';
|
||||
newparts->nr_subparts = 0;
|
||||
|
||||
next_subpart = &newparts->subpart;
|
||||
|
||||
while (next && *(++next)) {
|
||||
bdevdef = next;
|
||||
next = strchr(bdevdef, ',');
|
||||
|
||||
length = (!next) ? (sizeof(buf) - 1) :
|
||||
min_t(int, next - bdevdef, sizeof(buf) - 1);
|
||||
|
||||
strncpy(buf, bdevdef, length);
|
||||
buf[length] = '\0';
|
||||
|
||||
ret = parse_subpart(next_subpart, buf);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
newparts->nr_subparts++;
|
||||
next_subpart = &(*next_subpart)->next_subpart;
|
||||
}
|
||||
|
||||
if (!newparts->subpart) {
|
||||
pr_warn("cmdline partition has no valid partition.");
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
*parts = newparts;
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
free_subpart(newparts);
|
||||
kfree(newparts);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void cmdline_parts_free(struct cmdline_parts **parts)
|
||||
{
|
||||
struct cmdline_parts *next_parts;
|
||||
|
||||
while (*parts) {
|
||||
next_parts = (*parts)->next_parts;
|
||||
free_subpart(*parts);
|
||||
kfree(*parts);
|
||||
*parts = next_parts;
|
||||
}
|
||||
}
|
||||
|
||||
static int cmdline_parts_parse(struct cmdline_parts **parts,
|
||||
const char *cmdline)
|
||||
{
|
||||
int ret;
|
||||
char *buf;
|
||||
char *pbuf;
|
||||
char *next;
|
||||
struct cmdline_parts **next_parts;
|
||||
|
||||
*parts = NULL;
|
||||
|
||||
next = pbuf = buf = kstrdup(cmdline, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
next_parts = parts;
|
||||
|
||||
while (next && *pbuf) {
|
||||
next = strchr(pbuf, ';');
|
||||
if (next)
|
||||
*next = '\0';
|
||||
|
||||
ret = parse_parts(next_parts, pbuf);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
if (next)
|
||||
pbuf = ++next;
|
||||
|
||||
next_parts = &(*next_parts)->next_parts;
|
||||
}
|
||||
|
||||
if (!*parts) {
|
||||
pr_warn("cmdline partition has no valid partition.");
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
done:
|
||||
kfree(buf);
|
||||
return ret;
|
||||
|
||||
fail:
|
||||
cmdline_parts_free(parts);
|
||||
goto done;
|
||||
}
|
||||
|
||||
static struct cmdline_parts *cmdline_parts_find(struct cmdline_parts *parts,
|
||||
const char *bdev)
|
||||
{
|
||||
while (parts && strncmp(bdev, parts->name, sizeof(parts->name)))
|
||||
parts = parts->next_parts;
|
||||
return parts;
|
||||
}
|
||||
|
||||
static char *cmdline;
|
||||
static struct cmdline_parts *bdev_parts;
|
||||
|
||||
static int add_part(int slot, struct cmdline_subpart *subpart, void *param)
|
||||
static int add_part(int slot, struct cmdline_subpart *subpart,
|
||||
struct parsed_partitions *state)
|
||||
{
|
||||
int label_min;
|
||||
struct partition_meta_info *info;
|
||||
char tmp[sizeof(info->volname) + 4];
|
||||
struct parsed_partitions *state = (struct parsed_partitions *)param;
|
||||
|
||||
if (slot >= state->limit)
|
||||
return 1;
|
||||
@@ -50,6 +278,35 @@ static int add_part(int slot, struct cmdline_subpart *subpart, void *param)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmdline_parts_set(struct cmdline_parts *parts, sector_t disk_size,
|
||||
struct parsed_partitions *state)
|
||||
{
|
||||
sector_t from = 0;
|
||||
struct cmdline_subpart *subpart;
|
||||
int slot = 1;
|
||||
|
||||
for (subpart = parts->subpart; subpart;
|
||||
subpart = subpart->next_subpart, slot++) {
|
||||
if (subpart->from == (sector_t)(~0ULL))
|
||||
subpart->from = from;
|
||||
else
|
||||
from = subpart->from;
|
||||
|
||||
if (from >= disk_size)
|
||||
break;
|
||||
|
||||
if (subpart->size > (disk_size - from))
|
||||
subpart->size = disk_size - from;
|
||||
|
||||
from += subpart->size;
|
||||
|
||||
if (add_part(slot, subpart, state))
|
||||
break;
|
||||
}
|
||||
|
||||
return slot;
|
||||
}
|
||||
|
||||
static int __init cmdline_parts_setup(char *s)
|
||||
{
|
||||
cmdline = s;
|
||||
@@ -123,7 +380,6 @@ static void cmdline_parts_verifier(int slot, struct parsed_partitions *state)
|
||||
int cmdline_partition(struct parsed_partitions *state)
|
||||
{
|
||||
sector_t disk_size;
|
||||
char bdev[BDEVNAME_SIZE];
|
||||
struct cmdline_parts *parts;
|
||||
|
||||
if (cmdline) {
|
||||
@@ -140,14 +396,13 @@ int cmdline_partition(struct parsed_partitions *state)
|
||||
if (!bdev_parts)
|
||||
return 0;
|
||||
|
||||
bdevname(state->bdev, bdev);
|
||||
parts = cmdline_parts_find(bdev_parts, bdev);
|
||||
parts = cmdline_parts_find(bdev_parts, state->disk->disk_name);
|
||||
if (!parts)
|
||||
return 0;
|
||||
|
||||
disk_size = get_capacity(state->bdev->bd_disk) << 9;
|
||||
disk_size = get_capacity(state->disk) << 9;
|
||||
|
||||
cmdline_parts_set(parts, disk_size, 1, add_part, (void *)state);
|
||||
cmdline_parts_set(parts, disk_size, state);
|
||||
cmdline_parts_verifier(1, state);
|
||||
|
||||
strlcat(state->pp_buf, "\n", PAGE_SIZE);
|
||||
|
||||
@@ -135,8 +135,8 @@ static struct parsed_partitions *check_partition(struct gendisk *hd)
|
||||
}
|
||||
state->pp_buf[0] = '\0';
|
||||
|
||||
state->bdev = hd->part0;
|
||||
disk_name(hd, 0, state->name);
|
||||
state->disk = hd;
|
||||
snprintf(state->name, BDEVNAME_SIZE, "%s", hd->disk_name);
|
||||
snprintf(state->pp_buf, PAGE_SIZE, " %s:", state->name);
|
||||
if (isdigit(state->name[strlen(state->name)-1]))
|
||||
sprintf(state->name, "p");
|
||||
@@ -259,9 +259,8 @@ static const struct attribute_group *part_attr_groups[] = {
|
||||
|
||||
static void part_release(struct device *dev)
|
||||
{
|
||||
if (MAJOR(dev->devt) == BLOCK_EXT_MAJOR)
|
||||
blk_free_ext_minor(MINOR(dev->devt));
|
||||
bdput(dev_to_bdev(dev));
|
||||
put_disk(dev_to_bdev(dev)->bd_disk);
|
||||
iput(dev_to_bdev(dev)->bd_inode);
|
||||
}
|
||||
|
||||
static int part_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||
@@ -281,12 +280,10 @@ struct device_type part_type = {
|
||||
.uevent = part_uevent,
|
||||
};
|
||||
|
||||
/*
|
||||
* Must be called either with open_mutex held, before a disk can be opened or
|
||||
* after all disk users are gone.
|
||||
*/
|
||||
static void delete_partition(struct block_device *part)
|
||||
{
|
||||
lockdep_assert_held(&part->bd_disk->open_mutex);
|
||||
|
||||
fsync_bdev(part);
|
||||
__invalidate_device(part, true);
|
||||
|
||||
@@ -351,20 +348,17 @@ static struct block_device *add_partition(struct gendisk *disk, int partno,
|
||||
if (xa_load(&disk->part_tbl, partno))
|
||||
return ERR_PTR(-EBUSY);
|
||||
|
||||
/* ensure we always have a reference to the whole disk */
|
||||
get_device(disk_to_dev(disk));
|
||||
|
||||
err = -ENOMEM;
|
||||
bdev = bdev_alloc(disk, partno);
|
||||
if (!bdev)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
goto out_put_disk;
|
||||
|
||||
bdev->bd_start_sect = start;
|
||||
bdev_set_nr_sectors(bdev, len);
|
||||
|
||||
if (info) {
|
||||
err = -ENOMEM;
|
||||
bdev->bd_meta_info = kmemdup(info, sizeof(*info), GFP_KERNEL);
|
||||
if (!bdev->bd_meta_info)
|
||||
goto out_bdput;
|
||||
}
|
||||
|
||||
pdev = &bdev->bd_device;
|
||||
dname = dev_name(ddev);
|
||||
if (isdigit(dname[strlen(dname) - 1]))
|
||||
@@ -388,6 +382,13 @@ static struct block_device *add_partition(struct gendisk *disk, int partno,
|
||||
}
|
||||
pdev->devt = devt;
|
||||
|
||||
if (info) {
|
||||
err = -ENOMEM;
|
||||
bdev->bd_meta_info = kmemdup(info, sizeof(*info), GFP_KERNEL);
|
||||
if (!bdev->bd_meta_info)
|
||||
goto out_put;
|
||||
}
|
||||
|
||||
/* delay uevent until 'holders' subdir is created */
|
||||
dev_set_uevent_suppress(pdev, 1);
|
||||
err = device_add(pdev);
|
||||
@@ -417,14 +418,13 @@ static struct block_device *add_partition(struct gendisk *disk, int partno,
|
||||
kobject_uevent(&pdev->kobj, KOBJ_ADD);
|
||||
return bdev;
|
||||
|
||||
out_bdput:
|
||||
bdput(bdev);
|
||||
return ERR_PTR(err);
|
||||
out_del:
|
||||
kobject_put(bdev->bd_holder_dir);
|
||||
device_del(pdev);
|
||||
out_put:
|
||||
put_device(pdev);
|
||||
out_put_disk:
|
||||
put_disk(disk);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
@@ -449,15 +449,14 @@ static bool partition_overlaps(struct gendisk *disk, sector_t start,
|
||||
return overlap;
|
||||
}
|
||||
|
||||
int bdev_add_partition(struct block_device *bdev, int partno,
|
||||
sector_t start, sector_t length)
|
||||
int bdev_add_partition(struct gendisk *disk, int partno, sector_t start,
|
||||
sector_t length)
|
||||
{
|
||||
struct block_device *part;
|
||||
struct gendisk *disk = bdev->bd_disk;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&disk->open_mutex);
|
||||
if (!(disk->flags & GENHD_FL_UP)) {
|
||||
if (!disk_live(disk)) {
|
||||
ret = -ENXIO;
|
||||
goto out;
|
||||
}
|
||||
@@ -475,13 +474,13 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bdev_del_partition(struct block_device *bdev, int partno)
|
||||
int bdev_del_partition(struct gendisk *disk, int partno)
|
||||
{
|
||||
struct block_device *part = NULL;
|
||||
int ret = -ENXIO;
|
||||
|
||||
mutex_lock(&bdev->bd_disk->open_mutex);
|
||||
part = xa_load(&bdev->bd_disk->part_tbl, partno);
|
||||
mutex_lock(&disk->open_mutex);
|
||||
part = xa_load(&disk->part_tbl, partno);
|
||||
if (!part)
|
||||
goto out_unlock;
|
||||
|
||||
@@ -492,18 +491,18 @@ int bdev_del_partition(struct block_device *bdev, int partno)
|
||||
delete_partition(part);
|
||||
ret = 0;
|
||||
out_unlock:
|
||||
mutex_unlock(&bdev->bd_disk->open_mutex);
|
||||
mutex_unlock(&disk->open_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bdev_resize_partition(struct block_device *bdev, int partno,
|
||||
sector_t start, sector_t length)
|
||||
int bdev_resize_partition(struct gendisk *disk, int partno, sector_t start,
|
||||
sector_t length)
|
||||
{
|
||||
struct block_device *part = NULL;
|
||||
int ret = -ENXIO;
|
||||
|
||||
mutex_lock(&bdev->bd_disk->open_mutex);
|
||||
part = xa_load(&bdev->bd_disk->part_tbl, partno);
|
||||
mutex_lock(&disk->open_mutex);
|
||||
part = xa_load(&disk->part_tbl, partno);
|
||||
if (!part)
|
||||
goto out_unlock;
|
||||
|
||||
@@ -512,14 +511,14 @@ int bdev_resize_partition(struct block_device *bdev, int partno,
|
||||
goto out_unlock;
|
||||
|
||||
ret = -EBUSY;
|
||||
if (partition_overlaps(bdev->bd_disk, start, length, partno))
|
||||
if (partition_overlaps(disk, start, length, partno))
|
||||
goto out_unlock;
|
||||
|
||||
bdev_set_nr_sectors(part, length);
|
||||
|
||||
ret = 0;
|
||||
out_unlock:
|
||||
mutex_unlock(&bdev->bd_disk->open_mutex);
|
||||
mutex_unlock(&disk->open_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -667,7 +666,7 @@ int bdev_disk_changed(struct gendisk *disk, bool invalidate)
|
||||
|
||||
lockdep_assert_held(&disk->open_mutex);
|
||||
|
||||
if (!(disk->flags & GENHD_FL_UP))
|
||||
if (!disk_live(disk))
|
||||
return -ENXIO;
|
||||
|
||||
rescan:
|
||||
@@ -715,10 +714,10 @@ EXPORT_SYMBOL_GPL(bdev_disk_changed);
|
||||
|
||||
void *read_part_sector(struct parsed_partitions *state, sector_t n, Sector *p)
|
||||
{
|
||||
struct address_space *mapping = state->bdev->bd_inode->i_mapping;
|
||||
struct address_space *mapping = state->disk->part0->bd_inode->i_mapping;
|
||||
struct page *page;
|
||||
|
||||
if (n >= get_capacity(state->bdev->bd_disk)) {
|
||||
if (n >= get_capacity(state->disk)) {
|
||||
state->access_beyond_eod = true;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -124,19 +124,17 @@ efi_crc32(const void *buf, unsigned long len)
|
||||
|
||||
/**
|
||||
* last_lba(): return number of last logical block of device
|
||||
* @bdev: block device
|
||||
* @disk: block device
|
||||
*
|
||||
* Description: Returns last LBA value on success, 0 on error.
|
||||
* This is stored (by sd and ide-geometry) in
|
||||
* the part[0] entry for this disk, and is the number of
|
||||
* physical sectors available on the disk.
|
||||
*/
|
||||
static u64 last_lba(struct block_device *bdev)
|
||||
static u64 last_lba(struct gendisk *disk)
|
||||
{
|
||||
if (!bdev || !bdev->bd_inode)
|
||||
return 0;
|
||||
return div_u64(bdev->bd_inode->i_size,
|
||||
bdev_logical_block_size(bdev)) - 1ULL;
|
||||
return div_u64(disk->part0->bd_inode->i_size,
|
||||
queue_logical_block_size(disk->queue)) - 1ULL;
|
||||
}
|
||||
|
||||
static inline int pmbr_part_valid(gpt_mbr_record *part)
|
||||
@@ -231,17 +229,17 @@ done:
|
||||
* @buffer: destination buffer
|
||||
* @count: bytes to read
|
||||
*
|
||||
* Description: Reads @count bytes from @state->bdev into @buffer.
|
||||
* Description: Reads @count bytes from @state->disk into @buffer.
|
||||
* Returns number of bytes read on success, 0 on error.
|
||||
*/
|
||||
static size_t read_lba(struct parsed_partitions *state,
|
||||
u64 lba, u8 *buffer, size_t count)
|
||||
{
|
||||
size_t totalreadcount = 0;
|
||||
struct block_device *bdev = state->bdev;
|
||||
sector_t n = lba * (bdev_logical_block_size(bdev) / 512);
|
||||
sector_t n = lba *
|
||||
(queue_logical_block_size(state->disk->queue) / 512);
|
||||
|
||||
if (!buffer || lba > last_lba(bdev))
|
||||
if (!buffer || lba > last_lba(state->disk))
|
||||
return 0;
|
||||
|
||||
while (count) {
|
||||
@@ -302,14 +300,14 @@ static gpt_entry *alloc_read_gpt_entries(struct parsed_partitions *state,
|
||||
* @lba: the Logical Block Address of the partition table
|
||||
*
|
||||
* Description: returns GPT header on success, NULL on error. Allocates
|
||||
* and fills a GPT header starting at @ from @state->bdev.
|
||||
* and fills a GPT header starting at @ from @state->disk.
|
||||
* Note: remember to free gpt when finished with it.
|
||||
*/
|
||||
static gpt_header *alloc_read_gpt_header(struct parsed_partitions *state,
|
||||
u64 lba)
|
||||
{
|
||||
gpt_header *gpt;
|
||||
unsigned ssz = bdev_logical_block_size(state->bdev);
|
||||
unsigned ssz = queue_logical_block_size(state->disk->queue);
|
||||
|
||||
gpt = kmalloc(ssz, GFP_KERNEL);
|
||||
if (!gpt)
|
||||
@@ -356,10 +354,10 @@ static int is_gpt_valid(struct parsed_partitions *state, u64 lba,
|
||||
|
||||
/* Check the GUID Partition Table header size is too big */
|
||||
if (le32_to_cpu((*gpt)->header_size) >
|
||||
bdev_logical_block_size(state->bdev)) {
|
||||
queue_logical_block_size(state->disk->queue)) {
|
||||
pr_debug("GUID Partition Table Header size is too large: %u > %u\n",
|
||||
le32_to_cpu((*gpt)->header_size),
|
||||
bdev_logical_block_size(state->bdev));
|
||||
queue_logical_block_size(state->disk->queue));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -395,7 +393,7 @@ static int is_gpt_valid(struct parsed_partitions *state, u64 lba,
|
||||
/* Check the first_usable_lba and last_usable_lba are
|
||||
* within the disk.
|
||||
*/
|
||||
lastlba = last_lba(state->bdev);
|
||||
lastlba = last_lba(state->disk);
|
||||
if (le64_to_cpu((*gpt)->first_usable_lba) > lastlba) {
|
||||
pr_debug("GPT: first_usable_lba incorrect: %lld > %lld\n",
|
||||
(unsigned long long)le64_to_cpu((*gpt)->first_usable_lba),
|
||||
@@ -587,13 +585,15 @@ static int find_valid_gpt(struct parsed_partitions *state, gpt_header **gpt,
|
||||
gpt_header *pgpt = NULL, *agpt = NULL;
|
||||
gpt_entry *pptes = NULL, *aptes = NULL;
|
||||
legacy_mbr *legacymbr;
|
||||
sector_t total_sectors = i_size_read(state->bdev->bd_inode) >> 9;
|
||||
struct gendisk *disk = state->disk;
|
||||
const struct block_device_operations *fops = disk->fops;
|
||||
sector_t total_sectors = get_capacity(state->disk);
|
||||
u64 lastlba;
|
||||
|
||||
if (!ptes)
|
||||
return 0;
|
||||
|
||||
lastlba = last_lba(state->bdev);
|
||||
lastlba = last_lba(state->disk);
|
||||
if (!force_gpt) {
|
||||
/* This will be added to the EFI Spec. per Intel after v1.02. */
|
||||
legacymbr = kzalloc(sizeof(*legacymbr), GFP_KERNEL);
|
||||
@@ -621,6 +621,16 @@ static int find_valid_gpt(struct parsed_partitions *state, gpt_header **gpt,
|
||||
if (!good_agpt && force_gpt)
|
||||
good_agpt = is_gpt_valid(state, lastlba, &agpt, &aptes);
|
||||
|
||||
if (!good_agpt && force_gpt && fops->alternative_gpt_sector) {
|
||||
sector_t agpt_sector;
|
||||
int err;
|
||||
|
||||
err = fops->alternative_gpt_sector(disk, &agpt_sector);
|
||||
if (!err)
|
||||
good_agpt = is_gpt_valid(state, agpt_sector,
|
||||
&agpt, &aptes);
|
||||
}
|
||||
|
||||
/* The obviously unsuccessful case */
|
||||
if (!good_pgpt && !good_agpt)
|
||||
goto fail;
|
||||
@@ -705,7 +715,7 @@ int efi_partition(struct parsed_partitions *state)
|
||||
gpt_header *gpt = NULL;
|
||||
gpt_entry *ptes = NULL;
|
||||
u32 i;
|
||||
unsigned ssz = bdev_logical_block_size(state->bdev) / 512;
|
||||
unsigned ssz = queue_logical_block_size(state->disk->queue) / 512;
|
||||
|
||||
if (!find_valid_gpt(state, &gpt, &ptes) || !gpt || !ptes) {
|
||||
kfree(gpt);
|
||||
@@ -722,7 +732,7 @@ int efi_partition(struct parsed_partitions *state)
|
||||
u64 size = le64_to_cpu(ptes[i].ending_lba) -
|
||||
le64_to_cpu(ptes[i].starting_lba) + 1ULL;
|
||||
|
||||
if (!is_pte_valid(&ptes[i], last_lba(state->bdev)))
|
||||
if (!is_pte_valid(&ptes[i], last_lba(state->disk)))
|
||||
continue;
|
||||
|
||||
put_partition(state, i+1, start * ssz, size * ssz);
|
||||
|
||||
@@ -290,8 +290,8 @@ static int find_cms1_partitions(struct parsed_partitions *state,
|
||||
int ibm_partition(struct parsed_partitions *state)
|
||||
{
|
||||
int (*fn)(struct gendisk *disk, dasd_information2_t *info);
|
||||
struct block_device *bdev = state->bdev;
|
||||
struct gendisk *disk = bdev->bd_disk;
|
||||
struct gendisk *disk = state->disk;
|
||||
struct block_device *bdev = disk->part0;
|
||||
int blocksize, res;
|
||||
loff_t i_size, offset, size;
|
||||
dasd_information2_t *info;
|
||||
|
||||
@@ -304,7 +304,7 @@ static bool ldm_validate_privheads(struct parsed_partitions *state,
|
||||
}
|
||||
}
|
||||
|
||||
num_sects = state->bdev->bd_inode->i_size >> 9;
|
||||
num_sects = get_capacity(state->disk);
|
||||
|
||||
if ((ph[0]->config_start > num_sects) ||
|
||||
((ph[0]->config_start + ph[0]->config_size) > num_sects)) {
|
||||
@@ -339,11 +339,11 @@ out:
|
||||
/**
|
||||
* ldm_validate_tocblocks - Validate the table of contents and its backups
|
||||
* @state: Partition check state including device holding the LDM Database
|
||||
* @base: Offset, into @state->bdev, of the database
|
||||
* @base: Offset, into @state->disk, of the database
|
||||
* @ldb: Cache of the database structures
|
||||
*
|
||||
* Find and compare the four tables of contents of the LDM Database stored on
|
||||
* @state->bdev and return the parsed information into @toc1.
|
||||
* @state->disk and return the parsed information into @toc1.
|
||||
*
|
||||
* The offsets and sizes of the configs are range-checked against a privhead.
|
||||
*
|
||||
@@ -486,8 +486,8 @@ out:
|
||||
* only likely to happen if the underlying device is strange. If that IS
|
||||
* the case we should return zero to let someone else try.
|
||||
*
|
||||
* Return: 'true' @state->bdev is a dynamic disk
|
||||
* 'false' @state->bdev is not a dynamic disk, or an error occurred
|
||||
* Return: 'true' @state->disk is a dynamic disk
|
||||
* 'false' @state->disk is not a dynamic disk, or an error occurred
|
||||
*/
|
||||
static bool ldm_validate_partition_table(struct parsed_partitions *state)
|
||||
{
|
||||
@@ -1340,7 +1340,7 @@ static bool ldm_frag_commit (struct list_head *frags, struct ldmdb *ldb)
|
||||
/**
|
||||
* ldm_get_vblks - Read the on-disk database of VBLKs into memory
|
||||
* @state: Partition check state including device holding the LDM Database
|
||||
* @base: Offset, into @state->bdev, of the database
|
||||
* @base: Offset, into @state->disk, of the database
|
||||
* @ldb: Cache of the database structures
|
||||
*
|
||||
* To use the information from the VBLKs, they need to be read from the disk,
|
||||
@@ -1432,10 +1432,10 @@ static void ldm_free_vblks (struct list_head *lh)
|
||||
* example, if the device is hda, we would have: hda1: LDM database, hda2, hda3,
|
||||
* and so on: the actual data containing partitions.
|
||||
*
|
||||
* Return: 1 Success, @state->bdev is a dynamic disk and we handled it
|
||||
* 0 Success, @state->bdev is not a dynamic disk
|
||||
* Return: 1 Success, @state->disk is a dynamic disk and we handled it
|
||||
* 0 Success, @state->disk is not a dynamic disk
|
||||
* -1 An error occurred before enough information had been read
|
||||
* Or @state->bdev is a dynamic disk, but it may be corrupted
|
||||
* Or @state->disk is a dynamic disk, but it may be corrupted
|
||||
*/
|
||||
int ldm_partition(struct parsed_partitions *state)
|
||||
{
|
||||
|
||||
@@ -133,7 +133,7 @@ int mac_partition(struct parsed_partitions *state)
|
||||
}
|
||||
#ifdef CONFIG_PPC_PMAC
|
||||
if (found_root_goodness)
|
||||
note_bootable_part(state->bdev->bd_dev, found_root,
|
||||
note_bootable_part(state->disk->part0->bd_dev, found_root,
|
||||
found_root_goodness);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -135,11 +135,12 @@ static void parse_extended(struct parsed_partitions *state,
|
||||
Sector sect;
|
||||
unsigned char *data;
|
||||
sector_t this_sector, this_size;
|
||||
sector_t sector_size = bdev_logical_block_size(state->bdev) / 512;
|
||||
sector_t sector_size;
|
||||
int loopct = 0; /* number of links followed
|
||||
without finding a data partition */
|
||||
int i;
|
||||
|
||||
sector_size = queue_logical_block_size(state->disk->queue) / 512;
|
||||
this_sector = first_sector;
|
||||
this_size = first_size;
|
||||
|
||||
@@ -579,7 +580,7 @@ static struct {
|
||||
|
||||
int msdos_partition(struct parsed_partitions *state)
|
||||
{
|
||||
sector_t sector_size = bdev_logical_block_size(state->bdev) / 512;
|
||||
sector_t sector_size;
|
||||
Sector sect;
|
||||
unsigned char *data;
|
||||
struct msdos_partition *p;
|
||||
@@ -587,6 +588,7 @@ int msdos_partition(struct parsed_partitions *state)
|
||||
int slot;
|
||||
u32 disksig;
|
||||
|
||||
sector_size = queue_logical_block_size(state->disk->queue) / 512;
|
||||
data = read_part_sector(state, 0, §);
|
||||
if (!data)
|
||||
return -1;
|
||||
|
||||
@@ -43,7 +43,6 @@ int sgi_partition(struct parsed_partitions *state)
|
||||
Sector sect;
|
||||
struct sgi_disklabel *label;
|
||||
struct sgi_partition *p;
|
||||
char b[BDEVNAME_SIZE];
|
||||
|
||||
label = read_part_sector(state, 0, §);
|
||||
if (!label)
|
||||
@@ -52,7 +51,7 @@ int sgi_partition(struct parsed_partitions *state)
|
||||
magic = label->magic_mushroom;
|
||||
if(be32_to_cpu(magic) != SGI_LABEL_MAGIC) {
|
||||
/*printk("Dev %s SGI disklabel: bad magic %08x\n",
|
||||
bdevname(bdev, b), be32_to_cpu(magic));*/
|
||||
state->disk->disk_name, be32_to_cpu(magic));*/
|
||||
put_dev_sector(sect);
|
||||
return 0;
|
||||
}
|
||||
@@ -63,7 +62,7 @@ int sgi_partition(struct parsed_partitions *state)
|
||||
}
|
||||
if(csum) {
|
||||
printk(KERN_WARNING "Dev %s SGI disklabel: csum bad, label corrupted\n",
|
||||
bdevname(state->bdev, b));
|
||||
state->disk->disk_name);
|
||||
put_dev_sector(sect);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -65,7 +65,6 @@ int sun_partition(struct parsed_partitions *state)
|
||||
} * label;
|
||||
struct sun_partition *p;
|
||||
unsigned long spc;
|
||||
char b[BDEVNAME_SIZE];
|
||||
int use_vtoc;
|
||||
int nparts;
|
||||
|
||||
@@ -76,7 +75,7 @@ int sun_partition(struct parsed_partitions *state)
|
||||
p = label->partitions;
|
||||
if (be16_to_cpu(label->magic) != SUN_LABEL_MAGIC) {
|
||||
/* printk(KERN_INFO "Dev %s Sun disklabel: bad magic %04x\n",
|
||||
bdevname(bdev, b), be16_to_cpu(label->magic)); */
|
||||
state->disk->disk_name, be16_to_cpu(label->magic)); */
|
||||
put_dev_sector(sect);
|
||||
return 0;
|
||||
}
|
||||
@@ -86,7 +85,7 @@ int sun_partition(struct parsed_partitions *state)
|
||||
csum ^= *ush--;
|
||||
if (csum) {
|
||||
printk("Dev %s Sun disklabel: Csum bad, label corrupted\n",
|
||||
bdevname(state->bdev, b));
|
||||
state->disk->disk_name);
|
||||
put_dev_sector(sect);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user