diff options
Diffstat (limited to 'usr/src/test/zfs-tests')
12 files changed, 517 insertions, 7 deletions
diff --git a/usr/src/test/zfs-tests/cmd/scripts/zfstest.ksh b/usr/src/test/zfs-tests/cmd/scripts/zfstest.ksh index 3d53ef5fae..527c89163f 100644 --- a/usr/src/test/zfs-tests/cmd/scripts/zfstest.ksh +++ b/usr/src/test/zfs-tests/cmd/scripts/zfstest.ksh @@ -14,8 +14,10 @@ # # Copyright (c) 2012, 2016 by Delphix. All rights reserved. # Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved. +# Copyright 2019 Joyent, Inc. # Copyright 2021 Tintri by DDN, Inc. All rights reserved. # Copyright 2020 OmniOS Community Edition (OmniOSce) Association. +# Copyright 2022 MNX Cloud, Inc. # export PATH="/usr/bin" @@ -72,6 +74,8 @@ function find_runfile distro=openindiana elif [[ 0 -ne $(grep -c OmniOS /etc/release 2>/dev/null) ]]; then distro=omnios + elif [[ 0 -ne $(grep -c SmartOS /etc/release 2>/dev/null) ]]; then + distro=smartos fi [[ -n $distro ]] && echo $COMMON,$STF_SUITE/runfiles/$distro.run @@ -128,6 +132,18 @@ function constrain_path # Special case links ln -s /usr/gnu/bin/dd $PATHDIR/gnu_dd + + # SmartOS does not ship some required commands by default. + # Link to them in the package manager's namespace. + pkgsrc_bin=/opt/tools/bin + pkgsrc_packages="sudo truncate python base64 shuf sha256sum" + for pkg in $pkgsrc_packages; do + if [[ ! -x $PATHDIR/$pkg ]]; then + rm $PATHDIR/$pkg && + ln -s $pkgsrc_bin/$pkg $PATHDIR/$pkg || + fail "Couldn't link $pkg" + fi + done } constrain_path diff --git a/usr/src/test/zfs-tests/cmd/watch_dir/Makefile b/usr/src/test/zfs-tests/cmd/watch_dir/Makefile new file mode 100644 index 0000000000..517dff64af --- /dev/null +++ b/usr/src/test/zfs-tests/cmd/watch_dir/Makefile @@ -0,0 +1,19 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2020 Joyent, Inc. +# + +PROG = watch_dir + +include $(SRC)/cmd/Makefile.cmd +include ../Makefile.subdirs diff --git a/usr/src/test/zfs-tests/cmd/watch_dir/watch_dir.c b/usr/src/test/zfs-tests/cmd/watch_dir/watch_dir.c new file mode 100644 index 0000000000..f6d8445162 --- /dev/null +++ b/usr/src/test/zfs-tests/cmd/watch_dir/watch_dir.c @@ -0,0 +1,151 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2020 Joyent, Inc. + */ + +/* + * This program watches a directory with portfs or inotify, exiting when the + * directory is removed. It is useful in tests that ensure that watching a + * directory does not prevent it from being used as a mount point. + */ +#include <limits.h> +#include <port.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/inotify.h> +#include <unistd.h> + +void +fail_usage(void) +{ + (void) fprintf(stderr, "Usage: watch <portfs|inotify> directory\n"); + exit(1); +} + +#define MAX_PES 8 + +void +watch_port(const char *path) +{ + int port; + struct file_obj fobj = {0}; + + if ((port = port_create()) < 0) { + perror("port_create"); + exit(1); + } + + fobj.fo_name = (char *)path; + for (;;) { + timespec_t ts = {300, 0}; + port_event_t pe; + + if (port_associate(port, PORT_SOURCE_FILE, (uintptr_t)&fobj, + 0, (char *)path) != 0) { + perror("port_associate"); + exit(1); + } + + if (port_get(port, &pe, &ts) != 0) { + perror("port_get"); + exit(1); + } + + if (pe.portev_events & FILE_DELETE) { + (void) printf("DELETE\t%s\n", path); + exit(0); + } + if (pe.portev_events & MOUNTEDOVER) { + (void) printf("MOUNTEDOVER\t%s\n", path); + } + } +} + +void +watch_inotify(const char *path) +{ + int in, wd; + struct inotify_event ev; + + if ((in = inotify_init()) < 0) { + perror("inotify_init"); + exit(1); + } + if ((wd = inotify_add_watch(in, path, IN_DELETE_SELF)) == -1) { + perror("inotify_add_watch"); + exit(1); + } + + for (;;) { + ssize_t cnt; + char evpath[PATH_MAX]; + + cnt = read(in, &ev, sizeof (ev)); + if (cnt != sizeof (ev)) { + (void) fprintf(stderr, + "read: expected %ld bytes got %ld\n", + sizeof (ev), cnt); + exit(1); + } + if (ev.len != 0) { + if (ev.len > sizeof (evpath)) { + (void) fprintf(stderr, "read: oversize " + "path (%u bytes)\n", ev.len); + exit(1); + } + cnt = read(in, evpath, ev.len); + if (cnt != ev.len) { + (void) fprintf(stderr, "read: expected %ld " + "bytes for path, got %ld\n", ev.len, cnt); + exit(1); + } + evpath[ev.len - 1] = '\0'; + } else { + evpath[0] = '\0'; + } + if (ev.mask & IN_DELETE_SELF) { + /* + * IN_DELETE_SELF events don't appear to include + * the path in the event. + */ + (void) printf("DELETE_SELF\n"); + exit(0); + } else { + (void) printf("EVENT_%08x\t%s\n", ev.mask, evpath); + } + + } +} + +int +main(int argc, char **argv) +{ + const char *watcher, *path; + + if (argc != 3) { + fail_usage(); + } + watcher = argv[1]; + path = argv[2]; + + if (strcmp(watcher, "portfs") == 0) { + watch_port(path); + } else if (strcmp(watcher, "inotify") == 0) { + watch_inotify(path); + } else { + fail_usage(); + } + + return (0); +} diff --git a/usr/src/test/zfs-tests/include/commands.cfg b/usr/src/test/zfs-tests/include/commands.cfg index c4769cbc71..dad9372554 100644 --- a/usr/src/test/zfs-tests/include/commands.cfg +++ b/usr/src/test/zfs-tests/include/commands.cfg @@ -198,4 +198,5 @@ export ZFSTEST_FILES='btree_test randwritecomp readmmap rename_dir - rm_lnkcnt_zero_file' + rm_lnkcnt_zero_file + watch_dir' diff --git a/usr/src/test/zfs-tests/runfiles/common.run b/usr/src/test/zfs-tests/runfiles/common.run index 82672045ce..f58eecec40 100644 --- a/usr/src/test/zfs-tests/runfiles/common.run +++ b/usr/src/test/zfs-tests/runfiles/common.run @@ -156,7 +156,8 @@ tests = ['zfs_create_001_pos', 'zfs_create_002_pos', 'zfs_create_003_pos', 'zfs_create_004_pos', 'zfs_create_005_pos', 'zfs_create_006_pos', 'zfs_create_007_pos', 'zfs_create_008_neg', 'zfs_create_009_neg', 'zfs_create_010_neg', 'zfs_create_011_pos', 'zfs_create_012_pos', - 'zfs_create_013_pos', 'zfs_create_encrypted', 'zfs_create_crypt_combos'] + 'zfs_create_013_pos', 'zfs_create_encrypted', 'zfs_create_crypt_combos', + 'zfs_create_dryrun', 'zfs_create_verbose'] tags = ['functional', 'cli_root', 'zfs_create'] [tests/functional/cli_root/zfs_destroy] @@ -194,7 +195,8 @@ tests = ['zfs_mount_001_pos', 'zfs_mount_002_pos', 'zfs_mount_003_pos', 'zfs_mount_007_pos', 'zfs_mount_008_pos', 'zfs_mount_009_neg', 'zfs_mount_010_neg', 'zfs_mount_011_neg', 'zfs_mount_012_neg', 'zfs_mount_all_001_pos', 'zfs_mount_all_fail', 'zfs_mount_all_mountpoints', - 'zfs_mount_encrypted'] + 'zfs_mount_encrypted', 'zfs_mount_watched_inotify', + 'zfs_mount_watched_portfs'] tags = ['functional', 'cli_root', 'zfs_mount'] [tests/functional/cli_root/zfs_program] diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_dryrun.ksh b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_dryrun.ksh new file mode 100644 index 0000000000..64b8296f46 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_dryrun.ksh @@ -0,0 +1,169 @@ +#!/bin/ksh -p +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2019 Joyent, Inc. +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib + +# +# DESCRIPTION: +# zfs create -n should perform basic sanity checking but should never create a +# dataset. If -v and/or -P are used, it should verbose about what would be +# created if sanity checks pass. +# +# STRATEGY: +# 1. Attempt to create a file system and a volume using various combinations of +# -n with -v and -P. +# + +verify_runnable "both" + +# +# Verifies that valid commands with -n and without -[vP]: +# - succeed +# - do not create a dataset +# - do not generate output +# +function dry_create_no_output +{ + typeset -a cmd=(zfs create -n "$@") + + log_note "$0: ${cmd[@]}" + log_must "${cmd[@]}" + datasetexists "$TESTPOOL/$TESTFS1" && + log_fail "$TESTPOOL/$TESTFS1 unexpectedly created by '${cmd[@]}'" + typeset out=$("${cmd[@]}" 2>&1) + [[ -z "$out" ]] || + log_fail "unexpected output '$out' from '${cmd[@]}'" +} + +# +# Verifies that commands with invalid properties or invalid property values +# - fail +# - do not create a dataset +# - generate a message on stderr +# +function dry_create_error +{ + typeset -a cmd=(zfs create -n "$@") + + log_note "$0: ${cmd[@]}" + log_mustnot "${cmd[@]}" + datasetexists "$TESTPOOL/$TESTFS1" && + log_fail "$TESTPOOL/$TESTFS1 unexpectedly created by '${cmd[@]}'" + typeset out=$("${cmd[@]}" 2>&1 >/dev/null) + [[ -z "$out" ]] && + log_fail "expected an error message but got none from '${cmd[@]}'" +} + +# +# Verifies that dry-run commands with parseable output +# - succeed +# - do not create datasets +# - generate parseable output on stdout +# - output matches expectations +# +function dry_create_parseable +{ + typeset -n exp=$1 + shift + typeset -a cmd=(zfs create -Pn "$@") + typeset ds=${cmd[${#cmd[@]} - 1]} + typeset out + typeset -a toks + typeset -a props + typeset found_create=false + + log_note "$0: ${cmd[@]}" + out=$("${cmd[@]}") + (( $? == 0 )) || + log_fail "unexpected failure getting stdout from '${cmd[@]}'" + datasetexists "$TESTPOOL/$TESTFS1" && + log_fail "$TESTPOOL/$TESTFS1 unexpectedly created by '${cmd[@]}'" + echo "$out" | while IFS=$'\t' read -A toks; do + log_note "verifying ${toks[@]}" + case ${toks[0]} in + create) + log_must test "${#toks[@]}" -eq 2 + log_must test "${toks[1]}" == "$ds" + found_create="yes, I found create" + ;; + property) + log_must test "${#toks[@]}" -eq 3 + typeset prop=${toks[1]} + typeset val=${toks[2]} + if [[ -z "${exp[$prop]}" ]]; then + log_fail "unexpectedly got property '$prop'" + fi + # We may not know the exact value a property will take + # on. This is the case for at least refreservation. + if [[ ${exp[$prop]} != "*" ]]; then + log_must test "${exp[$prop]}" == "$val" + fi + unset exp[$prop] + ;; + *) + log_fail "Unexpected line ${toks[@]}" + ;; + esac + done + + log_must test "$found_create" == "yes, I found create" + log_must test "extra props: ${!exp[@]}" == "extra props: " +} + +function cleanup +{ + if datasetexists "$TESTPOOL/$TESTFS1"; then + log_must zfs destroy -r "$TESTPOOL/$TESTFS1" + fi +} +log_onexit cleanup + +log_assert "zfs create -n creates nothing but can describe what would be" \ + "created" + +# Typical creations should succeed +dry_create_no_output "$TESTPOOL/$TESTFS1" +dry_create_no_output -V 10m "$TESTPOOL/$TESTFS1" +# It shouldn't do a space check right now +dry_create_no_output -V 100t "$TESTPOOL/$TESTFS1" +# It shouldn't create parent datasets either +dry_create_no_output -p "$TESTPOOL/$TESTFS1/$TESTFS2" +dry_create_no_output -pV 10m "$TESTPOOL/$TESTFS1/$TESTFS2" + +# Various invalid properties should be recognized and result in an error +dry_create_error -o nosuchprop=42 "$TESTPOOL/$TESTFS1" +dry_create_error -b 1234 -V 10m "$TESTPOOL/$TESTFS1" + +# Parseable output should be parseable. +typeset -A expect +expect=([compression]=on) +dry_create_parseable expect -o compression=on "$TESTPOOL/$TESTFS1" + +# Sparse volumes should not get a gratuitous refreservation +expect=([volblocksize]=4096 [volsize]=$((1024 * 1024 * 10))) +dry_create_parseable expect -b 4k -V 10m -s "$TESTPOOL/$TESTFS1" + +# Non-sparse volumes should have refreservation +expect=( + [volblocksize]=4096 + [volsize]=$((1024 * 1024 * 10)) + [refreservation]="*" +) +dry_create_parseable expect -b 4k -V 10m "$TESTPOOL/$TESTFS1" + +log_pass "zfs create -n creates nothing but can describe what would be" \ + "created" diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_watched_inotify.ksh b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_watched_inotify.ksh new file mode 100644 index 0000000000..0f181621e8 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_watched_inotify.ksh @@ -0,0 +1,74 @@ +#!/bin/ksh -p +# +# CDDL HEADER START +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# +# CDDL HEADER END +# + +# +# Copyright 2020 Joyent, Inc. +# + +. $STF_SUITE/include/libtest.shlib + +# +# DESCRIPTION: +# 'zfs mount' should not get EBUSY due to inotify(5) watching a directory +# +# STRATEGY: +# 1. Create a directory +# 2. Start watching the directory with inotify(5). +# 3. Create a filesystem +# 4. Mount the filesystem at the directory created in step 1 +# 5. Destroy the filesystem +# 6. Remove the directory +# 7. Verify the watcher saw the directory removal +# + +verify_runnable "both" + +function cleanup +{ + datasetexists $TESTPOOL/$TESTFS1 && \ + log_must zfs destroy -f $TESTPOOL/$TESTFS1 + log_must rm -rf "$TESTDIR/mntpt" "$TESTDIR/watch_dir.log" +} + +log_onexit cleanup + +log_assert "'zfs mount' should not get EBUSY due to inotify(5) watching a directory" + +# 1. Create a directory. +log_must mkdir -p "$TESTDIR/mntpt" + +# 2. Start watching the directory with inotify(5). +watch_dir inotify $TESTDIR/mntpt > $TESTDIR/watch_dir.log & + +# 3. Create a filesystem +log_must zfs create $TESTPOOL/$TESTFS1 + +# 4. Mount the file system at the directory created in step 1 +log_must zfs set mountpoint=$TESTDIR/mntpt $TESTPOOL/$TESTFS1 + +# 5. Destroy the filesystem +log_must zfs destroy $TESTPOOL/$TESTFS1 + +# 6. Remove the directory. The corresponding inotify event will cause the +# watcher to exit. +log_must rmdir $TESTDIR/mntpt + +# 7. Verify the watcher saw the directory removal. This ensures that the watcher +# was watching the directory we are interested in. +wait +log_must grep -q DELETE_SELF $TESTDIR/watch_dir.log + +log_pass "'zfs mount' should not get EBUSY due to inotify(5) watching a directory" diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_watched_portfs.ksh b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_watched_portfs.ksh new file mode 100644 index 0000000000..3135203973 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_watched_portfs.ksh @@ -0,0 +1,74 @@ +#!/bin/ksh -p +# +# CDDL HEADER START +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# +# CDDL HEADER END +# + +# +# Copyright 2020 Joyent, Inc. +# + +. $STF_SUITE/include/libtest.shlib + +# +# DESCRIPTION: +# 'zfs mount' should not get EBUSY due to portfs watching a directory +# +# STRATEGY: +# 1. Create a directory +# 2. Start watching the directory with port_associate +# 3. Create a filesystem +# 4. Mount the filesystem at the directory created in step 1 +# 5. Destroy the filesystem +# 6. Remove the directory +# 7. Verify the watcher saw the directory removal +# + +verify_runnable "both" + +function cleanup +{ + datasetexists $TESTPOOL/$TESTFS1 && \ + log_must zfs destroy -f $TESTPOOL/$TESTFS1 + log_must rm -rf "$TESTDIR/mntpt" "$TESTDIR/watch_dir.log" +} + +log_onexit cleanup + +log_assert "'zfs mount' should not get EBUSY due to portfs watching a directory" + +# 1. Create a directory. +log_must mkdir -p "$TESTDIR/mntpt" + +# 2. Start watching the directory with port_associate +watch_dir portfs $TESTDIR/mntpt > $TESTDIR/watch_dir.log & + +# 3. Create a filesystem +log_must zfs create $TESTPOOL/$TESTFS1 + +# 4. Mount the file system at the directory created in step 1 +log_must zfs set mountpoint=$TESTDIR/mntpt $TESTPOOL/$TESTFS1 + +# 5. Destroy the filesystem +log_must zfs destroy $TESTPOOL/$TESTFS1 + +# 6. Remove the directory. The corresponding portfs event will cause the +# watcher to exit. +log_must rmdir $TESTDIR/mntpt + +# 7. Verify the watcher saw the directory removal. This ensures that the watcher +# was watching the directory we are interested in. +wait +log_must grep -q DELETE.$TESTDIR/mntpt $TESTDIR/watch_dir.log + +log_pass "'zfs mount' should not get EBUSY due to portfs watching a directory" diff --git a/usr/src/test/zfs-tests/tests/functional/mmp/mmp.cfg b/usr/src/test/zfs-tests/tests/functional/mmp/mmp.cfg index 9f7e76e270..a58346dcae 100644 --- a/usr/src/test/zfs-tests/tests/functional/mmp/mmp.cfg +++ b/usr/src/test/zfs-tests/tests/functional/mmp/mmp.cfg @@ -15,6 +15,7 @@ # # Copyright (c) 2017 by Lawrence Livermore National Security, LLC. +# Copyright 2019 Joyent, Inc. # export PREV_UBER="$TEST_BASE_DIR/mmp-uber-prev.txt" diff --git a/usr/src/test/zfs-tests/tests/functional/nopwrite/nopwrite_sync.ksh b/usr/src/test/zfs-tests/tests/functional/nopwrite/nopwrite_sync.ksh index 415c8bdc5e..0ff8fcf97b 100644 --- a/usr/src/test/zfs-tests/tests/functional/nopwrite/nopwrite_sync.ksh +++ b/usr/src/test/zfs-tests/tests/functional/nopwrite/nopwrite_sync.ksh @@ -13,6 +13,7 @@ # # Copyright (c) 2012, 2016 by Delphix. All rights reserved. +# Copyright 2019 Joyent, Inc. # . $STF_SUITE/include/libtest.shlib @@ -42,12 +43,12 @@ log_assert "nopwrite works for sync writes" log_must zfs set compress=on $origin log_must zfs set checksum=sha256 $origin -gnu_dd if=/dev/urandom of=$TESTDIR/file bs=1024k count=$MEGS oflag=sync \ +dd if=/dev/urandom of=$TESTDIR/file bs=1024k count=$MEGS oflag=sync \ conv=notrunc >/dev/null 2>&1 || log_fail "dd into $TESTDIR/file failed." zfs snapshot $origin@a || log_fail "zfs snap failed" log_must zfs clone $origin@a $origin/clone -gnu_dd if=/$TESTDIR/file of=/$TESTDIR/clone/file bs=1024k count=$MEGS \ +dd if=/$TESTDIR/file of=/$TESTDIR/clone/file bs=1024k count=$MEGS \ oflag=sync conv=notrunc >/dev/null 2>&1 || log_fail "dd failed." log_must verify_nopwrite $origin $origin@a $origin/clone diff --git a/usr/src/test/zfs-tests/tests/functional/slog/slog.cfg b/usr/src/test/zfs-tests/tests/functional/slog/slog.cfg index 6a28880ade..17f28abaac 100644 --- a/usr/src/test/zfs-tests/tests/functional/slog/slog.cfg +++ b/usr/src/test/zfs-tests/tests/functional/slog/slog.cfg @@ -26,10 +26,11 @@ # # Copyright (c) 2013, 2015 by Delphix. All rights reserved. +# Copyright 2019 Joyent, Inc. # -export VDIR=/disk-slog -export VDIR2=/disk2-slog +export VDIR=/var/tmp/disk-slog +export VDIR2=/var/tmp/disk2-slog export VDEV="$VDIR/a $VDIR/b $VDIR/c" export SDEV="$VDIR/d" diff --git a/usr/src/test/zfs-tests/tests/functional/slog/slog_014_pos.ksh b/usr/src/test/zfs-tests/tests/functional/slog/slog_014_pos.ksh index efd876d554..63bd52288a 100644 --- a/usr/src/test/zfs-tests/tests/functional/slog/slog_014_pos.ksh +++ b/usr/src/test/zfs-tests/tests/functional/slog/slog_014_pos.ksh @@ -27,6 +27,7 @@ # # Copyright (c) 2013, 2018 by Delphix. All rights reserved. +# Copyright 2019 Joyent, Inc. # Copyright 2019 RackTop Systems. # |