Commit 800c021f authored by Richard W.M. Jones's avatar Richard W.M. Jones
Browse files

fuse: Support trimming

In future we should also be able to support writing zeroes (fallocate
+ FALLOC_FL_ZERO_RANGE) but it doesn't seem to be possible with FUSE 35.
parent 8bc44161
......@@ -21,13 +21,15 @@ EXTRA_DIST = \
nbdfuse.pod \
test-file-mode.sh \
test-long-options.sh \
test-nbdkit.sh \
test-nbdkit-command.sh \
test-nbdkit-file-null.sh \
test-nbdkit.sh \
test-qcow2.sh \
test-short-options.sh \
test-trim.sh \
test-unix.sh \
test-version.sh \
test-zero.sh \
$(NULL)
TESTS_ENVIRONMENT = LIBNBD_DEBUG=1 EXPECTED_VERSION=$(VERSION)
......@@ -45,6 +47,7 @@ nbdfuse_SOURCES = \
$(NULL)
nbdfuse_CPPFLAGS = \
-I$(top_srcdir)/include \
-I$(top_srcdir)/common/include \
-I$(top_srcdir)/common/utils \
$(NULL)
nbdfuse_CFLAGS = $(WARNINGS_CFLAGS) $(FUSE_CFLAGS)
......@@ -77,6 +80,8 @@ TESTS += \
test-nbdkit-file-null.sh \
test-unix.sh \
test-qcow2.sh \
test-trim.sh \
test-zero.sh \
$(NULL)
check-valgrind:
......
......@@ -36,6 +36,7 @@
#include <libnbd.h>
#include "nbdfuse.h"
#include "minmax.h"
#define MAX_REQUEST_SIZE (32 * 1024 * 1024)
......@@ -200,6 +201,48 @@ nbdfuse_release (const char *path, struct fuse_file_info *fi)
return nbdfuse_fsync (path, 0, fi);
}
/* Punch a hole or write zeros. */
static int
nbdfuse_fallocate (const char *path, int mode, off_t offset, off_t len,
struct fuse_file_info *fi)
{
if (readonly)
return -EACCES;
if (mode & FALLOC_FL_PUNCH_HOLE) {
if (!nbd_can_trim (nbd))
return -EOPNOTSUPP; /* Trim not supported. */
else {
CHECK_NBD_ERROR (nbd_trim (nbd, len, offset, 0));
return 0;
}
}
/* As of FUSE 35 this is not supported by the kernel module and it
* always returns EOPNOTSUPP.
*/
else if (mode & FALLOC_FL_ZERO_RANGE) {
/* If the backend doesn't support writing zeroes then we can
* emulate it.
*/
if (!nbd_can_zero (nbd)) {
static char zerobuf[4096];
while (len > 0) {
off_t n = MIN (len, sizeof zerobuf);
CHECK_NBD_ERROR (nbd_pwrite (nbd, zerobuf, n, offset, 0));
len -= n;
}
return 0;
}
else {
CHECK_NBD_ERROR (nbd_zero (nbd, len, offset, 0));
return 0;
}
}
else
return -EOPNOTSUPP;
}
struct fuse_operations nbdfuse_operations = {
.getattr = nbdfuse_getattr,
.readdir = nbdfuse_readdir,
......@@ -208,4 +251,5 @@ struct fuse_operations nbdfuse_operations = {
.write = nbdfuse_write,
.fsync = nbdfuse_fsync,
.release = nbdfuse_release,
.fallocate = nbdfuse_fallocate,
};
#!/usr/bin/env bash
# nbd client library in userspace
# Copyright (C) 2019-2021 Red Hat Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
# Test trimming of files using nbdkit sh plugin.
. ../tests/functions.sh
set -e
set -x
requires fusermount3 --version
requires fallocate --version
requires dd --version
requires nbdkit --version
requires nbdkit sh --version
# Difficult to arrange for this test to be run this test under
# valgrind, so don't bother.
if [ "x$LIBNBD_VALGRIND" = "x1" ]; then
echo "$0: test skipped under valgrind"
exit 77
fi
mp=test-trim.d
pidfile=test-trim.pid
out=test-trim.out
cleanup_fn fusermount3 -u $mp
cleanup_fn rm -rf $mp $pidfile $out
mkdir $mp
export mp pidfile out
nbdkit -U - \
sh - \
--run '
set -x
# Run nbdfuse and connect to the nbdkit server.
nbdfuse -P $pidfile $mp --unix $unixsocket &
# Wait for the pidfile to appear.
for i in {1..60}; do
if test -f $pidfile; then
break
fi
sleep 1
done
if ! test -f $pidfile; then
echo "$0: nbdfuse PID file $pidfile was not created"
exit 1
fi
ls -al $mp
# Fully allocate the disk.
dd if=/dev/zero of=$mp/nbd bs=512 count=2
# Punch a hole in the second sector.
fallocate -p -l 512 -o 512 $mp/nbd
# We have to explicitly unmount it here else nbdfuse will
# never exit and nbdkit will hang.
fusermount3 -u $mp
' <<'EOF'
# The nbdkit server script.
case "$1" in
get_size) echo 1024 ;;
can_write) ;;
can_trim) ;;
can_zero) ;;
pread) ;;
pwrite) echo "$@" >> $out ;;
trim) echo "$@" >> $out ;;
zero) echo "$@" >> $out ;;
*) exit 2 ;;
esac
EOF
# What commands were sent to nbdkit?
cat $out
grep 'pwrite 512 0' $out
grep 'pwrite 512 512' $out
grep 'trim 512 512' $out
#!/usr/bin/env bash
# nbd client library in userspace
# Copyright (C) 2019-2021 Red Hat Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
# Test zeroing of files using nbdkit sh plugin.
. ../tests/functions.sh
set -e
set -x
# Not supported in FUSE 35. This test is left in case it is supported
# in future. See also the comment in nbdfuse/operations.c.
echo "$0: skipped because not supported by FUSE yet"
exit 77
requires fusermount3 --version
requires fallocate --version
requires dd --version
requires nbdkit --version
requires nbdkit sh --version
# Difficult to arrange for this test to be run this test under
# valgrind, so don't bother.
if [ "x$LIBNBD_VALGRIND" = "x1" ]; then
echo "$0: test skipped under valgrind"
exit 77
fi
mp=test-zero.d
pidfile=test-zero.pid
out=test-zero.out
cleanup_fn fusermount3 -u $mp
cleanup_fn rm -rf $mp $pidfile $out
mkdir $mp
export mp pidfile out
nbdkit -U - \
sh - \
--run '
set -x
# Run nbdfuse and connect to the nbdkit server.
nbdfuse -P $pidfile $mp --unix $unixsocket &
# Wait for the pidfile to appear.
for i in {1..60}; do
if test -f $pidfile; then
break
fi
sleep 1
done
if ! test -f $pidfile; then
echo "$0: nbdfuse PID file $pidfile was not created"
exit 1
fi
ls -al $mp
# Fully allocate the disk.
dd if=/dev/zero of=$mp/nbd bs=512 count=2
# Explicitly zero the second sector.
fallocate -z -l 512 -o 512 $mp/nbd
# We have to explicitly unmount it here else nbdfuse will
# never exit and nbdkit will hang.
fusermount3 -u $mp
' <<'EOF'
# The nbdkit server script.
case "$1" in
get_size) echo 1024 ;;
can_write) ;;
can_trim) ;;
can_zero) ;;
can_fast_zero) ;;
pread) ;;
pwrite) echo "$@" >> $out ;;
trim) echo "$@" >> $out ;;
zero) echo "$@" >> $out ;;
*) exit 2 ;;
esac
EOF
# What commands were sent to nbdkit?
cat $out
grep 'pwrite 512 0' $out
grep 'pwrite 512 512' $out
grep 'zero 512 512' $out
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment