diff options
author | Jerry Jelinek <jerry.jelinek@joyent.com> | 2016-03-10 12:27:27 +0000 |
---|---|---|
committer | Jerry Jelinek <jerry.jelinek@joyent.com> | 2016-03-10 12:27:27 +0000 |
commit | 587f4d19484a7d9f3f732214995e34f877831d02 (patch) | |
tree | 4135283bd079e18fdb10a5ea78597e6f9b70cac6 | |
parent | d0104768a77bae39972bdaa88afcf87231be8fe3 (diff) | |
parent | 286ef71398fb54b1d5007d6f45aa4320a9e0ede2 (diff) | |
download | illumos-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
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)); } |