summaryrefslogtreecommitdiff
path: root/usr/src/cmd/fs.d
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/fs.d')
-rw-r--r--usr/src/cmd/fs.d/Makefile3
-rw-r--r--usr/src/cmd/fs.d/df.c119
-rw-r--r--usr/src/cmd/fs.d/nfs/svc/nfs-server19
-rw-r--r--usr/src/cmd/fs.d/zfs/Makefile58
-rw-r--r--usr/src/cmd/fs.d/zfs/fstyp/Makefile41
-rw-r--r--usr/src/cmd/fs.d/zfs/fstyp/fstyp.c156
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);
+}