From: Christoph Hellwig <hch@lst.de>
To: Jens Axboe <axboe@kernel.dk>, Jan Kara <jack@suse.cz>
Cc: linux-block@vger.kernel.org, linux-s390@vger.kernel.org,
Hannes Reinecke <hare@suse.de>
Subject: [PATCH 1/7] block: refactor rescan_partitions
Date: Thu, 14 Nov 2019 15:34:32 +0100 [thread overview]
Message-ID: <20191114143438.14681-2-hch@lst.de> (raw)
In-Reply-To: <20191114143438.14681-1-hch@lst.de>
Split out a helper that adds one single partition, and another one
calling that dealing with the parsed_partitions state. This makes
it much more obvious how we clean up all state and start again when
using the rescan label.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Hannes Reinecke <hare@suse.de>
---
block/partition-generic.c | 172 +++++++++++++++++++++-----------------
1 file changed, 94 insertions(+), 78 deletions(-)
diff --git a/block/partition-generic.c b/block/partition-generic.c
index 31bff3fb28af..0909f66aab9d 100644
--- a/block/partition-generic.c
+++ b/block/partition-generic.c
@@ -459,128 +459,144 @@ static int drop_partitions(struct gendisk *disk, struct block_device *bdev)
return 0;
}
-int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
+static bool blk_add_partition(struct gendisk *disk, struct block_device *bdev,
+ struct parsed_partitions *state, int p)
{
- struct parsed_partitions *state = NULL;
+ sector_t size = state->parts[p].size;
+ sector_t from = state->parts[p].from;
struct hd_struct *part;
- int p, highest, res;
-rescan:
- if (state && !IS_ERR(state)) {
- free_partitions(state);
- state = NULL;
+
+ if (!size)
+ return true;
+
+ if (from >= get_capacity(disk)) {
+ printk(KERN_WARNING
+ "%s: p%d start %llu is beyond EOD, ",
+ disk->disk_name, p, (unsigned long long) from);
+ if (disk_unlock_native_capacity(disk))
+ return false;
+ return true;
}
- res = drop_partitions(disk, bdev);
- if (res)
- return res;
+ if (from + size > get_capacity(disk)) {
+ printk(KERN_WARNING
+ "%s: p%d size %llu extends beyond EOD, ",
+ disk->disk_name, p, (unsigned long long) size);
- if (disk->fops->revalidate_disk)
- disk->fops->revalidate_disk(disk);
- check_disk_size_change(disk, bdev, true);
- bdev->bd_invalidated = 0;
- if (!get_capacity(disk) || !(state = check_partition(disk, bdev)))
+ if (disk_unlock_native_capacity(disk))
+ return false;
+
+ /*
+ * 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.
+ */
+ size = get_capacity(disk) - from;
+ }
+
+ part = add_partition(disk, p, from, size, state->parts[p].flags,
+ &state->parts[p].info);
+ if (IS_ERR(part)) {
+ printk(KERN_ERR " %s: p%d could not be added: %ld\n",
+ disk->disk_name, p, -PTR_ERR(part));
+ return true;
+ }
+
+#ifdef CONFIG_BLK_DEV_MD
+ if (state->parts[p].flags & ADDPART_FLAG_RAID)
+ md_autodetect_dev(part_to_dev(part)->devt);
+#endif
+ return true;
+}
+
+static int blk_add_partitions(struct gendisk *disk, struct block_device *bdev)
+{
+ struct parsed_partitions *state;
+ int ret = -EAGAIN, p, highest;
+
+ state = check_partition(disk, bdev);
+ if (!state)
return 0;
if (IS_ERR(state)) {
/*
- * I/O error reading the partition table. If any
- * partition code tried to read beyond EOD, retry
- * after unlocking native capacity.
+ * I/O error reading the partition table. If we tried to read
+ * beyond EOD, retry after unlocking the native capacity.
*/
if (PTR_ERR(state) == -ENOSPC) {
printk(KERN_WARNING "%s: partition table beyond EOD, ",
disk->disk_name);
if (disk_unlock_native_capacity(disk))
- goto rescan;
+ return -EAGAIN;
}
return -EIO;
}
- /* Partitions are not supported on zoned block devices */
+ /*
+ * Partitions are not supported on zoned block devices.
+ */
if (bdev_is_zoned(bdev)) {
pr_warn("%s: ignoring partition table on zoned block device\n",
disk->disk_name);
- goto out;
+ ret = 0;
+ goto out_free_state;
}
/*
- * If any partition code tried to read beyond EOD, try
- * unlocking native capacity even if partition table is
- * successfully read as we could be missing some partitions.
+ * If we read beyond EOD, try unlocking native capacity even if the
+ * partition table was successfully read as we could be missing some
+ * partitions.
*/
if (state->access_beyond_eod) {
printk(KERN_WARNING
"%s: partition table partially beyond EOD, ",
disk->disk_name);
if (disk_unlock_native_capacity(disk))
- goto rescan;
+ goto out_free_state;
}
/* tell userspace that the media / partition table may have changed */
kobject_uevent(&disk_to_dev(disk)->kobj, KOBJ_CHANGE);
- /* Detect the highest partition number and preallocate
- * disk->part_tbl. This is an optimization and not strictly
- * necessary.
+ /*
+ * Detect the highest partition number and preallocate disk->part_tbl.
+ * This is an optimization and not strictly necessary.
*/
for (p = 1, highest = 0; p < state->limit; p++)
if (state->parts[p].size)
highest = p;
-
disk_expand_part_tbl(disk, highest);
- /* add partitions */
- for (p = 1; p < state->limit; p++) {
- sector_t size, from;
+ for (p = 1; p < state->limit; p++)
+ if (!blk_add_partition(disk, bdev, state, p))
+ goto out_free_state;
- size = state->parts[p].size;
- if (!size)
- continue;
+ ret = 0;
+out_free_state:
+ free_partitions(state);
+ return ret;
+}
- from = state->parts[p].from;
- if (from >= get_capacity(disk)) {
- printk(KERN_WARNING
- "%s: p%d start %llu is beyond EOD, ",
- disk->disk_name, p, (unsigned long long) from);
- if (disk_unlock_native_capacity(disk))
- goto rescan;
- continue;
- }
+int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
+{
+ int ret;
- if (from + size > get_capacity(disk)) {
- printk(KERN_WARNING
- "%s: p%d size %llu extends beyond EOD, ",
- disk->disk_name, p, (unsigned long long) size);
-
- if (disk_unlock_native_capacity(disk)) {
- /* free state and restart */
- goto rescan;
- } 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
- */
- size = get_capacity(disk) - from;
- }
- }
+rescan:
+ ret = drop_partitions(disk, bdev);
+ if (ret)
+ return ret;
- part = add_partition(disk, p, from, size,
- state->parts[p].flags,
- &state->parts[p].info);
- if (IS_ERR(part)) {
- printk(KERN_ERR " %s: p%d could not be added: %ld\n",
- disk->disk_name, p, -PTR_ERR(part));
- continue;
- }
-#ifdef CONFIG_BLK_DEV_MD
- if (state->parts[p].flags & ADDPART_FLAG_RAID)
- md_autodetect_dev(part_to_dev(part)->devt);
-#endif
- }
-out:
- free_partitions(state);
- return 0;
+ if (disk->fops->revalidate_disk)
+ disk->fops->revalidate_disk(disk);
+ check_disk_size_change(disk, bdev, true);
+ bdev->bd_invalidated = 0;
+
+ if (!get_capacity(disk))
+ return 0;
+
+ ret = blk_add_partitions(disk, bdev);
+ if (ret == -EAGAIN)
+ goto rescan;
+ return ret;
}
int invalidate_partitions(struct gendisk *disk, struct block_device *bdev)
--
2.20.1
next prev parent reply other threads:[~2019-11-14 14:34 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-11-14 14:34 disk revalidation cleanups and fixlets v2 Christoph Hellwig
2019-11-14 14:34 ` Christoph Hellwig [this message]
2019-11-14 14:34 ` [PATCH 2/7] block: merge invalidate_partitions into rescan_partitions Christoph Hellwig
2019-11-15 10:05 ` Hannes Reinecke
2019-11-30 21:49 ` Eric Biggers
2019-11-30 22:06 ` Eric Biggers
2019-12-02 7:21 ` Christoph Hellwig
2019-11-14 14:34 ` [PATCH 3/7] block: move rescan_partitions to fs/block_dev.c Christoph Hellwig
2019-11-15 10:06 ` Hannes Reinecke
2019-11-14 14:34 ` [PATCH 4/7] block: fix bdev_disk_changed for non-partitioned devices Christoph Hellwig
2019-11-15 10:07 ` Hannes Reinecke
2019-11-14 14:34 ` [PATCH 5/7] block: remove (__)blkdev_reread_part as an exported API Christoph Hellwig
2019-11-15 10:08 ` Hannes Reinecke
2019-11-14 14:34 ` [PATCH 6/7] block: move clearing bd_invalidated into check_disk_size_change Christoph Hellwig
2019-11-15 10:08 ` Hannes Reinecke
2019-11-14 14:34 ` [PATCH 7/7] block: move setting bd_invalidated from flush_disk to check_disk_change Christoph Hellwig
2019-11-15 10:09 ` Hannes Reinecke
2019-11-14 14:44 ` disk revalidation cleanups and fixlets v2 Jens Axboe
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20191114143438.14681-2-hch@lst.de \
--to=hch@lst.de \
--cc=axboe@kernel.dk \
--cc=hare@suse.de \
--cc=jack@suse.cz \
--cc=linux-block@vger.kernel.org \
--cc=linux-s390@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox