disk-create: Fix this API so it works correctly with block devices (RHBZ#1088262).

When you call guestfs_disk_create on a block device with format=raw
then it will try to discard the blocks on the device.
This commit is contained in:
Richard W.M. Jones
2014-04-16 11:43:23 +01:00
parent 1898d457bd
commit 27355c9b0b
4 changed files with 47 additions and 7 deletions

View File

@@ -291,6 +291,7 @@ AC_CHECK_HEADERS([\
byteswap.h \
endian.h \
errno.h \
linux/fs.h \
linux/raid/md_u.h \
printf.h \
sys/inotify.h \

View File

@@ -25,7 +25,10 @@
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#ifdef HAVE_LINUX_FS_H
#include <linux/fs.h>
#endif
#include "daemon.h"
#include "actions.h"

View File

@@ -3084,6 +3084,10 @@ size of the backing file, which is discovered automatically. You
are encouraged to also pass C<backingformat> to describe the format
of C<backingfile>.
If C<filename> refers to a block device, then the device is
formatted. The C<size> is ignored since block devices have an
intrinsic size.
The other optional parameters are:
=over 4

View File

@@ -27,8 +27,13 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <errno.h>
#ifdef HAVE_LINUX_FS_H
#include <linux/fs.h>
#endif
#include "guestfs.h"
#include "guestfs-internal.h"
#include "guestfs-internal-actions.h"
@@ -89,6 +94,36 @@ guestfs__disk_create (guestfs_h *g, const char *filename,
return 0;
}
static int
disk_create_raw_block (guestfs_h *g, const char *filename)
{
int fd;
fd = open (filename, O_WRONLY|O_NOCTTY|O_CLOEXEC, 0666);
if (fd == -1) {
perrorf (g, _("cannot open block device: %s"), filename);
return -1;
}
/* Just discard blocks, if possible. However don't try too hard. */
#if defined(BLKGETSIZE64) && defined(BLKDISCARD)
uint64_t size;
uint64_t range[2];
if (ioctl (fd, BLKGETSIZE64, &size) == 0) {
range[0] = 0;
range[1] = size;
if (ioctl (fd, BLKDISCARD, range) == 0)
debug (g, "disk_create: %s: BLKDISCARD failed on this device: %m",
filename);
}
#endif
close (fd);
return 0;
}
static int
disk_create_raw (guestfs_h *g, const char *filename, int64_t size,
const struct guestfs_disk_create_argv *optargs)
@@ -123,18 +158,15 @@ disk_create_raw (guestfs_h *g, const char *filename, int64_t size,
return -1;
}
/* This version refuses to overwrite block devices or char devices.
* XXX It would be possible to make it work with block devices.
*/
if (stat (filename, &statbuf) == 0) {
if (S_ISBLK (statbuf.st_mode)) {
error (g, _("refusing to overwrite block device '%s'"), filename);
return -1;
}
/* Refuse to overwrite char devices. */
if (S_ISCHR (statbuf.st_mode)) {
error (g, _("refusing to overwrite char device '%s'"), filename);
return -1;
}
/* Block devices have to be handled specially. */
if (S_ISBLK (statbuf.st_mode))
return disk_create_raw_block (g, filename);
}
fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_TRUNC|O_CLOEXEC, 0666);