mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-21 22:53:37 +00:00
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:
@@ -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 \
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
46
src/create.c
46
src/create.c
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user