diff --git a/daemon/Makefile.am b/daemon/Makefile.am index e64caca4a..b18f9ff51 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -83,6 +83,7 @@ guestfsd_SOURCES = \ available.c \ augeas.c \ base64.c \ + blkdiscard.c \ blkid.c \ blockdev.c \ btrfs.c \ diff --git a/daemon/blkdiscard.c b/daemon/blkdiscard.c new file mode 100644 index 000000000..1d507a399 --- /dev/null +++ b/daemon/blkdiscard.c @@ -0,0 +1,90 @@ +/* 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 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "daemon.h" +#include "actions.h" +#include "optgroups.h" + +/* http://rwmj.wordpress.com/2014/03/11/blkdiscard-blkzeroout-blkdiscardzeroes-blksecdiscard/ */ + +#ifdef BLKDISCARD + +int +optgroup_blkdiscard_available (void) +{ + return 1; +} + +int +do_blkdiscard (const char *device) +{ + /* XXX We could read /sys/block//queue/discard_* in order to + * determine if discard is supported and the largest request size we + * are allowed to make. However: + * + * (1) Mapping the device name to /sys/block/ is quite hard + * (cf. the lv_canonical function in daemon/lvm.c) + * + * (2) We don't really need to do this in modern libguestfs since + * we're very likely to be using virtio-scsi, which supports + * arbitrary block discards. + * + * Let's wait to see if it causes a problem in real world + * situations. + */ + uint64_t range[2]; + int64_t size; + int fd; + + size = do_blockdev_getsize64 (device); + if (size == -1) + return -1; + + range[0] = 0; + range[1] = (uint64_t) size; + + fd = open (device, O_WRONLY|O_CLOEXEC); + if (fd == -1) { + reply_with_perror ("open: %s", device); + return -1; + } + + if (ioctl (fd, BLKDISCARD, range) == -1) { + reply_with_perror ("ioctl: %s: BLKDISCARD", device); + close (fd); + return -1; + } + + close (fd); + return 0; +} + +#else /* !BLKDISCARD */ +OPTGROUP_BLKDISCARD_NOT_AVAILABLE +#endif diff --git a/generator/actions.ml b/generator/actions.ml index b25194cf0..5c4adbc04 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -11818,6 +11818,22 @@ device C. Note that partitions are numbered from 1. The partition name can only be read on certain types of partition table. This works on C but not on C partitions." }; + { defaults with + name = "blkdiscard"; + style = RErr, [Device "device"], []; + proc_nr = Some 417; + optional = Some "blkdiscard"; + shortdesc = "discard all blocks on a device"; + longdesc = "\ +This discards all blocks on the block device C, giving +the free space back to the host. + +This operation requires support in libguestfs, the host filesystem, +qemu and the host kernel. If this support isn't present it may give +an error or even appear to run but do nothing. You must also +set the C attribute on the underlying drive (see +C)." }; + ] (* Non-API meta-commands available only in guestfish. diff --git a/po/POTFILES b/po/POTFILES index 5aeeb2e82..ecdbae401 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -16,6 +16,7 @@ daemon/acl.c daemon/augeas.c daemon/available.c daemon/base64.c +daemon/blkdiscard.c daemon/blkid.c daemon/blockdev.c daemon/btrfs.c diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR index 1c105f1a6..53c86ff4f 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -416 +417