qemu-nbd: Removed deprecated --partition option

The option was deprecated in 4.0.0 (commit 0ae2d546); it's now been
long enough with no complaints to follow through with that process.

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <20200123164650.1741798-3-eblake@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
Eric Blake 2020-01-23 10:46:50 -06:00
parent 2e3cb7583a
commit 0bc16997f5
3 changed files with 24 additions and 173 deletions

View File

@ -72,13 +72,6 @@ driver options if ``--image-opts`` is specified.
Export the disk as read-only. Export the disk as read-only.
.. option:: -P, --partition=NUM
Deprecated: Only expose MBR partition *NUM*. Understands physical
partitions 1-4 and logical partition 5. New code should instead use
:option:`--image-opts` with the raw driver wrapping a subset of the
original image.
.. option:: -B, --bitmap=NAME .. option:: -B, --bitmap=NAME
If *filename* has a qcow2 persistent bitmap *NAME*, expose If *filename* has a qcow2 persistent bitmap *NAME*, expose
@ -224,14 +217,14 @@ a 1 megabyte subset of a raw file, using the export name 'subset':
-t -x subset -p 10810 \ -t -x subset -p 10810 \
--image-opts driver=raw,offset=1M,size=1M,file.driver=file,file.filename=file.raw --image-opts driver=raw,offset=1M,size=1M,file.driver=file,file.filename=file.raw
Serve a read-only copy of just the first MBR partition of a guest Serve a read-only copy of a guest image over a Unix socket with as
image over a Unix socket with as many as 5 simultaneous readers, with many as 5 simultaneous readers, with a persistent process forked as a
a persistent process forked as a daemon: daemon:
:: ::
qemu-nbd --fork --persistent --shared=5 --socket=/path/to/sock \ qemu-nbd --fork --persistent --shared=5 --socket=/path/to/sock \
--partition=1 --read-only --format=qcow2 file.qcow2 --read-only --format=qcow2 file.qcow2
Expose the guest-visible contents of a qcow2 file via a block device Expose the guest-visible contents of a qcow2 file via a block device
/dev/nbd0 (and possibly creating /dev/nbd0p1 and friends for /dev/nbd0 (and possibly creating /dev/nbd0p1 and friends for

View File

@ -313,37 +313,6 @@ The above, converted to the current supported format:
@section Related binaries @section Related binaries
@subsection qemu-nbd --partition (since 4.0.0)
The ``qemu-nbd --partition $digit'' code (also spelled @option{-P})
can only handle MBR partitions, and has never correctly handled
logical partitions beyond partition 5. If you know the offset and
length of the partition (perhaps by using @code{sfdisk} within the
guest), you can achieve the effect of exporting just that subset of
the disk by use of the @option{--image-opts} option with a raw
blockdev using the @code{offset} and @code{size} parameters layered on
top of any other existing blockdev. For example, if partition 1 is
100MiB long starting at 1MiB, the old command:
@code{qemu-nbd -t -P 1 -f qcow2 file.qcow2}
can be rewritten as:
@code{qemu-nbd -t --image-opts driver=raw,offset=1M,size=100M,file.driver=qcow2,file.file.driver=file,file.file.filename=file.qcow2}
Alternatively, the @code{nbdkit} project provides a more powerful
partition filter on top of its nbd plugin, which can be used to select
an arbitrary MBR or GPT partition on top of any other full-image NBD
export. Using this to rewrite the above example results in:
@code{qemu-nbd -t -k /tmp/sock -f qcow2 file.qcow2 &}
@code{nbdkit -f --filter=partition nbd socket=/tmp/sock partition=1}
Note that if you are exposing the export via /dev/nbd0, it is easier
to just export the entire image and then mount only /dev/nbd0p1 than
it is to reinvoke @command{qemu-nbd -c /dev/nbd0} limited to just a
subset of the image.
@subsection qemu-img convert -n -o (since 4.2.0) @subsection qemu-img convert -n -o (since 4.2.0)
All options specified in @option{-o} are image creation options, so All options specified in @option{-o} are image creation options, so
@ -400,3 +369,21 @@ trouble after a recent upgrade.
The "autoload" parameter has been ignored since 2.12.0. All bitmaps The "autoload" parameter has been ignored since 2.12.0. All bitmaps
are automatically loaded from qcow2 images. are automatically loaded from qcow2 images.
@section Related binaries
@subsection qemu-nbd --partition (removed in 5.0.0)
The ``qemu-nbd --partition $digit'' code (also spelled @option{-P})
could only handle MBR partitions, and never correctly handled logical
partitions beyond partition 5. Exporting a partition can still be
done by utilizing the @option{--image-opts} option with a raw blockdev
using the @code{offset} and @code{size} parameters layered on top of
any other existing blockdev. For example, if partition 1 is 100MiB
long starting at 1MiB, the old command:
@code{qemu-nbd -t -P 1 -f qcow2 file.qcow2}
can be rewritten as:
@code{qemu-nbd -t --image-opts driver=raw,offset=1M,size=100M,file.driver=qcow2,file.file.driver=file,file.file.filename=file.qcow2}

View File

@ -100,7 +100,6 @@ static void usage(const char *name)
"\n" "\n"
"Exposing part of the image:\n" "Exposing part of the image:\n"
" -o, --offset=OFFSET offset into the image\n" " -o, --offset=OFFSET offset into the image\n"
" -P, --partition=NUM only expose partition NUM\n"
" -B, --bitmap=NAME expose a persistent dirty bitmap\n" " -B, --bitmap=NAME expose a persistent dirty bitmap\n"
"\n" "\n"
"General purpose options:\n" "General purpose options:\n"
@ -156,96 +155,6 @@ QEMU_COPYRIGHT "\n"
, name); , name);
} }
struct partition_record
{
uint8_t bootable;
uint8_t start_head;
uint32_t start_cylinder;
uint8_t start_sector;
uint8_t system;
uint8_t end_head;
uint8_t end_cylinder;
uint8_t end_sector;
uint32_t start_sector_abs;
uint32_t nb_sectors_abs;
};
static void read_partition(uint8_t *p, struct partition_record *r)
{
r->bootable = p[0];
r->start_head = p[1];
r->start_cylinder = p[3] | ((p[2] << 2) & 0x0300);
r->start_sector = p[2] & 0x3f;
r->system = p[4];
r->end_head = p[5];
r->end_cylinder = p[7] | ((p[6] << 2) & 0x300);
r->end_sector = p[6] & 0x3f;
r->start_sector_abs = ldl_le_p(p + 8);
r->nb_sectors_abs = ldl_le_p(p + 12);
}
static int find_partition(BlockBackend *blk, int partition,
uint64_t *offset, uint64_t *size)
{
struct partition_record mbr[4];
uint8_t data[MBR_SIZE];
int i;
int ext_partnum = 4;
int ret;
ret = blk_pread(blk, 0, data, sizeof(data));
if (ret < 0) {
error_report("error while reading: %s", strerror(-ret));
exit(EXIT_FAILURE);
}
if (data[510] != 0x55 || data[511] != 0xaa) {
return -EINVAL;
}
for (i = 0; i < 4; i++) {
read_partition(&data[446 + 16 * i], &mbr[i]);
if (!mbr[i].system || !mbr[i].nb_sectors_abs) {
continue;
}
if (mbr[i].system == 0xF || mbr[i].system == 0x5) {
struct partition_record ext[4];
uint8_t data1[MBR_SIZE];
int j;
ret = blk_pread(blk, mbr[i].start_sector_abs * MBR_SIZE,
data1, sizeof(data1));
if (ret < 0) {
error_report("error while reading: %s", strerror(-ret));
exit(EXIT_FAILURE);
}
for (j = 0; j < 4; j++) {
read_partition(&data1[446 + 16 * j], &ext[j]);
if (!ext[j].system || !ext[j].nb_sectors_abs) {
continue;
}
if ((ext_partnum + j + 1) == partition) {
*offset = (uint64_t)ext[j].start_sector_abs << 9;
*size = (uint64_t)ext[j].nb_sectors_abs << 9;
return 0;
}
}
ext_partnum += 4;
} else if ((i + 1) == partition) {
*offset = (uint64_t)mbr[i].start_sector_abs << 9;
*size = (uint64_t)mbr[i].nb_sectors_abs << 9;
return 0;
}
}
return -ENOENT;
}
static void termsig_handler(int signum) static void termsig_handler(int signum)
{ {
atomic_cmpxchg(&state, RUNNING, TERMINATE); atomic_cmpxchg(&state, RUNNING, TERMINATE);
@ -617,7 +526,7 @@ int main(int argc, char **argv)
int64_t fd_size; int64_t fd_size;
QemuOpts *sn_opts = NULL; QemuOpts *sn_opts = NULL;
const char *sn_id_or_name = NULL; const char *sn_id_or_name = NULL;
const char *sopt = "hVb:o:p:rsnP:c:dvk:e:f:tl:x:T:D:B:L"; const char *sopt = "hVb:o:p:rsnc:dvk:e:f:tl:x:T:D:B:L";
struct option lopt[] = { struct option lopt[] = {
{ "help", no_argument, NULL, 'h' }, { "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' }, { "version", no_argument, NULL, 'V' },
@ -626,7 +535,6 @@ int main(int argc, char **argv)
{ "socket", required_argument, NULL, 'k' }, { "socket", required_argument, NULL, 'k' },
{ "offset", required_argument, NULL, 'o' }, { "offset", required_argument, NULL, 'o' },
{ "read-only", no_argument, NULL, 'r' }, { "read-only", no_argument, NULL, 'r' },
{ "partition", required_argument, NULL, 'P' },
{ "bitmap", required_argument, NULL, 'B' }, { "bitmap", required_argument, NULL, 'B' },
{ "connect", required_argument, NULL, 'c' }, { "connect", required_argument, NULL, 'c' },
{ "disconnect", no_argument, NULL, 'd' }, { "disconnect", no_argument, NULL, 'd' },
@ -657,7 +565,6 @@ int main(int argc, char **argv)
int ch; int ch;
int opt_ind = 0; int opt_ind = 0;
int flags = BDRV_O_RDWR; int flags = BDRV_O_RDWR;
int partition = 0;
int ret = 0; int ret = 0;
bool seen_cache = false; bool seen_cache = false;
bool seen_discard = false; bool seen_discard = false;
@ -789,15 +696,6 @@ int main(int argc, char **argv)
readonly = true; readonly = true;
flags &= ~BDRV_O_RDWR; flags &= ~BDRV_O_RDWR;
break; break;
case 'P':
warn_report("The '-P' option is deprecated; use --image-opts with "
"a raw device wrapper for subset exports instead");
if (qemu_strtoi(optarg, NULL, 0, &partition) < 0 ||
partition < 1 || partition > 8) {
error_report("Invalid partition '%s'", optarg);
exit(EXIT_FAILURE);
}
break;
case 'B': case 'B':
bitmap = optarg; bitmap = optarg;
break; break;
@ -894,7 +792,7 @@ int main(int argc, char **argv)
error_report("List mode is incompatible with a file name"); error_report("List mode is incompatible with a file name");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (export_name || export_description || dev_offset || partition || if (export_name || export_description || dev_offset ||
device || disconnect || fmt || sn_id_or_name || bitmap || device || disconnect || fmt || sn_id_or_name || bitmap ||
seen_aio || seen_discard || seen_cache) { seen_aio || seen_discard || seen_cache) {
error_report("List mode is incompatible with per-device settings"); error_report("List mode is incompatible with per-device settings");
@ -1158,33 +1056,6 @@ int main(int argc, char **argv)
} }
fd_size -= dev_offset; fd_size -= dev_offset;
if (partition) {
uint64_t limit;
if (dev_offset) {
error_report("Cannot request partition and offset together");
exit(EXIT_FAILURE);
}
ret = find_partition(blk, partition, &dev_offset, &limit);
if (ret < 0) {
error_report("Could not find partition %d: %s", partition,
strerror(-ret));
exit(EXIT_FAILURE);
}
/*
* MBR partition limits are (32-bit << 9); this assert lets
* the compiler know that we can't overflow 64 bits.
*/
assert(dev_offset + limit >= dev_offset);
if (dev_offset + limit > fd_size) {
error_report("Discovered partition %d at offset %" PRIu64
" size %" PRIu64 ", but size exceeds file length %"
PRId64, partition, dev_offset, limit, fd_size);
exit(EXIT_FAILURE);
}
fd_size = limit;
}
export = nbd_export_new(bs, dev_offset, fd_size, export_name, export = nbd_export_new(bs, dev_offset, fd_size, export_name,
export_description, bitmap, readonly, shared > 1, export_description, bitmap, readonly, shared > 1,
nbd_export_closed, writethrough, NULL, nbd_export_closed, writethrough, NULL,