summaryrefslogtreecommitdiff
path: root/usr/src/cmd/fs.d/nfs/lib/ref_subr.c
diff options
context:
space:
mode:
authorRobert Thurlow <Robert.Thurlow@Sun.COM>2009-12-09 17:27:22 -0600
committerRobert Thurlow <Robert.Thurlow@Sun.COM>2009-12-09 17:27:22 -0600
commit2f172c55ef76964744bc62b4500ece87f3089b4d (patch)
tree68a197e4eb4d77acf9993e2e3d75c3f3b06f6a86 /usr/src/cmd/fs.d/nfs/lib/ref_subr.c
parent1dbbbf767041f5cea7771826e2efc21c03bbffda (diff)
downloadillumos-joyent-2f172c55ef76964744bc62b4500ece87f3089b4d.tar.gz
6232737 Client should support NFS4ERR_MOVED and fs_locations
6232743 Server should support NFS4ERR_MOVED and fs_locations 6891289 client panick mutex_vector_tryenter with some stress testing
Diffstat (limited to 'usr/src/cmd/fs.d/nfs/lib/ref_subr.c')
-rw-r--r--usr/src/cmd/fs.d/nfs/lib/ref_subr.c311
1 files changed, 311 insertions, 0 deletions
diff --git a/usr/src/cmd/fs.d/nfs/lib/ref_subr.c b/usr/src/cmd/fs.d/nfs/lib/ref_subr.c
new file mode 100644
index 0000000000..b4980593d7
--- /dev/null
+++ b/usr/src/cmd/fs.d/nfs/lib/ref_subr.c
@@ -0,0 +1,311 @@
+/*
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <strings.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/errno.h>
+#include <limits.h>
+#include <libnvpair.h>
+#include <dlfcn.h>
+#include <link.h>
+#include <rp_plugin.h>
+#include <fcntl.h>
+#include <uuid/uuid.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include <rpc/clnt.h>
+#include <rpc/rpc_msg.h>
+#include <sys/param.h>
+#include <nfs/nfs4.h>
+#include <rpcsvc/nfs4_prot.h>
+
+/*
+ * str_to_utf8 - converts a null-terminated C string to a utf8 string
+ */
+utf8string *
+str_to_utf8(char *nm, utf8string *str)
+{
+ int len;
+
+ if (str == NULL)
+ return (NULL);
+
+ if (nm == NULL || *nm == '\0') {
+ str->utf8string_len = 0;
+ str->utf8string_val = NULL;
+ return (NULL);
+ }
+
+ len = strlen(nm);
+
+ str->utf8string_val = malloc(len);
+ if (str->utf8string_val == NULL) {
+ str->utf8string_len = 0;
+ return (NULL);
+ }
+ str->utf8string_len = len;
+ bcopy(nm, str->utf8string_val, len);
+
+ return (str);
+}
+
+/*
+ * Converts a utf8 string to a C string.
+ * kmem_allocs a new string if not supplied
+ */
+char *
+utf8_to_str(utf8string *str, uint_t *lenp, char *s)
+{
+ char *sp;
+ char *u8p;
+ int len;
+ int i;
+
+ if (str == NULL)
+ return (NULL);
+
+ u8p = str->utf8string_val;
+ len = str->utf8string_len;
+ if (len <= 0 || u8p == NULL) {
+ if (s)
+ *s = '\0';
+ return (NULL);
+ }
+
+ sp = s;
+ if (sp == NULL)
+ sp = malloc(len + 1);
+ if (sp == NULL)
+ return (NULL);
+
+ /*
+ * At least check for embedded nulls
+ */
+ for (i = 0; i < len; i++) {
+ sp[i] = u8p[i];
+ if (u8p[i] == '\0') {
+ if (s == NULL)
+ free(sp);
+ return (NULL);
+ }
+ }
+ sp[len] = '\0';
+ *lenp = len + 1;
+
+ return (sp);
+}
+
+void
+print_referral_summary(fs_locations4 *fsl)
+{
+ int i, j;
+ uint_t l;
+ char *s;
+ fs_location4 *fs;
+
+ if (fsl == NULL) {
+ printf("NULL\n");
+ return;
+ }
+
+ for (i = 0; i < fsl->locations.locations_len; i++) {
+ if (i > 0)
+ printf("\n");
+ fs = &fsl->locations.locations_val[i];
+ for (j = 0; j < fs->server.server_len; j++) {
+ s = utf8_to_str(&fs->server.server_val[j], &l, NULL);
+ if (j > 0)
+ printf(",");
+ printf("%s", s ? s : "");
+ if (s)
+ free(s);
+ }
+ printf(":");
+ for (j = 0; j < fs->rootpath.pathname4_len; j++) {
+ s = utf8_to_str(&fs->rootpath.pathname4_val[j],
+ &l, NULL);
+ printf("/%s", s ? s : "");
+ if (s)
+ free(s);
+ }
+ if (fs->rootpath.pathname4_len == 0)
+ printf("/");
+ }
+ printf("\n");
+}
+
+/*
+ * There is a kernel copy of this routine in nfs4_srv.c.
+ * Changes should be kept in sync.
+ */
+static int
+nfs4_create_components(char *path, component4 *comp4)
+{
+ int slen, plen, ncomp;
+ char *ori_path, *nxtc, buf[MAXNAMELEN];
+
+ if (path == NULL)
+ return (0);
+
+ plen = strlen(path) + 1; /* include the terminator */
+ ori_path = path;
+ ncomp = 0;
+
+ /* count number of components in the path */
+ for (nxtc = path; nxtc < ori_path + plen; nxtc++) {
+ if (*nxtc == '/' || *nxtc == '\0' || *nxtc == '\n') {
+ if ((slen = nxtc - path) == 0) {
+ path = nxtc + 1;
+ continue;
+ }
+
+ if (comp4 != NULL) {
+ bcopy(path, buf, slen);
+ buf[slen] = '\0';
+ if (str_to_utf8(buf, &comp4[ncomp]) == NULL)
+ return (NULL);
+ }
+
+ ncomp++; /* 1 valid component */
+ path = nxtc + 1;
+ }
+ if (*nxtc == '\0' || *nxtc == '\n')
+ break;
+ }
+
+ return (ncomp);
+}
+
+/*
+ * There is a kernel copy of this routine in nfs4_srv.c.
+ * Changes should be kept in sync.
+ */
+int
+make_pathname4(char *path, pathname4 *pathname)
+{
+ int ncomp;
+ component4 *comp4;
+
+ if (pathname == NULL)
+ return (0);
+
+ if (path == NULL) {
+ pathname->pathname4_val = NULL;
+ pathname->pathname4_len = 0;
+ return (0);
+ }
+
+ /* count number of components to alloc buffer */
+ if ((ncomp = nfs4_create_components(path, NULL)) == 0) {
+ pathname->pathname4_val = NULL;
+ pathname->pathname4_len = 0;
+ return (0);
+ }
+ comp4 = calloc(ncomp * sizeof (component4), 1);
+ if (comp4 == NULL) {
+ pathname->pathname4_val = NULL;
+ pathname->pathname4_len = 0;
+ return (0);
+ }
+
+ /* copy components into allocated buffer */
+ ncomp = nfs4_create_components(path, comp4);
+
+ pathname->pathname4_val = comp4;
+ pathname->pathname4_len = ncomp;
+
+ return (ncomp);
+}
+
+bool_t
+xdr_component4(register XDR *xdrs, component4 *objp)
+{
+
+ if (!xdr_utf8string(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_utf8string(register XDR *xdrs, utf8string *objp)
+{
+
+ if (xdrs->x_op != XDR_FREE)
+ return (xdr_bytes(xdrs, (char **)&objp->utf8string_val,
+ (uint_t *)&objp->utf8string_len, NFS4_MAX_UTF8STRING));
+ return (TRUE);
+}
+
+bool_t
+xdr_pathname4(register XDR *xdrs, pathname4 *objp)
+{
+
+ if (!xdr_array(xdrs, (char **)&objp->pathname4_val,
+ (uint_t *)&objp->pathname4_len, NFS4_MAX_PATHNAME4,
+ sizeof (component4), (xdrproc_t)xdr_component4))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_fs_location4(register XDR *xdrs, fs_location4 *objp)
+{
+
+ if (xdrs->x_op == XDR_DECODE) {
+ objp->server.server_val = NULL;
+ objp->rootpath.pathname4_val = NULL;
+ }
+ if (!xdr_array(xdrs, (char **)&objp->server.server_val,
+ (uint_t *)&objp->server.server_len, ~0,
+ sizeof (utf8string), (xdrproc_t)xdr_utf8string))
+ return (FALSE);
+ if (!xdr_pathname4(xdrs, &objp->rootpath))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_fs_locations4(register XDR *xdrs, fs_locations4 *objp)
+{
+
+ if (xdrs->x_op == XDR_DECODE) {
+ objp->fs_root.pathname4_len = 0;
+ objp->fs_root.pathname4_val = NULL;
+ objp->locations.locations_val = NULL;
+ }
+ if (!xdr_pathname4(xdrs, &objp->fs_root))
+ return (FALSE);
+ if (!xdr_array(xdrs, (char **)&objp->locations.locations_val,
+ (uint_t *)&objp->locations.locations_len, ~0,
+ sizeof (fs_location4), (xdrproc_t)xdr_fs_location4))
+ return (FALSE);
+ return (TRUE);
+}