# # 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) 2012, 2016 by Delphix. All rights reserved. # include $(SRC)/test/zfs-tests/Makefile.com include $(SRC)/test/Makefile.com # # 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) 2012, 2016 by Delphix. All rights reserved. # include $(SRC)/test/Makefile.com ROOTOPTPKG = $(ROOT)/opt/zfs-tests ROOTBIN = $(ROOTOPTPKG)/bin OBJS = $(PROG:%=%.o) SRCS = $(OBJS:%.o=%.c) CMDS = $(PROG:%=$(ROOTBIN)/%) $(CMDS) : FILEMODE = 0555 CSTD = $(CSTD_GNU99) CPPFLAGS += -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 all: $(PROG) $(PROG): $(OBJS) $(LINK.c) $(OBJS) -o $@ $(LDLIBS) $(POST_PROCESS) %.o: ../%.c $(COMPILE.c) $< install: all $(CMDS) clobber: clean -$(RM) $(PROG) clean: -$(RM) $(OBJS) $(CMDS): $(ROOTBIN) $(PROG) $(ROOTBIN): $(INS.dir) $(ROOTBIN)/%: % $(INS.file) # # 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 2022 Toomas Soome # PROG = btree_test include $(SRC)/cmd/Makefile.cmd CPPFLAGS += -I$(SRC)/uts/common/fs/zfs -DDEBUG LDLIBS += -lavl -lzpool -lumem include ../Makefile.subdirs /* * 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) 2019 by Delphix. All rights reserved. */ #include #include #include #include #include #include #include #define BUFSIZE 256 int seed = 0; int stress_timeout = 180; int contents_frequency = 100; int tree_limit = 64 * 1024; boolean_t stress_only = B_FALSE; static void usage(int exit_value) { (void) fprintf(stderr, "Usage:\tbtree_test -n \n"); (void) fprintf(stderr, "\tbtree_test -s [-r ] [-l ] " "[-t timeout>] [-c check_contents]\n"); (void) fprintf(stderr, "\tbtree_test [-r ] [-l ] " "[-t timeout>] [-c check_contents]\n"); (void) fprintf(stderr, "\n With the -n option, run the named " "negative test. With the -s option,\n"); (void) fprintf(stderr, " run the stress test according to the " "other options passed. With\n"); (void) fprintf(stderr, " neither, run all the positive tests, " "including the stress test with\n"); (void) fprintf(stderr, " the default options.\n"); (void) fprintf(stderr, "\n Options that control the stress test\n"); (void) fprintf(stderr, "\t-c stress iterations after which to compare " "tree contents [default: 100]\n"); (void) fprintf(stderr, "\t-l the largest value to allow in the tree " "[default: 1M]\n"); (void) fprintf(stderr, "\t-r random seed [default: from " "gettimeofday()]\n"); (void) fprintf(stderr, "\t-t seconds to let the stress test run " "[default: 180]\n"); exit(exit_value); } typedef struct int_node { avl_node_t node; uint64_t data; } int_node_t; /* * Utility functions */ static int avl_compare(const void *v1, const void *v2) { const int_node_t *n1 = v1; const int_node_t *n2 = v2; uint64_t a = n1->data; uint64_t b = n2->data; return (TREE_CMP(a, b)); } static int zfs_btree_compare(const void *v1, const void *v2) { const uint64_t *a = v1; const uint64_t *b = v2; return (TREE_CMP(*a, *b)); } static void verify_contents(avl_tree_t *avl, zfs_btree_t *bt) { static int count = 0; zfs_btree_index_t bt_idx = {0}; int_node_t *node; uint64_t *data; boolean_t forward = count % 2 == 0 ? B_TRUE : B_FALSE; count++; ASSERT3U(avl_numnodes(avl), ==, zfs_btree_numnodes(bt)); if (forward == B_TRUE) { node = avl_first(avl); data = zfs_btree_first(bt, &bt_idx); } else { node = avl_last(avl); data = zfs_btree_last(bt, &bt_idx); } while (node != NULL) { ASSERT3U(*data, ==, node->data); if (forward == B_TRUE) { data = zfs_btree_next(bt, &bt_idx, &bt_idx); node = AVL_NEXT(avl, node); } else { data = zfs_btree_prev(bt, &bt_idx, &bt_idx); node = AVL_PREV(avl, node); } } } static void verify_node(avl_tree_t *avl, zfs_btree_t *bt, int_node_t *node) { zfs_btree_index_t bt_idx = {0}; zfs_btree_index_t bt_idx2 = {0}; int_node_t *inp; uint64_t data = node->data; uint64_t *rv = NULL; ASSERT3U(avl_numnodes(avl), ==, zfs_btree_numnodes(bt)); ASSERT3P((rv = (uint64_t *)zfs_btree_find(bt, &data, &bt_idx)), !=, NULL); ASSERT3S(*rv, ==, data); ASSERT3P(zfs_btree_get(bt, &bt_idx), !=, NULL); ASSERT3S(data, ==, *(uint64_t *)zfs_btree_get(bt, &bt_idx)); if ((inp = AVL_NEXT(avl, node)) != NULL) { ASSERT3P((rv = zfs_btree_next(bt, &bt_idx, &bt_idx2)), !=, NULL); ASSERT3P(rv, ==, zfs_btree_get(bt, &bt_idx2)); ASSERT3S(inp->data, ==, *rv); } else { ASSERT3U(data, ==, *(uint64_t *)zfs_btree_last(bt, &bt_idx)); } if ((inp = AVL_PREV(avl, node)) != NULL) { ASSERT3P((rv = zfs_btree_prev(bt, &bt_idx, &bt_idx2)), !=, NULL); ASSERT3P(rv, ==, zfs_btree_get(bt, &bt_idx2)); ASSERT3S(inp->data, ==, *rv); } else { ASSERT3U(data, ==, *(uint64_t *)zfs_btree_first(bt, &bt_idx)); } } /* * Tests */ /* Verify that zfs_btree_find works correctly with a NULL index. */ static int find_without_index(zfs_btree_t *bt, char *why) { u_longlong_t *p, i = 12345; zfs_btree_add(bt, &i); if ((p = (u_longlong_t *)zfs_btree_find(bt, &i, NULL)) == NULL || *p != i) { (void) snprintf(why, BUFSIZE, "Unexpectedly found %llu\n", p == NULL ? 0 : *p); return (1); } i++; if ((p = (u_longlong_t *)zfs_btree_find(bt, &i, NULL)) != NULL) { (void) snprintf(why, BUFSIZE, "Found bad value: %llu\n", *p); return (1); } return (0); } /* Verify simple insertion and removal from the tree. */ static int insert_find_remove(zfs_btree_t *bt, char *why) { u_longlong_t *p, i = 12345; zfs_btree_index_t bt_idx = {0}; /* Insert 'i' into the tree, and attempt to find it again. */ zfs_btree_add(bt, &i); if ((p = (u_longlong_t *)zfs_btree_find(bt, &i, &bt_idx)) == NULL) { (void) snprintf(why, BUFSIZE, "Didn't find value in tree\n"); return (1); } else if (*p != i) { (void) snprintf(why, BUFSIZE, "Found (%llu) in tree\n", *p); return (1); } ASSERT3S(zfs_btree_numnodes(bt), ==, 1); zfs_btree_verify(bt); /* Remove 'i' from the tree, and verify it is not found. */ zfs_btree_remove(bt, &i); if ((p = (u_longlong_t *)zfs_btree_find(bt, &i, &bt_idx)) != NULL) { (void) snprintf(why, BUFSIZE, "Found removed value (%llu)\n", *p); return (1); } ASSERT3S(zfs_btree_numnodes(bt), ==, 0); zfs_btree_verify(bt); return (0); } /* * Add a number of random entries into a btree and avl tree. Then walk them * backwards and forwards while emptying the tree, verifying the trees look * the same. */ static int drain_tree(zfs_btree_t *bt, char *why) { uint64_t *p; avl_tree_t avl; int i = 0; int_node_t *node; avl_index_t avl_idx = {0}; zfs_btree_index_t bt_idx = {0}; avl_create(&avl, avl_compare, sizeof (int_node_t), offsetof(int_node_t, node)); /* Fill both trees with the same data */ for (i = 0; i < 64 * 1024; i++) { void *ret; u_longlong_t randval = random(); if ((p = (uint64_t *)zfs_btree_find(bt, &randval, &bt_idx)) != NULL) { continue; } zfs_btree_add_idx(bt, &randval, &bt_idx); node = malloc(sizeof (int_node_t)); ASSERT3P(node, !=, NULL); node->data = randval; if ((ret = avl_find(&avl, node, &avl_idx)) != NULL) { (void) snprintf(why, BUFSIZE, "Found in avl: %llu\n", randval); return (1); } avl_insert(&avl, node, avl_idx); } /* Remove data from either side of the trees, comparing the data */ while (avl_numnodes(&avl) != 0) { uint64_t *data; ASSERT3U(avl_numnodes(&avl), ==, zfs_btree_numnodes(bt)); if (avl_numnodes(&avl) % 2 == 0) { node = avl_first(&avl); data = zfs_btree_first(bt, &bt_idx); } else { node = avl_last(&avl); data = zfs_btree_last(bt, &bt_idx); } ASSERT3U(node->data, ==, *data); zfs_btree_remove_idx(bt, &bt_idx); avl_remove(&avl, node); if (avl_numnodes(&avl) == 0) { break; } node = avl_first(&avl); ASSERT3U(node->data, ==, *(uint64_t *)zfs_btree_first(bt, NULL)); node = avl_last(&avl); ASSERT3U(node->data, ==, *(uint64_t *)zfs_btree_last(bt, NULL)); } ASSERT3S(zfs_btree_numnodes(bt), ==, 0); void *avl_cookie = NULL; while ((node = avl_destroy_nodes(&avl, &avl_cookie)) != NULL) free(node); avl_destroy(&avl); return (0); } /* * This test uses an avl and btree, and continually processes new random * values. Each value is either removed or inserted, depending on whether * or not it is found in the tree. The test periodically checks that both * trees have the same data and does consistency checks. This stress * option can also be run on its own from the command line. */ static int stress_tree(zfs_btree_t *bt, char *why __unused) { avl_tree_t avl; int_node_t *node; struct timeval tp; time_t t0; int insertions = 0, removals = 0, iterations = 0; u_longlong_t max = 0, min = UINT64_MAX; (void) gettimeofday(&tp, NULL); t0 = tp.tv_sec; avl_create(&avl, avl_compare, sizeof (int_node_t), offsetof(int_node_t, node)); while (1) { zfs_btree_index_t bt_idx = {0}; avl_index_t avl_idx = {0}; uint64_t randval = random() % tree_limit; node = malloc(sizeof (*node)); node->data = randval; max = randval > max ? randval : max; min = randval < min ? randval : min; void *ret = avl_find(&avl, node, &avl_idx); if (ret == NULL) { insertions++; avl_insert(&avl, node, avl_idx); ASSERT3P(zfs_btree_find(bt, &randval, &bt_idx), ==, NULL); zfs_btree_add_idx(bt, &randval, &bt_idx); verify_node(&avl, bt, node); } else { removals++; verify_node(&avl, bt, ret); zfs_btree_remove(bt, &randval); avl_remove(&avl, ret); free(ret); free(node); } zfs_btree_verify(bt); iterations++; if (iterations % contents_frequency == 0) { verify_contents(&avl, bt); } zfs_btree_verify(bt); (void) gettimeofday(&tp, NULL); if (tp.tv_sec > t0 + stress_timeout) { fprintf(stderr, "insertions/removals: %u/%u\nmax/min: " "%llu/%llu\n", insertions, removals, max, min); break; } } void *avl_cookie = NULL; while ((node = avl_destroy_nodes(&avl, &avl_cookie)) != NULL) free(node); avl_destroy(&avl); if (stress_only) { zfs_btree_index_t *idx = NULL; uint64_t *rv; while ((rv = zfs_btree_destroy_nodes(bt, &idx)) != NULL) ; zfs_btree_verify(bt); } return (0); } /* * Verify inserting a duplicate value will cause a crash. * Note: negative test; return of 0 is a failure. */ static int insert_duplicate(zfs_btree_t *bt) { uint64_t *p, i = 23456; zfs_btree_index_t bt_idx = {0}; if ((p = (uint64_t *)zfs_btree_find(bt, &i, &bt_idx)) != NULL) { fprintf(stderr, "Found value in empty tree.\n"); return (0); } zfs_btree_add_idx(bt, &i, &bt_idx); if ((p = (uint64_t *)zfs_btree_find(bt, &i, &bt_idx)) == NULL) { fprintf(stderr, "Did not find expected value.\n"); return (0); } /* Crash on inserting a duplicate */ zfs_btree_add_idx(bt, &i, NULL); return (0); } /* * Verify removing a non-existent value will cause a crash. * Note: negative test; return of 0 is a failure. */ static int remove_missing(zfs_btree_t *bt) { uint64_t *p, i = 23456; zfs_btree_index_t bt_idx = {0}; if ((p = (uint64_t *)zfs_btree_find(bt, &i, &bt_idx)) != NULL) { fprintf(stderr, "Found value in empty tree.\n"); return (0); } /* Crash removing a nonexistent entry */ zfs_btree_remove(bt, &i); return (0); } static int do_negative_test(zfs_btree_t *bt, char *test_name) { int rval = 0; struct rlimit rlim = {0}; (void) setrlimit(RLIMIT_CORE, &rlim); if (strcmp(test_name, "insert_duplicate") == 0) { rval = insert_duplicate(bt); } else if (strcmp(test_name, "remove_missing") == 0) { rval = remove_missing(bt); } /* * Return 0, since callers will expect non-zero return values for * these tests, and we should have crashed before getting here anyway. */ (void) fprintf(stderr, "Test: %s returned %d.\n", test_name, rval); return (0); } typedef struct btree_test { const char *name; int (*func)(zfs_btree_t *, char *); } btree_test_t; static btree_test_t test_table[] = { { "insert_find_remove", insert_find_remove }, { "find_without_index", find_without_index }, { "drain_tree", drain_tree }, { "stress_tree", stress_tree }, { NULL, NULL } }; int main(int argc, char *argv[]) { char *negative_test = NULL; int failed_tests = 0; struct timeval tp; zfs_btree_t bt; int c; while ((c = getopt(argc, argv, "c:l:n:r:st:")) != -1) { switch (c) { case 'c': contents_frequency = atoi(optarg); break; case 'l': tree_limit = atoi(optarg); break; case 'n': negative_test = optarg; break; case 'r': seed = atoi(optarg); break; case 's': stress_only = B_TRUE; break; case 't': stress_timeout = atoi(optarg); break; case 'h': default: usage(1); break; } } argc -= optind; argv += optind; optind = 1; if (seed == 0) { (void) gettimeofday(&tp, NULL); seed = tp.tv_sec; } srandom(seed); zfs_btree_init(); zfs_btree_create(&bt, zfs_btree_compare, sizeof (uint64_t)); /* * This runs the named negative test. None of them should * return, as they both cause crashes. */ if (negative_test) { return (do_negative_test(&bt, negative_test)); } fprintf(stderr, "Seed: %u\n", seed); /* * This is a stress test that does operations on a btree over the * requested timeout period, verifying them against identical * operations in an avl tree. */ if (stress_only != 0) { return (stress_tree(&bt, NULL)); } /* Do the positive tests */ btree_test_t *test = &test_table[0]; while (test->name) { int retval; uint64_t *rv; char why[BUFSIZE] = {0}; zfs_btree_index_t *idx = NULL; (void) fprintf(stdout, "%-20s", test->name); retval = test->func(&bt, why); if (retval == 0) { (void) fprintf(stdout, "ok\n"); } else { (void) fprintf(stdout, "failed with %d\n", retval); if (strlen(why) != 0) (void) fprintf(stdout, "\t%s\n", why); why[0] = '\0'; failed_tests++; } /* Remove all the elements and re-verify the tree */ while ((rv = zfs_btree_destroy_nodes(&bt, &idx)) != NULL) ; zfs_btree_verify(&bt); test++; } zfs_btree_verify(&bt); zfs_btree_fini(); return (failed_tests); } # # 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) 2012 by Delphix. All rights reserved. # PROG = chg_usr_exec include $(SRC)/cmd/Makefile.cmd include ../Makefile.subdirs /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include #include #include #define EXECSHELL "/usr/xpg4/bin/sh" int main(int argc, char *argv[]) { char *plogin = NULL; char cmds[BUFSIZ] = { 0 }; char sep[] = " "; struct passwd *ppw = NULL; int i, len; if (argc < 3 || strlen(argv[1]) == 0) { (void) printf("\tUsage: %s ...\n", argv[0]); return (1); } plogin = argv[1]; len = 0; for (i = 2; i < argc; i++) { (void) snprintf(cmds+len, sizeof (cmds)-len, "%s%s", argv[i], sep); len += strlen(argv[i]) + strlen(sep); } if ((ppw = getpwnam(plogin)) == NULL) { perror("getpwnam"); return (errno); } if (setgid(ppw->pw_gid) != 0) { perror("setgid"); return (errno); } if (setuid(ppw->pw_uid) != 0) { perror("setuid"); return (errno); } if (execl(EXECSHELL, "sh", "-c", cmds, (char *)NULL) != 0) { perror("execl: " EXECSHELL); return (errno); } return (0); } # # 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) 2012 by Delphix. All rights reserved. # PROG = devname2devid include $(SRC)/cmd/Makefile.cmd LDLIBS += -ldevid include ../Makefile.subdirs /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include #include #include #include /* * Usage: devname2devid * * Examples: * # ./devname2devid /dev/dsk/c1t4d0s0 * devid id1,sd@SSEAGATE_ST318404LSUN18G_3BT2G0Z300002146G4CR/a * # ./devname2devid /dev/dsk/c1t4d0 * devid id1,sd@SSEAGATE_ST318404LSUN18G_3BT2G0Z300002146G4CR/wd * # ./devname2devid /dev/dsk/c1t4d0s1 * devid id1,sd@SSEAGATE_ST318404LSUN18G_3BT2G0Z300002146G4CR/b * # * * This program accepts a disk or disk slice path and prints a * device id. * * Exit values: * 0 - means success * 1 - means failure * */ int main(int argc, char *argv[]) { int fd; ddi_devid_t devid; char *minor_name, *devidstr, *device; #ifdef DEBUG devid_nmlist_t *list = NULL; char *search_path; int i; #endif if (argc == 1) { (void) printf("%s [search path]\n", argv[0]); exit(1); } device = argv[1]; if ((fd = open(device, O_RDONLY|O_NDELAY)) < 0) { perror(device); exit(1); } if (devid_get(fd, &devid) != 0) { perror("devid_get"); exit(1); } if (devid_get_minor_name(fd, &minor_name) != 0) { perror("devid_get_minor_name"); exit(1); } if ((devidstr = devid_str_encode(devid, minor_name)) == 0) { perror("devid_str_encode"); exit(1); } (void) printf("devid %s\n", devidstr); devid_str_free(devidstr); #ifdef DEBUG if (argc == 3) { search_path = argv[2]; } else { search_path = "/dev/rdsk"; } if (devid_deviceid_to_nmlist(search_path, devid, DEVID_MINOR_NAME_ALL, &list)) { perror("devid_deviceid_to_nmlist"); exit(1); } /* loop through list and process device names and numbers */ for (i = 0; list[i].devname != NULL; i++) { (void) printf("devname: %s %p\n", list[i].devname, list[i].dev); } devid_free_nmlist(list); #endif /* DEBUG */ devid_str_free(minor_name); devid_free(devid); return (0); } # # 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) 2012 by Delphix. All rights reserved. # PROG = dir_rd_update include $(SRC)/cmd/Makefile.cmd include ../Makefile.subdirs /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Assertion: * * A read operation and directory update operation performed * concurrently on the same directory can lead to deadlock * on a UFS logging file system, but not on a ZFS file system. */ #include #include #include #include #include #include #include #include #define TMP_DIR /tmp static char dirpath[256]; int main(int argc, char **argv) { char *cp1 = ""; int i = 0; int ret = 0; int testdd = 0; pid_t pid; static const int op_num = 5; if (argc == 1) { (void) printf("Usage: %s \n", argv[0]); exit(-1); } for (i = 0; i < 256; i++) { dirpath[i] = 0; } cp1 = argv[1]; if (strlen(cp1) >= (sizeof (dirpath) - strlen("TMP_DIR"))) { (void) printf("The string length of mount point is " "too large\n"); exit(-1); } (void) strcpy(&dirpath[0], (const char *)cp1); (void) strcat(&dirpath[strlen(dirpath)], "TMP_DIR"); ret = mkdir(dirpath, 0777); if (ret != 0) { if (errno != EEXIST) { (void) printf("%s: mkdir(<%s>, 0777) failed: errno " "(decimal)=%d\n", argv[0], dirpath, errno); exit(-1); } } testdd = open(dirpath, O_RDONLY|O_RSYNC|O_SYNC|O_DSYNC); if (testdd < 0) { (void) printf("%s: open(<%s>, O_RDONLY|O_RSYNC|O_SYNC|O_DSYNC)" " failed: errno (decimal)=%d\n", argv[0], dirpath, errno); exit(-1); } else { (void) close(testdd); } pid = fork(); if (pid > 0) { int fd = open(dirpath, O_RDONLY|O_RSYNC|O_SYNC|O_DSYNC); char buf[16]; int rdret; int j = 0; while (j < op_num) { (void) sleep(1); rdret = read(fd, buf, 16); if (rdret == -1) { (void) printf("readdir failed"); } j++; } } else if (pid == 0) { int fd = open(dirpath, O_RDONLY); int chownret; int k = 0; while (k < op_num) { (void) sleep(1); chownret = fchown(fd, 0, 0); if (chownret == -1) { (void) printf("chown failed"); } k++; } } return (0); } # # 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 2017 Nexenta Systems, Inc. All rights reserved. # PROG = dos_ro include $(SRC)/cmd/Makefile.cmd LDLIBS += -lnvpair include ../Makefile.subdirs /* * 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 2017 Nexenta Systems, Inc. All rights reserved. */ #include #include #include #include #include #include #include #include #include extern const char *__progname; int vflag = 0; static int dosattr_set_ro(int fildes, const char *fname) { nvlist_t *nvl = NULL; int err; err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0); if (err != 0) return (err); (void) nvlist_add_boolean_value(nvl, A_READONLY, 1); if (fname == NULL) { err = fsetattr(fildes, XATTR_VIEW_READWRITE, nvl); } else { err = setattrat(fildes, XATTR_VIEW_READWRITE, fname, nvl); } if (err < 0) { err = errno; if (vflag > 1) { (void) fprintf(stderr, "dosattr_set: setattrat (%s), err %d\n", fname, err); } } nvlist_free(nvl); return (err); } void usage(void) { (void) fprintf(stderr, "usage: %s [-v] file\n", __progname); exit(1); } int main(int argc, char **argv) { char *fname; int c, fd, n; while ((c = getopt(argc, argv, "v")) != -1) { switch (c) { case 'v': vflag++; break; case '?': default: usage(); break; } } if (optind + 1 != argc) usage(); fname = argv[optind]; fd = open(fname, O_CREAT | O_RDWR, 0644); if (fd < 0) { perror(fname); exit(1); } if (vflag) (void) fprintf(stderr, "Write 1 (mode 644)\n"); n = write(fd, "mode 644 OK\n", 12); if (n != 12) { (void) fprintf(stderr, "write mode 644, err=%d\n", errno); exit(1); } if (vflag) (void) fprintf(stderr, "Chmod 444\n"); n = fchmod(fd, 0444); if (n < 0) { (void) fprintf(stderr, "chmod 444, err=%d\n", errno); exit(1); } if (vflag) (void) fprintf(stderr, "Write 2 (mode 444)\n"); n = write(fd, "mode 444 OK\n", 12); if (n != 12) { (void) fprintf(stderr, "write mode 444, err=%d\n", errno); exit(1); } if (vflag) (void) fprintf(stderr, "Set DOS R/O\n"); n = dosattr_set_ro(fd, NULL /* fname? */); if (n != 0) { (void) fprintf(stderr, "Set R/O, err=%d\n", n); exit(1); } /* * This fails, but write on an already open handle should succeed * the same as when we've set the mode to 444 after open. */ if (vflag) (void) fprintf(stderr, "Write 3 (DOS R/O)\n"); n = write(fd, "Write DOS RO?\n", 14); if (n != 14) { (void) fprintf(stderr, "write (DOS R/O), err=%d\n", errno); exit(1); } return (0); } # # 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) 2012 by Delphix. All rights reserved. # PROG = file_check include $(SRC)/cmd/Makefile.cmd include ../Makefile.subdirs /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright 2022 MNX Cloud, Inc. */ #include "../file_common.h" static unsigned char bigbuffer[BIGBUFFERSIZE]; /* * Given a filename, check that the file consists entirely * of a particular pattern. If the pattern is not specified a * default will be used. For default values see file_common.h */ int main(int argc, char **argv) { int bigfd; long i, n; uchar_t fillchar = DATA; int bigbuffersize = BIGBUFFERSIZE; int64_t read_count = 0; /* * Validate arguments */ if (argc < 2) { (void) printf("Usage: %s filename [pattern]\n", argv[0]); exit(1); } if (argv[2]) { fillchar = atoi(argv[2]); } /* * Read the file contents and check every character * against the supplied pattern. Abort if the * pattern check fails. */ if ((bigfd = open(argv[1], O_RDONLY)) == -1) { (void) printf("open %s failed %d\n", argv[1], errno); exit(1); } do { int exitcode; if ((n = read(bigfd, &bigbuffer, bigbuffersize)) == -1) { exitcode = errno; (void) printf("read failed (%ld), %d\n", n, errno); exit(exitcode); } for (i = 0; i < n; i++) { if (bigbuffer[i] != fillchar) { (void) printf("error %s: 0x%x != 0x%x)\n", argv[1], bigbuffer[i], fillchar); exit(1); } } read_count += n; } while (n == bigbuffersize); return (0); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef FILE_COMMON_H #define FILE_COMMON_H /* * header file for file_* utilities. These utilities * are used by the test cases to perform various file * operations (append writes, for example). */ #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include #include #include #include #define BLOCKSZ 8192 #define DATA 0xa5 #define DATA_RANGE 120 #define BIGBUFFERSIZE 0x800000 #define BIGFILESIZE 20 extern char *optarg; extern int optind, opterr, optopt; #ifdef __cplusplus } #endif #endif /* FILE_COMMON_H */ # # 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) 2012 by Delphix. All rights reserved. # PROG = file_trunc include $(SRC)/cmd/Makefile.cmd include ../Makefile.subdirs /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (c) 2012, 2014 by Delphix. All rights reserved. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define FSIZE 256*1024*1024 #define BSIZE 512 /* Initialize Globals */ static long fsize = FSIZE; static size_t bsize = BSIZE; static int count = 0; static int rflag = 0; static int seed = 0; static int vflag = 0; static int errflag = 0; static off_t offset = 0; static char *filename = NULL; static void usage(char *execname); static void parse_options(int argc, char *argv[]); static void do_write(int fd); static void do_trunc(int fd); static void usage(char *execname) { (void) fprintf(stderr, "usage: %s [-b blocksize] [-c count] [-f filesize]" " [-o offset] [-s seed] [-r] [-v] filename\n", execname); (void) exit(1); } int main(int argc, char *argv[]) { int i; int fd = -1; parse_options(argc, argv); fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0666); if (fd < 0) { perror("open"); exit(3); } for (i = 0; count == 0 || i < count; i++) { (void) do_write(fd); (void) do_trunc(fd); } (void) close(fd); return (0); } static void parse_options(int argc, char *argv[]) { int c; extern char *optarg; extern int optind, optopt; count = fsize / bsize; seed = time(NULL); while ((c = getopt(argc, argv, "b:c:f:o:rs:v")) != -1) { switch (c) { case 'b': bsize = atoi(optarg); break; case 'c': count = atoi(optarg); break; case 'f': fsize = atoi(optarg); break; case 'o': offset = atoi(optarg); break; case 'r': rflag++; break; case 's': seed = atoi(optarg); break; case 'v': vflag++; break; case ':': (void) fprintf(stderr, "Option -%c requires an operand\n", optopt); errflag++; break; case '?': (void) fprintf(stderr, "Unrecognized option: -%c\n", optopt); errflag++; break; } if (errflag) { (void) usage(argv[0]); } } if (argc <= optind) { (void) fprintf(stderr, "No filename specified\n"); usage(argv[0]); } filename = argv[optind]; if (vflag) { (void) fprintf(stderr, "Seed = %d\n", seed); } srandom(seed); } static void do_write(int fd) { off_t roffset = 0; char *buf = NULL; char *rbuf = NULL; buf = (char *)calloc(1, bsize); rbuf = (char *)calloc(1, bsize); if (buf == NULL || rbuf == NULL) { perror("malloc"); exit(4); } roffset = random() % fsize; if (lseek64(fd, (offset + roffset), SEEK_SET) < 0) { perror("lseek"); exit(5); } (void) strcpy(buf, "ZFS Test Suite Truncation Test"); if (write(fd, buf, bsize) < bsize) { perror("write"); exit(6); } if (rflag) { if (lseek64(fd, (offset + roffset), SEEK_SET) < 0) { perror("lseek"); exit(7); } if (read(fd, rbuf, bsize) < bsize) { perror("read"); exit(8); } if (memcmp(buf, rbuf, bsize) != 0) { perror("memcmp"); exit(9); } } if (vflag) { (void) fprintf(stderr, "Wrote to offset %lld\n", (offset + roffset)); if (rflag) { (void) fprintf(stderr, "Read back from offset %lld\n", (offset + roffset)); } } (void) free(buf); (void) free(rbuf); } static void do_trunc(int fd) { off_t roffset = 0; roffset = random() % fsize; if (ftruncate64(fd, (offset + roffset)) < 0) { perror("truncate"); exit(7); } if (vflag) { (void) fprintf(stderr, "Truncated at offset %lld\n", (offset + roffset)); } } # # 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) 2012 by Delphix. All rights reserved. # PROG = file_write include $(SRC)/cmd/Makefile.cmd include ../Makefile.subdirs /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright 2022 MNX Cloud, Inc. */ #include "../file_common.h" #include static unsigned char bigbuffer[BIGBUFFERSIZE]; /* * Writes (or appends) a given value to a file repeatedly. * See header file for defaults. */ static void usage(void); int main(int argc, char **argv) { int bigfd; int c; int oflag = 0; int err = 0; int k; long i; int64_t good_writes = 0; uchar_t nxtfillchar; /* * Default Parameters */ int write_count = BIGFILESIZE; uchar_t fillchar = DATA; int block_size = BLOCKSZ; char *filename = NULL; char *operation = NULL; offset_t noffset, offset = 0; int verbose = 0; int rsync = 0; int wsync = 0; int exitcode; /* * Process Arguments */ while ((c = getopt(argc, argv, "b:c:d:s:f:o:vwr")) != -1) { switch (c) { case 'b': block_size = atoi(optarg); break; case 'c': write_count = atoi(optarg); break; case 'd': fillchar = atoi(optarg); break; case 's': offset = atoll(optarg); break; case 'f': filename = optarg; break; case 'o': operation = optarg; break; case 'v': verbose = 1; break; case 'w': wsync = 1; break; case 'r': rsync = 1; break; case '?': (void) printf("unknown arg %c\n", optopt); usage(); break; } } /* * Validate Parameters */ if (!filename) { (void) printf("Filename not specified (-f )\n"); err++; } if (!operation) { (void) printf("Operation not specified (-o ).\n"); err++; } if (block_size > BIGBUFFERSIZE) { (void) printf("block_size is too large max==%d.\n", BIGBUFFERSIZE); err++; } if (err) usage(); /* * Prepare the buffer and determine the requested operation */ nxtfillchar = fillchar; k = 0; for (i = 0; i < block_size; i++) { bigbuffer[i] = nxtfillchar; if (fillchar == 0) { if ((k % DATA_RANGE) == 0) { k = 0; } nxtfillchar = k++; } } /* * using the strncmp of operation will make the operation match the * first shortest match - as the operations are unique from the first * character this means that we match single character operations */ if ((strncmp(operation, "create", strlen(operation) + 1)) == 0 || (strncmp(operation, "overwrite", strlen(operation) + 1)) == 0) { oflag = (O_RDWR|O_CREAT); } else if ((strncmp(operation, "append", strlen(operation) + 1)) == 0) { oflag = (O_RDWR|O_APPEND); } else { (void) printf("valid operations are not '%s'\n", operation); usage(); } if (rsync) { oflag = oflag | O_RSYNC; } if (wsync) { oflag = oflag | O_SYNC; } /* * Given an operation (create/overwrite/append), open the file * accordingly and perform a write of the appropriate type. */ if ((bigfd = open(filename, oflag, 0666)) == -1) { exitcode = errno; (void) printf("open %s: failed [%s]%d. Aborting!\n", filename, strerror(errno), errno); exit(exitcode); } noffset = llseek(bigfd, offset, SEEK_SET); if (noffset != offset) { exitcode = errno; (void) printf("llseek %s (%lld/%lld) failed [%s]%d.Aborting!\n", filename, offset, noffset, strerror(errno), errno); exit(exitcode); } if (verbose) { (void) printf("%s: block_size = %d, write_count = %d, " "offset = %lld, data = %s%d\n", filename, block_size, write_count, offset, (fillchar == 0) ? "0->" : "", (fillchar == 0) ? DATA_RANGE : fillchar); } for (i = 0; i < write_count; i++) { ssize_t n; if ((n = write(bigfd, &bigbuffer, block_size)) == -1) { exitcode = errno; (void) printf("write failed (%ld), good_writes = %lld, " "error: %s[%d]\n", (long)n, good_writes, strerror(errno), errno); exit(exitcode); } good_writes++; } if (verbose) { (void) printf("Success: good_writes = %lld (%lld)\n", good_writes, (good_writes * block_size)); } return (0); } static void usage(void) { char *base = (char *)"file_write"; char *exec = (char *)getexecname(); if (exec != NULL) exec = strdup(exec); if (exec != NULL) base = basename(exec); (void) printf("Usage: %s [-v] -o {create,overwrite,append} -f file_name" " [-b block_size]\n" "\t[-s offset] [-c write_count] [-d data]\n" "\twhere [data] equal to zero causes chars " "0->%d to be repeated throughout\n", base, DATA_RANGE); if (exec) { free(exec); } exit(1); } # # 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) 2014 by Delphix. All rights reserved. # PROG = getholes include $(SRC)/cmd/Makefile.cmd LDLIBS += -lcmdutils -lumem -lzfs include ../Makefile.subdirs /* * 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) 2014 by Delphix. All rights reserved. */ #include #include #include #include #include #include #include #include #include #include #include #define PRINT_HOLE 0x1 #define PRINT_DATA 0x2 #define PRINT_VERBOSE 0x4 extern int errno; static void usage(char *msg, int exit_value) { (void) fprintf(stderr, "getholes [-dhv] filename\n"); (void) fprintf(stderr, "%s\n", msg); exit(exit_value); } typedef struct segment { list_node_t seg_node; int seg_type; off_t seg_offset; off_t seg_len; } seg_t; /* * Return an appropriate whence value, depending on whether the file begins * with a holes or data. */ static int starts_with_hole(int fd) { off_t off; if ((off = lseek(fd, 0, SEEK_HOLE)) == -1) { /* ENXIO means no holes were found */ if (errno == ENXIO) return (SEEK_DATA); perror("lseek failed"); exit(1); } return (off == 0 ? SEEK_HOLE : SEEK_DATA); } static void print_list(list_t *seg_list, char *fname, int options) { uint64_t lz_holes, bs = 0; uint64_t hole_blks_seen = 0, data_blks_seen = 0; seg_t *seg; if (0 == bs) if (zfs_get_hole_count(fname, &lz_holes, &bs) != 0) { perror("zfs_get_hole_count"); exit(1); } while ((seg = list_remove_head(seg_list)) != NULL) { if (options & PRINT_VERBOSE) (void) fprintf(stdout, "%c %llu:%llu\n", seg->seg_type == SEEK_HOLE ? 'h' : 'd', seg->seg_offset, seg->seg_len); if (seg->seg_type == SEEK_HOLE) { hole_blks_seen += seg->seg_len / bs; } else { data_blks_seen += seg->seg_len / bs; } umem_free(seg, sizeof (seg_t)); } /* Verify libzfs sees the same number of hole blocks found manually. */ if (lz_holes != hole_blks_seen) { (void) fprintf(stderr, "Counted %llu holes, but libzfs found " "%llu\n", hole_blks_seen, lz_holes); exit(1); } if (options & PRINT_HOLE && options & PRINT_DATA) { (void) fprintf(stdout, "datablks: %llu\n", data_blks_seen); (void) fprintf(stdout, "holeblks: %llu\n", hole_blks_seen); return; } if (options & PRINT_DATA) (void) fprintf(stdout, "%llu\n", data_blks_seen); if (options & PRINT_HOLE) (void) fprintf(stdout, "%llu\n", hole_blks_seen); } int main(int argc, char *argv[]) { off_t len, off = 0; int c, fd, options = 0, whence = SEEK_DATA; struct stat statbuf; char *fname; list_t seg_list; seg_t *seg = NULL; list_create(&seg_list, sizeof (seg_t), offsetof(seg_t, seg_node)); while ((c = getopt(argc, argv, "dhv")) != -1) { switch (c) { case 'd': options |= PRINT_DATA; break; case 'h': options |= PRINT_HOLE; break; case 'v': options |= PRINT_VERBOSE; break; } } argc -= optind; argv += optind; if (argc != 1) usage("Incorrect number of arguments.", 1); if ((fname = argv[0]) == NULL) usage("No filename provided.", 1); if ((fd = open(fname, O_LARGEFILE | O_RDONLY)) < 0) { perror("open failed"); exit(1); } if (fstat(fd, &statbuf) != 0) { perror("fstat failed"); exit(1); } len = statbuf.st_size; whence = starts_with_hole(fd); while ((off = lseek(fd, off, whence)) != -1) { seg_t *s; seg = umem_alloc(sizeof (seg_t), UMEM_DEFAULT); seg->seg_type = whence; seg->seg_offset = off; list_insert_tail(&seg_list, seg); if ((s = list_prev(&seg_list, seg)) != NULL) s->seg_len = seg->seg_offset - s->seg_offset; whence = whence == SEEK_HOLE ? SEEK_DATA : SEEK_HOLE; } if (errno != ENXIO) { perror("lseek failed"); exit(1); } (void) close(fd); /* * If this file ends with a hole block, then populate the length of * the last segment, otherwise this is the end of the file, so * discard the remaining zero length segment. */ if (seg && seg->seg_offset != len) { seg->seg_len = len - seg->seg_offset; } else { (void) list_remove_tail(&seg_list); } print_list(&seg_list, fname, options); list_destroy(&seg_list); return (0); } # # This file and its contents are supplied under the terms of the # Common Development and Distribution License ("CDDL"), version 1.0. # You may only use this file in accordance with the terms of version # 1.0 of the CDDL. # # A full copy of the text of the CDDL should have accompanied this # source. A copy of the CDDL is also available via the Internet at # http://www.illumos.org/license/CDDL. # # # Copyright 2019 Joyent, Inc. # PROG = has_unmap include $(SRC)/cmd/Makefile.cmd LDLIBS += -lc include ../Makefile.subdirs /* * This file and its contents are supplied under the terms of the * Common Development and Distribution License ("CDDL"), version 1.0. * You may only use this file in accordance with the terms of version * 1.0 of the CDDL. * * A full copy of the text of the CDDL should have accompanied this * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* * Copyright 2019 Joyent, Inc. */ #include #include #include #include #include #include #include #include #include int main(int argc, char **argv) { int umap, fd; if (argc < 2) { fprintf(stderr, "missing disk name\n"); exit(2); } if ((fd = open(argv[1], O_RDONLY)) == -1) { fprintf(stderr, "couldn't open %s: %s\n", argv[1], strerror(errno)); exit(2); } if (ioctl(fd, DKIOC_CANFREE, &umap) < 0) { fprintf(stderr, "ioctl failed %s: %s\n", argv[1], strerror(errno)); exit(2); } (void) close(fd); return (umap ? 0 : 1); } # # 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) 2012 by Delphix. All rights reserved. # PROG = largest_file include $(SRC)/cmd/Makefile.cmd include ../Makefile.subdirs /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (c) 2012 by Delphix. All rights reserved. */ #include "../file_common.h" #include #include #include /* * -------------------------------------------------------------- * * Assertion: * The last byte of the largest file size can be * accessed without any errors. Also, the writing * beyond the last byte of the largest file size * will produce an errno of EFBIG. * * -------------------------------------------------------------- * If the write() system call below returns a "1", * then the last byte can be accessed. * -------------------------------------------------------------- */ static void sigxfsz(int); static void usage(char *); int main(int argc, char **argv) { int fd = 0; offset_t offset = (MAXOFFSET_T - 1); offset_t llseek_ret = 0; int write_ret = 0; int err = 0; char mybuf[5]; char *testfile; mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; if (argc != 2) { usage(argv[0]); } (void) sigset(SIGXFSZ, sigxfsz); testfile = strdup(argv[1]); fd = open(testfile, O_CREAT | O_RDWR, mode); if (fd < 0) { perror("Failed to create testfile"); err = errno; goto out; } llseek_ret = llseek(fd, offset, SEEK_SET); if (llseek_ret < 0) { perror("Failed to seek to end of testfile"); err = errno; goto out; } write_ret = write(fd, mybuf, 1); if (write_ret < 0) { perror("Failed to write to end of file"); err = errno; goto out; } offset = 0; llseek_ret = llseek(fd, offset, SEEK_CUR); if (llseek_ret < 0) { perror("Failed to seek to end of file"); err = errno; goto out; } write_ret = write(fd, mybuf, 1); if (write_ret < 0) { if (errno == EFBIG) { (void) printf("write errno=EFBIG: success\n"); err = 0; } else { perror("Did not receive EFBIG"); err = errno; } } else { (void) printf("write completed successfully, test failed\n"); err = 1; } out: (void) unlink(testfile); free(testfile); return (err); } static void usage(char *name) { (void) printf("%s \n", name); exit(1); } /* ARGSUSED */ static void sigxfsz(int signo) { (void) printf("\nlargest_file: sigxfsz() caught SIGXFSZ\n"); } /libzfs_input_check # # This file and its contents are supplied under the terms of the # Common Development and Distribution License ("CDDL"), version 1.0. # You may only use this file in accordance with the terms of version # 1.0 of the CDDL. # # A full copy of the text of the CDDL should have accompanied this # source. A copy of the CDDL is also available via the Internet at # http://www.illumos.org/license/CDDL. # # # Copyright 2020 Joyent, Inc. # PROG = libzfs_input_check include $(SRC)/cmd/Makefile.cmd include ../Makefile.subdirs CPPFLAGS += -I$(SRC)/uts/common/fs/zfs LDLIBS += -lnvpair -lzfs_core /* * 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) 2018 by Delphix. All rights reserved. * Copyright 2020 Joyent, Inc. */ #include #include #include #include #include #include #include #include #include #include #include #include /* * Test the nvpair inputs for the non-legacy zfs ioctl commands. */ boolean_t unexpected_failures; int zfs_fd; const char *active_test; /* * Tracks which zfs_ioc_t commands were tested */ boolean_t ioc_tested[256]; /* * Legacy ioctls that are skipped (for now) */ static unsigned ioc_skip[] = { ZFS_IOC_POOL_CREATE, ZFS_IOC_POOL_DESTROY, ZFS_IOC_POOL_IMPORT, ZFS_IOC_POOL_EXPORT, ZFS_IOC_POOL_CONFIGS, ZFS_IOC_POOL_STATS, ZFS_IOC_POOL_TRYIMPORT, ZFS_IOC_POOL_SCAN, ZFS_IOC_POOL_FREEZE, ZFS_IOC_POOL_UPGRADE, ZFS_IOC_POOL_GET_HISTORY, ZFS_IOC_VDEV_ADD, ZFS_IOC_VDEV_REMOVE, ZFS_IOC_VDEV_SET_STATE, ZFS_IOC_VDEV_ATTACH, ZFS_IOC_VDEV_DETACH, ZFS_IOC_VDEV_SETPATH, ZFS_IOC_VDEV_SETFRU, ZFS_IOC_OBJSET_STATS, ZFS_IOC_OBJSET_ZPLPROPS, ZFS_IOC_DATASET_LIST_NEXT, ZFS_IOC_SNAPSHOT_LIST_NEXT, ZFS_IOC_SET_PROP, ZFS_IOC_DESTROY, ZFS_IOC_RENAME, ZFS_IOC_RECV, ZFS_IOC_SEND, ZFS_IOC_INJECT_FAULT, ZFS_IOC_CLEAR_FAULT, ZFS_IOC_INJECT_LIST_NEXT, ZFS_IOC_ERROR_LOG, ZFS_IOC_CLEAR, ZFS_IOC_PROMOTE, ZFS_IOC_DSOBJ_TO_DSNAME, ZFS_IOC_OBJ_TO_PATH, ZFS_IOC_POOL_SET_PROPS, ZFS_IOC_POOL_GET_PROPS, ZFS_IOC_SET_FSACL, ZFS_IOC_GET_FSACL, ZFS_IOC_SHARE, ZFS_IOC_INHERIT_PROP, ZFS_IOC_SMB_ACL, ZFS_IOC_USERSPACE_ONE, ZFS_IOC_USERSPACE_MANY, ZFS_IOC_USERSPACE_UPGRADE, ZFS_IOC_OBJSET_RECVD_PROPS, ZFS_IOC_VDEV_SPLIT, ZFS_IOC_NEXT_OBJ, ZFS_IOC_DIFF, ZFS_IOC_TMP_SNAPSHOT, ZFS_IOC_OBJ_TO_STATS, ZFS_IOC_SPACE_WRITTEN, ZFS_IOC_POOL_REGUID, ZFS_IOC_SEND_PROGRESS, #ifndef __sun ZFS_IOC_EVENTS_NEXT, ZFS_IOC_EVENTS_CLEAR, ZFS_IOC_EVENTS_SEEK, ZFS_IOC_NEXTBOOT, ZFS_IOC_JAIL, ZFS_IOC_UNJAIL, #else /* This is still a legacy ioctl in illumos */ ZFS_IOC_POOL_REOPEN, #endif }; #define IOC_INPUT_TEST(ioc, name, req, opt, err) \ IOC_INPUT_TEST_IMPL(ioc, name, req, opt, err, B_FALSE) #define IOC_INPUT_TEST_WILD(ioc, name, req, opt, err) \ IOC_INPUT_TEST_IMPL(ioc, name, req, opt, err, B_TRUE) #define IOC_INPUT_TEST_IMPL(ioc, name, req, opt, err, wild) \ do { \ active_test = __func__ + 5; \ ioc_tested[ioc - ZFS_IOC_FIRST] = B_TRUE; \ (void) lzc_ioctl_test(ioc, name, req, opt, err, wild); \ } while (0) /* * run a zfs ioctl command, verify expected results and log failures */ static void lzc_ioctl_run(zfs_ioc_t ioc, const char *name, nvlist_t *innvl, int expected) { zfs_cmd_t zc = {"\0"}; char *packed = NULL; const char *variant; size_t size = 0; int error = 0; switch (expected) { case ZFS_ERR_IOC_ARG_UNAVAIL: variant = "unsupported input"; break; case ZFS_ERR_IOC_ARG_REQUIRED: variant = "missing input"; break; case ZFS_ERR_IOC_ARG_BADTYPE: variant = "invalid input type"; break; default: variant = "valid input"; break; } packed = fnvlist_pack(innvl, &size); (void) strncpy(zc.zc_name, name, sizeof (zc.zc_name)); zc.zc_name[sizeof (zc.zc_name) - 1] = '\0'; zc.zc_nvlist_src = (uint64_t)(uintptr_t)packed; zc.zc_nvlist_src_size = size; zc.zc_nvlist_dst_size = MAX(size * 2, 128 * 1024); zc.zc_nvlist_dst = (uint64_t)(uintptr_t)malloc(zc.zc_nvlist_dst_size); if (ioctl(zfs_fd, ioc, &zc) != 0) error = errno; if (error != expected) { unexpected_failures = B_TRUE; (void) fprintf(stderr, "%s: Unexpected result with %s, " "error %d (expecting %d)\n", active_test, variant, error, expected); } fnvlist_pack_free(packed, size); free((void *)(uintptr_t)zc.zc_nvlist_dst); } /* * Test each ioc for the following ioctl input errors: * ZFS_ERR_IOC_ARG_UNAVAIL an input argument is not supported by kernel * ZFS_ERR_IOC_ARG_REQUIRED a required input argument is missing * ZFS_ERR_IOC_ARG_BADTYPE an input argument has an invalid type */ static int lzc_ioctl_test(zfs_ioc_t ioc, const char *name, nvlist_t *required, nvlist_t *optional, int expected_error, boolean_t wildcard) { nvlist_t *input = fnvlist_alloc(); nvlist_t *future = fnvlist_alloc(); int error = 0; if (required != NULL) { for (nvpair_t *pair = nvlist_next_nvpair(required, NULL); pair != NULL; pair = nvlist_next_nvpair(required, pair)) { fnvlist_add_nvpair(input, pair); } } if (optional != NULL) { for (nvpair_t *pair = nvlist_next_nvpair(optional, NULL); pair != NULL; pair = nvlist_next_nvpair(optional, pair)) { fnvlist_add_nvpair(input, pair); } } /* * Generic input run with 'optional' nvlist pair */ if (!wildcard) fnvlist_add_nvlist(input, "optional", future); lzc_ioctl_run(ioc, name, input, expected_error); if (!wildcard) fnvlist_remove(input, "optional"); /* * Bogus input value */ if (!wildcard) { fnvlist_add_string(input, "bogus_input", "bogus"); lzc_ioctl_run(ioc, name, input, ZFS_ERR_IOC_ARG_UNAVAIL); fnvlist_remove(input, "bogus_input"); } /* * Missing required inputs */ if (required != NULL) { nvlist_t *empty = fnvlist_alloc(); lzc_ioctl_run(ioc, name, empty, ZFS_ERR_IOC_ARG_REQUIRED); nvlist_free(empty); } /* * Wrong nvpair type */ if (required != NULL || optional != NULL) { /* * switch the type of one of the input pairs */ for (nvpair_t *pair = nvlist_next_nvpair(input, NULL); pair != NULL; pair = nvlist_next_nvpair(input, pair)) { char pname[MAXNAMELEN]; data_type_t ptype; (void) strncpy(pname, nvpair_name(pair), sizeof (pname)); pname[sizeof (pname) - 1] = '\0'; ptype = nvpair_type(pair); fnvlist_remove_nvpair(input, pair); switch (ptype) { case DATA_TYPE_STRING: fnvlist_add_uint64(input, pname, 42); break; default: fnvlist_add_string(input, pname, "bogus"); break; } } lzc_ioctl_run(ioc, name, input, ZFS_ERR_IOC_ARG_BADTYPE); } nvlist_free(future); nvlist_free(input); return (error); } static void test_pool_sync(const char *pool) { nvlist_t *required = fnvlist_alloc(); fnvlist_add_boolean_value(required, "force", B_TRUE); IOC_INPUT_TEST(ZFS_IOC_POOL_SYNC, pool, required, NULL, 0); nvlist_free(required); } #ifndef sun static void test_pool_reopen(const char *pool) { nvlist_t *required = fnvlist_alloc(); fnvlist_add_boolean_value(required, "scrub_restart", B_FALSE); IOC_INPUT_TEST(ZFS_IOC_POOL_REOPEN, pool, required, NULL, 0); nvlist_free(required); } #endif static void test_pool_checkpoint(const char *pool) { IOC_INPUT_TEST(ZFS_IOC_POOL_CHECKPOINT, pool, NULL, NULL, 0); } static void test_pool_discard_checkpoint(const char *pool) { int err = lzc_pool_checkpoint(pool); if (err == 0 || err == ZFS_ERR_CHECKPOINT_EXISTS) IOC_INPUT_TEST(ZFS_IOC_POOL_DISCARD_CHECKPOINT, pool, NULL, NULL, 0); } static void test_log_history(const char *pool) { nvlist_t *required = fnvlist_alloc(); fnvlist_add_string(required, "message", "input check"); IOC_INPUT_TEST(ZFS_IOC_LOG_HISTORY, pool, required, NULL, 0); nvlist_free(required); } static void test_create(const char *pool) { char dataset[MAXNAMELEN + 32]; (void) snprintf(dataset, sizeof (dataset), "%s/create-fs", pool); nvlist_t *required = fnvlist_alloc(); nvlist_t *optional = fnvlist_alloc(); nvlist_t *props = fnvlist_alloc(); fnvlist_add_int32(required, "type", DMU_OST_ZFS); fnvlist_add_uint64(props, "recordsize", 8192); fnvlist_add_nvlist(optional, "props", props); IOC_INPUT_TEST(ZFS_IOC_CREATE, dataset, required, optional, 0); nvlist_free(required); nvlist_free(optional); } static void test_snapshot(const char *pool, const char *snapshot) { nvlist_t *required = fnvlist_alloc(); nvlist_t *optional = fnvlist_alloc(); nvlist_t *snaps = fnvlist_alloc(); nvlist_t *props = fnvlist_alloc(); fnvlist_add_boolean(snaps, snapshot); fnvlist_add_nvlist(required, "snaps", snaps); fnvlist_add_string(props, "org.openzfs:launch", "September 17th, 2013"); fnvlist_add_nvlist(optional, "props", props); IOC_INPUT_TEST(ZFS_IOC_SNAPSHOT, pool, required, optional, 0); nvlist_free(props); nvlist_free(snaps); nvlist_free(optional); nvlist_free(required); } static void test_space_snaps(const char *snapshot) { nvlist_t *required = fnvlist_alloc(); fnvlist_add_string(required, "firstsnap", snapshot); IOC_INPUT_TEST(ZFS_IOC_SPACE_SNAPS, snapshot, required, NULL, 0); nvlist_free(required); } static void test_destroy_snaps(const char *pool, const char *snapshot) { nvlist_t *required = fnvlist_alloc(); nvlist_t *snaps = fnvlist_alloc(); fnvlist_add_boolean(snaps, snapshot); fnvlist_add_nvlist(required, "snaps", snaps); IOC_INPUT_TEST(ZFS_IOC_DESTROY_SNAPS, pool, required, NULL, 0); nvlist_free(snaps); nvlist_free(required); } static void test_bookmark(const char *pool, const char *snapshot, const char *bookmark) { nvlist_t *required = fnvlist_alloc(); fnvlist_add_string(required, bookmark, snapshot); IOC_INPUT_TEST_WILD(ZFS_IOC_BOOKMARK, pool, required, NULL, 0); nvlist_free(required); } static void test_get_bookmarks(const char *dataset) { nvlist_t *optional = fnvlist_alloc(); fnvlist_add_boolean(optional, "guid"); fnvlist_add_boolean(optional, "createtxg"); fnvlist_add_boolean(optional, "creation"); IOC_INPUT_TEST_WILD(ZFS_IOC_GET_BOOKMARKS, dataset, NULL, optional, 0); nvlist_free(optional); } static void test_destroy_bookmarks(const char *pool, const char *bookmark) { nvlist_t *required = fnvlist_alloc(); fnvlist_add_boolean(required, bookmark); IOC_INPUT_TEST_WILD(ZFS_IOC_DESTROY_BOOKMARKS, pool, required, NULL, 0); nvlist_free(required); } static void test_clone(const char *snapshot, const char *clone) { nvlist_t *required = fnvlist_alloc(); nvlist_t *optional = fnvlist_alloc(); nvlist_t *props = fnvlist_alloc(); fnvlist_add_string(required, "origin", snapshot); IOC_INPUT_TEST(ZFS_IOC_CLONE, clone, required, NULL, 0); nvlist_free(props); nvlist_free(optional); nvlist_free(required); } static void test_rollback(const char *dataset, const char *snapshot) { nvlist_t *optional = fnvlist_alloc(); fnvlist_add_string(optional, "target", snapshot); IOC_INPUT_TEST(ZFS_IOC_ROLLBACK, dataset, NULL, optional, B_FALSE); nvlist_free(optional); } static void test_hold(const char *pool, const char *snapshot) { nvlist_t *required = fnvlist_alloc(); nvlist_t *optional = fnvlist_alloc(); nvlist_t *holds = fnvlist_alloc(); fnvlist_add_string(holds, snapshot, "libzfs_check_hold"); fnvlist_add_nvlist(required, "holds", holds); fnvlist_add_int32(optional, "cleanup_fd", zfs_fd); IOC_INPUT_TEST(ZFS_IOC_HOLD, pool, required, optional, 0); nvlist_free(holds); nvlist_free(optional); nvlist_free(required); } static void test_get_holds(const char *snapshot) { IOC_INPUT_TEST(ZFS_IOC_GET_HOLDS, snapshot, NULL, NULL, 0); } static void test_release(const char *pool, const char *snapshot) { nvlist_t *required = fnvlist_alloc(); nvlist_t *release = fnvlist_alloc(); fnvlist_add_boolean(release, "libzfs_check_hold"); fnvlist_add_nvlist(required, snapshot, release); IOC_INPUT_TEST_WILD(ZFS_IOC_RELEASE, pool, required, NULL, 0); nvlist_free(release); nvlist_free(required); } static void test_send_new(const char *snapshot, int fd) { nvlist_t *required = fnvlist_alloc(); nvlist_t *optional = fnvlist_alloc(); fnvlist_add_int32(required, "fd", fd); fnvlist_add_boolean(optional, "largeblockok"); fnvlist_add_boolean(optional, "embedok"); fnvlist_add_boolean(optional, "compressok"); fnvlist_add_boolean(optional, "rawok"); /* * TODO - Resumable send is harder to set up. So we currently * ignore testing for that variant. */ #if 0 fnvlist_add_string(optional, "fromsnap", from); fnvlist_add_uint64(optional, "resume_object", resumeobj); fnvlist_add_uint64(optional, "resume_offset", offset); #endif IOC_INPUT_TEST(ZFS_IOC_SEND_NEW, snapshot, required, optional, 0); nvlist_free(optional); nvlist_free(required); } #ifndef __sun static void test_recv_new(const char *dataset, int fd) { dmu_replay_record_t drr = { 0 }; nvlist_t *required = fnvlist_alloc(); nvlist_t *optional = fnvlist_alloc(); nvlist_t *props = fnvlist_alloc(); char snapshot[MAXNAMELEN + 32]; ssize_t count; int cleanup_fd = open(ZFS_DEV, O_RDWR); (void) snprintf(snapshot, sizeof (snapshot), "%s@replicant", dataset); count = pread(fd, &drr, sizeof (drr), 0); if (count != sizeof (drr)) { (void) fprintf(stderr, "could not read stream: %s\n", strerror(errno)); } fnvlist_add_string(required, "snapname", snapshot); fnvlist_add_byte_array(required, "begin_record", (uchar_t *)&drr, sizeof (drr)); fnvlist_add_int32(required, "input_fd", fd); fnvlist_add_string(props, "org.openzfs:launch", "September 17th, 2013"); fnvlist_add_nvlist(optional, "localprops", props); fnvlist_add_boolean(optional, "force"); fnvlist_add_int32(optional, "cleanup_fd", cleanup_fd); /* * TODO - Resumable receive is harder to set up. So we currently * ignore testing for one. */ #if 0 fnvlist_add_nvlist(optional, "props", recvdprops); fnvlist_add_string(optional, "origin", origin); fnvlist_add_boolean(optional, "resumable"); fnvlist_add_uint64(optional, "action_handle", *action_handle); #endif IOC_INPUT_TEST(ZFS_IOC_RECV_NEW, dataset, required, optional, EBADE); nvlist_free(props); nvlist_free(optional); nvlist_free(required); (void) close(cleanup_fd); } #endif static void test_send_space(const char *snapshot1, const char *snapshot2) { nvlist_t *optional = fnvlist_alloc(); fnvlist_add_string(optional, "from", snapshot1); fnvlist_add_boolean(optional, "largeblockok"); fnvlist_add_boolean(optional, "embedok"); fnvlist_add_boolean(optional, "compressok"); fnvlist_add_boolean(optional, "rawok"); IOC_INPUT_TEST(ZFS_IOC_SEND_SPACE, snapshot2, NULL, optional, 0); nvlist_free(optional); } static void test_remap(const char *dataset) { IOC_INPUT_TEST(ZFS_IOC_REMAP, dataset, NULL, NULL, 0); } static void test_channel_program(const char *pool) { const char *program = "arg = ...\n" "argv = arg[\"argv\"]\n" "return argv[1]"; char *const argv[1] = { "Hello World!" }; nvlist_t *required = fnvlist_alloc(); nvlist_t *optional = fnvlist_alloc(); nvlist_t *args = fnvlist_alloc(); fnvlist_add_string(required, "program", program); fnvlist_add_string_array(args, "argv", argv, 1); fnvlist_add_nvlist(required, "arg", args); fnvlist_add_boolean_value(optional, "sync", B_TRUE); fnvlist_add_uint64(optional, "instrlimit", 1000 * 1000); fnvlist_add_uint64(optional, "memlimit", 8192 * 1024); IOC_INPUT_TEST(ZFS_IOC_CHANNEL_PROGRAM, pool, required, optional, 0); nvlist_free(args); nvlist_free(optional); nvlist_free(required); } #define WRAPPING_KEY_LEN 32 static void test_load_key(const char *dataset) { nvlist_t *required = fnvlist_alloc(); nvlist_t *optional = fnvlist_alloc(); nvlist_t *hidden = fnvlist_alloc(); uint8_t keydata[WRAPPING_KEY_LEN] = {0}; fnvlist_add_uint8_array(hidden, "wkeydata", keydata, sizeof (keydata)); fnvlist_add_nvlist(required, "hidden_args", hidden); fnvlist_add_boolean(optional, "noop"); IOC_INPUT_TEST(ZFS_IOC_LOAD_KEY, dataset, required, optional, EINVAL); nvlist_free(hidden); nvlist_free(optional); nvlist_free(required); } static void test_change_key(const char *dataset) { IOC_INPUT_TEST(ZFS_IOC_CHANGE_KEY, dataset, NULL, NULL, EINVAL); } static void test_unload_key(const char *dataset) { IOC_INPUT_TEST(ZFS_IOC_UNLOAD_KEY, dataset, NULL, NULL, EACCES); } static void test_vdev_initialize(const char *pool) { nvlist_t *required = fnvlist_alloc(); nvlist_t *vdev_guids = fnvlist_alloc(); fnvlist_add_uint64(vdev_guids, "path", 0xdeadbeefdeadbeef); fnvlist_add_uint64(required, ZPOOL_INITIALIZE_COMMAND, POOL_INITIALIZE_START); fnvlist_add_nvlist(required, ZPOOL_INITIALIZE_VDEVS, vdev_guids); IOC_INPUT_TEST(ZFS_IOC_POOL_INITIALIZE, pool, required, NULL, EINVAL); nvlist_free(vdev_guids); nvlist_free(required); } static void test_vdev_trim(const char *pool) { nvlist_t *required = fnvlist_alloc(); nvlist_t *optional = fnvlist_alloc(); nvlist_t *vdev_guids = fnvlist_alloc(); fnvlist_add_uint64(vdev_guids, "path", 0xdeadbeefdeadbeef); fnvlist_add_uint64(required, ZPOOL_TRIM_COMMAND, POOL_TRIM_START); fnvlist_add_nvlist(required, ZPOOL_TRIM_VDEVS, vdev_guids); fnvlist_add_uint64(optional, ZPOOL_TRIM_RATE, 1ULL << 30); fnvlist_add_boolean_value(optional, ZPOOL_TRIM_SECURE, B_TRUE); IOC_INPUT_TEST(ZFS_IOC_POOL_TRIM, pool, required, optional, EINVAL); nvlist_free(vdev_guids); nvlist_free(optional); nvlist_free(required); } static int zfs_destroy(const char *dataset) { zfs_cmd_t zc = {"\0"}; int err; (void) strncpy(zc.zc_name, dataset, sizeof (zc.zc_name)); zc.zc_name[sizeof (zc.zc_name) - 1] = '\0'; zc.zc_objset_type = DMU_OST_ZFS; err = ioctl(zfs_fd, ZFS_IOC_DESTROY, &zc); return (err == 0 ? 0 : errno); } static void test_get_bootenv(const char *pool) { IOC_INPUT_TEST(ZFS_IOC_GET_BOOTENV, pool, NULL, NULL, 0); } static void test_set_bootenv(const char *pool) { nvlist_t *required = fnvlist_alloc(); fnvlist_add_uint64(required, "version", VB_RAW); fnvlist_add_string(required, GRUB_ENVMAP, "test"); IOC_INPUT_TEST_WILD(ZFS_IOC_SET_BOOTENV, pool, required, NULL, 0); nvlist_free(required); } static void zfs_ioc_input_tests(const char *pool) { char filepath[] = "/tmp/ioc_test_file_XXXXXX"; char dataset[ZFS_MAX_DATASET_NAME_LEN]; char snapbase[ZFS_MAX_DATASET_NAME_LEN + 32]; char snapshot[ZFS_MAX_DATASET_NAME_LEN + 32]; char bookmark[ZFS_MAX_DATASET_NAME_LEN + 32]; char backup[ZFS_MAX_DATASET_NAME_LEN]; char clone[ZFS_MAX_DATASET_NAME_LEN]; int tmpfd, err; /* * Setup names and create a working dataset */ (void) snprintf(dataset, sizeof (dataset), "%s/test-fs", pool); (void) snprintf(snapbase, sizeof (snapbase), "%s@snapbase", dataset); (void) snprintf(snapshot, sizeof (snapshot), "%s@snapshot", dataset); (void) snprintf(bookmark, sizeof (bookmark), "%s#bookmark", dataset); (void) snprintf(clone, sizeof (clone), "%s/test-fs-clone", pool); (void) snprintf(backup, sizeof (backup), "%s/backup", pool); err = lzc_create(dataset, LZC_DATSET_TYPE_ZFS, NULL, NULL, 0); if (err) { (void) fprintf(stderr, "could not create '%s': %s\n", dataset, strerror(errno)); exit(2); } tmpfd = mkstemp(filepath); if (tmpfd < 0) { (void) fprintf(stderr, "could not create '%s': %s\n", filepath, strerror(errno)); exit(2); } /* * run a test for each ioctl * Note that some test build on previous test operations */ test_pool_sync(pool); #ifndef __sun test_pool_reopen(pool); #endif test_pool_checkpoint(pool); test_pool_discard_checkpoint(pool); test_log_history(pool); test_create(dataset); test_snapshot(pool, snapbase); test_snapshot(pool, snapshot); test_space_snaps(snapshot); test_send_space(snapbase, snapshot); test_send_new(snapshot, tmpfd); #ifndef __sun test_recv_new(backup, tmpfd); #endif test_bookmark(pool, snapshot, bookmark); test_get_bookmarks(dataset); test_destroy_bookmarks(pool, bookmark); test_hold(pool, snapshot); test_get_holds(snapshot); test_release(pool, snapshot); test_clone(snapshot, clone); (void) zfs_destroy(clone); test_rollback(dataset, snapshot); test_destroy_snaps(pool, snapshot); test_destroy_snaps(pool, snapbase); test_remap(dataset); test_channel_program(pool); test_load_key(dataset); test_change_key(dataset); test_unload_key(dataset); test_vdev_initialize(pool); test_vdev_trim(pool); test_set_bootenv(pool); test_get_bootenv(pool); /* * cleanup */ zfs_cmd_t zc = {"\0"}; nvlist_t *snaps = fnvlist_alloc(); fnvlist_add_boolean(snaps, snapshot); (void) lzc_destroy_snaps(snaps, B_FALSE, NULL); nvlist_free(snaps); (void) zfs_destroy(dataset); (void) zfs_destroy(backup); (void) close(tmpfd); (void) unlink(filepath); /* * All the unused slots should yield ZFS_ERR_IOC_CMD_UNAVAIL */ for (int i = 0; i < ARRAY_SIZE(ioc_skip); i++) { if (ioc_tested[ioc_skip[i] - ZFS_IOC_FIRST]) (void) fprintf(stderr, "cmd %d tested, not skipped!\n", (int)(ioc_skip[i] - ZFS_IOC_FIRST)); ioc_tested[ioc_skip[i] - ZFS_IOC_FIRST] = B_TRUE; } (void) strncpy(zc.zc_name, pool, sizeof (zc.zc_name)); zc.zc_name[sizeof (zc.zc_name) - 1] = '\0'; for (unsigned ioc = ZFS_IOC_FIRST; ioc < ZFS_IOC_LAST; ioc++) { unsigned cmd = ioc - ZFS_IOC_FIRST; if (ioc_tested[cmd]) continue; if (ioctl(zfs_fd, ioc, &zc) != 0 && errno != ZFS_ERR_IOC_CMD_UNAVAIL) { (void) fprintf(stderr, "cmd %d is missing a test case " "(%d)\n", cmd, errno); } } } enum zfs_ioc_ref { #ifdef __FreeBSD__ ZFS_IOC_BASE = 0, #else ZFS_IOC_BASE = ('Z' << 8), #endif ZFS_IOC_PLATFORM_BASE = ZFS_IOC_BASE + 0x80, }; /* * Canonical reference check of /dev/zfs ioctl numbers. * These cannot change and new ioctl numbers must be appended. */ boolean_t validate_ioc_values(void) { boolean_t result = B_TRUE; #define CHECK(expr) do { \ if (!(expr)) { \ result = B_FALSE; \ fprintf(stderr, "(%s) === FALSE\n", #expr); \ } \ } while (0) CHECK(ZFS_IOC_BASE + 0 == ZFS_IOC_POOL_CREATE); CHECK(ZFS_IOC_BASE + 1 == ZFS_IOC_POOL_DESTROY); CHECK(ZFS_IOC_BASE + 2 == ZFS_IOC_POOL_IMPORT); CHECK(ZFS_IOC_BASE + 3 == ZFS_IOC_POOL_EXPORT); CHECK(ZFS_IOC_BASE + 4 == ZFS_IOC_POOL_CONFIGS); CHECK(ZFS_IOC_BASE + 5 == ZFS_IOC_POOL_STATS); CHECK(ZFS_IOC_BASE + 6 == ZFS_IOC_POOL_TRYIMPORT); CHECK(ZFS_IOC_BASE + 7 == ZFS_IOC_POOL_SCAN); CHECK(ZFS_IOC_BASE + 8 == ZFS_IOC_POOL_FREEZE); CHECK(ZFS_IOC_BASE + 9 == ZFS_IOC_POOL_UPGRADE); CHECK(ZFS_IOC_BASE + 10 == ZFS_IOC_POOL_GET_HISTORY); CHECK(ZFS_IOC_BASE + 11 == ZFS_IOC_VDEV_ADD); CHECK(ZFS_IOC_BASE + 12 == ZFS_IOC_VDEV_REMOVE); CHECK(ZFS_IOC_BASE + 13 == ZFS_IOC_VDEV_SET_STATE); CHECK(ZFS_IOC_BASE + 14 == ZFS_IOC_VDEV_ATTACH); CHECK(ZFS_IOC_BASE + 15 == ZFS_IOC_VDEV_DETACH); CHECK(ZFS_IOC_BASE + 16 == ZFS_IOC_VDEV_SETPATH); CHECK(ZFS_IOC_BASE + 17 == ZFS_IOC_VDEV_SETFRU); CHECK(ZFS_IOC_BASE + 18 == ZFS_IOC_OBJSET_STATS); CHECK(ZFS_IOC_BASE + 19 == ZFS_IOC_OBJSET_ZPLPROPS); CHECK(ZFS_IOC_BASE + 20 == ZFS_IOC_DATASET_LIST_NEXT); CHECK(ZFS_IOC_BASE + 21 == ZFS_IOC_SNAPSHOT_LIST_NEXT); CHECK(ZFS_IOC_BASE + 22 == ZFS_IOC_SET_PROP); CHECK(ZFS_IOC_BASE + 23 == ZFS_IOC_CREATE); CHECK(ZFS_IOC_BASE + 24 == ZFS_IOC_DESTROY); CHECK(ZFS_IOC_BASE + 25 == ZFS_IOC_ROLLBACK); CHECK(ZFS_IOC_BASE + 26 == ZFS_IOC_RENAME); CHECK(ZFS_IOC_BASE + 27 == ZFS_IOC_RECV); CHECK(ZFS_IOC_BASE + 28 == ZFS_IOC_SEND); CHECK(ZFS_IOC_BASE + 29 == ZFS_IOC_INJECT_FAULT); CHECK(ZFS_IOC_BASE + 30 == ZFS_IOC_CLEAR_FAULT); CHECK(ZFS_IOC_BASE + 31 == ZFS_IOC_INJECT_LIST_NEXT); CHECK(ZFS_IOC_BASE + 32 == ZFS_IOC_ERROR_LOG); CHECK(ZFS_IOC_BASE + 33 == ZFS_IOC_CLEAR); CHECK(ZFS_IOC_BASE + 34 == ZFS_IOC_PROMOTE); CHECK(ZFS_IOC_BASE + 35 == ZFS_IOC_SNAPSHOT); CHECK(ZFS_IOC_BASE + 36 == ZFS_IOC_DSOBJ_TO_DSNAME); CHECK(ZFS_IOC_BASE + 37 == ZFS_IOC_OBJ_TO_PATH); CHECK(ZFS_IOC_BASE + 38 == ZFS_IOC_POOL_SET_PROPS); CHECK(ZFS_IOC_BASE + 39 == ZFS_IOC_POOL_GET_PROPS); CHECK(ZFS_IOC_BASE + 40 == ZFS_IOC_SET_FSACL); CHECK(ZFS_IOC_BASE + 41 == ZFS_IOC_GET_FSACL); CHECK(ZFS_IOC_BASE + 42 == ZFS_IOC_SHARE); CHECK(ZFS_IOC_BASE + 43 == ZFS_IOC_INHERIT_PROP); CHECK(ZFS_IOC_BASE + 44 == ZFS_IOC_SMB_ACL); CHECK(ZFS_IOC_BASE + 45 == ZFS_IOC_USERSPACE_ONE); CHECK(ZFS_IOC_BASE + 46 == ZFS_IOC_USERSPACE_MANY); CHECK(ZFS_IOC_BASE + 47 == ZFS_IOC_USERSPACE_UPGRADE); CHECK(ZFS_IOC_BASE + 48 == ZFS_IOC_HOLD); CHECK(ZFS_IOC_BASE + 49 == ZFS_IOC_RELEASE); CHECK(ZFS_IOC_BASE + 50 == ZFS_IOC_GET_HOLDS); CHECK(ZFS_IOC_BASE + 51 == ZFS_IOC_OBJSET_RECVD_PROPS); CHECK(ZFS_IOC_BASE + 52 == ZFS_IOC_VDEV_SPLIT); CHECK(ZFS_IOC_BASE + 53 == ZFS_IOC_NEXT_OBJ); CHECK(ZFS_IOC_BASE + 54 == ZFS_IOC_DIFF); CHECK(ZFS_IOC_BASE + 55 == ZFS_IOC_TMP_SNAPSHOT); CHECK(ZFS_IOC_BASE + 56 == ZFS_IOC_OBJ_TO_STATS); CHECK(ZFS_IOC_BASE + 57 == ZFS_IOC_SPACE_WRITTEN); CHECK(ZFS_IOC_BASE + 58 == ZFS_IOC_SPACE_SNAPS); CHECK(ZFS_IOC_BASE + 59 == ZFS_IOC_DESTROY_SNAPS); CHECK(ZFS_IOC_BASE + 60 == ZFS_IOC_POOL_REGUID); CHECK(ZFS_IOC_BASE + 61 == ZFS_IOC_POOL_REOPEN); CHECK(ZFS_IOC_BASE + 62 == ZFS_IOC_SEND_PROGRESS); CHECK(ZFS_IOC_BASE + 63 == ZFS_IOC_LOG_HISTORY); CHECK(ZFS_IOC_BASE + 64 == ZFS_IOC_SEND_NEW); CHECK(ZFS_IOC_BASE + 65 == ZFS_IOC_SEND_SPACE); CHECK(ZFS_IOC_BASE + 66 == ZFS_IOC_CLONE); CHECK(ZFS_IOC_BASE + 67 == ZFS_IOC_BOOKMARK); CHECK(ZFS_IOC_BASE + 68 == ZFS_IOC_GET_BOOKMARKS); CHECK(ZFS_IOC_BASE + 69 == ZFS_IOC_DESTROY_BOOKMARKS); #ifndef __sun CHECK(ZFS_IOC_BASE + 71 == ZFS_IOC_RECV_NEW); #endif CHECK(ZFS_IOC_BASE + 70 == ZFS_IOC_POOL_SYNC); CHECK(ZFS_IOC_BASE + 71 == ZFS_IOC_CHANNEL_PROGRAM); CHECK(ZFS_IOC_BASE + 72 == ZFS_IOC_LOAD_KEY); CHECK(ZFS_IOC_BASE + 73 == ZFS_IOC_UNLOAD_KEY); CHECK(ZFS_IOC_BASE + 74 == ZFS_IOC_CHANGE_KEY); CHECK(ZFS_IOC_BASE + 75 == ZFS_IOC_REMAP); CHECK(ZFS_IOC_BASE + 76 == ZFS_IOC_POOL_CHECKPOINT); #ifndef __sun CHECK(ZFS_IOC_BASE + 78 == ZFS_IOC_POOL_DISCARD_CHECKPOINT); CHECK(ZFS_IOC_PLATFORM_BASE + 1 == ZFS_IOC_EVENTS_NEXT); CHECK(ZFS_IOC_PLATFORM_BASE + 2 == ZFS_IOC_EVENTS_CLEAR); CHECK(ZFS_IOC_PLATFORM_BASE + 3 == ZFS_IOC_EVENTS_SEEK); #else CHECK(ZFS_IOC_BASE + 77 == ZFS_IOC_POOL_DISCARD_CHECKPOINT); CHECK(ZFS_IOC_BASE + 78 == ZFS_IOC_POOL_INITIALIZE); CHECK(ZFS_IOC_BASE + 79 == ZFS_IOC_POOL_TRIM); CHECK(ZFS_IOC_BASE + 80 == ZFS_IOC_REDACT); CHECK(ZFS_IOC_BASE + 81 == ZFS_IOC_GET_BOOKMARK_PROPS); #endif CHECK(ZFS_IOC_PLATFORM_BASE + 7 == ZFS_IOC_SET_BOOTENV); CHECK(ZFS_IOC_PLATFORM_BASE + 8 == ZFS_IOC_GET_BOOTENV); #undef CHECK return (result); } int main(int argc, const char *argv[]) { if (argc != 2) { (void) fprintf(stderr, "usage: %s \n", argv[0]); exit(2); } if (!validate_ioc_values()) { (void) fprintf(stderr, "WARNING: zfs_ioc_t has binary " "incompatible command values\n"); exit(3); } (void) libzfs_core_init(); zfs_fd = open(ZFS_DEV, O_RDWR|O_EXCL); if (zfs_fd < 0) { (void) fprintf(stderr, "open: %s\n", strerror(errno)); libzfs_core_fini(); exit(2); } zfs_ioc_input_tests(argv[1]); (void) close(zfs_fd); libzfs_core_fini(); return (unexpected_failures); } # # 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 = memory_balloon include $(SRC)/cmd/Makefile.cmd include ../Makefile.subdirs /* * 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. */ /* * Steal memory from the kernel, forcing the ARC to decrease in size, and hold * it until the process receives a signal. */ #include #include #include #include #include #include #include static void usage(char *progname) { (void) fprintf(stderr, "Usage: %s -f \n", progname); exit(1); } static void fail(char *err, int rval) { perror(err); exit(rval); } static void daemonize(void) { pid_t pid; if ((pid = fork()) < 0) { fail("fork", 1); } else if (pid != 0) { (void) fprintf(stdout, "%ld\n", pid); exit(0); } (void) setsid(); (void) close(0); (void) close(1); (void) close(2); } int main(int argc, char *argv[]) { int c; boolean_t fflag = B_FALSE; char *prog = argv[0]; long long size; char *stroll_leftovers; int shm_id; void *shm_attached; while ((c = getopt(argc, argv, "f")) != -1) { switch (c) { /* Run in the foreground */ case 'f': fflag = B_TRUE; break; default: usage(prog); } } argc -= optind; argv += optind; if (argc != 1) usage(prog); size = strtoll(argv[0], &stroll_leftovers, 10); if (size <= 0) fail("invalid size in bytes", 1); if ((shm_id = shmget(IPC_PRIVATE, size, IPC_CREAT|IPC_EXCL)) == -1) fail("shmget", 1); if ((shm_attached = shmat(shm_id, NULL, SHM_SHARE_MMU)) == (void *)-1) fail("shmat", 1); if (fflag == B_FALSE) daemonize(); (void) pause(); /* NOTREACHED */ return (0); } # # 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) 2012 by Delphix. All rights reserved. # PROG = mkbusy include $(SRC)/cmd/Makefile.cmd include ../Makefile.subdirs /* * 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) 2012 by Delphix. All rights reserved. */ /* * Make a directory busy. If the argument is an existing file or directory, * simply open it directly and pause. If not, verify that the parent directory * exists, and create a new file in that directory. */ #include #include #include #include #include #include #include #include #include static void usage(char *progname) { (void) fprintf(stderr, "Usage: %s \n", progname); exit(1); } static void fail(char *err, int rval) { perror(err); exit(rval); } static void daemonize(void) { pid_t pid; if ((pid = fork()) < 0) { fail("fork", 1); } else if (pid != 0) { (void) fprintf(stdout, "%ld\n", pid); exit(0); } (void) setsid(); (void) close(0); (void) close(1); (void) close(2); } int main(int argc, char *argv[]) { int ret, c; boolean_t isdir = B_FALSE; boolean_t fflag = B_FALSE; boolean_t rflag = B_FALSE; struct stat sbuf; char *fpath = NULL; char *prog = argv[0]; while ((c = getopt(argc, argv, "fr")) != -1) { switch (c) { /* Open the file or directory read only */ case 'r': rflag = B_TRUE; break; /* Run in the foreground */ case 'f': fflag = B_TRUE; break; default: usage(prog); } } argc -= optind; argv += optind; if (argc != 1) usage(prog); if ((ret = stat(argv[0], &sbuf)) != 0) { char *arg, *dname, *fname; int arglen, dlen, flen; char *slash; /* * The argument supplied doesn't exist. Copy the path, and * remove the trailing slash if presnt. */ if ((arg = strdup(argv[0])) == NULL) fail("strdup", 1); arglen = strlen(arg); if (arg[arglen - 1] == '/') arg[arglen - 1] = '\0'; /* * Get the directory and file names, using the current directory * if the provided path doesn't specify a directory at all. */ if ((slash = strrchr(arg, '/')) == NULL) { dname = strdup("."); fname = strdup(arg); } else { *slash = '\0'; dname = strdup(arg); fname = strdup(slash + 1); } free(arg); if (dname == NULL || fname == NULL) fail("strdup", 1); dlen = strlen(dname); flen = strlen(fname); /* The directory portion of the path must exist */ if ((ret = stat(dname, &sbuf)) != 0 || !(sbuf.st_mode & S_IFDIR)) usage(prog); if ((fpath = (char *)malloc(dlen + 1 + flen + 1)) == NULL) fail("malloc", 1); (void) memset(fpath, '\0', dlen + 1 + flen + 1); (void) strncpy(fpath, dname, dlen); fpath[dlen] = '/'; (void) strncat(fpath, fname, flen); free(dname); free(fname); } else if ((sbuf.st_mode & S_IFMT) == S_IFREG || (sbuf.st_mode & S_IFMT) == S_IFLNK || (sbuf.st_mode & S_IFMT) == S_IFCHR || (sbuf.st_mode & S_IFMT) == S_IFBLK) { fpath = strdup(argv[0]); } else if ((sbuf.st_mode & S_IFMT) == S_IFDIR) { fpath = strdup(argv[0]); isdir = B_TRUE; } else { usage(prog); } if (fpath == NULL) fail("strdup", 1); if (isdir == B_FALSE) { int fd, flags; mode_t mode = S_IRUSR | S_IWUSR; flags = rflag == B_FALSE ? O_CREAT | O_RDWR : O_RDONLY; if ((fd = open(fpath, flags, mode)) < 0) fail("open", 1); } else { DIR *dp; if ((dp = opendir(fpath)) == NULL) fail("opendir", 1); } free(fpath); if (fflag == B_FALSE) daemonize(); (void) pause(); /* NOTREACHED */ return (0); } # # 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 include ../Makefile.subdirs /* * 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 #include #include #include #include #include #include #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; unsigned int i; char buf[MAXPATHLEN]; 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); for (i = first_file; i < first_file + 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); } # # 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) 2014 by Delphix. All rights reserved. # PROG = mkholes include $(SRC)/cmd/Makefile.cmd LDLIBS += -lumem -lcmdutils include ../Makefile.subdirs /* * 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) 2014 by Delphix. All rights reserved. */ #include #include #include #include #include #include #include #include #include #include extern int errno; typedef enum { SEG_HOLE, SEG_DATA, SEG_TYPES } seg_type_t; typedef struct segment { list_node_t seg_node; seg_type_t seg_type; off_t seg_offset; off_t seg_len; } seg_t; static int no_memory(void) { (void) fprintf(stderr, "malloc failed\n"); return (UMEM_CALLBACK_EXIT(255)); } static void usage(char *msg, int exit_value) { (void) fprintf(stderr, "mkholes [-d|h offset:length] ... filename\n"); (void) fprintf(stderr, "%s\n", msg); exit(exit_value); } static char * get_random_buffer(size_t len) { int rand_fd; char *buf; buf = umem_alloc(len, UMEM_NOFAIL); /* * Fill the buffer from /dev/urandom to counteract the * effects of compression. */ if ((rand_fd = open("/dev/urandom", O_RDONLY)) < 0) { perror("open /dev/urandom failed"); exit(1); } if (read(rand_fd, buf, len) < 0) { perror("read /dev/urandom failed"); exit(1); } (void) close(rand_fd); return (buf); } static void push_segment(list_t *seg_list, seg_type_t seg_type, char *optarg) { char *off_str, *len_str; static off_t file_size = 0; off_t off, len; seg_t *seg; off_str = strtok(optarg, ":"); len_str = strtok(NULL, ":"); if (off_str == NULL || len_str == NULL) usage("Bad offset or length", 1); off = strtoull(off_str, NULL, 0); len = strtoull(len_str, NULL, 0); if (file_size >= off + len) usage("Ranges must ascend and may not overlap.", 1); file_size = off + len; seg = umem_alloc(sizeof (seg_t), UMEM_NOFAIL); seg->seg_type = seg_type; seg->seg_offset = off; seg->seg_len = len; list_insert_tail(seg_list, seg); } int main(int argc, char *argv[]) { int c, fd; char *fname; list_t seg_list; seg_t *seg; umem_nofail_callback(no_memory); list_create(&seg_list, sizeof (seg_t), offsetof(seg_t, seg_node)); while ((c = getopt(argc, argv, "d:h:")) != -1) { switch (c) { case 'd': push_segment(&seg_list, SEG_DATA, optarg); break; case 'h': push_segment(&seg_list, SEG_HOLE, optarg); break; } } argc -= optind; argv += optind; if ((fname = argv[0]) == NULL) usage("No filename specified", 1); fname = argv[0]; if ((fd = open(fname, O_LARGEFILE | O_RDWR | O_CREAT | O_SYNC, 00666)) < 0) { perror("open failed"); exit(1); } while ((seg = list_remove_head(&seg_list)) != NULL) { char *buf, *vbuf; off_t off = seg->seg_offset; off_t len = seg->seg_len; if (seg->seg_type == SEG_HOLE) { struct flock fl; off_t bytes_read = 0; ssize_t readlen = 1024 * 1024 * 16; fl.l_whence = SEEK_SET; fl.l_start = off; fl.l_len = len; if (fcntl(fd, F_FREESP, &fl) != 0) { perror("freesp failed"); exit(1); } buf = (char *)umem_alloc(readlen, UMEM_NOFAIL); vbuf = (char *)umem_zalloc(readlen, UMEM_NOFAIL); while (bytes_read < len) { ssize_t bytes = pread(fd, buf, readlen, off); if (bytes < 0) { perror("pread hole failed"); exit(1); } if (memcmp(buf, vbuf, bytes) != 0) { (void) fprintf(stderr, "Read back hole " "didn't match.\n"); exit(1); } bytes_read += bytes; off += bytes; } umem_free(buf, readlen); umem_free(vbuf, readlen); umem_free(seg, sizeof (seg_t)); } else if (seg->seg_type == SEG_DATA) { buf = get_random_buffer(len); vbuf = (char *)umem_alloc(len, UMEM_NOFAIL); if ((pwrite(fd, buf, len, off)) < 0) { perror("pwrite failed"); exit(1); } if ((pread(fd, vbuf, len, off)) != len) { perror("pread failed"); exit(1); } if (memcmp(buf, vbuf, len) != 0) { (void) fprintf(stderr, "Read back buf didn't " "match.\n"); exit(1); } umem_free(buf, len); umem_free(vbuf, len); umem_free(seg, sizeof (seg_t)); } } (void) close(fd); return (0); } # # 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) 2012 by Delphix. All rights reserved. # PROG = mktree include $(SRC)/cmd/Makefile.cmd include ../Makefile.subdirs /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright 2022 MNX Cloud, Inc. */ #include #include #include #include #include #include #include #include #include #define TYPE_D 'D' #define TYPE_F 'F' extern int errno; static char fdname[MAXPATHLEN] = {0}; static char *pbasedir = NULL; static int nlevel = 2; static int ndir = 2; static int nfile = 2; static void usage(char *this); static void crtfile(char *pname); static char *getfdname(char *pdir, char type, int level, int dir, int file); static int mktree(char *pbasedir, int level); int main(int argc, char *argv[]) { int c, ret; while ((c = getopt(argc, argv, "b:l:d:f:")) != -1) { switch (c) { case 'b': pbasedir = optarg; break; case 'l': nlevel = atoi(optarg); break; case 'd': ndir = atoi(optarg); break; case 'f': nfile = atoi(optarg); break; case '?': usage(argv[0]); } } if (nlevel < 0 || ndir < 0 || nfile < 0 || pbasedir == NULL) { usage(argv[0]); } ret = mktree(pbasedir, 1); return (ret); } static void usage(char *this) { (void) fprintf(stderr, "\tUsage: %s -b -l [nlevel] -d [ndir] -f [nfile]\n", this); exit(1); } static int mktree(char *pdir, int level) { int d, f; char dname[MAXPATHLEN] = {0}; char fname[MAXPATHLEN] = {0}; if (level > nlevel) { return (1); } for (d = 0; d < ndir; d++) { (void) memset(dname, '\0', sizeof (dname)); (void) strcpy(dname, getfdname(pdir, TYPE_D, level, d, 0)); if (mkdir(dname, 0777) != 0) { int exitcode = errno; (void) fprintf(stderr, "mkdir(%s) failed." "\n[%d]: %s.\n", dname, errno, strerror(errno)); exit(exitcode); } /* * No sub-directory need be created, only create files in it. */ if (mktree(dname, level+1) != 0) { for (f = 0; f < nfile; f++) { (void) memset(fname, '\0', sizeof (fname)); (void) strcpy(fname, getfdname(dname, TYPE_F, level+1, d, f)); crtfile(fname); } } } for (f = 0; f < nfile; f++) { (void) memset(fname, '\0', sizeof (fname)); (void) strcpy(fname, getfdname(pdir, TYPE_F, level, d, f)); crtfile(fname); } return (0); } static char * getfdname(char *pdir, char type, int level, int dir, int file) { (void) snprintf(fdname, sizeof (fdname), "%s/%c-l%dd%df%d", pdir, type, level, dir, file); return (fdname); } static void crtfile(char *pname) { int fd = -1; int afd = -1; int i, size; int exitcode; char *context = "0123456789ABCDF"; char *pbuf; if (pname == NULL) { exit(1); } size = sizeof (char) * 1024; pbuf = (char *)valloc(size); for (i = 0; i < size / strlen(context); i++) { int offset = i * strlen(context); (void) snprintf(pbuf+offset, size-offset, "%s", context); } if ((fd = open(pname, O_CREAT|O_RDWR, 0777)) < 0) { exitcode = errno; (void) fprintf(stderr, "open(%s, O_CREAT|O_RDWR, 0777) failed." "\n[%d]: %s.\n", pname, errno, strerror(errno)); exit(exitcode); } if (write(fd, pbuf, 1024) < 1024) { exitcode = errno; (void) fprintf(stderr, "write(fd, pbuf, 1024) failed." "\n[%d]: %s.\n", errno, strerror(errno)); exit(exitcode); } if ((afd = openat(fd, "xattr", O_CREAT | O_RDWR | O_XATTR, 0777)) < 0) { exitcode = errno; (void) fprintf(stderr, "openat failed.\n[%d]: %s.\n", errno, strerror(errno)); exit(exitcode); } if (write(afd, pbuf, 1024) < 1024) { exitcode = errno; (void) fprintf(stderr, "write(afd, pbuf, 1024) failed." "\n[%d]: %s.\n", errno, strerror(errno)); exit(exitcode); } (void) close(afd); (void) close(fd); free(pbuf); } # # 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) 2012 by Delphix. All rights reserved. # PROG = mmapwrite include $(SRC)/cmd/Makefile.cmd include ../Makefile.subdirs /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include #include #include /* * -------------------------------------------------------------------- * Bug Id: 5032643 * * Simply writing to a file and mmaping that file at the same time can * result in deadlock. Nothing perverse like writing from the file's * own mapping is required. * -------------------------------------------------------------------- */ static void * mapper(void *fdp) { void *addr; int fd = *(int *)fdp; if ((addr = mmap(0, 8192, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { perror("mmap"); exit(1); } for (;;) { if (mmap(addr, 8192, PROT_READ, MAP_SHARED|MAP_FIXED, fd, 0) == MAP_FAILED) { perror("mmap"); exit(1); } } /* NOTREACHED */ return ((void *)1); } int main(int argc, char **argv) { int fd; char buf[BUFSIZ]; if (argc != 2) { (void) printf("usage: %s \n", argv[0]); exit(1); } if ((fd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666)) == -1) { perror("open"); exit(1); } if (pthread_create(NULL, NULL, mapper, &fd) != 0) { perror("pthread_create"); exit(1); } for (;;) { if (write(fd, buf, sizeof (buf)) == -1) { perror("write"); exit(1); } } /* NOTREACHED */ return (0); } # # 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) 2012 by Delphix. All rights reserved. # PROG = randfree_file include $(SRC)/cmd/Makefile.cmd include ../Makefile.subdirs /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (c) 2012 by Delphix. All rights reserved. */ /* * Copyright (c) 2018, Joyent, Inc. */ #include "../file_common.h" /* * Create a file with assigned size and then free the specified * section of the file */ static void usage(char *progname); static void usage(char *progname) { (void) fprintf(stderr, "usage: %s [-l filesize] [-s start-offset]" "[-n section-len] filename\n", progname); exit(1); } int main(int argc, char *argv[]) { char *filename = NULL; char *buf; size_t filesize = 0; off_t start_off = 0; off_t off_len = 0; int fd, ch; struct flock fl; mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; while ((ch = getopt(argc, argv, "l:s:n:")) != EOF) { switch (ch) { case 'l': filesize = atoll(optarg); break; case 's': start_off = atoll(optarg); break; case 'n': off_len = atoll(optarg); break; default: usage(argv[0]); break; } } if (optind == argc - 1) filename = argv[optind]; else usage(argv[0]); buf = (char *)malloc(filesize); if ((fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, mode)) < 0) { perror("open"); free(buf); return (1); } if (write(fd, buf, filesize) < filesize) { perror("write"); free(buf); return (1); } fl.l_whence = SEEK_SET; fl.l_start = start_off; fl.l_len = off_len; if (fcntl(fd, F_FREESP, &fl) != 0) { perror("fcntl"); free(buf); return (1); } free(buf); return (0); } # # 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) 2017 by Delphix. All rights reserved. # PROG = randwritecomp include $(SRC)/cmd/Makefile.cmd include ../Makefile.subdirs /* * 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) 2017 by Delphix. All rights reserved. */ /* * The following is defined so the source can use * lrand48() and srand48(). */ #define __EXTENSIONS__ #include "../file_common.h" /* * The following sample was derived from real-world data * of a production Oracle database. */ static uint64_t size_distribution[] = { 0, 1499018, 352084, 1503485, 4206227, 5626657, 5387001, 3733756, 2233094, 874652, 238635, 81434, 33357, 13106, 2009, 1, 23660, }; static uint64_t distribution_n; static uint8_t randbuf[BLOCKSZ]; static void rwc_pwrite(int fd, const void *buf, size_t nbytes, off_t offset) { size_t nleft = nbytes; ssize_t nwrite = 0; nwrite = pwrite(fd, buf, nbytes, offset); if (nwrite < 0) { perror("pwrite"); exit(EXIT_FAILURE); } nleft -= nwrite; if (nleft != 0) { (void) fprintf(stderr, "warning: pwrite: " "wrote %zu out of %zu bytes\n", (nbytes - nleft), nbytes); } } static void fillbuf(char *buf) { uint64_t rv = lrand48() % distribution_n; uint64_t sum = 0; uint64_t i; for (i = 0; i < sizeof (size_distribution) / sizeof (size_distribution[0]); i++) { sum += size_distribution[i]; if (rv < sum) break; } bcopy(randbuf, buf, BLOCKSZ); if (i == 0) bzero(buf, BLOCKSZ - 10); else if (i < 16) bzero(buf, BLOCKSZ - i * 512 + 256); /*LINTED: E_BAD_PTR_CAST_ALIGN*/ ((uint32_t *)buf)[0] = lrand48(); } static void exit_usage(void) { (void) printf("usage: "); (void) printf("randwritecomp [-s] [nwrites]\n"); exit(EXIT_FAILURE); } static void sequential_writes(int fd, char *buf, uint64_t nblocks, int64_t n) { for (int64_t i = 0; n == -1 || i < n; i++) { fillbuf(buf); static uint64_t j = 0; if (j == 0) j = lrand48() % nblocks; rwc_pwrite(fd, buf, BLOCKSZ, j * BLOCKSZ); j++; if (j >= nblocks) j = 0; } } static void random_writes(int fd, char *buf, uint64_t nblocks, int64_t n) { for (int64_t i = 0; n == -1 || i < n; i++) { fillbuf(buf); rwc_pwrite(fd, buf, BLOCKSZ, (lrand48() % nblocks) * BLOCKSZ); } } int main(int argc, char *argv[]) { int fd, err; char *filename = NULL; char buf[BLOCKSZ]; struct stat ss; uint64_t nblocks; int64_t n = -1; int sequential = 0; if (argc < 2) exit_usage(); argv++; if (strcmp("-s", argv[0]) == 0) { sequential = 1; argv++; } if (argv[0] == NULL) exit_usage(); else filename = argv[0]; argv++; if (argv[0] != NULL) n = strtoull(argv[0], NULL, 0); fd = open(filename, O_RDWR|O_CREAT, 0666); err = fstat(fd, &ss); if (err != 0) { (void) fprintf(stderr, "error: fstat returned error code %d\n", err); exit(EXIT_FAILURE); } nblocks = ss.st_size / BLOCKSZ; if (nblocks == 0) { (void) fprintf(stderr, "error: " "file is too small (min allowed size is %d bytes)\n", BLOCKSZ); exit(EXIT_FAILURE); } srand48(getpid()); for (int i = 0; i < BLOCKSZ; i++) randbuf[i] = lrand48(); distribution_n = 0; for (uint64_t i = 0; i < sizeof (size_distribution) / sizeof (size_distribution[0]); i++) { distribution_n += size_distribution[i]; } if (sequential) sequential_writes(fd, buf, nblocks, n); else random_writes(fd, buf, nblocks, n); return (0); } # # 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) 2012 by Delphix. All rights reserved. # PROG = readmmap include $(SRC)/cmd/Makefile.cmd include ../Makefile.subdirs /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * -------------------------------------------------------------- * BugId 5047993 : Getting bad read data. * * Usage: readmmap * * where: * filename is an absolute path to the file name. * * Return values: * 1 : error * 0 : no errors * -------------------------------------------------------------- */ #include #include #include #include #include #include int main(int argc, char **argv) { char *filename = "badfile"; size_t size = 4395; size_t idx = 0; char *buf = NULL; char *map = NULL; int fd = -1, bytes, retval = 0; unsigned seed; if (argc < 2 || optind == argc) { (void) fprintf(stderr, "usage: %s \n", argv[0]); exit(1); } if ((buf = calloc(1, size)) == NULL) { perror("calloc"); exit(1); } filename = argv[optind]; (void) remove(filename); fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0666); if (fd == -1) { perror("open to create"); retval = 1; goto end; } bytes = write(fd, buf, size); if (bytes != size) { (void) printf("short write: %d != %ud\n", bytes, size); retval = 1; goto end; } map = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (map == MAP_FAILED) { perror("mmap"); retval = 1; goto end; } seed = time(NULL); srandom(seed); idx = random() % size; map[idx] = 1; if (msync(map, size, MS_SYNC) != 0) { perror("msync"); retval = 1; goto end; } if (munmap(map, size) != 0) { perror("munmap"); retval = 1; goto end; } bytes = pread(fd, buf, size, 0); if (bytes != size) { (void) printf("short read: %d != %ud\n", bytes, size); retval = 1; goto end; } if (buf[idx] != 1) { (void) printf( "bad data from read! got buf[%ud]=%d, expected 1\n", idx, buf[idx]); retval = 1; goto end; } (void) printf("good data from read: buf[%ud]=1\n", idx); end: if (fd != -1) { (void) close(fd); } if (buf != NULL) { free(buf); } return (retval); } # # 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) 2012 by Delphix. All rights reserved. # PROG = rename_dir include $(SRC)/cmd/Makefile.cmd include ../Makefile.subdirs /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (c) 2012 by Delphix. All rights reserved. */ /* * Assertion: * Create two directory trees in zfs filesystem, and rename * directory across the directory structure. ZFS can handle * the race situation. */ /* * Need to create the following directory structures before * running this program: * * mkdir -p 1/2/3/4/5 a/b/c/d/e */ #include #include #include #include int main() { int i = 1; switch (fork()) { case -1: perror("fork"); exit(1); break; case 0: while (i > 0) { int c_count = 0; if (rename("a/b/c", "1/2/3/c") == 0) c_count++; if (rename("1/2/3/c", "a/b/c") == 0) c_count++; if (c_count) { (void) fprintf(stderr, "c_count: %d", c_count); } } break; default: while (i > 0) { int p_count = 0; if (rename("1", "a/b/c/d/e/1") == 0) p_count++; if (rename("a/b/c/d/e/1", "1") == 0) p_count++; if (p_count) { (void) fprintf(stderr, "p_count: %d", p_count); } } break; } return (0); } # # 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) 2012 by Delphix. All rights reserved. # PROG = rm_lnkcnt_zero_file include $(SRC)/cmd/Makefile.cmd include ../Makefile.subdirs /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (c) 2012 by Delphix. All rights reserved. */ /* * -------------------------------------------------------------------- * The purpose of this test is to see if the bug reported (#4723351) for * UFS exists when using a ZFS file system. * -------------------------------------------------------------------- * */ #define _REENTRANT 1 #include #include #include #include #include #include #include #include #include #include static const int TRUE = 1; static char *filebase; static int pickidx() { return (random() % 1000); } /* ARGSUSED */ static void * mover(void *a) { char buf[256]; int idx, len, ret; len = strlen(filebase) + 5; while (TRUE) { idx = pickidx(); (void) snprintf(buf, len, "%s.%03d", filebase, idx); ret = rename(filebase, buf); if (ret < 0 && errno != ENOENT) (void) perror("renaming file"); } return (NULL); } /* ARGSUSED */ static void * cleaner(void *a) { char buf[256]; int idx, len, ret; len = strlen(filebase) + 5; while (TRUE) { idx = pickidx(); (void) snprintf(buf, len, "%s.%03d", filebase, idx); ret = remove(buf); if (ret < 0 && errno != ENOENT) (void) perror("removing file"); } return (NULL); } static void * writer(void *a) { int *fd = (int *)a; while (TRUE) { (void) close (*fd); *fd = open(filebase, O_APPEND | O_RDWR | O_CREAT, 0644); if (*fd < 0) perror("refreshing file"); (void) write(*fd, "test\n", 5); } return (NULL); } int main(int argc, char **argv) { int fd; pthread_t tid; if (argc == 1) { (void) printf("Usage: %s \n", argv[0]); exit(-1); } filebase = argv[1]; fd = open(filebase, O_APPEND | O_RDWR | O_CREAT, 0644); if (fd < 0) { perror("creating test file"); exit(-1); } (void) thr_setconcurrency(4); /* 3 threads + main */ (void) pthread_create(&tid, NULL, mover, NULL); (void) pthread_create(&tid, NULL, cleaner, NULL); (void) pthread_create(&tid, NULL, writer, (void *) &fd); while (TRUE) { int ret; struct stat st; ret = stat(filebase, &st); if (ret == 0 && (st.st_nlink > 2 || st.st_nlink < 1)) { (void) printf("st.st_nlink = %d, exiting\n", \ (int)st.st_nlink); exit(0); } (void) sleep(1); } return (0); } # # 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) 2012, 2016 by Delphix. All rights reserved. # include $(SRC)/Makefile.master ROOTOPTPKG = $(ROOT)/opt/zfs-tests TARGETDIR = $(ROOTOPTPKG)/bin include $(SRC)/test/zfs-tests/Makefile.com #!/usr/bin/ksh # # 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) 2012, 2016 by Delphix. All rights reserved. # Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved. # Copyright 2021 Tintri by DDN, Inc. All rights reserved. # Copyright 2020 OmniOS Community Edition (OmniOSce) Association. # export LC_ALL=C.UTF-8 export PATH="/usr/bin" export NOINUSE_CHECK=1 export STF_SUITE="/opt/zfs-tests" export COMMON="$STF_SUITE/runfiles/common.run" export STF_TOOLS="/opt/test-runner/stf" export PATHDIR="" runner="/opt/test-runner/bin/run" auto_detect=false if [[ -z "$TESTFAIL_CALLBACKS" ]] ; then export TESTFAIL_CALLBACKS="$STF_SUITE/callbacks/zfs_dbgmsg" fi function fail { echo $1 exit ${2:-1} } function find_disks { typeset all_disks=$(echo '' | sudo -k format | awk \ '/c[0-9]/ {print $2}') typeset used_disks=$(zpool status | awk \ '/c[0-9]+(t[0-9a-fA-F]+)?d[0-9]+/ {print $1}' | sed -E \ 's/(s|p)[0-9]+//g') typeset disk used avail_disks for disk in $all_disks; do for used in $used_disks; do [[ "$disk" == "$used" ]] && continue 2 done [[ -n $avail_disks ]] && avail_disks="$avail_disks $disk" [[ -z $avail_disks ]] && avail_disks="$disk" done echo $avail_disks } function find_rpool { typeset ds=$(mount | awk '/^\/ / {print $3}') echo ${ds%%/*} } function find_runfile { typeset distro= if [[ -d /opt/delphix && -h /etc/delphix/version ]]; then distro=delphix elif grep -qs OpenIndiana /etc/release; then distro=openindiana elif grep -qs OmniOS /etc/release; then distro=omnios fi [[ -n $distro ]] && echo $COMMON,$STF_SUITE/runfiles/$distro.run } function verify_id { [[ $(id -u) == "0" ]] && fail "This script must not be run as root." sudo -k -n id >/dev/null 2>&1 || fail "User must be able to sudo without a password." } function verify_disks { typeset disk typeset path typeset -lu expected_size typeset -lu size # Ensure disks are large enough for the tests: no less than 10GB # and large enough for a crash dump plus overheads: the disk partition # table (about 34k), zpool with 4.5MB for pool label and 128k for pool # data, so we round up pool data + labels to 5MB. expected_size=$(sudo -k -n dumpadm -epH) (( expected_size = expected_size + 5 * 1024 * 1024 )) if (( expected_size < 10 * 1024 * 1024 * 1024 )); then (( expected_size = 10 * 1024 * 1024 * 1024 )) fi for disk in $DISKS; do case $disk in /*) path=$disk;; *) path=/dev/rdsk/${disk}s0 esac set -A disksize $(sudo -k prtvtoc $path 2>&1 | awk '$3 == "bytes/sector" || ($3 == "accessible" && $4 == "sectors") {print $2}') if [[ (-n "${disksize[0]}") && (-n "${disksize[1]}") ]]; then (( size = disksize[0] * disksize[1] )) else return 1 fi if (( size < expected_size )); then (( size = expected_size / 1024 / 1024 / 1024 )) fail "$disk is too small, need at least ${size}GB" fi done return 0 } function create_links { typeset dir=$1 typeset file_list=$2 [[ -n $PATHDIR ]] || fail "PATHDIR wasn't correctly set" for i in $file_list; do [[ ! -e $PATHDIR/$i ]] || fail "$i already exists" ln -s $dir/$i $PATHDIR/$i || fail "Couldn't link $i" done } function constrain_path { . $STF_SUITE/include/commands.cfg PATHDIR=$(/usr/bin/mktemp -d /var/tmp/constrained_path.XXXX) chmod 755 $PATHDIR || fail "Couldn't chmod $PATHDIR" create_links "/usr/bin" "$USR_BIN_FILES" create_links "/usr/sbin" "$USR_SBIN_FILES" create_links "/sbin" "$SBIN_FILES" create_links "/opt/zfs-tests/bin" "$ZFSTEST_FILES" # Special case links ln -s /usr/gnu/bin/dd $PATHDIR/gnu_dd } constrain_path export PATH=$PATHDIR verify_id while getopts ac:l:qT: c; do case $c in 'a') auto_detect=true ;; 'c') runfile=$OPTARG [[ -f $runfile ]] || fail "Cannot read file: $runfile" if [[ -z $runfiles ]]; then runfiles=$runfile else runfiles+=",$runfile" fi ;; 'l') logfile=$OPTARG [[ -f $logfile ]] || fail "Cannot read file: $logfile" xargs+=" -l $logfile" ;; 'q') xargs+=" -q" ;; 'T') xargs+=" -T $OPTARG" ;; esac done shift $((OPTIND - 1)) # If the user specified -a, then use free disks, otherwise use those in $DISKS. if $auto_detect; then export DISKS=$(find_disks) elif [[ -z $DISKS ]]; then fail "\$DISKS not set in env, and -a not specified." else verify_disks || fail "Couldn't verify all the disks in \$DISKS" fi # Add the root pool to $KEEP according to its contents. # It's ok to list it twice. if [[ -z $KEEP ]]; then KEEP="$(find_rpool)" else KEEP+=" $(find_rpool)" fi export __ZFS_POOL_EXCLUDE="$KEEP" export KEEP="^$(echo $KEEP | sed 's/ /$|^/g')\$" [[ -z $runfiles ]] && runfiles=$(find_runfile) [[ -z $runfiles ]] && fail "Couldn't determine distro" . $STF_SUITE/include/default.cfg num_disks=$(echo $DISKS | awk '{print NF}') (( num_disks < 3 )) && fail "Not enough disks to run ZFS Test Suite" # Ensure user has only basic privileges. ppriv -s EIP=basic -e $runner -c $runfiles $xargs ret=$? rm -rf $PATHDIR || fail "Couldn't remove $PATHDIR" exit $ret