diff options
Diffstat (limited to 'usr/src/cmd/fs.d')
-rw-r--r-- | usr/src/cmd/fs.d/Makefile | 3 | ||||
-rw-r--r-- | usr/src/cmd/fs.d/df.c | 119 | ||||
-rw-r--r-- | usr/src/cmd/fs.d/nfs/svc/nfs-server | 19 | ||||
-rw-r--r-- | usr/src/cmd/fs.d/zfs/Makefile | 58 | ||||
-rw-r--r-- | usr/src/cmd/fs.d/zfs/fstyp/Makefile | 41 | ||||
-rw-r--r-- | usr/src/cmd/fs.d/zfs/fstyp/fstyp.c | 156 |
6 files changed, 390 insertions, 6 deletions
diff --git a/usr/src/cmd/fs.d/Makefile b/usr/src/cmd/fs.d/Makefile index 38039de5ab..b0653b5138 100644 --- a/usr/src/cmd/fs.d/Makefile +++ b/usr/src/cmd/fs.d/Makefile @@ -46,7 +46,8 @@ DEFAULTFILES= fs.dfl include ../Makefile.cmd SUBDIR1= lofs -SUBDIR2= fd pcfs nfs hsfs proc ctfs udfs ufs tmpfs cachefs autofs mntfs objfs +SUBDIR2= zfs fd pcfs nfs hsfs proc ctfs udfs ufs tmpfs cachefs autofs mntfs \ + objfs i386_SUBDIRS= xmemfs i386_I18NDIRS= xmemfs SUBDIRS= $(SUBDIR1) $(SUBDIR2) $($(MACH)_SUBDIRS) diff --git a/usr/src/cmd/fs.d/df.c b/usr/src/cmd/fs.d/df.c index 0d55abfcf5..6852626a68 100644 --- a/usr/src/cmd/fs.d/df.c +++ b/usr/src/cmd/fs.d/df.c @@ -24,13 +24,14 @@ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" +#include <dlfcn.h> #include <stdio.h> #include <stdarg.h> #include <string.h> @@ -51,6 +52,7 @@ #include <sys/mkdev.h> #include <sys/int_limits.h> #include <sys/zone.h> +#include <libzfs.h> #include "fslib.h" @@ -171,6 +173,7 @@ struct df_request { #define DFR_MOUNT_POINT(dfrp) (dfrp)->dfr_mte->mte_mount->mnt_mountp #define DFR_SPECIAL(dfrp) (dfrp)->dfr_mte->mte_mount->mnt_special +#define DFR_FSTYPE(dfrp) (dfrp)->dfr_mte->mte_mount->mnt_fstype #define DFR_ISMOUNTEDFS(dfrp) ((dfrp)->dfr_mte != NULL) #define DFRP(p) ((struct df_request *)(p)) @@ -236,9 +239,23 @@ static void parse_options(int, char **); static char *basename(char *); +/* ARGSUSED */ +static void +dummy_error_handler(const char *fmt, va_list ap) +{ + /* Do nothing */ +} + +static zfs_handle_t *(*_zfs_open)(const char *, int); +static void (*_zfs_close)(zfs_handle_t *); +static uint64_t (*_zfs_prop_get_int)(zfs_handle_t *, zfs_prop_t); +static void (*_zfs_set_error_handler)(void (*)(const char *, va_list)); + void main(int argc, char *argv[]) { + void *hdl; + (void) setlocale(LC_ALL, ""); #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ @@ -252,6 +269,32 @@ main(int argc, char *argv[]) sysv3_set = getenv("SYSV3"); #endif /* _iBCS2 */ + /* + * Dynamically check for libzfs, in case the user hasn't installed the + * SUNWzfs packages. A basic utility such as df shouldn't depend on + * optional filesystems. + */ + if ((hdl = dlopen("libzfs.so", RTLD_LAZY)) != NULL) { + _zfs_set_error_handler = (void (*)()) + dlsym(hdl, "zfs_set_error_handler"); + _zfs_open = (zfs_handle_t *(*)())dlsym(hdl, "zfs_open"); + _zfs_close = (void (*)())dlsym(hdl, "zfs_close"); + _zfs_prop_get_int = (uint64_t (*)()) + dlsym(hdl, "zfs_prop_get_int"); + + if (_zfs_set_error_handler != NULL) { + assert(_zfs_open != NULL); + assert(_zfs_close != NULL); + assert(_zfs_prop_get_int != NULL); + + /* + * Disable ZFS error reporting, so we don't get messages + * like "can't open ..." under race conditions. + */ + _zfs_set_error_handler(dummy_error_handler); + } + } + if (EQ(program_name, DEVNM_CMD)) do_devnm(argc, argv); @@ -1169,6 +1212,68 @@ number_to_scaled_string( return (buf); } +/* + * The statvfs() implementation allows us to return only two values, the total + * number of blocks and the number of blocks free. The equation 'used = total - + * free' will not work for ZFS filesystems, due to the nature of pooled storage. + * We choose to return values in the statvfs structure that will produce correct + * results for 'used' and 'available', but not 'total'. This function will open + * the underlying ZFS dataset if necessary and get the real value. + */ +static void +adjust_total_blocks(struct df_request *dfrp, fsblkcnt64_t *total, + uint64_t blocksize) +{ + zfs_handle_t *zhp; + char *dataset, *slash; + uint64_t quota; + + if (strcmp(DFR_FSTYPE(dfrp), MNTTYPE_ZFS) != 0 || + _zfs_open == NULL) + return; + + /* + * We want to get the total size for this filesystem as bounded by any + * quotas. In order to do this, we start at the current filesystem and + * work upwards until we find a dataset with a quota. If we reach the + * pool itself, then the total space is the amount used plus the amount + * available. + */ + if ((dataset = strdup(DFR_SPECIAL(dfrp))) == NULL) + return; + + slash = dataset + strlen(dataset); + do { + *slash = '\0'; + + if ((zhp = _zfs_open(dataset, ZFS_TYPE_ANY)) == NULL) { + free(dataset); + return; + } + + if ((quota = _zfs_prop_get_int(zhp, ZFS_PROP_QUOTA)) != 0) { + *total = quota / blocksize; + _zfs_close(zhp); + free(dataset); + return; + } + + _zfs_close(zhp); + + } while ((slash = strrchr(dataset, '/')) != NULL); + + + if ((zhp = _zfs_open(dataset, ZFS_TYPE_ANY)) == NULL) { + free(dataset); + return; + } + + *total = (_zfs_prop_get_int(zhp, ZFS_PROP_USED) + + _zfs_prop_get_int(zhp, ZFS_PROP_AVAILABLE)) / blocksize; + + _zfs_close(zhp); + free(dataset); +} /* * The output will appear properly columnized regardless of the names of @@ -1178,6 +1283,7 @@ static void g_output(struct df_request *dfrp, struct statvfs64 *fsp) { fsblkcnt64_t available_blocks = fsp->f_bavail; + fsblkcnt64_t total_blocks = fsp->f_blocks; numbuf_t total_blocks_buf; numbuf_t total_files_buf; numbuf_t free_blocks_buf; @@ -1258,9 +1364,11 @@ g_output(struct df_request *dfrp, struct statvfs64 *fsp) if ((long long)available_blocks < (long long)0) available_blocks = (fsblkcnt64_t)0; + adjust_total_blocks(dfrp, &total_blocks, fsp->f_frsize); + (void) printf("%*s %-*s %*s %-*s %*s %-*s %*s %-*s\n", NCOL1_WIDTH, number_to_string(total_blocks_buf, - fsp->f_blocks, fsp->f_frsize, 512), + total_blocks, fsp->f_frsize, 512), SCOL1_WIDTH, total_blocks_str, NCOL2_WIDTH, number_to_string(free_blocks_buf, fsp->f_bfree, fsp->f_frsize, 512), @@ -1346,6 +1454,8 @@ k_output(struct df_request *dfrp, struct statvfs64 *fsp) file_system = ""; } + adjust_total_blocks(dfrp, &total_blocks, fsp->f_frsize); + if (use_scaling) { /* comes from the -h option */ (void) printf("%-*s %*s %*s %*s %-*s %-s\n", FILESYSTEM_WIDTH, file_system, @@ -1428,6 +1538,7 @@ strings_init() static void t_output(struct df_request *dfrp, struct statvfs64 *fsp) { + fsblkcnt64_t total_blocks = fsp->f_blocks; numbuf_t total_blocks_buf; numbuf_t total_files_buf; numbuf_t free_blocks_buf; @@ -1435,6 +1546,8 @@ t_output(struct df_request *dfrp, struct statvfs64 *fsp) STRINGS_INIT(); + adjust_total_blocks(dfrp, &total_blocks, fsp->f_frsize); + (void) printf("%-*s(%-*s): %*s %s %*s %s\n", MOUNT_POINT_WIDTH, DFR_MOUNT_POINT(dfrp), SPECIAL_DEVICE_WIDTH, DFR_SPECIAL(dfrp), @@ -1456,7 +1569,7 @@ t_output(struct df_request *dfrp, struct statvfs64 *fsp) (void) printf("%*s: %*s %s %*s %s\n", MNT_SPEC_WIDTH, total_str, BLOCK_WIDTH, number_to_string(total_blocks_buf, - fsp->f_blocks, fsp->f_frsize, 512), + total_blocks, fsp->f_frsize, 512), blocks_str, NFILES_WIDTH, number_to_string(total_files_buf, fsp->f_files, 1, 1), diff --git a/usr/src/cmd/fs.d/nfs/svc/nfs-server b/usr/src/cmd/fs.d/nfs/svc/nfs-server index 36cf2cb3ad..dc3339e3d1 100644 --- a/usr/src/cmd/fs.d/nfs/svc/nfs-server +++ b/usr/src/cmd/fs.d/nfs/svc/nfs-server @@ -42,8 +42,7 @@ case "$1" in fi # If /etc/dfs/dfstab exists and has non-blank or non-commented-out - # lines, then run shareall to export them, and then start up mountd - # and nfsd if anything is exported. + # lines, then run shareall to export them. startnfsd=0 if [ -f /etc/dfs/dfstab ] && /usr/bin/egrep -v '^[ ]*(#|$)' \ @@ -52,6 +51,14 @@ case "$1" in /usr/sbin/shareall -F nfs fi + # Share any ZFS filesystems marked for sharing. + + if [ -x /usr/sbin/zfs ]; then + /usr/sbin/zfs share -a + fi + + # Start up mountd and nfsd if anything is exported. + if /usr/bin/grep -s nfs /etc/dfs/sharetab >/dev/null; then startnfsd=1 fi @@ -88,6 +95,14 @@ case "$1" in 'stop') /usr/bin/pkill -x -u 0,1 -z $zone '(nfsd|mountd)' + # Unshare shared ZFS filesystems. + + if [ -x /usr/sbin/zfs ]; then + /usr/sbin/zfs unshare -a + fi + + # Unshare remaining shared filesystems. + if /usr/bin/grep -s nfs /etc/dfs/sharetab >/dev/null; then /usr/sbin/unshareall -F nfs fi diff --git a/usr/src/cmd/fs.d/zfs/Makefile b/usr/src/cmd/fs.d/zfs/Makefile new file mode 100644 index 0000000000..39187b544d --- /dev/null +++ b/usr/src/cmd/fs.d/zfs/Makefile @@ -0,0 +1,58 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 +# +# +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +SUBDIRS= fstyp + +all:= TARGET= all +install:= TARGET= install +clean:= TARGET= clean +clobber:= TARGET= clobber +lint:= TARGET= lint +catalog:= TARGET= catalog + +# for messaging catalog +# +POFILE= zfs.po +POFILES= $(SUBDIRS:%=%/%.po) + +.KEEP_STATE: + +.PARALLEL: $(SUBDIRS) + +all install clean clobber lint: $(SUBDIRS) + +catalog: $(POFILE) + +$(POFILE): $(SUBDIRS) + $(RM) $@ + cat $(POFILES) > $@ + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: diff --git a/usr/src/cmd/fs.d/zfs/fstyp/Makefile b/usr/src/cmd/fs.d/zfs/fstyp/Makefile new file mode 100644 index 0000000000..8bad1c0f15 --- /dev/null +++ b/usr/src/cmd/fs.d/zfs/fstyp/Makefile @@ -0,0 +1,41 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 +# +# +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +FSTYPE= zfs +LIBPROG= fstyp + +include ../../Makefile.fstype + +POFILE= fstyp.po + +catalog: $(POFILE) + +LDLIBS += -lzfs -lnvpair + +lint := PROG = $(LIBPROG) +lint: lint_PROG diff --git a/usr/src/cmd/fs.d/zfs/fstyp/fstyp.c b/usr/src/cmd/fs.d/zfs/fstyp/fstyp.c new file mode 100644 index 0000000000..90de2fe5a6 --- /dev/null +++ b/usr/src/cmd/fs.d/zfs/fstyp/fstyp.c @@ -0,0 +1,156 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <unistd.h> +#include <libintl.h> +#include <locale.h> +#include <string.h> +#include <libzfs.h> +#include <errno.h> + +static void +usage(void) +{ + (void) fprintf(stderr, gettext("Usage: fstype [-v] <device>\n")); + exit(1); +} + +static void +dump_nvlist(nvlist_t *list, int indent) +{ + nvpair_t *elem = NULL; + + while ((elem = nvlist_next_nvpair(list, elem)) != NULL) { + switch (nvpair_type(elem)) { + case DATA_TYPE_STRING: + { + char *value; + + verify(nvpair_value_string(elem, &value) == 0); + (void) printf("%*s%s='%s'\n", indent, "", + nvpair_name(elem), value); + } + break; + + case DATA_TYPE_UINT64: + { + uint64_t value; + + verify(nvpair_value_uint64(elem, &value) == 0); + (void) printf("%*s%s=%llu\n", indent, "", + nvpair_name(elem), (u_longlong_t)value); + } + break; + + case DATA_TYPE_NVLIST: + { + nvlist_t *value; + + verify(nvpair_value_nvlist(elem, &value) == 0); + (void) printf("%*s%s\n", indent, "", + nvpair_name(elem)); + dump_nvlist(value, indent + 4); + } + break; + + case DATA_TYPE_NVLIST_ARRAY: + { + nvlist_t **value; + uint_t c, count; + + verify(nvpair_value_nvlist_array(elem, &value, + &count) == 0); + + for (c = 0; c < count; c++) { + (void) printf("%*s%s[%u]\n", indent, "", + nvpair_name(elem), c); + dump_nvlist(value[c], indent + 8); + } + } + break; + + default: + + (void) printf("bad config type %d for %s\n", + nvpair_type(elem), nvpair_name(elem)); + } + } +} + +int +main(int argc, char **argv) +{ + int c, fd; + int verbose = 0; + nvlist_t *config; + + (void) setlocale(LC_ALL, ""); + +#if !defined(TEXT_DOMAIN) +#define TEXT_DOMAIN "SYS_TEST" +#endif + (void) textdomain(TEXT_DOMAIN); + + while ((c = getopt(argc, argv, "v")) != -1) { + switch (c) { + case 'v': + verbose = 1; + break; + default: + usage(); + break; + } + } + + argv += optind; + argc -= optind; + + if (argc != 1) + usage(); + + if ((fd = open64(argv[0], O_RDONLY)) < 0) { + perror("open64"); + return (1); + } + + if ((config = zpool_read_label(fd)) == NULL) + return (1); + + (void) printf("zfs\n"); + + if (verbose) + dump_nvlist(config, 4); + + (void) close(fd); + + return (0); +} |