Richard W.M. Jones
2014-Nov-24 19:13 UTC
[Libguestfs] [PATCH v2 0/2] patches needed for virt-bmap
Does *not* incorporate changes suggested by Pino yet. Rich.
Richard W.M. Jones
2014-Nov-24 19:13 UTC
[Libguestfs] [PATCH v2 1/2] New API: guestfs_blockdev_setra: Adjust readahead for filesystems and devices.
This adds a binding for 'blockdev --setra', allowing you to adjust the readahead parameter for filesystems and devices. --- daemon/blockdev.c | 30 ++++++++++++++++++++---------- generator/actions.ml | 14 ++++++++++++++ 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/daemon/blockdev.c b/daemon/blockdev.c index 8a7b1a8..6e8821d 100644 --- a/daemon/blockdev.c +++ b/daemon/blockdev.c @@ -62,7 +62,7 @@ call_blockdev (const char *device, const char *switc, int extraarg, int prints) */ udev_settle (); - if (extraarg > 0) { + if (extraarg >= 0) { snprintf (buf, sizeof buf, "%d", extraarg); argv[2] = buf; argv[3] = device; @@ -89,33 +89,43 @@ call_blockdev (const char *device, const char *switc, int extraarg, int prints) } int +do_blockdev_setra (const char *device, int sectors) +{ + if (sectors < 0) { + reply_with_error ("readahead sectors must be >= 0"); + return -1; + } + return (int) call_blockdev (device, "--setra", sectors, 0); +} + +int do_blockdev_setro (const char *device) { - return (int) call_blockdev (device, "--setro", 0, 0); + return (int) call_blockdev (device, "--setro", -1, 0); } int do_blockdev_setrw (const char *device) { - return (int) call_blockdev (device, "--setrw", 0, 0); + return (int) call_blockdev (device, "--setrw", -1, 0); } int do_blockdev_getro (const char *device) { - return (int) call_blockdev (device, "--getro", 0, 1); + return (int) call_blockdev (device, "--getro", -1, 1); } int do_blockdev_getss (const char *device) { - return (int) call_blockdev (device, "--getss", 0, 1); + return (int) call_blockdev (device, "--getss", -1, 1); } int do_blockdev_getbsz (const char *device) { - return (int) call_blockdev (device, "--getbsz", 0, 1); + return (int) call_blockdev (device, "--getbsz", -1, 1); } int @@ -128,23 +138,23 @@ do_blockdev_setbsz (const char *device, int blocksize) int64_t do_blockdev_getsz (const char *device) { - return call_blockdev (device, "--getsz", 0, 1); + return call_blockdev (device, "--getsz", -1, 1); } int64_t do_blockdev_getsize64 (const char *device) { - return call_blockdev (device, "--getsize64", 0, 1); + return call_blockdev (device, "--getsize64", -1, 1); } int do_blockdev_flushbufs (const char *device) { - return call_blockdev (device, "--flushbufs", 0, 0); + return call_blockdev (device, "--flushbufs", -1, 0); } int do_blockdev_rereadpt (const char *device) { - return call_blockdev (device, "--rereadpt", 0, 0); + return call_blockdev (device, "--rereadpt", -1, 0); } diff --git a/generator/actions.ml b/generator/actions.ml index fe492e6..baa7679 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -12003,6 +12003,20 @@ This is the same as the C<lstat(2)> system call." }; longdesc = "\ This is the internal call which implements C<guestfs_lstatnslist>." }; + { defaults with + name = "blockdev_setra"; + style = RErr, [Device "device"; Int "sectors"], []; + proc_nr = Some 424; + tests = [ + InitEmpty, Always, TestRun ( + [["blockdev_setra"; "/dev/sda"; "1024" ]]), [] + ]; + shortdesc = "set readahead"; + longdesc = "\ +Set readahead (in 512-byte sectors) for the device. + +This uses the L<blockdev(8)> command." }; + ] (* Non-API meta-commands available only in guestfish. -- 2.1.0
Richard W.M. Jones
2014-Nov-24 19:13 UTC
[Libguestfs] [PATCH v2 2/2] New APIs: bmap-file, bmap-device, bmap.
Add support for a block mapping API, used by the 'virt-bmap' tool. --- daemon/Makefile.am | 1 + daemon/bmap.c | 178 +++++++++++++++++++++++++++++++++++++++++++++++++++ generator/actions.ml | 44 +++++++++++++ po/POTFILES | 1 + src/MAX_PROC_NR | 2 +- 5 files changed, 225 insertions(+), 1 deletion(-) create mode 100644 daemon/bmap.c diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 8ccf322..b6444fa 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -86,6 +86,7 @@ guestfsd_SOURCES = \ blkdiscard.c \ blkid.c \ blockdev.c \ + bmap.c \ btrfs.c \ cap.c \ checksum.c \ diff --git a/daemon/bmap.c b/daemon/bmap.c new file mode 100644 index 0000000..9714788 --- /dev/null +++ b/daemon/bmap.c @@ -0,0 +1,178 @@ +/* libguestfs - the guestfsd daemon + * Copyright (C) 2014 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <inttypes.h> +#include <fcntl.h> +#include <unistd.h> +#include <dirent.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <linux/fs.h> + +#include "daemon.h" +#include "actions.h" + +static int fd = -1; +static DIR *dir = NULL; +static struct stat statbuf; + +static void bmap_finalize (void) __attribute__((destructor)); +static void +bmap_finalize (void) +{ + if (fd >= 0) { + close (fd); + fd = -1; + } + if (dir != NULL) { + closedir (dir); + dir = NULL; + } +} + +static int +bmap_prepare (const char *path, const char *orig_path) +{ + bmap_finalize (); + + if (stat (path, &statbuf) == -1) { + reply_with_perror ("%s", orig_path); + return -1; + } + + if (S_ISDIR (statbuf.st_mode)) { + /* Open a directory. */ + dir = opendir (path); + if (dir == NULL) { + reply_with_perror ("opendir: %s", orig_path); + return -1; + } + } + else { + /* Open a regular file. */ + fd = open (path, O_RDONLY | O_CLOEXEC); + if (fd == -1) { + reply_with_perror ("%s", orig_path); + return -1; + } + + posix_fadvise (fd, 0, 0, + POSIX_FADV_SEQUENTIAL | + POSIX_FADV_NOREUSE | + POSIX_FADV_DONTNEED); + } + + return 0; +} + +int +do_bmap_file (const char *path) +{ + CLEANUP_FREE char *buf = NULL; + + buf = sysroot_path (path); + if (!buf) { + reply_with_perror ("malloc"); + return -1; + } + + return bmap_prepare (buf, path); +} + +int +do_bmap_device (const char *device) +{ + return bmap_prepare (device, device); +} + +static char buffer[BUFSIZ]; + +int +do_bmap (void) +{ + uint64_t n; + ssize_t r; + struct dirent *d; + + /* Drop caches before starting the read. */ + if (do_drop_caches (3) == -1) + return -1; + + if (fd >= 0) { + if (S_ISBLK (statbuf.st_mode)) { + /* Get size of block device. */ + if (ioctl (fd, BLKGETSIZE64, &n) == -1) { + reply_with_perror ("ioctl: BLKGETSIZE64"); + return -1; + } + } + else + n = statbuf.st_size; + + while (n > 0) { + r = read (fd, buffer, n > BUFSIZ ? BUFSIZ : n); + if (r == -1) { + reply_with_perror ("read"); + close (fd); + fd = -1; + return -1; + } + n -= r; + } + + if (close (fd) == -1) { + reply_with_perror ("close"); + fd = -1; + return -1; + } + fd = -1; + } + + if (dir != NULL) { + for (;;) { + errno = 0; + d = readdir (dir); + if (!d) break; + } + + /* Check readdir didn't fail */ + if (errno != 0) { + reply_with_perror ("readdir"); + closedir (dir); + dir = NULL; + return -1; + } + + /* Close the directory handle */ + if (closedir (dir) == -1) { + reply_with_perror ("closedir"); + dir = NULL; + return -1; + } + dir = NULL; + } + + return 0; +} diff --git a/generator/actions.ml b/generator/actions.ml index baa7679..0f2e040 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -12017,6 +12017,50 @@ Set readahead (in 512-byte sectors) for the device. This uses the L<blockdev(8)> command." }; + { defaults with + name = "bmap_file"; + style = RErr, [Pathname "path"], []; + proc_nr = Some 425; + shortdesc = "prepare a file for block mapping"; + longdesc = "\ +This is a specialized function used by L<virt-bmap(1)> to map which +blocks are used by a file. It is unlikely to be useful outside +virt-bmap. + +This call prepares C<path> (which may be a regular file or directory) +to be mapped. You have to call C<guestfs_bmap> immediately afterwards." }; + + { defaults with + name = "bmap_device"; + style = RErr, [Device "device"], []; + proc_nr = Some 426; + shortdesc = "prepare a device for block mapping"; + longdesc = "\ +This is a specialized function used by L<virt-bmap(1)> to map which +blocks are used by a device. It is unlikely to be useful outside +virt-bmap. + +This call prepares C<device> to be mapped. You have to call C<guestfs_bmap> +immediately afterwards." }; + + { defaults with + name = "bmap"; + style = RErr, [], []; + proc_nr = Some 427; + shortdesc = "block map file or device"; + longdesc = "\ +This is a specialized function used by L<virt-bmap(1)> to map which +blocks are used by a file or device. It is unlikely to be useful outside +virt-bmap. + +This performs the specialized read of the file or device which was +previously prepared (see C<guestfs_bmap_file> and C<guestfs_bmap_device>). +The file/directory/device is read from start to end without any caching +or readahead. + +L<virt-bmap(1)> uses this call in conjunction with an nbdkit plugin +which monitors which disk blocks are read during the operation." }; + ] (* Non-API meta-commands available only in guestfish. diff --git a/po/POTFILES b/po/POTFILES index 1a088f5..b13cb86 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -22,6 +22,7 @@ daemon/base64.c daemon/blkdiscard.c daemon/blkid.c daemon/blockdev.c +daemon/bmap.c daemon/btrfs.c daemon/cap.c daemon/checksum.c diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR index 5721413..d2a1e59 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -423 +427 -- 2.1.0