mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-23 02:44:41 +03:00
Compare commits
109 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1222e921c9 | |||
| c37fa0d5a8 | |||
| 12a78fbb4f | |||
| 63d8f57fe7 | |||
| 9fa8b5b55b | |||
| e17445d1f7 | |||
| 97d4986214 | |||
| 0ae5f0c8d2 | |||
| 146d7d8846 | |||
| 9f261b1be6 | |||
| 5acba22ec0 | |||
| 38528476bf | |||
| beb21db3c6 | |||
| 13e5e396a3 | |||
| 3cf4ecb03f | |||
| 0e765c4eb8 | |||
| c7a4255f12 | |||
| 931bef81c8 | |||
| ea34735203 | |||
| 95319fc569 | |||
| 33374f21f0 | |||
| 512a50f38d | |||
| 023ab67a64 | |||
| 65469f6e30 | |||
| 569f5d5d05 | |||
| 6d1599c1e1 | |||
| 6c9882d5db | |||
| 8c00159411 | |||
| a8c5bcb5de | |||
| 6c68594675 | |||
| 1f5979d23f | |||
| 4f951b183c | |||
| 65a0b28b42 | |||
| be068aeea8 | |||
| 1c4b0fc745 | |||
| bbbe4b0a98 | |||
| 3c144b9267 | |||
| 428a63cc62 | |||
| 3982d959c5 | |||
| 54561073e7 | |||
| 4c98586daf | |||
| ceb516ac2f | |||
| 2b9f73e5e6 | |||
| 984bfb373f | |||
| 446d08fba4 | |||
| af7a5672c3 | |||
| 73e50a7d5d | |||
| d751b12a9d | |||
| 78831d4290 | |||
| 0a223246e1 | |||
| cf966cb19a | |||
| 6e19cc77cf | |||
| c3a3c5a30f | |||
| ccd8125e45 | |||
| 2ac233c633 | |||
| 1f72a18f59 | |||
| 14a11bf2f6 | |||
| 7a03d7c73c | |||
| 9e09826b33 | |||
| 093bb64461 | |||
| 7d2489cfad | |||
| 04d4df89f4 | |||
| 05006f125c | |||
| bfe5f029cf | |||
| cc7fe8a599 | |||
| 7d64595c25 | |||
| be4a282a8d | |||
| 2d88230d97 | |||
| 95fcb04215 | |||
| d053481523 | |||
| 7a5f4656ce | |||
| 1fd28bd8d4 | |||
| ab24c9cd4c | |||
| 3c2a42fd25 | |||
| 9af524b0ee | |||
| b96ceeead2 | |||
| 01cc94f68d | |||
| fb6f6b47d6 | |||
| 2087b6cf49 | |||
| 5b0327bc57 | |||
| b5e8d14a4b | |||
| ed7b0d357a | |||
| 9e54b9d930 | |||
| b033353b25 | |||
| 6083f40387 | |||
| 592ee2e6dd | |||
| cab7d856ea | |||
| 19cebf0518 | |||
| 77e64c6fff | |||
| 4f809bddc6 | |||
| 516a08ebb4 | |||
| 812c36fc71 | |||
| fe11968bbf | |||
| 4be4dedb9f | |||
| fb52bf9b1d | |||
| a22b00f924 | |||
| c350e62309 | |||
| 6f7bc75825 | |||
| 06900c409b | |||
| 60cbc18136 | |||
| b63ed49c29 | |||
| fafe72712a | |||
| 328c95e391 | |||
| 6ce10fdabb | |||
| e4a11acfac | |||
| 90d8067a77 | |||
| e5a877c5d0 | |||
| 4933b0a25b | |||
| e0cd6c28a3 |
+11
@@ -63,3 +63,14 @@ cscope.*
|
||||
*.log
|
||||
venv
|
||||
|
||||
#
|
||||
# Module leftovers
|
||||
#
|
||||
/module/avl/zavl.mod
|
||||
/module/icp/icp.mod
|
||||
/module/lua/zlua.mod
|
||||
/module/nvpair/znvpair.mod
|
||||
/module/spl/spl.mod
|
||||
/module/unicode/zunicode.mod
|
||||
/module/zcommon/zcommon.mod
|
||||
/module/zfs/zfs.mod
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
Meta: 1
|
||||
Name: zfs
|
||||
Branch: 1.0
|
||||
Version: 0.8.1
|
||||
Version: 0.8.2
|
||||
Release: 1
|
||||
Release-Tags: relext
|
||||
License: CDDL
|
||||
Author: OpenZFS on Linux
|
||||
Linux-Maximum: 5.1
|
||||
Linux-Maximum: 5.3
|
||||
Linux-Minimum: 2.6.32
|
||||
|
||||
+2
-1
@@ -52,7 +52,8 @@ distclean-local::
|
||||
-type f -print | xargs $(RM)
|
||||
|
||||
all-local:
|
||||
-${top_srcdir}/scripts/zfs-tests.sh -c
|
||||
-[ -x ${top_builddir}/scripts/zfs-tests.sh ] && \
|
||||
${top_builddir}/scripts/zfs-tests.sh -c
|
||||
|
||||
dist-hook: gitrev
|
||||
cp ${top_srcdir}/include/zfs_gitrev.h $(distdir)/include; \
|
||||
|
||||
+1
-1
@@ -5,4 +5,4 @@ if USING_PYTHON
|
||||
SUBDIRS += arcstat arc_summary dbufstat
|
||||
endif
|
||||
|
||||
SUBDIRS += mount_zfs zed zvol_id
|
||||
SUBDIRS += mount_zfs zed zvol_id zvol_wait
|
||||
|
||||
+2
-55
@@ -1,12 +1,11 @@
|
||||
SUBDIRS = zed.d
|
||||
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
DEFAULT_INCLUDES += \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/lib/libspl/include
|
||||
|
||||
EXTRA_DIST = zed.d/README \
|
||||
zed.d/history_event-zfs-list-cacher.sh.in
|
||||
|
||||
sbin_PROGRAMS = zed
|
||||
|
||||
ZED_SRC = \
|
||||
@@ -47,55 +46,3 @@ zed_LDADD = \
|
||||
|
||||
zed_LDADD += -lrt
|
||||
zed_LDFLAGS = -pthread
|
||||
|
||||
zedconfdir = $(sysconfdir)/zfs/zed.d
|
||||
|
||||
dist_zedconf_DATA = \
|
||||
zed.d/zed-functions.sh \
|
||||
zed.d/zed.rc
|
||||
|
||||
zedexecdir = $(zfsexecdir)/zed.d
|
||||
|
||||
dist_zedexec_SCRIPTS = \
|
||||
zed.d/all-debug.sh \
|
||||
zed.d/all-syslog.sh \
|
||||
zed.d/data-notify.sh \
|
||||
zed.d/generic-notify.sh \
|
||||
zed.d/resilver_finish-notify.sh \
|
||||
zed.d/scrub_finish-notify.sh \
|
||||
zed.d/statechange-led.sh \
|
||||
zed.d/statechange-notify.sh \
|
||||
zed.d/vdev_clear-led.sh \
|
||||
zed.d/vdev_attach-led.sh \
|
||||
zed.d/pool_import-led.sh \
|
||||
zed.d/resilver_finish-start-scrub.sh
|
||||
|
||||
nodist_zedexec_SCRIPTS = zed.d/history_event-zfs-list-cacher.sh
|
||||
|
||||
$(nodist_zedexec_SCRIPTS): %: %.in
|
||||
-$(SED) -e 's,@bindir\@,$(bindir),g' \
|
||||
-e 's,@runstatedir\@,$(runstatedir),g' \
|
||||
-e 's,@sbindir\@,$(sbindir),g' \
|
||||
-e 's,@sysconfdir\@,$(sysconfdir),g' \
|
||||
$< >'$@'
|
||||
|
||||
zedconfdefaults = \
|
||||
all-syslog.sh \
|
||||
data-notify.sh \
|
||||
resilver_finish-notify.sh \
|
||||
scrub_finish-notify.sh \
|
||||
statechange-led.sh \
|
||||
statechange-notify.sh \
|
||||
vdev_clear-led.sh \
|
||||
vdev_attach-led.sh \
|
||||
pool_import-led.sh \
|
||||
resilver_finish-start-scrub.sh
|
||||
|
||||
install-data-hook:
|
||||
$(MKDIR_P) "$(DESTDIR)$(zedconfdir)"
|
||||
for f in $(zedconfdefaults); do \
|
||||
test -f "$(DESTDIR)$(zedconfdir)/$${f}" -o \
|
||||
-L "$(DESTDIR)$(zedconfdir)/$${f}" || \
|
||||
ln -s "$(zedexecdir)/$${f}" "$(DESTDIR)$(zedconfdir)"; \
|
||||
done
|
||||
chmod 0600 "$(DESTDIR)$(zedconfdir)/zed.rc"
|
||||
|
||||
@@ -116,7 +116,8 @@ zfs_agent_iter_vdev(zpool_handle_t *zhp, nvlist_t *nvl, void *arg)
|
||||
/*
|
||||
* On a devid match, grab the vdev guid and expansion time, if any.
|
||||
*/
|
||||
if ((nvlist_lookup_string(nvl, ZPOOL_CONFIG_DEVID, &path) == 0) &&
|
||||
if (gsp->gs_devid != NULL &&
|
||||
(nvlist_lookup_string(nvl, ZPOOL_CONFIG_DEVID, &path) == 0) &&
|
||||
(strcmp(gsp->gs_devid, path) == 0)) {
|
||||
(void) nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_GUID,
|
||||
&gsp->gs_vdev_guid);
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
include $(top_srcdir)/config/Rules.am
|
||||
|
||||
EXTRA_DIST = \
|
||||
README \
|
||||
history_event-zfs-list-cacher.sh.in
|
||||
|
||||
zedconfdir = $(sysconfdir)/zfs/zed.d
|
||||
|
||||
dist_zedconf_DATA = \
|
||||
zed-functions.sh \
|
||||
zed.rc
|
||||
|
||||
zedexecdir = $(zfsexecdir)/zed.d
|
||||
|
||||
dist_zedexec_SCRIPTS = \
|
||||
all-debug.sh \
|
||||
all-syslog.sh \
|
||||
data-notify.sh \
|
||||
generic-notify.sh \
|
||||
resilver_finish-notify.sh \
|
||||
scrub_finish-notify.sh \
|
||||
statechange-led.sh \
|
||||
statechange-notify.sh \
|
||||
vdev_clear-led.sh \
|
||||
vdev_attach-led.sh \
|
||||
pool_import-led.sh \
|
||||
resilver_finish-start-scrub.sh
|
||||
|
||||
nodist_zedexec_SCRIPTS = history_event-zfs-list-cacher.sh
|
||||
|
||||
$(nodist_zedexec_SCRIPTS): %: %.in
|
||||
-$(SED) -e 's,@bindir\@,$(bindir),g' \
|
||||
-e 's,@runstatedir\@,$(runstatedir),g' \
|
||||
-e 's,@sbindir\@,$(sbindir),g' \
|
||||
-e 's,@sysconfdir\@,$(sysconfdir),g' \
|
||||
$< >'$@'
|
||||
|
||||
zedconfdefaults = \
|
||||
all-syslog.sh \
|
||||
data-notify.sh \
|
||||
resilver_finish-notify.sh \
|
||||
scrub_finish-notify.sh \
|
||||
statechange-led.sh \
|
||||
statechange-notify.sh \
|
||||
vdev_clear-led.sh \
|
||||
vdev_attach-led.sh \
|
||||
pool_import-led.sh \
|
||||
resilver_finish-start-scrub.sh
|
||||
|
||||
install-data-hook:
|
||||
$(MKDIR_P) "$(DESTDIR)$(zedconfdir)"
|
||||
for f in $(zedconfdefaults); do \
|
||||
test -f "$(DESTDIR)$(zedconfdir)/$${f}" -o \
|
||||
-L "$(DESTDIR)$(zedconfdir)/$${f}" || \
|
||||
ln -s "$(zedexecdir)/$${f}" "$(DESTDIR)$(zedconfdir)"; \
|
||||
done
|
||||
chmod 0600 "$(DESTDIR)$(zedconfdir)/zed.rc"
|
||||
@@ -47,7 +47,7 @@ case "${ZEVENT_HISTORY_INTERNAL_NAME}" in
|
||||
# Only act if one of the tracked properties is altered.
|
||||
case "${ZEVENT_HISTORY_INTERNAL_STR%%=*}" in
|
||||
canmount|mountpoint|atime|relatime|devices|exec| \
|
||||
readonly|setuid|nbmand) ;;
|
||||
readonly|setuid|nbmand|encroot|keylocation) ;;
|
||||
*) exit 0 ;;
|
||||
esac
|
||||
;;
|
||||
@@ -62,7 +62,7 @@ zed_lock zfs-list
|
||||
trap abort_alter EXIT
|
||||
|
||||
PROPS="name,mountpoint,canmount,atime,relatime,devices,exec,readonly"
|
||||
PROPS="${PROPS},setuid,nbmand"
|
||||
PROPS="${PROPS},setuid,nbmand,encroot,keylocation"
|
||||
|
||||
"${ZFS}" list -H -t filesystem -o $PROPS -r "${ZEVENT_POOL}" > "${FSLIST_TMP}"
|
||||
|
||||
|
||||
+20
-3
@@ -6446,8 +6446,25 @@ share_mount_one(zfs_handle_t *zhp, int op, int flags, char *protocol,
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (zfs_mount(zhp, options, flags) != 0)
|
||||
if (zfs_mount(zhp, options, flags) != 0) {
|
||||
/*
|
||||
* Check if a mount sneaked in after we checked
|
||||
*/
|
||||
if (!explicit &&
|
||||
libzfs_errno(g_zfs) == EZFS_MOUNTFAILED) {
|
||||
usleep(10 * MILLISEC);
|
||||
libzfs_mnttab_cache(g_zfs, B_FALSE);
|
||||
|
||||
if (zfs_is_mounted(zhp, NULL)) {
|
||||
(void) fprintf(stderr, gettext(
|
||||
"Ignoring previous 'already "
|
||||
"mounted' error for '%s'\n"),
|
||||
zfs_get_name(zhp));
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -6733,8 +6750,8 @@ unshare_unmount_compare(const void *larg, const void *rarg, void *unused)
|
||||
|
||||
/*
|
||||
* Convenience routine used by zfs_do_umount() and manual_unmount(). Given an
|
||||
* absolute path, find the entry /proc/self/mounts, verify that its a
|
||||
* ZFS filesystems, and unmount it appropriately.
|
||||
* absolute path, find the entry /proc/self/mounts, verify that it's a
|
||||
* ZFS filesystem, and unmount it appropriately.
|
||||
*/
|
||||
static int
|
||||
unshare_unmount_path(int op, char *path, int flags, boolean_t is_manual)
|
||||
|
||||
+8
-10
@@ -785,7 +785,7 @@ add_prop_list_default(const char *propname, char *propval, nvlist_t **props,
|
||||
* -P Display full path for vdev name.
|
||||
*
|
||||
* Adds the given vdevs to 'pool'. As with create, the bulk of this work is
|
||||
* handled by get_vdev_spec(), which constructs the nvlist needed to pass to
|
||||
* handled by make_root_vdev(), which constructs the nvlist needed to pass to
|
||||
* libzfs.
|
||||
*/
|
||||
int
|
||||
@@ -883,7 +883,7 @@ zpool_do_add(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
/* pass off to get_vdev_spec for processing */
|
||||
/* pass off to make_root_vdev for processing */
|
||||
nvroot = make_root_vdev(zhp, props, force, !force, B_FALSE, dryrun,
|
||||
argc, argv);
|
||||
if (nvroot == NULL) {
|
||||
@@ -1232,9 +1232,9 @@ errout:
|
||||
* -O Set fsproperty=value in the pool's root file system
|
||||
*
|
||||
* Creates the named pool according to the given vdev specification. The
|
||||
* bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c. Once
|
||||
* we get the nvlist back from get_vdev_spec(), we either print out the contents
|
||||
* (if '-n' was specified), or pass it to libzfs to do the creation.
|
||||
* bulk of the vdev processing is done in make_root_vdev() in zpool_vdev.c.
|
||||
* Once we get the nvlist back from make_root_vdev(), we either print out the
|
||||
* contents (if '-n' was specified), or pass it to libzfs to do the creation.
|
||||
*/
|
||||
int
|
||||
zpool_do_create(int argc, char **argv)
|
||||
@@ -1388,7 +1388,7 @@ zpool_do_create(int argc, char **argv)
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* pass off to get_vdev_spec for bulk processing */
|
||||
/* pass off to make_root_vdev for bulk processing */
|
||||
nvroot = make_root_vdev(NULL, props, force, !force, B_FALSE, dryrun,
|
||||
argc - 1, argv + 1);
|
||||
if (nvroot == NULL)
|
||||
@@ -6111,9 +6111,8 @@ zpool_do_detach(int argc, char **argv)
|
||||
int ret;
|
||||
|
||||
/* check options */
|
||||
while ((c = getopt(argc, argv, "f")) != -1) {
|
||||
while ((c = getopt(argc, argv, "")) != -1) {
|
||||
switch (c) {
|
||||
case 'f':
|
||||
case '?':
|
||||
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
|
||||
optopt);
|
||||
@@ -6342,12 +6341,11 @@ zpool_do_online(int argc, char **argv)
|
||||
int flags = 0;
|
||||
|
||||
/* check options */
|
||||
while ((c = getopt(argc, argv, "et")) != -1) {
|
||||
while ((c = getopt(argc, argv, "e")) != -1) {
|
||||
switch (c) {
|
||||
case 'e':
|
||||
flags |= ZFS_ONLINE_EXPAND;
|
||||
break;
|
||||
case 't':
|
||||
case '?':
|
||||
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
|
||||
optopt);
|
||||
|
||||
@@ -433,6 +433,7 @@ check_disk(const char *path, blkid_cache cache, int force,
|
||||
char *value = blkid_get_tag_value(cache, "TYPE", path);
|
||||
(void) fprintf(stderr, gettext("%s is in use and contains "
|
||||
"a %s filesystem.\n"), path, value ? value : "unknown");
|
||||
free(value);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,6 @@
|
||||
*/
|
||||
#define DUMP_GROUPING 4
|
||||
|
||||
uint64_t total_write_size = 0;
|
||||
uint64_t total_stream_len = 0;
|
||||
FILE *send_stream = 0;
|
||||
boolean_t do_byteswap = B_FALSE;
|
||||
@@ -219,6 +218,9 @@ main(int argc, char *argv[])
|
||||
{
|
||||
char *buf = safe_malloc(SPA_MAXBLOCKSIZE);
|
||||
uint64_t drr_record_count[DRR_NUMTYPES] = { 0 };
|
||||
uint64_t total_payload_size = 0;
|
||||
uint64_t total_overhead_size = 0;
|
||||
uint64_t drr_byte_count[DRR_NUMTYPES] = { 0 };
|
||||
char salt[ZIO_DATA_SALT_LEN * 2 + 1];
|
||||
char iv[ZIO_DATA_IV_LEN * 2 + 1];
|
||||
char mac[ZIO_DATA_MAC_LEN * 2 + 1];
|
||||
@@ -336,7 +338,9 @@ main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
drr_record_count[drr->drr_type]++;
|
||||
total_overhead_size += sizeof (*drr);
|
||||
total_records++;
|
||||
payload_size = 0;
|
||||
|
||||
switch (drr->drr_type) {
|
||||
case DRR_BEGIN:
|
||||
@@ -390,6 +394,7 @@ main(int argc, char *argv[])
|
||||
nvlist_print(stdout, nv);
|
||||
nvlist_free(nv);
|
||||
}
|
||||
payload_size = sz;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -554,7 +559,6 @@ main(int argc, char *argv[])
|
||||
if (dump) {
|
||||
print_block(buf, payload_size);
|
||||
}
|
||||
total_write_size += payload_size;
|
||||
break;
|
||||
|
||||
case DRR_WRITE_BYREF:
|
||||
@@ -683,6 +687,7 @@ main(int argc, char *argv[])
|
||||
print_block(buf,
|
||||
P2ROUNDUP(drrwe->drr_psize, 8));
|
||||
}
|
||||
payload_size = P2ROUNDUP(drrwe->drr_psize, 8);
|
||||
break;
|
||||
case DRR_OBJECT_RANGE:
|
||||
if (do_byteswap) {
|
||||
@@ -723,6 +728,8 @@ main(int argc, char *argv[])
|
||||
(longlong_t)drrc->drr_checksum.zc_word[3]);
|
||||
}
|
||||
pcksum = zc;
|
||||
drr_byte_count[drr->drr_type] += payload_size;
|
||||
total_payload_size += payload_size;
|
||||
}
|
||||
free(buf);
|
||||
fletcher_4_fini();
|
||||
@@ -730,28 +737,40 @@ main(int argc, char *argv[])
|
||||
/* Print final summary */
|
||||
|
||||
(void) printf("SUMMARY:\n");
|
||||
(void) printf("\tTotal DRR_BEGIN records = %lld\n",
|
||||
(u_longlong_t)drr_record_count[DRR_BEGIN]);
|
||||
(void) printf("\tTotal DRR_END records = %lld\n",
|
||||
(u_longlong_t)drr_record_count[DRR_END]);
|
||||
(void) printf("\tTotal DRR_OBJECT records = %lld\n",
|
||||
(u_longlong_t)drr_record_count[DRR_OBJECT]);
|
||||
(void) printf("\tTotal DRR_FREEOBJECTS records = %lld\n",
|
||||
(u_longlong_t)drr_record_count[DRR_FREEOBJECTS]);
|
||||
(void) printf("\tTotal DRR_WRITE records = %lld\n",
|
||||
(u_longlong_t)drr_record_count[DRR_WRITE]);
|
||||
(void) printf("\tTotal DRR_WRITE_BYREF records = %lld\n",
|
||||
(u_longlong_t)drr_record_count[DRR_WRITE_BYREF]);
|
||||
(void) printf("\tTotal DRR_WRITE_EMBEDDED records = %lld\n",
|
||||
(u_longlong_t)drr_record_count[DRR_WRITE_EMBEDDED]);
|
||||
(void) printf("\tTotal DRR_FREE records = %lld\n",
|
||||
(u_longlong_t)drr_record_count[DRR_FREE]);
|
||||
(void) printf("\tTotal DRR_SPILL records = %lld\n",
|
||||
(u_longlong_t)drr_record_count[DRR_SPILL]);
|
||||
(void) printf("\tTotal DRR_BEGIN records = %lld (%llu bytes)\n",
|
||||
(u_longlong_t)drr_record_count[DRR_BEGIN],
|
||||
(u_longlong_t)drr_byte_count[DRR_BEGIN]);
|
||||
(void) printf("\tTotal DRR_END records = %lld (%llu bytes)\n",
|
||||
(u_longlong_t)drr_record_count[DRR_END],
|
||||
(u_longlong_t)drr_byte_count[DRR_END]);
|
||||
(void) printf("\tTotal DRR_OBJECT records = %lld (%llu bytes)\n",
|
||||
(u_longlong_t)drr_record_count[DRR_OBJECT],
|
||||
(u_longlong_t)drr_byte_count[DRR_OBJECT]);
|
||||
(void) printf("\tTotal DRR_FREEOBJECTS records = %lld (%llu bytes)\n",
|
||||
(u_longlong_t)drr_record_count[DRR_FREEOBJECTS],
|
||||
(u_longlong_t)drr_byte_count[DRR_FREEOBJECTS]);
|
||||
(void) printf("\tTotal DRR_WRITE records = %lld (%llu bytes)\n",
|
||||
(u_longlong_t)drr_record_count[DRR_WRITE],
|
||||
(u_longlong_t)drr_byte_count[DRR_WRITE]);
|
||||
(void) printf("\tTotal DRR_WRITE_BYREF records = %lld (%llu bytes)\n",
|
||||
(u_longlong_t)drr_record_count[DRR_WRITE_BYREF],
|
||||
(u_longlong_t)drr_byte_count[DRR_WRITE_BYREF]);
|
||||
(void) printf("\tTotal DRR_WRITE_EMBEDDED records = %lld (%llu "
|
||||
"bytes)\n", (u_longlong_t)drr_record_count[DRR_WRITE_EMBEDDED],
|
||||
(u_longlong_t)drr_byte_count[DRR_WRITE_EMBEDDED]);
|
||||
(void) printf("\tTotal DRR_FREE records = %lld (%llu bytes)\n",
|
||||
(u_longlong_t)drr_record_count[DRR_FREE],
|
||||
(u_longlong_t)drr_byte_count[DRR_FREE]);
|
||||
(void) printf("\tTotal DRR_SPILL records = %lld (%llu bytes)\n",
|
||||
(u_longlong_t)drr_record_count[DRR_SPILL],
|
||||
(u_longlong_t)drr_byte_count[DRR_SPILL]);
|
||||
(void) printf("\tTotal records = %lld\n",
|
||||
(u_longlong_t)total_records);
|
||||
(void) printf("\tTotal write size = %lld (0x%llx)\n",
|
||||
(u_longlong_t)total_write_size, (u_longlong_t)total_write_size);
|
||||
(void) printf("\tTotal payload size = %lld (0x%llx)\n",
|
||||
(u_longlong_t)total_payload_size, (u_longlong_t)total_payload_size);
|
||||
(void) printf("\tTotal header overhead = %lld (0x%llx)\n",
|
||||
(u_longlong_t)total_overhead_size,
|
||||
(u_longlong_t)total_overhead_size);
|
||||
(void) printf("\tTotal stream length = %lld (0x%llx)\n",
|
||||
(u_longlong_t)total_stream_len, (u_longlong_t)total_stream_len);
|
||||
return (0);
|
||||
|
||||
+17
-1
@@ -2745,8 +2745,24 @@ ztest_spa_create_destroy(ztest_ds_t *zd, uint64_t id)
|
||||
VERIFY3U(EEXIST, ==,
|
||||
spa_create(zo->zo_pool, nvroot, NULL, NULL, NULL));
|
||||
nvlist_free(nvroot);
|
||||
|
||||
/*
|
||||
* We open a reference to the spa and then we try to export it
|
||||
* expecting one of the following errors:
|
||||
*
|
||||
* EBUSY
|
||||
* Because of the reference we just opened.
|
||||
*
|
||||
* ZFS_ERR_EXPORT_IN_PROGRESS
|
||||
* For the case that there is another ztest thread doing
|
||||
* an export concurrently.
|
||||
*/
|
||||
VERIFY3U(0, ==, spa_open(zo->zo_pool, &spa, FTAG));
|
||||
VERIFY3U(EBUSY, ==, spa_destroy(zo->zo_pool));
|
||||
int error = spa_destroy(zo->zo_pool);
|
||||
if (error != EBUSY && error != ZFS_ERR_EXPORT_IN_PROGRESS) {
|
||||
fatal(0, "spa_destroy(%s) returned unexpected value %d",
|
||||
spa->spa_name, error);
|
||||
}
|
||||
spa_close(spa, FTAG);
|
||||
|
||||
(void) pthread_rwlock_unlock(&ztest_name_lock);
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
dist_bin_SCRIPTS = zvol_wait
|
||||
Executable
+112
@@ -0,0 +1,112 @@
|
||||
#!/bin/sh
|
||||
|
||||
count_zvols() {
|
||||
if [ -z "$zvols" ]; then
|
||||
echo 0
|
||||
else
|
||||
echo "$zvols" | wc -l
|
||||
fi
|
||||
}
|
||||
|
||||
filter_out_zvols_with_links() {
|
||||
while read -r zvol; do
|
||||
if [ ! -L "/dev/zvol/$zvol" ]; then
|
||||
echo "$zvol"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
filter_out_deleted_zvols() {
|
||||
while read -r zvol; do
|
||||
if zfs list "$zvol" >/dev/null 2>&1; then
|
||||
echo "$zvol"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
list_zvols() {
|
||||
zfs list -t volume -H -o name,volmode,receive_resume_token |
|
||||
while read -r zvol_line; do
|
||||
name=$(echo "$zvol_line" | awk '{print $1}')
|
||||
volmode=$(echo "$zvol_line" | awk '{print $2}')
|
||||
token=$(echo "$zvol_line" | awk '{print $3}')
|
||||
#
|
||||
# /dev links are not created for zvols with volmode = "none".
|
||||
#
|
||||
[ "$volmode" = "none" ] && continue
|
||||
#
|
||||
# We also also ignore partially received zvols if it is
|
||||
# not an incremental receive, as those won't even have a block
|
||||
# device minor node created yet.
|
||||
#
|
||||
if [ "$token" != "-" ]; then
|
||||
#
|
||||
# Incremental receives create an invisible clone that
|
||||
# is not automatically displayed by zfs list.
|
||||
#
|
||||
if ! zfs list "$name/%recv" >/dev/null 2>&1; then
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
echo "$name"
|
||||
done
|
||||
}
|
||||
|
||||
zvols=$(list_zvols)
|
||||
zvols_count=$(count_zvols)
|
||||
if [ "$zvols_count" -eq 0 ]; then
|
||||
echo "No zvols found, nothing to do."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Testing $zvols_count zvol links"
|
||||
|
||||
outer_loop=0
|
||||
while [ "$outer_loop" -lt 20 ]; do
|
||||
outer_loop=$((outer_loop + 1))
|
||||
|
||||
old_zvols_count=$(count_zvols)
|
||||
|
||||
inner_loop=0
|
||||
while [ "$inner_loop" -lt 30 ]; do
|
||||
inner_loop=$((inner_loop + 1))
|
||||
|
||||
zvols="$(echo "$zvols" | filter_out_zvols_with_links)"
|
||||
|
||||
zvols_count=$(count_zvols)
|
||||
if [ "$zvols_count" -eq 0 ]; then
|
||||
echo "All zvol links are now present."
|
||||
exit 0
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
echo "Still waiting on $zvols_count zvol links ..."
|
||||
#
|
||||
# Although zvols should normally not be deleted at boot time,
|
||||
# if that is the case then their links will be missing and
|
||||
# we would stall.
|
||||
#
|
||||
if [ "$old_zvols_count" -eq "$zvols_count" ]; then
|
||||
echo "No progress since last loop."
|
||||
echo "Checking if any zvols were deleted."
|
||||
|
||||
zvols=$(echo "$zvols" | filter_out_deleted_zvols)
|
||||
zvols_count=$(count_zvols)
|
||||
|
||||
if [ "$old_zvols_count" -ne "$zvols_count" ]; then
|
||||
echo "$((old_zvols_count - zvols_count)) zvol(s) deleted."
|
||||
fi
|
||||
|
||||
if [ "$zvols_count" -ne 0 ]; then
|
||||
echo "Remaining zvols:"
|
||||
echo "$zvols"
|
||||
else
|
||||
echo "All zvol links are now present."
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Timed out waiting on zvol links"
|
||||
exit 1
|
||||
+23
-64
@@ -1,47 +1,3 @@
|
||||
dnl #
|
||||
dnl # ZFS_AC_PYTHON_VERSION(version, [action-if-true], [action-if-false])
|
||||
dnl #
|
||||
dnl # Verify Python version
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_PYTHON_VERSION], [
|
||||
ver_check=`$PYTHON -c "import sys; print (sys.version.split()[[0]] $1)"`
|
||||
AS_IF([test "$ver_check" = "True"], [
|
||||
m4_ifvaln([$2], [$2])
|
||||
], [
|
||||
m4_ifvaln([$3], [$3])
|
||||
])
|
||||
])
|
||||
|
||||
dnl #
|
||||
dnl # ZFS_AC_PYTHON_VERSION_IS_2
|
||||
dnl # ZFS_AC_PYTHON_VERSION_IS_3
|
||||
dnl #
|
||||
dnl # Tests if the $PYTHON_VERSION matches 2.x or 3.x.
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_PYTHON_VERSION_IS_2],
|
||||
[test "${PYTHON_VERSION%%\.*}" = "2"])
|
||||
AC_DEFUN([ZFS_AC_PYTHON_VERSION_IS_3],
|
||||
[test "${PYTHON_VERSION%%\.*}" = "3"])
|
||||
|
||||
dnl #
|
||||
dnl # ZFS_AC_PYTHON_MODULE(module_name, [action-if-true], [action-if-false])
|
||||
dnl #
|
||||
dnl # Checks for Python module. Freely inspired by AX_PYTHON_MODULE
|
||||
dnl # https://www.gnu.org/software/autoconf-archive/ax_python_module.html
|
||||
dnl # Required by ZFS_AC_CONFIG_ALWAYS_PYZFS.
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_PYTHON_MODULE], [
|
||||
PYTHON_NAME=`basename $PYTHON`
|
||||
AC_MSG_CHECKING([for $PYTHON_NAME module: $1])
|
||||
AS_IF([$PYTHON -c "import $1" 2>/dev/null], [
|
||||
AC_MSG_RESULT(yes)
|
||||
m4_ifvaln([$2], [$2])
|
||||
], [
|
||||
AC_MSG_RESULT(no)
|
||||
m4_ifvaln([$3], [$3])
|
||||
])
|
||||
])
|
||||
|
||||
dnl #
|
||||
dnl # The majority of the python scripts are written to be compatible
|
||||
dnl # with Python 2.6 and Python 3.4. Therefore, they may be installed
|
||||
@@ -66,35 +22,38 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_PYTHON], [
|
||||
[AC_MSG_ERROR([Unknown --with-python value '$with_python'])]
|
||||
)
|
||||
|
||||
AS_IF([test $PYTHON != :], [
|
||||
AS_IF([$PYTHON --version >/dev/null 2>&1],
|
||||
[AM_PATH_PYTHON([2.6], [], [:])],
|
||||
[AC_MSG_ERROR([Cannot find $PYTHON in your system path])]
|
||||
)
|
||||
])
|
||||
AM_CONDITIONAL([USING_PYTHON], [test "$PYTHON" != :])
|
||||
AM_CONDITIONAL([USING_PYTHON_2], [ZFS_AC_PYTHON_VERSION_IS_2])
|
||||
AM_CONDITIONAL([USING_PYTHON_3], [ZFS_AC_PYTHON_VERSION_IS_3])
|
||||
|
||||
dnl #
|
||||
dnl # Minimum supported Python versions for utilities:
|
||||
dnl # Python 2.6.x, or Python 3.4.x
|
||||
dnl # Python 2.6 or Python 3.4
|
||||
dnl #
|
||||
AS_IF([ZFS_AC_PYTHON_VERSION_IS_2], [
|
||||
ZFS_AC_PYTHON_VERSION([>= '2.6'], [ true ],
|
||||
[AC_MSG_ERROR("Python >= 2.6.x is not available")])
|
||||
AM_PATH_PYTHON([], [], [:])
|
||||
AS_IF([test -z "$PYTHON_VERSION"], [
|
||||
PYTHON_VERSION=$(basename $PYTHON | tr -cd 0-9.)
|
||||
])
|
||||
PYTHON_MINOR=${PYTHON_VERSION#*\.}
|
||||
|
||||
AS_IF([ZFS_AC_PYTHON_VERSION_IS_3], [
|
||||
ZFS_AC_PYTHON_VERSION([>= '3.4'], [ true ],
|
||||
[AC_MSG_ERROR("Python >= 3.4.x is not available")])
|
||||
])
|
||||
AS_CASE([$PYTHON_VERSION],
|
||||
[2.*], [
|
||||
AS_IF([test $PYTHON_MINOR -lt 6],
|
||||
[AC_MSG_ERROR("Python >= 2.6 is required")])
|
||||
],
|
||||
[3.*], [
|
||||
AS_IF([test $PYTHON_MINOR -lt 4],
|
||||
[AC_MSG_ERROR("Python >= 3.4 is required")])
|
||||
],
|
||||
[:|2|3], [],
|
||||
[PYTHON_VERSION=3]
|
||||
)
|
||||
|
||||
AM_CONDITIONAL([USING_PYTHON], [test "$PYTHON" != :])
|
||||
AM_CONDITIONAL([USING_PYTHON_2], [test "x${PYTHON_VERSION%%\.*}" = x2])
|
||||
AM_CONDITIONAL([USING_PYTHON_3], [test "x${PYTHON_VERSION%%\.*}" = x3])
|
||||
|
||||
dnl #
|
||||
dnl # Request that packages be built for a specific Python version.
|
||||
dnl #
|
||||
AS_IF([test $with_python != check], [
|
||||
PYTHON_PKG_VERSION=`echo ${PYTHON} | tr -d 'a-zA-Z.'`
|
||||
AS_IF([test "x$with_python" != xcheck], [
|
||||
PYTHON_PKG_VERSION=$(echo $PYTHON_VERSION | tr -d .)
|
||||
DEFINE_PYTHON_PKG_VERSION='--define "__use_python_pkg_version '${PYTHON_PKG_VERSION}'"'
|
||||
DEFINE_PYTHON_VERSION='--define "__use_python '${PYTHON}'"'
|
||||
], [
|
||||
|
||||
+30
-15
@@ -1,5 +1,24 @@
|
||||
dnl #
|
||||
dnl # Determines if pyzfs can be built, requires Python 2.7 or latter.
|
||||
dnl # ZFS_AC_PYTHON_MODULE(module_name, [action-if-true], [action-if-false])
|
||||
dnl #
|
||||
dnl # Checks for Python module. Freely inspired by AX_PYTHON_MODULE
|
||||
dnl # https://www.gnu.org/software/autoconf-archive/ax_python_module.html
|
||||
dnl # Required by ZFS_AC_CONFIG_ALWAYS_PYZFS.
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_PYTHON_MODULE], [
|
||||
PYTHON_NAME=$(basename $PYTHON)
|
||||
AC_MSG_CHECKING([for $PYTHON_NAME module: $1])
|
||||
AS_IF([$PYTHON -c "import $1" 2>/dev/null], [
|
||||
AC_MSG_RESULT(yes)
|
||||
m4_ifvaln([$2], [$2])
|
||||
], [
|
||||
AC_MSG_RESULT(no)
|
||||
m4_ifvaln([$3], [$3])
|
||||
])
|
||||
])
|
||||
|
||||
dnl #
|
||||
dnl # Determines if pyzfs can be built, requires Python 2.7 or later.
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_PYZFS], [
|
||||
AC_ARG_ENABLE([pyzfs],
|
||||
@@ -18,7 +37,7 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_PYZFS], [
|
||||
DEFINE_PYZFS='--without pyzfs'
|
||||
])
|
||||
], [
|
||||
AS_IF([test $PYTHON != :], [
|
||||
AS_IF([test "$PYTHON" != :], [
|
||||
DEFINE_PYZFS=''
|
||||
], [
|
||||
enable_pyzfs=no
|
||||
@@ -31,20 +50,16 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_PYZFS], [
|
||||
dnl # Require python-devel libraries
|
||||
dnl #
|
||||
AS_IF([test "x$enable_pyzfs" = xcheck -o "x$enable_pyzfs" = xyes], [
|
||||
AS_IF([ZFS_AC_PYTHON_VERSION_IS_2], [
|
||||
PYTHON_REQUIRED_VERSION=">= '2.7.0'"
|
||||
], [
|
||||
AS_IF([ZFS_AC_PYTHON_VERSION_IS_3], [
|
||||
PYTHON_REQUIRED_VERSION=">= '3.4.0'"
|
||||
], [
|
||||
AC_MSG_ERROR("Python $PYTHON_VERSION unknown")
|
||||
])
|
||||
])
|
||||
AS_CASE([$PYTHON_VERSION],
|
||||
[3.*], [PYTHON_REQUIRED_VERSION=">= '3.4.0'"],
|
||||
[2.*], [PYTHON_REQUIRED_VERSION=">= '2.7.0'"],
|
||||
[AC_MSG_ERROR("Python $PYTHON_VERSION unknown")]
|
||||
)
|
||||
|
||||
AX_PYTHON_DEVEL([$PYTHON_REQUIRED_VERSION], [
|
||||
AS_IF([test "x$enable_pyzfs" = xyes], [
|
||||
AC_MSG_ERROR("Python $PYTHON_REQUIRED_VERSION development library is not installed")
|
||||
], [test ! "x$enable_pyzfs" = xno], [
|
||||
], [test "x$enable_pyzfs" != xno], [
|
||||
enable_pyzfs=no
|
||||
])
|
||||
])
|
||||
@@ -57,7 +72,7 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_PYZFS], [
|
||||
ZFS_AC_PYTHON_MODULE([setuptools], [], [
|
||||
AS_IF([test "x$enable_pyzfs" = xyes], [
|
||||
AC_MSG_ERROR("Python $PYTHON_VERSION setuptools is not installed")
|
||||
], [test ! "x$enable_pyzfs" = xno], [
|
||||
], [test "x$enable_pyzfs" != xno], [
|
||||
enable_pyzfs=no
|
||||
])
|
||||
])
|
||||
@@ -70,7 +85,7 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_PYZFS], [
|
||||
ZFS_AC_PYTHON_MODULE([cffi], [], [
|
||||
AS_IF([test "x$enable_pyzfs" = xyes], [
|
||||
AC_MSG_ERROR("Python $PYTHON_VERSION cffi is not installed")
|
||||
], [test ! "x$enable_pyzfs" = xno], [
|
||||
], [test "x$enable_pyzfs" != xno], [
|
||||
enable_pyzfs=no
|
||||
])
|
||||
])
|
||||
@@ -81,7 +96,7 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_PYZFS], [
|
||||
dnl #
|
||||
AS_IF([test "x$enable_pyzfs" = xcheck], [enable_pyzfs=yes])
|
||||
|
||||
AM_CONDITIONAL([PYZFS_ENABLED], [test x$enable_pyzfs = xyes])
|
||||
AM_CONDITIONAL([PYZFS_ENABLED], [test "x$enable_pyzfs" = xyes])
|
||||
AC_SUBST([PYZFS_ENABLED], [$enable_pyzfs])
|
||||
AC_SUBST(pythonsitedir, [$PYTHON_SITE_PKG])
|
||||
|
||||
|
||||
+4
-4
@@ -20,7 +20,7 @@ deb-kmod: deb-local rpm-kmod
|
||||
arch=`$(RPM) -qp $${name}-kmod-$${version}.src.rpm --qf %{arch} | tail -1`; \
|
||||
debarch=`$(DPKG) --print-architecture`; \
|
||||
pkg1=kmod-$${name}*$${version}.$${arch}.rpm; \
|
||||
fakeroot $(ALIEN) --bump=0 --scripts --to-deb --target=$$debarch $$pkg1; \
|
||||
fakeroot $(ALIEN) --bump=0 --scripts --to-deb --target=$$debarch $$pkg1 || exit 1; \
|
||||
$(RM) $$pkg1
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ deb-dkms: deb-local rpm-dkms
|
||||
arch=`$(RPM) -qp $${name}-dkms-$${version}.src.rpm --qf %{arch} | tail -1`; \
|
||||
debarch=`$(DPKG) --print-architecture`; \
|
||||
pkg1=$${name}-dkms-$${version}.$${arch}.rpm; \
|
||||
fakeroot $(ALIEN) --bump=0 --scripts --to-deb --target=$$debarch $$pkg1; \
|
||||
fakeroot $(ALIEN) --bump=0 --scripts --to-deb --target=$$debarch $$pkg1 || exit 1; \
|
||||
$(RM) $$pkg1
|
||||
|
||||
deb-utils: deb-local rpm-utils
|
||||
@@ -45,7 +45,7 @@ deb-utils: deb-local rpm-utils
|
||||
pkg5=libzpool2-$${version}.$${arch}.rpm; \
|
||||
pkg6=libzfs2-devel-$${version}.$${arch}.rpm; \
|
||||
pkg7=$${name}-test-$${version}.$${arch}.rpm; \
|
||||
pkg8=$${name}-dracut-$${version}.$${arch}.rpm; \
|
||||
pkg8=$${name}-dracut-$${version}.noarch.rpm; \
|
||||
pkg9=$${name}-initramfs-$${version}.$${arch}.rpm; \
|
||||
pkg10=`ls python*-pyzfs-$${version}* | tail -1`; \
|
||||
## Arguments need to be passed to dh_shlibdeps. Alien provides no mechanism
|
||||
@@ -63,7 +63,7 @@ deb-utils: deb-local rpm-utils
|
||||
env PATH=$${path_prepend}:$${PATH} \
|
||||
fakeroot $(ALIEN) --bump=0 --scripts --to-deb --target=$$debarch \
|
||||
$$pkg1 $$pkg2 $$pkg3 $$pkg4 $$pkg5 $$pkg6 $$pkg7 \
|
||||
$$pkg8 $$pkg9 $$pkg10; \
|
||||
$$pkg8 $$pkg9 $$pkg10 || exit 1; \
|
||||
$(RM) $${path_prepend}/dh_shlibdeps; \
|
||||
rmdir $${path_prepend}; \
|
||||
$(RM) $$pkg1 $$pkg2 $$pkg3 $$pkg4 $$pkg5 $$pkg6 $$pkg7 \
|
||||
|
||||
@@ -18,7 +18,8 @@ AC_DEFUN([ZFS_AC_KERNEL_FPU], [
|
||||
#include <asm/fpu/api.h>
|
||||
],[
|
||||
],[
|
||||
AC_DEFINE(HAVE_KERNEL_FPU_API_HEADER, 1, [kernel has asm/fpu/api.h])
|
||||
AC_DEFINE(HAVE_KERNEL_FPU_API_HEADER, 1,
|
||||
[kernel has asm/fpu/api.h])
|
||||
AC_MSG_RESULT(asm/fpu/api.h)
|
||||
],[
|
||||
AC_MSG_RESULT(i387.h & xcr.h)
|
||||
@@ -39,8 +40,10 @@ AC_DEFUN([ZFS_AC_KERNEL_FPU], [
|
||||
kernel_fpu_end();
|
||||
], [kernel_fpu_begin], [arch/x86/kernel/fpu/core.c], [
|
||||
AC_MSG_RESULT(kernel_fpu_*)
|
||||
AC_DEFINE(HAVE_KERNEL_FPU, 1, [kernel has kernel_fpu_* functions])
|
||||
AC_DEFINE(KERNEL_EXPORTS_X86_FPU, 1, [kernel exports FPU functions])
|
||||
AC_DEFINE(HAVE_KERNEL_FPU, 1,
|
||||
[kernel has kernel_fpu_* functions])
|
||||
AC_DEFINE(KERNEL_EXPORTS_X86_FPU, 1,
|
||||
[kernel exports FPU functions])
|
||||
],[
|
||||
ZFS_LINUX_TRY_COMPILE_SYMBOL([
|
||||
#include <linux/module.h>
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
dnl #
|
||||
dnl # 2.6.36 API change,
|
||||
dnl # The 'struct fs_struct->lock' was changed from a rwlock_t to
|
||||
dnl # a spinlock_t to improve the fastpath performance.
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_FS_STRUCT_SPINLOCK], [
|
||||
AC_MSG_CHECKING([whether struct fs_struct uses spinlock_t])
|
||||
tmp_flags="$EXTRA_KCFLAGS"
|
||||
EXTRA_KCFLAGS="-Werror"
|
||||
ZFS_LINUX_TRY_COMPILE([
|
||||
#include <linux/sched.h>
|
||||
#include <linux/fs_struct.h>
|
||||
],[
|
||||
static struct fs_struct fs;
|
||||
spin_lock_init(&fs.lock);
|
||||
],[
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_FS_STRUCT_SPINLOCK, 1,
|
||||
[struct fs_struct uses spinlock_t])
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
EXTRA_KCFLAGS="$tmp_flags"
|
||||
])
|
||||
+52
-11
@@ -1,26 +1,51 @@
|
||||
dnl # 4.14-rc3 API change
|
||||
dnl # https://lwn.net/Articles/735887/
|
||||
dnl #
|
||||
dnl # 4.15 API change
|
||||
dnl # https://lkml.org/lkml/2017/11/25/90
|
||||
dnl # Check if timer_list.func get passed a timer_list or an unsigned long
|
||||
dnl # (older kernels). Also sanity check the from_timer() and timer_setup()
|
||||
dnl # macros are available as well, since they will be used in the same newer
|
||||
dnl # kernels that support the new timer_list.func signature.
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_TIMER_FUNCTION_TIMER_LIST], [
|
||||
AC_MSG_CHECKING([whether timer_list.function gets a timer_list])
|
||||
dnl # Also check for the existance of flags in struct timer_list, they were
|
||||
dnl # added in 4.1-rc8 via 0eeda71bc30d.
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_TIMER_SETUP], [
|
||||
AC_MSG_CHECKING([whether timer_setup() is available])
|
||||
tmp_flags="$EXTRA_KCFLAGS"
|
||||
EXTRA_KCFLAGS="-Werror"
|
||||
|
||||
ZFS_LINUX_TRY_COMPILE([
|
||||
#include <linux/timer.h>
|
||||
|
||||
struct my_task_timer {
|
||||
struct timer_list timer;
|
||||
int data;
|
||||
};
|
||||
|
||||
void task_expire(struct timer_list *tl)
|
||||
{
|
||||
struct my_task_timer *task_timer = from_timer(task_timer, tl, timer);
|
||||
task_timer->data = 42;
|
||||
}
|
||||
],[
|
||||
struct my_task_timer task_timer;
|
||||
timer_setup(&task_timer.timer, task_expire, 0);
|
||||
],[
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_KERNEL_TIMER_SETUP, 1,
|
||||
[timer_setup() is available])
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
|
||||
AC_MSG_CHECKING([whether timer function expects timer_list])
|
||||
|
||||
ZFS_LINUX_TRY_COMPILE([
|
||||
#include <linux/timer.h>
|
||||
void task_expire(struct timer_list *tl) {}
|
||||
],[
|
||||
#ifndef from_timer
|
||||
#error "No from_timer() macro"
|
||||
#endif
|
||||
|
||||
struct timer_list timer;
|
||||
timer.function = task_expire;
|
||||
timer_setup(&timer, NULL, 0);
|
||||
struct timer_list tl;
|
||||
tl.function = task_expire;
|
||||
],[
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_KERNEL_TIMER_FUNCTION_TIMER_LIST, 1,
|
||||
@@ -28,5 +53,21 @@ AC_DEFUN([ZFS_AC_KERNEL_TIMER_FUNCTION_TIMER_LIST], [
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
|
||||
AC_MSG_CHECKING([whether struct timer_list has flags])
|
||||
|
||||
ZFS_LINUX_TRY_COMPILE([
|
||||
#include <linux/timer.h>
|
||||
],[
|
||||
struct timer_list tl;
|
||||
tl.flags = 2;
|
||||
],[
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_KERNEL_TIMER_LIST_FLAGS, 1,
|
||||
[struct timer_list has a flags member])
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
|
||||
EXTRA_KCFLAGS="$tmp_flags"
|
||||
])
|
||||
|
||||
+1
-2
@@ -12,7 +12,6 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [
|
||||
ZFS_AC_KERNEL_CTL_NAME
|
||||
ZFS_AC_KERNEL_PDE_DATA
|
||||
ZFS_AC_KERNEL_2ARGS_VFS_FSYNC
|
||||
ZFS_AC_KERNEL_FS_STRUCT_SPINLOCK
|
||||
ZFS_AC_KERNEL_KUIDGID_T
|
||||
ZFS_AC_KERNEL_FALLOCATE
|
||||
ZFS_AC_KERNEL_2ARGS_ZLIB_DEFLATE_WORKSPACESIZE
|
||||
@@ -36,7 +35,7 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [
|
||||
ZFS_AC_KERNEL_GROUP_INFO_GID
|
||||
ZFS_AC_KERNEL_WRITE
|
||||
ZFS_AC_KERNEL_READ
|
||||
ZFS_AC_KERNEL_TIMER_FUNCTION_TIMER_LIST
|
||||
ZFS_AC_KERNEL_TIMER_SETUP
|
||||
ZFS_AC_KERNEL_DECLARE_EVENT_CLASS
|
||||
ZFS_AC_KERNEL_CURRENT_BIO_TAIL
|
||||
ZFS_AC_KERNEL_SUPER_USER_NS
|
||||
|
||||
@@ -120,8 +120,10 @@ AC_CONFIG_FILES([
|
||||
cmd/dbufstat/Makefile
|
||||
cmd/arc_summary/Makefile
|
||||
cmd/zed/Makefile
|
||||
cmd/zed/zed.d/Makefile
|
||||
cmd/raidz_test/Makefile
|
||||
cmd/zgenhostid/Makefile
|
||||
cmd/zvol_wait/Makefile
|
||||
contrib/Makefile
|
||||
contrib/bash_completion.d/Makefile
|
||||
contrib/dracut/Makefile
|
||||
@@ -271,6 +273,7 @@ AC_CONFIG_FILES([
|
||||
tests/zfs-tests/tests/functional/cli_user/zfs_list/Makefile
|
||||
tests/zfs-tests/tests/functional/cli_user/zpool_iostat/Makefile
|
||||
tests/zfs-tests/tests/functional/cli_user/zpool_list/Makefile
|
||||
tests/zfs-tests/tests/functional/cli_user/zpool_status/Makefile
|
||||
tests/zfs-tests/tests/functional/compression/Makefile
|
||||
tests/zfs-tests/tests/functional/cp_files/Makefile
|
||||
tests/zfs-tests/tests/functional/ctime/Makefile
|
||||
@@ -326,6 +329,7 @@ AC_CONFIG_FILES([
|
||||
tests/zfs-tests/tests/functional/snapshot/Makefile
|
||||
tests/zfs-tests/tests/functional/snapused/Makefile
|
||||
tests/zfs-tests/tests/functional/sparse/Makefile
|
||||
tests/zfs-tests/tests/functional/suid/Makefile
|
||||
tests/zfs-tests/tests/functional/alloc_class/Makefile
|
||||
tests/zfs-tests/tests/functional/threadsappend/Makefile
|
||||
tests/zfs-tests/tests/functional/tmpfile/Makefile
|
||||
|
||||
@@ -144,7 +144,7 @@ ask_for_password() {
|
||||
|
||||
{ flock -s 9;
|
||||
# Prompt for password with plymouth, if installed and running.
|
||||
if whereis plymouth >/dev/null 2>&1 && plymouth --ping 2>/dev/null; then
|
||||
if type plymouth >/dev/null 2>&1 && plymouth --ping 2>/dev/null; then
|
||||
plymouth ask-for-password \
|
||||
--prompt "$ply_prompt" --number-of-tries="$ply_tries" \
|
||||
--command="$ply_cmd"
|
||||
|
||||
@@ -11,13 +11,18 @@ EXTRA_DIST = \
|
||||
$(top_srcdir)/contrib/initramfs/README.initramfs.markdown
|
||||
|
||||
install-initrdSCRIPTS: $(EXTRA_DIST)
|
||||
for d in conf.d conf-hooks.d hooks scripts scripts/local-top; do \
|
||||
$(MKDIR_P) $(DESTDIR)$(initrddir)/$$d; \
|
||||
cp $(top_srcdir)/contrib/initramfs/$$d/zfs \
|
||||
$(DESTDIR)$(initrddir)/$$d/; \
|
||||
for d in conf.d conf-hooks.d scripts/local-top; do \
|
||||
$(MKDIR_P) $(DESTDIR)$(initrddir)/$$d; \
|
||||
cp $(top_srcdir)/contrib/initramfs/$$d/zfs \
|
||||
$(DESTDIR)$(initrddir)/$$d/; \
|
||||
done
|
||||
if [ -f etc/init.d/zfs ]; then \
|
||||
$(MKDIR_P) $(DESTDIR)$(DEFAULT_INITCONF_DIR); \
|
||||
cp $(top_srcdir)/etc/init.d/zfs \
|
||||
$(DESTDIR)$(DEFAULT_INITCONF_DIR)/; \
|
||||
for d in hooks scripts; do \
|
||||
$(MKDIR_P) $(DESTDIR)$(initrddir)/$$d; \
|
||||
cp $(top_builddir)/contrib/initramfs/$$d/zfs \
|
||||
$(DESTDIR)$(initrddir)/$$d/; \
|
||||
done
|
||||
if [ -f $(top_builddir)/etc/init.d/zfs ]; then \
|
||||
$(MKDIR_P) $(DESTDIR)$(DEFAULT_INITCONF_DIR); \
|
||||
cp $(top_builddir)/etc/init.d/zfs \
|
||||
$(DESTDIR)$(DEFAULT_INITCONF_DIR)/; \
|
||||
fi
|
||||
|
||||
@@ -411,29 +411,29 @@ decrypt_fs()
|
||||
|
||||
# Determine dataset that holds key for root dataset
|
||||
ENCRYPTIONROOT=$(${ZFS} get -H -o value encryptionroot "${fs}")
|
||||
DECRYPT_CMD="${ZFS} load-key '${ENCRYPTIONROOT}'"
|
||||
|
||||
# If root dataset is encrypted...
|
||||
if ! [ "${ENCRYPTIONROOT}" = "-" ]; then
|
||||
|
||||
TRY_COUNT=3
|
||||
# Prompt with plymouth, if active
|
||||
if [ -e /bin/plymouth ] && /bin/plymouth --ping 2>/dev/null; then
|
||||
plymouth ask-for-password --prompt "Encrypted ZFS password for ${ENCRYPTIONROOT}" \
|
||||
--number-of-tries="3" \
|
||||
--command="${DECRYPT_CMD}"
|
||||
while [ $TRY_COUNT -gt 0 ]; do
|
||||
plymouth ask-for-password --prompt "Encrypted ZFS password for ${ENCRYPTIONROOT}" | \
|
||||
$ZFS load-key "${ENCRYPTIONROOT}" && break
|
||||
TRY_COUNT=$((TRY_COUNT - 1))
|
||||
done
|
||||
|
||||
# Prompt with systemd, if active
|
||||
elif [ -e /run/systemd/system ]; then
|
||||
TRY_COUNT=3
|
||||
while [ $TRY_COUNT -gt 0 ]; do
|
||||
systemd-ask-password "Encrypted ZFS password for ${ENCRYPTIONROOT}" --no-tty | \
|
||||
${DECRYPT_CMD} && break
|
||||
$ZFS load-key "${ENCRYPTIONROOT}" && break
|
||||
TRY_COUNT=$((TRY_COUNT - 1))
|
||||
done
|
||||
|
||||
# Prompt with ZFS tty, otherwise
|
||||
else
|
||||
eval "${DECRYPT_CMD}"
|
||||
$ZFS load-key "${ENCRYPTIONROOT}"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -24,7 +24,7 @@ all-local:
|
||||
# files are later created by manually loading the Python modules.
|
||||
#
|
||||
install-exec-local:
|
||||
$(PYTHON) $(srcdir)/setup.py install \
|
||||
$(PYTHON) $(builddir)/setup.py install \
|
||||
--prefix $(prefix) \
|
||||
--root $(DESTDIR)/ \
|
||||
--install-lib $(pythonsitedir) \
|
||||
|
||||
@@ -294,13 +294,6 @@ checksystem()
|
||||
# Just make sure that /dev/zfs is created.
|
||||
udev_trigger
|
||||
|
||||
if ! [ "$(uname -m)" = "x86_64" ]; then
|
||||
echo "Warning: You're not running 64bit. Currently native zfs in";
|
||||
echo " Linux is only supported and tested on 64bit.";
|
||||
# should we break here? People doing this should know what they
|
||||
# do, thus i'm not breaking here.
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +71,8 @@ process_line() {
|
||||
p_readonly="${8}"
|
||||
p_setuid="${9}"
|
||||
p_nbmand="${10}"
|
||||
p_encroot="${11}"
|
||||
p_keyloc="${12}"
|
||||
|
||||
# Check for canmount=off .
|
||||
if [ "${p_canmount}" = "off" ] ; then
|
||||
@@ -168,6 +170,54 @@ process_line() {
|
||||
"${dataset}" >/dev/kmsg
|
||||
fi
|
||||
|
||||
# Minimal pre-requisites to mount a ZFS dataset
|
||||
wants="zfs-import.target"
|
||||
if [ -n "${p_encroot}" ] &&
|
||||
[ "${p_encroot}" != "-" ] ; then
|
||||
keyloadunit="zfs-load-key-$(systemd-escape "${p_encroot}").service"
|
||||
if [ "${p_encroot}" = "${dataset}" ] ; then
|
||||
pathdep=""
|
||||
if [ "${p_keyloc%%://*}" = "file" ] ; then
|
||||
pathdep="RequiresMountsFor='${p_keyloc#file://}'"
|
||||
keyloadcmd="@sbindir@/zfs load-key '${dataset}'"
|
||||
elif [ "${p_keyloc}" = "prompt" ] ; then
|
||||
keyloadcmd="sh -c 'set -eu;"\
|
||||
"count=0;"\
|
||||
"while [ \$\$count -lt 3 ];do"\
|
||||
" systemd-ask-password --id=\"zfs:${dataset}\""\
|
||||
" \"Enter passphrase for ${dataset}:\"|"\
|
||||
" @sbindir@/zfs load-key \"${dataset}\" && exit 0;"\
|
||||
" count=\$\$((count + 1));"\
|
||||
"done;"\
|
||||
"exit 1'"
|
||||
else
|
||||
printf 'zfs-mount-generator: (%s) invalid keylocation\n' \
|
||||
"${dataset}" >/dev/kmsg
|
||||
fi
|
||||
cat > "${dest_norm}/${keyloadunit}" << EOF
|
||||
# Automatically generated by zfs-mount-generator
|
||||
|
||||
[Unit]
|
||||
Description=Load ZFS key for ${dataset}
|
||||
SourcePath=${cachefile}
|
||||
Documentation=man:zfs-mount-generator(8)
|
||||
DefaultDependencies=no
|
||||
Wants=${wants}
|
||||
After=${wants}
|
||||
${pathdep}
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStart=${keyloadcmd}
|
||||
ExecStop=@sbindir@/zfs unload-key '${dataset}'
|
||||
EOF
|
||||
fi
|
||||
# Update the dependencies for the mount file to require the
|
||||
# key-loading unit.
|
||||
wants="${wants} ${keyloadunit}"
|
||||
fi
|
||||
|
||||
# If the mountpoint has already been created, give it precedence.
|
||||
if [ -e "${dest_norm}/${mountfile}" ] ; then
|
||||
printf 'zfs-mount-generator: %s already exists\n' "${mountfile}" \
|
||||
@@ -183,8 +233,8 @@ process_line() {
|
||||
SourcePath=${cachefile}
|
||||
Documentation=man:zfs-mount-generator(8)
|
||||
Before=local-fs.target zfs-mount.service
|
||||
After=zfs-import.target
|
||||
Wants=zfs-import.target
|
||||
After=${wants}
|
||||
Wants=${wants}
|
||||
|
||||
[Mount]
|
||||
Where=${p_mountpoint}
|
||||
|
||||
@@ -5,4 +5,5 @@ enable zfs-import.target
|
||||
enable zfs-mount.service
|
||||
enable zfs-share.service
|
||||
enable zfs-zed.service
|
||||
enable zfs-volume-wait.service
|
||||
enable zfs.target
|
||||
|
||||
@@ -7,7 +7,9 @@ systemdunit_DATA = \
|
||||
zfs-import-scan.service \
|
||||
zfs-mount.service \
|
||||
zfs-share.service \
|
||||
zfs-volume-wait.service \
|
||||
zfs-import.target \
|
||||
zfs-volumes.target \
|
||||
zfs.target
|
||||
|
||||
EXTRA_DIST = \
|
||||
@@ -17,6 +19,8 @@ EXTRA_DIST = \
|
||||
$(top_srcdir)/etc/systemd/system/zfs-mount.service.in \
|
||||
$(top_srcdir)/etc/systemd/system/zfs-share.service.in \
|
||||
$(top_srcdir)/etc/systemd/system/zfs-import.target.in \
|
||||
$(top_srcdir)/etc/systemd/system/zfs-volume-wait.service.in \
|
||||
$(top_srcdir)/etc/systemd/system/zfs-volumes.target.in \
|
||||
$(top_srcdir)/etc/systemd/system/zfs.target.in \
|
||||
$(top_srcdir)/etc/systemd/system/50-zfs.preset.in
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ After=nfs-server.service nfs-kernel-server.service
|
||||
After=smb.service
|
||||
Before=rpc-statd-notify.service
|
||||
Wants=zfs-mount.service
|
||||
After=zfs-mount.service
|
||||
PartOf=nfs-server.service nfs-kernel-server.service
|
||||
PartOf=smb.service
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
[Unit]
|
||||
Description=Wait for ZFS Volume (zvol) links in /dev
|
||||
DefaultDependencies=no
|
||||
After=systemd-udev-settle.service
|
||||
After=zfs-import.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStart=@bindir@/zvol_wait
|
||||
|
||||
[Install]
|
||||
WantedBy=zfs-volumes.target
|
||||
@@ -0,0 +1,7 @@
|
||||
[Unit]
|
||||
Description=ZFS volumes are ready
|
||||
After=zfs-volume-wait.service
|
||||
Requires=zfs-volume-wait.service
|
||||
|
||||
[Install]
|
||||
WantedBy=zfs.target
|
||||
@@ -147,6 +147,7 @@ typedef enum zfs_error {
|
||||
EZFS_NO_TRIM, /* no active trim */
|
||||
EZFS_TRIM_NOTSUP, /* device does not support trim */
|
||||
EZFS_NO_RESILVER_DEFER, /* pool doesn't support resilver_defer */
|
||||
EZFS_EXPORT_IN_PROGRESS, /* currently exporting the pool */
|
||||
EZFS_UNKNOWN
|
||||
} zfs_error_t;
|
||||
|
||||
|
||||
@@ -26,8 +26,10 @@
|
||||
* USER API:
|
||||
*
|
||||
* Kernel fpu methods:
|
||||
* kfpu_begin()
|
||||
* kfpu_end()
|
||||
* kfpu_allowed()
|
||||
* kfpu_initialize()
|
||||
* kfpu_begin()
|
||||
* kfpu_end()
|
||||
*/
|
||||
|
||||
#ifndef _SIMD_AARCH64_H
|
||||
|
||||
+25
-23
@@ -26,8 +26,10 @@
|
||||
* USER API:
|
||||
*
|
||||
* Kernel fpu methods:
|
||||
* kfpu_begin()
|
||||
* kfpu_end()
|
||||
* kfpu_allowed()
|
||||
* kfpu_initialize()
|
||||
* kfpu_begin()
|
||||
* kfpu_end()
|
||||
*
|
||||
* SIMD support:
|
||||
*
|
||||
@@ -37,31 +39,31 @@
|
||||
* all relevant feature test functions should be called.
|
||||
*
|
||||
* Supported features:
|
||||
* zfs_sse_available()
|
||||
* zfs_sse2_available()
|
||||
* zfs_sse3_available()
|
||||
* zfs_ssse3_available()
|
||||
* zfs_sse4_1_available()
|
||||
* zfs_sse4_2_available()
|
||||
* zfs_sse_available()
|
||||
* zfs_sse2_available()
|
||||
* zfs_sse3_available()
|
||||
* zfs_ssse3_available()
|
||||
* zfs_sse4_1_available()
|
||||
* zfs_sse4_2_available()
|
||||
*
|
||||
* zfs_avx_available()
|
||||
* zfs_avx2_available()
|
||||
* zfs_avx_available()
|
||||
* zfs_avx2_available()
|
||||
*
|
||||
* zfs_bmi1_available()
|
||||
* zfs_bmi2_available()
|
||||
* zfs_bmi1_available()
|
||||
* zfs_bmi2_available()
|
||||
*
|
||||
* zfs_avx512f_available()
|
||||
* zfs_avx512cd_available()
|
||||
* zfs_avx512er_available()
|
||||
* zfs_avx512pf_available()
|
||||
* zfs_avx512bw_available()
|
||||
* zfs_avx512dq_available()
|
||||
* zfs_avx512vl_available()
|
||||
* zfs_avx512ifma_available()
|
||||
* zfs_avx512vbmi_available()
|
||||
* zfs_avx512f_available()
|
||||
* zfs_avx512cd_available()
|
||||
* zfs_avx512er_available()
|
||||
* zfs_avx512pf_available()
|
||||
* zfs_avx512bw_available()
|
||||
* zfs_avx512dq_available()
|
||||
* zfs_avx512vl_available()
|
||||
* zfs_avx512ifma_available()
|
||||
* zfs_avx512vbmi_available()
|
||||
*
|
||||
* NOTE(AVX-512VL): If using AVX-512 instructions with 128Bit registers
|
||||
* also add zfs_avx512vl_available() to feature check.
|
||||
* also add zfs_avx512vl_available() to feature check.
|
||||
*/
|
||||
|
||||
#ifndef _SIMD_X86_H
|
||||
@@ -190,7 +192,7 @@ typedef struct cpuid_feature_desc {
|
||||
* Descriptions of supported instruction sets
|
||||
*/
|
||||
static const cpuid_feature_desc_t cpuid_features[] = {
|
||||
[SSE] = {1U, 0U, 1U << 25, EDX },
|
||||
[SSE] = {1U, 0U, 1U << 25, EDX },
|
||||
[SSE2] = {1U, 0U, 1U << 26, EDX },
|
||||
[SSE3] = {1U, 0U, 1U << 0, ECX },
|
||||
[SSSE3] = {1U, 0U, 1U << 9, ECX },
|
||||
|
||||
@@ -127,6 +127,8 @@ spl_mutex_lockdep_on_maybe(kmutex_t *mp) \
|
||||
})
|
||||
/* END CSTYLED */
|
||||
|
||||
#define NESTED_SINGLE 1
|
||||
|
||||
#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
||||
#define mutex_enter_nested(mp, subclass) \
|
||||
{ \
|
||||
@@ -179,7 +181,4 @@ spl_mutex_lockdep_on_maybe(kmutex_t *mp) \
|
||||
/* NOTE: do not dereference mp after this point */ \
|
||||
}
|
||||
|
||||
int spl_mutex_init(void);
|
||||
void spl_mutex_fini(void);
|
||||
|
||||
#endif /* _SPL_MUTEX_H */
|
||||
|
||||
+12
-120
@@ -29,43 +29,6 @@
|
||||
#include <linux/rwsem.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
/* Linux kernel compatibility */
|
||||
#if defined(CONFIG_PREEMPT_RT_FULL)
|
||||
#define SPL_RWSEM_SINGLE_READER_VALUE (1)
|
||||
#define SPL_RWSEM_SINGLE_WRITER_VALUE (0)
|
||||
#elif defined(CONFIG_RWSEM_GENERIC_SPINLOCK)
|
||||
#define SPL_RWSEM_SINGLE_READER_VALUE (1)
|
||||
#define SPL_RWSEM_SINGLE_WRITER_VALUE (-1)
|
||||
#elif defined(RWSEM_ACTIVE_MASK)
|
||||
#define SPL_RWSEM_SINGLE_READER_VALUE (RWSEM_ACTIVE_READ_BIAS)
|
||||
#define SPL_RWSEM_SINGLE_WRITER_VALUE (RWSEM_ACTIVE_WRITE_BIAS)
|
||||
#endif
|
||||
|
||||
/* Linux 3.16 changed activity to count for rwsem-spinlock */
|
||||
#if defined(CONFIG_PREEMPT_RT_FULL)
|
||||
#define RWSEM_COUNT(sem) sem->read_depth
|
||||
#elif defined(HAVE_RWSEM_ACTIVITY)
|
||||
#define RWSEM_COUNT(sem) sem->activity
|
||||
/* Linux 4.8 changed count to an atomic_long_t for !rwsem-spinlock */
|
||||
#elif defined(HAVE_RWSEM_ATOMIC_LONG_COUNT)
|
||||
#define RWSEM_COUNT(sem) atomic_long_read(&(sem)->count)
|
||||
#else
|
||||
#define RWSEM_COUNT(sem) sem->count
|
||||
#endif
|
||||
|
||||
#if defined(RWSEM_SPINLOCK_IS_RAW)
|
||||
#define spl_rwsem_lock_irqsave(lk, fl) raw_spin_lock_irqsave(lk, fl)
|
||||
#define spl_rwsem_unlock_irqrestore(lk, fl) \
|
||||
raw_spin_unlock_irqrestore(lk, fl)
|
||||
#define spl_rwsem_trylock_irqsave(lk, fl) raw_spin_trylock_irqsave(lk, fl)
|
||||
#else
|
||||
#define spl_rwsem_lock_irqsave(lk, fl) spin_lock_irqsave(lk, fl)
|
||||
#define spl_rwsem_unlock_irqrestore(lk, fl) spin_unlock_irqrestore(lk, fl)
|
||||
#define spl_rwsem_trylock_irqsave(lk, fl) spin_trylock_irqsave(lk, fl)
|
||||
#endif /* RWSEM_SPINLOCK_IS_RAW */
|
||||
|
||||
#define spl_rwsem_is_locked(rwsem) rwsem_is_locked(rwsem)
|
||||
|
||||
typedef enum {
|
||||
RW_DRIVER = 2,
|
||||
RW_DEFAULT = 4,
|
||||
@@ -78,15 +41,9 @@ typedef enum {
|
||||
RW_READER = 2
|
||||
} krw_t;
|
||||
|
||||
/*
|
||||
* If CONFIG_RWSEM_SPIN_ON_OWNER is defined, rw_semaphore will have an owner
|
||||
* field, so we don't need our own.
|
||||
*/
|
||||
typedef struct {
|
||||
struct rw_semaphore rw_rwlock;
|
||||
#ifndef CONFIG_RWSEM_SPIN_ON_OWNER
|
||||
kthread_t *rw_owner;
|
||||
#endif
|
||||
#ifdef CONFIG_LOCKDEP
|
||||
krw_type_t rw_type;
|
||||
#endif /* CONFIG_LOCKDEP */
|
||||
@@ -97,31 +54,19 @@ typedef struct {
|
||||
static inline void
|
||||
spl_rw_set_owner(krwlock_t *rwp)
|
||||
{
|
||||
/*
|
||||
* If CONFIG_RWSEM_SPIN_ON_OWNER is defined, down_write, up_write,
|
||||
* downgrade_write and __init_rwsem will set/clear owner for us.
|
||||
*/
|
||||
#ifndef CONFIG_RWSEM_SPIN_ON_OWNER
|
||||
rwp->rw_owner = current;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
spl_rw_clear_owner(krwlock_t *rwp)
|
||||
{
|
||||
#ifndef CONFIG_RWSEM_SPIN_ON_OWNER
|
||||
rwp->rw_owner = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline kthread_t *
|
||||
rw_owner(krwlock_t *rwp)
|
||||
{
|
||||
#ifdef CONFIG_RWSEM_SPIN_ON_OWNER
|
||||
return (SEM(rwp)->owner);
|
||||
#else
|
||||
return (rwp->rw_owner);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LOCKDEP
|
||||
@@ -148,6 +93,11 @@ spl_rw_lockdep_on_maybe(krwlock_t *rwp) \
|
||||
#define spl_rw_lockdep_on_maybe(rwp)
|
||||
#endif /* CONFIG_LOCKDEP */
|
||||
|
||||
static inline int
|
||||
RW_LOCK_HELD(krwlock_t *rwp)
|
||||
{
|
||||
return (rwsem_is_locked(SEM(rwp)));
|
||||
}
|
||||
|
||||
static inline int
|
||||
RW_WRITE_HELD(krwlock_t *rwp)
|
||||
@@ -155,55 +105,10 @@ RW_WRITE_HELD(krwlock_t *rwp)
|
||||
return (rw_owner(rwp) == current);
|
||||
}
|
||||
|
||||
static inline int
|
||||
RW_LOCK_HELD(krwlock_t *rwp)
|
||||
{
|
||||
return (spl_rwsem_is_locked(SEM(rwp)));
|
||||
}
|
||||
|
||||
static inline int
|
||||
RW_READ_HELD(krwlock_t *rwp)
|
||||
{
|
||||
if (!RW_LOCK_HELD(rwp))
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* rw_semaphore cheat sheet:
|
||||
*
|
||||
* < 3.16:
|
||||
* There's no rw_semaphore.owner, so use rwp.owner instead.
|
||||
* If rwp.owner == NULL then it's a reader
|
||||
*
|
||||
* 3.16 - 4.7:
|
||||
* rw_semaphore.owner added (https://lwn.net/Articles/596656/)
|
||||
* and CONFIG_RWSEM_SPIN_ON_OWNER introduced.
|
||||
* If rw_semaphore.owner == NULL then it's a reader
|
||||
*
|
||||
* 4.8 - 4.16.16:
|
||||
* RWSEM_READER_OWNED added as an internal #define.
|
||||
* (https://lore.kernel.org/patchwork/patch/678590/)
|
||||
* If rw_semaphore.owner == 1 then it's a reader
|
||||
*
|
||||
* 4.16.17 - 4.19:
|
||||
* RWSEM_OWNER_UNKNOWN introduced as ((struct task_struct *)-1L)
|
||||
* (https://do-db2.lkml.org/lkml/2018/5/15/985)
|
||||
* If rw_semaphore.owner == 1 then it's a reader.
|
||||
*
|
||||
* 4.20+:
|
||||
* RWSEM_OWNER_UNKNOWN changed to ((struct task_struct *)-2L)
|
||||
* (https://lkml.org/lkml/2018/9/6/986)
|
||||
* If rw_semaphore.owner & 1 then it's a reader, and also the reader's
|
||||
* task_struct may be embedded in rw_semaphore->owner.
|
||||
*/
|
||||
#if defined(CONFIG_RWSEM_SPIN_ON_OWNER) && defined(RWSEM_OWNER_UNKNOWN)
|
||||
if (RWSEM_OWNER_UNKNOWN == (struct task_struct *)-2L) {
|
||||
/* 4.20+ kernels with CONFIG_RWSEM_SPIN_ON_OWNER */
|
||||
return ((unsigned long) SEM(rwp)->owner & 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* < 4.20 kernel or !CONFIG_RWSEM_SPIN_ON_OWNER */
|
||||
return (rw_owner(rwp) == NULL || (unsigned long) rw_owner(rwp) == 1);
|
||||
return (RW_LOCK_HELD(rwp) && rw_owner(rwp) == NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -228,6 +133,12 @@ RW_READ_HELD(krwlock_t *rwp)
|
||||
*/
|
||||
#define rw_destroy(rwp) ((void) 0)
|
||||
|
||||
/*
|
||||
* Upgrading a rwsem from a reader to a writer is not supported by the
|
||||
* Linux kernel. The lock must be dropped and reacquired as a writer.
|
||||
*/
|
||||
#define rw_tryupgrade(rwp) RW_WRITE_HELD(rwp)
|
||||
|
||||
#define rw_tryenter(rwp, rw) \
|
||||
({ \
|
||||
int _rc_ = 0; \
|
||||
@@ -285,25 +196,6 @@ RW_READ_HELD(krwlock_t *rwp)
|
||||
downgrade_write(SEM(rwp)); \
|
||||
spl_rw_lockdep_on_maybe(rwp); \
|
||||
})
|
||||
|
||||
#define rw_tryupgrade(rwp) \
|
||||
({ \
|
||||
int _rc_ = 0; \
|
||||
\
|
||||
if (RW_WRITE_HELD(rwp)) { \
|
||||
_rc_ = 1; \
|
||||
} else { \
|
||||
spl_rw_lockdep_off_maybe(rwp); \
|
||||
if ((_rc_ = rwsem_tryupgrade(SEM(rwp)))) \
|
||||
spl_rw_set_owner(rwp); \
|
||||
spl_rw_lockdep_on_maybe(rwp); \
|
||||
} \
|
||||
_rc_; \
|
||||
})
|
||||
/* END CSTYLED */
|
||||
|
||||
int spl_rw_init(void);
|
||||
void spl_rw_fini(void);
|
||||
int rwsem_tryupgrade(struct rw_semaphore *rwsem);
|
||||
|
||||
#endif /* _SPL_RWLOCK_H */
|
||||
|
||||
@@ -72,4 +72,29 @@ usleep_range(unsigned long min, unsigned long max)
|
||||
#define USEC_TO_TICK(us) usecs_to_jiffies(us)
|
||||
#define NSEC_TO_TICK(ns) usecs_to_jiffies(ns / NSEC_PER_USEC)
|
||||
|
||||
#ifndef from_timer
|
||||
#define from_timer(var, timer, timer_field) \
|
||||
container_of(timer, typeof(*var), timer_field)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_KERNEL_TIMER_FUNCTION_TIMER_LIST
|
||||
typedef struct timer_list *spl_timer_list_t;
|
||||
#else
|
||||
typedef unsigned long spl_timer_list_t;
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_KERNEL_TIMER_SETUP
|
||||
|
||||
static inline void
|
||||
timer_setup(struct timer_list *timer, void (*func)(spl_timer_list_t), u32 fl)
|
||||
{
|
||||
#ifdef HAVE_KERNEL_TIMER_LIST_FLAGS
|
||||
(timer)->flags = fl;
|
||||
#endif
|
||||
init_timer(timer);
|
||||
setup_timer(timer, func, (spl_timer_list_t)(timer));
|
||||
}
|
||||
|
||||
#endif /* HAVE_KERNEL_TIMER_SETUP */
|
||||
|
||||
#endif /* _SPL_TIMER_H */
|
||||
|
||||
@@ -182,7 +182,6 @@ extern int vn_space(vnode_t *vp, int cmd, struct flock *bfp, int flag,
|
||||
extern file_t *vn_getf(int fd);
|
||||
extern void vn_releasef(int fd);
|
||||
extern void vn_areleasef(int fd, uf_info_t *fip);
|
||||
extern int vn_set_pwd(const char *filename);
|
||||
|
||||
int spl_vn_init(void);
|
||||
void spl_vn_fini(void);
|
||||
|
||||
+2
-5
@@ -46,6 +46,7 @@ extern "C" {
|
||||
*/
|
||||
#define DNODE_MUST_BE_ALLOCATED 1
|
||||
#define DNODE_MUST_BE_FREE 2
|
||||
#define DNODE_DRY_RUN 4
|
||||
|
||||
/*
|
||||
* dnode_next_offset() flags.
|
||||
@@ -415,6 +416,7 @@ int dnode_hold_impl(struct objset *dd, uint64_t object, int flag, int dn_slots,
|
||||
boolean_t dnode_add_ref(dnode_t *dn, void *ref);
|
||||
void dnode_rele(dnode_t *dn, void *ref);
|
||||
void dnode_rele_and_unlock(dnode_t *dn, void *tag, boolean_t evicting);
|
||||
int dnode_try_claim(objset_t *os, uint64_t object, int slots);
|
||||
void dnode_setdirty(dnode_t *dn, dmu_tx_t *tx);
|
||||
void dnode_sync(dnode_t *dn, dmu_tx_t *tx);
|
||||
void dnode_allocate(dnode_t *dn, dmu_object_type_t ot, int blocksize, int ibs,
|
||||
@@ -532,11 +534,6 @@ typedef struct dnode_stats {
|
||||
* a range of dnode slots which would overflow the dnode_phys_t.
|
||||
*/
|
||||
kstat_named_t dnode_hold_free_overflow;
|
||||
/*
|
||||
* Number of times a dnode_hold(...) was attempted on a dnode
|
||||
* which had already been unlinked in an earlier txg.
|
||||
*/
|
||||
kstat_named_t dnode_hold_free_txg;
|
||||
/*
|
||||
* Number of times dnode_free_interior_slots() needed to retry
|
||||
* acquiring a slot zrl lock due to contention.
|
||||
|
||||
@@ -37,9 +37,11 @@ typedef struct zfs_bookmark_phys {
|
||||
uint64_t zbm_creation_txg; /* birth transaction group */
|
||||
uint64_t zbm_creation_time; /* bookmark creation time */
|
||||
|
||||
/* the following fields are reserved for redacted send / recv */
|
||||
/* fields used for redacted send / recv */
|
||||
uint64_t zbm_redaction_obj; /* redaction list object */
|
||||
uint64_t zbm_flags; /* ZBM_FLAG_* */
|
||||
|
||||
/* fields used for bookmark written size */
|
||||
uint64_t zbm_referenced_bytes_refd;
|
||||
uint64_t zbm_compressed_bytes_refd;
|
||||
uint64_t zbm_uncompressed_bytes_refd;
|
||||
|
||||
@@ -209,7 +209,6 @@ void dsl_dataset_create_crypt_sync(uint64_t dsobj, dsl_dir_t *dd,
|
||||
struct dsl_dataset *origin, dsl_crypto_params_t *dcp, dmu_tx_t *tx);
|
||||
uint64_t dsl_crypto_key_create_sync(uint64_t crypt, dsl_wrapping_key_t *wkey,
|
||||
dmu_tx_t *tx);
|
||||
int dmu_objset_clone_crypt_check(dsl_dir_t *parentdd, dsl_dir_t *origindd);
|
||||
uint64_t dsl_crypto_key_clone_sync(dsl_dir_t *origindd, dmu_tx_t *tx);
|
||||
void dsl_crypto_key_destroy_sync(uint64_t dckobj, dmu_tx_t *tx);
|
||||
|
||||
|
||||
@@ -1318,6 +1318,7 @@ typedef enum {
|
||||
ZFS_ERR_FROM_IVSET_GUID_MISSING,
|
||||
ZFS_ERR_FROM_IVSET_GUID_MISMATCH,
|
||||
ZFS_ERR_SPILL_BLOCK_FLAG_MISSING,
|
||||
ZFS_ERR_EXPORT_IN_PROGRESS,
|
||||
} zfs_errno_t;
|
||||
|
||||
/*
|
||||
|
||||
@@ -50,6 +50,7 @@ int metaslab_init(metaslab_group_t *, uint64_t, uint64_t, uint64_t,
|
||||
void metaslab_fini(metaslab_t *);
|
||||
|
||||
int metaslab_load(metaslab_t *);
|
||||
void metaslab_potentially_unload(metaslab_t *, uint64_t);
|
||||
void metaslab_unload(metaslab_t *);
|
||||
|
||||
uint64_t metaslab_allocated_space(metaslab_t *);
|
||||
|
||||
@@ -89,6 +89,8 @@ void multilist_sublist_insert_head(multilist_sublist_t *, void *);
|
||||
void multilist_sublist_insert_tail(multilist_sublist_t *, void *);
|
||||
void multilist_sublist_move_forward(multilist_sublist_t *mls, void *obj);
|
||||
void multilist_sublist_remove(multilist_sublist_t *, void *);
|
||||
int multilist_sublist_is_empty(multilist_sublist_t *);
|
||||
int multilist_sublist_is_empty_idx(multilist_t *, unsigned int);
|
||||
|
||||
void *multilist_sublist_head(multilist_sublist_t *);
|
||||
void *multilist_sublist_tail(multilist_sublist_t *);
|
||||
|
||||
@@ -54,8 +54,10 @@ extern "C" {
|
||||
*/
|
||||
typedef struct pathname {
|
||||
char *pn_buf; /* underlying storage */
|
||||
#if 0 /* unused in ZoL */
|
||||
char *pn_path; /* remaining pathname */
|
||||
size_t pn_pathlen; /* remaining length */
|
||||
#endif
|
||||
size_t pn_bufsize; /* total size of pn_buf */
|
||||
} pathname_t;
|
||||
|
||||
|
||||
+1
-1
@@ -1104,7 +1104,7 @@ extern uint64_t spa_missing_tvds_allowed(spa_t *spa);
|
||||
extern void spa_set_missing_tvds(spa_t *spa, uint64_t missing);
|
||||
extern boolean_t spa_top_vdevs_spacemap_addressable(spa_t *spa);
|
||||
extern boolean_t spa_multihost(spa_t *spa);
|
||||
extern unsigned long spa_get_hostid(void);
|
||||
extern uint32_t spa_get_hostid(spa_t *spa);
|
||||
extern void spa_activate_allocation_classes(spa_t *, dmu_tx_t *);
|
||||
|
||||
extern int spa_mode(spa_t *spa);
|
||||
|
||||
@@ -219,6 +219,7 @@ struct spa {
|
||||
spa_taskqs_t spa_zio_taskq[ZIO_TYPES][ZIO_TASKQ_TYPES];
|
||||
dsl_pool_t *spa_dsl_pool;
|
||||
boolean_t spa_is_initializing; /* true while opening pool */
|
||||
boolean_t spa_is_exporting; /* true while exporting pool */
|
||||
metaslab_class_t *spa_normal_class; /* normal data class */
|
||||
metaslab_class_t *spa_log_class; /* intent log data class */
|
||||
metaslab_class_t *spa_special_class; /* special allocation class */
|
||||
@@ -394,6 +395,7 @@ struct spa {
|
||||
mmp_thread_t spa_mmp; /* multihost mmp thread */
|
||||
list_t spa_leaf_list; /* list of leaf vdevs */
|
||||
uint64_t spa_leaf_list_gen; /* track leaf_list changes */
|
||||
uint32_t spa_hostid; /* cached system hostid */
|
||||
|
||||
/*
|
||||
* spa_refcount & spa_config_lock must be the last elements
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014, 2017 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2014, 2019 by Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _SYS_VDEV_REMOVAL_H
|
||||
@@ -81,13 +81,13 @@ extern void spa_vdev_condense_suspend(spa_t *);
|
||||
extern int spa_vdev_remove(spa_t *, uint64_t, boolean_t);
|
||||
extern void free_from_removing_vdev(vdev_t *, uint64_t, uint64_t);
|
||||
extern int spa_removal_get_stats(spa_t *, pool_removal_stat_t *);
|
||||
extern void svr_sync(spa_t *spa, dmu_tx_t *tx);
|
||||
extern void svr_sync(spa_t *, dmu_tx_t *);
|
||||
extern void spa_vdev_remove_suspend(spa_t *);
|
||||
extern int spa_vdev_remove_cancel(spa_t *);
|
||||
extern void spa_vdev_removal_destroy(spa_vdev_removal_t *svr);
|
||||
extern void spa_vdev_removal_destroy(spa_vdev_removal_t *);
|
||||
extern uint64_t spa_remove_max_segment(spa_t *);
|
||||
|
||||
extern int vdev_removal_max_span;
|
||||
extern int zfs_remove_max_segment;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
+5
-2
@@ -21,7 +21,7 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2012, 2018 by Delphix. All rights reserved.
|
||||
* Copyright 2017 Nexenta Systems, Inc.
|
||||
*/
|
||||
|
||||
@@ -350,6 +350,7 @@ typedef struct zap_cursor {
|
||||
uint64_t zc_serialized;
|
||||
uint64_t zc_hash;
|
||||
uint32_t zc_cd;
|
||||
boolean_t zc_prefetch;
|
||||
} zap_cursor_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -375,7 +376,9 @@ typedef struct {
|
||||
* Initialize a zap cursor, pointing to the "first" attribute of the
|
||||
* zapobj. You must _fini the cursor when you are done with it.
|
||||
*/
|
||||
void zap_cursor_init(zap_cursor_t *zc, objset_t *ds, uint64_t zapobj);
|
||||
void zap_cursor_init(zap_cursor_t *zc, objset_t *os, uint64_t zapobj);
|
||||
void zap_cursor_init_noprefetch(zap_cursor_t *zc, objset_t *os,
|
||||
uint64_t zapobj);
|
||||
void zap_cursor_fini(zap_cursor_t *zc);
|
||||
|
||||
/*
|
||||
|
||||
@@ -257,6 +257,8 @@ extern void mutex_enter(kmutex_t *mp);
|
||||
extern void mutex_exit(kmutex_t *mp);
|
||||
extern int mutex_tryenter(kmutex_t *mp);
|
||||
|
||||
#define NESTED_SINGLE 1
|
||||
#define mutex_enter_nested(mp, class) mutex_enter(mp)
|
||||
/*
|
||||
* RW locks
|
||||
*/
|
||||
|
||||
@@ -196,6 +196,7 @@ typedef struct znode {
|
||||
uint8_t z_atime_dirty; /* atime needs to be synced */
|
||||
uint8_t z_zn_prefetch; /* Prefetch znodes? */
|
||||
uint8_t z_moved; /* Has this znode been moved? */
|
||||
boolean_t z_suspended; /* extra ref from a suspend? */
|
||||
uint_t z_blksz; /* block size in bytes */
|
||||
uint_t z_seq; /* modification sequence number */
|
||||
uint64_t z_mapcnt; /* number of pages mapped to file */
|
||||
@@ -371,7 +372,7 @@ extern void zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
|
||||
extern int zfs_log_create_txtype(zil_create_t, vsecattr_t *vsecp,
|
||||
vattr_t *vap);
|
||||
extern void zfs_log_remove(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
|
||||
znode_t *dzp, char *name, uint64_t foid);
|
||||
znode_t *dzp, char *name, uint64_t foid, boolean_t unlinked);
|
||||
#define ZFS_NO_OBJECT 0 /* no object id */
|
||||
extern void zfs_log_link(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
|
||||
znode_t *dzp, znode_t *zp, char *name);
|
||||
|
||||
@@ -105,8 +105,7 @@ extern size_t lz4_compress_zfs(void *src, void *dst, size_t s_len, size_t d_len,
|
||||
int level);
|
||||
extern int lz4_decompress_zfs(void *src, void *dst, size_t s_len, size_t d_len,
|
||||
int level);
|
||||
extern int lz4_decompress_abd(abd_t *src, void *dst, size_t s_len, size_t d_len,
|
||||
int level);
|
||||
|
||||
/*
|
||||
* Compress and decompress data if necessary.
|
||||
*/
|
||||
|
||||
@@ -43,6 +43,8 @@ typedef enum {
|
||||
NAME_ERR_RESERVED, /* entire name is reserved */
|
||||
NAME_ERR_DISKLIKE, /* reserved disk name (c[0-9].*) */
|
||||
NAME_ERR_TOOLONG, /* name is too long */
|
||||
NAME_ERR_SELF_REF, /* reserved self path name ('.') */
|
||||
NAME_ERR_PARENT_REF, /* reserved parent path name ('..') */
|
||||
NAME_ERR_NO_AT, /* permission set is missing '@' */
|
||||
} namecheck_err_t;
|
||||
|
||||
|
||||
@@ -9,4 +9,4 @@ Version: @VERSION@
|
||||
URL: http://zfsonlinux.org
|
||||
Requires: libzfs_core
|
||||
Cflags: -I${includedir}/libzfs -I${includedir}/libspl
|
||||
Libs: -L${libdir} -lzfs
|
||||
Libs: -L${libdir} -lzfs -lnvpair
|
||||
|
||||
@@ -475,9 +475,10 @@ change_one(zfs_handle_t *zhp, void *data)
|
||||
prop_changelist_t *clp = data;
|
||||
char property[ZFS_MAXPROPLEN];
|
||||
char where[64];
|
||||
prop_changenode_t *cn;
|
||||
prop_changenode_t *cn = NULL;
|
||||
zprop_source_t sourcetype = ZPROP_SRC_NONE;
|
||||
zprop_source_t share_sourcetype = ZPROP_SRC_NONE;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* We only want to unmount/unshare those filesystems that may inherit
|
||||
@@ -493,8 +494,7 @@ change_one(zfs_handle_t *zhp, void *data)
|
||||
zfs_prop_get(zhp, clp->cl_prop, property,
|
||||
sizeof (property), &sourcetype, where, sizeof (where),
|
||||
B_FALSE) != 0) {
|
||||
zfs_close(zhp);
|
||||
return (0);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -506,8 +506,7 @@ change_one(zfs_handle_t *zhp, void *data)
|
||||
zfs_prop_get(zhp, clp->cl_shareprop, property,
|
||||
sizeof (property), &share_sourcetype, where, sizeof (where),
|
||||
B_FALSE) != 0) {
|
||||
zfs_close(zhp);
|
||||
return (0);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (clp->cl_alldependents || clp->cl_allchildren ||
|
||||
@@ -518,8 +517,8 @@ change_one(zfs_handle_t *zhp, void *data)
|
||||
share_sourcetype == ZPROP_SRC_INHERITED))) {
|
||||
if ((cn = zfs_alloc(zfs_get_handle(zhp),
|
||||
sizeof (prop_changenode_t))) == NULL) {
|
||||
zfs_close(zhp);
|
||||
return (-1);
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cn->cn_handle = zhp;
|
||||
@@ -541,16 +540,23 @@ change_one(zfs_handle_t *zhp, void *data)
|
||||
uu_avl_insert(clp->cl_tree, cn, idx);
|
||||
} else {
|
||||
free(cn);
|
||||
zfs_close(zhp);
|
||||
cn = NULL;
|
||||
}
|
||||
|
||||
if (!clp->cl_alldependents)
|
||||
return (zfs_iter_children(zhp, change_one, data));
|
||||
} else {
|
||||
zfs_close(zhp);
|
||||
ret = zfs_iter_children(zhp, change_one, data);
|
||||
|
||||
/*
|
||||
* If we added the handle to the changelist, we will re-use it
|
||||
* later so return without closing it.
|
||||
*/
|
||||
if (cn != NULL)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
return (0);
|
||||
out:
|
||||
zfs_close(zhp);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
|
||||
@@ -740,14 +740,6 @@ zfs_crypto_create(libzfs_handle_t *hdl, char *parent_name, nvlist_t *props,
|
||||
pcrypt = ZIO_CRYPT_OFF;
|
||||
}
|
||||
|
||||
/* Check for encryption being explicitly truned off */
|
||||
if (crypt == ZIO_CRYPT_OFF && pcrypt != ZIO_CRYPT_OFF) {
|
||||
ret = EINVAL;
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"Invalid encryption value. Dataset must be encrypted."));
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Get the inherited encryption property if we don't have it locally */
|
||||
if (!local_crypt)
|
||||
crypt = pcrypt;
|
||||
@@ -849,10 +841,7 @@ int
|
||||
zfs_crypto_clone_check(libzfs_handle_t *hdl, zfs_handle_t *origin_zhp,
|
||||
char *parent_name, nvlist_t *props)
|
||||
{
|
||||
int ret;
|
||||
char errbuf[1024];
|
||||
zfs_handle_t *pzhp = NULL;
|
||||
uint64_t pcrypt, ocrypt;
|
||||
|
||||
(void) snprintf(errbuf, sizeof (errbuf),
|
||||
dgettext(TEXT_DOMAIN, "Encryption clone error"));
|
||||
@@ -865,40 +854,12 @@ zfs_crypto_clone_check(libzfs_handle_t *hdl, zfs_handle_t *origin_zhp,
|
||||
nvlist_exists(props, zfs_prop_to_name(ZFS_PROP_KEYLOCATION)) ||
|
||||
nvlist_exists(props, zfs_prop_to_name(ZFS_PROP_ENCRYPTION)) ||
|
||||
nvlist_exists(props, zfs_prop_to_name(ZFS_PROP_PBKDF2_ITERS))) {
|
||||
ret = EINVAL;
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"Encryption properties must inherit from origin dataset."));
|
||||
goto out;
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/* get a reference to parent dataset, should never be NULL */
|
||||
pzhp = make_dataset_handle(hdl, parent_name);
|
||||
if (pzhp == NULL) {
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"Failed to lookup parent."));
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
/* Lookup parent's crypt */
|
||||
pcrypt = zfs_prop_get_int(pzhp, ZFS_PROP_ENCRYPTION);
|
||||
ocrypt = zfs_prop_get_int(origin_zhp, ZFS_PROP_ENCRYPTION);
|
||||
|
||||
/* all children of encrypted parents must be encrypted */
|
||||
if (pcrypt != ZIO_CRYPT_OFF && ocrypt == ZIO_CRYPT_OFF) {
|
||||
ret = EINVAL;
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"Cannot create unencrypted clone as a child "
|
||||
"of encrypted parent."));
|
||||
goto out;
|
||||
}
|
||||
|
||||
zfs_close(pzhp);
|
||||
return (0);
|
||||
|
||||
out:
|
||||
if (pzhp != NULL)
|
||||
zfs_close(pzhp);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
typedef struct loadkeys_cbdata {
|
||||
|
||||
+27
-19
@@ -197,6 +197,16 @@ zfs_validate_name(libzfs_handle_t *hdl, const char *path, int type,
|
||||
"reserved disk name"));
|
||||
break;
|
||||
|
||||
case NAME_ERR_SELF_REF:
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"self reference, '.' is found in name"));
|
||||
break;
|
||||
|
||||
case NAME_ERR_PARENT_REF:
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"parent reference, '..' is found in name"));
|
||||
break;
|
||||
|
||||
default:
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"(%d) not defined"), why);
|
||||
@@ -4107,6 +4117,16 @@ zfs_promote(zfs_handle_t *zhp)
|
||||
|
||||
if (ret != 0) {
|
||||
switch (ret) {
|
||||
case EACCES:
|
||||
/*
|
||||
* Promoting encrypted dataset outside its
|
||||
* encryption root.
|
||||
*/
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"cannot promote dataset outside its "
|
||||
"encryption root"));
|
||||
return (zfs_error(hdl, EZFS_EXISTS, errbuf));
|
||||
|
||||
case EEXIST:
|
||||
/* There is a conflicting snapshot name. */
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
@@ -4470,8 +4490,6 @@ zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive,
|
||||
zfs_cmd_t zc = {"\0"};
|
||||
char *delim;
|
||||
prop_changelist_t *cl = NULL;
|
||||
zfs_handle_t *zhrp = NULL;
|
||||
char *parentname = NULL;
|
||||
char parent[ZFS_MAX_DATASET_NAME_LEN];
|
||||
libzfs_handle_t *hdl = zhp->zfs_hdl;
|
||||
char errbuf[1024];
|
||||
@@ -4566,7 +4584,8 @@ zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive,
|
||||
}
|
||||
|
||||
if (recursive) {
|
||||
parentname = zfs_strdup(zhp->zfs_hdl, zhp->zfs_name);
|
||||
zfs_handle_t *zhrp;
|
||||
char *parentname = zfs_strdup(zhp->zfs_hdl, zhp->zfs_name);
|
||||
if (parentname == NULL) {
|
||||
ret = -1;
|
||||
goto error;
|
||||
@@ -4574,10 +4593,12 @@ zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive,
|
||||
delim = strchr(parentname, '@');
|
||||
*delim = '\0';
|
||||
zhrp = zfs_open(zhp->zfs_hdl, parentname, ZFS_TYPE_DATASET);
|
||||
free(parentname);
|
||||
if (zhrp == NULL) {
|
||||
ret = -1;
|
||||
goto error;
|
||||
}
|
||||
zfs_close(zhrp);
|
||||
} else if (zhp->zfs_type != ZFS_TYPE_SNAPSHOT) {
|
||||
if ((cl = changelist_gather(zhp, ZFS_PROP_NAME,
|
||||
CL_GATHER_ITER_MOUNTED,
|
||||
@@ -4621,16 +4642,9 @@ zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive,
|
||||
"with the new name"));
|
||||
(void) zfs_error(hdl, EZFS_EXISTS, errbuf);
|
||||
} else if (errno == EACCES) {
|
||||
if (zfs_prop_get_int(zhp, ZFS_PROP_ENCRYPTION) ==
|
||||
ZIO_CRYPT_OFF) {
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"cannot rename an unencrypted dataset to "
|
||||
"be a decendent of an encrypted one"));
|
||||
} else {
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"cannot move encryption child outside of "
|
||||
"its encryption root"));
|
||||
}
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"cannot move encrypted child outside of "
|
||||
"its encryption root"));
|
||||
(void) zfs_error(hdl, EZFS_CRYPTOFAILED, errbuf);
|
||||
} else {
|
||||
(void) zfs_standard_error(zhp->zfs_hdl, errno, errbuf);
|
||||
@@ -4650,12 +4664,6 @@ zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive,
|
||||
}
|
||||
|
||||
error:
|
||||
if (parentname != NULL) {
|
||||
free(parentname);
|
||||
}
|
||||
if (zhrp != NULL) {
|
||||
zfs_close(zhrp);
|
||||
}
|
||||
if (cl != NULL) {
|
||||
changelist_free(cl);
|
||||
}
|
||||
|
||||
@@ -1302,12 +1302,14 @@ mountpoint_cmp(const void *arga, const void *argb)
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if path2 is a child of path1.
|
||||
* Return true if path2 is a child of path1 or path2 equals path1 or
|
||||
* path1 is "/" (path2 is always a child of "/").
|
||||
*/
|
||||
static boolean_t
|
||||
libzfs_path_contains(const char *path1, const char *path2)
|
||||
{
|
||||
return (strstr(path2, path1) == path2 && path2[strlen(path1)] == '/');
|
||||
return (strcmp(path1, path2) == 0 || strcmp(path1, "/") == 0 ||
|
||||
(strstr(path2, path1) == path2 && path2[strlen(path1)] == '/'));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -2827,7 +2827,7 @@ recv_fix_encryption_hierarchy(libzfs_handle_t *hdl, const char *destname,
|
||||
is_clone = zhp->zfs_dmustats.dds_origin[0] != '\0';
|
||||
(void) zfs_crypto_get_encryption_root(zhp, &is_encroot, NULL);
|
||||
|
||||
/* we don't need to do anything for unencrypted filesystems */
|
||||
/* we don't need to do anything for unencrypted datasets */
|
||||
if (crypt == ZIO_CRYPT_OFF) {
|
||||
zfs_close(zhp);
|
||||
continue;
|
||||
@@ -3992,11 +3992,18 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* if the fs does not exist, look for it based on the
|
||||
* fromsnap GUID
|
||||
* If the fs does not exist, look for it based on the
|
||||
* fromsnap GUID.
|
||||
*/
|
||||
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
|
||||
"cannot receive incremental stream"));
|
||||
if (resuming) {
|
||||
(void) snprintf(errbuf, sizeof (errbuf),
|
||||
dgettext(TEXT_DOMAIN,
|
||||
"cannot receive resume stream"));
|
||||
} else {
|
||||
(void) snprintf(errbuf, sizeof (errbuf),
|
||||
dgettext(TEXT_DOMAIN,
|
||||
"cannot receive incremental stream"));
|
||||
}
|
||||
|
||||
(void) strcpy(name, destsnap);
|
||||
*strchr(name, '@') = '\0';
|
||||
@@ -4210,34 +4217,6 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* It is invalid to receive a properties stream that was
|
||||
* unencrypted on the send side as a child of an encrypted
|
||||
* parent. Technically there is nothing preventing this, but
|
||||
* it would mean that the encryption=off property which is
|
||||
* locally set on the send side would not be received correctly.
|
||||
* We can infer encryption=off if the stream is not raw and
|
||||
* properties were included since the send side will only ever
|
||||
* send the encryption property in a raw nvlist header. This
|
||||
* check will be avoided if the user specifically overrides
|
||||
* the encryption property on the command line.
|
||||
*/
|
||||
if (!raw && rcvprops != NULL &&
|
||||
!nvlist_exists(cmdprops,
|
||||
zfs_prop_to_name(ZFS_PROP_ENCRYPTION))) {
|
||||
uint64_t crypt;
|
||||
|
||||
crypt = zfs_prop_get_int(zhp, ZFS_PROP_ENCRYPTION);
|
||||
|
||||
if (crypt != ZIO_CRYPT_OFF) {
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"parent '%s' must not be encrypted to "
|
||||
"receive unenecrypted property"), name);
|
||||
err = zfs_error(hdl, EZFS_BADPROP, errbuf);
|
||||
zfs_close(zhp);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
zfs_close(zhp);
|
||||
|
||||
newfs = B_TRUE;
|
||||
@@ -4274,6 +4253,24 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
|
||||
&oxprops, &wkeydata, &wkeylen, errbuf)) != 0)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* When sending with properties (zfs send -p), the encryption property
|
||||
* is not included because it is a SETONCE property and therefore
|
||||
* treated as read only. However, we are always able to determine its
|
||||
* value because raw sends will include it in the DRR_BDEGIN payload
|
||||
* and non-raw sends with properties are not allowed for encrypted
|
||||
* datasets. Therefore, if this is a non-raw properties stream, we can
|
||||
* infer that the value should be ZIO_CRYPT_OFF and manually add that
|
||||
* to the received properties.
|
||||
*/
|
||||
if (stream_wantsnewfs && !raw && rcvprops != NULL &&
|
||||
!nvlist_exists(cmdprops, zfs_prop_to_name(ZFS_PROP_ENCRYPTION))) {
|
||||
if (oxprops == NULL)
|
||||
oxprops = fnvlist_alloc();
|
||||
fnvlist_add_uint64(oxprops,
|
||||
zfs_prop_to_name(ZFS_PROP_ENCRYPTION), ZIO_CRYPT_OFF);
|
||||
}
|
||||
|
||||
err = ioctl_err = lzc_receive_with_cmdprops(destsnap, rcvprops,
|
||||
oxprops, wkeydata, wkeylen, origin, flags->force, flags->resumable,
|
||||
raw, infd, drr_noswap, cleanup_fd, &read_bytes, &errflags,
|
||||
@@ -4428,14 +4425,15 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
|
||||
*cp = '@';
|
||||
break;
|
||||
case EINVAL:
|
||||
if (flags->resumable)
|
||||
if (flags->resumable) {
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"kernel modules must be upgraded to "
|
||||
"receive this stream."));
|
||||
if (embedded && !raw)
|
||||
} else if (embedded && !raw) {
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"incompatible embedded data stream "
|
||||
"feature with encrypted receive."));
|
||||
}
|
||||
(void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
|
||||
break;
|
||||
case ECKSUM:
|
||||
|
||||
@@ -303,6 +303,8 @@ libzfs_error_description(libzfs_handle_t *hdl)
|
||||
case EZFS_NO_RESILVER_DEFER:
|
||||
return (dgettext(TEXT_DOMAIN, "this action requires the "
|
||||
"resilver_defer feature"));
|
||||
case EZFS_EXPORT_IN_PROGRESS:
|
||||
return (dgettext(TEXT_DOMAIN, "pool export in progress"));
|
||||
case EZFS_UNKNOWN:
|
||||
return (dgettext(TEXT_DOMAIN, "unknown error"));
|
||||
default:
|
||||
@@ -598,6 +600,9 @@ zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
|
||||
case ZFS_ERR_VDEV_TOO_BIG:
|
||||
zfs_verror(hdl, EZFS_VDEV_TOO_BIG, fmt, ap);
|
||||
break;
|
||||
case ZFS_ERR_EXPORT_IN_PROGRESS:
|
||||
zfs_verror(hdl, EZFS_EXPORT_IN_PROGRESS, fmt, ap);
|
||||
break;
|
||||
case ZFS_ERR_IOC_CMD_UNAVAIL:
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "the loaded zfs "
|
||||
"module does not support this operation. A reboot may "
|
||||
@@ -1134,7 +1139,7 @@ int
|
||||
zcmd_alloc_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, size_t len)
|
||||
{
|
||||
if (len == 0)
|
||||
len = 16 * 1024;
|
||||
len = 256 * 1024;
|
||||
zc->zc_nvlist_dst_size = len;
|
||||
zc->zc_nvlist_dst =
|
||||
(uint64_t)(uintptr_t)zfs_alloc(hdl, zc->zc_nvlist_dst_size);
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
*
|
||||
* - Thin Layer. libzfs_core is a thin layer, marshaling arguments
|
||||
* to/from the kernel ioctls. There is generally a 1:1 correspondence
|
||||
* between libzfs_core functions and ioctls to /dev/zfs.
|
||||
* between libzfs_core functions and ioctls to ZFS_DEV.
|
||||
*
|
||||
* - Clear Atomicity. Because libzfs_core functions are generally 1:1
|
||||
* with kernel ioctls, and kernel ioctls are general atomic, each
|
||||
@@ -135,7 +135,7 @@ libzfs_core_init(void)
|
||||
{
|
||||
(void) pthread_mutex_lock(&g_lock);
|
||||
if (g_refcount == 0) {
|
||||
g_fd = open("/dev/zfs", O_RDWR);
|
||||
g_fd = open(ZFS_DEV, O_RDWR);
|
||||
if (g_fd < 0) {
|
||||
(void) pthread_mutex_unlock(&g_lock);
|
||||
return (errno);
|
||||
@@ -499,7 +499,7 @@ lzc_sync(const char *pool_name, nvlist_t *innvl, nvlist_t **outnvl)
|
||||
* The snapshots must all be in the same pool.
|
||||
* The value is the name of the hold (string type).
|
||||
*
|
||||
* If cleanup_fd is not -1, it must be the result of open("/dev/zfs", O_EXCL).
|
||||
* If cleanup_fd is not -1, it must be the result of open(ZFS_DEV, O_EXCL).
|
||||
* In this case, when the cleanup_fd is closed (including on process
|
||||
* termination), the holds will be released. If the system is shut down
|
||||
* uncleanly, the holds will be released when the pool is next opened
|
||||
|
||||
+1
-1
@@ -223,7 +223,7 @@ pool_active(void *unused, const char *name, uint64_t guid,
|
||||
* Use ZFS_IOC_POOL_SYNC to confirm if a pool is active
|
||||
*/
|
||||
|
||||
fd = open("/dev/zfs", O_RDWR);
|
||||
fd = open(ZFS_DEV, O_RDWR);
|
||||
if (fd < 0)
|
||||
return (-1);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
dist_man_MANS = zhack.1 ztest.1 raidz_test.1
|
||||
dist_man_MANS = zhack.1 ztest.1 raidz_test.1 zvol_wait.1
|
||||
EXTRA_DIST = cstyle.1
|
||||
|
||||
install-data-local:
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
.Dd July 5, 2019
|
||||
.Dt ZVOL_WAIT 1 SMM
|
||||
.Os Linux
|
||||
.Sh NAME
|
||||
.Nm zvol_wait
|
||||
.Nd Wait for ZFS volume links in
|
||||
.Em /dev
|
||||
to be created.
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Sh DESCRIPTION
|
||||
When a ZFS pool is imported, ZFS will register each ZFS volume
|
||||
(zvol) as a disk device with the system. As the disks are registered,
|
||||
.Xr \fBudev 7\fR
|
||||
will asynchronously create symlinks under
|
||||
.Em /dev/zvol
|
||||
using the zvol's name.
|
||||
.Nm
|
||||
will wait for all those symlinks to be created before returning.
|
||||
.Sh SEE ALSO
|
||||
.Xr \fBudev 7\fR
|
||||
@@ -104,6 +104,18 @@ to a log2 fraction of the target arc size.
|
||||
Default value: \fB6\fR.
|
||||
.RE
|
||||
|
||||
.sp
|
||||
.ne 2
|
||||
.na
|
||||
\fBdmu_prefetch_max\fR (int)
|
||||
.ad
|
||||
.RS 12n
|
||||
Limit the amount we can prefetch with one call to this amount (in bytes).
|
||||
This helps to limit the amount of memory that can be used by prefetching.
|
||||
.sp
|
||||
Default value: \fB134,217,728\fR (128MB).
|
||||
.RE
|
||||
|
||||
.sp
|
||||
.ne 2
|
||||
.na
|
||||
@@ -502,6 +514,19 @@ regular reads (but there's no reason it has to be the same).
|
||||
Default value: \fB32,768\fR.
|
||||
.RE
|
||||
|
||||
.sp
|
||||
.ne 2
|
||||
.na
|
||||
\fBzap_iterate_prefetch\fR (int)
|
||||
.ad
|
||||
.RS 12n
|
||||
If this is set, when we start iterating over a ZAP object, zfs will prefetch
|
||||
the entire object (all leaf blocks). However, this is limited by
|
||||
\fBdmu_prefetch_max\fR.
|
||||
.sp
|
||||
Use \fB1\fR for on (default) and \fB0\fR for off.
|
||||
.RE
|
||||
|
||||
.sp
|
||||
.ne 2
|
||||
.na
|
||||
@@ -1817,7 +1842,7 @@ this value. If a metaslab group exceeds this threshold then it will be
|
||||
skipped unless all metaslab groups within the metaslab class have also
|
||||
crossed this threshold.
|
||||
.sp
|
||||
Default value: \fB85\fR.
|
||||
Default value: \fB95\fR.
|
||||
.RE
|
||||
|
||||
.sp
|
||||
@@ -2169,6 +2194,33 @@ pool cannot be returned to a healthy state prior to removing the device.
|
||||
Default value: \fB0\fR.
|
||||
.RE
|
||||
|
||||
.sp
|
||||
.ne 2
|
||||
.na
|
||||
\fBzfs_removal_suspend_progress\fR (int)
|
||||
.ad
|
||||
.RS 12n
|
||||
.sp
|
||||
This is used by the test suite so that it can ensure that certain actions
|
||||
happen while in the middle of a removal.
|
||||
.sp
|
||||
Default value: \fB0\fR.
|
||||
.RE
|
||||
|
||||
.sp
|
||||
.ne 2
|
||||
.na
|
||||
\fBzfs_remove_max_segment\fR (int)
|
||||
.ad
|
||||
.RS 12n
|
||||
.sp
|
||||
The largest contiguous segment that we will attempt to allocate when removing
|
||||
a device. This can be no larger than 16MB. If there is a performance
|
||||
problem with attempting to allocate large blocks, consider decreasing this.
|
||||
.sp
|
||||
Default value: \fB16,777,216\fR (16MB).
|
||||
.RE
|
||||
|
||||
.sp
|
||||
.ne 2
|
||||
.na
|
||||
@@ -2419,9 +2471,21 @@ Default value: \fB25\fR.
|
||||
\fBzfs_sync_pass_dont_compress\fR (int)
|
||||
.ad
|
||||
.RS 12n
|
||||
Don't compress starting in this pass
|
||||
Starting in this sync pass, we disable compression (including of metadata).
|
||||
With the default setting, in practice, we don't have this many sync passes,
|
||||
so this has no effect.
|
||||
.sp
|
||||
Default value: \fB5\fR.
|
||||
The original intent was that disabling compression would help the sync passes
|
||||
to converge. However, in practice disabling compression increases the average
|
||||
number of sync passes, because when we turn compression off, a lot of block's
|
||||
size will change and thus we have to re-allocate (not overwrite) them. It
|
||||
also increases the number of 128KB allocations (e.g. for indirect blocks and
|
||||
spacemaps) because these will not be compressed. The 128K allocations are
|
||||
especially detrimental to performance on highly fragmented systems, which may
|
||||
have very few free segments of this size, and may need to load new metaslabs
|
||||
to satisfy 128K allocations.
|
||||
.sp
|
||||
Default value: \fB8\fR.
|
||||
.RE
|
||||
|
||||
.sp
|
||||
|
||||
@@ -26,7 +26,7 @@ information on ZFS mountpoints must be stored separately. The output
|
||||
of the command
|
||||
.PP
|
||||
.RS 4
|
||||
zfs list -H -o name,mountpoint,canmount,atime,relatime,devices,exec,readonly,setuid,nbmand
|
||||
zfs list -H -o name,mountpoint,canmount,atime,relatime,devices,exec,readonly,setuid,nbmand,encroot,keylocation
|
||||
.RE
|
||||
.PP
|
||||
for datasets that should be mounted by systemd, should be kept
|
||||
|
||||
+14
-13
@@ -1,11 +1,11 @@
|
||||
subdir-m += avl
|
||||
subdir-m += icp
|
||||
subdir-m += lua
|
||||
subdir-m += nvpair
|
||||
subdir-m += spl
|
||||
subdir-m += unicode
|
||||
subdir-m += zcommon
|
||||
subdir-m += zfs
|
||||
obj-m += avl/
|
||||
obj-m += icp/
|
||||
obj-m += lua/
|
||||
obj-m += nvpair/
|
||||
obj-m += spl/
|
||||
obj-m += unicode/
|
||||
obj-m += zcommon/
|
||||
obj-m += zfs/
|
||||
|
||||
INSTALL_MOD_DIR ?= extra
|
||||
|
||||
@@ -60,14 +60,15 @@ modules_install:
|
||||
modules_uninstall:
|
||||
@# Uninstall the kernel modules
|
||||
kmoddir=$(DESTDIR)$(INSTALL_MOD_PATH)/lib/modules/@LINUX_VERSION@
|
||||
list='$(subdir-m)'; for subdir in $$list; do \
|
||||
$(RM) -R $$kmoddir/$(INSTALL_MOD_DIR)/$$subdir; \
|
||||
list='$(obj-m)'; for objdir in $$list; do \
|
||||
$(RM) -R $$kmoddir/$(INSTALL_MOD_DIR)/$$objdir; \
|
||||
done
|
||||
|
||||
distdir:
|
||||
list='$(subdir-m)'; for subdir in $$list; do \
|
||||
(cd @top_srcdir@/module && find $$subdir -name '*.c' -o -name '*.h' -o -name '*.S' |\
|
||||
xargs cp --parents -t $$distdir); \
|
||||
list='$(obj-m)'; for objdir in $$list; do \
|
||||
(cd @top_srcdir@/module && find $$objdir \
|
||||
-name '*.c' -o -name '*.h' -o -name '*.S' | \
|
||||
xargs cp --parents -t @abs_top_builddir@/module/$$distdir); \
|
||||
done
|
||||
|
||||
distclean maintainer-clean: clean
|
||||
|
||||
@@ -303,16 +303,21 @@ aes_impl_init(void)
|
||||
}
|
||||
aes_supp_impl_cnt = c;
|
||||
|
||||
/* set fastest implementation. assume hardware accelerated is fastest */
|
||||
/*
|
||||
* Set the fastest implementation given the assumption that the
|
||||
* hardware accelerated version is the fastest.
|
||||
*/
|
||||
#if defined(__x86_64)
|
||||
#if defined(HAVE_AES)
|
||||
if (aes_aesni_impl.is_supported())
|
||||
if (aes_aesni_impl.is_supported()) {
|
||||
memcpy(&aes_fastest_impl, &aes_aesni_impl,
|
||||
sizeof (aes_fastest_impl));
|
||||
else
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
memcpy(&aes_fastest_impl, &aes_x86_64_impl,
|
||||
sizeof (aes_fastest_impl));
|
||||
}
|
||||
#else
|
||||
memcpy(&aes_fastest_impl, &aes_generic_impl,
|
||||
sizeof (aes_fastest_impl));
|
||||
|
||||
@@ -646,7 +646,7 @@ const gcm_impl_ops_t *gcm_all_impl[] = {
|
||||
/* Indicate that benchmark has been completed */
|
||||
static boolean_t gcm_impl_initialized = B_FALSE;
|
||||
|
||||
/* Select aes implementation */
|
||||
/* Select GCM implementation */
|
||||
#define IMPL_FASTEST (UINT32_MAX)
|
||||
#define IMPL_CYCLE (UINT32_MAX-1)
|
||||
|
||||
@@ -713,13 +713,15 @@ gcm_impl_init(void)
|
||||
|
||||
/* set fastest implementation. assume hardware accelerated is fastest */
|
||||
#if defined(__x86_64) && defined(HAVE_PCLMULQDQ)
|
||||
if (gcm_pclmulqdq_impl.is_supported())
|
||||
if (gcm_pclmulqdq_impl.is_supported()) {
|
||||
memcpy(&gcm_fastest_impl, &gcm_pclmulqdq_impl,
|
||||
sizeof (gcm_fastest_impl));
|
||||
else
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
memcpy(&gcm_fastest_impl, &gcm_generic_impl,
|
||||
sizeof (gcm_fastest_impl));
|
||||
}
|
||||
|
||||
strcpy(gcm_fastest_impl.name, "fastest");
|
||||
|
||||
@@ -742,7 +744,7 @@ static const struct {
|
||||
* If we are called before init(), user preference will be saved in
|
||||
* user_sel_impl, and applied in later init() call. This occurs when module
|
||||
* parameter is specified on module load. Otherwise, directly update
|
||||
* icp_aes_impl.
|
||||
* icp_gcm_impl.
|
||||
*
|
||||
* @val Name of gcm implementation to use
|
||||
* @param Unused.
|
||||
|
||||
@@ -162,7 +162,7 @@ typedef enum aes_mech_type {
|
||||
#endif /* _AES_IMPL */
|
||||
|
||||
/*
|
||||
* Methods used to define aes implementation
|
||||
* Methods used to define AES implementation
|
||||
*
|
||||
* @aes_gen_f Key generation
|
||||
* @aes_enc_f Function encrypts one block
|
||||
|
||||
@@ -37,12 +37,12 @@ extern "C" {
|
||||
#include <sys/crypto/common.h>
|
||||
|
||||
/*
|
||||
* Methods used to define gcm implementation
|
||||
* Methods used to define GCM implementation
|
||||
*
|
||||
* @gcm_mul_f Perform carry-less multiplication
|
||||
* @gcm_will_work_f Function tests whether implementation will function
|
||||
*/
|
||||
typedef void (*gcm_mul_f)(uint64_t *, uint64_t *, uint64_t *);
|
||||
typedef void (*gcm_mul_f)(uint64_t *, uint64_t *, uint64_t *);
|
||||
typedef boolean_t (*gcm_will_work_f)(void);
|
||||
|
||||
#define GCM_IMPL_NAME_MAX (16)
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@
|
||||
#elif defined(__mips__)
|
||||
#define JMP_BUF_CNT 12
|
||||
#elif defined(__s390x__)
|
||||
#define JMP_BUF_CNT 9
|
||||
#define JMP_BUF_CNT 18
|
||||
#else
|
||||
#define JMP_BUF_CNT 1
|
||||
#endif
|
||||
|
||||
+6
-3
@@ -431,9 +431,12 @@ static int llex (LexState *ls, SemInfo *seminfo) {
|
||||
if (sep >= 0) {
|
||||
read_long_string(ls, seminfo, sep);
|
||||
return TK_STRING;
|
||||
}
|
||||
else if (sep == -1) return '[';
|
||||
else lexerror(ls, "invalid long string delimiter", TK_STRING);
|
||||
} else if (sep == -1) {
|
||||
return '[';
|
||||
} else {
|
||||
lexerror(ls, "invalid long string delimiter", TK_STRING);
|
||||
break;
|
||||
}
|
||||
}
|
||||
case '=': {
|
||||
next(ls);
|
||||
|
||||
@@ -16,10 +16,8 @@ $(MODULE)-objs += spl-kmem.o
|
||||
$(MODULE)-objs += spl-kmem-cache.o
|
||||
$(MODULE)-objs += spl-kobj.o
|
||||
$(MODULE)-objs += spl-kstat.o
|
||||
$(MODULE)-objs += spl-mutex.o
|
||||
$(MODULE)-objs += spl-proc.o
|
||||
$(MODULE)-objs += spl-procfs-list.o
|
||||
$(MODULE)-objs += spl-rwlock.o
|
||||
$(MODULE)-objs += spl-taskq.o
|
||||
$(MODULE)-objs += spl-thread.o
|
||||
$(MODULE)-objs += spl-tsd.o
|
||||
|
||||
@@ -154,26 +154,39 @@ EXPORT_SYMBOL(__cv_wait_sig);
|
||||
#if defined(HAVE_IO_SCHEDULE_TIMEOUT)
|
||||
#define spl_io_schedule_timeout(t) io_schedule_timeout(t)
|
||||
#else
|
||||
|
||||
struct spl_task_timer {
|
||||
struct timer_list timer;
|
||||
struct task_struct *task;
|
||||
};
|
||||
|
||||
static void
|
||||
__cv_wakeup(unsigned long data)
|
||||
__cv_wakeup(spl_timer_list_t t)
|
||||
{
|
||||
wake_up_process((struct task_struct *)data);
|
||||
struct timer_list *tmr = (struct timer_list *)t;
|
||||
struct spl_task_timer *task_timer = from_timer(task_timer, tmr, timer);
|
||||
|
||||
wake_up_process(task_timer->task);
|
||||
}
|
||||
|
||||
static long
|
||||
spl_io_schedule_timeout(long time_left)
|
||||
{
|
||||
long expire_time = jiffies + time_left;
|
||||
struct timer_list timer;
|
||||
struct spl_task_timer task_timer;
|
||||
struct timer_list *timer = &task_timer.timer;
|
||||
|
||||
init_timer(&timer);
|
||||
setup_timer(&timer, __cv_wakeup, (unsigned long)current);
|
||||
timer.expires = expire_time;
|
||||
add_timer(&timer);
|
||||
task_timer.task = current;
|
||||
|
||||
timer_setup(timer, __cv_wakeup, 0);
|
||||
|
||||
timer->expires = expire_time;
|
||||
add_timer(timer);
|
||||
|
||||
io_schedule();
|
||||
|
||||
del_timer_sync(&timer);
|
||||
del_timer_sync(timer);
|
||||
|
||||
time_left = expire_time - jiffies;
|
||||
|
||||
return (time_left < 0 ? 0 : time_left);
|
||||
|
||||
+13
-25
@@ -694,51 +694,41 @@ spl_init(void)
|
||||
if ((rc = spl_kvmem_init()))
|
||||
goto out1;
|
||||
|
||||
if ((rc = spl_mutex_init()))
|
||||
if ((rc = spl_tsd_init()))
|
||||
goto out2;
|
||||
|
||||
if ((rc = spl_rw_init()))
|
||||
if ((rc = spl_taskq_init()))
|
||||
goto out3;
|
||||
|
||||
if ((rc = spl_tsd_init()))
|
||||
if ((rc = spl_kmem_cache_init()))
|
||||
goto out4;
|
||||
|
||||
if ((rc = spl_taskq_init()))
|
||||
if ((rc = spl_vn_init()))
|
||||
goto out5;
|
||||
|
||||
if ((rc = spl_kmem_cache_init()))
|
||||
if ((rc = spl_proc_init()))
|
||||
goto out6;
|
||||
|
||||
if ((rc = spl_vn_init()))
|
||||
if ((rc = spl_kstat_init()))
|
||||
goto out7;
|
||||
|
||||
if ((rc = spl_proc_init()))
|
||||
goto out8;
|
||||
|
||||
if ((rc = spl_kstat_init()))
|
||||
goto out9;
|
||||
|
||||
if ((rc = spl_zlib_init()))
|
||||
goto out10;
|
||||
goto out8;
|
||||
|
||||
return (rc);
|
||||
|
||||
out10:
|
||||
spl_kstat_fini();
|
||||
out9:
|
||||
spl_proc_fini();
|
||||
out8:
|
||||
spl_vn_fini();
|
||||
spl_kstat_fini();
|
||||
out7:
|
||||
spl_kmem_cache_fini();
|
||||
spl_proc_fini();
|
||||
out6:
|
||||
spl_taskq_fini();
|
||||
spl_vn_fini();
|
||||
out5:
|
||||
spl_tsd_fini();
|
||||
spl_kmem_cache_fini();
|
||||
out4:
|
||||
spl_rw_fini();
|
||||
spl_taskq_fini();
|
||||
out3:
|
||||
spl_mutex_fini();
|
||||
spl_tsd_fini();
|
||||
out2:
|
||||
spl_kvmem_fini();
|
||||
out1:
|
||||
@@ -755,8 +745,6 @@ spl_fini(void)
|
||||
spl_kmem_cache_fini();
|
||||
spl_taskq_fini();
|
||||
spl_tsd_fini();
|
||||
spl_rw_fini();
|
||||
spl_mutex_fini();
|
||||
spl_kvmem_fini();
|
||||
}
|
||||
|
||||
|
||||
@@ -180,7 +180,8 @@ spl_kmem_alloc_impl(size_t size, int flags, int node)
|
||||
*/
|
||||
if ((size > spl_kmem_alloc_max) || use_vmem) {
|
||||
if (flags & KM_VMEM) {
|
||||
ptr = __vmalloc(size, lflags, PAGE_KERNEL);
|
||||
ptr = __vmalloc(size, lflags | __GFP_HIGHMEM,
|
||||
PAGE_KERNEL);
|
||||
} else {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
|
||||
* Copyright (C) 2007 The Regents of the University of California.
|
||||
* Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
|
||||
* Written by Brian Behlendorf <behlendorf1@llnl.gov>.
|
||||
* UCRL-CODE-235197
|
||||
*
|
||||
* This file is part of the SPL, Solaris Porting Layer.
|
||||
* For details, see <http://zfsonlinux.org/>.
|
||||
*
|
||||
* The SPL 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.
|
||||
*
|
||||
* The SPL 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 the SPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Solaris Porting Layer (SPL) Mutex Implementation.
|
||||
*/
|
||||
|
||||
#include <sys/mutex.h>
|
||||
|
||||
int spl_mutex_init(void) { return 0; }
|
||||
void spl_mutex_fini(void) { }
|
||||
@@ -1,132 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
|
||||
* Copyright (C) 2007 The Regents of the University of California.
|
||||
* Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
|
||||
* Written by Brian Behlendorf <behlendorf1@llnl.gov>.
|
||||
* UCRL-CODE-235197
|
||||
*
|
||||
* This file is part of the SPL, Solaris Porting Layer.
|
||||
* For details, see <http://zfsonlinux.org/>.
|
||||
*
|
||||
* The SPL 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.
|
||||
*
|
||||
* The SPL 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 the SPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Solaris Porting Layer (SPL) Reader/Writer Lock Implementation.
|
||||
*/
|
||||
|
||||
#include <sys/rwlock.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#if defined(CONFIG_PREEMPT_RT_FULL)
|
||||
|
||||
#include <linux/rtmutex.h>
|
||||
#define RT_MUTEX_OWNER_MASKALL 1UL
|
||||
|
||||
static int
|
||||
__rwsem_tryupgrade(struct rw_semaphore *rwsem)
|
||||
{
|
||||
#if defined(READER_BIAS) && defined(WRITER_BIAS)
|
||||
/*
|
||||
* After the 4.9.20-rt16 kernel the realtime patch series lifted the
|
||||
* single reader restriction. While this could be accommodated by
|
||||
* adding additional compatibility code assume the rwsem can never
|
||||
* be upgraded. All caller must already cleanly handle this case.
|
||||
*/
|
||||
return (0);
|
||||
#else
|
||||
ASSERT((struct task_struct *)
|
||||
((unsigned long)rwsem->lock.owner & ~RT_MUTEX_OWNER_MASKALL) ==
|
||||
current);
|
||||
|
||||
/*
|
||||
* Prior to 4.9.20-rt16 kernel the realtime patch series, rwsem is
|
||||
* implemented as a single mutex held by readers and writers alike.
|
||||
* However, this implementation would prevent a thread from taking
|
||||
* a read lock twice, as the mutex would already be locked on
|
||||
* the second attempt. Therefore the implementation allows a
|
||||
* single thread to take a rwsem as read lock multiple times
|
||||
* tracking that nesting as read_depth counter.
|
||||
*/
|
||||
if (rwsem->read_depth <= 1) {
|
||||
/*
|
||||
* In case, the current thread has not taken the lock
|
||||
* more than once as read lock, we can allow an
|
||||
* upgrade to a write lock. rwsem_rt.h implements
|
||||
* write locks as read_depth == 0.
|
||||
*/
|
||||
rwsem->read_depth = 0;
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
#endif
|
||||
}
|
||||
#elif defined(CONFIG_RWSEM_GENERIC_SPINLOCK)
|
||||
static int
|
||||
__rwsem_tryupgrade(struct rw_semaphore *rwsem)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long flags;
|
||||
spl_rwsem_lock_irqsave(&rwsem->wait_lock, flags);
|
||||
if (RWSEM_COUNT(rwsem) == SPL_RWSEM_SINGLE_READER_VALUE &&
|
||||
list_empty(&rwsem->wait_list)) {
|
||||
ret = 1;
|
||||
RWSEM_COUNT(rwsem) = SPL_RWSEM_SINGLE_WRITER_VALUE;
|
||||
}
|
||||
spl_rwsem_unlock_irqrestore(&rwsem->wait_lock, flags);
|
||||
return (ret);
|
||||
}
|
||||
#elif defined(RWSEM_ACTIVE_MASK)
|
||||
#if defined(HAVE_RWSEM_ATOMIC_LONG_COUNT)
|
||||
static int
|
||||
__rwsem_tryupgrade(struct rw_semaphore *rwsem)
|
||||
{
|
||||
long val;
|
||||
val = atomic_long_cmpxchg(&rwsem->count, SPL_RWSEM_SINGLE_READER_VALUE,
|
||||
SPL_RWSEM_SINGLE_WRITER_VALUE);
|
||||
return (val == SPL_RWSEM_SINGLE_READER_VALUE);
|
||||
}
|
||||
#else
|
||||
static int
|
||||
__rwsem_tryupgrade(struct rw_semaphore *rwsem)
|
||||
{
|
||||
typeof(rwsem->count) val;
|
||||
val = cmpxchg(&rwsem->count, SPL_RWSEM_SINGLE_READER_VALUE,
|
||||
SPL_RWSEM_SINGLE_WRITER_VALUE);
|
||||
return (val == SPL_RWSEM_SINGLE_READER_VALUE);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
static int
|
||||
__rwsem_tryupgrade(struct rw_semaphore *rwsem)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
rwsem_tryupgrade(struct rw_semaphore *rwsem)
|
||||
{
|
||||
if (__rwsem_tryupgrade(rwsem)) {
|
||||
rwsem_release(&rwsem->dep_map, 1, _RET_IP_);
|
||||
rwsem_acquire(&rwsem->dep_map, 0, 1, _RET_IP_);
|
||||
#ifdef CONFIG_RWSEM_SPIN_ON_OWNER
|
||||
rwsem->owner = current;
|
||||
#endif
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
EXPORT_SYMBOL(rwsem_tryupgrade);
|
||||
|
||||
int spl_rw_init(void) { return 0; }
|
||||
void spl_rw_fini(void) { }
|
||||
+4
-20
@@ -24,6 +24,7 @@
|
||||
* Solaris Porting Layer (SPL) Task Queue Implementation.
|
||||
*/
|
||||
|
||||
#include <sys/timer.h>
|
||||
#include <sys/taskq.h>
|
||||
#include <sys/kmem.h>
|
||||
#include <sys/tsd.h>
|
||||
@@ -242,20 +243,13 @@ task_expire_impl(taskq_ent_t *t)
|
||||
wake_up(&tq->tq_work_waitq);
|
||||
}
|
||||
|
||||
#ifdef HAVE_KERNEL_TIMER_FUNCTION_TIMER_LIST
|
||||
static void
|
||||
task_expire(struct timer_list *tl)
|
||||
task_expire(spl_timer_list_t tl)
|
||||
{
|
||||
taskq_ent_t *t = from_timer(t, tl, tqent_timer);
|
||||
struct timer_list *tmr = (struct timer_list *)tl;
|
||||
taskq_ent_t *t = from_timer(t, tmr, tqent_timer);
|
||||
task_expire_impl(t);
|
||||
}
|
||||
#else
|
||||
static void
|
||||
task_expire(unsigned long data)
|
||||
{
|
||||
task_expire_impl((taskq_ent_t *)data);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Returns the lowest incomplete taskqid_t. The taskqid_t may
|
||||
@@ -597,9 +591,6 @@ taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t flags)
|
||||
t->tqent_func = func;
|
||||
t->tqent_arg = arg;
|
||||
t->tqent_taskq = tq;
|
||||
#ifndef HAVE_KERNEL_TIMER_FUNCTION_TIMER_LIST
|
||||
t->tqent_timer.data = 0;
|
||||
#endif
|
||||
t->tqent_timer.function = NULL;
|
||||
t->tqent_timer.expires = 0;
|
||||
t->tqent_birth = jiffies;
|
||||
@@ -649,9 +640,6 @@ taskq_dispatch_delay(taskq_t *tq, task_func_t func, void *arg,
|
||||
t->tqent_func = func;
|
||||
t->tqent_arg = arg;
|
||||
t->tqent_taskq = tq;
|
||||
#ifndef HAVE_KERNEL_TIMER_FUNCTION_TIMER_LIST
|
||||
t->tqent_timer.data = (unsigned long)t;
|
||||
#endif
|
||||
t->tqent_timer.function = task_expire;
|
||||
t->tqent_timer.expires = (unsigned long)expire_time;
|
||||
add_timer(&t->tqent_timer);
|
||||
@@ -744,11 +732,7 @@ taskq_init_ent(taskq_ent_t *t)
|
||||
{
|
||||
spin_lock_init(&t->tqent_lock);
|
||||
init_waitqueue_head(&t->tqent_waitq);
|
||||
#ifdef HAVE_KERNEL_TIMER_FUNCTION_TIMER_LIST
|
||||
timer_setup(&t->tqent_timer, NULL, 0);
|
||||
#else
|
||||
init_timer(&t->tqent_timer);
|
||||
#endif
|
||||
INIT_LIST_HEAD(&t->tqent_list);
|
||||
t->tqent_id = 0;
|
||||
t->tqent_func = NULL;
|
||||
|
||||
@@ -153,8 +153,9 @@ spl_kthread_create(int (*func)(void *), void *data, const char namefmt[], ...)
|
||||
if (PTR_ERR(tsk) == -ENOMEM)
|
||||
continue;
|
||||
return (NULL);
|
||||
} else
|
||||
} else {
|
||||
return (tsk);
|
||||
}
|
||||
} while (1);
|
||||
}
|
||||
EXPORT_SYMBOL(spl_kthread_create);
|
||||
|
||||
@@ -641,64 +641,6 @@ vn_areleasef(int fd, uf_info_t *fip)
|
||||
} /* releasef() */
|
||||
EXPORT_SYMBOL(areleasef);
|
||||
|
||||
|
||||
static void
|
||||
vn_set_fs_pwd(struct fs_struct *fs, struct path *path)
|
||||
{
|
||||
struct path old_pwd;
|
||||
|
||||
#ifdef HAVE_FS_STRUCT_SPINLOCK
|
||||
spin_lock(&fs->lock);
|
||||
old_pwd = fs->pwd;
|
||||
fs->pwd = *path;
|
||||
path_get(path);
|
||||
spin_unlock(&fs->lock);
|
||||
#else
|
||||
write_lock(&fs->lock);
|
||||
old_pwd = fs->pwd;
|
||||
fs->pwd = *path;
|
||||
path_get(path);
|
||||
write_unlock(&fs->lock);
|
||||
#endif /* HAVE_FS_STRUCT_SPINLOCK */
|
||||
|
||||
if (old_pwd.dentry)
|
||||
path_put(&old_pwd);
|
||||
}
|
||||
|
||||
int
|
||||
vn_set_pwd(const char *filename)
|
||||
{
|
||||
struct path path;
|
||||
mm_segment_t saved_fs;
|
||||
int rc;
|
||||
|
||||
/*
|
||||
* user_path_dir() and __user_walk() both expect 'filename' to be
|
||||
* a user space address so we must briefly increase the data segment
|
||||
* size to ensure strncpy_from_user() does not fail with -EFAULT.
|
||||
*/
|
||||
saved_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
rc = user_path_dir(filename, &path);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
rc = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS);
|
||||
if (rc)
|
||||
goto dput_and_out;
|
||||
|
||||
vn_set_fs_pwd(current->fs, &path);
|
||||
|
||||
dput_and_out:
|
||||
path_put(&path);
|
||||
out:
|
||||
set_fs(saved_fs);
|
||||
|
||||
return (-rc);
|
||||
} /* vn_set_pwd() */
|
||||
EXPORT_SYMBOL(vn_set_pwd);
|
||||
|
||||
static int
|
||||
vn_cache_constructor(void *buf, void *cdrarg, int kmflags)
|
||||
{
|
||||
|
||||
@@ -592,8 +592,9 @@ fletcher_4_incremental_byteswap(void *buf, size_t size, void *data)
|
||||
}
|
||||
|
||||
#if defined(_KERNEL)
|
||||
/* Fletcher 4 kstats */
|
||||
|
||||
/*
|
||||
* Fletcher 4 kstats
|
||||
*/
|
||||
static int
|
||||
fletcher_4_kstat_headers(char *buf, size_t size)
|
||||
{
|
||||
@@ -669,7 +670,6 @@ fletcher_4_benchmark_impl(boolean_t native, char *data, uint64_t data_size)
|
||||
zio_cksum_t zc;
|
||||
uint32_t i, l, sel_save = IMPL_READ(fletcher_4_impl_chosen);
|
||||
|
||||
|
||||
fletcher_checksum_func_t *fletcher_4_test = native ?
|
||||
fletcher_4_native : fletcher_4_byteswap;
|
||||
|
||||
|
||||
@@ -232,6 +232,27 @@ entity_namecheck(const char *path, namecheck_err_t *why, char *what)
|
||||
}
|
||||
}
|
||||
|
||||
if (*end == '\0' || *end == '/') {
|
||||
int component_length = end - start;
|
||||
/* Validate the contents of this component is not '.' */
|
||||
if (component_length == 1) {
|
||||
if (start[0] == '.') {
|
||||
if (why)
|
||||
*why = NAME_ERR_SELF_REF;
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Validate the content of this component is not '..' */
|
||||
if (component_length == 2) {
|
||||
if (start[0] == '.' && start[1] == '.') {
|
||||
if (why)
|
||||
*why = NAME_ERR_PARENT_REF;
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Snapshot or bookmark delimiter found */
|
||||
if (*end == '@' || *end == '#') {
|
||||
/* Multiple delimiters are not allowed */
|
||||
|
||||
@@ -1370,8 +1370,10 @@ abd_raidz_gen_iterate(abd_t **cabds, abd_t *dabd,
|
||||
switch (parity) {
|
||||
case 3:
|
||||
len = MIN(caiters[2].iter_mapsize, len);
|
||||
/* falls through */
|
||||
case 2:
|
||||
len = MIN(caiters[1].iter_mapsize, len);
|
||||
/* falls through */
|
||||
case 1:
|
||||
len = MIN(caiters[0].iter_mapsize, len);
|
||||
}
|
||||
@@ -1461,9 +1463,11 @@ abd_raidz_rec_iterate(abd_t **cabds, abd_t **tabds,
|
||||
case 3:
|
||||
len = MIN(xiters[2].iter_mapsize, len);
|
||||
len = MIN(citers[2].iter_mapsize, len);
|
||||
/* falls through */
|
||||
case 2:
|
||||
len = MIN(xiters[1].iter_mapsize, len);
|
||||
len = MIN(citers[1].iter_mapsize, len);
|
||||
/* falls through */
|
||||
case 1:
|
||||
len = MIN(xiters[0].iter_mapsize, len);
|
||||
len = MIN(citers[0].iter_mapsize, len);
|
||||
|
||||
+20
-10
@@ -21,7 +21,7 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, Joyent, Inc.
|
||||
* Copyright (c) 2011, 2018 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2019 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2014 by Saso Kiselkov. All rights reserved.
|
||||
* Copyright 2017 Nexenta Systems, Inc. All rights reserved.
|
||||
*/
|
||||
@@ -1872,7 +1872,8 @@ arc_buf_try_copy_decompressed_data(arc_buf_t *buf)
|
||||
* There were no decompressed bufs, so there should not be a
|
||||
* checksum on the hdr either.
|
||||
*/
|
||||
EQUIV(!copied, hdr->b_l1hdr.b_freeze_cksum == NULL);
|
||||
if (zfs_flags & ZFS_DEBUG_MODIFY)
|
||||
EQUIV(!copied, hdr->b_l1hdr.b_freeze_cksum == NULL);
|
||||
|
||||
return (copied);
|
||||
}
|
||||
@@ -2253,7 +2254,6 @@ arc_buf_fill(arc_buf_t *buf, spa_t *spa, const zbookmark_phys_t *zb,
|
||||
*/
|
||||
if (arc_buf_try_copy_decompressed_data(buf)) {
|
||||
/* Skip byteswapping and checksumming (already done) */
|
||||
ASSERT3P(hdr->b_l1hdr.b_freeze_cksum, !=, NULL);
|
||||
return (0);
|
||||
} else {
|
||||
error = zio_decompress_data(HDR_GET_COMPRESS(hdr),
|
||||
@@ -4801,8 +4801,6 @@ arc_reduce_target_size(int64_t to_free)
|
||||
if (c > to_free && c - to_free > arc_c_min) {
|
||||
arc_c = c - to_free;
|
||||
atomic_add_64(&arc_p, -(arc_p >> arc_shrink_shift));
|
||||
if (asize < arc_c)
|
||||
arc_c = MAX(asize, arc_c_min);
|
||||
if (arc_p > arc_c)
|
||||
arc_p = (arc_c >> 1);
|
||||
ASSERT(arc_c >= arc_c_min);
|
||||
@@ -5081,6 +5079,9 @@ arc_kmem_reap_soon(void)
|
||||
static boolean_t
|
||||
arc_adjust_cb_check(void *arg, zthr_t *zthr)
|
||||
{
|
||||
if (!arc_initialized)
|
||||
return (B_FALSE);
|
||||
|
||||
/*
|
||||
* This is necessary so that any changes which may have been made to
|
||||
* many of the zfs_arc_* module parameters will be propagated to
|
||||
@@ -5168,6 +5169,9 @@ arc_adjust_cb(void *arg, zthr_t *zthr)
|
||||
static boolean_t
|
||||
arc_reap_cb_check(void *arg, zthr_t *zthr)
|
||||
{
|
||||
if (!arc_initialized)
|
||||
return (B_FALSE);
|
||||
|
||||
int64_t free_memory = arc_available_memory();
|
||||
|
||||
/*
|
||||
@@ -5608,7 +5612,7 @@ arc_get_data_impl(arc_buf_hdr_t *hdr, uint64_t size, void *tag)
|
||||
* If we are growing the cache, and we are adding anonymous
|
||||
* data, and we have outgrown arc_p, update arc_p
|
||||
*/
|
||||
if (aggsum_compare(&arc_size, arc_c) < 0 &&
|
||||
if (aggsum_upper_bound(&arc_size) < arc_c &&
|
||||
hdr->b_l1hdr.b_state == arc_anon &&
|
||||
(zfs_refcount_count(&arc_anon->arcs_size) +
|
||||
zfs_refcount_count(&arc_mru->arcs_size) > arc_p))
|
||||
@@ -7926,11 +7930,9 @@ arc_fini(void)
|
||||
|
||||
list_destroy(&arc_prune_list);
|
||||
mutex_destroy(&arc_prune_mtx);
|
||||
(void) zthr_cancel(arc_adjust_zthr);
|
||||
zthr_destroy(arc_adjust_zthr);
|
||||
|
||||
(void) zthr_cancel(arc_adjust_zthr);
|
||||
(void) zthr_cancel(arc_reap_zthr);
|
||||
zthr_destroy(arc_reap_zthr);
|
||||
|
||||
mutex_destroy(&arc_adjust_lock);
|
||||
cv_destroy(&arc_adjust_waiters_cv);
|
||||
@@ -7943,6 +7945,14 @@ arc_fini(void)
|
||||
buf_fini();
|
||||
arc_state_fini();
|
||||
|
||||
/*
|
||||
* We destroy the zthrs after all the ARC state has been
|
||||
* torn down to avoid the case of them receiving any
|
||||
* wakeup() signals after they are destroyed.
|
||||
*/
|
||||
zthr_destroy(arc_adjust_zthr);
|
||||
zthr_destroy(arc_reap_zthr);
|
||||
|
||||
ASSERT0(arc_loaned_bytes);
|
||||
}
|
||||
|
||||
@@ -8760,7 +8770,7 @@ l2arc_apply_transforms(spa_t *spa, arc_buf_hdr_t *hdr, uint64_t asize,
|
||||
|
||||
/*
|
||||
* If this data simply needs its own buffer, we simply allocate it
|
||||
* and copy the data. This may be done to elimiate a depedency on a
|
||||
* and copy the data. This may be done to eliminate a dependency on a
|
||||
* shared buffer or to reallocate the buffer to match asize.
|
||||
*/
|
||||
if (HDR_HAS_RABD(hdr) && asize != psize) {
|
||||
|
||||
+2
-1
@@ -2591,7 +2591,8 @@ dbuf_destroy(dmu_buf_impl_t *db)
|
||||
if (db->db_blkid != DMU_BONUS_BLKID) {
|
||||
boolean_t needlock = !MUTEX_HELD(&dn->dn_dbufs_mtx);
|
||||
if (needlock)
|
||||
mutex_enter(&dn->dn_dbufs_mtx);
|
||||
mutex_enter_nested(&dn->dn_dbufs_mtx,
|
||||
NESTED_SINGLE);
|
||||
avl_remove(&dn->dn_dbufs, db);
|
||||
atomic_dec_32(&dn->dn_dbufs_count);
|
||||
membar_producer();
|
||||
|
||||
+13
-1
@@ -21,6 +21,7 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018 by Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <sys/zfs_context.h>
|
||||
@@ -117,7 +118,18 @@ ddt_zap_walk(objset_t *os, uint64_t object, ddt_entry_t *dde, uint64_t *walk)
|
||||
zap_attribute_t za;
|
||||
int error;
|
||||
|
||||
zap_cursor_init_serialized(&zc, os, object, *walk);
|
||||
if (*walk == 0) {
|
||||
/*
|
||||
* We don't want to prefetch the entire ZAP object, because
|
||||
* it can be enormous. Also the primary use of DDT iteration
|
||||
* is for scrubbing, in which case we will be issuing many
|
||||
* scrub I/Os for each ZAP block that we read in, so
|
||||
* reading the ZAP is unlikely to be the bottleneck.
|
||||
*/
|
||||
zap_cursor_init_noprefetch(&zc, os, object);
|
||||
} else {
|
||||
zap_cursor_init_serialized(&zc, os, object, *walk);
|
||||
}
|
||||
if ((error = zap_cursor_retrieve(&zc, &za)) == 0) {
|
||||
uchar_t cbuf[sizeof (dde->dde_phys) + 1];
|
||||
uint64_t csize = za.za_num_integers;
|
||||
|
||||
@@ -81,6 +81,13 @@ int zfs_dmu_offset_next_sync = 0;
|
||||
*/
|
||||
int zfs_object_remap_one_indirect_delay_ms = 0;
|
||||
|
||||
/*
|
||||
* Limit the amount we can prefetch with one call to this amount. This
|
||||
* helps to limit the amount of memory that can be used by prefetching.
|
||||
* Larger objects should be prefetched a bit at a time.
|
||||
*/
|
||||
int dmu_prefetch_max = 8 * SPA_MAXBLOCKSIZE;
|
||||
|
||||
const dmu_object_type_info_t dmu_ot[DMU_OT_NUMTYPES] = {
|
||||
{DMU_BSWAP_UINT8, TRUE, FALSE, FALSE, "unallocated" },
|
||||
{DMU_BSWAP_ZAP, TRUE, TRUE, FALSE, "object directory" },
|
||||
@@ -667,6 +674,11 @@ dmu_prefetch(objset_t *os, uint64_t object, int64_t level, uint64_t offset,
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* See comment before the definition of dmu_prefetch_max.
|
||||
*/
|
||||
len = MIN(len, dmu_prefetch_max);
|
||||
|
||||
/*
|
||||
* XXX - Note, if the dnode for the requested object is not
|
||||
* already cached, we will do a *synchronous* read in the
|
||||
@@ -2629,6 +2641,10 @@ module_param(zfs_dmu_offset_next_sync, int, 0644);
|
||||
MODULE_PARM_DESC(zfs_dmu_offset_next_sync,
|
||||
"Enable forcing txg sync to find holes");
|
||||
|
||||
module_param(dmu_prefetch_max, int, 0644);
|
||||
MODULE_PARM_DESC(dmu_prefetch_max,
|
||||
"Limit one prefetch call to this size");
|
||||
|
||||
/* END CSTYLED */
|
||||
|
||||
#endif
|
||||
|
||||
+14
-12
@@ -1348,13 +1348,6 @@ dmu_objset_clone_check(void *arg, dmu_tx_t *tx)
|
||||
return (SET_ERROR(EINVAL));
|
||||
}
|
||||
|
||||
error = dmu_objset_clone_crypt_check(pdd, origin->ds_dir);
|
||||
if (error != 0) {
|
||||
dsl_dataset_rele(origin, FTAG);
|
||||
dsl_dir_rele(pdd, FTAG);
|
||||
return (error);
|
||||
}
|
||||
|
||||
dsl_dataset_rele(origin, FTAG);
|
||||
dsl_dir_rele(pdd, FTAG);
|
||||
|
||||
@@ -1699,6 +1692,8 @@ dmu_objset_sync(objset_t *os, zio_t *pio, dmu_tx_t *tx)
|
||||
zio_t *zio;
|
||||
list_t *list;
|
||||
dbuf_dirty_record_t *dr;
|
||||
int num_sublists;
|
||||
multilist_t *ml;
|
||||
blkptr_t *blkptr_copy = kmem_alloc(sizeof (*os->os_rootbp), KM_SLEEP);
|
||||
*blkptr_copy = *os->os_rootbp;
|
||||
|
||||
@@ -1787,10 +1782,13 @@ dmu_objset_sync(objset_t *os, zio_t *pio, dmu_tx_t *tx)
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0;
|
||||
i < multilist_get_num_sublists(os->os_dirty_dnodes[txgoff]); i++) {
|
||||
ml = os->os_dirty_dnodes[txgoff];
|
||||
num_sublists = multilist_get_num_sublists(ml);
|
||||
for (int i = 0; i < num_sublists; i++) {
|
||||
if (multilist_sublist_is_empty_idx(ml, i))
|
||||
continue;
|
||||
sync_dnodes_arg_t *sda = kmem_alloc(sizeof (*sda), KM_SLEEP);
|
||||
sda->sda_list = os->os_dirty_dnodes[txgoff];
|
||||
sda->sda_list = ml;
|
||||
sda->sda_sublist_idx = i;
|
||||
sda->sda_tx = tx;
|
||||
(void) taskq_dispatch(dmu_objset_pool(os)->dp_sync_taskq,
|
||||
@@ -2093,6 +2091,8 @@ userquota_updates_task(void *arg)
|
||||
void
|
||||
dmu_objset_do_userquota_updates(objset_t *os, dmu_tx_t *tx)
|
||||
{
|
||||
int num_sublists;
|
||||
|
||||
if (!dmu_objset_userused_enabled(os))
|
||||
return;
|
||||
|
||||
@@ -2125,8 +2125,10 @@ dmu_objset_do_userquota_updates(objset_t *os, dmu_tx_t *tx)
|
||||
DMU_OT_USERGROUP_USED, DMU_OT_NONE, 0, tx));
|
||||
}
|
||||
|
||||
for (int i = 0;
|
||||
i < multilist_get_num_sublists(os->os_synced_dnodes); i++) {
|
||||
num_sublists = multilist_get_num_sublists(os->os_synced_dnodes);
|
||||
for (int i = 0; i < num_sublists; i++) {
|
||||
if (multilist_sublist_is_empty_idx(os->os_synced_dnodes, i))
|
||||
continue;
|
||||
userquota_updates_arg_t *uua =
|
||||
kmem_alloc(sizeof (*uua), KM_SLEEP);
|
||||
uua->uua_os = os;
|
||||
|
||||
+19
-15
@@ -86,21 +86,25 @@ recv_begin_check_existing_impl(dmu_recv_begin_arg_t *drba, dsl_dataset_t *ds,
|
||||
boolean_t raw = (featureflags & DMU_BACKUP_FEATURE_RAW) != 0;
|
||||
boolean_t embed = (featureflags & DMU_BACKUP_FEATURE_EMBED_DATA) != 0;
|
||||
|
||||
/* temporary clone name must not exist */
|
||||
/* Temporary clone name must not exist. */
|
||||
error = zap_lookup(dp->dp_meta_objset,
|
||||
dsl_dir_phys(ds->ds_dir)->dd_child_dir_zapobj, recv_clone_name,
|
||||
8, 1, &val);
|
||||
if (error != ENOENT)
|
||||
return (error == 0 ? EBUSY : error);
|
||||
|
||||
/* new snapshot name must not exist */
|
||||
/* Resume state must not be set. */
|
||||
if (dsl_dataset_has_resume_receive_state(ds))
|
||||
return (SET_ERROR(EBUSY));
|
||||
|
||||
/* New snapshot name must not exist. */
|
||||
error = zap_lookup(dp->dp_meta_objset,
|
||||
dsl_dataset_phys(ds)->ds_snapnames_zapobj,
|
||||
drba->drba_cookie->drc_tosnap, 8, 1, &val);
|
||||
if (error != ENOENT)
|
||||
return (error == 0 ? EEXIST : error);
|
||||
|
||||
/* must not have children if receiving a ZVOL */
|
||||
/* Must not have children if receiving a ZVOL. */
|
||||
error = zap_count(dp->dp_meta_objset,
|
||||
dsl_dir_phys(ds->ds_dir)->dd_child_dir_zapobj, &children);
|
||||
if (error != 0)
|
||||
@@ -327,7 +331,7 @@ dmu_recv_begin_check(void *arg, dmu_tx_t *tx)
|
||||
/* Open the parent of tofs */
|
||||
ASSERT3U(strlen(tofs), <, sizeof (buf));
|
||||
(void) strlcpy(buf, tofs, strrchr(tofs, '/') - tofs + 1);
|
||||
error = dsl_dataset_hold_flags(dp, buf, dsflags, FTAG, &ds);
|
||||
error = dsl_dataset_hold(dp, buf, FTAG, &ds);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
@@ -345,13 +349,13 @@ dmu_recv_begin_check(void *arg, dmu_tx_t *tx)
|
||||
error = dmu_objset_create_crypt_check(ds->ds_dir,
|
||||
drba->drba_dcp, &will_encrypt);
|
||||
if (error != 0) {
|
||||
dsl_dataset_rele_flags(ds, dsflags, FTAG);
|
||||
dsl_dataset_rele(ds, FTAG);
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (will_encrypt &&
|
||||
(featureflags & DMU_BACKUP_FEATURE_EMBED_DATA)) {
|
||||
dsl_dataset_rele_flags(ds, dsflags, FTAG);
|
||||
dsl_dataset_rele(ds, FTAG);
|
||||
return (SET_ERROR(EINVAL));
|
||||
}
|
||||
}
|
||||
@@ -364,25 +368,25 @@ dmu_recv_begin_check(void *arg, dmu_tx_t *tx)
|
||||
error = dsl_fs_ss_limit_check(ds->ds_dir, 1,
|
||||
ZFS_PROP_FILESYSTEM_LIMIT, NULL, drba->drba_cred);
|
||||
if (error != 0) {
|
||||
dsl_dataset_rele_flags(ds, dsflags, FTAG);
|
||||
dsl_dataset_rele(ds, FTAG);
|
||||
return (error);
|
||||
}
|
||||
|
||||
error = dsl_fs_ss_limit_check(ds->ds_dir, 1,
|
||||
ZFS_PROP_SNAPSHOT_LIMIT, NULL, drba->drba_cred);
|
||||
if (error != 0) {
|
||||
dsl_dataset_rele_flags(ds, dsflags, FTAG);
|
||||
dsl_dataset_rele(ds, FTAG);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/* can't recv below anything but filesystems (eg. no ZVOLs) */
|
||||
error = dmu_objset_from_ds(ds, &os);
|
||||
if (error != 0) {
|
||||
dsl_dataset_rele_flags(ds, dsflags, FTAG);
|
||||
dsl_dataset_rele(ds, FTAG);
|
||||
return (error);
|
||||
}
|
||||
if (dmu_objset_type(os) != DMU_OST_ZFS) {
|
||||
dsl_dataset_rele_flags(ds, dsflags, FTAG);
|
||||
dsl_dataset_rele(ds, FTAG);
|
||||
return (SET_ERROR(ZFS_ERR_WRONG_PARENT));
|
||||
}
|
||||
|
||||
@@ -392,31 +396,31 @@ dmu_recv_begin_check(void *arg, dmu_tx_t *tx)
|
||||
error = dsl_dataset_hold_flags(dp, drba->drba_origin,
|
||||
dsflags, FTAG, &origin);
|
||||
if (error != 0) {
|
||||
dsl_dataset_rele_flags(ds, dsflags, FTAG);
|
||||
dsl_dataset_rele(ds, FTAG);
|
||||
return (error);
|
||||
}
|
||||
if (!origin->ds_is_snapshot) {
|
||||
dsl_dataset_rele_flags(origin, dsflags, FTAG);
|
||||
dsl_dataset_rele_flags(ds, dsflags, FTAG);
|
||||
dsl_dataset_rele(ds, FTAG);
|
||||
return (SET_ERROR(EINVAL));
|
||||
}
|
||||
if (dsl_dataset_phys(origin)->ds_guid != fromguid &&
|
||||
fromguid != 0) {
|
||||
dsl_dataset_rele_flags(origin, dsflags, FTAG);
|
||||
dsl_dataset_rele_flags(ds, dsflags, FTAG);
|
||||
dsl_dataset_rele(ds, FTAG);
|
||||
return (SET_ERROR(ENODEV));
|
||||
}
|
||||
if (origin->ds_dir->dd_crypto_obj != 0 &&
|
||||
(featureflags & DMU_BACKUP_FEATURE_EMBED_DATA)) {
|
||||
dsl_dataset_rele_flags(origin, dsflags, FTAG);
|
||||
dsl_dataset_rele_flags(ds, dsflags, FTAG);
|
||||
dsl_dataset_rele(ds, FTAG);
|
||||
return (SET_ERROR(EINVAL));
|
||||
}
|
||||
dsl_dataset_rele_flags(origin,
|
||||
dsflags, FTAG);
|
||||
}
|
||||
|
||||
dsl_dataset_rele_flags(ds, dsflags, FTAG);
|
||||
dsl_dataset_rele(ds, FTAG);
|
||||
error = 0;
|
||||
}
|
||||
return (error);
|
||||
|
||||
+23
-2
@@ -925,6 +925,25 @@ dmu_tx_try_assign(dmu_tx_t *tx, uint64_t txg_how)
|
||||
txh = list_next(&tx->tx_holds, txh)) {
|
||||
dnode_t *dn = txh->txh_dnode;
|
||||
if (dn != NULL) {
|
||||
/*
|
||||
* This thread can't hold the dn_struct_rwlock
|
||||
* while assigning the tx, because this can lead to
|
||||
* deadlock. Specifically, if this dnode is already
|
||||
* assigned to an earlier txg, this thread may need
|
||||
* to wait for that txg to sync (the ERESTART case
|
||||
* below). The other thread that has assigned this
|
||||
* dnode to an earlier txg prevents this txg from
|
||||
* syncing until its tx can complete (calling
|
||||
* dmu_tx_commit()), but it may need to acquire the
|
||||
* dn_struct_rwlock to do so (e.g. via
|
||||
* dmu_buf_hold*()).
|
||||
*
|
||||
* Note that this thread can't hold the lock for
|
||||
* read either, but the rwlock doesn't record
|
||||
* enough information to make that assertion.
|
||||
*/
|
||||
ASSERT(!RW_WRITE_HELD(&dn->dn_struct_rwlock));
|
||||
|
||||
mutex_enter(&dn->dn_mtx);
|
||||
if (dn->dn_assigned_txg == tx->tx_txg - 1) {
|
||||
mutex_exit(&dn->dn_mtx);
|
||||
@@ -1319,7 +1338,10 @@ dmu_tx_hold_sa(dmu_tx_t *tx, sa_handle_t *hdl, boolean_t may_grow)
|
||||
|
||||
object = sa_handle_object(hdl);
|
||||
|
||||
dmu_tx_hold_bonus(tx, object);
|
||||
dmu_buf_impl_t *db = (dmu_buf_impl_t *)hdl->sa_bonus;
|
||||
DB_DNODE_ENTER(db);
|
||||
dmu_tx_hold_bonus_by_dnode(tx, DB_DNODE(db));
|
||||
DB_DNODE_EXIT(db);
|
||||
|
||||
if (tx->tx_objset->os_sa->sa_master_obj == 0)
|
||||
return;
|
||||
@@ -1341,7 +1363,6 @@ dmu_tx_hold_sa(dmu_tx_t *tx, sa_handle_t *hdl, boolean_t may_grow)
|
||||
ASSERT(tx->tx_txg == 0);
|
||||
dmu_tx_hold_spill(tx, object);
|
||||
} else {
|
||||
dmu_buf_impl_t *db = (dmu_buf_impl_t *)hdl->sa_bonus;
|
||||
dnode_t *dn;
|
||||
|
||||
DB_DNODE_ENTER(db);
|
||||
|
||||
+47
-12
@@ -55,7 +55,6 @@ dnode_stats_t dnode_stats = {
|
||||
{ "dnode_hold_free_lock_retry", KSTAT_DATA_UINT64 },
|
||||
{ "dnode_hold_free_overflow", KSTAT_DATA_UINT64 },
|
||||
{ "dnode_hold_free_refcount", KSTAT_DATA_UINT64 },
|
||||
{ "dnode_hold_free_txg", KSTAT_DATA_UINT64 },
|
||||
{ "dnode_free_interior_lock_retry", KSTAT_DATA_UINT64 },
|
||||
{ "dnode_allocate", KSTAT_DATA_UINT64 },
|
||||
{ "dnode_reallocate", KSTAT_DATA_UINT64 },
|
||||
@@ -1255,6 +1254,10 @@ dnode_buf_evict_async(void *dbu)
|
||||
* as an extra dnode slot by an large dnode, in which case it returns
|
||||
* ENOENT.
|
||||
*
|
||||
* If the DNODE_DRY_RUN flag is set, we don't actually hold the dnode, just
|
||||
* return whether the hold would succeed or not. tag and dnp should set to
|
||||
* NULL in this case.
|
||||
*
|
||||
* errors:
|
||||
* EINVAL - Invalid object number or flags.
|
||||
* ENOSPC - Hole too small to fulfill "slots" request (DNODE_MUST_BE_FREE)
|
||||
@@ -1283,6 +1286,7 @@ dnode_hold_impl(objset_t *os, uint64_t object, int flag, int slots,
|
||||
|
||||
ASSERT(!(flag & DNODE_MUST_BE_ALLOCATED) || (slots == 0));
|
||||
ASSERT(!(flag & DNODE_MUST_BE_FREE) || (slots > 0));
|
||||
IMPLY(flag & DNODE_DRY_RUN, (tag == NULL) && (dnp == NULL));
|
||||
|
||||
/*
|
||||
* If you are holding the spa config lock as writer, you shouldn't
|
||||
@@ -1312,8 +1316,11 @@ dnode_hold_impl(objset_t *os, uint64_t object, int flag, int slots,
|
||||
if ((flag & DNODE_MUST_BE_FREE) && type != DMU_OT_NONE)
|
||||
return (SET_ERROR(EEXIST));
|
||||
DNODE_VERIFY(dn);
|
||||
(void) zfs_refcount_add(&dn->dn_holds, tag);
|
||||
*dnp = dn;
|
||||
/* Don't actually hold if dry run, just return 0 */
|
||||
if (!(flag & DNODE_DRY_RUN)) {
|
||||
(void) zfs_refcount_add(&dn->dn_holds, tag);
|
||||
*dnp = dn;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -1455,6 +1462,14 @@ dnode_hold_impl(objset_t *os, uint64_t object, int flag, int slots,
|
||||
return (SET_ERROR(ENOENT));
|
||||
}
|
||||
|
||||
/* Don't actually hold if dry run, just return 0 */
|
||||
if (flag & DNODE_DRY_RUN) {
|
||||
mutex_exit(&dn->dn_mtx);
|
||||
dnode_slots_rele(dnc, idx, slots);
|
||||
dbuf_rele(db, FTAG);
|
||||
return (0);
|
||||
}
|
||||
|
||||
DNODE_STAT_BUMP(dnode_hold_alloc_hits);
|
||||
} else if (flag & DNODE_MUST_BE_FREE) {
|
||||
|
||||
@@ -1512,6 +1527,14 @@ dnode_hold_impl(objset_t *os, uint64_t object, int flag, int slots,
|
||||
return (SET_ERROR(EEXIST));
|
||||
}
|
||||
|
||||
/* Don't actually hold if dry run, just return 0 */
|
||||
if (flag & DNODE_DRY_RUN) {
|
||||
mutex_exit(&dn->dn_mtx);
|
||||
dnode_slots_rele(dnc, idx, slots);
|
||||
dbuf_rele(db, FTAG);
|
||||
return (0);
|
||||
}
|
||||
|
||||
dnode_set_slots(dnc, idx + 1, slots - 1, DN_SLOT_INTERIOR);
|
||||
DNODE_STAT_BUMP(dnode_hold_free_hits);
|
||||
} else {
|
||||
@@ -1519,15 +1542,7 @@ dnode_hold_impl(objset_t *os, uint64_t object, int flag, int slots,
|
||||
return (SET_ERROR(EINVAL));
|
||||
}
|
||||
|
||||
if (dn->dn_free_txg) {
|
||||
DNODE_STAT_BUMP(dnode_hold_free_txg);
|
||||
type = dn->dn_type;
|
||||
mutex_exit(&dn->dn_mtx);
|
||||
dnode_slots_rele(dnc, idx, slots);
|
||||
dbuf_rele(db, FTAG);
|
||||
return (SET_ERROR((flag & DNODE_MUST_BE_ALLOCATED) ?
|
||||
ENOENT : EEXIST));
|
||||
}
|
||||
ASSERT0(dn->dn_free_txg);
|
||||
|
||||
if (zfs_refcount_add(&dn->dn_holds, tag) == 1)
|
||||
dbuf_add_ref(db, dnh);
|
||||
@@ -1618,6 +1633,16 @@ dnode_rele_and_unlock(dnode_t *dn, void *tag, boolean_t evicting)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Test whether we can create a dnode at the specified location.
|
||||
*/
|
||||
int
|
||||
dnode_try_claim(objset_t *os, uint64_t object, int slots)
|
||||
{
|
||||
return (dnode_hold_impl(os, object, DNODE_MUST_BE_FREE | DNODE_DRY_RUN,
|
||||
slots, NULL, NULL));
|
||||
}
|
||||
|
||||
void
|
||||
dnode_setdirty(dnode_t *dn, dmu_tx_t *tx)
|
||||
{
|
||||
@@ -2483,3 +2508,13 @@ out:
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
#if defined(_KERNEL)
|
||||
EXPORT_SYMBOL(dnode_hold);
|
||||
EXPORT_SYMBOL(dnode_rele);
|
||||
EXPORT_SYMBOL(dnode_set_nlevels);
|
||||
EXPORT_SYMBOL(dnode_set_blksz);
|
||||
EXPORT_SYMBOL(dnode_free_range);
|
||||
EXPORT_SYMBOL(dnode_evict_dbufs);
|
||||
EXPORT_SYMBOL(dnode_evict_bonus);
|
||||
#endif
|
||||
|
||||
+14
-50
@@ -1610,15 +1610,8 @@ dsl_dir_rename_crypt_check(dsl_dir_t *dd, dsl_dir_t *newparent)
|
||||
int ret;
|
||||
uint64_t curr_rddobj, parent_rddobj;
|
||||
|
||||
if (dd->dd_crypto_obj == 0) {
|
||||
/* children of encrypted parents must be encrypted */
|
||||
if (newparent->dd_crypto_obj != 0) {
|
||||
ret = SET_ERROR(EACCES);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (dd->dd_crypto_obj == 0)
|
||||
return (0);
|
||||
}
|
||||
|
||||
ret = dsl_dir_get_encryption_root_ddobj(dd, &curr_rddobj);
|
||||
if (ret != 0)
|
||||
@@ -1683,11 +1676,15 @@ dsl_dataset_promote_crypt_check(dsl_dir_t *target, dsl_dir_t *origin)
|
||||
* Check that the parent of the target has the same encryption root.
|
||||
*/
|
||||
ret = dsl_dir_get_encryption_root_ddobj(origin->dd_parent, &op_rddobj);
|
||||
if (ret != 0)
|
||||
if (ret == ENOENT)
|
||||
return (SET_ERROR(EACCES));
|
||||
else if (ret != 0)
|
||||
return (ret);
|
||||
|
||||
ret = dsl_dir_get_encryption_root_ddobj(target->dd_parent, &tp_rddobj);
|
||||
if (ret != 0)
|
||||
if (ret == ENOENT)
|
||||
return (SET_ERROR(EACCES));
|
||||
else if (ret != 0)
|
||||
return (ret);
|
||||
|
||||
if (op_rddobj != tp_rddobj)
|
||||
@@ -1747,34 +1744,6 @@ dsl_dataset_promote_crypt_sync(dsl_dir_t *target, dsl_dir_t *origin,
|
||||
kmem_free(keylocation, ZAP_MAXVALUELEN);
|
||||
}
|
||||
|
||||
int
|
||||
dmu_objset_clone_crypt_check(dsl_dir_t *parentdd, dsl_dir_t *origindd)
|
||||
{
|
||||
int ret;
|
||||
uint64_t pcrypt, crypt;
|
||||
|
||||
/*
|
||||
* Check that we are not making an unencrypted child of an
|
||||
* encrypted parent.
|
||||
*/
|
||||
ret = dsl_dir_get_crypt(parentdd, &pcrypt);
|
||||
if (ret != 0)
|
||||
return (ret);
|
||||
|
||||
ret = dsl_dir_get_crypt(origindd, &crypt);
|
||||
if (ret != 0)
|
||||
return (ret);
|
||||
|
||||
ASSERT3U(pcrypt, !=, ZIO_CRYPT_INHERIT);
|
||||
ASSERT3U(crypt, !=, ZIO_CRYPT_INHERIT);
|
||||
|
||||
if (crypt == ZIO_CRYPT_OFF && pcrypt != ZIO_CRYPT_OFF)
|
||||
return (SET_ERROR(EINVAL));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
dmu_objset_create_crypt_check(dsl_dir_t *parentdd, dsl_crypto_params_t *dcp,
|
||||
boolean_t *will_encrypt)
|
||||
@@ -1805,13 +1774,6 @@ dmu_objset_create_crypt_check(dsl_dir_t *parentdd, dsl_crypto_params_t *dcp,
|
||||
ASSERT3U(pcrypt, !=, ZIO_CRYPT_INHERIT);
|
||||
ASSERT3U(crypt, !=, ZIO_CRYPT_INHERIT);
|
||||
|
||||
/*
|
||||
* We can't create an unencrypted child of an encrypted parent
|
||||
* under any circumstances.
|
||||
*/
|
||||
if (crypt == ZIO_CRYPT_OFF && pcrypt != ZIO_CRYPT_OFF)
|
||||
return (SET_ERROR(EINVAL));
|
||||
|
||||
/* check for valid dcp with no encryption (inherited or local) */
|
||||
if (crypt == ZIO_CRYPT_OFF) {
|
||||
/* Must not specify encryption params */
|
||||
@@ -2662,11 +2624,13 @@ dsl_dataset_crypt_stats(dsl_dataset_t *ds, nvlist_t *nv)
|
||||
}
|
||||
|
||||
if (dsl_dir_get_encryption_root_ddobj(dd, &intval) == 0) {
|
||||
VERIFY0(dsl_dir_hold_obj(dd->dd_pool, intval, NULL, FTAG,
|
||||
&enc_root));
|
||||
dsl_dir_name(enc_root, buf);
|
||||
dsl_dir_rele(enc_root, FTAG);
|
||||
dsl_prop_nvlist_add_string(nv, ZFS_PROP_ENCRYPTION_ROOT, buf);
|
||||
if (dsl_dir_hold_obj(dd->dd_pool, intval, NULL, FTAG,
|
||||
&enc_root) == 0) {
|
||||
dsl_dir_name(enc_root, buf);
|
||||
dsl_dir_rele(enc_root, FTAG);
|
||||
dsl_prop_nvlist_add_string(nv,
|
||||
ZFS_PROP_ENCRYPTION_ROOT, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1059,9 +1059,10 @@ dsl_destroy_head(const char *name)
|
||||
/*
|
||||
* Head deletion is processed in one txg on old pools;
|
||||
* remove the objects from open context so that the txg sync
|
||||
* is not too long.
|
||||
* is not too long. This optimization can only work for
|
||||
* encrypted datasets if the wrapping key is loaded.
|
||||
*/
|
||||
error = dmu_objset_own(name, DMU_OST_ANY, B_FALSE, B_FALSE,
|
||||
error = dmu_objset_own(name, DMU_OST_ANY, B_FALSE, B_TRUE,
|
||||
FTAG, &os);
|
||||
if (error == 0) {
|
||||
uint64_t prev_snap_txg =
|
||||
@@ -1073,7 +1074,7 @@ dsl_destroy_head(const char *name)
|
||||
(void) dmu_free_long_object(os, obj);
|
||||
/* sync out all frees */
|
||||
txg_wait_synced(dmu_objset_pool(os), 0);
|
||||
dmu_objset_disown(os, B_FALSE, FTAG);
|
||||
dmu_objset_disown(os, B_TRUE, FTAG);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+81
-40
@@ -23,7 +23,7 @@
|
||||
* Copyright (c) 2011, 2017 by Delphix. All rights reserved.
|
||||
* Copyright 2016 Gary Mills
|
||||
* Copyright (c) 2017 Datto Inc.
|
||||
* Copyright 2017 Joyent, Inc.
|
||||
* Copyright 2019 Joyent, Inc.
|
||||
*/
|
||||
|
||||
#include <sys/dsl_scan.h>
|
||||
@@ -952,13 +952,16 @@ dsl_scan_done(dsl_scan_t *scn, boolean_t complete, dmu_tx_t *tx)
|
||||
* will find the drives that need to be resilvered
|
||||
* when the machine reboots and start the resilver then.
|
||||
*/
|
||||
boolean_t resilver_needed =
|
||||
dsl_scan_clear_deferred(spa->spa_root_vdev, tx);
|
||||
if (resilver_needed) {
|
||||
spa_history_log_internal(spa,
|
||||
"starting deferred resilver", tx,
|
||||
"errors=%llu", spa_get_errlog_size(spa));
|
||||
spa_async_request(spa, SPA_ASYNC_RESILVER);
|
||||
if (spa_feature_is_enabled(spa, SPA_FEATURE_RESILVER_DEFER)) {
|
||||
boolean_t resilver_needed =
|
||||
dsl_scan_clear_deferred(spa->spa_root_vdev, tx);
|
||||
if (resilver_needed) {
|
||||
spa_history_log_internal(spa,
|
||||
"starting deferred resilver", tx,
|
||||
"errors=%llu",
|
||||
(u_longlong_t)spa_get_errlog_size(spa));
|
||||
spa_async_request(spa, SPA_ASYNC_RESILVER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2165,16 +2168,17 @@ ds_clone_swapped_bookmark(dsl_dataset_t *ds1, dsl_dataset_t *ds2,
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when a parent dataset and its clone are swapped. If we were
|
||||
* Called when an origin dataset and its clone are swapped. If we were
|
||||
* currently traversing the dataset, we need to switch to traversing the
|
||||
* newly promoted parent.
|
||||
* newly promoted clone.
|
||||
*/
|
||||
void
|
||||
dsl_scan_ds_clone_swapped(dsl_dataset_t *ds1, dsl_dataset_t *ds2, dmu_tx_t *tx)
|
||||
{
|
||||
dsl_pool_t *dp = ds1->ds_dir->dd_pool;
|
||||
dsl_scan_t *scn = dp->dp_scan;
|
||||
uint64_t mintxg;
|
||||
uint64_t mintxg1, mintxg2;
|
||||
boolean_t ds1_queued, ds2_queued;
|
||||
|
||||
if (!dsl_scan_is_running(scn))
|
||||
return;
|
||||
@@ -2182,44 +2186,81 @@ dsl_scan_ds_clone_swapped(dsl_dataset_t *ds1, dsl_dataset_t *ds2, dmu_tx_t *tx)
|
||||
ds_clone_swapped_bookmark(ds1, ds2, &scn->scn_phys.scn_bookmark);
|
||||
ds_clone_swapped_bookmark(ds1, ds2, &scn->scn_phys_cached.scn_bookmark);
|
||||
|
||||
if (scan_ds_queue_contains(scn, ds1->ds_object, &mintxg)) {
|
||||
scan_ds_queue_remove(scn, ds1->ds_object);
|
||||
scan_ds_queue_insert(scn, ds2->ds_object, mintxg);
|
||||
/*
|
||||
* Handle the in-memory scan queue.
|
||||
*/
|
||||
ds1_queued = scan_ds_queue_contains(scn, ds1->ds_object, &mintxg1);
|
||||
ds2_queued = scan_ds_queue_contains(scn, ds2->ds_object, &mintxg2);
|
||||
|
||||
/* Sanity checking. */
|
||||
if (ds1_queued) {
|
||||
ASSERT3U(mintxg1, ==, dsl_dataset_phys(ds1)->ds_prev_snap_txg);
|
||||
ASSERT3U(mintxg1, ==, dsl_dataset_phys(ds2)->ds_prev_snap_txg);
|
||||
}
|
||||
if (scan_ds_queue_contains(scn, ds2->ds_object, &mintxg)) {
|
||||
scan_ds_queue_remove(scn, ds2->ds_object);
|
||||
scan_ds_queue_insert(scn, ds1->ds_object, mintxg);
|
||||
if (ds2_queued) {
|
||||
ASSERT3U(mintxg2, ==, dsl_dataset_phys(ds1)->ds_prev_snap_txg);
|
||||
ASSERT3U(mintxg2, ==, dsl_dataset_phys(ds2)->ds_prev_snap_txg);
|
||||
}
|
||||
|
||||
if (zap_lookup_int_key(dp->dp_meta_objset, scn->scn_phys.scn_queue_obj,
|
||||
ds1->ds_object, &mintxg) == 0) {
|
||||
int err;
|
||||
ASSERT3U(mintxg, ==, dsl_dataset_phys(ds1)->ds_prev_snap_txg);
|
||||
ASSERT3U(mintxg, ==, dsl_dataset_phys(ds2)->ds_prev_snap_txg);
|
||||
VERIFY3U(0, ==, zap_remove_int(dp->dp_meta_objset,
|
||||
if (ds1_queued && ds2_queued) {
|
||||
/*
|
||||
* If both are queued, we don't need to do anything.
|
||||
* The swapping code below would not handle this case correctly,
|
||||
* since we can't insert ds2 if it is already there. That's
|
||||
* because scan_ds_queue_insert() prohibits a duplicate insert
|
||||
* and panics.
|
||||
*/
|
||||
} else if (ds1_queued) {
|
||||
scan_ds_queue_remove(scn, ds1->ds_object);
|
||||
scan_ds_queue_insert(scn, ds2->ds_object, mintxg1);
|
||||
} else if (ds2_queued) {
|
||||
scan_ds_queue_remove(scn, ds2->ds_object);
|
||||
scan_ds_queue_insert(scn, ds1->ds_object, mintxg2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle the on-disk scan queue.
|
||||
* The on-disk state is an out-of-date version of the in-memory state,
|
||||
* so the in-memory and on-disk values for ds1_queued and ds2_queued may
|
||||
* be different. Therefore we need to apply the swap logic to the
|
||||
* on-disk state independently of the in-memory state.
|
||||
*/
|
||||
ds1_queued = zap_lookup_int_key(dp->dp_meta_objset,
|
||||
scn->scn_phys.scn_queue_obj, ds1->ds_object, &mintxg1) == 0;
|
||||
ds2_queued = zap_lookup_int_key(dp->dp_meta_objset,
|
||||
scn->scn_phys.scn_queue_obj, ds2->ds_object, &mintxg2) == 0;
|
||||
|
||||
/* Sanity checking. */
|
||||
if (ds1_queued) {
|
||||
ASSERT3U(mintxg1, ==, dsl_dataset_phys(ds1)->ds_prev_snap_txg);
|
||||
ASSERT3U(mintxg1, ==, dsl_dataset_phys(ds2)->ds_prev_snap_txg);
|
||||
}
|
||||
if (ds2_queued) {
|
||||
ASSERT3U(mintxg2, ==, dsl_dataset_phys(ds1)->ds_prev_snap_txg);
|
||||
ASSERT3U(mintxg2, ==, dsl_dataset_phys(ds2)->ds_prev_snap_txg);
|
||||
}
|
||||
|
||||
if (ds1_queued && ds2_queued) {
|
||||
/*
|
||||
* If both are queued, we don't need to do anything.
|
||||
* Alternatively, we could check for EEXIST from
|
||||
* zap_add_int_key() and back out to the original state, but
|
||||
* that would be more work than checking for this case upfront.
|
||||
*/
|
||||
} else if (ds1_queued) {
|
||||
VERIFY3S(0, ==, zap_remove_int(dp->dp_meta_objset,
|
||||
scn->scn_phys.scn_queue_obj, ds1->ds_object, tx));
|
||||
err = zap_add_int_key(dp->dp_meta_objset,
|
||||
scn->scn_phys.scn_queue_obj, ds2->ds_object, mintxg, tx);
|
||||
VERIFY(err == 0 || err == EEXIST);
|
||||
if (err == EEXIST) {
|
||||
/* Both were there to begin with */
|
||||
VERIFY(0 == zap_add_int_key(dp->dp_meta_objset,
|
||||
scn->scn_phys.scn_queue_obj,
|
||||
ds1->ds_object, mintxg, tx));
|
||||
}
|
||||
VERIFY3S(0, ==, zap_add_int_key(dp->dp_meta_objset,
|
||||
scn->scn_phys.scn_queue_obj, ds2->ds_object, mintxg1, tx));
|
||||
zfs_dbgmsg("clone_swap ds %llu; in queue; "
|
||||
"replacing with %llu",
|
||||
(u_longlong_t)ds1->ds_object,
|
||||
(u_longlong_t)ds2->ds_object);
|
||||
}
|
||||
if (zap_lookup_int_key(dp->dp_meta_objset, scn->scn_phys.scn_queue_obj,
|
||||
ds2->ds_object, &mintxg) == 0) {
|
||||
ASSERT3U(mintxg, ==, dsl_dataset_phys(ds1)->ds_prev_snap_txg);
|
||||
ASSERT3U(mintxg, ==, dsl_dataset_phys(ds2)->ds_prev_snap_txg);
|
||||
VERIFY3U(0, ==, zap_remove_int(dp->dp_meta_objset,
|
||||
} else if (ds2_queued) {
|
||||
VERIFY3S(0, ==, zap_remove_int(dp->dp_meta_objset,
|
||||
scn->scn_phys.scn_queue_obj, ds2->ds_object, tx));
|
||||
VERIFY(0 == zap_add_int_key(dp->dp_meta_objset,
|
||||
scn->scn_phys.scn_queue_obj, ds1->ds_object, mintxg, tx));
|
||||
VERIFY3S(0, ==, zap_add_int_key(dp->dp_meta_objset,
|
||||
scn->scn_phys.scn_queue_obj, ds1->ds_object, mintxg2, tx));
|
||||
zfs_dbgmsg("clone_swap ds %llu; in queue; "
|
||||
"replacing with %llu",
|
||||
(u_longlong_t)ds2->ds_object,
|
||||
|
||||
+45
-27
@@ -20,7 +20,7 @@
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2018 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2019 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
|
||||
* Copyright (c) 2017, Intel Corporation.
|
||||
*/
|
||||
@@ -103,12 +103,27 @@ int zfs_mg_noalloc_threshold = 0;
|
||||
|
||||
/*
|
||||
* Metaslab groups are considered eligible for allocations if their
|
||||
* fragmenation metric (measured as a percentage) is less than or equal to
|
||||
* zfs_mg_fragmentation_threshold. If a metaslab group exceeds this threshold
|
||||
* then it will be skipped unless all metaslab groups within the metaslab
|
||||
* class have also crossed this threshold.
|
||||
* fragmenation metric (measured as a percentage) is less than or
|
||||
* equal to zfs_mg_fragmentation_threshold. If a metaslab group
|
||||
* exceeds this threshold then it will be skipped unless all metaslab
|
||||
* groups within the metaslab class have also crossed this threshold.
|
||||
*
|
||||
* This tunable was introduced to avoid edge cases where we continue
|
||||
* allocating from very fragmented disks in our pool while other, less
|
||||
* fragmented disks, exists. On the other hand, if all disks in the
|
||||
* pool are uniformly approaching the threshold, the threshold can
|
||||
* be a speed bump in performance, where we keep switching the disks
|
||||
* that we allocate from (e.g. we allocate some segments from disk A
|
||||
* making it bypassing the threshold while freeing segments from disk
|
||||
* B getting its fragmentation below the threshold).
|
||||
*
|
||||
* Empirically, we've seen that our vdev selection for allocations is
|
||||
* good enough that fragmentation increases uniformly across all vdevs
|
||||
* the majority of the time. Thus we set the threshold percentage high
|
||||
* enough to avoid hitting the speed bump on pools that are being pushed
|
||||
* to the edge.
|
||||
*/
|
||||
int zfs_mg_fragmentation_threshold = 85;
|
||||
int zfs_mg_fragmentation_threshold = 95;
|
||||
|
||||
/*
|
||||
* Allow metaslabs to keep their active state as long as their fragmentation
|
||||
@@ -2934,6 +2949,30 @@ metaslab_sync(metaslab_t *msp, uint64_t txg)
|
||||
dmu_tx_commit(tx);
|
||||
}
|
||||
|
||||
void
|
||||
metaslab_potentially_unload(metaslab_t *msp, uint64_t txg)
|
||||
{
|
||||
/*
|
||||
* If the metaslab is loaded and we've not tried to load or allocate
|
||||
* from it in 'metaslab_unload_delay' txgs, then unload it.
|
||||
*/
|
||||
if (msp->ms_loaded &&
|
||||
msp->ms_disabled == 0 &&
|
||||
msp->ms_selected_txg + metaslab_unload_delay < txg) {
|
||||
for (int t = 1; t < TXG_CONCURRENT_STATES; t++) {
|
||||
VERIFY0(range_tree_space(
|
||||
msp->ms_allocating[(txg + t) & TXG_MASK]));
|
||||
}
|
||||
if (msp->ms_allocator != -1) {
|
||||
metaslab_passivate(msp, msp->ms_weight &
|
||||
~METASLAB_ACTIVE_MASK);
|
||||
}
|
||||
|
||||
if (!metaslab_debug_unload)
|
||||
metaslab_unload(msp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Called after a transaction group has completely synced to mark
|
||||
* all of the metaslab's free space as usable.
|
||||
@@ -3071,27 +3110,6 @@ metaslab_sync_done(metaslab_t *msp, uint64_t txg)
|
||||
*/
|
||||
metaslab_recalculate_weight_and_sort(msp);
|
||||
|
||||
/*
|
||||
* If the metaslab is loaded and we've not tried to load or allocate
|
||||
* from it in 'metaslab_unload_delay' txgs, then unload it.
|
||||
*/
|
||||
if (msp->ms_loaded &&
|
||||
msp->ms_disabled == 0 &&
|
||||
msp->ms_selected_txg + metaslab_unload_delay < txg) {
|
||||
|
||||
for (int t = 1; t < TXG_CONCURRENT_STATES; t++) {
|
||||
VERIFY0(range_tree_space(
|
||||
msp->ms_allocating[(txg + t) & TXG_MASK]));
|
||||
}
|
||||
if (msp->ms_allocator != -1) {
|
||||
metaslab_passivate(msp, msp->ms_weight &
|
||||
~METASLAB_ACTIVE_MASK);
|
||||
}
|
||||
|
||||
if (!metaslab_debug_unload)
|
||||
metaslab_unload(msp);
|
||||
}
|
||||
|
||||
ASSERT0(range_tree_space(msp->ms_allocating[txg & TXG_MASK]));
|
||||
ASSERT0(range_tree_space(msp->ms_freeing));
|
||||
ASSERT0(range_tree_space(msp->ms_freed));
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user