summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJerry Jelinek <jerry.jelinek@joyent.com>2016-03-10 12:27:27 +0000
committerJerry Jelinek <jerry.jelinek@joyent.com>2016-03-10 12:27:27 +0000
commit587f4d19484a7d9f3f732214995e34f877831d02 (patch)
tree4135283bd079e18fdb10a5ea78597e6f9b70cac6
parentd0104768a77bae39972bdaa88afcf87231be8fe3 (diff)
parent286ef71398fb54b1d5007d6f45aa4320a9e0ede2 (diff)
downloadillumos-joyent-587f4d19484a7d9f3f732214995e34f877831d02.tar.gz
[illumos-gate merge]
commit 286ef71398fb54b1d5007d6f45aa4320a9e0ede2 6370 ZFS send fails to transmit some holes commit 4549a1bd3fb75b70dd34ba46715014effe21dc07 6727 lofiadm: remove "o:" from getopt argument commit e2e882f7e139a951a52c7f4b5af447c3e6e68398 6691 V490 and V890 symlinks missing on SPARC build commit 2f15e7adf5d6f13b15dfa8f3900a07804cadd86c 6581 cmd/format should be able label virtio BLKDEV drives commit debed2c9e88134586f1a03761f87d8a1d599b854 6733 mh_contents rwlock is not initialised Conflicts: usr/src/cmd/lofiadm/main.c
-rw-r--r--usr/src/cmd/format/auto_sense.c133
-rw-r--r--usr/src/cmd/format/menu_command.c4
-rw-r--r--usr/src/cmd/lofiadm/main.c3
-rw-r--r--usr/src/lib/libprtdiag_psr/sparc/cherrystone/Makefile3
-rw-r--r--usr/src/lib/libprtdiag_psr/sparc/daktari/Makefile3
-rw-r--r--usr/src/lib/libprtdiag_psr/sparc/ontario/Makefile3
-rw-r--r--usr/src/pkg/manifests/system-test-zfstest.mf3
-rw-r--r--usr/src/test/zfs-tests/cmd/Makefile1
-rw-r--r--usr/src/test/zfs-tests/cmd/mkfiles/Makefile23
-rw-r--r--usr/src/test/zfs-tests/cmd/mkfiles/mkfiles.c63
-rw-r--r--usr/src/test/zfs-tests/include/default.cfg3
-rw-r--r--usr/src/test/zfs-tests/runfiles/delphix.run3
-rw-r--r--usr/src/test/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_010_pos.ksh5
-rw-r--r--usr/src/test/zfs-tests/tests/functional/cli_root/zfs_send/Makefile5
-rw-r--r--usr/src/test/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_007_pos.ksh99
-rw-r--r--usr/src/uts/common/fs/zfs/dmu_object.c8
-rw-r--r--usr/src/uts/common/fs/zfs/dmu_traverse.c49
-rw-r--r--usr/src/uts/common/os/modhash.c4
18 files changed, 296 insertions, 119 deletions
diff --git a/usr/src/cmd/format/auto_sense.c b/usr/src/cmd/format/auto_sense.c
index 5ea76569ca..6d51a72414 100644
--- a/usr/src/cmd/format/auto_sense.c
+++ b/usr/src/cmd/format/auto_sense.c
@@ -24,6 +24,7 @@
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
*/
/*
@@ -210,15 +211,11 @@ static struct disk_info *find_scsi_disk_info(
static struct disk_type *new_direct_disk_type(int fd, char *disk_name,
struct dk_label *label);
-static struct disk_info *find_direct_disk_info(struct dk_cinfo *dkinfo);
static int efi_ioctl(int fd, int cmd, dk_efi_t *dk_ioc);
static int auto_label_init(struct dk_label *label);
-static struct ctlr_type *find_direct_ctlr_type(void);
-static struct ctlr_info *find_direct_ctlr_info(struct dk_cinfo *dkinfo);
-static struct disk_info *find_direct_disk_info(struct dk_cinfo *dkinfo);
-static struct ctlr_type *find_vbd_ctlr_type(void);
-static struct ctlr_info *find_vbd_ctlr_info(struct dk_cinfo *dkinfo);
-static struct disk_info *find_vbd_disk_info(struct dk_cinfo *dkinfo);
+static struct ctlr_type *find_ctlr_type(ushort_t);
+static struct ctlr_info *find_ctlr_info(struct dk_cinfo *, ushort_t);
+static struct disk_info *find_disk_info(struct dk_cinfo *, ushort_t);
static char *get_sun_disk_name(
char *disk_name,
@@ -264,12 +261,11 @@ auto_efi_sense(int fd, struct efi_info *label)
}
return (NULL);
}
- if ((cur_ctype != NULL) && (cur_ctype->ctype_ctype == DKC_DIRECT)) {
- ctlr = find_direct_ctlr_info(&dkinfo);
- disk_info = find_direct_disk_info(&dkinfo);
- } else if ((cur_ctype != NULL) && (cur_ctype->ctype_ctype == DKC_VBD)) {
- ctlr = find_vbd_ctlr_info(&dkinfo);
- disk_info = find_vbd_disk_info(&dkinfo);
+ if ((cur_ctype != NULL) && (cur_ctype->ctype_ctype == DKC_DIRECT ||
+ cur_ctype->ctype_ctype == DKC_VBD ||
+ cur_ctype->ctype_ctype == DKC_BLKDEV)) {
+ ctlr = find_ctlr_info(&dkinfo, cur_ctype->ctype_ctype);
+ disk_info = find_disk_info(&dkinfo, cur_ctype->ctype_ctype);
} else {
ctlr = find_scsi_ctlr_info(&dkinfo);
disk_info = find_scsi_disk_info(&dkinfo);
@@ -378,116 +374,61 @@ efi_ioctl(int fd, int cmd, dk_efi_t *dk_ioc)
}
static struct ctlr_type *
-find_direct_ctlr_type()
+find_ctlr_type(ushort_t type)
{
struct mctlr_list *mlp;
- mlp = controlp;
-
- while (mlp != NULL) {
- if (mlp->ctlr_type->ctype_ctype == DKC_DIRECT) {
- return (mlp->ctlr_type);
- }
- mlp = mlp->next;
- }
-
- impossible("no DIRECT controller type");
-
- return ((struct ctlr_type *)NULL);
-}
-
-static struct ctlr_type *
-find_vbd_ctlr_type()
-{
- struct mctlr_list *mlp;
+ assert(type == DKC_DIRECT ||
+ type == DKC_VBD ||
+ type == DKC_BLKDEV);
mlp = controlp;
while (mlp != NULL) {
- if (mlp->ctlr_type->ctype_ctype == DKC_VBD) {
+ if (mlp->ctlr_type->ctype_ctype == type) {
return (mlp->ctlr_type);
}
mlp = mlp->next;
}
- impossible("no VBD controller type");
+ impossible("no DIRECT/VBD/BLKDEV controller type");
return ((struct ctlr_type *)NULL);
}
static struct ctlr_info *
-find_direct_ctlr_info(
- struct dk_cinfo *dkinfo)
+find_ctlr_info(struct dk_cinfo *dkinfo, ushort_t type)
{
struct ctlr_info *ctlr;
- if (dkinfo->dki_ctype != DKC_DIRECT)
- return (NULL);
+ assert(type == DKC_DIRECT ||
+ type == DKC_VBD ||
+ type == DKC_BLKDEV);
for (ctlr = ctlr_list; ctlr != NULL; ctlr = ctlr->ctlr_next) {
if (ctlr->ctlr_addr == dkinfo->dki_addr &&
ctlr->ctlr_space == dkinfo->dki_space &&
- ctlr->ctlr_ctype->ctype_ctype == DKC_DIRECT) {
+ ctlr->ctlr_ctype->ctype_ctype == dkinfo->dki_ctype) {
return (ctlr);
}
}
- impossible("no DIRECT controller info");
- /*NOTREACHED*/
-}
-
-static struct ctlr_info *
-find_vbd_ctlr_info(
- struct dk_cinfo *dkinfo)
-{
- struct ctlr_info *ctlr;
-
- if (dkinfo->dki_ctype != DKC_VBD)
- return (NULL);
-
- for (ctlr = ctlr_list; ctlr != NULL; ctlr = ctlr->ctlr_next) {
- if (ctlr->ctlr_addr == dkinfo->dki_addr &&
- ctlr->ctlr_space == dkinfo->dki_space &&
- ctlr->ctlr_ctype->ctype_ctype == DKC_VBD) {
- return (ctlr);
- }
- }
-
- impossible("no VBD controller info");
+ impossible("no DIRECT/VBD/BLKDEV controller info");
/*NOTREACHED*/
+ return ((struct ctlr_info *)NULL);
}
static struct disk_info *
-find_direct_disk_info(
- struct dk_cinfo *dkinfo)
+find_disk_info(struct dk_cinfo *dkinfo, ushort_t type)
{
struct disk_info *disk;
struct dk_cinfo *dp;
- for (disk = disk_list; disk != NULL; disk = disk->disk_next) {
- assert(dkinfo->dki_ctype == DKC_DIRECT);
- dp = &disk->disk_dkinfo;
- if (dp->dki_ctype == dkinfo->dki_ctype &&
- dp->dki_cnum == dkinfo->dki_cnum &&
- dp->dki_unit == dkinfo->dki_unit &&
- strcmp(dp->dki_dname, dkinfo->dki_dname) == 0) {
- return (disk);
- }
- }
-
- impossible("No DIRECT disk info instance\n");
- /*NOTREACHED*/
-}
-
-static struct disk_info *
-find_vbd_disk_info(
- struct dk_cinfo *dkinfo)
-{
- struct disk_info *disk;
- struct dk_cinfo *dp;
+ assert(type == DKC_DIRECT ||
+ type == DKC_VBD ||
+ type == DKC_BLKDEV);
for (disk = disk_list; disk != NULL; disk = disk->disk_next) {
- assert(dkinfo->dki_ctype == DKC_VBD);
dp = &disk->disk_dkinfo;
if (dp->dki_ctype == dkinfo->dki_ctype &&
dp->dki_cnum == dkinfo->dki_cnum &&
@@ -497,8 +438,9 @@ find_vbd_disk_info(
}
}
- impossible("No VBD disk info instance\n");
+ impossible("No DIRECT/VBD/BLKDEV disk info instance\n");
/*NOTREACHED*/
+ return ((struct disk_info *)NULL);
}
/*
@@ -691,7 +633,7 @@ new_direct_disk_type(
/*
* Find the ctlr_info for this disk.
*/
- ctlr = find_direct_ctlr_info(&dkinfo);
+ ctlr = find_ctlr_info(&dkinfo, dkinfo.dki_ctype);
/*
* Allocate a new disk type for the direct controller.
@@ -701,7 +643,7 @@ new_direct_disk_type(
/*
* Find the disk_info instance for this disk.
*/
- disk_info = find_direct_disk_info(&dkinfo);
+ disk_info = find_disk_info(&dkinfo, dkinfo.dki_ctype);
/*
* The controller and the disk should match.
@@ -2010,16 +1952,15 @@ new_scsi_disk_type(
* Delete a disk type from disk type list.
*/
int
-delete_disk_type(
- struct disk_type *disk_type)
+delete_disk_type(struct disk_type *disk_type)
{
struct ctlr_type *ctlr;
struct disk_type *dp, *disk;
- if (cur_ctype->ctype_ctype == DKC_DIRECT)
- ctlr = find_direct_ctlr_type();
- else if (cur_ctype->ctype_ctype == DKC_VBD)
- ctlr = find_vbd_ctlr_type();
+ if (cur_ctype->ctype_ctype == DKC_DIRECT ||
+ cur_ctype->ctype_ctype == DKC_VBD ||
+ cur_ctype->ctype_ctype == DKC_BLKDEV)
+ ctlr = find_ctlr_type(cur_ctype->ctype_ctype);
else
ctlr = find_scsi_ctlr_type();
if (ctlr == NULL || ctlr->ctype_dlist == NULL) {
@@ -2157,7 +2098,7 @@ strcopy(
*/
int
adjust_disk_geometry(diskaddr_t capacity, uint_t *cyl, uint_t *nhead,
- uint_t *nsect)
+ uint_t *nsect)
{
uint_t lcyl = *cyl;
uint_t lnhead = *nhead;
@@ -2296,7 +2237,7 @@ square_box(
*/
static void
compute_chs_values(diskaddr_t total_capacity, diskaddr_t usable_capacity,
- uint_t *pcylp, uint_t *nheadp, uint_t *nsectp)
+ uint_t *pcylp, uint_t *nheadp, uint_t *nsectp)
{
/* Unlabeled SCSI floppy device */
diff --git a/usr/src/cmd/format/menu_command.c b/usr/src/cmd/format/menu_command.c
index 838813dde6..142c4f119a 100644
--- a/usr/src/cmd/format/menu_command.c
+++ b/usr/src/cmd/format/menu_command.c
@@ -23,6 +23,7 @@
* Copyright 2012 Milan Jurik. All rights reserved.
* Copyright 2014 Toomas Soome <tsoome@me.com>
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
*/
/*
@@ -1621,7 +1622,8 @@ c_label()
(void) memset((char *)&label, 0, sizeof (struct dk_label));
(void) strcpy(x86_devname, cur_disk->disk_name);
- if (cur_ctype->ctype_ctype == DKC_DIRECT)
+ if (cur_ctype->ctype_ctype == DKC_DIRECT ||
+ cur_ctype->ctype_ctype == DKC_BLKDEV)
dptr = auto_direct_get_geom_label(cur_file, &label);
else
dptr = auto_sense(cur_file, 1, &label);
diff --git a/usr/src/cmd/lofiadm/main.c b/usr/src/cmd/lofiadm/main.c
index 0c32b69323..fd6513fdf8 100644
--- a/usr/src/cmd/lofiadm/main.c
+++ b/usr/src/cmd/lofiadm/main.c
@@ -25,6 +25,7 @@
*
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2014 Gary Mills
+ * Copyright (c) 2016 Andrey Sokolov
*/
/*
@@ -1837,7 +1838,7 @@ main(int argc, char *argv[])
(void) setlocale(LC_ALL, "");
(void) textdomain(TEXT_DOMAIN);
- while ((c = getopt(argc, argv, "a:c:Cd:efk:o:rs:T:UX")) != EOF) {
+ while ((c = getopt(argc, argv, "a:c:Cd:efk:rs:T:UX")) != EOF) {
switch (c) {
case 'a':
addflag = B_TRUE;
diff --git a/usr/src/lib/libprtdiag_psr/sparc/cherrystone/Makefile b/usr/src/lib/libprtdiag_psr/sparc/cherrystone/Makefile
index f54f6f38da..eb842af94d 100644
--- a/usr/src/lib/libprtdiag_psr/sparc/cherrystone/Makefile
+++ b/usr/src/lib/libprtdiag_psr/sparc/cherrystone/Makefile
@@ -19,6 +19,7 @@
# CDDL HEADER END
#
#
+# Copyright 2016 Gary Mills
# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -82,7 +83,7 @@ $(LINKED_DIRS): $(USR_PLAT_DIR)
$(LINKED_LIB_DIRS): $(LINKED_DIRS)
-$(INS.dir)
-$(LINKED_PRTDIAG_DIRS): $(USR_PLAT_DIR)
+$(LINKED_PRTDIAG_DIRS): $(LINKED_LIB_DIRS)
-$(INS.slink6)
#
diff --git a/usr/src/lib/libprtdiag_psr/sparc/daktari/Makefile b/usr/src/lib/libprtdiag_psr/sparc/daktari/Makefile
index ad046bb974..adac196b93 100644
--- a/usr/src/lib/libprtdiag_psr/sparc/daktari/Makefile
+++ b/usr/src/lib/libprtdiag_psr/sparc/daktari/Makefile
@@ -19,6 +19,7 @@
# CDDL HEADER END
#
#
+# Copyright 2016 Gary Mills
# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -76,7 +77,7 @@ $(LINKED_DIRS): $(USR_PLAT_DIR)
$(LINKED_LIB_DIRS): $(LINKED_DIRS)
-$(INS.dir)
-$(LINKED_PRTDIAG_DIRS): $(USR_PLAT_DIR)
+$(LINKED_PRTDIAG_DIRS): $(LINKED_LIB_DIRS)
-$(INS.slink6)
#
diff --git a/usr/src/lib/libprtdiag_psr/sparc/ontario/Makefile b/usr/src/lib/libprtdiag_psr/sparc/ontario/Makefile
index 60c2862426..062a657321 100644
--- a/usr/src/lib/libprtdiag_psr/sparc/ontario/Makefile
+++ b/usr/src/lib/libprtdiag_psr/sparc/ontario/Makefile
@@ -19,6 +19,7 @@
# CDDL HEADER END
#
#
+# Copyright 2016 Gary Mills
# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -77,7 +78,7 @@ $(LINKED_DIRS): $(USR_PLAT_DIR)
$(LINKED_LIB_DIRS): $(LINKED_DIRS)
-$(INS.dir)
-$(LINKED_PRTDIAG_DIRS): $(USR_PLAT_DIR)
+$(LINKED_PRTDIAG_DIRS): $(LINKED_LIB_DIRS)
-$(INS.slink6)
#
diff --git a/usr/src/pkg/manifests/system-test-zfstest.mf b/usr/src/pkg/manifests/system-test-zfstest.mf
index cb1016e921..457fe05e29 100644
--- a/usr/src/pkg/manifests/system-test-zfstest.mf
+++ b/usr/src/pkg/manifests/system-test-zfstest.mf
@@ -152,6 +152,7 @@ file path=opt/zfs-tests/bin/file_write mode=0555
file path=opt/zfs-tests/bin/getholes mode=0555
file path=opt/zfs-tests/bin/largest_file mode=0555
file path=opt/zfs-tests/bin/mkbusy mode=0555
+file path=opt/zfs-tests/bin/mkfiles mode=0555
file path=opt/zfs-tests/bin/mkholes mode=0555
file path=opt/zfs-tests/bin/mktree mode=0555
file path=opt/zfs-tests/bin/mmapwrite mode=0555
@@ -794,6 +795,8 @@ file path=opt/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_005_pos \
mode=0555
file path=opt/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_006_pos \
mode=0555
+file path=opt/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_007_pos \
+ mode=0555
file path=opt/zfs-tests/tests/functional/cli_root/zfs_set/cache_001_pos \
mode=0555
file path=opt/zfs-tests/tests/functional/cli_root/zfs_set/cache_002_neg \
diff --git a/usr/src/test/zfs-tests/cmd/Makefile b/usr/src/test/zfs-tests/cmd/Makefile
index 031b8ff1f6..5bc6db13c3 100644
--- a/usr/src/test/zfs-tests/cmd/Makefile
+++ b/usr/src/test/zfs-tests/cmd/Makefile
@@ -24,6 +24,7 @@ SUBDIRS = chg_usr_exec \
getholes \
largest_file \
mkbusy \
+ mkfiles \
mkholes \
mktree \
mmapwrite \
diff --git a/usr/src/test/zfs-tests/cmd/mkfiles/Makefile b/usr/src/test/zfs-tests/cmd/mkfiles/Makefile
new file mode 100644
index 0000000000..7e833fefb1
--- /dev/null
+++ b/usr/src/test/zfs-tests/cmd/mkfiles/Makefile
@@ -0,0 +1,23 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+PROG = mkfiles
+
+include $(SRC)/cmd/Makefile.cmd
+
+LDLIBS += -lc
+C99MODE = -xc99=%all
+
+include ../Makefile.subdirs
diff --git a/usr/src/test/zfs-tests/cmd/mkfiles/mkfiles.c b/usr/src/test/zfs-tests/cmd/mkfiles/mkfiles.c
new file mode 100644
index 0000000000..58c7d5f509
--- /dev/null
+++ b/usr/src/test/zfs-tests/cmd/mkfiles/mkfiles.c
@@ -0,0 +1,63 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright (c) 2016 by Delphix. All rights reserved.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/param.h>
+
+#define MAX_INT_LENGTH 10
+
+static void
+usage(char *msg, int exit_value)
+{
+ (void) fprintf(stderr, "mkfiles basename max_file [min_file]\n");
+ (void) fprintf(stderr, "%s\n", msg);
+ exit(exit_value);
+}
+
+int
+main(int argc, char **argv)
+{
+ unsigned int numfiles = 0;
+ unsigned int first_file = 0;
+ if (argc < 3 || argc > 4)
+ usage("Invalid number of arguments", -1);
+
+ if (sscanf(argv[2], "%u", &numfiles) != 1)
+ usage("Invalid maximum file", -2);
+
+ if (argc == 4 && sscanf(argv[3], "%u", &first_file) != 1)
+ usage("Invalid first file", -3);
+
+ if (numfiles < first_file)
+ usage("First file larger than last file", -3);
+
+ char buf[MAXPATHLEN];
+ for (unsigned int i = first_file; i <= numfiles; i++) {
+ int fd;
+ (void) snprintf(buf, MAXPATHLEN, "%s%u", argv[1], i);
+ if ((fd = open(buf, O_CREAT | O_EXCL, O_RDWR)) == -1) {
+ (void) fprintf(stderr, "Failed to create %s %s\n", buf,
+ strerror(errno));
+ return (-4);
+ }
+ (void) close(fd);
+ }
+ return (0);
+}
diff --git a/usr/src/test/zfs-tests/include/default.cfg b/usr/src/test/zfs-tests/include/default.cfg
index fa57c978a7..61fb25e628 100644
--- a/usr/src/test/zfs-tests/include/default.cfg
+++ b/usr/src/test/zfs-tests/include/default.cfg
@@ -25,7 +25,7 @@
#
#
-# Copyright (c) 2012, 2014 by Delphix. All rights reserved.
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
#
. $STF_SUITE/include/commands.cfg
@@ -50,6 +50,7 @@ export FILE_WRITE="/opt/zfs-tests/bin/file_write"
export GETHOLES="/opt/zfs-tests/bin/getholes"
export LARGEST_FILE="/opt/zfs-tests/bin/largest_file"
export MKBUSY="/opt/zfs-tests/bin/mkbusy"
+export MKFILES="/opt/zfs-tests/bin/mkfiles"
export MKHOLES="/opt/zfs-tests/bin/mkholes"
export MKTREE="/opt/zfs-tests/bin/mktree"
export MMAPWRITE="/opt/zfs-tests/bin/mmapwrite"
diff --git a/usr/src/test/zfs-tests/runfiles/delphix.run b/usr/src/test/zfs-tests/runfiles/delphix.run
index bc6c80d491..bcd19ae686 100644
--- a/usr/src/test/zfs-tests/runfiles/delphix.run
+++ b/usr/src/test/zfs-tests/runfiles/delphix.run
@@ -168,7 +168,8 @@ tests = ['zfs_rollback_001_pos', 'zfs_rollback_002_pos',
[/opt/zfs-tests/tests/functional/cli_root/zfs_send]
tests = ['zfs_send_001_pos', 'zfs_send_002_pos', 'zfs_send_003_pos',
- 'zfs_send_004_neg', 'zfs_send_005_pos', 'zfs_send_006_pos']
+ 'zfs_send_004_neg', 'zfs_send_005_pos', 'zfs_send_006_pos',
+ 'zfs_send_007_pos']
[/opt/zfs-tests/tests/functional/cli_root/zfs_set]
tests = ['cache_001_pos', 'cache_002_neg', 'canmount_001_pos',
diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_010_pos.ksh b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_010_pos.ksh
index f9c1ec4a5f..b1fbff2976 100644
--- a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_010_pos.ksh
+++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_010_pos.ksh
@@ -137,6 +137,11 @@ $TOUCH $mntpnt2/f18
$RM $mntpnt/h17
$RM $mntpnt2/h*
+# Add empty objects to $fs to exercise dmu_traverse code
+for i in `seq 1 100`; do
+ log_must touch $mntpnt/uf$i
+done
+
log_must $ZFS snapshot $fs@s1
log_must $ZFS snapshot $fs2@s1
diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_send/Makefile b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_send/Makefile
index e8d5a70bf6..2647f8bbe4 100644
--- a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_send/Makefile
+++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_send/Makefile
@@ -10,7 +10,7 @@
#
#
-# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright (c) 2012, 2015 by Delphix. All rights reserved.
#
include $(SRC)/Makefile.master
@@ -25,7 +25,8 @@ PROGS = cleanup \
zfs_send_003_pos \
zfs_send_004_neg \
zfs_send_005_pos \
- zfs_send_006_pos
+ zfs_send_006_pos \
+ zfs_send_007_pos
FILES = zfs_send.cfg
diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_007_pos.ksh b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_007_pos.ksh
new file mode 100644
index 0000000000..13ae4f0248
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_007_pos.ksh
@@ -0,0 +1,99 @@
+#!/bin/ksh
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2015, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+#
+# DESCRIPTION:
+# Verify 'zfs send' drills holes appropriately when files are replaced
+#
+# STRATEGY:
+# 1. Create dataset
+# 2. Write block 0 in a bunch of files
+# 3. Snapshot the dataset
+# 4. Remove all the files and rewrite some files with just block 1
+# 5. Snapshot the dataset
+# 6. Send both snapshots and receive them locally
+# 7. diff the received dataset and the old datasets.
+# 8. Repeat steps 1-7 above with pool that never had hole birth enabled.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ $ZFS destroy -rf $TESTPOOL/fs
+ $ZFS destroy -rf $TESTPOOL/recvfs
+ $RM $streamfile
+ $RM $vdev
+ $ZPOOL destroy testpool
+}
+
+
+log_assert "Verify that 'zfs send' drills appropriate holes"
+log_onexit cleanup
+streamfile=$(mktemp /var/tmp/file.XXXXXX)
+vdev=$(mktemp /var/tmp/file.XXXXXX)
+
+
+test_pool ()
+{
+ POOL=$1
+ log_must $ZFS create -o recordsize=512 $POOL/fs
+ mntpnt=$(get_prop mountpoint "$POOL/fs")
+ log_must $DD if=/dev/urandom of=${mntpnt}/file bs=512 count=1 2>/dev/null
+ first_object=$(ls -i $mntpnt | awk '{print $1}')
+ log_must $ZFS snapshot $POOL/fs@a
+ while true; do
+ log_must $FIND $mntpnt -delete
+ sync
+ log_must $MKFILES "$mntpnt/" 4000
+ FILE=$(ls -i $mntpnt | awk \
+ '{if ($1 == '$first_object') {print $2}}')
+ if [[ -n "$FILE" ]]; then
+ break
+ fi
+ done
+ $DD if=/dev/urandom of=${mntpnt}/$FILE bs=512 count=1 seek=1 2>/dev/null
+
+ log_must $ZFS snapshot $POOL/fs@b
+
+ log_must eval "$ZFS send $POOL/fs@a > $streamfile"
+ $CAT $streamfile | log_must $ZFS receive $POOL/recvfs
+
+ log_must eval "$ZFS send -i @a $POOL/fs@b > $streamfile"
+ $CAT $streamfile | log_must $ZFS receive $POOL/recvfs
+
+ recv_mntpnt=$(get_prop mountpoint "$POOL/recvfs")
+ log_must $DIFF -r $mntpnt $recv_mntpnt
+ log_must $ZFS destroy -rf $POOL/fs
+ log_must $ZFS destroy -rf $POOL/recvfs
+}
+
+test_pool $TESTPOOL
+log_must $TRUNCATE --size=1G $vdev
+log_must $ZPOOL create -o version=1 testpool $vdev
+test_pool testpool
+log_must $ZPOOL destroy testpool
+log_must $ZPOOL create -d testpool $vdev
+test_pool testpool
+log_must $ZPOOL destroy testpool
+
+
+log_pass "'zfs send' drills appropriate holes"
diff --git a/usr/src/uts/common/fs/zfs/dmu_object.c b/usr/src/uts/common/fs/zfs/dmu_object.c
index 6ca021eecb..2c9802f51e 100644
--- a/usr/src/uts/common/fs/zfs/dmu_object.c
+++ b/usr/src/uts/common/fs/zfs/dmu_object.c
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2013, 2014 by Delphix. All rights reserved.
+ * Copyright (c) 2013, 2015 by Delphix. All rights reserved.
* Copyright 2014 HybridCluster. All rights reserved.
*/
@@ -50,6 +50,12 @@ dmu_object_alloc(objset_t *os, dmu_object_type_t ot, int blocksize,
* reasonably sparse (at most 1/4 full). Look from the
* beginning once, but after that keep looking from here.
* If we can't find one, just keep going from here.
+ *
+ * Note that dmu_traverse depends on the behavior that we use
+ * multiple blocks of the dnode object before going back to
+ * reuse objects. Any change to this algorithm should preserve
+ * that property or find another solution to the issues
+ * described in traverse_visitbp.
*/
if (P2PHASE(object, L2_dnode_count) == 0) {
uint64_t offset = restarted ? object << DNODE_SHIFT : 0;
diff --git a/usr/src/uts/common/fs/zfs/dmu_traverse.c b/usr/src/uts/common/fs/zfs/dmu_traverse.c
index e8739eddaf..2822ca4525 100644
--- a/usr/src/uts/common/fs/zfs/dmu_traverse.c
+++ b/usr/src/uts/common/fs/zfs/dmu_traverse.c
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
+ * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
*/
#include <sys/zfs_context.h>
@@ -62,6 +62,7 @@ typedef struct traverse_data {
uint64_t td_hole_birth_enabled_txg;
blkptr_cb_t *td_func;
void *td_arg;
+ boolean_t td_realloc_possible;
} traverse_data_t;
static int traverse_dnode(traverse_data_t *td, const dnode_phys_t *dnp,
@@ -231,18 +232,30 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp,
if (bp->blk_birth == 0) {
/*
- * Since this block has a birth time of 0 it must be a
- * hole created before the SPA_FEATURE_HOLE_BIRTH
- * feature was enabled. If SPA_FEATURE_HOLE_BIRTH
- * was enabled before the min_txg for this traveral we
- * know the hole must have been created before the
- * min_txg for this traveral, so we can skip it. If
- * SPA_FEATURE_HOLE_BIRTH was enabled after the min_txg
- * for this traveral we cannot tell if the hole was
- * created before or after the min_txg for this
- * traversal, so we cannot skip it.
+ * Since this block has a birth time of 0 it must be one of
+ * two things: a hole created before the
+ * SPA_FEATURE_HOLE_BIRTH feature was enabled, or a hole
+ * which has always been a hole in an object.
+ *
+ * If a file is written sparsely, then the unwritten parts of
+ * the file were "always holes" -- that is, they have been
+ * holes since this object was allocated. However, we (and
+ * our callers) can not necessarily tell when an object was
+ * allocated. Therefore, if it's possible that this object
+ * was freed and then its object number reused, we need to
+ * visit all the holes with birth==0.
+ *
+ * If it isn't possible that the object number was reused,
+ * then if SPA_FEATURE_HOLE_BIRTH was enabled before we wrote
+ * all the blocks we will visit as part of this traversal,
+ * then this hole must have always existed, so we can skip
+ * it. We visit blocks born after (exclusive) td_min_txg.
+ *
+ * Note that the meta-dnode cannot be reallocated.
*/
- if (td->td_hole_birth_enabled_txg < td->td_min_txg)
+ if ((!td->td_realloc_possible ||
+ zb->zb_object == DMU_META_DNODE_OBJECT) &&
+ td->td_hole_birth_enabled_txg <= td->td_min_txg)
return (0);
} else if (bp->blk_birth <= td->td_min_txg) {
return (0);
@@ -337,6 +350,15 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp,
objset_phys_t *osp = buf->b_data;
prefetch_dnode_metadata(td, &osp->os_meta_dnode, zb->zb_objset,
DMU_META_DNODE_OBJECT);
+ /*
+ * See the block comment above for the goal of this variable.
+ * If the maxblkid of the meta-dnode is 0, then we know that
+ * we've never had more than DNODES_PER_BLOCK objects in the
+ * dataset, which means we can't have reused any object ids.
+ */
+ if (osp->os_meta_dnode.dn_maxblkid == 0)
+ td->td_realloc_possible = B_FALSE;
+
if (arc_buf_size(buf) >= sizeof (objset_phys_t)) {
prefetch_dnode_metadata(td, &osp->os_groupused_dnode,
zb->zb_objset, DMU_GROUPUSED_OBJECT);
@@ -543,12 +565,13 @@ traverse_impl(spa_t *spa, dsl_dataset_t *ds, uint64_t objset, blkptr_t *rootbp,
td.td_pfd = &pd;
td.td_flags = flags;
td.td_paused = B_FALSE;
+ td.td_realloc_possible = (txg_start == 0 ? B_FALSE : B_TRUE);
if (spa_feature_is_active(spa, SPA_FEATURE_HOLE_BIRTH)) {
VERIFY(spa_feature_enabled_txg(spa,
SPA_FEATURE_HOLE_BIRTH, &td.td_hole_birth_enabled_txg));
} else {
- td.td_hole_birth_enabled_txg = 0;
+ td.td_hole_birth_enabled_txg = UINT64_MAX;
}
pd.pd_flags = flags;
diff --git a/usr/src/uts/common/os/modhash.c b/usr/src/uts/common/os/modhash.c
index 4d52a9eb66..7280ecc07c 100644
--- a/usr/src/uts/common/os/modhash.c
+++ b/usr/src/uts/common/os/modhash.c
@@ -454,6 +454,8 @@ mod_hash_create_extended(
mod_hash->mh_hashalg_data = hash_alg_data;
mod_hash->mh_keycmp = keycmp;
+ rw_init(&mod_hash->mh_contents, NULL, RW_DEFAULT, NULL);
+
/*
* Link the hash up on the list of hashes
*/
@@ -502,6 +504,8 @@ mod_hash_destroy_hash(mod_hash_t *hash)
*/
mod_hash_clear(hash);
+ rw_destroy(&hash->mh_contents);
+
kmem_free(hash->mh_name, strlen(hash->mh_name) + 1);
kmem_free(hash, MH_SIZE(hash->mh_nchains));
}