summaryrefslogtreecommitdiffstats
path: root/xlators/nfs
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/nfs')
-rw-r--r--xlators/nfs/Makefile.am2
-rw-r--r--xlators/nfs/lib/Makefile.am3
-rw-r--r--xlators/nfs/lib/src/Makefile.am11
-rw-r--r--xlators/nfs/lib/src/auth-null.c71
-rw-r--r--xlators/nfs/lib/src/auth-unix.c91
-rw-r--r--xlators/nfs/lib/src/msg-nfs3.c558
-rw-r--r--xlators/nfs/lib/src/msg-nfs3.h192
-rw-r--r--xlators/nfs/lib/src/rpc-socket.c358
-rw-r--r--xlators/nfs/lib/src/rpc-socket.h65
-rw-r--r--xlators/nfs/lib/src/rpcsvc-auth.c391
-rw-r--r--xlators/nfs/lib/src/rpcsvc.c2743
-rw-r--r--xlators/nfs/lib/src/rpcsvc.h715
-rw-r--r--xlators/nfs/lib/src/xdr-common.h48
-rw-r--r--xlators/nfs/lib/src/xdr-nfs3.c1892
-rw-r--r--xlators/nfs/lib/src/xdr-nfs3.h1205
-rw-r--r--xlators/nfs/lib/src/xdr-rpc.c190
-rw-r--r--xlators/nfs/lib/src/xdr-rpc.h74
-rw-r--r--xlators/nfs/server/src/Makefile.am26
-rw-r--r--xlators/nfs/server/src/acl3.c708
-rw-r--r--xlators/nfs/server/src/acl3.h31
-rw-r--r--xlators/nfs/server/src/mount3.c2202
-rw-r--r--xlators/nfs/server/src/mount3.h85
-rw-r--r--xlators/nfs/server/src/mount3udp_svc.c189
-rw-r--r--xlators/nfs/server/src/nfs-common.c290
-rw-r--r--xlators/nfs/server/src/nfs-common.h43
-rw-r--r--xlators/nfs/server/src/nfs-fops.c856
-rw-r--r--xlators/nfs/server/src/nfs-fops.h54
-rw-r--r--xlators/nfs/server/src/nfs-generics.c64
-rw-r--r--xlators/nfs/server/src/nfs-generics.h40
-rw-r--r--xlators/nfs/server/src/nfs-inodes.c146
-rw-r--r--xlators/nfs/server/src/nfs-inodes.h23
-rw-r--r--xlators/nfs/server/src/nfs-mem-types.h53
-rw-r--r--xlators/nfs/server/src/nfs.c1390
-rw-r--r--xlators/nfs/server/src/nfs.h67
-rw-r--r--xlators/nfs/server/src/nfs3-fh.c221
-rw-r--r--xlators/nfs/server/src/nfs3-fh.h88
-rw-r--r--xlators/nfs/server/src/nfs3-helpers.c3153
-rw-r--r--xlators/nfs/server/src/nfs3-helpers.h97
-rw-r--r--xlators/nfs/server/src/nfs3.c2357
-rw-r--r--xlators/nfs/server/src/nfs3.h148
-rw-r--r--xlators/nfs/server/src/nlm4.c2525
-rw-r--r--xlators/nfs/server/src/nlm4.h77
-rw-r--r--xlators/nfs/server/src/nlmcbk_svc.c117
43 files changed, 12100 insertions, 11559 deletions
diff --git a/xlators/nfs/Makefile.am b/xlators/nfs/Makefile.am
index de3c08cba..8771032f6 100644
--- a/xlators/nfs/Makefile.am
+++ b/xlators/nfs/Makefile.am
@@ -1,3 +1,3 @@
-SUBDIRS = lib server
+SUBDIRS = server
CLEANFILES =
diff --git a/xlators/nfs/lib/Makefile.am b/xlators/nfs/lib/Makefile.am
deleted file mode 100644
index a985f42a8..000000000
--- a/xlators/nfs/lib/Makefile.am
+++ /dev/null
@@ -1,3 +0,0 @@
-SUBDIRS = src
-
-CLEANFILES =
diff --git a/xlators/nfs/lib/src/Makefile.am b/xlators/nfs/lib/src/Makefile.am
deleted file mode 100644
index a3a342aca..000000000
--- a/xlators/nfs/lib/src/Makefile.am
+++ /dev/null
@@ -1,11 +0,0 @@
-lib_LTLIBRARIES = libglrpcsvc.la
-libglrpcsvc_la_LDFLAGS = -module -avoidversion
-
-libglrpcsvc_la_SOURCES = msg-nfs3.c xdr-nfs3.c xdr-rpc.c auth-unix.c rpcsvc-auth.c rpcsvc.c auth-null.c rpc-socket.c
-libglrpcsvc_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la
-
-noinst_HEADERS = xdr-rpc.h msg-nfs3.h xdr-common.h xdr-nfs3.h rpc-socket.h rpcsvc.h
-AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -Wall -D$(GF_HOST_OS)\
- -I$(top_srcdir)/libglusterfs/src -shared -nostartfiles $(GF_CFLAGS)
-
-CLEANFILES =
diff --git a/xlators/nfs/lib/src/auth-null.c b/xlators/nfs/lib/src/auth-null.c
deleted file mode 100644
index b162db112..000000000
--- a/xlators/nfs/lib/src/auth-null.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
- This file is part of GlusterFS.
-
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
-*/
-
-
-#ifndef _CONFIG_H
-#define _CONFIG_H
-#include "config.h"
-#endif
-
-#include "rpcsvc.h"
-#include "list.h"
-#include "dict.h"
-
-
-int
-auth_null_request_init (rpcsvc_request_t *req, void *priv)
-{
- if (!req)
- return -1;
-
- memset (req->cred.authdata, 0, RPCSVC_MAX_AUTH_BYTES);
- req->cred.datalen = 0;
-
- memset (req->verf.authdata, 0, RPCSVC_MAX_AUTH_BYTES);
- req->verf.datalen = 0;
-
- return 0;
-}
-
-int auth_null_authenticate (rpcsvc_request_t *req, void *priv)
-{
- /* Always succeed. */
- return RPCSVC_AUTH_ACCEPT;
-}
-
-rpcsvc_auth_ops_t auth_null_ops = {
- .conn_init = NULL,
- .request_init = auth_null_request_init,
- .authenticate = auth_null_authenticate
-};
-
-rpcsvc_auth_t rpcsvc_auth_null = {
- .authname = "AUTH_NULL",
- .authnum = AUTH_NULL,
- .authops = &auth_null_ops,
- .authprivate = NULL
-};
-
-
-rpcsvc_auth_t *
-rpcsvc_auth_null_init (rpcsvc_t *svc, dict_t *options)
-{
- return &rpcsvc_auth_null;
-}
-
diff --git a/xlators/nfs/lib/src/auth-unix.c b/xlators/nfs/lib/src/auth-unix.c
deleted file mode 100644
index 0eaf06866..000000000
--- a/xlators/nfs/lib/src/auth-unix.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
- This file is part of GlusterFS.
-
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
-*/
-
-
-
-#ifndef _CONFIG_H
-#define _CONFIG_H
-#include "config.h"
-#endif
-
-#include "rpcsvc.h"
-#include "list.h"
-#include "dict.h"
-#include "xdr-rpc.h"
-
-
-int
-auth_unix_request_init (rpcsvc_request_t *req, void *priv)
-{
- if (!req)
- return -1;
- memset (req->verf.authdata, 0, RPCSVC_MAX_AUTH_BYTES);
- req->verf.datalen = 0;
- req->verf.flavour = AUTH_NULL;
-
- return 0;
-}
-
-int auth_unix_authenticate (rpcsvc_request_t *req, void *priv)
-{
- int ret = RPCSVC_AUTH_REJECT;
- struct authunix_parms aup;
- char machname[MAX_MACHINE_NAME];
-
- if (!req)
- return ret;
-
- ret = xdr_to_auth_unix_cred (req->cred.authdata, req->cred.datalen,
- &aup, machname, req->auxgids);
- if (ret == -1) {
- ret = RPCSVC_AUTH_REJECT;
- goto err;
- }
-
- req->uid = aup.aup_uid;
- req->gid = aup.aup_gid;
- req->auxgidcount = aup.aup_len;
-
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "Auth Info: machine name: %s, uid: %d"
- ", gid: %d", machname, req->uid, req->gid);
- ret = RPCSVC_AUTH_ACCEPT;
-err:
- return ret;
-}
-
-rpcsvc_auth_ops_t auth_unix_ops = {
- .conn_init = NULL,
- .request_init = auth_unix_request_init,
- .authenticate = auth_unix_authenticate
-};
-
-rpcsvc_auth_t rpcsvc_auth_unix = {
- .authname = "AUTH_UNIX",
- .authnum = AUTH_UNIX,
- .authops = &auth_unix_ops,
- .authprivate = NULL
-};
-
-
-rpcsvc_auth_t *
-rpcsvc_auth_unix_init (rpcsvc_t *svc, dict_t *options)
-{
- return &rpcsvc_auth_unix;
-}
-
diff --git a/xlators/nfs/lib/src/msg-nfs3.c b/xlators/nfs/lib/src/msg-nfs3.c
deleted file mode 100644
index 781466045..000000000
--- a/xlators/nfs/lib/src/msg-nfs3.c
+++ /dev/null
@@ -1,558 +0,0 @@
-/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
- This file is part of GlusterFS.
-
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _CONFIG_H
-#define _CONFIG_H
-#include "config.h"
-#endif
-
-#include <sys/uio.h>
-#include <rpc/rpc.h>
-#include <rpc/xdr.h>
-#include <sys/types.h>
-
-#include "xdr-nfs3.h"
-#include "msg-nfs3.h"
-#include "xdr-common.h"
-
-
-/* Decode the mount path from the network message in inmsg
- * into the memory referenced by outpath.iov_base.
- * The size allocated for outpath.iov_base is outpath.iov_len.
- * The size of the path extracted from the message is returned.
- */
-ssize_t
-xdr_to_mountpath (struct iovec outpath, struct iovec inmsg)
-{
- XDR xdr;
- ssize_t ret = -1;
- char *mntpath = NULL;
-
- if ((!outpath.iov_base) || (!inmsg.iov_base))
- return -1;
-
- xdrmem_create (&xdr, inmsg.iov_base, (unsigned int)inmsg.iov_len,
- XDR_DECODE);
-
- mntpath = outpath.iov_base;
- if (!xdr_dirpath (&xdr, (dirpath *)&mntpath)) {
- ret = -1;
- goto ret;
- }
-
- ret = xdr_decoded_length (xdr);
-
-ret:
- return ret;
-}
-
-
-ssize_t
-xdr_serialize_generic (struct iovec outmsg, void *res, xdrproc_t proc)
-{
- ssize_t ret = -1;
- XDR xdr;
-
- if ((!outmsg.iov_base) || (!res) || (!proc))
- return -1;
-
- xdrmem_create (&xdr, outmsg.iov_base, (unsigned int)outmsg.iov_len,
- XDR_ENCODE);
-
- if (!proc (&xdr, res)) {
- ret = -1;
- goto ret;
- }
-
- ret = xdr_encoded_length (xdr);
-
-ret:
- return ret;
-}
-
-
-ssize_t
-xdr_to_generic (struct iovec inmsg, void *args, xdrproc_t proc)
-{
- XDR xdr;
- ssize_t ret = -1;
-
- if ((!inmsg.iov_base) || (!args) || (!proc))
- return -1;
-
- xdrmem_create (&xdr, inmsg.iov_base, (unsigned int)inmsg.iov_len,
- XDR_DECODE);
-
- if (!proc (&xdr, args)) {
- ret = -1;
- goto ret;
- }
-
- ret = xdr_decoded_length (xdr);
-ret:
- return ret;
-}
-
-
-ssize_t
-xdr_to_generic_payload (struct iovec inmsg, void *args, xdrproc_t proc,
- struct iovec *pendingpayload)
-{
- XDR xdr;
- ssize_t ret = -1;
-
- if ((!inmsg.iov_base) || (!args) || (!proc))
- return -1;
-
- xdrmem_create (&xdr, inmsg.iov_base, (unsigned int)inmsg.iov_len,
- XDR_DECODE);
-
- if (!proc (&xdr, args)) {
- ret = -1;
- goto ret;
- }
-
- ret = xdr_decoded_length (xdr);
-
- if (pendingpayload) {
- pendingpayload->iov_base = xdr_decoded_remaining_addr (xdr);
- pendingpayload->iov_len = xdr_decoded_remaining_len (xdr);
- }
-
-ret:
- return ret;
-}
-
-
-/* Translate the mountres3 structure in res into XDR format into memory
- * referenced by outmsg.iov_base.
- * Returns the number of bytes used in encoding into XDR format.
- */
-ssize_t
-xdr_serialize_mountres3 (struct iovec outmsg, mountres3 *res)
-{
- return xdr_serialize_generic (outmsg, (void *)res,
- (xdrproc_t)xdr_mountres3);
-}
-
-
-ssize_t
-xdr_serialize_mountbody (struct iovec outmsg, mountbody *mb)
-{
- return xdr_serialize_generic (outmsg, (void *)mb,
- (xdrproc_t)xdr_mountbody);
-}
-
-ssize_t
-xdr_serialize_mountlist (struct iovec outmsg, mountlist *ml)
-{
- return xdr_serialize_generic (outmsg, (void *)ml,
- (xdrproc_t)xdr_mountlist);
-}
-
-
-ssize_t
-xdr_serialize_mountstat3 (struct iovec outmsg, mountstat3 *m)
-{
- return xdr_serialize_generic (outmsg, (void *)m,
- (xdrproc_t)xdr_mountstat3);
-}
-
-
-ssize_t
-xdr_to_getattr3args (struct iovec inmsg, getattr3args *ga)
-{
- return xdr_to_generic (inmsg, (void *)ga,(xdrproc_t)xdr_getattr3args);
-}
-
-
-ssize_t
-xdr_serialize_getattr3res (struct iovec outmsg, getattr3res *res)
-{
- return xdr_serialize_generic (outmsg, (void *)res,
- (xdrproc_t)xdr_getattr3res);
-}
-
-
-ssize_t
-xdr_serialize_setattr3res (struct iovec outmsg, setattr3res *res)
-{
- return xdr_serialize_generic (outmsg, (void *)res,
- (xdrproc_t)xdr_setattr3res);
-}
-
-
-ssize_t
-xdr_to_setattr3args (struct iovec inmsg, setattr3args *sa)
-{
- return xdr_to_generic (inmsg, (void *)sa, (xdrproc_t)xdr_setattr3args);
-}
-
-
-ssize_t
-xdr_serialize_lookup3res (struct iovec outmsg, lookup3res *res)
-{
- return xdr_serialize_generic (outmsg, (void *)res,
- (xdrproc_t)xdr_lookup3res);
-}
-
-
-ssize_t
-xdr_to_lookup3args (struct iovec inmsg, lookup3args *la)
-{
- return xdr_to_generic (inmsg, (void *)la, (xdrproc_t)xdr_lookup3args);
-}
-
-
-ssize_t
-xdr_to_access3args (struct iovec inmsg, access3args *ac)
-{
- return xdr_to_generic (inmsg,(void *)ac, (xdrproc_t)xdr_access3args);
-}
-
-
-ssize_t
-xdr_serialize_access3res (struct iovec outmsg, access3res *res)
-{
- return xdr_serialize_generic (outmsg, (void *)res,
- (xdrproc_t)xdr_access3res);
-}
-
-
-ssize_t
-xdr_to_readlink3args (struct iovec inmsg, readlink3args *ra)
-{
- return xdr_to_generic (inmsg, (void *)ra, (xdrproc_t)xdr_readlink3args);
-}
-
-
-ssize_t
-xdr_serialize_readlink3res (struct iovec outmsg, readlink3res *res)
-{
- return xdr_serialize_generic (outmsg, (void *)res,
- (xdrproc_t)xdr_readlink3res);
-}
-
-
-ssize_t
-xdr_to_read3args (struct iovec inmsg, read3args *ra)
-{
- return xdr_to_generic (inmsg, (void *)ra, (xdrproc_t)xdr_read3args);
-}
-
-
-ssize_t
-xdr_serialize_read3res (struct iovec outmsg, read3res *res)
-{
- return xdr_serialize_generic (outmsg, (void *)res,
- (xdrproc_t)xdr_read3res);
-}
-
-ssize_t
-xdr_serialize_read3res_nocopy (struct iovec outmsg, read3res *res)
-{
- return xdr_serialize_generic (outmsg, (void *)res,
- (xdrproc_t)xdr_read3res_nocopy);
-}
-
-
-ssize_t
-xdr_to_write3args (struct iovec inmsg, write3args *wa)
-{
- return xdr_to_generic (inmsg, (void *)wa,(xdrproc_t)xdr_write3args);
-}
-
-
-ssize_t
-xdr_to_write3args_nocopy (struct iovec inmsg, write3args *wa,
- struct iovec *payload)
-{
- return xdr_to_generic_payload (inmsg, (void *)wa,
- (xdrproc_t)xdr_write3args, payload);
-}
-
-
-ssize_t
-xdr_serialize_write3res (struct iovec outmsg, write3res *res)
-{
- return xdr_serialize_generic (outmsg, (void *)res,
- (xdrproc_t)xdr_write3res);
-}
-
-
-ssize_t
-xdr_to_create3args (struct iovec inmsg, create3args *ca)
-{
- return xdr_to_generic (inmsg, (void *)ca, (xdrproc_t)xdr_create3args);
-}
-
-
-ssize_t
-xdr_serialize_create3res (struct iovec outmsg, create3res *res)
-{
- return xdr_serialize_generic (outmsg, (void *)res,
- (xdrproc_t)xdr_create3res);
-}
-
-
-ssize_t
-xdr_serialize_mkdir3res (struct iovec outmsg, mkdir3res *res)
-{
- return xdr_serialize_generic (outmsg, (void *)res,
- (xdrproc_t)xdr_mkdir3res);
-}
-
-
-ssize_t
-xdr_to_mkdir3args (struct iovec inmsg, mkdir3args *ma)
-{
- return xdr_to_generic (inmsg, (void *)ma, (xdrproc_t)xdr_mkdir3args);
-}
-
-
-ssize_t
-xdr_to_symlink3args (struct iovec inmsg, symlink3args *sa)
-{
- return xdr_to_generic (inmsg, (void *)sa, (xdrproc_t)xdr_symlink3args);
-}
-
-
-ssize_t
-xdr_serialize_symlink3res (struct iovec outmsg, symlink3res *res)
-{
- return xdr_serialize_generic (outmsg, (void *)res,
- (xdrproc_t)xdr_symlink3res);
-}
-
-
-ssize_t
-xdr_to_mknod3args (struct iovec inmsg, mknod3args *ma)
-{
- return xdr_to_generic (inmsg, (void *)ma, (xdrproc_t)xdr_mknod3args);
-}
-
-
-ssize_t
-xdr_serialize_mknod3res (struct iovec outmsg, mknod3res *res)
-{
- return xdr_serialize_generic (outmsg, (void *)res,
- (xdrproc_t)xdr_mknod3res);
-}
-
-
-ssize_t
-xdr_to_remove3args (struct iovec inmsg, remove3args *ra)
-{
- return xdr_to_generic (inmsg, (void *)ra, (xdrproc_t)xdr_remove3args);
-}
-
-
-ssize_t
-xdr_serialize_remove3res (struct iovec outmsg, remove3res *res)
-{
- return xdr_serialize_generic (outmsg, (void *)res,
- (xdrproc_t)xdr_remove3res);
-}
-
-
-ssize_t
-xdr_to_rmdir3args (struct iovec inmsg, rmdir3args *ra)
-{
- return xdr_to_generic (inmsg, (void *)ra, (xdrproc_t)xdr_rmdir3args);
-}
-
-
-ssize_t
-xdr_serialize_rmdir3res (struct iovec outmsg, rmdir3res *res)
-{
- return xdr_serialize_generic (outmsg, (void *)res,
- (xdrproc_t)xdr_rmdir3res);
-}
-
-
-ssize_t
-xdr_serialize_rename3res (struct iovec outmsg, rename3res *res)
-{
- return xdr_serialize_generic (outmsg, (void *)res,
- (xdrproc_t)xdr_rename3res);
-}
-
-
-ssize_t
-xdr_to_rename3args (struct iovec inmsg, rename3args *ra)
-{
- return xdr_to_generic (inmsg, (void *)ra, (xdrproc_t)xdr_rename3args);
-}
-
-
-ssize_t
-xdr_serialize_link3res (struct iovec outmsg, link3res *li)
-{
- return xdr_serialize_generic (outmsg, (void *)li,
- (xdrproc_t)xdr_link3res);
-}
-
-
-ssize_t
-xdr_to_link3args (struct iovec inmsg, link3args *la)
-{
- return xdr_to_generic (inmsg, (void *)la, (xdrproc_t)xdr_link3args);
-}
-
-
-ssize_t
-xdr_to_readdir3args (struct iovec inmsg, readdir3args *rd)
-{
- return xdr_to_generic (inmsg, (void *)rd, (xdrproc_t)xdr_readdir3args);
-}
-
-
-ssize_t
-xdr_serialize_readdir3res (struct iovec outmsg, readdir3res *res)
-{
- return xdr_serialize_generic (outmsg, (void *)res,
- (xdrproc_t)xdr_readdir3res);
-}
-
-
-ssize_t
-xdr_to_readdirp3args (struct iovec inmsg, readdirp3args *rp)
-{
- return xdr_to_generic (inmsg, (void *)rp, (xdrproc_t)xdr_readdirp3args);
-}
-
-
-ssize_t
-xdr_serialize_readdirp3res (struct iovec outmsg, readdirp3res *res)
-{
- return xdr_serialize_generic (outmsg, (void *)res,
- (xdrproc_t)xdr_readdirp3res);
-}
-
-
-ssize_t
-xdr_to_fsstat3args (struct iovec inmsg, fsstat3args *fa)
-{
- return xdr_to_generic (inmsg, (void *)fa, (xdrproc_t)xdr_fsstat3args);
-}
-
-
-ssize_t
-xdr_serialize_fsstat3res (struct iovec outmsg, fsstat3res *res)
-{
- return xdr_serialize_generic (outmsg, (void *)res,
- (xdrproc_t)xdr_fsstat3res);
-}
-
-ssize_t
-xdr_to_fsinfo3args (struct iovec inmsg, fsinfo3args *fi)
-{
- return xdr_to_generic (inmsg, (void *)fi, (xdrproc_t)xdr_fsinfo3args);
-}
-
-
-ssize_t
-xdr_serialize_fsinfo3res (struct iovec outmsg, fsinfo3res *res)
-{
- return xdr_serialize_generic (outmsg, (void *)res,
- (xdrproc_t)xdr_fsinfo3res);
-}
-
-
-ssize_t
-xdr_to_pathconf3args (struct iovec inmsg, pathconf3args *pc)
-{
- return xdr_to_generic (inmsg, (void *)pc, (xdrproc_t)xdr_pathconf3args);}
-
-
-ssize_t
-xdr_serialize_pathconf3res (struct iovec outmsg, pathconf3res *res)
-{
- return xdr_serialize_generic (outmsg, (void *)res,
- (xdrproc_t)xdr_pathconf3res);
-}
-
-
-ssize_t
-xdr_to_commit3args (struct iovec inmsg, commit3args *ca)
-{
- return xdr_to_generic (inmsg, (void *)ca, (xdrproc_t)xdr_commit3args);
-}
-
-
-ssize_t
-xdr_serialize_commit3res (struct iovec outmsg, commit3res *res)
-{
- return xdr_serialize_generic (outmsg, (void *)res,
- (xdrproc_t)xdr_commit3res);
-}
-
-
-ssize_t
-xdr_serialize_exports (struct iovec outmsg, exports *elist)
-{
- XDR xdr;
- ssize_t ret = -1;
-
- if ((!outmsg.iov_base) || (!elist))
- return -1;
-
- xdrmem_create (&xdr, outmsg.iov_base, (unsigned int)outmsg.iov_len,
- XDR_ENCODE);
-
- if (!xdr_exports (&xdr, elist))
- goto ret;
-
- ret = xdr_decoded_length (xdr);
-
-ret:
- return ret;
-}
-
-
-ssize_t
-xdr_serialize_nfsstat3 (struct iovec outmsg, nfsstat3 *s)
-{
- return xdr_serialize_generic (outmsg, (void *)s,
- (xdrproc_t)xdr_nfsstat3);
-}
-
-
-ssize_t
-xdr_length_round_up (size_t len, size_t bufsize)
-{
- int roundup = 0;
-
- roundup = len % XDR_BYTES_PER_UNIT;
- if (roundup > 0)
- roundup = XDR_BYTES_PER_UNIT - roundup;
-
- if ((roundup > 0) && ((roundup + len) <= bufsize))
- len += roundup;
-
- return len;
-}
-
-int
-xdr_bytes_round_up (struct iovec *vec, size_t bufsize)
-{
- vec->iov_len = xdr_length_round_up (vec->iov_len, bufsize);
- return 0;
-}
-
diff --git a/xlators/nfs/lib/src/msg-nfs3.h b/xlators/nfs/lib/src/msg-nfs3.h
deleted file mode 100644
index 78682bc1c..000000000
--- a/xlators/nfs/lib/src/msg-nfs3.h
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
- This file is part of GlusterFS.
-
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _MSG_NFS3_H_
-#define _MSG_NFS3_H_
-
-#ifndef _CONFIG_H
-#define _CONFIG_H
-#include "config.h"
-#endif
-
-#include "xdr-nfs3.h"
-
-#include <sys/types.h>
-#include <sys/uio.h>
-
-extern ssize_t
-xdr_to_mountpath (struct iovec outpath, struct iovec inmsg);
-
-extern ssize_t
-xdr_serialize_mountres3 (struct iovec outmsg, mountres3 *res);
-
-extern ssize_t
-xdr_serialize_mountbody (struct iovec outmsg, mountbody *mb);
-
-extern ssize_t
-xdr_to_getattr3args (struct iovec inmsg, getattr3args *ga);
-
-extern ssize_t
-xdr_serialize_getattr3res (struct iovec outmsg, getattr3res *res);
-
-extern ssize_t
-xdr_serialize_setattr3res (struct iovec outmsg, setattr3res *res);
-
-extern ssize_t
-xdr_to_setattr3args (struct iovec inmsg, setattr3args *sa);
-
-extern ssize_t
-xdr_serialize_lookup3res (struct iovec outmsg, lookup3res *res);
-
-extern ssize_t
-xdr_to_lookup3args (struct iovec inmsg, lookup3args *la);
-
-extern ssize_t
-xdr_to_access3args (struct iovec inmsg, access3args *ac);
-
-extern ssize_t
-xdr_serialize_access3res (struct iovec outmsg, access3res *res);
-
-extern ssize_t
-xdr_to_readlink3args (struct iovec inmsg, readlink3args *ra);
-
-extern ssize_t
-xdr_serialize_readlink3res (struct iovec outmsg, readlink3res *res);
-
-extern ssize_t
-xdr_to_read3args (struct iovec inmsg, read3args *ra);
-
-extern ssize_t
-xdr_serialize_read3res (struct iovec outmsg, read3res *res);
-
-extern ssize_t
-xdr_serialize_read3res_nocopy (struct iovec outmsg, read3res *res);
-
-extern ssize_t
-xdr_to_write3args (struct iovec inmsg, write3args *wa);
-
-extern ssize_t
-xdr_to_write3args_nocopy (struct iovec inmsg, write3args *wa,
- struct iovec *payload);
-
-extern ssize_t
-xdr_serialize_write3res (struct iovec outmsg, write3res *res);
-
-extern ssize_t
-xdr_to_create3args (struct iovec inmsg, create3args *ca);
-
-extern ssize_t
-xdr_serialize_create3res (struct iovec outmsg, create3res *res);
-
-extern ssize_t
-xdr_serialize_mkdir3res (struct iovec outmsg, mkdir3res *res);
-
-extern ssize_t
-xdr_to_mkdir3args (struct iovec inmsg, mkdir3args *ma);
-
-extern ssize_t
-xdr_to_symlink3args (struct iovec inmsg, symlink3args *sa);
-
-extern ssize_t
-xdr_serialize_symlink3res (struct iovec outmsg, symlink3res *res);
-
-extern ssize_t
-xdr_to_mknod3args (struct iovec inmsg, mknod3args *ma);
-
-extern ssize_t
-xdr_serialize_mknod3res (struct iovec outmsg, mknod3res *res);
-
-extern ssize_t
-xdr_to_remove3args (struct iovec inmsg, remove3args *ra);
-
-extern ssize_t
-xdr_serialize_remove3res (struct iovec outmsg, remove3res *res);
-
-extern ssize_t
-xdr_to_rmdir3args (struct iovec inmsg, rmdir3args *ra);
-
-extern ssize_t
-xdr_serialize_rmdir3res (struct iovec outmsg, rmdir3res *res);
-
-extern ssize_t
-xdr_serialize_rename3res (struct iovec outmsg, rename3res *res);
-
-extern ssize_t
-xdr_to_rename3args (struct iovec inmsg, rename3args *ra);
-
-extern ssize_t
-xdr_serialize_link3res (struct iovec outmsg, link3res *li);
-
-extern ssize_t
-xdr_to_link3args (struct iovec inmsg, link3args *la);
-
-extern ssize_t
-xdr_to_readdir3args (struct iovec inmsg, readdir3args *rd);
-
-extern ssize_t
-xdr_serialize_readdir3res (struct iovec outmsg, readdir3res *res);
-
-extern ssize_t
-xdr_to_readdirp3args (struct iovec inmsg, readdirp3args *rp);
-
-extern ssize_t
-xdr_serialize_readdirp3res (struct iovec outmsg, readdirp3res *res);
-
-extern ssize_t
-xdr_to_fsstat3args (struct iovec inmsg, fsstat3args *fa);
-
-extern ssize_t
-xdr_serialize_fsstat3res (struct iovec outmsg, fsstat3res *res);
-
-extern ssize_t
-xdr_to_fsinfo3args (struct iovec inmsg, fsinfo3args *fi);
-
-extern ssize_t
-xdr_serialize_fsinfo3res (struct iovec outmsg, fsinfo3res *res);
-
-extern ssize_t
-xdr_to_pathconf3args (struct iovec inmsg, pathconf3args *pc);
-
-extern ssize_t
-xdr_serialize_pathconf3res (struct iovec outmsg, pathconf3res *res);
-
-extern ssize_t
-xdr_to_commit3args (struct iovec inmsg, commit3args *ca);
-
-extern ssize_t
-xdr_serialize_commit3res (struct iovec outmsg, commit3res *res);
-
-extern ssize_t
-xdr_serialize_exports (struct iovec outmsg, exports *elist);
-
-extern ssize_t
-xdr_serialize_mountlist (struct iovec outmsg, mountlist *ml);
-
-extern ssize_t
-xdr_serialize_mountstat3 (struct iovec outmsg, mountstat3 *m);
-
-extern ssize_t
-xdr_serialize_nfsstat3 (struct iovec outmsg, nfsstat3 *s);
-
-extern int
-xdr_bytes_round_up (struct iovec *vec, size_t bufsize);
-
-extern ssize_t
-xdr_length_round_up (size_t len, size_t bufsize);
-#endif
diff --git a/xlators/nfs/lib/src/rpc-socket.c b/xlators/nfs/lib/src/rpc-socket.c
deleted file mode 100644
index 01f114a85..000000000
--- a/xlators/nfs/lib/src/rpc-socket.c
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
- This file is part of GlusterFS.
-
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _CONFIG_H
-#define _CONFIG_H
-#include "config.h"
-#endif
-
-#include "rpc-socket.h"
-#include "rpcsvc.h"
-#include "dict.h"
-#include "logging.h"
-#include "byte-order.h"
-#include "common-utils.h"
-#include "compat-errno.h"
-
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-
-static int
-rpcsvc_socket_server_get_local_socket (int addrfam, char *listenhost,
- uint16_t listenport,
- struct sockaddr *addr,
- socklen_t *addr_len)
-{
- struct addrinfo hints, *res = 0;
- char service[NI_MAXSERV];
- int ret = -1;
-
- memset (service, 0, sizeof (service));
- sprintf (service, "%d", listenport);
-
- memset (&hints, 0, sizeof (hints));
- addr->sa_family = hints.ai_family = addrfam;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
-
- ret = getaddrinfo(listenhost, service, &hints, &res);
- if (ret != 0) {
- gf_log (GF_RPCSVC_SOCK, GF_LOG_ERROR,
- "getaddrinfo failed for host %s, service %s (%s)",
- listenhost, service, gai_strerror (ret));
- ret = -1;
- goto err;
- }
-
- memcpy (addr, res->ai_addr, res->ai_addrlen);
- *addr_len = res->ai_addrlen;
-
- freeaddrinfo (res);
- ret = 0;
-
-err:
- return ret;
-}
-
-
-int
-rpcsvc_socket_listen (int addrfam, char *listenhost, uint16_t listenport)
-{
- int sock = -1;
- struct sockaddr_storage sockaddr;
- socklen_t sockaddr_len;
- int flags = 0;
- int ret = -1;
- int opt = 1;
-
- ret = rpcsvc_socket_server_get_local_socket (addrfam, listenhost,
- listenport,SA (&sockaddr),
- &sockaddr_len);
-
- if (ret == -1)
- return ret;
-
- sock = socket (SA (&sockaddr)->sa_family, SOCK_STREAM, 0);
- if (sock == -1) {
- gf_log (GF_RPCSVC_SOCK, GF_LOG_ERROR, "socket creation failed"
- " (%s)", strerror (errno));
- goto err;
- }
-
- flags = fcntl (sock, F_GETFL);
- if (flags == -1) {
- gf_log (GF_RPCSVC_SOCK, GF_LOG_ERROR, "cannot get socket flags"
- " (%s)", strerror(errno));
- goto close_err;
- }
-
- ret = fcntl (sock, F_SETFL, flags | O_NONBLOCK);
- if (ret == -1) {
- gf_log (GF_RPCSVC_SOCK, GF_LOG_ERROR, "cannot set socket "
- "non-blocking (%s)", strerror (errno));
- goto close_err;
- }
-
- ret = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt));
- if (ret == -1) {
- gf_log (GF_RPCSVC_SOCK, GF_LOG_ERROR, "setsockopt() for "
- "SO_REUSEADDR failed (%s)", strerror (errno));
- goto close_err;
- }
-
- ret = bind (sock, (struct sockaddr *)&sockaddr, sockaddr_len);
- if (ret == -1) {
- gf_log (GF_RPCSVC_SOCK, GF_LOG_ERROR, "binding socket failed:"
- " %s", strerror (errno));
- if (errno == EADDRINUSE)
- gf_log (GF_RPCSVC_SOCK, GF_LOG_ERROR, "Port is already"
- " in use");
- goto close_err;
- }
-
- ret = listen (sock, 10);
- if (ret == -1) {
- gf_log (GF_RPCSVC_SOCK, GF_LOG_ERROR, "could not listen on"
- " socket (%s)", strerror (errno));
- goto close_err;
- }
-
- return sock;
-
-close_err:
- close (sock);
- sock = -1;
-
-err:
- return sock;
-}
-
-
-int
-rpcsvc_socket_accept (int listenfd)
-{
- int new_sock = -1;
- struct sockaddr_storage new_sockaddr = {0, };
- socklen_t addrlen = sizeof (new_sockaddr);
- int flags = 0;
- int ret = -1;
- int on = 1;
-
- new_sock = accept (listenfd, SA (&new_sockaddr), &addrlen);
- if (new_sock == -1) {
- gf_log (GF_RPCSVC_SOCK, GF_LOG_ERROR,"accept on socket failed");
- goto err;
- }
-
- flags = fcntl (new_sock, F_GETFL);
- if (flags == -1) {
- gf_log (GF_RPCSVC_SOCK, GF_LOG_ERROR, "cannot get socket flags"
- " (%s)", strerror(errno));
- goto close_err;
- }
-
- ret = fcntl (new_sock, F_SETFL, flags | O_NONBLOCK);
- if (ret == -1) {
- gf_log (GF_RPCSVC_SOCK, GF_LOG_ERROR, "cannot set socket "
- "non-blocking (%s)", strerror (errno));
- goto close_err;
- }
-
-#ifdef TCP_NODELAY
- ret = setsockopt(new_sock, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
- if (ret == -1) {
- gf_log (GF_RPCSVC_SOCK, GF_LOG_ERROR, "cannot set no-delay "
- " socket option");
- }
-#endif
-
- return new_sock;
-
-close_err:
- close (new_sock);
- new_sock = -1;
-
-err:
- return new_sock;
-}
-
-ssize_t
-rpcsvc_socket_read (int sockfd, char *readaddr, size_t readsize)
-{
- ssize_t dataread = 0;
- ssize_t readlen = -1;
-
- if (!readaddr)
- return -1;
-
- while (readsize > 0) {
- readlen = read (sockfd, readaddr, readsize);
- if (readlen == -1) {
- if (errno != EAGAIN) {
- dataread = -1;
- break;
- } else
- break;
- } else if (readlen == 0)
- break;
-
- dataread += readlen;
- readaddr += readlen;
- readsize -= readlen;
- }
-
- return dataread;
-}
-
-
-ssize_t
-rpcsvc_socket_write (int sockfd, char *buffer, size_t size)
-{
- size_t writelen = -1;
- ssize_t written = 0;
-
- if (!buffer)
- return -1;
-
- while (size > 0) {
- writelen = write (sockfd, buffer, size);
- if (writelen == -1) {
- if (errno != EAGAIN) {
- written = -1;
- break;
- } else
- break;
- } else if (writelen == 0)
- break;
-
- written += writelen;
- size -= writelen;
- buffer += writelen;
- }
-
- return written;
-}
-
-
-int
-rpcsvc_socket_peername (int sockfd, char *hostname, int hostlen)
-{
- struct sockaddr sa;
- socklen_t sl = sizeof (sa);
- int ret = EAI_FAIL;
-
- if (!hostname)
- return ret;
-
- ret = getpeername (sockfd, &sa, &sl);
- if (ret == -1) {
- gf_log (GF_RPCSVC_SOCK, GF_LOG_ERROR, "Failed to get peer name:"
- " %s", strerror (errno));
- ret = EAI_FAIL;
- goto err;
- }
-
- ret = getnameinfo (&sa, sl, hostname, hostlen, NULL, 0, 0);
- if (ret != 0)
- goto err;
-
-err:
- return ret;
-}
-
-
-int
-rpcsvc_socket_peeraddr (int sockfd, char *addrstr, int addrlen,
- struct sockaddr *returnsa, socklen_t sasize)
-{
- struct sockaddr sa;
- int ret = EAI_FAIL;
-
- if (returnsa)
- ret = getpeername (sockfd, returnsa, &sasize);
- else {
- sasize = sizeof (sa);
- ret = getpeername (sockfd, &sa, &sasize);
- }
-
- if (ret == -1) {
- gf_log (GF_RPCSVC_SOCK, GF_LOG_ERROR, "Failed to get peer addr:"
- " %s", strerror (errno));
- ret = EAI_FAIL;
- goto err;
- }
-
- /* If caller did not specify a string into which the address can be
- * stored, dont bother getting it.
- */
- if (!addrstr) {
- ret = 0;
- goto err;
- }
-
- if (returnsa)
- ret = getnameinfo (returnsa, sasize, addrstr, addrlen, NULL, 0,
- NI_NUMERICHOST);
- else
- ret = getnameinfo (&sa, sasize, addrstr, addrlen, NULL, 0,
- NI_NUMERICHOST);
-
-err:
- return ret;
-}
-
-
-int
-rpcsvc_socket_block_tx (int sockfd)
-{
- int ret = -1;
- int on = 1;
-
-#ifdef TCP_CORK
- ret = setsockopt(sockfd, IPPROTO_TCP, TCP_CORK, &on, sizeof(on));
-#endif
-
-#ifdef TCP_NOPUSH
- ret = setsockopt(sockfd, IPPROTO_TCP, TCP_NOPUSH, &on, sizeof(on));
-#endif
-
- return ret;
-}
-
-
-int
-rpcsvc_socket_unblock_tx (int sockfd)
-{
- int ret = -1;
- int off = 0;
-
-#ifdef TCP_CORK
- ret = setsockopt(sockfd, IPPROTO_TCP, TCP_CORK, &off, sizeof(off));
-#endif
-
-#ifdef TCP_NOPUSH
- ret = setsockopt(sockfd, IPPROTO_TCP, TCP_NOPUSH, &off, sizeof(off));
-#endif
- return ret;
-}
-
diff --git a/xlators/nfs/lib/src/rpc-socket.h b/xlators/nfs/lib/src/rpc-socket.h
deleted file mode 100644
index 3a50c97a9..000000000
--- a/xlators/nfs/lib/src/rpc-socket.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
- This file is part of GlusterFS.
-
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _RPCSVC_SOCKET_H_
-#define _RPCSVC_SOCKET_H_
-
-#ifndef _CONFIG_H
-#define _CONFIG_H
-#include "config.h"
-#endif
-
-#include "rpcsvc.h"
-#include "dict.h"
-#include "logging.h"
-#include "byte-order.h"
-#include "common-utils.h"
-#include "compat-errno.h"
-
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <netdb.h>
-
-#define SA(ptr) ((struct sockaddr *)ptr)
-#define GF_RPCSVC_SOCK "rpc-socket"
-extern int
-rpcsvc_socket_listen (int addrfam, char *listenhost, uint16_t listenport);
-
-extern int
-rpcsvc_socket_accept (int listenfd);
-
-extern ssize_t
-rpcsvc_socket_read (int sockfd, char *readaddr, size_t readsize);
-
-extern ssize_t
-rpcsvc_socket_write (int sockfd, char *buffer, size_t size);
-
-extern int
-rpcsvc_socket_peername (int sockfd, char *hostname, int hostlen);
-
-extern int
-rpcsvc_socket_peeraddr (int sockfd, char *addrstr, int addrlen,
- struct sockaddr *returnsa, socklen_t sasize);
-extern int
-rpcsvc_socket_block_tx (int sockfd);
-
-extern int
-rpcsvc_socket_unblock_tx (int sockfd);
-#endif
diff --git a/xlators/nfs/lib/src/rpcsvc-auth.c b/xlators/nfs/lib/src/rpcsvc-auth.c
deleted file mode 100644
index 38697965b..000000000
--- a/xlators/nfs/lib/src/rpcsvc-auth.c
+++ /dev/null
@@ -1,391 +0,0 @@
-/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
- This file is part of GlusterFS.
-
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
-*/
-
-#include "rpcsvc.h"
-#include "logging.h"
-#include "dict.h"
-
-extern rpcsvc_auth_t *
-rpcsvc_auth_null_init (rpcsvc_t *svc, dict_t *options);
-
-extern rpcsvc_auth_t *
-rpcsvc_auth_unix_init (rpcsvc_t *svc, dict_t *options);
-
-int
-rpcsvc_auth_add_initer (struct list_head *list, char *idfier,
- rpcsvc_auth_initer_t init)
-{
- struct rpcsvc_auth_list *new = NULL;
-
- if ((!list) || (!init) || (!idfier))
- return -1;
-
- new = CALLOC (1, sizeof (*new));
- if (!new) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Memory allocation failed");
- return -1;
- }
-
- new->init = init;
- strcpy (new->name, idfier);
- INIT_LIST_HEAD (&new->authlist);
- list_add_tail (&new->authlist, list);
- return 0;
-}
-
-
-
-int
-rpcsvc_auth_add_initers (rpcsvc_t *svc)
-{
- int ret = -1;
-
- ret = rpcsvc_auth_add_initer (&svc->authschemes, "auth-unix",
- (rpcsvc_auth_initer_t)
- rpcsvc_auth_unix_init);
- if (ret == -1) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to add AUTH_UNIX");
- goto err;
- }
-
- ret = rpcsvc_auth_add_initer (&svc->authschemes, "auth-null",
- (rpcsvc_auth_initer_t)
- rpcsvc_auth_null_init);
- if (ret == -1) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to add AUTH_NULL");
- goto err;
- }
-
- ret = 0;
-err:
- return 0;
-}
-
-
-int
-rpcsvc_auth_init_auth (rpcsvc_t *svc, dict_t *options,
- struct rpcsvc_auth_list *authitem)
-{
- int ret = -1;
-
- if ((!svc) || (!options) || (!authitem))
- return -1;
-
- if (!authitem->init) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "No init function defined");
- ret = -1;
- goto err;
- }
-
- authitem->auth = authitem->init (svc, options);
- if (!authitem->auth) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Registration of auth failed:"
- " %s", authitem->name);
- ret = -1;
- goto err;
- }
-
- authitem->enable = 1;
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "Authentication enabled: %s",
- authitem->auth->authname);
-
- ret = 0;
-err:
- return ret;
-}
-
-
-int
-rpcsvc_auth_init_auths (rpcsvc_t *svc, dict_t *options)
-{
- int ret = -1;
- struct rpcsvc_auth_list *auth = NULL;
- struct rpcsvc_auth_list *tmp = NULL;
-
- if (!svc)
- return -1;
-
- if (list_empty (&svc->authschemes)) {
- gf_log (GF_RPCSVC, GF_LOG_WARNING, "No authentication!");
- ret = 0;
- goto err;
- }
-
- /* If auth null and sys are not disabled by the user, we must enable
- * it by default. This is a globally default rule, the user is still
- * allowed to disable the two for particular subvolumes.
- */
- if (!dict_get (options, "rpc-auth.auth-null"))
- ret = dict_set_dynstr (options, "rpc-auth.auth-null", "on");
-
- if (!dict_get (options, "rpc-auth.auth-unix"))
- ret = dict_set_dynstr (options, "rpc-auth.auth-unix", "on");
-
- list_for_each_entry_safe (auth, tmp, &svc->authschemes, authlist) {
- ret = rpcsvc_auth_init_auth (svc, options, auth);
- if (ret == -1)
- goto err;
- }
-
- ret = 0;
-err:
- return ret;
-
-}
-
-int
-rpcsvc_auth_init (rpcsvc_t *svc, dict_t *options)
-{
- int ret = -1;
-
- if ((!svc) || (!options))
- return -1;
-
- ret = rpcsvc_auth_add_initers (svc);
- if (ret == -1) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to add initers");
- goto out;
- }
-
- ret = rpcsvc_auth_init_auths (svc, options);
- if (ret == -1) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to init auth schemes");
- goto out;
- }
-
-out:
- return ret;
-}
-
-
-rpcsvc_auth_t *
-__rpcsvc_auth_get_handler (rpcsvc_request_t *req)
-{
- int ret = -1;
- struct rpcsvc_auth_list *auth = NULL;
- struct rpcsvc_auth_list *tmp = NULL;
- rpcsvc_t *svc = NULL;
-
- if (!req)
- return NULL;
-
- svc = rpcsvc_request_service (req);
- if (list_empty (&svc->authschemes)) {
- gf_log (GF_RPCSVC, GF_LOG_WARNING, "No authentication!");
- ret = 0;
- goto err;
- }
-
- list_for_each_entry_safe (auth, tmp, &svc->authschemes, authlist) {
- if (!auth->enable)
- continue;
- if (auth->auth->authnum == req->cred.flavour)
- goto err;
-
- }
-
- auth = NULL;
-err:
- if (auth)
- return auth->auth;
- else
- return NULL;
-}
-
-rpcsvc_auth_t *
-rpcsvc_auth_get_handler (rpcsvc_request_t *req)
-{
- rpcsvc_auth_t *auth = NULL;
-
- auth = __rpcsvc_auth_get_handler (req);
- if (auth)
- goto ret;
-
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "No auth handler: %d",
- req->cred.flavour);
-
- /* The requested scheme was not available so fall back the to one
- * scheme that will always be present.
- */
- req->cred.flavour = AUTH_NULL;
- req->verf.flavour = AUTH_NULL;
- auth = __rpcsvc_auth_get_handler (req);
-ret:
- return auth;
-}
-
-
-int
-rpcsvc_auth_request_init (rpcsvc_request_t *req)
-{
- int ret = -1;
- rpcsvc_auth_t *auth = NULL;
-
- if (!req)
- return -1;
-
- auth = rpcsvc_auth_get_handler (req);
- if (!auth)
- goto err;
- ret = 0;
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "Auth handler: %s", auth->authname);
- if (!auth->authops->request_init)
- ret = auth->authops->request_init (req, auth->authprivate);
-
-err:
- return ret;
-}
-
-
-int
-rpcsvc_authenticate (rpcsvc_request_t *req)
-{
- int ret = RPCSVC_AUTH_REJECT;
- rpcsvc_auth_t *auth = NULL;
- int minauth = 0;
-
- if (!req)
- return ret;
-
- minauth = rpcsvc_request_prog_minauth (req);
- if (minauth > rpcsvc_request_cred_flavour (req)) {
- gf_log (GF_RPCSVC, GF_LOG_DEBUG, "Auth too weak");
- rpcsvc_request_set_autherr (req, AUTH_TOOWEAK);
- goto err;
- }
-
- auth = rpcsvc_auth_get_handler (req);
- if (!auth) {
- gf_log (GF_RPCSVC, GF_LOG_DEBUG, "No auth handler found");
- goto err;
- }
-
- if (auth->authops->authenticate)
- ret = auth->authops->authenticate (req, auth->authprivate);
-
-err:
- return ret;
-}
-
-
-int
-rpcsvc_auth_array (rpcsvc_t *svc, char *volname, int *autharr, int arrlen)
-{
- int count = 0;
- int gen = RPCSVC_AUTH_REJECT;
- int spec = RPCSVC_AUTH_REJECT;
- int final = RPCSVC_AUTH_REJECT;
- char *srchstr = NULL;
- char *valstr = NULL;
- gf_boolean_t boolval = _gf_false;
- int ret = 0;
-
- struct rpcsvc_auth_list *auth = NULL;
- struct rpcsvc_auth_list *tmp = NULL;
-
- if ((!svc) || (!autharr) || (!volname))
- return -1;
-
- memset (autharr, 0, arrlen * sizeof(int));
- if (list_empty (&svc->authschemes)) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "No authentication!");
- goto err;
- }
-
- list_for_each_entry_safe (auth, tmp, &svc->authschemes, authlist) {
- if (count >= arrlen)
- break;
-
- gen = asprintf (&srchstr, "rpc-auth.%s", auth->name);
- if (gen == -1) {
- count = -1;
- goto err;
- }
-
- gen = RPCSVC_AUTH_REJECT;
- if (dict_get (svc->options, srchstr)) {
- ret = dict_get_str (svc->options, srchstr, &valstr);
- if (ret == 0) {
- ret = gf_string2boolean (valstr, &boolval);
- if (ret == 0) {
- if (boolval == _gf_true)
- gen = RPCSVC_AUTH_ACCEPT;
- } else
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Faile"
- "d to read auth val");
- } else
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Faile"
- "d to read auth val");
- }
-
- FREE (srchstr);
- spec = asprintf (&srchstr, "rpc-auth.%s.%s", auth->name,
- volname);
- if (spec == -1) {
- count = -1;
- goto err;
- }
-
- spec = RPCSVC_AUTH_DONTCARE;
- if (dict_get (svc->options, srchstr)) {
- ret = dict_get_str (svc->options, srchstr, &valstr);
- if (ret == 0) {
- ret = gf_string2boolean (valstr, &boolval);
- if (ret == 0) {
- if (boolval == _gf_true)
- spec = RPCSVC_AUTH_ACCEPT;
- else
- spec = RPCSVC_AUTH_REJECT;
- } else
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Faile"
- "d to read auth val");
- } else
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Faile"
- "d to read auth val");
- }
-
- FREE (srchstr);
- final = rpcsvc_combine_gen_spec_volume_checks (gen, spec);
- if (final == RPCSVC_AUTH_ACCEPT) {
- autharr[count] = auth->auth->authnum;
- ++count;
- }
- }
-
-err:
- return count;
-}
-
-
-gid_t *
-rpcsvc_auth_unix_auxgids (rpcsvc_request_t *req, int *arrlen)
-{
- if ((!req) || (!arrlen))
- return NULL;
-
- if (req->cred.flavour != AUTH_UNIX)
- return NULL;
-
- *arrlen = req->auxgidcount;
- if (*arrlen == 0)
- return NULL;
-
- return &req->auxgids[0];
-}
-
diff --git a/xlators/nfs/lib/src/rpcsvc.c b/xlators/nfs/lib/src/rpcsvc.c
deleted file mode 100644
index 47510ad8a..000000000
--- a/xlators/nfs/lib/src/rpcsvc.c
+++ /dev/null
@@ -1,2743 +0,0 @@
-/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
- This file is part of GlusterFS.
-
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _CONFIG_H
-#define _CONFIG_H
-#include "config.h"
-#endif
-
-#include "rpcsvc.h"
-#include "rpc-socket.h"
-#include "dict.h"
-#include "logging.h"
-#include "byte-order.h"
-#include "common-utils.h"
-#include "compat-errno.h"
-#include "list.h"
-#include "xdr-rpc.h"
-#include "iobuf.h"
-#include "globals.h"
-
-#include <errno.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <rpc/rpc.h>
-#include <rpc/pmap_clnt.h>
-#include <arpa/inet.h>
-#include <rpc/xdr.h>
-#include <fnmatch.h>
-#include <stdarg.h>
-#include <stdio.h>
-
-
-#define rpcsvc_alloc_request(con, request) \
- do { \
- request = (rpcsvc_request_t *) mem_get ((con)->rxpool); \
- memset (request, 0, sizeof (rpcsvc_request_t)); \
- } while (0) \
-
-/* The generic event handler for every stage */
-void *
-rpcsvc_stage_proc (void *arg)
-{
- rpcsvc_stage_t *stg = (rpcsvc_stage_t *)arg;
-
- if (!stg)
- return NULL;
-
- event_dispatch (stg->eventpool);
- return NULL;
-}
-
-
-rpcsvc_stage_t *
-rpcsvc_stage_init (rpcsvc_t *svc)
-{
- rpcsvc_stage_t *stg = NULL;
- int ret = -1;
- size_t stacksize = RPCSVC_THREAD_STACK_SIZE;
- pthread_attr_t stgattr;
- unsigned int eventpoolsize = 0;
-
- if (!svc)
- return NULL;
-
- stg = CALLOC (1, sizeof(*stg));
- if (!stg)
- return NULL;
-
- eventpoolsize = svc->memfactor * RPCSVC_EVENTPOOL_SIZE_MULT;
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "event pool size: %d", eventpoolsize);
- stg->eventpool = event_pool_new (eventpoolsize);
- if (!stg->eventpool)
- goto free_stg;
-
- pthread_attr_init (&stgattr);
- ret = pthread_attr_setstacksize (&stgattr, stacksize);
- if (ret == EINVAL)
- gf_log (GF_RPCSVC, GF_LOG_WARNING,
- "Using default thread stack size");
-
- ret = pthread_create (&stg->tid, &stgattr, rpcsvc_stage_proc,
- (void *)stg);
- if (ret != 0) {
- ret = -1;
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Stage creation failed");
- goto free_stg;
- }
-
- stg->svc = svc;
- ret = 0;
-free_stg:
- if (ret == -1) {
- FREE (stg);
- stg = NULL;
- }
-
- return stg;
-}
-
-
-int
-rpcsvc_init_options (rpcsvc_t *svc, dict_t *options)
-{
- svc->memfactor = RPCSVC_DEFAULT_MEMFACTOR;
- return 0;
-}
-
-
-/* The global RPC service initializer.
- * Starts up the stages and then waits for RPC program registrations
- * to come in.
- */
-rpcsvc_t *
-rpcsvc_init (glusterfs_ctx_t *ctx, dict_t *options)
-{
- rpcsvc_t *svc = NULL;
- int ret = -1;
-
- if ((!ctx) || (!options))
- return NULL;
-
- svc = CALLOC (1, sizeof (*svc));
- if (!svc)
- return NULL;
-
- pthread_mutex_init (&svc->rpclock, NULL);
- INIT_LIST_HEAD (&svc->stages);
- INIT_LIST_HEAD (&svc->authschemes);
-
- ret = rpcsvc_init_options (svc, options);
- if (ret == -1) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to init options");
- goto free_svc;
- }
-
- ret = rpcsvc_auth_init (svc, options);
- if (ret == -1) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to init "
- "authentication");
- goto free_svc;
- }
-
- ret = -1;
- svc->defaultstage = rpcsvc_stage_init (svc);
- if (!svc->defaultstage) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR,"RPC service init failed.");
- goto free_svc;
- }
- svc->options = options;
- svc->ctx = ctx;
- gf_log (GF_RPCSVC, GF_LOG_DEBUG, "RPC service inited.");
-
- ret = 0;
-free_svc:
- if (ret == -1) {
- FREE (svc);
- svc = NULL;
- }
-
- return svc;
-}
-
-
-/* Once multi-threaded support is complete, we'll be able to round-robin
- * the various incoming connections over the many available stages. This
- * function selects one from among all the stages.
- */
-rpcsvc_stage_t *
-rpcsvc_select_stage (rpcsvc_t *rpcservice)
-{
- if (!rpcservice)
- return NULL;
-
- return rpcservice->defaultstage;
-}
-
-
-int
-rpcsvc_conn_peer_check_search (dict_t *options, char *pattern, char *clstr)
-{
- int ret = -1;
- char *addrtok = NULL;
- char *addrstr = NULL;
- char *svptr = NULL;
-
- if ((!options) || (!clstr))
- return -1;
-
- if (!dict_get (options, pattern))
- return -1;
-
- ret = dict_get_str (options, pattern, &addrstr);
- if (ret < 0) {
- ret = -1;
- goto err;
- }
-
- if (!addrstr) {
- ret = -1;
- goto err;
- }
-
- addrtok = strtok_r (addrstr, ",", &svptr);
- while (addrtok) {
-
- ret = fnmatch (addrtok, clstr, FNM_CASEFOLD);
- if (ret == 0)
- goto err;
-
- addrtok = strtok_r (NULL, ",", &svptr);
- }
-
- ret = -1;
-err:
-
- return ret;
-}
-
-
-int
-rpcsvc_conn_peer_check_allow (dict_t *options, char *volname, char *clstr)
-{
- int ret = RPCSVC_AUTH_DONTCARE;
- char *srchstr = NULL;
- char globalrule[] = "rpc-auth.addr.allow";
-
- if ((!options) || (!clstr))
- return ret;
-
- /* If volname is NULL, then we're searching for the general rule to
- * determine the current address in clstr is allowed or not for all
- * subvolumes.
- */
- if (volname) {
- ret = asprintf (&srchstr, "rpc-auth.addr.%s.allow", volname);
- if (ret == -1) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "asprintf failed");
- ret = RPCSVC_AUTH_DONTCARE;
- goto out;
- }
- } else
- srchstr = globalrule;
-
- ret = rpcsvc_conn_peer_check_search (options, srchstr, clstr);
- if (volname)
- FREE (srchstr);
-
- if (ret == 0)
- ret = RPCSVC_AUTH_ACCEPT;
- else
- ret = RPCSVC_AUTH_DONTCARE;
-out:
- return ret;
-}
-
-int
-rpcsvc_conn_peer_check_reject (dict_t *options, char *volname, char *clstr)
-{
- int ret = RPCSVC_AUTH_DONTCARE;
- char *srchstr = NULL;
- char generalrule[] = "rpc-auth.addr.reject";
-
- if ((!options) || (!clstr))
- return ret;
-
- if (volname) {
- ret = asprintf (&srchstr, "rpc-auth.addr.%s.reject", volname);
- if (ret == -1) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "asprintf failed");
- ret = RPCSVC_AUTH_REJECT;
- goto out;
- }
- } else
- srchstr = generalrule;
-
- ret = rpcsvc_conn_peer_check_search (options, srchstr, clstr);
- if (volname)
- FREE (srchstr);
-
- if (ret == 0)
- ret = RPCSVC_AUTH_REJECT;
- else
- ret = RPCSVC_AUTH_DONTCARE;
-out:
- return ret;
-}
-
-
-/* This function tests the results of the allow rule and the reject rule to
- * combine them into a single result that can be used to determine if the
- * connection should be allowed to proceed.
- * Heres the test matrix we need to follow in this function.
- *
- * A - Allow, the result of the allow test. Never returns R.
- * R - Reject, result of the reject test. Never returns A.
- * Both can return D or dont care if no rule was given.
- *
- * | @allow | @reject | Result |
- * | A | R | R |
- * | D | D | D |
- * | A | D | A |
- * | D | R | R |
- */
-int
-rpcsvc_combine_allow_reject_volume_check (int allow, int reject)
-{
- int final = RPCSVC_AUTH_REJECT;
-
- /* If allowed rule allows but reject rule rejects, we stay cautious
- * and reject. */
- if ((allow == RPCSVC_AUTH_ACCEPT) && (reject == RPCSVC_AUTH_REJECT))
- final = RPCSVC_AUTH_REJECT;
- /* if both are dont care, that is user did not specify for either allow
- * or reject, we leave it up to the general rule to apply, in the hope
- * that there is one.
- */
- else if ((allow == RPCSVC_AUTH_DONTCARE) &&
- (reject == RPCSVC_AUTH_DONTCARE))
- final = RPCSVC_AUTH_DONTCARE;
- /* If one is dont care, the other one applies. */
- else if ((allow == RPCSVC_AUTH_ACCEPT) &&
- (reject == RPCSVC_AUTH_DONTCARE))
- final = RPCSVC_AUTH_ACCEPT;
- else if ((allow == RPCSVC_AUTH_DONTCARE) &&
- (reject == RPCSVC_AUTH_REJECT))
- final = RPCSVC_AUTH_REJECT;
-
- return final;
-}
-
-
-/* Combines the result of the general rule test against, the specific rule
- * to determine final permission for the client's address.
- *
- * | @gen | @spec | Result |
- * | A | A | A |
- * | A | R | R |
- * | A | D | A |
- * | D | A | A |
- * | D | R | R |
- * | D | D | D |
- * | R | A | A |
- * | R | D | R |
- * | R | R | R |
- */
-int
-rpcsvc_combine_gen_spec_addr_checks (int gen, int spec)
-{
- int final = RPCSVC_AUTH_REJECT;
-
- if ((gen == RPCSVC_AUTH_ACCEPT) && (spec == RPCSVC_AUTH_ACCEPT))
- final = RPCSVC_AUTH_ACCEPT;
- else if ((gen == RPCSVC_AUTH_ACCEPT) && (spec == RPCSVC_AUTH_REJECT))
- final = RPCSVC_AUTH_REJECT;
- else if ((gen == RPCSVC_AUTH_ACCEPT) && (spec == RPCSVC_AUTH_DONTCARE))
- final = RPCSVC_AUTH_ACCEPT;
- else if ((gen == RPCSVC_AUTH_DONTCARE) && (spec == RPCSVC_AUTH_ACCEPT))
- final = RPCSVC_AUTH_ACCEPT;
- else if ((gen == RPCSVC_AUTH_DONTCARE) && (spec == RPCSVC_AUTH_REJECT))
- final = RPCSVC_AUTH_REJECT;
- else if ((gen == RPCSVC_AUTH_DONTCARE) && (spec== RPCSVC_AUTH_DONTCARE))
- final = RPCSVC_AUTH_DONTCARE;
- else if ((gen == RPCSVC_AUTH_REJECT) && (spec == RPCSVC_AUTH_ACCEPT))
- final = RPCSVC_AUTH_ACCEPT;
- else if ((gen == RPCSVC_AUTH_REJECT) && (spec == RPCSVC_AUTH_DONTCARE))
- final = RPCSVC_AUTH_REJECT;
- else if ((gen == RPCSVC_AUTH_REJECT) && (spec == RPCSVC_AUTH_REJECT))
- final = RPCSVC_AUTH_REJECT;
-
- return final;
-}
-
-
-
-/* Combines the result of the general rule test against, the specific rule
- * to determine final test for the connection coming in for a given volume.
- *
- * | @gen | @spec | Result |
- * | A | A | A |
- * | A | R | R |
- * | A | D | A |
- * | D | A | A |
- * | D | R | R |
- * | D | D | R |, special case, we intentionally disallow this.
- * | R | A | A |
- * | R | D | R |
- * | R | R | R |
- */
-int
-rpcsvc_combine_gen_spec_volume_checks (int gen, int spec)
-{
- int final = RPCSVC_AUTH_REJECT;
-
- if ((gen == RPCSVC_AUTH_ACCEPT) && (spec == RPCSVC_AUTH_ACCEPT))
- final = RPCSVC_AUTH_ACCEPT;
- else if ((gen == RPCSVC_AUTH_ACCEPT) && (spec == RPCSVC_AUTH_REJECT))
- final = RPCSVC_AUTH_REJECT;
- else if ((gen == RPCSVC_AUTH_ACCEPT) && (spec == RPCSVC_AUTH_DONTCARE))
- final = RPCSVC_AUTH_ACCEPT;
- else if ((gen == RPCSVC_AUTH_DONTCARE) && (spec == RPCSVC_AUTH_ACCEPT))
- final = RPCSVC_AUTH_ACCEPT;
- else if ((gen == RPCSVC_AUTH_DONTCARE) && (spec == RPCSVC_AUTH_REJECT))
- final = RPCSVC_AUTH_REJECT;
- /* On no rule, we reject. */
- else if ((gen == RPCSVC_AUTH_DONTCARE) && (spec== RPCSVC_AUTH_DONTCARE))
- final = RPCSVC_AUTH_REJECT;
- else if ((gen == RPCSVC_AUTH_REJECT) && (spec == RPCSVC_AUTH_ACCEPT))
- final = RPCSVC_AUTH_ACCEPT;
- else if ((gen == RPCSVC_AUTH_REJECT) && (spec == RPCSVC_AUTH_DONTCARE))
- final = RPCSVC_AUTH_REJECT;
- else if ((gen == RPCSVC_AUTH_REJECT) && (spec == RPCSVC_AUTH_REJECT))
- final = RPCSVC_AUTH_REJECT;
-
- return final;
-}
-
-
-int
-rpcsvc_conn_peer_check_name (dict_t *options, char *volname,
- rpcsvc_conn_t *conn)
-{
- int ret = RPCSVC_AUTH_REJECT;
- int aret = RPCSVC_AUTH_REJECT;
- int rjret = RPCSVC_AUTH_REJECT;
- char clstr[RPCSVC_PEER_STRLEN];
-
- if (!conn)
- return ret;
-
- ret = rpcsvc_conn_peername (conn, clstr, RPCSVC_PEER_STRLEN);
- if (ret != 0) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to get remote addr: "
- "%s", gai_strerror (ret));
- ret = RPCSVC_AUTH_REJECT;
- goto err;
- }
-
- aret = rpcsvc_conn_peer_check_allow (options, volname, clstr);
- rjret = rpcsvc_conn_peer_check_reject (options, volname, clstr);
-
- ret = rpcsvc_combine_allow_reject_volume_check (aret, rjret);
-
-err:
- return ret;
-}
-
-
-int
-rpcsvc_conn_peer_check_addr (dict_t *options, char *volname,rpcsvc_conn_t *conn)
-{
- int ret = RPCSVC_AUTH_REJECT;
- int aret = RPCSVC_AUTH_DONTCARE;
- int rjret = RPCSVC_AUTH_REJECT;
- char clstr[RPCSVC_PEER_STRLEN];
-
- if (!conn)
- return ret;
-
- ret = rpcsvc_conn_peeraddr (conn, clstr, RPCSVC_PEER_STRLEN, NULL, 0);
- if (ret != 0) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to get remote addr: "
- "%s", gai_strerror (ret));
- ret = RPCSVC_AUTH_REJECT;
- goto err;
- }
-
- aret = rpcsvc_conn_peer_check_allow (options, volname, clstr);
- rjret = rpcsvc_conn_peer_check_reject (options, volname, clstr);
-
- ret = rpcsvc_combine_allow_reject_volume_check (aret, rjret);
-err:
- return ret;
-}
-
-
-int
-rpcsvc_conn_check_volume_specific (dict_t *options, char *volname,
- rpcsvc_conn_t *conn)
-{
- int namechk = RPCSVC_AUTH_REJECT;
- int addrchk = RPCSVC_AUTH_REJECT;
- gf_boolean_t namelookup = _gf_true;
- char *namestr = NULL;
- int ret = 0;
-
- if ((!options) || (!volname) || (!conn))
- return RPCSVC_AUTH_REJECT;
-
- /* Enabled by default */
- if ((dict_get (options, "rpc-auth.addr.namelookup"))) {
- ret = dict_get_str (options, "rpc-auth.addr.namelookup"
- , &namestr);
- if (ret == 0)
- ret = gf_string2boolean (namestr, &namelookup);
- }
-
- /* We need two separate checks because the rules with addresses in them
- * can be network addresses which can be general and names can be
- * specific which will over-ride the network address rules.
- */
- if (namelookup)
- namechk = rpcsvc_conn_peer_check_name (options, volname, conn);
- addrchk = rpcsvc_conn_peer_check_addr (options, volname, conn);
-
- if (namelookup)
- ret = rpcsvc_combine_gen_spec_addr_checks (addrchk, namechk);
- else
- ret = addrchk;
-
- return ret;
-}
-
-
-int
-rpcsvc_conn_check_volume_general (dict_t *options, rpcsvc_conn_t *conn)
-{
- int addrchk = RPCSVC_AUTH_REJECT;
- int namechk = RPCSVC_AUTH_REJECT;
- gf_boolean_t namelookup = _gf_true;
- char *namestr = NULL;
- int ret = 0;
-
- if ((!options) || (!conn))
- return RPCSVC_AUTH_REJECT;
-
- /* Enabled by default */
- if ((dict_get (options, "rpc-auth.addr.namelookup"))) {
- ret = dict_get_str (options, "rpc-auth.addr.namelookup"
- , &namestr);
- if (ret == 0)
- ret = gf_string2boolean (namestr, &namelookup);
- }
-
- /* We need two separate checks because the rules with addresses in them
- * can be network addresses which can be general and names can be
- * specific which will over-ride the network address rules.
- */
- if (namelookup)
- namechk = rpcsvc_conn_peer_check_name (options, NULL, conn);
- addrchk = rpcsvc_conn_peer_check_addr (options, NULL, conn);
-
- if (namelookup)
- ret = rpcsvc_combine_gen_spec_addr_checks (addrchk, namechk);
- else
- ret = addrchk;
-
- return ret;
-}
-
-int
-rpcsvc_conn_peer_check (dict_t *options, char *volname, rpcsvc_conn_t *conn)
-{
- int general_chk = RPCSVC_AUTH_REJECT;
- int specific_chk = RPCSVC_AUTH_REJECT;
-
- if ((!options) || (!volname) || (!conn))
- return RPCSVC_AUTH_REJECT;
-
- general_chk = rpcsvc_conn_check_volume_general (options, conn);
- specific_chk = rpcsvc_conn_check_volume_specific (options, volname,
- conn);
-
- return rpcsvc_combine_gen_spec_volume_checks (general_chk,specific_chk);
-}
-
-
-char *
-rpcsvc_volume_allowed (dict_t *options, char *volname)
-{
- char globalrule[] = "rpc-auth.addr.allow";
- char *srchstr = NULL;
- char *addrstr = NULL;
- int ret = -1;
-
- if ((!options) || (!volname))
- return NULL;
-
- ret = asprintf (&srchstr, "rpc-auth.addr.%s.allow", volname);
- if (ret == -1) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "asprintf failed");
- goto out;
- }
-
- if (!dict_get (options, srchstr)) {
- FREE (srchstr);
- srchstr = globalrule;
- ret = dict_get_str (options, srchstr, &addrstr);
- } else
- ret = dict_get_str (options, srchstr, &addrstr);
-
-out:
- return addrstr;
-}
-
-
-/* Initialize the core of a connection */
-rpcsvc_conn_t *
-rpcsvc_conn_init (rpcsvc_t *svc, rpcsvc_program_t *prog, int sockfd)
-{
- rpcsvc_conn_t *conn = NULL;
- int ret = -1;
- unsigned int poolcount = 0;
-
- conn = CALLOC (1, sizeof(*conn));
- if (!conn) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "memory allocation failed");
- return NULL;
- }
-
- conn->sockfd = sockfd;
- conn->program = (void *)prog;
- INIT_LIST_HEAD (&conn->txbufs);
- poolcount = RPCSVC_POOLCOUNT_MULT * svc->memfactor;
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "tx pool: %d", poolcount);
- conn->txpool = mem_pool_new (rpcsvc_txbuf_t, poolcount);
- if (!conn->txpool) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "mem pool allocation failed");
- goto free_conn;
- }
-
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "rx pool: %d", poolcount);
- conn->rxpool = mem_pool_new (rpcsvc_request_t, poolcount);
- if (!conn->rxpool) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "mem pool allocation failed");
- goto free_txp;
- }
-
- /* Cannot consider a connection connected unless the user of this
- * connection decides it is ready to use. It is possible that we have
- * to free this connection soon after. That free will not happpen
- * unless the state is disconnected.
- */
- conn->connstate = RPCSVC_CONNSTATE_DISCONNECTED;
- pthread_mutex_init (&conn->connlock, NULL);
- conn->connref = 0;
- gf_log (GF_RPCSVC, GF_LOG_DEBUG, "New connection inited: sockfd: %d",
- sockfd);
-
- ret = 0;
-free_txp:
- if (ret == -1)
- mem_pool_destroy (conn->txpool);
-
-free_conn:
- if (ret == -1) {
- FREE (conn);
- conn = NULL;
- }
-
- return conn;
-}
-
-
-void
-rpcsvc_conn_destroy (rpcsvc_conn_t *conn)
-{
- mem_pool_destroy (conn->txpool);
- mem_pool_destroy (conn->rxpool);
-
- if (conn->program->conn_destroy)
- conn->program->conn_destroy (conn->program->private, conn);
-
- /* Need to destory record state, txlists etc. */
- FREE (conn);
- gf_log (GF_RPCSVC, GF_LOG_DEBUG, "Connection destroyed");
-}
-
-
-int
-__rpcsvc_conn_unref (rpcsvc_conn_t *conn)
-{
- --conn->connref;
- return conn->connref;
-}
-
-
-void
-__rpcsvc_conn_deinit (rpcsvc_conn_t *conn)
-{
- if (!conn)
- return;
-
- if ((conn->stage) && (conn->stage->eventpool)) {
- event_unregister (conn->stage->eventpool, conn->sockfd,
- conn->eventidx);
- }
-
- if (rpcsvc_conn_check_active (conn)) {
- gf_log (GF_RPCSVC, GF_LOG_DEBUG, "Connection de-activated:"
- " sockfd: %d", conn->sockfd);
- conn->connstate = RPCSVC_CONNSTATE_DISCONNECTED;
- }
-
- if (conn->sockfd != -1) {
- close (conn->sockfd);
- conn->sockfd = -1;
- }
-}
-
-
-void
-rpcsvc_conn_deinit (rpcsvc_conn_t *conn)
-{
- int ref = 0;
-
- if (!conn)
- return;
-
- pthread_mutex_lock (&conn->connlock);
- {
- __rpcsvc_conn_deinit (conn);
- ref = __rpcsvc_conn_unref (conn);
- }
- pthread_mutex_unlock (&conn->connlock);
-
- if (ref == 0)
- rpcsvc_conn_destroy (conn);
-
- return;
-}
-
-
-void
-rpcsvc_conn_unref (rpcsvc_conn_t *conn)
-{
- int ref = 0;
- if (!conn)
- return;
-
- pthread_mutex_lock (&conn->connlock);
- {
- ref = __rpcsvc_conn_unref (conn);
- }
- pthread_mutex_unlock (&conn->connlock);
-
- if (ref == 0)
- rpcsvc_conn_destroy (conn);
-}
-
-
-int
-rpcsvc_conn_active (rpcsvc_conn_t *conn)
-{
- int status = 0;
-
- if (!conn)
- return 0;
-
- pthread_mutex_lock (&conn->connlock);
- {
- status = rpcsvc_conn_check_active (conn);
- }
- pthread_mutex_unlock (&conn->connlock);
-
- return status;
-}
-
-
-
-void
-rpcsvc_conn_ref (rpcsvc_conn_t *conn)
-{
- if (!conn)
- return;
-
- pthread_mutex_lock (&conn->connlock);
- {
- ++conn->connref;
- }
- pthread_mutex_unlock (&conn->connlock);
-
- return;
-}
-
-
-void
-rpcsvc_conn_state_init (rpcsvc_conn_t *conn)
-{
- if (!conn)
- return;
-
- ++conn->connref;
- conn->connstate = RPCSVC_CONNSTATE_CONNECTED;
-}
-
-/* Builds a rpcsvc_conn_t with the aim of listening on it.
- */
-rpcsvc_conn_t *
-rpcsvc_conn_listen_init (rpcsvc_t *svc, rpcsvc_program_t *newprog)
-{
- rpcsvc_conn_t *conn = NULL;
- int sock = -1;
-
- if (!newprog)
- return NULL;
-
- sock = rpcsvc_socket_listen (newprog->progaddrfamily, newprog->proghost,
- newprog->progport);
- if (sock == -1)
- goto err;
-
- conn = rpcsvc_conn_init (svc, newprog, sock);
- if (!conn)
- goto sock_close_err;
-
- rpcsvc_conn_state_init (conn);
-sock_close_err:
- if (!conn)
- close (sock);
-
-err:
- return conn;
-}
-
-void
-rpcsvc_record_init (rpcsvc_record_state_t *rs, struct iobuf_pool *pool)
-{
- if (!rs)
- return;
-
- rs->state = RPCSVC_READ_FRAGHDR;
- rs->vecstate = 0;
- rs->remainingfraghdr = RPCSVC_FRAGHDR_SIZE;
- rs->remainingfrag = 0;
- rs->fragsize = 0;
- rs->recordsize = 0;
- rs->islastfrag = 0;
-
- /* If the rs preserves a ref to the iob used by the previous request,
- * we must unref it here to prevent memory leak.
- * If program actor wanted to keep that memory around, it should've
- * refd it on entry into the actor.
- */
- if (rs->activeiob)
- iobuf_unref (rs->activeiob);
-
- if (rs->vectoriob) {
- iobuf_unref (rs->vectoriob);
- rs->vectoriob = NULL;
- }
-
- rs->activeiob = iobuf_get (pool);
- rs->fragcurrent = iobuf_ptr (rs->activeiob);
-
- memset (rs->fragheader, 0, RPCSVC_FRAGHDR_SIZE);
- rs->hdrcurrent = &rs->fragheader[0];
-
-}
-
-
-int
-rpcsvc_conn_privport_check (rpcsvc_t *svc, char *volname, rpcsvc_conn_t *conn)
-{
- struct sockaddr_in sa;
- int ret = RPCSVC_AUTH_REJECT;
- socklen_t sasize = sizeof (sa);
- char *srchstr = NULL;
- char *valstr = NULL;
- int globalinsecure = RPCSVC_AUTH_REJECT;
- int exportinsecure = RPCSVC_AUTH_DONTCARE;
- uint16_t port = 0;
- gf_boolean_t insecure = _gf_false;
-
- if ((!svc) || (!volname) || (!conn))
- return ret;
-
- ret = rpcsvc_conn_peeraddr (conn, NULL, 0, (struct sockaddr *)&sa,
- sasize);
- if (ret != 0) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to get peer addr: %s",
- gai_strerror (ret));
- ret = RPCSVC_AUTH_REJECT;
- goto err;
- }
-
- port = ntohs (sa.sin_port);
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "Client port: %d", (int)port);
- /* If the port is already a privileged one, dont bother with checking
- * options.
- */
- if (port <= 1024) {
- ret = RPCSVC_AUTH_ACCEPT;
- goto err;
- }
-
- /* Disabled by default */
- if ((dict_get (svc->options, "rpc-auth.ports.insecure"))) {
- ret = dict_get_str (svc->options, "rpc-auth.ports.insecure"
- , &srchstr);
- if (ret == 0) {
- ret = gf_string2boolean (srchstr, &insecure);
- if (ret == 0) {
- if (insecure == _gf_true)
- globalinsecure = RPCSVC_AUTH_ACCEPT;
- } else
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to"
- " read rpc-auth.ports.insecure value");
- } else
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to"
- " read rpc-auth.ports.insecure value");
- }
-
- /* Disabled by default */
- ret = asprintf (&srchstr, "rpc-auth.ports.%s.insecure", volname);
- if (ret == -1) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "asprintf failed");
- ret = RPCSVC_AUTH_REJECT;
- goto err;
- }
-
- if (dict_get (svc->options, srchstr)) {
- ret = dict_get_str (svc->options, srchstr, &valstr);
- if (ret == 0) {
- ret = gf_string2boolean (srchstr, &insecure);
- if (ret == 0) {
- if (insecure == _gf_true)
- exportinsecure = RPCSVC_AUTH_ACCEPT;
- else
- exportinsecure = RPCSVC_AUTH_REJECT;
- } else
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to"
- " read rpc-auth.ports.insecure value");
- } else
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to"
- " read rpc-auth.ports.insecure value");
- }
-
- ret = rpcsvc_combine_gen_spec_volume_checks (globalinsecure,
- exportinsecure);
- if (ret == RPCSVC_AUTH_ACCEPT)
- gf_log (GF_RPCSVC, GF_LOG_DEBUG, "Unprivileged port allowed");
- else
- gf_log (GF_RPCSVC, GF_LOG_DEBUG, "Unprivileged port not"
- " allowed");
-
-err:
- return ret;
-}
-
-/* Inits a rpcsvc_conn_t after accepting the connection.
- */
-rpcsvc_conn_t *
-rpcsvc_conn_accept_init (rpcsvc_t *svc, int listenfd,
- rpcsvc_program_t *destprog)
-{
- rpcsvc_conn_t *newconn = NULL;
- int sock = -1;
- int ret = -1;
-
- sock = rpcsvc_socket_accept (listenfd);
- if (sock == -1)
- goto err;
-
- newconn = rpcsvc_conn_init (svc, destprog, sock);
- if (!newconn) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to init conn object");
- ret = -1;
- goto err;
- }
-
- rpcsvc_record_init (&newconn->rstate, svc->ctx->iobuf_pool);
- rpcsvc_conn_state_init (newconn);
- if (destprog->conn_init)
- destprog->conn_init (destprog->private, newconn);
- ret = 0;
-
-err:
- if (ret == -1)
- close (sock);
-
- return newconn;
-}
-
-
-/* Once the connection has been created, we need to associate it with
- * a stage so that the selected stage will handle the event on this connection.
- * This function also allows the caller to decide which handler should
- * be executed in the context of the stage, and also which specific events
- * should be handed to the handler when running in this particular stage.
- */
-int
-rpcsvc_stage_conn_associate (rpcsvc_stage_t *stg, rpcsvc_conn_t *conn,
- event_handler_t handler, void *data)
-{
- int ret = -1;
-
- if ((!stg) || (!conn))
- return -1;
-
- conn->stage = stg;
- conn->eventidx = event_register (stg->eventpool, conn->sockfd, handler,
- data, 1, 0);
- if (conn->eventidx == -1)
- goto err;
-
- ret = 0;
-err:
- return ret;
-}
-
-
-/* Depending on the state we're in, return the size of the next read request. */
-size_t
-rpcsvc_record_read_size (rpcsvc_record_state_t *rs)
-{
- size_t toread = -1;
-
- if (!rs)
- return -1;
-
- if (rpcsvc_record_readfraghdr (rs))
- toread = rs->remainingfraghdr;
- else if (rpcsvc_record_readfrag (rs))
- toread = rs->remainingfrag;
- else
- toread = RPCSVC_CONN_READ;
-
- return toread;
-}
-
-
-uint32_t
-rpcsvc_record_extract_fraghdr (char *fraghdr)
-{
- uint32_t hdr = 0;
- if (!fraghdr)
- return 0;
-
- memcpy ((void *)&hdr, fraghdr, sizeof (hdr));
-
- hdr = ntohl (hdr);
- return hdr;
-}
-
-
-ssize_t
-rpcsvc_record_read_complete_fraghdr (rpcsvc_record_state_t *rs,ssize_t dataread)
-{
- uint32_t remhdr = 0;
- char *fraghdrstart = NULL;
- uint32_t fraghdr = 0;
-
- fraghdrstart = &rs->fragheader[0];
- remhdr = rs->remainingfraghdr;
- fraghdr = rpcsvc_record_extract_fraghdr (fraghdrstart);
- rs->fragsize = RPCSVC_FRAGSIZE (fraghdr);
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "Received fragment size: %d",
- rs->fragsize);
- if (rpcsvc_record_vectored (rs)) {
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "Vectored RPC header,"
- " remaining: %d", RPCSVC_BARERPC_MSGSZ);
- rs->remainingfrag = RPCSVC_BARERPC_MSGSZ;
- } else {
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "Regular RPC header,"
- " remaining: %d", rs->fragsize);
- rs->remainingfrag = rs->fragsize;
- }
-
- rs->state = RPCSVC_READ_FRAG;
- dataread -= remhdr;
- rs->remainingfraghdr -= remhdr;
- rs->islastfrag = RPCSVC_LASTFRAG (fraghdr);
-
- return dataread;
-}
-
-
-ssize_t
-rpcsvc_record_read_partial_fraghdr (rpcsvc_record_state_t *rs, ssize_t dataread)
-{
-
- /* In case we got less than even the remaining header size,
- * we need to consume it all and wait for remaining frag hdr
- * bytes to come in.
- */
- rs->remainingfraghdr -= dataread;
- rpcsvc_record_update_currenthdr (rs, dataread);
- dataread = 0;
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "Fragment header remaining: %d",
- rs->remainingfraghdr);
-
- return dataread;
-}
-
-
-ssize_t
-rpcsvc_record_update_fraghdr (rpcsvc_record_state_t *rs, ssize_t dataread)
-{
- if ((!rs) || (dataread <= 0))
- return -1;
-
- /* Why are we even here, we're not supposed to be in the fragment
- * header processing state.
- */
- if (!rpcsvc_record_readfraghdr(rs)) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "record state inconsistent"
- ": request to update frag header when state is not"
- "RPCSVC_READ_FRAGHDR");
- return -1;
- }
-
- /* Again, if header has been read then the state member above should've
- * been different, this is crazy. We should not be here.
- */
- if (rs->remainingfraghdr == 0) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "record state inconsistent"
- ": request to update frag header when frag header"
- "remaining is 0.");
- return -1;
- }
-
- /* We've definitely got the full header now and may be even more. */
- if (dataread >= rs->remainingfraghdr)
- dataread = rpcsvc_record_read_complete_fraghdr (rs, dataread);
- else
- dataread = rpcsvc_record_read_partial_fraghdr (rs, dataread);
-
- return dataread;
-}
-
-ssize_t
-rpcsvc_record_read_complete_frag (rpcsvc_record_state_t *rs, ssize_t dataread)
-{
- uint32_t remfrag;
-
- /* Since the frag is now complete, change the state to the next
- * one, i.e. to read the header of the next fragment.
- */
- remfrag = rs->remainingfrag;
- rs->state = RPCSVC_READ_FRAGHDR;
- dataread -= remfrag;
-
- /* This will be 0 now. */
- rs->remainingfrag -= remfrag;
-
- /* Now that the fragment is complete, we must update the
- * record size. Recall that fragsize was got from the frag
- * header.
- */
- rs->recordsize += rs->fragsize;
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "Fragment remaining: %d",
- rs->remainingfrag);
-
- return dataread;
-}
-
-
-ssize_t
-rpcsvc_record_read_partial_frag (rpcsvc_record_state_t *rs, ssize_t dataread)
-{
- /* Just take whatever has come through the current network buffer. */
- rs->remainingfrag -= dataread;
-
- rpcsvc_record_update_currentfrag (rs, dataread);
- /* Since we know we're consuming the whole buffer from dataread
- * simply setting to 0 zero is fine.
- */
- dataread = 0;
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "Fragment remaining: %d",
- rs->remainingfrag);
- return dataread;
-}
-
-
-ssize_t
-rpcsvc_record_update_frag (rpcsvc_record_state_t *rs, ssize_t dataread)
-{
- if ((!rs) || (dataread <= 0))
- return -1;
-
- if (!rpcsvc_record_readfrag (rs)) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "record state inconsistent"
- ": request to update fragment when record state is not"
- "RPCSVC_READ_FRAG.");
- return -1;
- }
-
- if (rs->remainingfrag == 0) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "record state inconsistent"
- ": request to update fragment when there is no fragment"
- " data remaining to be read.");
- return -1;
- }
-
- /* We've read in more data than the current fragment requires. */
- if (dataread >= rs->remainingfrag)
- dataread = rpcsvc_record_read_complete_frag (rs, dataread);
- else
- dataread = rpcsvc_record_read_partial_frag (rs, dataread);
-
- return dataread;
-}
-
-
-/* This needs to change to returning errors, since
- * we need to return RPC specific error messages when some
- * of the pointers below are NULL.
- */
-rpcsvc_actor_t *
-rpcsvc_program_actor (rpcsvc_conn_t *conn, rpcsvc_request_t *req)
-{
- rpcsvc_program_t *program = NULL;
- int err = SYSTEM_ERR;
- rpcsvc_actor_t *actor = NULL;
-
- if ((!conn) || (!req))
- goto err;
-
- program = (rpcsvc_program_t *)conn->program;
- if (!program)
- goto err;
-
- if (req->prognum != program->prognum) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "RPC program not available");
- err = PROG_UNAVAIL;
- goto err;
- }
-
- if (!program->actors) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "RPC System error");
- err = SYSTEM_ERR;
- goto err;
- }
-
- if (req->progver != program->progver) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "RPC program version not"
- " available");
- err = PROG_MISMATCH;
- goto err;
- }
-
- if ((req->procnum < 0) || (req->procnum >= program->numactors)) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "RPC Program procedure not"
- " available");
- err = PROC_UNAVAIL;
- goto err;
- }
-
- actor = &program->actors[req->procnum];
- if (!actor->actor) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "RPC Program procedure not"
- " available");
- err = PROC_UNAVAIL;
- actor = NULL;
- goto err;
- }
-
- err = SUCCESS;
- gf_log (GF_RPCSVC, GF_LOG_DEBUG, "Actor found: %s - %s",
- program->progname, actor->procname);
-err:
- if (req)
- req->rpc_err = err;
-
- return actor;
-}
-
-
-rpcsvc_txbuf_t *
-rpcsvc_init_txbuf (rpcsvc_conn_t *conn, struct iovec msg, struct iobuf *iob,
- struct iobref *iobref, int txflags)
-{
- rpcsvc_txbuf_t *txbuf = NULL;
-
- txbuf = (rpcsvc_txbuf_t *) mem_get(conn->txpool);
- if (!txbuf) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to get txbuf");
- return NULL;
- }
-
- memset (txbuf, 0, sizeof (*txbuf));
- INIT_LIST_HEAD (&txbuf->txlist);
- txbuf->buf = msg;
-
- /* If it was required, this iob must've been ref'd already
- * so I dont have to bother here.
- */
- txbuf->iob = iob;
- txbuf->iobref = iobref;
- txbuf->offset = 0;
- txbuf->txbehave = txflags;
-
- return txbuf;
-}
-
-
-int
-rpcsvc_conn_append_txlist (rpcsvc_conn_t *conn, struct iovec msg,
- struct iobuf *iob, int txflags)
-{
- rpcsvc_txbuf_t *txbuf = NULL;
-
- if ((!conn) || (!msg.iov_base) || (!iob))
- return -1;
-
- txbuf = rpcsvc_init_txbuf (conn, msg, iob, NULL, txflags);
- if (!txbuf)
- return -1;
-
- list_add_tail (&txbuf->txlist, &conn->txbufs);
- return 0;
-}
-
-
-void
-rpcsvc_set_lastfrag (uint32_t *fragsize) {
- (*fragsize) |= 0x80000000U;
-}
-
-void
-rpcsvc_set_frag_header_size (uint32_t size, char *haddr)
-{
- size = htonl (size);
- memcpy (haddr, &size, sizeof (size));
-}
-
-void
-rpcsvc_set_last_frag_header_size (uint32_t size, char *haddr)
-{
- rpcsvc_set_lastfrag (&size);
- rpcsvc_set_frag_header_size (size, haddr);
-}
-
-
-/* Given the RPC reply structure and the payload handed by the RPC program,
- * encode the RPC record header into the buffer pointed by recordstart.
- */
-struct iovec
-rpcsvc_record_build_header (char *recordstart, size_t rlen,
- struct rpc_msg reply, size_t payload)
-{
- struct iovec replyhdr;
- struct iovec txrecord = {0, 0};
- size_t fraglen = 0;
- int ret = -1;
-
- /* After leaving aside the 4 bytes for the fragment header, lets
- * encode the RPC reply structure into the buffer given to us.
- */
- ret = rpc_reply_to_xdr (&reply,(recordstart + RPCSVC_FRAGHDR_SIZE),
- rlen, &replyhdr);
- if (ret == -1) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to create RPC reply");
- goto err;
- }
-
- fraglen = payload + replyhdr.iov_len;
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "Reply fraglen %zu, payload: %zu, "
- "rpc hdr: %zu", fraglen, payload, replyhdr.iov_len);
-
- /* Since we're not spreading RPC records over mutiple fragments
- * we just set this fragment as the first and last fragment for this
- * record.
- */
- rpcsvc_set_last_frag_header_size (fraglen, recordstart);
-
- /* Even though the RPC record starts at recordstart+RPCSVC_FRAGHDR_SIZE
- * we need to transmit the record with the fragment header, which starts
- * at recordstart.
- */
- txrecord.iov_base = recordstart;
-
- /* Remember, this is only the vec for the RPC header and does not
- * include the payload above. We needed the payload only to calculate
- * the size of the full fragment. This size is sent in the fragment
- * header.
- */
- txrecord.iov_len = RPCSVC_FRAGHDR_SIZE + replyhdr.iov_len;
-
-err:
- return txrecord;
-}
-
-
-int
-rpcsvc_conn_submit (rpcsvc_conn_t *conn, struct iovec hdr,
- struct iobuf *hdriob, struct iovec msgvec,
- struct iobuf *msgiob)
-{
- int ret = -1;
-
- if ((!conn) || (!hdr.iov_base) || (!hdriob))
- return -1;
-
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "Tx Header: %zu, payload: %zu",
- hdr.iov_len, msgvec.iov_len);
- /* Now that we have both the RPC and Program buffers in xdr format
- * lets hand it to the transmission layer.
- */
- pthread_mutex_lock (&conn->connlock);
- {
- if (!rpcsvc_conn_check_active (conn)) {
- gf_log (GF_RPCSVC, GF_LOG_DEBUG, "Connection inactive");
- goto unlock_err;
- }
-
- ret = rpcsvc_conn_append_txlist (conn, hdr, hdriob,
- RPCSVC_TXB_FIRST);
- if (ret == -1) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to append "
- "header to transmission list");
- goto unlock_err;
- }
-
- /* It is possible that this RPC reply is an error reply. In that
- * case we might not have been handed a payload.
- */
- ret = 0;
- if (msgiob)
- ret = rpcsvc_conn_append_txlist (conn, msgvec, msgiob,
- RPCSVC_TXB_LAST);
- if (ret == -1) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to append"
- " payload to transmission list");
- goto unlock_err;
- }
- }
-unlock_err:
- pthread_mutex_unlock (&conn->connlock);
-
- if (ret == -1)
- goto err;
-
- /* Tell event pool, we're interested in poll_out to trigger flush
- * of our tx buffers.
- */
- conn->eventidx = event_select_on (conn->stage->eventpool, conn->sockfd,
- conn->eventidx, -1, 1);
- ret = 0;
-err:
-
- return ret;
-}
-
-
-int
-rpcsvc_fill_reply (rpcsvc_request_t *req, struct rpc_msg *reply)
-{
- rpcsvc_program_t *prog = NULL;
- if ((!req) || (!reply))
- return -1;
-
- prog = rpcsvc_request_program (req);
- rpc_fill_empty_reply (reply, req->xid);
-
- if (req->rpc_stat == MSG_DENIED)
- rpc_fill_denied_reply (reply, req->rpc_err, req->auth_err);
- else if (req->rpc_stat == MSG_ACCEPTED)
- rpc_fill_accepted_reply (reply, req->rpc_err, prog->proglowvers,
- prog->proghighvers, req->verf.flavour,
- req->verf.datalen,
- req->verf.authdata);
- else
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Invalid rpc_stat value");
-
- return 0;
-}
-
-
-/* Given a request and the reply payload, build a reply and encodes the reply
- * into a record header. This record header is encoded into the vector pointed
- * to be recbuf.
- * msgvec is the buffer that points to the payload of the RPC program.
- * This buffer can be NULL, if an RPC error reply is being constructed.
- * The only reason it is needed here is that in case the buffer is provided,
- * we should account for the length of that buffer in the RPC fragment header.
- */
-struct iobuf *
-rpcsvc_record_build_record (rpcsvc_request_t *req, size_t payload,
- struct iovec *recbuf)
-{
- struct rpc_msg reply;
- struct iobuf *replyiob = NULL;
- char *record = NULL;
- struct iovec recordhdr = {0, };
- size_t pagesize = 0;
- rpcsvc_conn_t *conn = NULL;
- rpcsvc_t *svc = NULL;
-
- if ((!req) || (!req->conn) || (!recbuf))
- return NULL;
-
- /* First, try to get a pointer into the buffer which the RPC
- * layer can use.
- */
- conn = req->conn;
- svc = rpcsvc_conn_rpcsvc (conn);
- replyiob = iobuf_get (svc->ctx->iobuf_pool);
- pagesize = iobpool_pagesize ((struct iobuf_pool *)svc->ctx->iobuf_pool);
- if (!replyiob) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to get iobuf");
- goto err_exit;
- }
-
- record = iobuf_ptr (replyiob); /* Now we have it. */
-
- /* Fill the rpc structure and XDR it into the buffer got above. */
- rpcsvc_fill_reply (req, &reply);
- recordhdr = rpcsvc_record_build_header (record, pagesize, reply,
- payload);
- if (!recordhdr.iov_base) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to build record "
- " header");
- iobuf_unref (replyiob);
- replyiob = NULL;
- recbuf->iov_base = NULL;
- goto err_exit;
- }
-
- recbuf->iov_base = recordhdr.iov_base;
- recbuf->iov_len = recordhdr.iov_len;
-err_exit:
- return replyiob;
-}
-
-
-/*
- * The function to submit a program message to the RPC service.
- * This message is added to the transmission queue of the
- * conn.
- *
- * Program callers are not expected to use the msgvec->iov_base
- * address for anything else.
- * Nor are they expected to free it once this function returns.
- * Once the transmission of the buffer is completed by the RPC service,
- * the memory area as referenced through @msg will be unrefed.
- * If a higher layer does not want anything to do with this iobuf
- * after this function returns, it should call unref on it. For keeping
- * it around till the transmission is actually complete, rpcsvc also refs it.
- * *
- * If this function returns an error by returning -1, the
- * higher layer programs should assume that a disconnection happened
- * and should know that the conn memory area as well as the req structure
- * has been freed internally.
- *
- * For now, this function assumes that a submit is always called
- * to send a new record. Later, if there is a situation where different
- * buffers for the same record come from different sources, then we'll
- * need to change this code to account for multiple submit calls adding
- * the buffers into a single record.
- */
-
-int
-rpcsvc_submit_generic (rpcsvc_request_t *req, struct iovec msgvec,
- struct iobuf *msg)
-{
- int ret = -1;
- struct iobuf *replyiob = NULL;
- struct iovec recordhdr = {0, };
- rpcsvc_conn_t *conn = NULL;
-
- if ((!req) || (!req->conn))
- return -1;
-
- conn = req->conn;
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "Tx message: %zu", msgvec.iov_len);
- /* Build the buffer containing the encoded RPC reply. */
- replyiob = rpcsvc_record_build_record (req, msgvec.iov_len, &recordhdr);
- if (!replyiob) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR,"Reply record creation failed");
- goto disconnect_exit;
- }
-
- /* Must ref the iobuf got from higher layer so that the higher layer
- * can rest assured that it can unref it and leave the final freeing
- * of the buffer to us. Note msg can be NULL if an RPC-only message
- * was being sent. Happens when an RPC error reply is being sent.
- */
- if (msg)
- iobuf_ref (msg);
- ret = rpcsvc_conn_submit (conn, recordhdr, replyiob, msgvec, msg);
- mem_put (conn->rxpool, req);
-
- if (ret == -1) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to submit message");
- iobuf_unref (replyiob);
- }
-
-disconnect_exit:
- /* Note that a unref is called everytime a reply is sent. This is in
- * response to the ref that is performed on the conn when a request is
- * handed to the RPC program.
- *
- * The catch, however, is that if the reply is an rpc error, we must
- * not unref. This is because the ref only contains
- * references for the actors to which the request was handed plus one
- * reference maintained by the RPC layer. By unrefing for a case where
- * no actor was called, we will be losing the ref held for the RPC
- * layer.
- */
- if ((rpcsvc_request_accepted (req)) &&
- (rpcsvc_request_accepted_success (req)))
- rpcsvc_conn_unref (conn);
-
- return ret;
-}
-
-
-int
-rpcsvc_request_attach_vector (rpcsvc_request_t *req, struct iovec msgvec,
- struct iobuf *iob, struct iobref *iobref,
- int finalvector)
-{
- rpcsvc_txbuf_t *txb = NULL;
- int txflags = 0;
-
- if ((!req) || (!msgvec.iov_base))
- return -1;
-
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "Tx Vector: %zu", msgvec.iov_len);
- if (finalvector)
- txflags |= RPCSVC_TXB_LAST;
- /* We only let the user decide whether this is the last vector for the
- * record, since the first vector is always the RPC header.
- */
- txb = rpcsvc_init_txbuf (req->conn, msgvec, iob, iobref, txflags);
- if (!txb) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Could not init tx buf");
- return -1;
- }
-
- req->payloadsize += msgvec.iov_len;
- if (iob)
- iobuf_ref (iob);
- if (iobref)
- iobref_ref (iobref);
- list_add_tail (&txb->txlist, &req->txlist);
-
- return 0;
-}
-
-
-int
-rpcsvc_submit_vectors (rpcsvc_request_t *req)
-{
- int ret = -1;
- struct iobuf *replyiob = NULL;
- struct iovec recordhdr = {0, };
- rpcsvc_txbuf_t *rpctxb = NULL;
-
- if ((!req) || (!req->conn))
- return -1;
-
- /* Build the buffer containing the encoded RPC reply. */
- replyiob = rpcsvc_record_build_record (req, req->payloadsize,
- &recordhdr);
- if (!replyiob) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR,"Reply record creation failed");
- goto disconnect_exit;
- }
-
- rpctxb = rpcsvc_init_txbuf (req->conn, recordhdr, replyiob, NULL,
- RPCSVC_TXB_FIRST);
- if (!rpctxb) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to create tx buf");
- goto disconnect_exit;
- }
-
- pthread_mutex_lock (&req->conn->connlock);
- {
- list_splice_init (&req->txlist, &req->conn->txbufs);
- list_add (&rpctxb->txlist, &req->conn->txbufs);
- }
- pthread_mutex_unlock (&req->conn->connlock);
-
- ret = 0;
- req->conn->eventidx = event_select_on (req->conn->stage->eventpool,
- req->conn->sockfd,
- req->conn->eventidx, -1, 1);
-disconnect_exit:
- /* Note that a unref is called everytime a reply is sent. This is in
- * response to the ref that is performed on the conn when a request is
- * handed to the RPC program.
- */
- rpcsvc_conn_unref (req->conn);
- if (ret == -1)
- iobuf_unref (replyiob);
-
- mem_put (req->conn->rxpool, req);
- return ret;
-}
-
-
-int
-rpcsvc_error_reply (rpcsvc_request_t *req)
-{
- struct iovec dummyvec = {0, };
-
- if (!req)
- return -1;
-
- /* At this point the req should already have been filled with the
- * appropriate RPC error numbers.
- */
- return rpcsvc_submit_generic (req, dummyvec, NULL);
-}
-
-
-rpcsvc_request_t *
-rpcsvc_request_init (rpcsvc_conn_t *conn, struct rpc_msg *callmsg,
- struct iovec progmsg, rpcsvc_request_t *req)
-{
- if ((!conn) || (!callmsg)|| (!req))
- return NULL;
-
-
- /* We start a RPC request as always denied. */
- req->rpc_stat = MSG_DENIED;
- req->xid = rpc_call_xid (callmsg);
- req->prognum = rpc_call_program (callmsg);
- req->progver = rpc_call_progver (callmsg);
- req->procnum = rpc_call_progproc (callmsg);
- req->conn = conn;
- req->msg = progmsg;
- req->recordiob = conn->rstate.activeiob;
- INIT_LIST_HEAD (&req->txlist);
- req->payloadsize = 0;
-
- /* By this time, the data bytes for the auth scheme would have already
- * been copied into the required sections of the req structure,
- * we just need to fill in the meta-data about it now.
- */
- req->cred.flavour = rpc_call_cred_flavour (callmsg);
- req->cred.datalen = rpc_call_cred_len (callmsg);
- req->verf.flavour = rpc_call_verf_flavour (callmsg);
- req->verf.datalen = rpc_call_verf_len (callmsg);
-
- /* AUTH */
- rpcsvc_auth_request_init (req);
- return req;
-}
-
-
-rpcsvc_request_t *
-rpcsvc_request_create (rpcsvc_conn_t *conn)
-{
- char *msgbuf = NULL;
- struct rpc_msg rpcmsg;
- struct iovec progmsg; /* RPC Program payload */
- rpcsvc_request_t *req = NULL;
- int ret = -1;
-
- if (!conn)
- return NULL;
-
- /* We need to allocate the request before actually calling
- * rpcsvc_request_init on the request so that we, can fill the auth
- * data directly into the request structure from the message iobuf.
- * This avoids a need to keep a temp buffer into which the auth data
- * would've been copied otherwise.
- */
- rpcsvc_alloc_request (conn, req);
- if (!req) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to alloc request");
- goto err;
- }
-
- msgbuf = iobuf_ptr (conn->rstate.activeiob);
- ret = xdr_to_rpc_call (msgbuf, conn->rstate.recordsize, &rpcmsg,
- &progmsg, req->cred.authdata,req->verf.authdata);
-
- if (ret == -1) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "RPC call decoding failed");
- rpcsvc_request_seterr (req, GARBAGE_ARGS);
- goto err;
- }
-
- ret = -1;
- rpcsvc_request_init (conn, &rpcmsg, progmsg, req);
-
- gf_log (GF_RPCSVC, GF_LOG_DEBUG, "RPC XID: %lx, Ver: %ld, Program: %ld,"
- " ProgVers: %ld, Proc: %ld", rpc_call_xid (&rpcmsg),
- rpc_call_rpcvers (&rpcmsg), rpc_call_program (&rpcmsg),
- rpc_call_progver (&rpcmsg), rpc_call_progproc (&rpcmsg));
-
- if (rpc_call_rpcvers (&rpcmsg) != 2) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "RPC version not supported");
- rpcsvc_request_seterr (req, RPC_MISMATCH);
- goto err;
- }
-
- ret = rpcsvc_authenticate (req);
- if (ret == RPCSVC_AUTH_REJECT) {
- /* No need to set auth_err, that is the responsibility of
- * the authentication handler since only that know what exact
- * error happened.
- */
- rpcsvc_request_seterr (req, AUTH_ERROR);
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed authentication");
- ret = -1;
- goto err;
- }
-
-
- /* If the error is not RPC_MISMATCH, we consider the call as accepted
- * since we are not handling authentication failures for now.
- */
- req->rpc_stat = MSG_ACCEPTED;
- ret = 0;
-err:
- if (ret == -1) {
- ret = rpcsvc_error_reply (req);
- req = NULL;
- }
-
- return req;
-}
-
-
-int
-rpcsvc_handle_rpc_call (rpcsvc_conn_t *conn)
-{
- rpcsvc_actor_t *actor = NULL;
- rpcsvc_request_t *req = NULL;
- int ret = -1;
-
- if (!conn)
- return -1;
-
- req = rpcsvc_request_create (conn);
- if (!req)
- goto err;
-
- if (!rpcsvc_request_accepted (req))
- goto err_reply;
-
- actor = rpcsvc_program_actor (conn, req);
- if (!actor)
- goto err_reply;
-
- if ((actor) && (actor->actor)) {
- rpcsvc_conn_ref (conn);
- ret = actor->actor (req);
- }
-
-err_reply:
- if (ret == RPCSVC_ACTOR_ERROR)
- ret = rpcsvc_error_reply (req);
-
- /* No need to propagate error beyond this function since the reply
- * has now been queued. */
- ret = 0;
-err:
- return ret;
-}
-
-#define rpc_call_cred_addr(rs) (iobuf_ptr ((rs)->activeiob) + RPCSVC_BARERPC_MSGSZ - 4)
-
-uint32_t
-rpcsvc_call_credlen (rpcsvc_record_state_t *rs)
-{
- char *credaddr = NULL;
- uint32_t credlen_nw = 0;
- uint32_t credlen_host = 0;
-
- /* Position to the start of the credential length field. */
- credaddr = rpc_call_cred_addr (rs);
- credlen_nw = *(uint32_t *)credaddr;
- credlen_host = ntohl (credlen_nw);
-
- return credlen_host;
-}
-
-uint32_t
-rpcsvc_call_verflen (rpcsvc_record_state_t *rs)
-{
- char *verfaddr = NULL;
- uint32_t verflen_nw = 0;
- uint32_t verflen_host = 0;
- uint32_t credlen = 0;
-
- /* Position to the start of the verifier length field. */
- credlen = rpcsvc_call_credlen (rs);
- verfaddr = (rpc_call_cred_addr (rs) + 4 + credlen);
- verflen_nw = *(uint32_t *)verfaddr;
- verflen_host = ntohl (verflen_nw);
-
- return verflen_host;
-}
-
-
-void
-rpcsvc_update_vectored_verf (rpcsvc_record_state_t *rs)
-{
- if (!rs)
- return;
-
- rs->recordsize += rpcsvc_call_verflen (rs);
- return;
-}
-
-
-void
-rpcsvc_handle_vectored_prep_rpc_call (rpcsvc_conn_t *conn)
-{
- rpcsvc_actor_t *actor = NULL;
- rpcsvc_request_t *req = NULL;
- rpcsvc_record_state_t *rs = NULL;
- rpcsvc_t *svc = NULL;
- int ret = -1;
- ssize_t remfrag = RPCSVC_ACTOR_ERROR;
- int newbuf = 0;
-
- if (!conn)
- return;
-
- rs = &conn->rstate;
-
- /* In case one of the steps below fails, we need to make sure that the
- * remaining frag in the kernel's buffers are read-out so that the
- * requests that follow can be served.
- */
- rs->remainingfrag = rs->fragsize - rs->recordsize;
- rs->vecstate = RPCSVC_VECTOR_IGNORE;
- req = rpcsvc_request_create (conn);
- svc = rpcsvc_conn_rpcsvc (conn);
- if (!req)
- goto err;
-
- if (!rpcsvc_request_accepted (req))
- goto err_reply;
-
- actor = rpcsvc_program_actor (conn, req);
- if (!actor)
- goto err_reply;
-
- if (!actor->vector_sizer) {
- ret = -1;
- rpcsvc_request_seterr (req, PROC_UNAVAIL);
- goto err_reply;
- }
-
- rpcsvc_conn_ref (conn);
- ret = actor->vector_sizer (req, &remfrag, &newbuf);
- rpcsvc_conn_unref (conn);
-
- if (ret == RPCSVC_ACTOR_ERROR) {
- ret = -1;
- rpcsvc_request_seterr (req, SYSTEM_ERR);
- goto err_reply;
- }
-
- rs->remainingfrag = remfrag;
- rs->vecstate = RPCSVC_VECTOR_READPROCHDR;
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "Vectored RPC proc header remaining:"
- " %d", rs->remainingfrag);
- conn->vectoredreq = req;
-
- /* Store the reference to the current frag pointer. This is where the
- * proc header will be read into.
- */
- req->msg.iov_base = rs->fragcurrent;
- req->msg.iov_len = rs->remainingfrag;
- ret = 0;
-
-err_reply:
- if (ret == -1)
- ret = rpcsvc_error_reply (req);
-
- /* No need to propagate error beyond this function since the reply
- * has now been queued. */
- ret = 0;
-err:
- return;
-}
-
-
-void
-rpcsvc_update_vectored_verfsz (rpcsvc_conn_t *conn)
-{
- rpcsvc_record_state_t *rs = NULL;
- uint32_t verflen = 0;
-
- if (!conn)
- return;
-
- rs = &conn->rstate;
-
- verflen = rpcsvc_call_verflen (rs);
- rs->recordsize += 8;
- if (verflen > 0) {
- rs->remainingfrag = verflen;
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "Vectored RPC verf remaining: "
- " %d", rs->remainingfrag);
- rs->vecstate = RPCSVC_VECTOR_READVERF;
- } else {
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "Vectored RPC preparing call");
- rpcsvc_handle_vectored_prep_rpc_call (conn);
- }
-
- return;
-}
-
-
-void
-rpcsvc_update_vectored_cred (rpcsvc_record_state_t *rs)
-{
- uint32_t credlen = 0;
-
- if (!rs)
- return;
-
- credlen = rpcsvc_call_credlen (rs);
- /* Update remainingfrag to read the 8 bytes needed for
- * reading verf flavour and verf len.
- */
- rs->remainingfrag = (2 * sizeof (uint32_t));
- rs->vecstate = RPCSVC_VECTOR_READVERFSZ;
- rs->recordsize += credlen;
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "Vectored RPC verfsz remaining: %d",
- rs->remainingfrag);
-
- return;
-}
-
-void
-rpcsvc_update_vectored_barerpc (rpcsvc_record_state_t *rs)
-{
- uint32_t credlen = 0;
-
- if (!rs)
- return;
-
- credlen = rpcsvc_call_credlen (rs);
- rs->recordsize = RPCSVC_BARERPC_MSGSZ;
- if (credlen == 0) {
- rs->remainingfrag = 8;
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "Vectored RPC verfsz remaining"
- ": %d", rs->remainingfrag);
- rs->vecstate = RPCSVC_VECTOR_READVERFSZ;
- } else {
- rs->remainingfrag = credlen;
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "Vectored RPC cred remaining: "
- "%d", rs->remainingfrag);
- rs->vecstate = RPCSVC_VECTOR_READCRED;
- }
-
- return;
-}
-
-
-void
-rpcsvc_handle_vectored_rpc_call (rpcsvc_conn_t *conn)
-{
- rpcsvc_actor_t *actor = NULL;
- rpcsvc_request_t *req = NULL;
- rpcsvc_record_state_t *rs = NULL;
- rpcsvc_t *svc = NULL;
- int ret = -1;
- ssize_t remfrag = -1;
- int newbuf = 0;
-
- if (!conn)
- return;
-
- rs = &conn->rstate;
-
- req = conn->vectoredreq;
- svc = rpcsvc_conn_rpcsvc (conn);
-
- if (!req)
- goto err;
-
- actor = rpcsvc_program_actor (conn, req);
- if (!actor)
- goto err_reply;
-
- if (!actor->vector_sizer) {
- ret = -1;
- rpcsvc_request_seterr (req, PROC_UNAVAIL);
- goto err_reply;
- }
-
- req->msg.iov_len = (unsigned long)((long)rs->fragcurrent - (long)req->msg.iov_base);
- rpcsvc_conn_ref (conn);
- ret = actor->vector_sizer (req, &remfrag, &newbuf);
- rpcsvc_conn_unref (conn);
- if (ret == RPCSVC_ACTOR_ERROR) {
- ret = -1;
- rpcsvc_request_seterr (req, SYSTEM_ERR);
- goto err_reply;
- }
-
- if (newbuf) {
- rs->vectoriob = iobuf_get (svc->ctx->iobuf_pool);
- rs->fragcurrent = iobuf_ptr (rs->vectoriob);
- rs->vecstate = RPCSVC_VECTOR_READVEC;
- rs->remainingfrag = remfrag;
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "Vectored RPC buf remaining:"
- " %d", rs->remainingfrag);
- } else {
- rs->remainingfrag = remfrag;
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "Vectored RPC proc remaining:"
- " %d", rs->remainingfrag);
- }
-
- ret = 0;
-err_reply:
- if (ret == -1)
- ret = rpcsvc_error_reply (req);
-
- /* No need to propagate error beyond this function since the reply
- * has now been queued. */
- ret = 0;
-err:
- return;
-}
-
-
-
-void
-rpcsvc_record_vectored_call_actor (rpcsvc_conn_t *conn)
-{
- rpcsvc_actor_t *actor = NULL;
- rpcsvc_request_t *req = NULL;
- rpcsvc_record_state_t *rs = NULL;
- rpcsvc_t *svc = NULL;
- int ret = -1;
-
- if (!conn)
- return;
-
- rs = &conn->rstate;
- req = conn->vectoredreq;
- svc = rpcsvc_conn_rpcsvc (conn);
-
- if (!req)
- goto err;
-
- actor = rpcsvc_program_actor (conn, req);
- if (!actor)
- goto err_reply;
-
- if (actor->vector_actor) {
- rpcsvc_conn_ref (conn);
- ret = actor->vector_actor (req, rs->vectoriob);
- } else {
- rpcsvc_request_seterr (req, PROC_UNAVAIL);
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "No vectored handler present");
- ret = RPCSVC_ACTOR_ERROR;
- }
-
-err_reply:
- if (ret == RPCSVC_ACTOR_ERROR)
- ret = rpcsvc_error_reply (req);
-
- /* No need to propagate error beyond this function since the reply
- * has now been queued. */
- ret = 0;
-err:
- return;
-}
-
-
-
-ssize_t
-rpcsvc_update_vectored_state (rpcsvc_conn_t *conn)
-{
- rpcsvc_record_state_t *rs = NULL;
- rpcsvc_t *svc = NULL;
-
- if (!conn)
- return 0;
-
- /* At this point, we can be confident that the activeiob contains
- * exactly the first RPCSVC_BARERPC_MSGSZ bytes needed in order to
- * determine the program and actor. So the next state will be
- * to read the credentials.
- *
- * But first, try to determine how many more bytes do we need from the
- * network to complete the RPC message including the credentials.
- */
-
- rs = &conn->rstate;
- if (rpcsvc_record_vectored_baremsg (rs))
- rpcsvc_update_vectored_barerpc (rs);
- else if (rpcsvc_record_vectored_cred (rs))
- rpcsvc_update_vectored_cred (rs);
- else if (rpcsvc_record_vectored_verfsz (rs))
- rpcsvc_update_vectored_verfsz (conn);
- else if (rpcsvc_record_vectored_verfread (rs)) {
- rpcsvc_update_vectored_verf (rs);
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "Vectored RPC preparing call");
- rpcsvc_handle_vectored_prep_rpc_call (conn);
- } else if (rpcsvc_record_vectored_readprochdr (rs))
- rpcsvc_handle_vectored_rpc_call (conn);
- else if (rpcsvc_record_vectored_ignore (rs)) {
- svc = rpcsvc_conn_rpcsvc (conn);
- rpcsvc_record_init (rs, svc->ctx->iobuf_pool);
- } else if (rpcsvc_record_vectored_readvec (rs)) {
- svc = rpcsvc_conn_rpcsvc (conn);
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "Vectored RPC vector read");
- rpcsvc_record_vectored_call_actor (conn);
- rpcsvc_record_init (rs, svc->ctx->iobuf_pool);
- }
-
- return 0;
-}
-
-
-ssize_t
-rpcsvc_record_read_partial_frag (rpcsvc_record_state_t *rs, ssize_t dataread);
-
-ssize_t
-rpcsvc_update_vectored_msg (rpcsvc_conn_t *conn, ssize_t dataread)
-{
-
- if (!conn)
- return dataread;
-
- /* find out how much of the bare msg is pending and set that up to be
- * read into the updated fragcurrent along with the updated size into
- * remainingfrag.
- */
-
-
- /* Incidently, the logic needed here is similar to a regular partial
- * fragment read since we've already set the remainingfrag member in
- * rstate to be RPCSVC_BARERPC_MSGSZ for the purpose of a vectored
- * fragment.
- */
- return rpcsvc_record_read_partial_frag (&conn->rstate, dataread);
-}
-
-/* FIX: As a first version of vectored reading, I am assuming dataread will
- * always be equal to RPCSVC_BARERPC_MSGSZ for the sake of simplicity on the
- * belief that we're never actually reading more bytes than needed in each
- * poll_in.
- */
-ssize_t
-rpcsvc_handle_vectored_frag (rpcsvc_conn_t *conn, ssize_t dataread)
-{
- if (!conn)
- return dataread;
-
- /* At this point we can be confident that only the frag size has been
- * read from the network. Now it is up to us to have the remaining RPC
- * fields given to us here.
- */
-
- /* Since the poll_in handler uses the remainingfrag field to determine
- * how much to read from the network, we'll hack this scheme to tell
- * the poll_in to read at most RPCSVC_BARERPC_MSGSZ bytes. This is done
- * to, as a first step, identify which (program, actor) we need to call.
- */
-
- dataread = rpcsvc_update_vectored_msg (conn, dataread);
-
- if (conn->rstate.remainingfrag == 0) {
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "Vectored frag complete");
- dataread = rpcsvc_update_vectored_state (conn);
- }
-
- return dataread;
-}
-
-
-int
-rpcsvc_record_update_state (rpcsvc_conn_t *conn, ssize_t dataread)
-{
- rpcsvc_record_state_t *rs = NULL;
- rpcsvc_t *svc = NULL;
-
- if (!conn)
- return -1;
-
- rs = &conn->rstate;
- /* At entry into this function, fragcurrent will be pointing to the\
- * start of the area into which dataread number of bytes were read.
- */
-
- if (rpcsvc_record_readfraghdr(rs))
- dataread = rpcsvc_record_update_fraghdr (rs, dataread);
-
- if (rpcsvc_record_readfrag(rs)) {
- /* The minimum needed for triggering the vectored handler is
- * the frag size field. The fragsize member remains set to this
- * size till this request is completely extracted from the
- * network. Once all the data has been read from the network,
- * the request structure would've been created. The point being
- * that even if it takes multiple calls to network IO for
- * getting the vectored fragment, we can continue to use this
- * condition as the flag to tell us that this is a vectored
- * fragment.
- */
- if ((dataread > 0) && (rpcsvc_record_vectored (rs))) {
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "Vectored frag");
- dataread = rpcsvc_handle_vectored_frag (conn, dataread);
- } else if (dataread > 0) {
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "Regular frag");
- dataread = rpcsvc_record_update_frag (rs, dataread);
- }
- }
-
- /* This should not happen. We are never reading more than the current
- * fragment needs. Something is seriously wrong.
- */
- if (dataread > 0) {
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "Data Left: %zd", dataread);
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Unwanted data read from "
- " connection.");
- }
-
- /* If we're now supposed to wait for a new fragment header and if the
- * fragment that we just completed in the previous call to
- * rpcsvc_record_update_frag was the last fragment for the current
- * RPC record, then, it is time to perform the translation from
- * XDR formatted buffer in activeiob followed by the upcall to the
- * protocol actor.
- */
- if ((rpcsvc_record_readfraghdr(rs)) && (rs->islastfrag)) {
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "Full Record Received.");
- rpcsvc_handle_rpc_call (conn);
- svc = rpcsvc_conn_rpcsvc (conn);
- rpcsvc_record_init (rs, svc->ctx->iobuf_pool);
- }
-
- return 0;
-}
-
-
-char *
-rpcsvc_record_read_addr (rpcsvc_record_state_t *rs)
-{
-
- if (rpcsvc_record_readfraghdr (rs))
- return rpcsvc_record_currenthdr_addr (rs);
- else if (rpcsvc_record_readfrag (rs))
- return rpcsvc_record_currentfrag_addr (rs);
-
- return NULL;
-}
-
-
-int
-rpcsvc_conn_data_poll_in (rpcsvc_conn_t *conn)
-{
- ssize_t dataread = -1;
- size_t readsize = 0;
- char *readaddr = NULL;
- int ret = -1;
-
- readaddr = rpcsvc_record_read_addr (&conn->rstate);
- if (!readaddr)
- goto err;
-
- readsize = rpcsvc_record_read_size (&conn->rstate);
- if (readsize == -1)
- goto err;
-
- dataread = rpcsvc_socket_read (conn->sockfd, readaddr, readsize);
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "conn: 0x%lx, readsize: %zu, dataread: %zd",
- (long)conn, readsize, dataread);
-
- if (dataread > 0)
- ret = rpcsvc_record_update_state (conn, dataread);
-
-err:
- return ret;
-}
-
-
-int
-rpcsvc_conn_data_poll_err (rpcsvc_conn_t *conn)
-{
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "Received error event");
- rpcsvc_conn_deinit (conn);
- return 0;
-}
-
-
-int
-__rpcsvc_conn_data_poll_out (rpcsvc_conn_t *conn)
-{
- rpcsvc_txbuf_t *txbuf = NULL;
- rpcsvc_txbuf_t *tmp = NULL;
- ssize_t written = -1;
- char *writeaddr = NULL;
- size_t writesize = -1;
-
- if (!conn)
- return -1;
-
- /* Attempt transmission of each of the pending buffers */
- list_for_each_entry_safe (txbuf, tmp, &conn->txbufs, txlist) {
-tx_remaining:
- writeaddr = (char *)(txbuf->buf.iov_base + txbuf->offset);
- writesize = (txbuf->buf.iov_len - txbuf->offset);
-
- if (txbuf->txbehave & RPCSVC_TXB_FIRST) {
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "First Tx Buf");
- rpcsvc_socket_block_tx (conn->sockfd);
- }
-
- written = rpcsvc_socket_write (conn->sockfd, writeaddr,
- writesize);
- if (txbuf->txbehave & RPCSVC_TXB_LAST) {
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "Last Tx Buf");
- rpcsvc_socket_unblock_tx (conn->sockfd);
- }
- gf_log (GF_RPCSVC, GF_LOG_TRACE, "conn: 0x%lx, Tx request: %zu,"
- " Tx sent: %zd", (long)conn, writesize, written);
-
- /* There was an error transmitting this buffer */
- if (written == -1)
- break;
-
- if (written >= 0)
- txbuf->offset += written;
-
- /* If the current buffer has been completely transmitted,
- * delete it from the list and move on to the next buffer.
- */
- if (txbuf->offset == txbuf->buf.iov_len) {
- /* It doesnt matter who ref'ed this iobuf, rpcsvc for
- * its own header or a RPC program.
- */
- if (txbuf->iob)
- iobuf_unref (txbuf->iob);
- if (txbuf->iobref)
- iobref_unref (txbuf->iobref);
-
- list_del (&txbuf->txlist);
- mem_put (conn->txpool, txbuf);
- } else
- /* If the current buffer is incompletely tx'd, do not
- * go to the head of the loop, since that moves us to
- * the next buffer.
- */
- goto tx_remaining;
- }
-
- /* If we've broken out of the loop above then we must unblock
- * the transmission now.
- */
- rpcsvc_socket_unblock_tx (conn->sockfd);
- if (list_empty (&conn->txbufs))
- conn->eventidx = event_select_on (conn->stage->eventpool,
- conn->sockfd, conn->eventidx,
- -1, 0);
-
- return 0;
-}
-
-
-int
-rpcsvc_conn_data_poll_out (rpcsvc_conn_t *conn)
-{
- if (!conn)
- return -1;
-
-
- pthread_mutex_lock (&conn->connlock);
- {
- __rpcsvc_conn_data_poll_out (conn);
- }
- pthread_mutex_unlock (&conn->connlock);
-
- return 0;
-}
-
-
-int
-rpcsvc_conn_data_handler (int fd, int idx, void *data, int poll_in, int poll_out
- , int poll_err)
-{
- rpcsvc_conn_t *conn = NULL;
- int ret = 0;
-
- if (!data)
- return 0;
-
- conn = (rpcsvc_conn_t *)data;
-
- if (poll_out)
- ret = rpcsvc_conn_data_poll_out (conn);
-
- if (poll_err) {
- ret = rpcsvc_conn_data_poll_err (conn);
- return 0;
- }
-
- if (poll_in) {
- ret = 0;
- ret = rpcsvc_conn_data_poll_in (conn);
- }
-
- if (ret == -1)
- rpcsvc_conn_data_poll_err (conn);
-
- return 0;
-}
-
-
-int
-rpcsvc_conn_listening_handler (int fd, int idx, void *data, int poll_in,
- int poll_out, int poll_err)
-{
- rpcsvc_conn_t *newconn = NULL;
- rpcsvc_stage_t *selectedstage = NULL;
- int ret = -1;
- rpcsvc_conn_t *conn = NULL;
- rpcsvc_program_t *prog = NULL;
- rpcsvc_t *svc = NULL;
-
- if (!poll_in)
- return 0;
-
- conn = (rpcsvc_conn_t *)data;
- prog = (rpcsvc_program_t *)conn->program;
- svc = rpcsvc_conn_rpcsvc (conn);
- newconn = rpcsvc_conn_accept_init (svc, fd, prog);
- if (!newconn) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "failed to accept connection");
- goto err;
- }
-
- selectedstage = rpcsvc_select_stage (svc);
- if (!selectedstage)
- goto close_err;
-
- /* Now that we've accepted the connection, we need to associate
- * its events to a stage.
- */
- ret = rpcsvc_stage_conn_associate (selectedstage, newconn,
- rpcsvc_conn_data_handler, newconn);
- if (ret == -1) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "could not associated stage "
- " with new connection");
- goto close_err;
- }
- gf_log (GF_RPCSVC, GF_LOG_DEBUG, "New Connection: Program %s, Num: %d,"
- " Ver: %d, Port: %d", prog->progname, prog->prognum,
- prog->progver, prog->progport);
- ret = 0;
-close_err:
- if (ret == -1)
- rpcsvc_conn_unref (newconn);
-
-err:
- return ret;
-}
-
-
-/* Register the program with the local portmapper service. */
-int
-rpcsvc_program_register_portmap (rpcsvc_program_t *newprog)
-{
- if (!newprog)
- return -1;
-
- if (!(pmap_set(newprog->prognum, newprog->progver, IPPROTO_TCP,
- newprog->progport))) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Could not register with"
- " portmap");
- return -1;
- }
-
- return 0;
-}
-
-
-int
-rpcsvc_program_unregister_portmap (rpcsvc_program_t *prog)
-{
- if (!prog)
- return -1;
-
- if (!(pmap_unset(prog->prognum, prog->progver))) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Could not unregister with"
- " portmap");
- return -1;
- }
-
- return 0;
-}
-
-
-int
-rpcsvc_stage_program_register (rpcsvc_stage_t *stg, rpcsvc_program_t *newprog)
-{
- rpcsvc_conn_t *newconn = NULL;
- rpcsvc_t *svc = NULL;
-
- if ((!stg) || (!newprog))
- return -1;
-
- svc = rpcsvc_stage_service (stg);
- /* Create a listening socket */
- newconn = rpcsvc_conn_listen_init (svc, newprog);
- if (!newconn) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "could not create listening"
- " connection");
- return -1;
- }
-
- if ((rpcsvc_stage_conn_associate (stg, newconn,
- rpcsvc_conn_listening_handler,
- newconn)) == -1) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR,"could not associate stage with"
- " listening connection");
- return -1;
- }
-
- return 0;
-}
-
-
-int
-rpcsvc_program_register (rpcsvc_t *svc, rpcsvc_program_t program)
-{
- rpcsvc_program_t *newprog = NULL;
- rpcsvc_stage_t *selectedstage = NULL;
- int ret = -1;
-
- if (!svc)
- return -1;
-
- newprog = CALLOC (1, sizeof(*newprog));
- if (!newprog)
- return -1;
-
- if (!program.actors)
- goto free_prog;
-
- memcpy (newprog, &program, sizeof (program));
- selectedstage = rpcsvc_select_stage (svc);
-
- ret = rpcsvc_stage_program_register (selectedstage, newprog);
- if (ret == -1) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "stage registration of program"
- " failed");
- goto free_prog;
- }
-
- ret = rpcsvc_program_register_portmap (newprog);
- if (ret == -1) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "portmap registration of"
- " program failed");
- goto free_prog;
- }
-
- ret = 0;
- gf_log (GF_RPCSVC, GF_LOG_DEBUG, "New program registered: %s, Num: %d,"
- " Ver: %d, Port: %d", newprog->progname, newprog->prognum,
- newprog->progver, newprog->progport);
-
-free_prog:
- if (ret == -1) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Program registration failed:"
- " %s, Num: %d, Ver: %d, Port: %d", newprog->progname,
- newprog->prognum, newprog->progver, newprog->progport);
- FREE (newprog);
- }
-
- return ret;
-}
-
-/* The only difference between the generic submit and this one is that the
- * generic submit is also used for submitting RPC error replies in where there
- * are no payloads so the msgvec and msgbuf can be NULL.
- * Since RPC programs should be using this function along with their payloads
- * we must perform NULL checks before calling the generic submit.
- */
-int
-rpcsvc_submit_message (rpcsvc_request_t *req, struct iovec msgvec,
- struct iobuf *msg)
-{
- if ((!req) || (!req->conn) || (!msg) || (!msgvec.iov_base))
- return -1;
-
- return rpcsvc_submit_generic (req, msgvec, msg);
-}
-
-
-int
-rpcsvc_program_unregister (rpcsvc_t *svc, rpcsvc_program_t prog)
-{
- int ret = -1;
-
- if (!svc)
- return -1;
-
- /* TODO: De-init the listening connection for this program. */
- ret = rpcsvc_program_unregister_portmap (&prog);
- if (ret == -1) {
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "portmap unregistration of"
- " program failed");
- goto err;
- }
-
- ret = 0;
- gf_log (GF_RPCSVC, GF_LOG_DEBUG, "Program unregistered: %s, Num: %d,"
- " Ver: %d, Port: %d", prog.progname, prog.prognum,
- prog.progver, prog.progport);
-
-err:
- if (ret == -1)
- gf_log (GF_RPCSVC, GF_LOG_ERROR, "Program unregistration failed"
- ": %s, Num: %d, Ver: %d, Port: %d", prog.progname,
- prog.prognum, prog.progver, prog.progport);
-
- return ret;
-}
-
-
-int
-rpcsvc_conn_peername (rpcsvc_conn_t *conn, char *hostname, int hostlen)
-{
- if (!conn)
- return -1;
-
- return rpcsvc_socket_peername (conn->sockfd, hostname, hostlen);
-}
-
-
-int
-rpcsvc_conn_peeraddr (rpcsvc_conn_t *conn, char *addrstr, int addrlen,
- struct sockaddr *sa, socklen_t sasize)
-{
- if (!conn)
- return -1;
-
- return rpcsvc_socket_peeraddr (conn->sockfd, addrstr, addrlen, sa,
- sasize);
-}
-
diff --git a/xlators/nfs/lib/src/rpcsvc.h b/xlators/nfs/lib/src/rpcsvc.h
deleted file mode 100644
index 2746288f8..000000000
--- a/xlators/nfs/lib/src/rpcsvc.h
+++ /dev/null
@@ -1,715 +0,0 @@
-/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
- This file is part of GlusterFS.
-
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _RPCSVC_H
-#define _RPCSVC_H
-
-
-#ifndef _CONFIG_H
-#define _CONFIG_H
-#include "config.h"
-#endif
-
-#include "event.h"
-#include "transport.h"
-#include "logging.h"
-#include "dict.h"
-#include "mem-pool.h"
-#include "list.h"
-#include "iobuf.h"
-#include "xdr-rpc.h"
-#include "glusterfs.h"
-
-#include <pthread.h>
-#include <sys/uio.h>
-
-#define GF_RPCSVC "rpc-service"
-#define RPCSVC_THREAD_STACK_SIZE ((size_t)(1024 * GF_UNIT_KB))
-
-#define RPCSVC_DEFAULT_MEMFACTOR 15
-#define RPCSVC_EVENTPOOL_SIZE_MULT 1024
-#define RPCSVC_POOLCOUNT_MULT 35
-#define RPCSVC_CONN_READ (128 * GF_UNIT_KB)
-#define RPCSVC_PAGE_SIZE (128 * GF_UNIT_KB)
-
-/* Defines for RPC record and fragment assembly */
-
-#define RPCSVC_FRAGHDR_SIZE 4 /* 4-byte RPC fragment header size */
-
-/* Given the 4-byte fragment header, returns non-zero if this fragment
- * is the last fragment for the RPC record being assemebled.
- * RPC Record marking standard defines a 32 bit value as the fragment
- * header with the MSB signifying whether the fragment is the last
- * fragment for the record being asembled.
- */
-#define RPCSVC_LASTFRAG(fraghdr) ((uint32_t)(fraghdr & 0x80000000U))
-
-/* Given the 4-byte fragment header, extracts the bits that contain
- * the fragment size.
- */
-#define RPCSVC_FRAGSIZE(fraghdr) ((uint32_t)(fraghdr & 0x7fffffffU))
-
-/* RPC Record States */
-#define RPCSVC_READ_FRAGHDR 1
-#define RPCSVC_READ_FRAG 2
-/* The size in bytes, if crossed by a fragment will be handed over to the
- * vectored actor so that it can allocate its buffers the way it wants.
- * In our RPC layer, we assume that vectored RPC requests/records are never
- * spread over multiple RPC fragments since that prevents us from determining
- * whether the record should be handled in RPC layer completely or handed to
- * the vectored handler.
- */
-#define RPCSVC_VECTORED_FRAGSZ 4096
-#define RPCSVC_VECTOR_READCRED 1003
-#define RPCSVC_VECTOR_READVERFSZ 1004
-#define RPCSVC_VECTOR_READVERF 1005
-#define RPCSVC_VECTOR_IGNORE 1006
-#define RPCSVC_VECTOR_READVEC 1007
-#define RPCSVC_VECTOR_READPROCHDR 1008
-
-#define rpcsvc_record_vectored_baremsg(rs) (((rs)->state == RPCSVC_READ_FRAG) && (rs)->vecstate == 0)
-#define rpcsvc_record_vectored_cred(rs) ((rs)->vecstate == RPCSVC_VECTOR_READCRED)
-#define rpcsvc_record_vectored_verfsz(rs) ((rs)->vecstate == RPCSVC_VECTOR_READVERFSZ)
-#define rpcsvc_record_vectored_verfread(rs) ((rs)->vecstate == RPCSVC_VECTOR_READVERF)
-#define rpcsvc_record_vectored_ignore(rs) ((rs)->vecstate == RPCSVC_VECTOR_IGNORE)
-#define rpcsvc_record_vectored_readvec(rs) ((rs)->vecstate == RPCSVC_VECTOR_READVEC)
-#define rpcsvc_record_vectored_readprochdr(rs) ((rs)->vecstate == RPCSVC_VECTOR_READPROCHDR)
-#define rpcsvc_record_vectored(rs) ((rs)->fragsize > RPCSVC_VECTORED_FRAGSZ)
-/* Includes bytes up to and including the credential length field. The credlen
- * will be followed by @credlen bytes of credential data which will have to be
- * read separately by the vectored reader. After the credentials comes the
- * verifier which will also have to be read separately including the 8 bytes of
- * verf flavour and verflen.
- */
-#define RPCSVC_BARERPC_MSGSZ 32
-#define rpcsvc_record_readfraghdr(rs) ((rs)->state == RPCSVC_READ_FRAGHDR)
-#define rpcsvc_record_readfrag(rs) ((rs)->state == RPCSVC_READ_FRAG)
-
-#define rpcsvc_conn_rpcsvc(conn) ((conn)->stage->svc)
-#define RPCSVC_LOWVERS 2
-#define RPCSVC_HIGHVERS 2
-
-typedef struct rpc_svc_program rpcsvc_program_t;
-/* A Stage is the event handler thread together with
- * the connections being served by this thread.
- * It is called a stage because all the actors, i.e, protocol actors,
- * defined by higher level users of the RPC layer, are executed here.
- */
-typedef struct rpc_svc_stage_context {
- pthread_t tid;
- struct event_pool *eventpool; /* Per-stage event-pool */
- void *svc; /* Ref to the rpcsvc_t */
-} rpcsvc_stage_t;
-
-
-/* RPC Records and Fragments assembly state.
- * This is per-connection state that is used to determine
- * how much data has come in, how much more needs to be read
- * and where it needs to be read.
- *
- * All this state is then used to re-assemble network buffers into
- * RPC fragments, which are then re-assembled into RPC records.
- *
- * See RFC 1831: "RPC: Remote Procedure Call Protocol Specification Version 2",
- * particularly the section on Record Marking Standard.
- */
-typedef struct rpcsvc_record_state {
-
- /* Pending messages storage
- * This memory area is currently being used to assemble
- * the latest RPC record.
- *
- * Note that this buffer contains the data other than the
- * fragment headers received from the network. This is so that we can
- * directly pass this buffer to higher layers without requiring to
- * perform memory copies and marshalling of data.
- */
- struct iobuf *activeiob;
-
- struct iobuf *vectoriob;
- /* The pointer into activeiob memory, into which will go the
- * contents from the next read from the network.
- */
- char *fragcurrent;
-
- /* Size of the currently incomplete RPC fragment.
- * This is filled in when the fragment header comes in.
- * Even though only the 31 least significant bits are used from the
- * fragment header, we use a 32 bit variable to store the size.
- */
- uint32_t fragsize;
-
- /* The fragment header is always read in here so that
- * the RPC messages contained in a RPC records can be processed
- * separately without copying them out of the activeiob above.
- */
- char fragheader[RPCSVC_FRAGHDR_SIZE];
- char *hdrcurrent;
-
- /* Bytes remaining to come in for the current fragment. */
- uint32_t remainingfrag;
-
- /* It is possible for the frag header to be split over separate
- * read calls, so we need to keep track of how much is left.
- */
- uint32_t remainingfraghdr;
-
- /* Record size, the total size of the RPC record, i.e. the total
- * of all fragment sizes received till now. Does not include the size
- * of a partial fragment which is continuing to be assembled right now.
- */
- int recordsize;
-
- /* Current state of the record */
- int state;
-
- /* Current state of the vectored reading process. */
- int vecstate;
-
- /* Set to non-zero when the currently partial or complete fragment is
- * the last fragment being received for the current RPC record.
- */
- uint32_t islastfrag;
-
-} rpcsvc_record_state_t;
-
-
-#define RPCSVC_CONNSTATE_CONNECTED 1
-#define RPCSVC_CONNSTATE_DISCONNECTED 2
-
-#define rpcsvc_conn_check_active(conn) ((conn)->connstate==RPCSVC_CONNSTATE_CONNECTED)
-
-typedef struct rpcsvc_request rpcsvc_request_t;
-/* Contains the state for each connection that is used for transmitting and
- * receiving RPC messages.
- *
- * There is also an eventidx because each connection's fd is added to the event
- * pool of the stage to which a connection belongs.
- * Anything that can be accessed by a RPC program must be synced through
- * connlock.
- */
-typedef struct rpc_conn_state {
-
- /* Transport or connection state */
-
- /* Once we start working on RDMA support, this TCP specific state will
- * have to be abstracted away.
- */
- int sockfd;
- int eventidx;
- int windowsize;
-
- /* Reference to the stage which is handling this
- * connection.
- */
- rpcsvc_stage_t *stage;
-
- /* RPC Records and Fragments assembly state.
- * All incoming data is staged here before being
- * called a full RPC message.
- */
- rpcsvc_record_state_t rstate;
-
- /* It is possible that a client disconnects while
- * the higher layer RPC service is busy in a call.
- * In this case, we cannot just free the conn
- * structure, since the higher layer service could
- * still have a reference to it.
- * The refcount avoids freeing until all references
- * have been given up, although the connection is clos()ed at the first
- * call to unref.
- */
- int connref;
- pthread_mutex_t connlock;
- int connstate;
-
- /* The program that is listening for requests on this connection. */
- rpcsvc_program_t *program;
-
- /* List of buffers awaiting transmission */
- /* Accesses to txbufs between multiple threads calling
- * rpcsvc_submit is synced through connlock. Prefer spinlock over
- * mutex because this is a low overhead op that needs simple
- * appending to the tx list.
- */
- struct list_head txbufs;
-
- /* Mem pool for the txbufs above. */
- struct mem_pool *txpool;
-
- /* Memory pool for rpcsvc_request_t */
- struct mem_pool *rxpool;
-
- /* The request which hasnt yet been handed to the RPC program because
- * this request is being treated as a vector request and so needs some
- * more data to be got from the network.
- */
- rpcsvc_request_t *vectoredreq;
-} rpcsvc_conn_t;
-
-
-#define RPCSVC_MAX_AUTH_BYTES 400
-typedef struct rpcsvc_auth_data {
- int flavour;
- int datalen;
- char authdata[RPCSVC_MAX_AUTH_BYTES];
-} rpcsvc_auth_data_t;
-
-#define rpcsvc_auth_flavour(au) ((au).flavour)
-
-/* The container for the RPC call handed up to an actor.
- * Dynamically allocated. Lives till the call reply is completely
- * transmitted.
- * */
-struct rpcsvc_request {
- /* Connection over which this request came. */
- rpcsvc_conn_t *conn;
-
- /* The identifier for the call from client.
- * Needed to pair the reply with the call.
- */
- uint32_t xid;
-
- int prognum;
-
- int progver;
-
- int procnum;
- /* Uid and gid filled by the rpc-auth module during the authentication
- * phase.
- */
- uid_t uid;
- gid_t gid;
-
- /* Might want to move this to AUTH_UNIX specifix state since this array
- * is not available for every authenticatino scheme.
- */
- gid_t auxgids[NGRPS];
- int auxgidcount;
-
-
- /* The RPC message payload, contains the data required
- * by the program actors. This is the buffer that will need to
- * be de-xdred by the actor.
- */
- struct iovec msg;
-
- /* The full message buffer allocated to store the RPC headers.
- * This buffer is ref'd when allocated why RPC svc and unref'd after
- * the buffer is handed to the actor. That means if the actor or any
- * higher layer wants to keep this buffer around, they too must ref it
- * right after entering the program actor.
- */
- struct iobuf *recordiob;
-
- /* Status of the RPC call, whether it was accepted or denied. */
- int rpc_stat;
-
- /* In case, the call was denied, the RPC error is stored here
- * till the reply is sent.
- */
- int rpc_err;
-
- /* In case the failure happened because of an authentication problem
- * , this value needs to be assigned the correct auth error number.
- */
- int auth_err;
-
- /* There can be cases of RPC requests where the reply needs to
- * be built from multiple sources. For eg. where even the NFS reply can
- * contain a payload, as in the NFSv3 read reply. Here the RPC header
- * ,NFS header and the read data are brought together separately from
- * different buffers, so we need to stage the buffers temporarily here
- * before all of them get added to the connection's transmission list.
- */
- struct list_head txlist;
-
- /* While the reply record is being built, this variable keeps track
- * of how many bytes have been added to the record.
- */
- size_t payloadsize;
-
- /* The credentials extracted from the rpc request */
- rpcsvc_auth_data_t cred;
-
- /* The verified extracted from the rpc request. In request side
- * processing this contains the verifier sent by the client, on reply
- * side processing, it is filled with the verified that will be
- * sent to the client.
- */
- rpcsvc_auth_data_t verf;
-
- /* Container for a RPC program wanting to store a temp
- * request-specific item.
- */
- void *private;
-
-};
-
-#define rpcsvc_request_program(req) ((rpcsvc_program_t *)((req)->conn->program))
-#define rpcsvc_request_program_private(req) (((rpcsvc_program_t *)((req)->conn->program))->private)
-#define rpcsvc_request_conn(req) (req)->conn
-#define rpcsvc_request_accepted(req) ((req)->rpc_stat == MSG_ACCEPTED)
-#define rpcsvc_request_accepted_success(req) ((req)->rpc_err == SUCCESS)
-#define rpcsvc_request_uid(req) ((req)->uid)
-#define rpcsvc_request_gid(req) ((req)->gid)
-#define rpcsvc_stage_service(stg) ((rpcsvc_t *)((stg)->svc))
-#define rpcsvc_conn_stage(conn) ((conn)->stage)
-#define rpcsvc_request_service(req) (rpcsvc_stage_service(rpcsvc_conn_stage(rpcsvc_request_conn(req))))
-#define rpcsvc_request_prog_minauth(req) (rpcsvc_request_program(req)->min_auth)
-#define rpcsvc_request_cred_flavour(req) (rpcsvc_auth_flavour(req->cred))
-#define rpcsvc_request_verf_flavour(req) (rpcsvc_auth_flavour(req->verf))
-
-#define rpcsvc_request_uid(req) ((req)->uid)
-#define rpcsvc_request_gid(req) ((req)->gid)
-#define rpcsvc_request_private(req) ((req)->private)
-#define rpcsvc_request_xid(req) ((req)->xid)
-#define rpcsvc_request_set_private(req,prv) (req)->private = (void *)(prv)
-#define rpcsvc_request_record_iob(rq) ((rq)->recordiob)
-#define rpcsvc_request_record_ref(req) (iobuf_ref ((req)->recordiob))
-#define rpcsvc_request_record_unref(req) (iobuf_unref ((req)->recordiob))
-
-
-#define RPCSVC_ACTOR_SUCCESS 0
-#define RPCSVC_ACTOR_ERROR (-1)
-
-/* Functor for every type of protocol actor
- * must be defined like this.
- *
- * See the request structure for info on how to handle the request
- * in the program actor.
- *
- * On successful santify checks inside the actor, it should return
- * RPCSVC_ACTOR_SUCCESS.
- * On an error, on which the RPC layer is expected to return a reply, the actor
- * should return RPCSVC_ACTOR_ERROR.
- *
- */
-typedef int (*rpcsvc_actor) (rpcsvc_request_t *req);
-typedef int (*rpcsvc_vector_actor) (rpcsvc_request_t *req, struct iobuf *iob);
-typedef int (*rpcsvc_vector_sizer) (rpcsvc_request_t *req, ssize_t *readsize,
- int *newiob);
-
-/* Every protocol actor will also need to specify the function the RPC layer
- * will use to serialize or encode the message into XDR format just before
- * transmitting on the connection.
- */
-typedef void *(*rpcsvc_encode_reply) (void *msg);
-
-/* Once the reply has been transmitted, the message will have to be de-allocated
- * , so every actor will need to provide a function that deallocates the message
- * it had allocated as a response.
- */
-typedef void (*rpcsvc_deallocate_reply) (void *msg);
-
-
-#define RPCSVC_NAME_MAX 32
-/* The descriptor for each procedure/actor that runs
- * over the RPC service.
- */
-typedef struct rpc_svc_actor_desc {
- char procname[RPCSVC_NAME_MAX];
- int procnum;
- rpcsvc_actor actor;
-
- /* Handler for cases where the RPC requests fragments are large enough
- * to benefit from being decoded into aligned memory addresses. While
- * decoding the request in a non-vectored manner, due to the nature of
- * the XDR scheme, RPC cannot guarantee memory aligned addresses for
- * the resulting message-specific structures. Allowing a specialized
- * handler for letting the RPC program read the data from the network
- * directly into its alligned buffers.
- */
- rpcsvc_vector_actor vector_actor;
- rpcsvc_vector_sizer vector_sizer;
-
-} rpcsvc_actor_t;
-
-typedef int (*rpcsvc_conn_notify_fn) (void *progpriv, rpcsvc_conn_t *conn);
-
-/* Describes a program and its version along with the function pointers
- * required to handle the procedures/actors of each program/version.
- * Never changed ever by any thread so no need for a lock.
- */
-struct rpc_svc_program {
- char progname[RPCSVC_NAME_MAX];
- int prognum;
- int progver;
- uint16_t progport; /* Registered with portmap */
- int progaddrfamily; /* AF_INET or AF_INET6 */
- char *proghost; /* Bind host, can be NULL */
- rpcsvc_actor_t *actors; /* All procedure handlers */
- int numactors; /* Num actors in actor array */
- int proghighvers; /* Highest ver for program
- supported by the system. */
- int proglowvers; /* Lowest ver */
-
- /* Program specific state handed to actors */
- void *private;
-
- /* This upcall is made when a connection's refcount reaches 0 and the
- * connection is about to be destroyed. We want to let the RPC program
- * know that it should also now free any state it is maintaining
- * for this connection.
- */
- rpcsvc_conn_notify_fn conn_destroy;
-
- /* Used to tell RPC program to init the state it needs to associate
- * with the new connection.
- */
- rpcsvc_conn_notify_fn conn_init;
-
- /* An integer that identifies the min auth strength that is required
- * by this protocol, for eg. MOUNT3 needs AUTH_UNIX at least.
- * See RFC 1813, Section 5.2.1.
- */
- int min_auth;
-};
-
-
-/* Contains global state required for all the RPC services.
- */
-typedef struct rpc_svc_state {
-
- /* Contains the list of rpcsvc_stage_t
- * list of (program, version) handlers.
- * other options.
- */
-
- /* At this point, lock is not used to protect anything. Later, it'll
- * be used for protecting stages.
- */
- pthread_mutex_t rpclock;
-
- /* This is the first stage that is inited, so that any RPC based
- * services that do not need multi-threaded support can just use the
- * service right away. This is not added to the stages list
- * declared later.
- * This is also the stage over which all service listeners are run.
- */
- rpcsvc_stage_t *defaultstage;
-
- /* When we have multi-threaded RPC support, we'll use this to link
- * to the multiple Stages.
- */
- struct list_head stages; /* All stages */
-
- unsigned int memfactor;
-
- /* List of the authentication schemes available. */
- struct list_head authschemes;
-
- /* Reference to the options */
- dict_t *options;
-
- /* Allow insecure ports. */
- int allow_insecure;
-
- glusterfs_ctx_t *ctx;
-} rpcsvc_t;
-
-
-/* All users of RPC services should use this API to register their
- * procedure handlers.
- */
-extern int
-rpcsvc_program_register (rpcsvc_t *svc, rpcsvc_program_t program);
-
-extern int
-rpcsvc_program_unregister (rpcsvc_t *svc, rpcsvc_program_t program);
-
-/* Inits the global RPC service data structures.
- * Called in main.
- */
-extern rpcsvc_t *
-rpcsvc_init (glusterfs_ctx_t *ctx, dict_t *options);
-
-
-extern int
-rpcsvc_submit_message (rpcsvc_request_t * req, struct iovec msg,
- struct iobuf *iob);
-
-int
-rpcsvc_submit_generic (rpcsvc_request_t *req, struct iovec msgvec,
- struct iobuf *msg);
-#define rpcsvc_record_currentfrag_addr(rs) ((rs)->fragcurrent)
-#define rpcsvc_record_currenthdr_addr(rs) ((rs)->hdrcurrent)
-
-#define rpcsvc_record_update_currentfrag(rs, size) \
- do { \
- (rs)->fragcurrent += size; \
- } while (0) \
-
-#define rpcsvc_record_update_currenthdr(rs, size) \
- do { \
- (rs)->hdrcurrent += size; \
- } while (0) \
-
-
-/* These are used to differentiate between multiple txbufs which form
- * a single RPC record. For eg, one purpose we use these for is to
- * prevent dividing a RPC record over multiple TCP segments. Multiple
- * TCP segments are possible for a single RPC record because we generally do not
- * have control over how the kernel's TCP segments the buffers when putting
- * them on the wire. So, on Linux, we use these to set TCP_CORK to create
- * a single TCP segment from multiple txbufs that are part of the same RPC
- * record. This improves network performance by reducing tiny message
- * transmissions.
- */
-#define RPCSVC_TXB_FIRST 0x1
-#define RPCSVC_TXB_LAST 0x2
-
-/* The list of buffers appended to a connection's pending
- * transmission list.
- */
-typedef struct rpcsvc_txbuf {
- struct list_head txlist;
- /* The iobuf which contains the full message to be transmitted */
- struct iobuf *iob;
-
- /* For vectored messages from an RPC program, we need to be able
- * maintain a ref to an iobuf which we do not have access to directly
- * except through the iobref which in turn could've been passed to
- * the RPC program by a higher layer.
- *
- * So either the iob is defined or iobref is defined for a reply,
- * never both.
- */
- struct iobref *iobref;
- /* In order to handle non-blocking writes, we'll need to keep track of
- * how much data from an iobuf has been written and where the next
- * transmission needs to start from. This iov.base points to the base of
- * the iobuf, iov.len is the size of iobuf being used for the message
- * from the total size in the iobuf.
- */
- struct iovec buf;
- /* offset is the point from where the next transmission for this buffer
- * should start.
- */
- size_t offset;
-
- /* This is a special field that tells us what kind of transmission
- * behaviour to provide to a particular buffer.
- * See the RPCSVC_TXB_* defines for more info.
- */
- int txbehave;
-} rpcsvc_txbuf_t;
-
-extern int
-rpcsvc_error_reply (rpcsvc_request_t *req);
-
-#define RPCSVC_PEER_STRLEN 1024
-#define RPCSVC_AUTH_ACCEPT 1
-#define RPCSVC_AUTH_REJECT 2
-#define RPCSVC_AUTH_DONTCARE 3
-
-extern int
-rpcsvc_conn_peername (rpcsvc_conn_t *conn, char *hostname, int hostlen);
-
-extern int
-rpcsvc_conn_peeraddr (rpcsvc_conn_t *conn, char *addrstr, int addrlen,
- struct sockaddr *returnsa, socklen_t sasize);
-
-extern int
-rpcsvc_conn_peer_check (dict_t *options, char *volname, rpcsvc_conn_t *conn);
-
-extern int
-rpcsvc_conn_privport_check (rpcsvc_t *svc, char *volname, rpcsvc_conn_t *conn);
-#define rpcsvc_request_seterr(req, err) (req)->rpc_err = err
-#define rpcsvc_request_set_autherr(req, err) (req)->auth_err = err
-
-extern void
-rpcsvc_conn_deinit (rpcsvc_conn_t *conn);
-extern void rpcsvc_conn_ref (rpcsvc_conn_t *conn);
-extern void rpcsvc_conn_unref (rpcsvc_conn_t *conn);
-
-extern int rpcsvc_submit_vectors (rpcsvc_request_t *req);
-
-extern int rpcsvc_request_attach_vector (rpcsvc_request_t *req,
- struct iovec msgvec, struct iobuf *iob,
- struct iobref *ioref, int finalvector);
-
-
-typedef int (*auth_init_conn) (rpcsvc_conn_t *conn, void *priv);
-typedef int (*auth_init_request) (rpcsvc_request_t *req, void *priv);
-typedef int (*auth_request_authenticate) (rpcsvc_request_t *req, void *priv);
-
-/* This structure needs to be registered by every authentication scheme.
- * Our authentication schemes are stored per connection because
- * each connection will end up using a different authentication scheme.
- */
-typedef struct rpcsvc_auth_ops {
- auth_init_conn conn_init;
- auth_init_request request_init;
- auth_request_authenticate authenticate;
-} rpcsvc_auth_ops_t;
-
-typedef struct rpcsvc_auth_flavour_desc {
- char authname[RPCSVC_NAME_MAX];
- int authnum;
- rpcsvc_auth_ops_t *authops;
- void *authprivate;
-} rpcsvc_auth_t;
-
-typedef void * (*rpcsvc_auth_initer_t) (rpcsvc_t *svc, dict_t *options);
-
-struct rpcsvc_auth_list {
- struct list_head authlist;
- rpcsvc_auth_initer_t init;
- /* Should be the name with which we identify the auth scheme given
- * in the volfile options.
- * This should be different from the authname in rpc_auth_t
- * in way that makes it easier to specify this scheme in the volfile.
- * This is because the technical names of the schemes can be a bit
- * arcane.
- */
- char name[RPCSVC_NAME_MAX];
- rpcsvc_auth_t *auth;
- int enable;
-};
-
-extern int
-rpcsvc_auth_request_init (rpcsvc_request_t *req);
-
-extern int
-rpcsvc_auth_init (rpcsvc_t *svc, dict_t *options);
-
-extern int
-rpcsvc_auth_conn_init (rpcsvc_conn_t *conn);
-
-extern int
-rpcsvc_authenticate (rpcsvc_request_t *req);
-
-extern int
-rpcsvc_auth_array (rpcsvc_t *svc, char *volname, int *autharr, int arrlen);
-
-/* If the request has been sent using AUTH_UNIX, this function returns the
- * auxiliary gids as an array, otherwise, it returns NULL.
- * Move to auth-unix specific source file when we need to modularize the
- * authentication code even further to support mode auth schemes.
- */
-extern gid_t *
-rpcsvc_auth_unix_auxgids (rpcsvc_request_t *req, int *arrlen);
-
-extern int
-rpcsvc_combine_gen_spec_volume_checks (int gen, int spec);
-
-extern char *
-rpcsvc_volume_allowed (dict_t *options, char *volname);
-#endif
diff --git a/xlators/nfs/lib/src/xdr-common.h b/xlators/nfs/lib/src/xdr-common.h
deleted file mode 100644
index 50a57ade9..000000000
--- a/xlators/nfs/lib/src/xdr-common.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
- This file is part of GlusterFS.
-
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _XDR_COMMON_H_
-#define _XDR_COMMON_H_
-
-#ifndef _CONFIG_H
-#define _CONFIG_H
-#include "config.h"
-#endif
-
-#include <rpc/rpc.h>
-#define XDR_BYTES_PER_UNIT 4
-
-/* Returns the address of the byte that follows the
- * last byte used for decoding the previous xdr component.
- * For eg, once the RPC call for NFS has been decoded, thie macro will return
- * the address from which the NFS header starts.
- */
-#define xdr_decoded_remaining_addr(xdr) ((&xdr)->x_private)
-
-/* Returns the length of the remaining record after the previous decode
- * operation completed.
- */
-#define xdr_decoded_remaining_len(xdr) ((&xdr)->x_handy)
-
-/* Returns the number of bytes used by the last encode operation. */
-#define xdr_encoded_length(xdr) (((size_t)(&xdr)->x_private) - ((size_t)(&xdr)->x_base))
-
-#define xdr_decoded_length(xdr) (((size_t)(&xdr)->x_private) - ((size_t)(&xdr)->x_base))
-
-#endif
diff --git a/xlators/nfs/lib/src/xdr-nfs3.c b/xlators/nfs/lib/src/xdr-nfs3.c
deleted file mode 100644
index 7d8075a56..000000000
--- a/xlators/nfs/lib/src/xdr-nfs3.c
+++ /dev/null
@@ -1,1892 +0,0 @@
-/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
- This file is part of GlusterFS.
-
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
-*/
-
-#include "xdr-nfs3.h"
-#include "mem-pool.h"
-
-bool_t
-xdr_uint64 (XDR *xdrs, uint64 *objp)
-{
- if (!xdr_u_quad_t (xdrs, objp))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_int64 (XDR *xdrs, int64 *objp)
-{
- if (!xdr_quad_t (xdrs, objp))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_uint32 (XDR *xdrs, uint32 *objp)
-{
- if (!xdr_uint32_t (xdrs, objp))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_int32 (XDR *xdrs, int32 *objp)
-{
- if (!xdr_int32_t (xdrs, objp))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_filename3 (XDR *xdrs, filename3 *objp)
-{
- if (!xdr_string (xdrs, objp, ~0))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_nfspath3 (XDR *xdrs, nfspath3 *objp)
-{
- if (!xdr_string (xdrs, objp, ~0))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_fileid3 (XDR *xdrs, fileid3 *objp)
-{
- if (!xdr_uint64 (xdrs, objp))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_cookie3 (XDR *xdrs, cookie3 *objp)
-{
- if (!xdr_uint64 (xdrs, objp))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_cookieverf3 (XDR *xdrs, cookieverf3 objp)
-{
- if (!xdr_opaque (xdrs, objp, NFS3_COOKIEVERFSIZE))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_createverf3 (XDR *xdrs, createverf3 objp)
-{
- if (!xdr_opaque (xdrs, objp, NFS3_CREATEVERFSIZE))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_writeverf3 (XDR *xdrs, writeverf3 objp)
-{
- if (!xdr_opaque (xdrs, objp, NFS3_WRITEVERFSIZE))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_uid3 (XDR *xdrs, uid3 *objp)
-{
- if (!xdr_uint32 (xdrs, objp))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_gid3 (XDR *xdrs, gid3 *objp)
-{
- if (!xdr_uint32 (xdrs, objp))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_size3 (XDR *xdrs, size3 *objp)
-{
- if (!xdr_uint64 (xdrs, objp))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_offset3 (XDR *xdrs, offset3 *objp)
-{
- if (!xdr_uint64 (xdrs, objp))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_mode3 (XDR *xdrs, mode3 *objp)
-{
- if (!xdr_uint32 (xdrs, objp))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_count3 (XDR *xdrs, count3 *objp)
-{
- if (!xdr_uint32 (xdrs, objp))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_nfsstat3 (XDR *xdrs, nfsstat3 *objp)
-{
- if (!xdr_enum (xdrs, (enum_t *) objp))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_ftype3 (XDR *xdrs, ftype3 *objp)
-{
- if (!xdr_enum (xdrs, (enum_t *) objp))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_specdata3 (XDR *xdrs, specdata3 *objp)
-{
- if (!xdr_uint32 (xdrs, &objp->specdata1))
- return FALSE;
- if (!xdr_uint32 (xdrs, &objp->specdata2))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_nfs_fh3 (XDR *xdrs, nfs_fh3 *objp)
-{
- if (!xdr_bytes (xdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, NFS3_FHSIZE))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_nfstime3 (XDR *xdrs, nfstime3 *objp)
-{
- if (!xdr_uint32 (xdrs, &objp->seconds))
- return FALSE;
- if (!xdr_uint32 (xdrs, &objp->nseconds))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_fattr3 (XDR *xdrs, fattr3 *objp)
-{
- if (!xdr_ftype3 (xdrs, &objp->type))
- return FALSE;
- if (!xdr_mode3 (xdrs, &objp->mode))
- return FALSE;
- if (!xdr_uint32 (xdrs, &objp->nlink))
- return FALSE;
- if (!xdr_uid3 (xdrs, &objp->uid))
- return FALSE;
- if (!xdr_gid3 (xdrs, &objp->gid))
- return FALSE;
- if (!xdr_size3 (xdrs, &objp->size))
- return FALSE;
- if (!xdr_size3 (xdrs, &objp->used))
- return FALSE;
- if (!xdr_specdata3 (xdrs, &objp->rdev))
- return FALSE;
- if (!xdr_uint64 (xdrs, &objp->fsid))
- return FALSE;
- if (!xdr_fileid3 (xdrs, &objp->fileid))
- return FALSE;
- if (!xdr_nfstime3 (xdrs, &objp->atime))
- return FALSE;
- if (!xdr_nfstime3 (xdrs, &objp->mtime))
- return FALSE;
- if (!xdr_nfstime3 (xdrs, &objp->ctime))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_post_op_attr (XDR *xdrs, post_op_attr *objp)
-{
- if (!xdr_bool (xdrs, &objp->attributes_follow))
- return FALSE;
- switch (objp->attributes_follow) {
- case TRUE:
- if (!xdr_fattr3 (xdrs, &objp->post_op_attr_u.attributes))
- return FALSE;
- break;
- case FALSE:
- break;
- default:
- return FALSE;
- }
- return TRUE;
-}
-
-bool_t
-xdr_wcc_attr (XDR *xdrs, wcc_attr *objp)
-{
- if (!xdr_size3 (xdrs, &objp->size))
- return FALSE;
- if (!xdr_nfstime3 (xdrs, &objp->mtime))
- return FALSE;
- if (!xdr_nfstime3 (xdrs, &objp->ctime))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_pre_op_attr (XDR *xdrs, pre_op_attr *objp)
-{
- if (!xdr_bool (xdrs, &objp->attributes_follow))
- return FALSE;
- switch (objp->attributes_follow) {
- case TRUE:
- if (!xdr_wcc_attr (xdrs, &objp->pre_op_attr_u.attributes))
- return FALSE;
- break;
- case FALSE:
- break;
- default:
- return FALSE;
- }
- return TRUE;
-}
-
-bool_t
-xdr_wcc_data (XDR *xdrs, wcc_data *objp)
-{
- if (!xdr_pre_op_attr (xdrs, &objp->before))
- return FALSE;
- if (!xdr_post_op_attr (xdrs, &objp->after))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_post_op_fh3 (XDR *xdrs, post_op_fh3 *objp)
-{
- if (!xdr_bool (xdrs, &objp->handle_follows))
- return FALSE;
- switch (objp->handle_follows) {
- case TRUE:
- if (!xdr_nfs_fh3 (xdrs, &objp->post_op_fh3_u.handle))
- return FALSE;
- break;
- case FALSE:
- break;
- default:
- return FALSE;
- }
- return TRUE;
-}
-
-bool_t
-xdr_time_how (XDR *xdrs, time_how *objp)
-{
- if (!xdr_enum (xdrs, (enum_t *) objp))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_set_mode3 (XDR *xdrs, set_mode3 *objp)
-{
- if (!xdr_bool (xdrs, &objp->set_it))
- return FALSE;
- switch (objp->set_it) {
- case TRUE:
- if (!xdr_mode3 (xdrs, &objp->set_mode3_u.mode))
- return FALSE;
- break;
- default:
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_set_uid3 (XDR *xdrs, set_uid3 *objp)
-{
- if (!xdr_bool (xdrs, &objp->set_it))
- return FALSE;
- switch (objp->set_it) {
- case TRUE:
- if (!xdr_uid3 (xdrs, &objp->set_uid3_u.uid))
- return FALSE;
- break;
- default:
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_set_gid3 (XDR *xdrs, set_gid3 *objp)
-{
- if (!xdr_bool (xdrs, &objp->set_it))
- return FALSE;
- switch (objp->set_it) {
- case TRUE:
- if (!xdr_gid3 (xdrs, &objp->set_gid3_u.gid))
- return FALSE;
- break;
- default:
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_set_size3 (XDR *xdrs, set_size3 *objp)
-{
- if (!xdr_bool (xdrs, &objp->set_it))
- return FALSE;
- switch (objp->set_it) {
- case TRUE:
- if (!xdr_size3 (xdrs, &objp->set_size3_u.size))
- return FALSE;
- break;
- default:
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_set_atime (XDR *xdrs, set_atime *objp)
-{
- if (!xdr_time_how (xdrs, &objp->set_it))
- return FALSE;
- switch (objp->set_it) {
- case SET_TO_CLIENT_TIME:
- if (!xdr_nfstime3 (xdrs, &objp->set_atime_u.atime))
- return FALSE;
- break;
- default:
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_set_mtime (XDR *xdrs, set_mtime *objp)
-{
- if (!xdr_time_how (xdrs, &objp->set_it))
- return FALSE;
- switch (objp->set_it) {
- case SET_TO_CLIENT_TIME:
- if (!xdr_nfstime3 (xdrs, &objp->set_mtime_u.mtime))
- return FALSE;
- break;
- default:
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_sattr3 (XDR *xdrs, sattr3 *objp)
-{
- if (!xdr_set_mode3 (xdrs, &objp->mode))
- return FALSE;
- if (!xdr_set_uid3 (xdrs, &objp->uid))
- return FALSE;
- if (!xdr_set_gid3 (xdrs, &objp->gid))
- return FALSE;
- if (!xdr_set_size3 (xdrs, &objp->size))
- return FALSE;
- if (!xdr_set_atime (xdrs, &objp->atime))
- return FALSE;
- if (!xdr_set_mtime (xdrs, &objp->mtime))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_diropargs3 (XDR *xdrs, diropargs3 *objp)
-{
- if (!xdr_nfs_fh3 (xdrs, &objp->dir))
- return FALSE;
- if (!xdr_filename3 (xdrs, &objp->name))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_getattr3args (XDR *xdrs, getattr3args *objp)
-{
- if (!xdr_nfs_fh3 (xdrs, &objp->object))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_getattr3resok (XDR *xdrs, getattr3resok *objp)
-{
- if (!xdr_fattr3 (xdrs, &objp->obj_attributes))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_getattr3res (XDR *xdrs, getattr3res *objp)
-{
- if (!xdr_nfsstat3 (xdrs, &objp->status))
- return FALSE;
- switch (objp->status) {
- case NFS3_OK:
- if (!xdr_getattr3resok (xdrs, &objp->getattr3res_u.resok))
- return FALSE;
- break;
- default:
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_sattrguard3 (XDR *xdrs, sattrguard3 *objp)
-{
- if (!xdr_bool (xdrs, &objp->check))
- return FALSE;
- switch (objp->check) {
- case TRUE:
- if (!xdr_nfstime3 (xdrs, &objp->sattrguard3_u.obj_ctime))
- return FALSE;
- break;
- case FALSE:
- break;
- default:
- return FALSE;
- }
- return TRUE;
-}
-
-bool_t
-xdr_setattr3args (XDR *xdrs, setattr3args *objp)
-{
- if (!xdr_nfs_fh3 (xdrs, &objp->object))
- return FALSE;
- if (!xdr_sattr3 (xdrs, &objp->new_attributes))
- return FALSE;
- if (!xdr_sattrguard3 (xdrs, &objp->guard))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_setattr3resok (XDR *xdrs, setattr3resok *objp)
-{
- if (!xdr_wcc_data (xdrs, &objp->obj_wcc))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_setattr3resfail (XDR *xdrs, setattr3resfail *objp)
-{
- if (!xdr_wcc_data (xdrs, &objp->obj_wcc))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_setattr3res (XDR *xdrs, setattr3res *objp)
-{
- if (!xdr_nfsstat3 (xdrs, &objp->status))
- return FALSE;
- switch (objp->status) {
- case NFS3_OK:
- if (!xdr_setattr3resok (xdrs, &objp->setattr3res_u.resok))
- return FALSE;
- break;
- default:
- if (!xdr_setattr3resfail (xdrs, &objp->setattr3res_u.resfail))
- return FALSE;
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_lookup3args (XDR *xdrs, lookup3args *objp)
-{
- if (!xdr_diropargs3 (xdrs, &objp->what))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_lookup3resok (XDR *xdrs, lookup3resok *objp)
-{
- if (!xdr_nfs_fh3 (xdrs, &objp->object))
- return FALSE;
- if (!xdr_post_op_attr (xdrs, &objp->obj_attributes))
- return FALSE;
- if (!xdr_post_op_attr (xdrs, &objp->dir_attributes))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_lookup3resfail (XDR *xdrs, lookup3resfail *objp)
-{
- if (!xdr_post_op_attr (xdrs, &objp->dir_attributes))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_lookup3res (XDR *xdrs, lookup3res *objp)
-{
- if (!xdr_nfsstat3 (xdrs, &objp->status))
- return FALSE;
- switch (objp->status) {
- case NFS3_OK:
- if (!xdr_lookup3resok (xdrs, &objp->lookup3res_u.resok))
- return FALSE;
- break;
- default:
- if (!xdr_lookup3resfail (xdrs, &objp->lookup3res_u.resfail))
- return FALSE;
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_access3args (XDR *xdrs, access3args *objp)
-{
- if (!xdr_nfs_fh3 (xdrs, &objp->object))
- return FALSE;
- if (!xdr_uint32 (xdrs, &objp->access))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_access3resok (XDR *xdrs, access3resok *objp)
-{
- if (!xdr_post_op_attr (xdrs, &objp->obj_attributes))
- return FALSE;
- if (!xdr_uint32 (xdrs, &objp->access))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_access3resfail (XDR *xdrs, access3resfail *objp)
-{
- if (!xdr_post_op_attr (xdrs, &objp->obj_attributes))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_access3res (XDR *xdrs, access3res *objp)
-{
- if (!xdr_nfsstat3 (xdrs, &objp->status))
- return FALSE;
- switch (objp->status) {
- case NFS3_OK:
- if (!xdr_access3resok (xdrs, &objp->access3res_u.resok))
- return FALSE;
- break;
- default:
- if (!xdr_access3resfail (xdrs, &objp->access3res_u.resfail))
- return FALSE;
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_readlink3args (XDR *xdrs, readlink3args *objp)
-{
- if (!xdr_nfs_fh3 (xdrs, &objp->symlink))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_readlink3resok (XDR *xdrs, readlink3resok *objp)
-{
- if (!xdr_post_op_attr (xdrs, &objp->symlink_attributes))
- return FALSE;
- if (!xdr_nfspath3 (xdrs, &objp->data))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_readlink3resfail (XDR *xdrs, readlink3resfail *objp)
-{
- if (!xdr_post_op_attr (xdrs, &objp->symlink_attributes))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_readlink3res (XDR *xdrs, readlink3res *objp)
-{
- if (!xdr_nfsstat3 (xdrs, &objp->status))
- return FALSE;
- switch (objp->status) {
- case NFS3_OK:
- if (!xdr_readlink3resok (xdrs, &objp->readlink3res_u.resok))
- return FALSE;
- break;
- default:
- if (!xdr_readlink3resfail (xdrs, &objp->readlink3res_u.resfail))
- return FALSE;
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_read3args (XDR *xdrs, read3args *objp)
-{
- if (!xdr_nfs_fh3 (xdrs, &objp->file))
- return FALSE;
- if (!xdr_offset3 (xdrs, &objp->offset))
- return FALSE;
- if (!xdr_count3 (xdrs, &objp->count))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_read3resok_nocopy (XDR *xdrs, read3resok *objp)
-{
- if (!xdr_post_op_attr (xdrs, &objp->file_attributes))
- return FALSE;
- if (!xdr_count3 (xdrs, &objp->count))
- return FALSE;
- if (!xdr_bool (xdrs, &objp->eof))
- return FALSE;
- if (!xdr_u_int (xdrs, (u_int *) &objp->data.data_len))
- return FALSE;
- return TRUE;
-}
-
-
-bool_t
-xdr_read3resok (XDR *xdrs, read3resok *objp)
-{
- if (!xdr_post_op_attr (xdrs, &objp->file_attributes))
- return FALSE;
- if (!xdr_count3 (xdrs, &objp->count))
- return FALSE;
- if (!xdr_bool (xdrs, &objp->eof))
- return FALSE;
- if (!xdr_bytes (xdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, ~0))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_read3resfail (XDR *xdrs, read3resfail *objp)
-{
- if (!xdr_post_op_attr (xdrs, &objp->file_attributes))
- return FALSE;
- return TRUE;
-}
-
-
-bool_t
-xdr_read3res_nocopy (XDR *xdrs, read3res *objp)
-{
- if (!xdr_nfsstat3 (xdrs, &objp->status))
- return FALSE;
- switch (objp->status) {
- case NFS3_OK:
- if (!xdr_read3resok_nocopy (xdrs, &objp->read3res_u.resok))
- return FALSE;
- break;
- default:
- if (!xdr_read3resfail (xdrs, &objp->read3res_u.resfail))
- return FALSE;
- break;
- }
- return TRUE;
-}
-
-
-bool_t
-xdr_read3res (XDR *xdrs, read3res *objp)
-{
- if (!xdr_nfsstat3 (xdrs, &objp->status))
- return FALSE;
- switch (objp->status) {
- case NFS3_OK:
- if (!xdr_read3resok (xdrs, &objp->read3res_u.resok))
- return FALSE;
- break;
- default:
- if (!xdr_read3resfail (xdrs, &objp->read3res_u.resfail))
- return FALSE;
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_stable_how (XDR *xdrs, stable_how *objp)
-{
- if (!xdr_enum (xdrs, (enum_t *) objp))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_write3args (XDR *xdrs, write3args *objp)
-{
- if (!xdr_nfs_fh3 (xdrs, &objp->file))
- return FALSE;
- if (!xdr_offset3 (xdrs, &objp->offset))
- return FALSE;
- if (!xdr_count3 (xdrs, &objp->count))
- return FALSE;
- if (!xdr_stable_how (xdrs, &objp->stable))
- return FALSE;
-
- /* Added specifically to avoid copies from the xdr buffer into
- * the write3args structure, which will also require an already
- * allocated buffer. That is not optimal.
- */
- if (!xdr_u_int (xdrs, (u_int *) &objp->data.data_len))
- return FALSE;
-
- /* The remaining bytes in the xdr buffer are the bytes that need to be
- * written. See how these bytes are extracted in the xdr_to_write3args
- * code path. Be careful, while using the write3args structure, since
- * only the data.data_len has been filled. The actual data is
- * extracted in xdr_to_write3args path.
- */
-
- /* if (!xdr_bytes (xdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, ~0))
- return FALSE;
- */
- return TRUE;
-}
-
-bool_t
-xdr_write3resok (XDR *xdrs, write3resok *objp)
-{
- if (!xdr_wcc_data (xdrs, &objp->file_wcc))
- return FALSE;
- if (!xdr_count3 (xdrs, &objp->count))
- return FALSE;
- if (!xdr_stable_how (xdrs, &objp->committed))
- return FALSE;
- if (!xdr_writeverf3 (xdrs, objp->verf))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_write3resfail (XDR *xdrs, write3resfail *objp)
-{
- if (!xdr_wcc_data (xdrs, &objp->file_wcc))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_write3res (XDR *xdrs, write3res *objp)
-{
- if (!xdr_nfsstat3 (xdrs, &objp->status))
- return FALSE;
- switch (objp->status) {
- case NFS3_OK:
- if (!xdr_write3resok (xdrs, &objp->write3res_u.resok))
- return FALSE;
- break;
- default:
- if (!xdr_write3resfail (xdrs, &objp->write3res_u.resfail))
- return FALSE;
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_createmode3 (XDR *xdrs, createmode3 *objp)
-{
- if (!xdr_enum (xdrs, (enum_t *) objp))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_createhow3 (XDR *xdrs, createhow3 *objp)
-{
- if (!xdr_createmode3 (xdrs, &objp->mode))
- return FALSE;
- switch (objp->mode) {
- case UNCHECKED:
- case GUARDED:
- if (!xdr_sattr3 (xdrs, &objp->createhow3_u.obj_attributes))
- return FALSE;
- break;
- case EXCLUSIVE:
- if (!xdr_createverf3 (xdrs, objp->createhow3_u.verf))
- return FALSE;
- break;
- default:
- return FALSE;
- }
- return TRUE;
-}
-
-bool_t
-xdr_create3args (XDR *xdrs, create3args *objp)
-{
- if (!xdr_diropargs3 (xdrs, &objp->where))
- return FALSE;
- if (!xdr_createhow3 (xdrs, &objp->how))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_create3resok (XDR *xdrs, create3resok *objp)
-{
- if (!xdr_post_op_fh3 (xdrs, &objp->obj))
- return FALSE;
- if (!xdr_post_op_attr (xdrs, &objp->obj_attributes))
- return FALSE;
- if (!xdr_wcc_data (xdrs, &objp->dir_wcc))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_create3resfail (XDR *xdrs, create3resfail *objp)
-{
- if (!xdr_wcc_data (xdrs, &objp->dir_wcc))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_create3res (XDR *xdrs, create3res *objp)
-{
- if (!xdr_nfsstat3 (xdrs, &objp->status))
- return FALSE;
- switch (objp->status) {
- case NFS3_OK:
- if (!xdr_create3resok (xdrs, &objp->create3res_u.resok))
- return FALSE;
- break;
- default:
- if (!xdr_create3resfail (xdrs, &objp->create3res_u.resfail))
- return FALSE;
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_mkdir3args (XDR *xdrs, mkdir3args *objp)
-{
- if (!xdr_diropargs3 (xdrs, &objp->where))
- return FALSE;
- if (!xdr_sattr3 (xdrs, &objp->attributes))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_mkdir3resok (XDR *xdrs, mkdir3resok *objp)
-{
- if (!xdr_post_op_fh3 (xdrs, &objp->obj))
- return FALSE;
- if (!xdr_post_op_attr (xdrs, &objp->obj_attributes))
- return FALSE;
- if (!xdr_wcc_data (xdrs, &objp->dir_wcc))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_mkdir3resfail (XDR *xdrs, mkdir3resfail *objp)
-{
- if (!xdr_wcc_data (xdrs, &objp->dir_wcc))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_mkdir3res (XDR *xdrs, mkdir3res *objp)
-{
- if (!xdr_nfsstat3 (xdrs, &objp->status))
- return FALSE;
- switch (objp->status) {
- case NFS3_OK:
- if (!xdr_mkdir3resok (xdrs, &objp->mkdir3res_u.resok))
- return FALSE;
- break;
- default:
- if (!xdr_mkdir3resfail (xdrs, &objp->mkdir3res_u.resfail))
- return FALSE;
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_symlinkdata3 (XDR *xdrs, symlinkdata3 *objp)
-{
- if (!xdr_sattr3 (xdrs, &objp->symlink_attributes))
- return FALSE;
- if (!xdr_nfspath3 (xdrs, &objp->symlink_data))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_symlink3args (XDR *xdrs, symlink3args *objp)
-{
- if (!xdr_diropargs3 (xdrs, &objp->where))
- return FALSE;
- if (!xdr_symlinkdata3 (xdrs, &objp->symlink))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_symlink3resok (XDR *xdrs, symlink3resok *objp)
-{
- if (!xdr_post_op_fh3 (xdrs, &objp->obj))
- return FALSE;
- if (!xdr_post_op_attr (xdrs, &objp->obj_attributes))
- return FALSE;
- if (!xdr_wcc_data (xdrs, &objp->dir_wcc))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_symlink3resfail (XDR *xdrs, symlink3resfail *objp)
-{
- if (!xdr_wcc_data (xdrs, &objp->dir_wcc))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_symlink3res (XDR *xdrs, symlink3res *objp)
-{
- if (!xdr_nfsstat3 (xdrs, &objp->status))
- return FALSE;
- switch (objp->status) {
- case NFS3_OK:
- if (!xdr_symlink3resok (xdrs, &objp->symlink3res_u.resok))
- return FALSE;
- break;
- default:
- if (!xdr_symlink3resfail (xdrs, &objp->symlink3res_u.resfail))
- return FALSE;
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_devicedata3 (XDR *xdrs, devicedata3 *objp)
-{
- if (!xdr_sattr3 (xdrs, &objp->dev_attributes))
- return FALSE;
- if (!xdr_specdata3 (xdrs, &objp->spec))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_mknoddata3 (XDR *xdrs, mknoddata3 *objp)
-{
- if (!xdr_ftype3 (xdrs, &objp->type))
- return FALSE;
- switch (objp->type) {
- case NF3CHR:
- case NF3BLK:
- if (!xdr_devicedata3 (xdrs, &objp->mknoddata3_u.device))
- return FALSE;
- break;
- case NF3SOCK:
- case NF3FIFO:
- if (!xdr_sattr3 (xdrs, &objp->mknoddata3_u.pipe_attributes))
- return FALSE;
- break;
- default:
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_mknod3args (XDR *xdrs, mknod3args *objp)
-{
- if (!xdr_diropargs3 (xdrs, &objp->where))
- return FALSE;
- if (!xdr_mknoddata3 (xdrs, &objp->what))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_mknod3resok (XDR *xdrs, mknod3resok *objp)
-{
- if (!xdr_post_op_fh3 (xdrs, &objp->obj))
- return FALSE;
- if (!xdr_post_op_attr (xdrs, &objp->obj_attributes))
- return FALSE;
- if (!xdr_wcc_data (xdrs, &objp->dir_wcc))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_mknod3resfail (XDR *xdrs, mknod3resfail *objp)
-{
- if (!xdr_wcc_data (xdrs, &objp->dir_wcc))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_mknod3res (XDR *xdrs, mknod3res *objp)
-{
- if (!xdr_nfsstat3 (xdrs, &objp->status))
- return FALSE;
- switch (objp->status) {
- case NFS3_OK:
- if (!xdr_mknod3resok (xdrs, &objp->mknod3res_u.resok))
- return FALSE;
- break;
- default:
- if (!xdr_mknod3resfail (xdrs, &objp->mknod3res_u.resfail))
- return FALSE;
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_remove3args (XDR *xdrs, remove3args *objp)
-{
- if (!xdr_diropargs3 (xdrs, &objp->object))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_remove3resok (XDR *xdrs, remove3resok *objp)
-{
- if (!xdr_wcc_data (xdrs, &objp->dir_wcc))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_remove3resfail (XDR *xdrs, remove3resfail *objp)
-{
- if (!xdr_wcc_data (xdrs, &objp->dir_wcc))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_remove3res (XDR *xdrs, remove3res *objp)
-{
- if (!xdr_nfsstat3 (xdrs, &objp->status))
- return FALSE;
- switch (objp->status) {
- case NFS3_OK:
- if (!xdr_remove3resok (xdrs, &objp->remove3res_u.resok))
- return FALSE;
- break;
- default:
- if (!xdr_remove3resfail (xdrs, &objp->remove3res_u.resfail))
- return FALSE;
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_rmdir3args (XDR *xdrs, rmdir3args *objp)
-{
- if (!xdr_diropargs3 (xdrs, &objp->object))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_rmdir3resok (XDR *xdrs, rmdir3resok *objp)
-{
- if (!xdr_wcc_data (xdrs, &objp->dir_wcc))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_rmdir3resfail (XDR *xdrs, rmdir3resfail *objp)
-{
- if (!xdr_wcc_data (xdrs, &objp->dir_wcc))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_rmdir3res (XDR *xdrs, rmdir3res *objp)
-{
- if (!xdr_nfsstat3 (xdrs, &objp->status))
- return FALSE;
- switch (objp->status) {
- case NFS3_OK:
- if (!xdr_rmdir3resok (xdrs, &objp->rmdir3res_u.resok))
- return FALSE;
- break;
- default:
- if (!xdr_rmdir3resfail (xdrs, &objp->rmdir3res_u.resfail))
- return FALSE;
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_rename3args (XDR *xdrs, rename3args *objp)
-{
- if (!xdr_diropargs3 (xdrs, &objp->from))
- return FALSE;
- if (!xdr_diropargs3 (xdrs, &objp->to))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_rename3resok (XDR *xdrs, rename3resok *objp)
-{
- if (!xdr_wcc_data (xdrs, &objp->fromdir_wcc))
- return FALSE;
- if (!xdr_wcc_data (xdrs, &objp->todir_wcc))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_rename3resfail (XDR *xdrs, rename3resfail *objp)
-{
- if (!xdr_wcc_data (xdrs, &objp->fromdir_wcc))
- return FALSE;
- if (!xdr_wcc_data (xdrs, &objp->todir_wcc))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_rename3res (XDR *xdrs, rename3res *objp)
-{
- if (!xdr_nfsstat3 (xdrs, &objp->status))
- return FALSE;
- switch (objp->status) {
- case NFS3_OK:
- if (!xdr_rename3resok (xdrs, &objp->rename3res_u.resok))
- return FALSE;
- break;
- default:
- if (!xdr_rename3resfail (xdrs, &objp->rename3res_u.resfail))
- return FALSE;
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_link3args (XDR *xdrs, link3args *objp)
-{
- if (!xdr_nfs_fh3 (xdrs, &objp->file))
- return FALSE;
- if (!xdr_diropargs3 (xdrs, &objp->link))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_link3resok (XDR *xdrs, link3resok *objp)
-{
- if (!xdr_post_op_attr (xdrs, &objp->file_attributes))
- return FALSE;
- if (!xdr_wcc_data (xdrs, &objp->linkdir_wcc))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_link3resfail (XDR *xdrs, link3resfail *objp)
-{
- if (!xdr_post_op_attr (xdrs, &objp->file_attributes))
- return FALSE;
- if (!xdr_wcc_data (xdrs, &objp->linkdir_wcc))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_link3res (XDR *xdrs, link3res *objp)
-{
- if (!xdr_nfsstat3 (xdrs, &objp->status))
- return FALSE;
- switch (objp->status) {
- case NFS3_OK:
- if (!xdr_link3resok (xdrs, &objp->link3res_u.resok))
- return FALSE;
- break;
- default:
- if (!xdr_link3resfail (xdrs, &objp->link3res_u.resfail))
- return FALSE;
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_readdir3args (XDR *xdrs, readdir3args *objp)
-{
- if (!xdr_nfs_fh3 (xdrs, &objp->dir))
- return FALSE;
- if (!xdr_cookie3 (xdrs, &objp->cookie))
- return FALSE;
- if (!xdr_cookieverf3 (xdrs, objp->cookieverf))
- return FALSE;
- if (!xdr_count3 (xdrs, &objp->count))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_entry3 (XDR *xdrs, entry3 *objp)
-{
- if (!xdr_fileid3 (xdrs, &objp->fileid))
- return FALSE;
- if (!xdr_filename3 (xdrs, &objp->name))
- return FALSE;
- if (!xdr_cookie3 (xdrs, &objp->cookie))
- return FALSE;
- if (!xdr_pointer (xdrs, (char **)&objp->nextentry, sizeof (entry3), (xdrproc_t) xdr_entry3))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_dirlist3 (XDR *xdrs, dirlist3 *objp)
-{
- if (!xdr_pointer (xdrs, (char **)&objp->entries, sizeof (entry3), (xdrproc_t) xdr_entry3))
- return FALSE;
- if (!xdr_bool (xdrs, &objp->eof))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_readdir3resok (XDR *xdrs, readdir3resok *objp)
-{
- if (!xdr_post_op_attr (xdrs, &objp->dir_attributes))
- return FALSE;
- if (!xdr_cookieverf3 (xdrs, objp->cookieverf))
- return FALSE;
- if (!xdr_dirlist3 (xdrs, &objp->reply))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_readdir3resfail (XDR *xdrs, readdir3resfail *objp)
-{
- if (!xdr_post_op_attr (xdrs, &objp->dir_attributes))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_readdir3res (XDR *xdrs, readdir3res *objp)
-{
- if (!xdr_nfsstat3 (xdrs, &objp->status))
- return FALSE;
- switch (objp->status) {
- case NFS3_OK:
- if (!xdr_readdir3resok (xdrs, &objp->readdir3res_u.resok))
- return FALSE;
- break;
- default:
- if (!xdr_readdir3resfail (xdrs, &objp->readdir3res_u.resfail))
- return FALSE;
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_readdirp3args (XDR *xdrs, readdirp3args *objp)
-{
- if (!xdr_nfs_fh3 (xdrs, &objp->dir))
- return FALSE;
- if (!xdr_cookie3 (xdrs, &objp->cookie))
- return FALSE;
- if (!xdr_cookieverf3 (xdrs, objp->cookieverf))
- return FALSE;
- if (!xdr_count3 (xdrs, &objp->dircount))
- return FALSE;
- if (!xdr_count3 (xdrs, &objp->maxcount))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_entryp3 (XDR *xdrs, entryp3 *objp)
-{
- if (!xdr_fileid3 (xdrs, &objp->fileid))
- return FALSE;
- if (!xdr_filename3 (xdrs, &objp->name))
- return FALSE;
- if (!xdr_cookie3 (xdrs, &objp->cookie))
- return FALSE;
- if (!xdr_post_op_attr (xdrs, &objp->name_attributes))
- return FALSE;
- if (!xdr_post_op_fh3 (xdrs, &objp->name_handle))
- return FALSE;
- if (!xdr_pointer (xdrs, (char **)&objp->nextentry, sizeof (entryp3), (xdrproc_t) xdr_entryp3))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_dirlistp3 (XDR *xdrs, dirlistp3 *objp)
-{
- if (!xdr_pointer (xdrs, (char **)&objp->entries, sizeof (entryp3), (xdrproc_t) xdr_entryp3))
- return FALSE;
- if (!xdr_bool (xdrs, &objp->eof))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_readdirp3resok (XDR *xdrs, readdirp3resok *objp)
-{
- if (!xdr_post_op_attr (xdrs, &objp->dir_attributes))
- return FALSE;
- if (!xdr_cookieverf3 (xdrs, objp->cookieverf))
- return FALSE;
- if (!xdr_dirlistp3 (xdrs, &objp->reply))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_readdirp3resfail (XDR *xdrs, readdirp3resfail *objp)
-{
- if (!xdr_post_op_attr (xdrs, &objp->dir_attributes))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_readdirp3res (XDR *xdrs, readdirp3res *objp)
-{
- if (!xdr_nfsstat3 (xdrs, &objp->status))
- return FALSE;
- switch (objp->status) {
- case NFS3_OK:
- if (!xdr_readdirp3resok (xdrs, &objp->readdirp3res_u.resok))
- return FALSE;
- break;
- default:
- if (!xdr_readdirp3resfail (xdrs, &objp->readdirp3res_u.resfail))
- return FALSE;
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_fsstat3args (XDR *xdrs, fsstat3args *objp)
-{
- if (!xdr_nfs_fh3 (xdrs, &objp->fsroot))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_fsstat3resok (XDR *xdrs, fsstat3resok *objp)
-{
- if (!xdr_post_op_attr (xdrs, &objp->obj_attributes))
- return FALSE;
- if (!xdr_size3 (xdrs, &objp->tbytes))
- return FALSE;
- if (!xdr_size3 (xdrs, &objp->fbytes))
- return FALSE;
- if (!xdr_size3 (xdrs, &objp->abytes))
- return FALSE;
- if (!xdr_size3 (xdrs, &objp->tfiles))
- return FALSE;
- if (!xdr_size3 (xdrs, &objp->ffiles))
- return FALSE;
- if (!xdr_size3 (xdrs, &objp->afiles))
- return FALSE;
- if (!xdr_uint32 (xdrs, &objp->invarsec))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_fsstat3resfail (XDR *xdrs, fsstat3resfail *objp)
-{
- if (!xdr_post_op_attr (xdrs, &objp->obj_attributes))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_fsstat3res (XDR *xdrs, fsstat3res *objp)
-{
- if (!xdr_nfsstat3 (xdrs, &objp->status))
- return FALSE;
- switch (objp->status) {
- case NFS3_OK:
- if (!xdr_fsstat3resok (xdrs, &objp->fsstat3res_u.resok))
- return FALSE;
- break;
- default:
- if (!xdr_fsstat3resfail (xdrs, &objp->fsstat3res_u.resfail))
- return FALSE;
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_fsinfo3args (XDR *xdrs, fsinfo3args *objp)
-{
- if (!xdr_nfs_fh3 (xdrs, &objp->fsroot))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_fsinfo3resok (XDR *xdrs, fsinfo3resok *objp)
-{
- if (!xdr_post_op_attr (xdrs, &objp->obj_attributes))
- return FALSE;
- if (!xdr_uint32 (xdrs, &objp->rtmax))
- return FALSE;
- if (!xdr_uint32 (xdrs, &objp->rtpref))
- return FALSE;
- if (!xdr_uint32 (xdrs, &objp->rtmult))
- return FALSE;
- if (!xdr_uint32 (xdrs, &objp->wtmax))
- return FALSE;
- if (!xdr_uint32 (xdrs, &objp->wtpref))
- return FALSE;
- if (!xdr_uint32 (xdrs, &objp->wtmult))
- return FALSE;
- if (!xdr_uint32 (xdrs, &objp->dtpref))
- return FALSE;
- if (!xdr_size3 (xdrs, &objp->maxfilesize))
- return FALSE;
- if (!xdr_nfstime3 (xdrs, &objp->time_delta))
- return FALSE;
- if (!xdr_uint32 (xdrs, &objp->properties))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_fsinfo3resfail (XDR *xdrs, fsinfo3resfail *objp)
-{
- if (!xdr_post_op_attr (xdrs, &objp->obj_attributes))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_fsinfo3res (XDR *xdrs, fsinfo3res *objp)
-{
- if (!xdr_nfsstat3 (xdrs, &objp->status))
- return FALSE;
- switch (objp->status) {
- case NFS3_OK:
- if (!xdr_fsinfo3resok (xdrs, &objp->fsinfo3res_u.resok))
- return FALSE;
- break;
- default:
- if (!xdr_fsinfo3resfail (xdrs, &objp->fsinfo3res_u.resfail))
- return FALSE;
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_pathconf3args (XDR *xdrs, pathconf3args *objp)
-{
- if (!xdr_nfs_fh3 (xdrs, &objp->object))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_pathconf3resok (XDR *xdrs, pathconf3resok *objp)
-{
- register int32_t *buf;
-
-
- if (xdrs->x_op == XDR_ENCODE) {
- if (!xdr_post_op_attr (xdrs, &objp->obj_attributes))
- return FALSE;
- if (!xdr_uint32 (xdrs, &objp->linkmax))
- return FALSE;
- if (!xdr_uint32 (xdrs, &objp->name_max))
- return FALSE;
- buf = XDR_INLINE (xdrs, 4 * BYTES_PER_XDR_UNIT);
- if (buf == NULL) {
- if (!xdr_bool (xdrs, &objp->no_trunc))
- return FALSE;
- if (!xdr_bool (xdrs, &objp->chown_restricted))
- return FALSE;
- if (!xdr_bool (xdrs, &objp->case_insensitive))
- return FALSE;
- if (!xdr_bool (xdrs, &objp->case_preserving))
- return FALSE;
- } else {
- IXDR_PUT_BOOL(buf, objp->no_trunc);
- IXDR_PUT_BOOL(buf, objp->chown_restricted);
- IXDR_PUT_BOOL(buf, objp->case_insensitive);
- IXDR_PUT_BOOL(buf, objp->case_preserving);
- }
- return TRUE;
- } else if (xdrs->x_op == XDR_DECODE) {
- if (!xdr_post_op_attr (xdrs, &objp->obj_attributes))
- return FALSE;
- if (!xdr_uint32 (xdrs, &objp->linkmax))
- return FALSE;
- if (!xdr_uint32 (xdrs, &objp->name_max))
- return FALSE;
- buf = XDR_INLINE (xdrs, 4 * BYTES_PER_XDR_UNIT);
- if (buf == NULL) {
- if (!xdr_bool (xdrs, &objp->no_trunc))
- return FALSE;
- if (!xdr_bool (xdrs, &objp->chown_restricted))
- return FALSE;
- if (!xdr_bool (xdrs, &objp->case_insensitive))
- return FALSE;
- if (!xdr_bool (xdrs, &objp->case_preserving))
- return FALSE;
- } else {
- objp->no_trunc = IXDR_GET_BOOL(buf);
- objp->chown_restricted = IXDR_GET_BOOL(buf);
- objp->case_insensitive = IXDR_GET_BOOL(buf);
- objp->case_preserving = IXDR_GET_BOOL(buf);
- }
- return TRUE;
- }
-
- if (!xdr_post_op_attr (xdrs, &objp->obj_attributes))
- return FALSE;
- if (!xdr_uint32 (xdrs, &objp->linkmax))
- return FALSE;
- if (!xdr_uint32 (xdrs, &objp->name_max))
- return FALSE;
- if (!xdr_bool (xdrs, &objp->no_trunc))
- return FALSE;
- if (!xdr_bool (xdrs, &objp->chown_restricted))
- return FALSE;
- if (!xdr_bool (xdrs, &objp->case_insensitive))
- return FALSE;
- if (!xdr_bool (xdrs, &objp->case_preserving))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_pathconf3resfail (XDR *xdrs, pathconf3resfail *objp)
-{
- if (!xdr_post_op_attr (xdrs, &objp->obj_attributes))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_pathconf3res (XDR *xdrs, pathconf3res *objp)
-{
- if (!xdr_nfsstat3 (xdrs, &objp->status))
- return FALSE;
- switch (objp->status) {
- case NFS3_OK:
- if (!xdr_pathconf3resok (xdrs, &objp->pathconf3res_u.resok))
- return FALSE;
- break;
- default:
- if (!xdr_pathconf3resfail (xdrs, &objp->pathconf3res_u.resfail))
- return FALSE;
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_commit3args (XDR *xdrs, commit3args *objp)
-{
- if (!xdr_nfs_fh3 (xdrs, &objp->file))
- return FALSE;
- if (!xdr_offset3 (xdrs, &objp->offset))
- return FALSE;
- if (!xdr_count3 (xdrs, &objp->count))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_commit3resok (XDR *xdrs, commit3resok *objp)
-{
- if (!xdr_wcc_data (xdrs, &objp->file_wcc))
- return FALSE;
- if (!xdr_writeverf3 (xdrs, objp->verf))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_commit3resfail (XDR *xdrs, commit3resfail *objp)
-{
- if (!xdr_wcc_data (xdrs, &objp->file_wcc))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_commit3res (XDR *xdrs, commit3res *objp)
-{
- if (!xdr_nfsstat3 (xdrs, &objp->status))
- return FALSE;
- switch (objp->status) {
- case NFS3_OK:
- if (!xdr_commit3resok (xdrs, &objp->commit3res_u.resok))
- return FALSE;
- break;
- default:
- if (!xdr_commit3resfail (xdrs, &objp->commit3res_u.resfail))
- return FALSE;
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_fhandle3 (XDR *xdrs, fhandle3 *objp)
-{
- if (!xdr_bytes (xdrs, (char **)&objp->fhandle3_val, (u_int *) &objp->fhandle3_len, FHSIZE3))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_dirpath (XDR *xdrs, dirpath *objp)
-{
- if (!xdr_string (xdrs, objp, MNTPATHLEN))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_name (XDR *xdrs, name *objp)
-{
- if (!xdr_string (xdrs, objp, MNTNAMLEN))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_mountstat3 (XDR *xdrs, mountstat3 *objp)
-{
- if (!xdr_enum (xdrs, (enum_t *) objp))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_mountres3_ok (XDR *xdrs, mountres3_ok *objp)
-{
- if (!xdr_fhandle3 (xdrs, &objp->fhandle))
- return FALSE;
- if (!xdr_array (xdrs, (char **)&objp->auth_flavors.auth_flavors_val, (u_int *) &objp->auth_flavors.auth_flavors_len, ~0,
- sizeof (int), (xdrproc_t) xdr_int))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_mountres3 (XDR *xdrs, mountres3 *objp)
-{
- if (!xdr_mountstat3 (xdrs, &objp->fhs_status))
- return FALSE;
- switch (objp->fhs_status) {
- case MNT3_OK:
- if (!xdr_mountres3_ok (xdrs, &objp->mountres3_u.mountinfo))
- return FALSE;
- break;
- default:
- break;
- }
- return TRUE;
-}
-
-bool_t
-xdr_mountlist (XDR *xdrs, mountlist *objp)
-{
- if (!xdr_pointer (xdrs, (char **)objp, sizeof (struct mountbody), (xdrproc_t) xdr_mountbody))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_mountbody (XDR *xdrs, mountbody *objp)
-{
- if (!xdr_name (xdrs, &objp->ml_hostname))
- return FALSE;
- if (!xdr_dirpath (xdrs, &objp->ml_directory))
- return FALSE;
- if (!xdr_mountlist (xdrs, &objp->ml_next))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_groups (XDR *xdrs, groups *objp)
-{
- if (!xdr_pointer (xdrs, (char **)objp, sizeof (struct groupnode), (xdrproc_t) xdr_groupnode))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_groupnode (XDR *xdrs, groupnode *objp)
-{
- if (!xdr_name (xdrs, &objp->gr_name))
- return FALSE;
- if (!xdr_groups (xdrs, &objp->gr_next))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_exports (XDR *xdrs, exports *objp)
-{
- if (!xdr_pointer (xdrs, (char **)objp, sizeof (struct exportnode), (xdrproc_t) xdr_exportnode))
- return FALSE;
- return TRUE;
-}
-
-bool_t
-xdr_exportnode (XDR *xdrs, exportnode *objp)
-{
- if (!xdr_dirpath (xdrs, &objp->ex_dir))
- return FALSE;
- if (!xdr_groups (xdrs, &objp->ex_groups))
- return FALSE;
- if (!xdr_exports (xdrs, &objp->ex_next))
- return FALSE;
- return TRUE;
-}
-
-void
-xdr_free_exports_list (struct exportnode *first)
-{
- struct exportnode *elist = NULL;
-
- if (!first)
- return;
-
- while (first) {
- elist = first->ex_next;
- if (first->ex_dir)
- FREE (first->ex_dir);
-
- if (first->ex_groups) {
- if (first->ex_groups->gr_name)
- FREE (first->ex_groups->gr_name);
- FREE (first->ex_groups);
- }
-
- FREE (first);
- first = elist;
- }
-
-}
-
-
-void
-xdr_free_mountlist (mountlist ml)
-{
- struct mountbody *next = NULL;
-
- if (!ml)
- return;
-
- while (ml) {
- FREE (ml->ml_hostname);
- FREE (ml->ml_directory);
- next = ml->ml_next;
- FREE (ml);
- ml = next;
- }
-
- return;
-}
-
-
-/* Free statements are based on the way sunrpc xdr decoding
- * code performs memory allocations.
- */
-void
-xdr_free_write3args_nocopy (write3args *wa)
-{
- if (!wa)
- return;
-
- FREE (wa->file.data.data_val);
- FREE (wa);
-}
-
-
diff --git a/xlators/nfs/lib/src/xdr-nfs3.h b/xlators/nfs/lib/src/xdr-nfs3.h
deleted file mode 100644
index fe4046584..000000000
--- a/xlators/nfs/lib/src/xdr-nfs3.h
+++ /dev/null
@@ -1,1205 +0,0 @@
-/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
- This file is part of GlusterFS.
-
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _XDR_NFS3_H
-#define _XDR_NFS3_H
-
-#include <rpc/rpc.h>
-
-#define NFS3_FHSIZE 64
-#define NFS3_COOKIEVERFSIZE 8
-#define NFS3_CREATEVERFSIZE 8
-#define NFS3_WRITEVERFSIZE 8
-
-#define NFS3_ENTRY3_FIXED_SIZE 24
-#define NFS3_POSTOPATTR_SIZE 88
-#define NFS3_READDIR_RESOK_SIZE (NFS3_POSTOPATTR_SIZE + sizeof (bool_t) + NFS3_COOKIEVERFSIZE)
-
-/* In size of post_op_fh3, the length of the file handle will have to be
- * included separately since we have variable length fh. Here we only account
- * for the field for handle_follows and for the file handle length field.
- */
-#define NFS3_POSTOPFH3_FIXED_SIZE (sizeof (bool_t) + sizeof (uint32_t))
-
-/* Similarly, the size of the entry will have to include the variable length
- * file handle and the length of the entry name.
- */
-#define NFS3_ENTRYP3_FIXED_SIZE (NFS3_ENTRY3_FIXED_SIZE + NFS3_POSTOPATTR_SIZE + NFS3_POSTOPFH3_FIXED_SIZE)
-
-typedef u_quad_t uint64;
-typedef quad_t int64;
-typedef uint32_t uint32;
-typedef int32_t int32;
-typedef char *filename3;
-typedef char *nfspath3;
-typedef uint64 fileid3;
-typedef uint64 cookie3;
-typedef char cookieverf3[NFS3_COOKIEVERFSIZE];
-typedef char createverf3[NFS3_CREATEVERFSIZE];
-typedef char writeverf3[NFS3_WRITEVERFSIZE];
-typedef uint32 uid3;
-typedef uint32 gid3;
-typedef uint64 size3;
-typedef uint64 offset3;
-typedef uint32 mode3;
-typedef uint32 count3;
-
-#define NFS3MODE_SETXUID 0x00800
-#define NFS3MODE_SETXGID 0x00400
-#define NFS3MODE_SAVESWAPTXT 0x00200
-#define NFS3MODE_ROWNER 0x00100
-#define NFS3MODE_WOWNER 0x00080
-#define NFS3MODE_XOWNER 0x00040
-#define NFS3MODE_RGROUP 0x00020
-#define NFS3MODE_WGROUP 0x00010
-#define NFS3MODE_XGROUP 0x00008
-#define NFS3MODE_ROTHER 0x00004
-#define NFS3MODE_WOTHER 0x00002
-#define NFS3MODE_XOTHER 0x00001
-
-enum nfsstat3 {
- NFS3_OK = 0,
- NFS3ERR_PERM = 1,
- NFS3ERR_NOENT = 2,
- NFS3ERR_IO = 5,
- NFS3ERR_NXIO = 6,
- NFS3ERR_ACCES = 13,
- NFS3ERR_EXIST = 17,
- NFS3ERR_XDEV = 18,
- NFS3ERR_NODEV = 19,
- NFS3ERR_NOTDIR = 20,
- NFS3ERR_ISDIR = 21,
- NFS3ERR_INVAL = 22,
- NFS3ERR_FBIG = 27,
- NFS3ERR_NOSPC = 28,
- NFS3ERR_ROFS = 30,
- NFS3ERR_MLINK = 31,
- NFS3ERR_NAMETOOLONG = 63,
- NFS3ERR_NOTEMPTY = 66,
- NFS3ERR_DQUOT = 69,
- NFS3ERR_STALE = 70,
- NFS3ERR_REMOTE = 71,
- NFS3ERR_BADHANDLE = 10001,
- NFS3ERR_NOT_SYNC = 10002,
- NFS3ERR_BAD_COOKIE = 10003,
- NFS3ERR_NOTSUPP = 10004,
- NFS3ERR_TOOSMALL = 10005,
- NFS3ERR_SERVERFAULT = 10006,
- NFS3ERR_BADTYPE = 10007,
- NFS3ERR_JUKEBOX = 10008,
-};
-typedef enum nfsstat3 nfsstat3;
-
-enum ftype3 {
- NF3REG = 1,
- NF3DIR = 2,
- NF3BLK = 3,
- NF3CHR = 4,
- NF3LNK = 5,
- NF3SOCK = 6,
- NF3FIFO = 7,
-};
-typedef enum ftype3 ftype3;
-
-struct specdata3 {
- uint32 specdata1;
- uint32 specdata2;
-};
-typedef struct specdata3 specdata3;
-
-struct nfs_fh3 {
- struct {
- u_int data_len;
- char *data_val;
- } data;
-};
-typedef struct nfs_fh3 nfs_fh3;
-
-struct nfstime3 {
- uint32 seconds;
- uint32 nseconds;
-};
-typedef struct nfstime3 nfstime3;
-
-struct fattr3 {
- ftype3 type;
- mode3 mode;
- uint32 nlink;
- uid3 uid;
- gid3 gid;
- size3 size;
- size3 used;
- specdata3 rdev;
- uint64 fsid;
- fileid3 fileid;
- nfstime3 atime;
- nfstime3 mtime;
- nfstime3 ctime;
-};
-typedef struct fattr3 fattr3;
-
-struct post_op_attr {
- bool_t attributes_follow;
- union {
- fattr3 attributes;
- } post_op_attr_u;
-};
-typedef struct post_op_attr post_op_attr;
-
-struct wcc_attr {
- size3 size;
- nfstime3 mtime;
- nfstime3 ctime;
-};
-typedef struct wcc_attr wcc_attr;
-
-struct pre_op_attr {
- bool_t attributes_follow;
- union {
- wcc_attr attributes;
- } pre_op_attr_u;
-};
-typedef struct pre_op_attr pre_op_attr;
-
-struct wcc_data {
- pre_op_attr before;
- post_op_attr after;
-};
-typedef struct wcc_data wcc_data;
-
-struct post_op_fh3 {
- bool_t handle_follows;
- union {
- nfs_fh3 handle;
- } post_op_fh3_u;
-};
-typedef struct post_op_fh3 post_op_fh3;
-
-enum time_how {
- DONT_CHANGE = 0,
- SET_TO_SERVER_TIME = 1,
- SET_TO_CLIENT_TIME = 2,
-};
-typedef enum time_how time_how;
-
-struct set_mode3 {
- bool_t set_it;
- union {
- mode3 mode;
- } set_mode3_u;
-};
-typedef struct set_mode3 set_mode3;
-
-struct set_uid3 {
- bool_t set_it;
- union {
- uid3 uid;
- } set_uid3_u;
-};
-typedef struct set_uid3 set_uid3;
-
-struct set_gid3 {
- bool_t set_it;
- union {
- gid3 gid;
- } set_gid3_u;
-};
-typedef struct set_gid3 set_gid3;
-
-struct set_size3 {
- bool_t set_it;
- union {
- size3 size;
- } set_size3_u;
-};
-typedef struct set_size3 set_size3;
-
-struct set_atime {
- time_how set_it;
- union {
- nfstime3 atime;
- } set_atime_u;
-};
-typedef struct set_atime set_atime;
-
-struct set_mtime {
- time_how set_it;
- union {
- nfstime3 mtime;
- } set_mtime_u;
-};
-typedef struct set_mtime set_mtime;
-
-struct sattr3 {
- set_mode3 mode;
- set_uid3 uid;
- set_gid3 gid;
- set_size3 size;
- set_atime atime;
- set_mtime mtime;
-};
-typedef struct sattr3 sattr3;
-
-struct diropargs3 {
- nfs_fh3 dir;
- filename3 name;
-};
-typedef struct diropargs3 diropargs3;
-
-struct getattr3args {
- nfs_fh3 object;
-};
-typedef struct getattr3args getattr3args;
-
-struct getattr3resok {
- fattr3 obj_attributes;
-};
-typedef struct getattr3resok getattr3resok;
-
-struct getattr3res {
- nfsstat3 status;
- union {
- getattr3resok resok;
- } getattr3res_u;
-};
-typedef struct getattr3res getattr3res;
-
-struct sattrguard3 {
- bool_t check;
- union {
- nfstime3 obj_ctime;
- } sattrguard3_u;
-};
-typedef struct sattrguard3 sattrguard3;
-
-struct setattr3args {
- nfs_fh3 object;
- sattr3 new_attributes;
- sattrguard3 guard;
-};
-typedef struct setattr3args setattr3args;
-
-struct setattr3resok {
- wcc_data obj_wcc;
-};
-typedef struct setattr3resok setattr3resok;
-
-struct setattr3resfail {
- wcc_data obj_wcc;
-};
-typedef struct setattr3resfail setattr3resfail;
-
-struct setattr3res {
- nfsstat3 status;
- union {
- setattr3resok resok;
- setattr3resfail resfail;
- } setattr3res_u;
-};
-typedef struct setattr3res setattr3res;
-
-struct lookup3args {
- diropargs3 what;
-};
-typedef struct lookup3args lookup3args;
-
-struct lookup3resok {
- nfs_fh3 object;
- post_op_attr obj_attributes;
- post_op_attr dir_attributes;
-};
-typedef struct lookup3resok lookup3resok;
-
-struct lookup3resfail {
- post_op_attr dir_attributes;
-};
-typedef struct lookup3resfail lookup3resfail;
-
-struct lookup3res {
- nfsstat3 status;
- union {
- lookup3resok resok;
- lookup3resfail resfail;
- } lookup3res_u;
-};
-typedef struct lookup3res lookup3res;
-#define ACCESS3_READ 0x0001
-#define ACCESS3_LOOKUP 0x0002
-#define ACCESS3_MODIFY 0x0004
-#define ACCESS3_EXTEND 0x0008
-#define ACCESS3_DELETE 0x0010
-#define ACCESS3_EXECUTE 0x0020
-
-struct access3args {
- nfs_fh3 object;
- uint32 access;
-};
-typedef struct access3args access3args;
-
-struct access3resok {
- post_op_attr obj_attributes;
- uint32 access;
-};
-typedef struct access3resok access3resok;
-
-struct access3resfail {
- post_op_attr obj_attributes;
-};
-typedef struct access3resfail access3resfail;
-
-struct access3res {
- nfsstat3 status;
- union {
- access3resok resok;
- access3resfail resfail;
- } access3res_u;
-};
-typedef struct access3res access3res;
-
-struct readlink3args {
- nfs_fh3 symlink;
-};
-typedef struct readlink3args readlink3args;
-
-struct readlink3resok {
- post_op_attr symlink_attributes;
- nfspath3 data;
-};
-typedef struct readlink3resok readlink3resok;
-
-struct readlink3resfail {
- post_op_attr symlink_attributes;
-};
-typedef struct readlink3resfail readlink3resfail;
-
-struct readlink3res {
- nfsstat3 status;
- union {
- readlink3resok resok;
- readlink3resfail resfail;
- } readlink3res_u;
-};
-typedef struct readlink3res readlink3res;
-
-struct read3args {
- nfs_fh3 file;
- offset3 offset;
- count3 count;
-};
-typedef struct read3args read3args;
-
-struct read3resok {
- post_op_attr file_attributes;
- count3 count;
- bool_t eof;
- struct {
- u_int data_len;
- char *data_val;
- } data;
-};
-typedef struct read3resok read3resok;
-
-struct read3resfail {
- post_op_attr file_attributes;
-};
-typedef struct read3resfail read3resfail;
-
-struct read3res {
- nfsstat3 status;
- union {
- read3resok resok;
- read3resfail resfail;
- } read3res_u;
-};
-typedef struct read3res read3res;
-
-enum stable_how {
- UNSTABLE = 0,
- DATA_SYNC = 1,
- FILE_SYNC = 2,
-};
-typedef enum stable_how stable_how;
-
-struct write3args {
- nfs_fh3 file;
- offset3 offset;
- count3 count;
- stable_how stable;
- struct {
- u_int data_len;
- char *data_val;
- } data;
-};
-typedef struct write3args write3args;
-
-/* Generally, the protocol allows the file handle to be less than 64 bytes but
- * our server does not return file handles less than 64b so we can safely say
- * sizeof (nfs_fh3) rather than first trying to extract the fh size of the
- * network followed by a sized-read of the file handle.
- */
-#define NFS3_WRITE3ARGS_SIZE (sizeof (uint32_t) + NFS3_FHSIZE + sizeof (offset3) + sizeof (count3) + sizeof (uint32_t))
-struct write3resok {
- wcc_data file_wcc;
- count3 count;
- stable_how committed;
- writeverf3 verf;
-};
-typedef struct write3resok write3resok;
-
-struct write3resfail {
- wcc_data file_wcc;
-};
-typedef struct write3resfail write3resfail;
-
-struct write3res {
- nfsstat3 status;
- union {
- write3resok resok;
- write3resfail resfail;
- } write3res_u;
-};
-typedef struct write3res write3res;
-
-enum createmode3 {
- UNCHECKED = 0,
- GUARDED = 1,
- EXCLUSIVE = 2,
-};
-typedef enum createmode3 createmode3;
-
-struct createhow3 {
- createmode3 mode;
- union {
- sattr3 obj_attributes;
- createverf3 verf;
- } createhow3_u;
-};
-typedef struct createhow3 createhow3;
-
-struct create3args {
- diropargs3 where;
- createhow3 how;
-};
-typedef struct create3args create3args;
-
-struct create3resok {
- post_op_fh3 obj;
- post_op_attr obj_attributes;
- wcc_data dir_wcc;
-};
-typedef struct create3resok create3resok;
-
-struct create3resfail {
- wcc_data dir_wcc;
-};
-typedef struct create3resfail create3resfail;
-
-struct create3res {
- nfsstat3 status;
- union {
- create3resok resok;
- create3resfail resfail;
- } create3res_u;
-};
-typedef struct create3res create3res;
-
-struct mkdir3args {
- diropargs3 where;
- sattr3 attributes;
-};
-typedef struct mkdir3args mkdir3args;
-
-struct mkdir3resok {
- post_op_fh3 obj;
- post_op_attr obj_attributes;
- wcc_data dir_wcc;
-};
-typedef struct mkdir3resok mkdir3resok;
-
-struct mkdir3resfail {
- wcc_data dir_wcc;
-};
-typedef struct mkdir3resfail mkdir3resfail;
-
-struct mkdir3res {
- nfsstat3 status;
- union {
- mkdir3resok resok;
- mkdir3resfail resfail;
- } mkdir3res_u;
-};
-typedef struct mkdir3res mkdir3res;
-
-struct symlinkdata3 {
- sattr3 symlink_attributes;
- nfspath3 symlink_data;
-};
-typedef struct symlinkdata3 symlinkdata3;
-
-struct symlink3args {
- diropargs3 where;
- symlinkdata3 symlink;
-};
-typedef struct symlink3args symlink3args;
-
-struct symlink3resok {
- post_op_fh3 obj;
- post_op_attr obj_attributes;
- wcc_data dir_wcc;
-};
-typedef struct symlink3resok symlink3resok;
-
-struct symlink3resfail {
- wcc_data dir_wcc;
-};
-typedef struct symlink3resfail symlink3resfail;
-
-struct symlink3res {
- nfsstat3 status;
- union {
- symlink3resok resok;
- symlink3resfail resfail;
- } symlink3res_u;
-};
-typedef struct symlink3res symlink3res;
-
-struct devicedata3 {
- sattr3 dev_attributes;
- specdata3 spec;
-};
-typedef struct devicedata3 devicedata3;
-
-struct mknoddata3 {
- ftype3 type;
- union {
- devicedata3 device;
- sattr3 pipe_attributes;
- } mknoddata3_u;
-};
-typedef struct mknoddata3 mknoddata3;
-
-struct mknod3args {
- diropargs3 where;
- mknoddata3 what;
-};
-typedef struct mknod3args mknod3args;
-
-struct mknod3resok {
- post_op_fh3 obj;
- post_op_attr obj_attributes;
- wcc_data dir_wcc;
-};
-typedef struct mknod3resok mknod3resok;
-
-struct mknod3resfail {
- wcc_data dir_wcc;
-};
-typedef struct mknod3resfail mknod3resfail;
-
-struct mknod3res {
- nfsstat3 status;
- union {
- mknod3resok resok;
- mknod3resfail resfail;
- } mknod3res_u;
-};
-typedef struct mknod3res mknod3res;
-
-struct remove3args {
- diropargs3 object;
-};
-typedef struct remove3args remove3args;
-
-struct remove3resok {
- wcc_data dir_wcc;
-};
-typedef struct remove3resok remove3resok;
-
-struct remove3resfail {
- wcc_data dir_wcc;
-};
-typedef struct remove3resfail remove3resfail;
-
-struct remove3res {
- nfsstat3 status;
- union {
- remove3resok resok;
- remove3resfail resfail;
- } remove3res_u;
-};
-typedef struct remove3res remove3res;
-
-struct rmdir3args {
- diropargs3 object;
-};
-typedef struct rmdir3args rmdir3args;
-
-struct rmdir3resok {
- wcc_data dir_wcc;
-};
-typedef struct rmdir3resok rmdir3resok;
-
-struct rmdir3resfail {
- wcc_data dir_wcc;
-};
-typedef struct rmdir3resfail rmdir3resfail;
-
-struct rmdir3res {
- nfsstat3 status;
- union {
- rmdir3resok resok;
- rmdir3resfail resfail;
- } rmdir3res_u;
-};
-typedef struct rmdir3res rmdir3res;
-
-struct rename3args {
- diropargs3 from;
- diropargs3 to;
-};
-typedef struct rename3args rename3args;
-
-struct rename3resok {
- wcc_data fromdir_wcc;
- wcc_data todir_wcc;
-};
-typedef struct rename3resok rename3resok;
-
-struct rename3resfail {
- wcc_data fromdir_wcc;
- wcc_data todir_wcc;
-};
-typedef struct rename3resfail rename3resfail;
-
-struct rename3res {
- nfsstat3 status;
- union {
- rename3resok resok;
- rename3resfail resfail;
- } rename3res_u;
-};
-typedef struct rename3res rename3res;
-
-struct link3args {
- nfs_fh3 file;
- diropargs3 link;
-};
-typedef struct link3args link3args;
-
-struct link3resok {
- post_op_attr file_attributes;
- wcc_data linkdir_wcc;
-};
-typedef struct link3resok link3resok;
-
-struct link3resfail {
- post_op_attr file_attributes;
- wcc_data linkdir_wcc;
-};
-typedef struct link3resfail link3resfail;
-
-struct link3res {
- nfsstat3 status;
- union {
- link3resok resok;
- link3resfail resfail;
- } link3res_u;
-};
-typedef struct link3res link3res;
-
-struct readdir3args {
- nfs_fh3 dir;
- cookie3 cookie;
- cookieverf3 cookieverf;
- count3 count;
-};
-typedef struct readdir3args readdir3args;
-
-struct entry3 {
- fileid3 fileid;
- filename3 name;
- cookie3 cookie;
- struct entry3 *nextentry;
-};
-typedef struct entry3 entry3;
-
-struct dirlist3 {
- entry3 *entries;
- bool_t eof;
-};
-typedef struct dirlist3 dirlist3;
-
-struct readdir3resok {
- post_op_attr dir_attributes;
- cookieverf3 cookieverf;
- dirlist3 reply;
-};
-typedef struct readdir3resok readdir3resok;
-
-struct readdir3resfail {
- post_op_attr dir_attributes;
-};
-typedef struct readdir3resfail readdir3resfail;
-
-struct readdir3res {
- nfsstat3 status;
- union {
- readdir3resok resok;
- readdir3resfail resfail;
- } readdir3res_u;
-};
-typedef struct readdir3res readdir3res;
-
-struct readdirp3args {
- nfs_fh3 dir;
- cookie3 cookie;
- cookieverf3 cookieverf;
- count3 dircount;
- count3 maxcount;
-};
-typedef struct readdirp3args readdirp3args;
-
-struct entryp3 {
- fileid3 fileid;
- filename3 name;
- cookie3 cookie;
- post_op_attr name_attributes;
- post_op_fh3 name_handle;
- struct entryp3 *nextentry;
-};
-typedef struct entryp3 entryp3;
-
-struct dirlistp3 {
- entryp3 *entries;
- bool_t eof;
-};
-typedef struct dirlistp3 dirlistp3;
-
-struct readdirp3resok {
- post_op_attr dir_attributes;
- cookieverf3 cookieverf;
- dirlistp3 reply;
-};
-typedef struct readdirp3resok readdirp3resok;
-
-struct readdirp3resfail {
- post_op_attr dir_attributes;
-};
-typedef struct readdirp3resfail readdirp3resfail;
-
-struct readdirp3res {
- nfsstat3 status;
- union {
- readdirp3resok resok;
- readdirp3resfail resfail;
- } readdirp3res_u;
-};
-typedef struct readdirp3res readdirp3res;
-
-struct fsstat3args {
- nfs_fh3 fsroot;
-};
-typedef struct fsstat3args fsstat3args;
-
-struct fsstat3resok {
- post_op_attr obj_attributes;
- size3 tbytes;
- size3 fbytes;
- size3 abytes;
- size3 tfiles;
- size3 ffiles;
- size3 afiles;
- uint32 invarsec;
-};
-typedef struct fsstat3resok fsstat3resok;
-
-struct fsstat3resfail {
- post_op_attr obj_attributes;
-};
-typedef struct fsstat3resfail fsstat3resfail;
-
-struct fsstat3res {
- nfsstat3 status;
- union {
- fsstat3resok resok;
- fsstat3resfail resfail;
- } fsstat3res_u;
-};
-typedef struct fsstat3res fsstat3res;
-#define FSF3_LINK 0x0001
-#define FSF3_SYMLINK 0x0002
-#define FSF3_HOMOGENEOUS 0x0008
-#define FSF3_CANSETTIME 0x0010
-
-struct fsinfo3args {
- nfs_fh3 fsroot;
-};
-typedef struct fsinfo3args fsinfo3args;
-
-struct fsinfo3resok {
- post_op_attr obj_attributes;
- uint32 rtmax;
- uint32 rtpref;
- uint32 rtmult;
- uint32 wtmax;
- uint32 wtpref;
- uint32 wtmult;
- uint32 dtpref;
- size3 maxfilesize;
- nfstime3 time_delta;
- uint32 properties;
-};
-typedef struct fsinfo3resok fsinfo3resok;
-
-struct fsinfo3resfail {
- post_op_attr obj_attributes;
-};
-typedef struct fsinfo3resfail fsinfo3resfail;
-
-struct fsinfo3res {
- nfsstat3 status;
- union {
- fsinfo3resok resok;
- fsinfo3resfail resfail;
- } fsinfo3res_u;
-};
-typedef struct fsinfo3res fsinfo3res;
-
-struct pathconf3args {
- nfs_fh3 object;
-};
-typedef struct pathconf3args pathconf3args;
-
-struct pathconf3resok {
- post_op_attr obj_attributes;
- uint32 linkmax;
- uint32 name_max;
- bool_t no_trunc;
- bool_t chown_restricted;
- bool_t case_insensitive;
- bool_t case_preserving;
-};
-typedef struct pathconf3resok pathconf3resok;
-
-struct pathconf3resfail {
- post_op_attr obj_attributes;
-};
-typedef struct pathconf3resfail pathconf3resfail;
-
-struct pathconf3res {
- nfsstat3 status;
- union {
- pathconf3resok resok;
- pathconf3resfail resfail;
- } pathconf3res_u;
-};
-typedef struct pathconf3res pathconf3res;
-
-struct commit3args {
- nfs_fh3 file;
- offset3 offset;
- count3 count;
-};
-typedef struct commit3args commit3args;
-
-struct commit3resok {
- wcc_data file_wcc;
- writeverf3 verf;
-};
-typedef struct commit3resok commit3resok;
-
-struct commit3resfail {
- wcc_data file_wcc;
-};
-typedef struct commit3resfail commit3resfail;
-
-struct commit3res {
- nfsstat3 status;
- union {
- commit3resok resok;
- commit3resfail resfail;
- } commit3res_u;
-};
-typedef struct commit3res commit3res;
-#define MNTPATHLEN 1024
-#define MNTNAMLEN 255
-#define FHSIZE3 NFS3_FHSIZE
-
-typedef struct {
- u_int fhandle3_len;
- char *fhandle3_val;
-} fhandle3;
-
-typedef char *dirpath;
-
-typedef char *name;
-
-enum mountstat3 {
- MNT3_OK = 0,
- MNT3ERR_PERM = 1,
- MNT3ERR_NOENT = 2,
- MNT3ERR_IO = 5,
- MNT3ERR_ACCES = 13,
- MNT3ERR_NOTDIR = 20,
- MNT3ERR_INVAL = 22,
- MNT3ERR_NAMETOOLONG = 63,
- MNT3ERR_NOTSUPP = 10004,
- MNT3ERR_SERVERFAULT = 10006,
-};
-typedef enum mountstat3 mountstat3;
-
-struct mountres3_ok {
- fhandle3 fhandle;
- struct {
- u_int auth_flavors_len;
- int *auth_flavors_val;
- } auth_flavors;
-};
-typedef struct mountres3_ok mountres3_ok;
-
-struct mountres3 {
- mountstat3 fhs_status;
- union {
- mountres3_ok mountinfo;
- } mountres3_u;
-};
-typedef struct mountres3 mountres3;
-
-typedef struct mountbody *mountlist;
-
-struct mountbody {
- name ml_hostname;
- dirpath ml_directory;
- mountlist ml_next;
-};
-typedef struct mountbody mountbody;
-
-typedef struct groupnode *groups;
-
-struct groupnode {
- name gr_name;
- groups gr_next;
-};
-typedef struct groupnode groupnode;
-
-typedef struct exportnode *exports;
-
-struct exportnode {
- dirpath ex_dir;
- groups ex_groups;
- exports ex_next;
-};
-typedef struct exportnode exportnode;
-
-#define NFS_PROGRAM 100003
-#define NFS_V3 3
-
-#define NFS3_NULL 0
-#define NFS3_GETATTR 1
-#define NFS3_SETATTR 2
-#define NFS3_LOOKUP 3
-#define NFS3_ACCESS 4
-#define NFS3_READLINK 5
-#define NFS3_READ 6
-#define NFS3_WRITE 7
-#define NFS3_CREATE 8
-#define NFS3_MKDIR 9
-#define NFS3_SYMLINK 10
-#define NFS3_MKNOD 11
-#define NFS3_REMOVE 12
-#define NFS3_RMDIR 13
-#define NFS3_RENAME 14
-#define NFS3_LINK 15
-#define NFS3_READDIR 16
-#define NFS3_READDIRP 17
-#define NFS3_FSSTAT 18
-#define NFS3_FSINFO 19
-#define NFS3_PATHCONF 20
-#define NFS3_COMMIT 21
-#define NFS3_PROC_COUNT 22
-
-#define MOUNT_PROGRAM 100005
-#define MOUNT_V3 3
-#define MOUNT_V1 1
-
-#define MOUNT3_NULL 0
-#define MOUNT3_MNT 1
-#define MOUNT3_DUMP 2
-#define MOUNT3_UMNT 3
-#define MOUNT3_UMNTALL 4
-#define MOUNT3_EXPORT 5
-#define MOUNT3_PROC_COUNT 6
-
-#define MOUNT1_NULL 0
-#define MOUNT1_DUMP 2
-#define MOUNT1_UMNT 3
-#define MOUNT1_EXPORT 5
-#define MOUNT1_PROC_COUNT 6
-/* the xdr functions */
-
-extern bool_t xdr_uint64 (XDR *, uint64*);
-extern bool_t xdr_int64 (XDR *, int64*);
-extern bool_t xdr_uint32 (XDR *, uint32*);
-extern bool_t xdr_int32 (XDR *, int32*);
-extern bool_t xdr_filename3 (XDR *, filename3*);
-extern bool_t xdr_nfspath3 (XDR *, nfspath3*);
-extern bool_t xdr_fileid3 (XDR *, fileid3*);
-extern bool_t xdr_cookie3 (XDR *, cookie3*);
-extern bool_t xdr_cookieverf3 (XDR *, cookieverf3);
-extern bool_t xdr_createverf3 (XDR *, createverf3);
-extern bool_t xdr_writeverf3 (XDR *, writeverf3);
-extern bool_t xdr_uid3 (XDR *, uid3*);
-extern bool_t xdr_gid3 (XDR *, gid3*);
-extern bool_t xdr_size3 (XDR *, size3*);
-extern bool_t xdr_offset3 (XDR *, offset3*);
-extern bool_t xdr_mode3 (XDR *, mode3*);
-extern bool_t xdr_count3 (XDR *, count3*);
-extern bool_t xdr_nfsstat3 (XDR *, nfsstat3*);
-extern bool_t xdr_ftype3 (XDR *, ftype3*);
-extern bool_t xdr_specdata3 (XDR *, specdata3*);
-extern bool_t xdr_nfs_fh3 (XDR *, nfs_fh3*);
-extern bool_t xdr_nfstime3 (XDR *, nfstime3*);
-extern bool_t xdr_fattr3 (XDR *, fattr3*);
-extern bool_t xdr_post_op_attr (XDR *, post_op_attr*);
-extern bool_t xdr_wcc_attr (XDR *, wcc_attr*);
-extern bool_t xdr_pre_op_attr (XDR *, pre_op_attr*);
-extern bool_t xdr_wcc_data (XDR *, wcc_data*);
-extern bool_t xdr_post_op_fh3 (XDR *, post_op_fh3*);
-extern bool_t xdr_time_how (XDR *, time_how*);
-extern bool_t xdr_set_mode3 (XDR *, set_mode3*);
-extern bool_t xdr_set_uid3 (XDR *, set_uid3*);
-extern bool_t xdr_set_gid3 (XDR *, set_gid3*);
-extern bool_t xdr_set_size3 (XDR *, set_size3*);
-extern bool_t xdr_set_atime (XDR *, set_atime*);
-extern bool_t xdr_set_mtime (XDR *, set_mtime*);
-extern bool_t xdr_sattr3 (XDR *, sattr3*);
-extern bool_t xdr_diropargs3 (XDR *, diropargs3*);
-extern bool_t xdr_getattr3args (XDR *, getattr3args*);
-extern bool_t xdr_getattr3resok (XDR *, getattr3resok*);
-extern bool_t xdr_getattr3res (XDR *, getattr3res*);
-extern bool_t xdr_sattrguard3 (XDR *, sattrguard3*);
-extern bool_t xdr_setattr3args (XDR *, setattr3args*);
-extern bool_t xdr_setattr3resok (XDR *, setattr3resok*);
-extern bool_t xdr_setattr3resfail (XDR *, setattr3resfail*);
-extern bool_t xdr_setattr3res (XDR *, setattr3res*);
-extern bool_t xdr_lookup3args (XDR *, lookup3args*);
-extern bool_t xdr_lookup3resok (XDR *, lookup3resok*);
-extern bool_t xdr_lookup3resfail (XDR *, lookup3resfail*);
-extern bool_t xdr_lookup3res (XDR *, lookup3res*);
-extern bool_t xdr_access3args (XDR *, access3args*);
-extern bool_t xdr_access3resok (XDR *, access3resok*);
-extern bool_t xdr_access3resfail (XDR *, access3resfail*);
-extern bool_t xdr_access3res (XDR *, access3res*);
-extern bool_t xdr_readlink3args (XDR *, readlink3args*);
-extern bool_t xdr_readlink3resok (XDR *, readlink3resok*);
-extern bool_t xdr_readlink3resfail (XDR *, readlink3resfail*);
-extern bool_t xdr_readlink3res (XDR *, readlink3res*);
-extern bool_t xdr_read3args (XDR *, read3args*);
-extern bool_t xdr_read3resok (XDR *, read3resok*);
-extern bool_t xdr_read3resfail (XDR *, read3resfail*);
-extern bool_t xdr_read3res (XDR *, read3res*);
-extern bool_t xdr_read3res_nocopy (XDR *xdrs, read3res *objp);
-extern bool_t xdr_stable_how (XDR *, stable_how*);
-extern bool_t xdr_write3args (XDR *, write3args*);
-extern bool_t xdr_write3resok (XDR *, write3resok*);
-extern bool_t xdr_write3resfail (XDR *, write3resfail*);
-extern bool_t xdr_write3res (XDR *, write3res*);
-extern bool_t xdr_createmode3 (XDR *, createmode3*);
-extern bool_t xdr_createhow3 (XDR *, createhow3*);
-extern bool_t xdr_create3args (XDR *, create3args*);
-extern bool_t xdr_create3resok (XDR *, create3resok*);
-extern bool_t xdr_create3resfail (XDR *, create3resfail*);
-extern bool_t xdr_create3res (XDR *, create3res*);
-extern bool_t xdr_mkdir3args (XDR *, mkdir3args*);
-extern bool_t xdr_mkdir3resok (XDR *, mkdir3resok*);
-extern bool_t xdr_mkdir3resfail (XDR *, mkdir3resfail*);
-extern bool_t xdr_mkdir3res (XDR *, mkdir3res*);
-extern bool_t xdr_symlinkdata3 (XDR *, symlinkdata3*);
-extern bool_t xdr_symlink3args (XDR *, symlink3args*);
-extern bool_t xdr_symlink3resok (XDR *, symlink3resok*);
-extern bool_t xdr_symlink3resfail (XDR *, symlink3resfail*);
-extern bool_t xdr_symlink3res (XDR *, symlink3res*);
-extern bool_t xdr_devicedata3 (XDR *, devicedata3*);
-extern bool_t xdr_mknoddata3 (XDR *, mknoddata3*);
-extern bool_t xdr_mknod3args (XDR *, mknod3args*);
-extern bool_t xdr_mknod3resok (XDR *, mknod3resok*);
-extern bool_t xdr_mknod3resfail (XDR *, mknod3resfail*);
-extern bool_t xdr_mknod3res (XDR *, mknod3res*);
-extern bool_t xdr_remove3args (XDR *, remove3args*);
-extern bool_t xdr_remove3resok (XDR *, remove3resok*);
-extern bool_t xdr_remove3resfail (XDR *, remove3resfail*);
-extern bool_t xdr_remove3res (XDR *, remove3res*);
-extern bool_t xdr_rmdir3args (XDR *, rmdir3args*);
-extern bool_t xdr_rmdir3resok (XDR *, rmdir3resok*);
-extern bool_t xdr_rmdir3resfail (XDR *, rmdir3resfail*);
-extern bool_t xdr_rmdir3res (XDR *, rmdir3res*);
-extern bool_t xdr_rename3args (XDR *, rename3args*);
-extern bool_t xdr_rename3resok (XDR *, rename3resok*);
-extern bool_t xdr_rename3resfail (XDR *, rename3resfail*);
-extern bool_t xdr_rename3res (XDR *, rename3res*);
-extern bool_t xdr_link3args (XDR *, link3args*);
-extern bool_t xdr_link3resok (XDR *, link3resok*);
-extern bool_t xdr_link3resfail (XDR *, link3resfail*);
-extern bool_t xdr_link3res (XDR *, link3res*);
-extern bool_t xdr_readdir3args (XDR *, readdir3args*);
-extern bool_t xdr_entry3 (XDR *, entry3*);
-extern bool_t xdr_dirlist3 (XDR *, dirlist3*);
-extern bool_t xdr_readdir3resok (XDR *, readdir3resok*);
-extern bool_t xdr_readdir3resfail (XDR *, readdir3resfail*);
-extern bool_t xdr_readdir3res (XDR *, readdir3res*);
-extern bool_t xdr_readdirp3args (XDR *, readdirp3args*);
-extern bool_t xdr_entryp3 (XDR *, entryp3*);
-extern bool_t xdr_dirlistp3 (XDR *, dirlistp3*);
-extern bool_t xdr_readdirp3resok (XDR *, readdirp3resok*);
-extern bool_t xdr_readdirp3resfail (XDR *, readdirp3resfail*);
-extern bool_t xdr_readdirp3res (XDR *, readdirp3res*);
-extern bool_t xdr_fsstat3args (XDR *, fsstat3args*);
-extern bool_t xdr_fsstat3resok (XDR *, fsstat3resok*);
-extern bool_t xdr_fsstat3resfail (XDR *, fsstat3resfail*);
-extern bool_t xdr_fsstat3res (XDR *, fsstat3res*);
-extern bool_t xdr_fsinfo3args (XDR *, fsinfo3args*);
-extern bool_t xdr_fsinfo3resok (XDR *, fsinfo3resok*);
-extern bool_t xdr_fsinfo3resfail (XDR *, fsinfo3resfail*);
-extern bool_t xdr_fsinfo3res (XDR *, fsinfo3res*);
-extern bool_t xdr_pathconf3args (XDR *, pathconf3args*);
-extern bool_t xdr_pathconf3resok (XDR *, pathconf3resok*);
-extern bool_t xdr_pathconf3resfail (XDR *, pathconf3resfail*);
-extern bool_t xdr_pathconf3res (XDR *, pathconf3res*);
-extern bool_t xdr_commit3args (XDR *, commit3args*);
-extern bool_t xdr_commit3resok (XDR *, commit3resok*);
-extern bool_t xdr_commit3resfail (XDR *, commit3resfail*);
-extern bool_t xdr_commit3res (XDR *, commit3res*);
-extern bool_t xdr_fhandle3 (XDR *, fhandle3*);
-extern bool_t xdr_dirpath (XDR *, dirpath*);
-extern bool_t xdr_name (XDR *, name*);
-extern bool_t xdr_mountstat3 (XDR *, mountstat3*);
-extern bool_t xdr_mountres3_ok (XDR *, mountres3_ok*);
-extern bool_t xdr_mountres3 (XDR *, mountres3*);
-extern bool_t xdr_mountlist (XDR *, mountlist*);
-extern bool_t xdr_mountbody (XDR *, mountbody*);
-extern bool_t xdr_groups (XDR *, groups*);
-extern bool_t xdr_groupnode (XDR *, groupnode*);
-extern bool_t xdr_exports (XDR *, exports*);
-extern bool_t xdr_exportnode (XDR *, exportnode*);
-
-extern void xdr_free_exports_list (struct exportnode *first);
-extern void xdr_free_mountlist (mountlist ml);
-
-extern void xdr_free_write3args_nocopy (write3args *wa);
-#endif
diff --git a/xlators/nfs/lib/src/xdr-rpc.c b/xlators/nfs/lib/src/xdr-rpc.c
deleted file mode 100644
index ac0f8afd3..000000000
--- a/xlators/nfs/lib/src/xdr-rpc.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
- This file is part of GlusterFS.
-
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _CONFIG_H
-#define _CONFIG_H
-#include "config.h"
-#endif
-
-#include <rpc/rpc.h>
-#include <rpc/pmap_clnt.h>
-#include <arpa/inet.h>
-#include <rpc/xdr.h>
-#include <sys/uio.h>
-#include <rpc/auth_unix.h>
-
-#include "mem-pool.h"
-#include "xdr-rpc.h"
-#include "xdr-common.h"
-#include "logging.h"
-
-/* Decodes the XDR format in msgbuf into rpc_msg.
- * The remaining payload is returned into payload.
- */
-int
-xdr_to_rpc_call (char *msgbuf, size_t len, struct rpc_msg *call,
- struct iovec *payload, char *credbytes, char *verfbytes)
-{
- XDR xdr;
- char opaquebytes[MAX_AUTH_BYTES];
- struct opaque_auth *oa = NULL;
-
- if ((!msgbuf) || (!call))
- return -1;
-
- memset (call, 0, sizeof (*call));
-
- oa = &call->rm_call.cb_cred;
- if (!credbytes)
- oa->oa_base = opaquebytes;
- else
- oa->oa_base = credbytes;
-
- oa = &call->rm_call.cb_verf;
- if (!verfbytes)
- oa->oa_base = opaquebytes;
- else
- oa->oa_base = verfbytes;
-
- xdrmem_create (&xdr, msgbuf, len, XDR_DECODE);
- if (!xdr_callmsg (&xdr, call))
- return -1;
-
- if (payload) {
- payload->iov_base = xdr_decoded_remaining_addr (xdr);
- payload->iov_len = xdr_decoded_remaining_len (xdr);
- }
-
- return 0;
-}
-
-
-bool_t
-true_func (XDR *s, caddr_t *a)
-{
- return TRUE;
-}
-
-
-int
-rpc_fill_empty_reply (struct rpc_msg *reply, uint32_t xid)
-{
- if (!reply)
- return -1;
-
- /* Setting to 0 also results in reply verifier flavor to be
- * set to AUTH_NULL which is what we want right now.
- */
- memset (reply, 0, sizeof (*reply));
- reply->rm_xid = xid;
- reply->rm_direction = REPLY;
-
- return 0;
-}
-
-int
-rpc_fill_denied_reply (struct rpc_msg *reply, int rjstat, int auth_err)
-{
- if (!reply)
- return -1;
-
- reply->rm_reply.rp_stat = MSG_DENIED;
- reply->rjcted_rply.rj_stat = rjstat;
- if (rjstat == RPC_MISMATCH) {
- /* No problem with hardocoding
- * RPC version numbers. We only support
- * v2 anyway.
- */
- reply->rjcted_rply.rj_vers.low = 2;
- reply->rjcted_rply.rj_vers.high = 2;
- } else if (rjstat == AUTH_ERROR)
- reply->rjcted_rply.rj_why = auth_err;
-
- return 0;
-}
-
-
-int
-rpc_fill_accepted_reply (struct rpc_msg *reply, int arstat, int proglow,
- int proghigh, int verf, int len, char *vdata)
-{
- if (!reply)
- return -1;
-
- reply->rm_reply.rp_stat = MSG_ACCEPTED;
- reply->acpted_rply.ar_stat = arstat;
-
- reply->acpted_rply.ar_verf.oa_flavor = verf;
- reply->acpted_rply.ar_verf.oa_length = len;
- reply->acpted_rply.ar_verf.oa_base = vdata;
- if (arstat == PROG_MISMATCH) {
- reply->acpted_rply.ar_vers.low = proglow;
- reply->acpted_rply.ar_vers.high = proghigh;
- } else if (arstat == SUCCESS) {
-
- /* This is a hack. I'd really like to build a custom
- * XDR library because Sun RPC interface is not very flexible.
- */
- reply->acpted_rply.ar_results.proc = (xdrproc_t)true_func;
- reply->acpted_rply.ar_results.where = NULL;
- }
-
- return 0;
-}
-
-int
-rpc_reply_to_xdr (struct rpc_msg *reply, char *dest, size_t len,
- struct iovec *dst)
-{
- XDR xdr;
-
- if ((!dest) || (!reply) || (!dst))
- return -1;
-
- xdrmem_create (&xdr, dest, len, XDR_ENCODE);
- if (!xdr_replymsg(&xdr, reply))
- return -1;
-
- dst->iov_base = dest;
- dst->iov_len = xdr_encoded_length (xdr);
-
- return 0;
-}
-
-
-int
-xdr_to_auth_unix_cred (char *msgbuf, int msglen, struct authunix_parms *au,
- char *machname, gid_t *gids)
-{
- XDR xdr;
-
- if ((!msgbuf) || (!machname) || (!gids) || (!au))
- return -1;
-
- au->aup_machname = machname;
- au->aup_gids = gids;
-
- xdrmem_create (&xdr, msgbuf, msglen, XDR_DECODE);
-
- if (!xdr_authunix_parms (&xdr, au))
- return -1;
-
- return 0;
-}
-
diff --git a/xlators/nfs/lib/src/xdr-rpc.h b/xlators/nfs/lib/src/xdr-rpc.h
deleted file mode 100644
index 4c0ee69b1..000000000
--- a/xlators/nfs/lib/src/xdr-rpc.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
- This file is part of GlusterFS.
-
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _XDR_RPC_H
-#define _XDR_RPC_H_
-
-#ifndef _CONFIG_H
-#define _CONFIG_H
-#include "config.h"
-#endif
-
-#include <rpc/rpc.h>
-#include <rpc/pmap_clnt.h>
-#include <arpa/inet.h>
-#include <rpc/xdr.h>
-#include <sys/uio.h>
-
-/* Converts a given network buffer from its XDR format to a structure
- * that contains everything an RPC call needs to work.
- */
-extern int
-xdr_to_rpc_call (char *msgbuf, size_t len, struct rpc_msg *call,
- struct iovec *payload, char *credbytes, char *verfbytes);
-
-extern int
-rpc_fill_empty_reply (struct rpc_msg *reply, uint32_t xid);
-
-extern int
-rpc_fill_denied_reply (struct rpc_msg *reply, int rjstat, int auth_err);
-
-extern int
-rpc_fill_accepted_reply (struct rpc_msg *reply, int arstat, int proglow,
- int proghigh, int verf, int len, char *vdata);
-extern int
-rpc_reply_to_xdr (struct rpc_msg *reply, char *dest, size_t len,
- struct iovec *dst);
-
-extern int
-xdr_to_auth_unix_cred (char *msgbuf, int msglen, struct authunix_parms *au,
- char *machname, gid_t *gids);
-/* Macros that simplify accesing the members of an RPC call structure. */
-#define rpc_call_xid(call) ((call)->rm_xid)
-#define rpc_call_direction(call) ((call)->rm_direction)
-#define rpc_call_rpcvers(call) ((call)->ru.RM_cmb.cb_rpcvers)
-#define rpc_call_program(call) ((call)->ru.RM_cmb.cb_prog)
-#define rpc_call_progver(call) ((call)->ru.RM_cmb.cb_vers)
-#define rpc_call_progproc(call) ((call)->ru.RM_cmb.cb_proc)
-#define rpc_opaque_auth_flavour(oa) ((oa)->oa_flavor)
-#define rpc_opaque_auth_len(oa) ((oa)->oa_length)
-
-#define rpc_call_cred_flavour(call) (rpc_opaque_auth_flavour ((&(call)->ru.RM_cmb.cb_cred)))
-#define rpc_call_cred_len(call) (rpc_opaque_auth_len ((&(call)->ru.RM_cmb.cb_cred)))
-
-
-#define rpc_call_verf_flavour(call) (rpc_opaque_auth_flavour ((&(call)->ru.RM_cmb.cb_verf)))
-#define rpc_call_verf_len(call) (rpc_opaque_auth_len ((&(call)->ru.RM_cmb.cb_verf)))
-
-#endif
diff --git a/xlators/nfs/server/src/Makefile.am b/xlators/nfs/server/src/Makefile.am
index 020c6b1a1..62fbf6535 100644
--- a/xlators/nfs/server/src/Makefile.am
+++ b/xlators/nfs/server/src/Makefile.am
@@ -1,14 +1,24 @@
xlator_LTLIBRARIES = server.la
xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/nfs
-rpclibdir = $(top_srcdir)/xlators/nfs/lib/src/
-server_la_LDFLAGS = -module -avoidversion
-server_la_SOURCES = nfs.c nfs-common.c nfs-fops.c nfs-inodes.c nfs-generics.c mount3.c nfs3-fh.c nfs3.c nfs3-helpers.c
-server_la_LIBADD = $(top_builddir)/xlators/nfs/lib/src/libglrpcsvc.la $(top_builddir)/libglusterfs/src/libglusterfs.la
+nfsrpclibdir = $(top_srcdir)/rpc/rpc-lib/src
+server_la_LDFLAGS = -module -avoid-version
+server_la_SOURCES = nfs.c nfs-common.c nfs-fops.c nfs-inodes.c \
+ nfs-generics.c mount3.c nfs3-fh.c nfs3.c nfs3-helpers.c nlm4.c \
+ nlmcbk_svc.c mount3udp_svc.c acl3.c
+server_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la
-noinst_HEADERS = nfs.h nfs-common.h nfs-fops.h nfs-inodes.h nfs-generics.h mount3.h nfs3-fh.h nfs3.h nfs3-helpers.h
+noinst_HEADERS = nfs.h nfs-common.h nfs-fops.h nfs-inodes.h nfs-generics.h \
+ mount3.h nfs3-fh.h nfs3.h nfs3-helpers.h nfs-mem-types.h nlm4.h \
+ acl3.h
-AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -Wall -D$(GF_HOST_OS)\
- -I$(top_srcdir)/libglusterfs/src -shared -nostartfiles $(GF_CFLAGS)\
- -I$(rpclibdir) -L$(xlatordir)/ -I$(CONTRIBDIR)/rbtree
+AM_CPPFLAGS = $(GF_CPPFLAGS) \
+ -DLIBDIR=\"$(libdir)/glusterfs/$(PACKAGE_VERSION)/auth\" \
+ -I$(top_srcdir)/libglusterfs/src \
+ -I$(nfsrpclibdir) -I$(CONTRIBDIR)/rbtree \
+ -I$(top_srcdir)/rpc/xdr/src/
+
+AM_CFLAGS = -Wall $(GF_CFLAGS)
+
+AM_LDFLAGS = -L$(xlatordir)
CLEANFILES =
diff --git a/xlators/nfs/server/src/acl3.c b/xlators/nfs/server/src/acl3.c
new file mode 100644
index 000000000..08b099b4e
--- /dev/null
+++ b/xlators/nfs/server/src/acl3.c
@@ -0,0 +1,708 @@
+/*
+ * Copyright (c) 2012 Red Hat, Inc. <http://www.redhat.com>
+ * This file is part of GlusterFS.
+ *
+ * This file is licensed to you under your choice of the GNU Lesser
+ * General Public License, version 3 or any later version (LGPLv3 or
+ * later), or the GNU General Public License, version 2 (GPLv2), in all
+ * cases as published by the Free Software Foundation.
+ */
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include "defaults.h"
+#include "rpcsvc.h"
+#include "dict.h"
+#include "xlator.h"
+#include "nfs.h"
+#include "mem-pool.h"
+#include "logging.h"
+#include "nfs-fops.h"
+#include "inode.h"
+#include "nfs3.h"
+#include "nfs-mem-types.h"
+#include "nfs3-helpers.h"
+#include "nfs3-fh.h"
+#include "nfs-generics.h"
+#include "acl3.h"
+
+
+typedef ssize_t (*acl3_serializer) (struct iovec outmsg, void *args);
+
+extern void nfs3_call_state_wipe (nfs3_call_state_t *cs);
+
+extern nfs3_call_state_t *
+nfs3_call_state_init (struct nfs3_state *s, rpcsvc_request_t *req, xlator_t *v);
+
+extern int
+nfs3_fh_validate (struct nfs3_fh *fh);
+
+extern fattr3
+nfs3_stat_to_fattr3 (struct iatt *buf);
+
+#define acl3_validate_nfs3_state(request, state, status, label, retval) \
+ do { \
+ state = rpcsvc_request_program_private (request); \
+ if (!state) { \
+ gf_log (GF_ACL, GF_LOG_ERROR, "NFSv3 state " \
+ "missing from RPC request"); \
+ rpcsvc_request_seterr (req, SYSTEM_ERR); \
+ status = NFS3ERR_SERVERFAULT; \
+ goto label; \
+ } \
+ } while (0); \
+
+#define acl3_validate_gluster_fh(handle, status, errlabel) \
+ do { \
+ if (!nfs3_fh_validate (handle)) { \
+ status = NFS3ERR_SERVERFAULT; \
+ goto errlabel; \
+ } \
+ } while (0) \
+
+
+extern xlator_t *
+nfs3_fh_to_xlator (struct nfs3_state *nfs3, struct nfs3_fh *fh);
+
+#define acl3_map_fh_to_volume(nfs3state, handle, req, volume, status, label) \
+ do { \
+ char exportid[256], gfid[256]; \
+ rpc_transport_t *trans = NULL; \
+ volume = nfs3_fh_to_xlator ((nfs3state), handle); \
+ if (!volume) { \
+ uuid_unparse (handle->exportid, exportid); \
+ uuid_unparse (handle->gfid, gfid); \
+ trans = rpcsvc_request_transport (req); \
+ gf_log (GF_ACL, GF_LOG_ERROR, "Failed to map " \
+ "FH to vol: client=%s, exportid=%s, gfid=%s",\
+ trans->peerinfo.identifier, exportid, \
+ gfid); \
+ gf_log (GF_ACL, GF_LOG_ERROR, \
+ "Stale nfs client %s must be trying to "\
+ "connect to a deleted volume, please " \
+ "unmount it.", trans->peerinfo.identifier);\
+ status = NFS3ERR_STALE; \
+ goto label; \
+ } else { \
+ gf_log (GF_ACL, GF_LOG_TRACE, "FH to Volume: %s"\
+ ,volume->name); \
+ rpcsvc_request_set_private (req, volume); \
+ } \
+ } while (0); \
+
+#define acl3_volume_started_check(nfs3state, vlm, rtval, erlbl) \
+ do { \
+ if ((!nfs_subvolume_started (nfs_state (nfs3state->nfsx), vlm))){\
+ gf_log (GF_ACL, GF_LOG_ERROR, "Volume is disabled: %s",\
+ vlm->name); \
+ rtval = RPCSVC_ACTOR_IGNORE; \
+ goto erlbl; \
+ } \
+ } while (0) \
+
+#define acl3_check_fh_resolve_status(cst, nfstat, erlabl) \
+ do { \
+ xlator_t *xlatorp = NULL; \
+ char buf[256], gfid[256]; \
+ rpc_transport_t *trans = NULL; \
+ if ((cst)->resolve_ret < 0) { \
+ trans = rpcsvc_request_transport (cst->req); \
+ xlatorp = nfs3_fh_to_xlator (cst->nfs3state, \
+ &cst->resolvefh); \
+ uuid_unparse (cst->resolvefh.gfid, gfid); \
+ snprintf (buf, sizeof (buf), "(%s) %s : %s", \
+ trans->peerinfo.identifier, \
+ xlatorp ? xlatorp->name : "ERR", \
+ gfid); \
+ gf_log (GF_ACL, GF_LOG_ERROR, "Unable to resolve FH"\
+ ": %s", buf); \
+ nfstat = nfs3_errno_to_nfsstat3 (cst->resolve_errno);\
+ goto erlabl; \
+ } \
+ } while (0) \
+
+#define acl3_handle_call_state_init(nfs3state, calls, rq, v, opstat, errlabel)\
+ do { \
+ calls = nfs3_call_state_init ((nfs3state), (rq), v); \
+ if (!calls) { \
+ gf_log (GF_ACL, GF_LOG_ERROR, "Failed to " \
+ "init call state"); \
+ opstat = NFS3ERR_SERVERFAULT; \
+ rpcsvc_request_seterr (req, SYSTEM_ERR); \
+ goto errlabel; \
+ } \
+ } while (0) \
+
+
+int
+acl3svc_submit_reply (rpcsvc_request_t *req, void *arg, acl3_serializer sfunc)
+{
+ struct iovec outmsg = {0, };
+ struct iobuf *iob = NULL;
+ struct nfs3_state *nfs3 = NULL;
+ int ret = -1;
+ ssize_t msglen = 0;
+ struct iobref *iobref = NULL;
+
+ if (!req)
+ return -1;
+
+ nfs3 = (struct nfs3_state *)rpcsvc_request_program_private (req);
+ if (!nfs3) {
+ gf_log (GF_ACL, GF_LOG_ERROR, "mount state not found");
+ goto ret;
+ }
+
+ /* First, get the io buffer into which the reply in arg will
+ * be serialized.
+ */
+ iob = iobuf_get (nfs3->iobpool);
+ if (!iob) {
+ gf_log (GF_ACL, GF_LOG_ERROR, "Failed to get iobuf");
+ goto ret;
+ }
+
+ iobuf_to_iovec (iob, &outmsg);
+ /* Use the given serializer to translate the give C structure in arg
+ * to XDR format which will be written into the buffer in outmsg.
+ */
+ msglen = sfunc (outmsg, arg);
+ if (msglen < 0) {
+ gf_log (GF_ACL, GF_LOG_ERROR, "Failed to encode message");
+ goto ret;
+ }
+ outmsg.iov_len = msglen;
+
+ iobref = iobref_new ();
+ if (iobref == NULL) {
+ gf_log (GF_ACL, GF_LOG_ERROR, "Failed to get iobref");
+ goto ret;
+ }
+
+ ret = iobref_add (iobref, iob);
+ if (ret) {
+ gf_log (GF_ACL, GF_LOG_ERROR, "Failed to add iob to iobref");
+ goto ret;
+ }
+
+ /* Then, submit the message for transmission. */
+ ret = rpcsvc_submit_message (req, &outmsg, 1, NULL, 0, iobref);
+ if (ret == -1) {
+ gf_log (GF_ACL, GF_LOG_ERROR, "Reply submission failed");
+ goto ret;
+ }
+
+ ret = 0;
+ret:
+ if (iob)
+ iobuf_unref (iob);
+ if (iobref)
+ iobref_unref (iobref);
+
+ return ret;
+}
+
+
+int
+acl3svc_null (rpcsvc_request_t *req)
+{
+ struct iovec dummyvec = {0, };
+
+ if (!req) {
+ gf_log (GF_ACL, GF_LOG_ERROR, "Got NULL request!");
+ return 0;
+ }
+ rpcsvc_submit_generic (req, &dummyvec, 1, NULL, 0, NULL);
+ return 0;
+}
+
+int
+acl3_getacl_reply (nfs3_call_state_t *cs, getaclreply *reply)
+{
+ acl3svc_submit_reply (cs->req, (void *)reply,
+ (acl3_serializer)xdr_serialize_getaclreply);
+ return 0;
+}
+
+
+int
+acl3_getacl_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, dict_t *dict,
+ dict_t *xdata)
+{
+ nfsstat3 stat = NFS3ERR_SERVERFAULT;
+ nfs3_call_state_t *cs = NULL;
+ data_t *data = NULL;
+ int *p = NULL;
+ int i = 0;
+ getaclreply *getaclreply = NULL;
+
+ if (!frame->local) {
+ gf_log (GF_ACL, GF_LOG_ERROR, "Invalid argument,"
+ " frame->local NULL");
+ return EINVAL;
+ }
+ cs = frame->local;
+ getaclreply = &cs->args.getaclreply;
+ if (op_ret == -1) {
+ stat = nfs3_cbk_errno_status (op_ret, op_errno);
+ goto err;
+ }
+
+ getaclreply->aclentry.aclentry_val = cs->aclentry;
+ getaclreply->daclentry.daclentry_val = cs->daclentry;
+
+ /* FIXME: use posix_acl_from_xattr() */
+ data = dict_get (dict, POSIX_ACL_ACCESS_XATTR);
+ if (data && (p = data_to_bin (data))) {
+ /* POSIX_ACL_VERSION */
+ p++;
+ while ((char *)p < (data->data + data->len)) {
+ getaclreply->aclentry.aclentry_val[i].type = *(*(short **)&p)++;
+ getaclreply->aclentry.aclentry_val[i].perm = *(*(short **)&p)++;
+ getaclreply->aclentry.aclentry_val[i].uid = *(*(int **)&p)++;
+ i++;
+ }
+ getaclreply->aclcount = getaclreply->aclentry.aclentry_len = i;
+ }
+ i = 0;
+
+ data = dict_get (dict, POSIX_ACL_DEFAULT_XATTR);
+ if (data && (p = data_to_bin (data))) {
+ /* POSIX_ACL_VERSION */
+ p++;
+ while ((char *)p < (data->data + data->len)) {
+ getaclreply->daclentry.daclentry_val[i].type = *(*(short **)&p)++;
+ getaclreply->daclentry.daclentry_val[i].perm = *(*(short **)&p)++;
+ getaclreply->daclentry.daclentry_val[i].uid = *(*(int **)&p)++;
+ i++;
+ }
+ getaclreply->daclcount = getaclreply->daclentry.daclentry_len = i;
+ }
+
+ acl3_getacl_reply (cs, getaclreply);
+ nfs3_call_state_wipe (cs);
+ return 0;
+
+err:
+ if (getaclreply)
+ getaclreply->status = stat;
+ acl3_getacl_reply (cs, getaclreply);
+ nfs3_call_state_wipe (cs);
+ return 0;
+}
+
+int
+acl3_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, struct iatt *buf,
+ dict_t *xdata)
+{
+ nfsstat3 stat = NFS3ERR_SERVERFAULT;
+ nfs3_call_state_t *cs = NULL;
+ getaclreply *getaclreply = NULL;
+ int ret = -1;
+ nfs_user_t nfu = {0, };
+
+ if (!frame->local) {
+ gf_log (GF_ACL, GF_LOG_ERROR, "Invalid argument,"
+ " frame->local NULL");
+ return EINVAL;
+ }
+
+ cs = frame->local;
+ getaclreply = &cs->args.getaclreply;
+
+ if (op_ret == -1) {
+ stat = nfs3_cbk_errno_status (op_ret, op_errno);
+ goto err;
+ }
+
+ getaclreply->attr_follows = 1;
+ getaclreply->attr = nfs3_stat_to_fattr3 (buf);
+ getaclreply->mask = 0xf;
+ nfs_request_user_init (&nfu, cs->req);
+ ret = nfs_getxattr (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, NULL, NULL,
+ acl3_getacl_cbk, cs);
+ if (ret == -1) {
+ stat = nfs3_cbk_errno_status (op_ret, op_errno);
+ goto err;
+ }
+ return 0;
+err:
+ getaclreply->status = stat;
+ acl3_getacl_reply (cs, getaclreply);
+ nfs3_call_state_wipe (cs);
+ return 0;
+}
+
+
+int
+acl3_getacl_resume (void *carg)
+{
+ int ret = -1;
+ nfs3_call_state_t *cs = NULL;
+ nfsstat3 stat = NFS3ERR_SERVERFAULT;
+ nfs_user_t nfu = {0, };
+
+ if (!carg)
+ return ret;
+
+ cs = (nfs3_call_state_t *)carg;
+ acl3_check_fh_resolve_status (cs, stat, acl3err);
+ nfs_request_user_init (&nfu, cs->req);
+
+ ret = nfs_stat (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
+ acl3_stat_cbk, cs);
+ stat = -ret;
+acl3err:
+ if (ret < 0) {
+ gf_log (GF_ACL, GF_LOG_ERROR, "unable to open_and_resume");
+ cs->args.getaclreply.status = nfs3_errno_to_nfsstat3 (stat);
+ acl3_getacl_reply (cs, &cs->args.getaclreply);
+ nfs3_call_state_wipe (cs);
+ }
+
+ return ret;
+}
+
+
+int
+acl3svc_getacl (rpcsvc_request_t *req)
+{
+ xlator_t *vol = NULL;
+ struct nfs_state *nfs = NULL;
+ nfs3_state_t *nfs3 = NULL;
+ nfs3_call_state_t *cs = NULL;
+ int ret = RPCSVC_ACTOR_ERROR;
+ nfsstat3 stat = NFS3ERR_SERVERFAULT;
+ struct nfs3_fh fh, *fhp = NULL;
+ getaclargs getaclargs;
+
+ if (!req)
+ return ret;
+
+ acl3_validate_nfs3_state (req, nfs3, stat, rpcerr, ret);
+ nfs = nfs_state (nfs3->nfsx);
+ memset (&getaclargs, 0, sizeof (getaclargs));
+ getaclargs.fh.n_bytes = (char *)&fh;
+ if (xdr_to_getaclargs(req->msg[0], &getaclargs) <= 0) {
+ gf_log (GF_ACL, GF_LOG_ERROR, "Error decoding args");
+ rpcsvc_request_seterr (req, GARBAGE_ARGS);
+ goto rpcerr;
+ }
+ fhp = &fh;
+ acl3_validate_gluster_fh (&fh, stat, acl3err);
+ acl3_map_fh_to_volume (nfs->nfs3state, fhp, req,
+ vol, stat, acl3err);
+ acl3_handle_call_state_init (nfs->nfs3state, cs, req,
+ vol, stat, rpcerr);
+
+ cs->vol = vol;
+ acl3_volume_started_check (nfs3, vol, ret, acl3err);
+
+ ret = nfs3_fh_resolve_and_resume (cs, fhp,
+ NULL, acl3_getacl_resume);
+
+acl3err:
+ if (ret < 0) {
+ gf_log (GF_ACL, GF_LOG_ERROR, "unable to resolve and resume");
+ if (cs) {
+ cs->args.getaclreply.status = stat;
+ acl3_getacl_reply (cs, &cs->args.getaclreply);
+ nfs3_call_state_wipe (cs);
+ }
+ return 0;
+ }
+
+rpcerr:
+ return ret;
+}
+
+int
+acl3_setacl_cbk (call_frame_t *frame, void *cookie,
+ xlator_t *this, int32_t op_ret, int32_t op_errno,
+ dict_t *xdata)
+{
+ nfs3_call_state_t *cs = NULL;
+ cs = frame->local;
+ if (op_ret < 0) {
+ nfsstat3 status = nfs3_cbk_errno_status (op_ret, op_errno);
+ cs->args.setaclreply.status = status;
+ }
+
+ acl3svc_submit_reply (cs->req, (void *)&cs->args.setaclreply,
+ (acl3_serializer)xdr_serialize_setaclreply);
+ return 0;
+}
+
+int
+acl3_setacl_resume (void *carg)
+{
+ int ret = -1;
+ nfs3_call_state_t *cs = NULL;
+ nfsstat3 stat = NFS3ERR_SERVERFAULT;
+ nfs_user_t nfu = {0, };
+ dict_t *xattr = NULL;
+
+ if (!carg)
+ return ret;
+ cs = (nfs3_call_state_t *)carg;
+ acl3_check_fh_resolve_status (cs, stat, acl3err);
+ nfs_request_user_init (&nfu, cs->req);
+ xattr = dict_new();
+ if (cs->aclcount)
+ ret = dict_set_static_bin (xattr, POSIX_ACL_ACCESS_XATTR, cs->aclxattr,
+ cs->aclcount * 8 + 4);
+ if (cs->daclcount)
+ ret = dict_set_static_bin (xattr, POSIX_ACL_DEFAULT_XATTR,
+ cs->daclxattr, cs->daclcount * 8 + 4);
+
+ ret = nfs_setxattr (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, xattr,
+ 0, NULL, acl3_setacl_cbk, cs);
+ dict_unref (xattr);
+
+acl3err:
+ if (ret < 0) {
+ stat = -ret;
+ gf_log (GF_ACL, GF_LOG_ERROR, "unable to open_and_resume");
+ cs->args.setaclreply.status = nfs3_errno_to_nfsstat3 (stat);
+ acl3svc_submit_reply (cs->req, (void *)&cs->args.setaclreply,
+ (acl3_serializer)xdr_serialize_setaclreply);
+ nfs3_call_state_wipe (cs);
+ }
+
+ return ret;
+}
+
+
+int
+acl3svc_setacl (rpcsvc_request_t *req)
+{
+ xlator_t *vol = NULL;
+ struct nfs_state *nfs = NULL;
+ nfs3_state_t *nfs3 = NULL;
+ nfs3_call_state_t *cs = NULL;
+ int ret = RPCSVC_ACTOR_ERROR;
+ nfsstat3 stat = NFS3ERR_SERVERFAULT;
+ struct nfs3_fh fh;
+ struct nfs3_fh *fhp = NULL;
+ setaclargs setaclargs;
+ aclentry *aclentry = NULL;
+ struct aclentry *daclentry = NULL;
+ int i = 0;
+ struct posix_acl_xattr_header *bufheader = NULL;
+ struct posix_acl_xattr_entry *bufentry = NULL;
+
+ if (!req)
+ return ret;
+ aclentry = GF_CALLOC (NFS_ACL_MAX_ENTRIES, sizeof(*aclentry),
+ gf_nfs_mt_arr);
+ if (!aclentry) {
+ goto rpcerr;
+ }
+ daclentry = GF_CALLOC (NFS_ACL_MAX_ENTRIES, sizeof(*daclentry),
+ gf_nfs_mt_arr);
+ if (!daclentry) {
+ goto rpcerr;
+ }
+
+ acl3_validate_nfs3_state (req, nfs3, stat, rpcerr, ret);
+ nfs = nfs_state (nfs3->nfsx);
+ memset (&setaclargs, 0, sizeof (setaclargs));
+ memset (&fh, 0, sizeof (fh));
+ setaclargs.fh.n_bytes = (char *)&fh;
+ setaclargs.aclentry.aclentry_val = aclentry;
+ setaclargs.daclentry.daclentry_val = daclentry;
+ if (xdr_to_setaclargs(req->msg[0], &setaclargs) <= 0) {
+ gf_log (GF_ACL, GF_LOG_ERROR, "Error decoding args");
+ rpcsvc_request_seterr (req, GARBAGE_ARGS);
+ goto rpcerr;
+ }
+ fhp = &fh;
+ acl3_validate_gluster_fh (fhp, stat, acl3err);
+ acl3_map_fh_to_volume (nfs->nfs3state, fhp, req,
+ vol, stat, acl3err);
+ acl3_handle_call_state_init (nfs->nfs3state, cs, req,
+ vol, stat, rpcerr);
+
+ cs->vol = vol;
+ acl3_volume_started_check (nfs3, vol, ret, rpcerr);
+
+ cs->aclcount = setaclargs.aclcount;
+ cs->daclcount = setaclargs.daclcount;
+
+ if ((cs->aclcount > NFS_ACL_MAX_ENTRIES) ||
+ (cs->daclcount > NFS_ACL_MAX_ENTRIES))
+ goto acl3err;
+ /* FIXME: use posix_acl_to_xattr() */
+ /* Populate xattr buffer for user ACL */
+ bufheader = (struct posix_acl_xattr_header *)(cs->aclxattr);
+ bufheader->version = htole32(POSIX_ACL_VERSION);
+ bufentry = bufheader->entries;
+ for (i = 0; i < cs->aclcount; i++) {
+ int uaceuid;
+ const struct aclentry *uace = &aclentry[i];
+ switch (uace->type) {
+ case POSIX_ACL_USER:
+ case POSIX_ACL_GROUP:
+ uaceuid = uace->uid;
+ break;
+ default:
+ uaceuid = POSIX_ACL_UNDEFINED_ID;
+ break;
+ }
+ bufentry->tag = htole16(uace->type);
+ bufentry->perm = htole16(uace->perm);
+ bufentry->id = htole32(uaceuid);
+
+ bufentry++;
+ }
+
+ /* Populate xattr buffer for Default ACL */
+ bufheader = (struct posix_acl_xattr_header *)(cs->aclxattr);
+ bufheader->version = htole32(POSIX_ACL_VERSION);
+ bufentry = bufheader->entries;
+ for (i = 0; i < cs->daclcount; i++) {
+ int daceuid;
+ int dacetype;
+ const struct aclentry *dace = &daclentry[i];
+ /*
+ * For "default ACL", NFSv3 handles the 'type' differently
+ * i.e. by logical OR'ing 'type' with NFS_ACL_DEFAULT.
+ * Which the backend File system does not understand and
+ * that needs to be masked OFF.
+ */
+ dacetype = (dace->type & ~(NFS_ACL_DEFAULT));
+ switch (dacetype) {
+ case POSIX_ACL_USER:
+ case POSIX_ACL_GROUP:
+ daceuid = dace->uid;
+ break;
+ default:
+ daceuid = POSIX_ACL_UNDEFINED_ID;
+ break;
+ }
+ bufentry->tag = htole16(dacetype);
+ bufentry->perm = htole16(dace->perm);
+ bufentry->id = htole32(daceuid);
+
+ bufentry++;
+ }
+
+
+ ret = nfs3_fh_resolve_and_resume (cs, fhp,
+ NULL, acl3_setacl_resume);
+
+acl3err:
+ if (ret < 0) {
+ gf_log (GF_ACL, GF_LOG_ERROR, "unable to resolve and resume");
+ cs->args.setaclreply.status = stat;
+ acl3svc_submit_reply (cs->req, (void *)&cs->args.setaclreply,
+ (acl3_serializer)xdr_serialize_setaclreply);
+ nfs3_call_state_wipe (cs);
+ GF_FREE(aclentry);
+ GF_FREE(daclentry);
+ return 0;
+ }
+
+rpcerr:
+ if (ret < 0)
+ nfs3_call_state_wipe (cs);
+ if (aclentry)
+ GF_FREE (aclentry);
+ if (daclentry)
+ GF_FREE (daclentry);
+ return ret;
+}
+
+
+
+rpcsvc_actor_t acl3svc_actors[ACL3_PROC_COUNT] = {
+ {"NULL", ACL3_NULL, acl3svc_null, NULL, 0},
+ {"GETACL", ACL3_GETACL, acl3svc_getacl, NULL, 0},
+ {"SETACL", ACL3_SETACL, acl3svc_setacl, NULL, 0},
+};
+
+rpcsvc_program_t acl3prog = {
+ .progname = "ACL3",
+ .prognum = ACL_PROGRAM,
+ .progver = ACLV3_VERSION,
+ .progport = GF_NFS3_PORT,
+ .actors = acl3svc_actors,
+ .numactors = ACL3_PROC_COUNT,
+ .min_auth = AUTH_NULL,
+};
+
+rpcsvc_program_t *
+acl3svc_init(xlator_t *nfsx)
+{
+ struct nfs3_state *ns = NULL;
+ struct nfs_state *nfs = NULL;
+ dict_t *options = NULL;
+ int ret = -1;
+ char *portstr = NULL;
+ static gf_boolean_t acl3_inited = _gf_false;
+
+ /* Already inited */
+ if (acl3_inited)
+ return &acl3prog;
+
+ nfs = (struct nfs_state*)nfsx->private;
+
+ ns = nfs->nfs3state;
+ if (!ns) {
+ gf_log (GF_ACL, GF_LOG_ERROR, "ACL3 init failed");
+ goto err;
+ }
+ acl3prog.private = ns;
+
+ options = dict_new ();
+
+ ret = gf_asprintf (&portstr, "%d", GF_ACL3_PORT);
+ if (ret == -1)
+ goto err;
+
+ ret = dict_set_dynstr (options, "transport.socket.listen-port",
+ portstr);
+ if (ret == -1)
+ goto err;
+ ret = dict_set_str (options, "transport-type", "socket");
+ if (ret == -1) {
+ gf_log (GF_ACL, GF_LOG_ERROR, "dict_set_str error");
+ goto err;
+ }
+
+ if (nfs->allow_insecure) {
+ ret = dict_set_str (options, "rpc-auth-allow-insecure", "on");
+ if (ret == -1) {
+ gf_log (GF_ACL, GF_LOG_ERROR, "dict_set_str error");
+ goto err;
+ }
+ ret = dict_set_str (options, "rpc-auth.ports.insecure", "on");
+ if (ret == -1) {
+ gf_log (GF_ACL, GF_LOG_ERROR, "dict_set_str error");
+ goto err;
+ }
+ }
+
+ ret = dict_set_str (options, "transport.address-family", "inet");
+ if (ret == -1) {
+ gf_log (GF_ACL, GF_LOG_ERROR, "dict_set_str error");
+ goto err;
+ }
+
+ ret = rpcsvc_create_listeners (nfs->rpcsvc, options, "ACL");
+ if (ret == -1) {
+ gf_log (GF_ACL, GF_LOG_ERROR, "Unable to create listeners");
+ dict_unref (options);
+ goto err;
+ }
+
+ acl3_inited = _gf_true;
+ return &acl3prog;
+err:
+ return NULL;
+}
diff --git a/xlators/nfs/server/src/acl3.h b/xlators/nfs/server/src/acl3.h
new file mode 100644
index 000000000..e0e61281a
--- /dev/null
+++ b/xlators/nfs/server/src/acl3.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2012 Red Hat, Inc. <http://www.redhat.com>
+ * This file is part of GlusterFS.
+ *
+ * This file is licensed to you under your choice of the GNU Lesser
+ * General Public License, version 3 or any later version (LGPLv3 or
+ * later), or the GNU General Public License, version 2 (GPLv2), in all
+ * cases as published by the Free Software Foundation.
+ */
+
+#ifndef _ACL3_H
+#define _ACL3_H
+
+#include "glusterfs-acl.h"
+
+#define GF_ACL3_PORT 38469
+#define GF_ACL GF_NFS"-ACL"
+
+/*
+ * NFSv3, identifies the default ACL by NFS_ACL_DEFAULT. Gluster
+ * NFS needs to mask it OFF before sending it upto POSIX layer
+ * or File system layer.
+ */
+#define NFS_ACL_DEFAULT 0x1000
+
+#define NFS_ACL_MAX_ENTRIES 1024
+
+rpcsvc_program_t *
+acl3svc_init(xlator_t *nfsx);
+
+#endif
diff --git a/xlators/nfs/server/src/mount3.c b/xlators/nfs/server/src/mount3.c
index db4a88e3d..b0824bf10 100644
--- a/xlators/nfs/server/src/mount3.c
+++ b/xlators/nfs/server/src/mount3.c
@@ -1,20 +1,11 @@
/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
+ Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.com>
This file is part of GlusterFS.
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
*/
#ifndef _CONFIG_H
@@ -36,23 +27,75 @@
#include "nfs-generics.h"
#include "locking.h"
#include "iatt.h"
-
+#include "nfs-mem-types.h"
+#include "nfs.h"
+#include "common-utils.h"
+#include "store.h"
#include <errno.h>
#include <sys/socket.h>
#include <sys/uio.h>
+
+#define IPv4_ADDR_SIZE 32
+
+/* Macro to typecast the parameter to struct sockaddr_in
+ */
+#define SA(addr) ((struct sockaddr_in*)(addr))
+
+/* Macro will mask the ip address with netmask.
+ */
+#define MASKED_IP(ipv4addr, netmask) \
+ (ntohl(SA(ipv4addr)->sin_addr.s_addr) & (netmask))
+
+/* Macro will compare two IP address after applying the mask
+ */
+#define COMPARE_IPv4_ADDRS(ip1, ip2, netmask) \
+ ((MASKED_IP(ip1, netmask)) == (MASKED_IP(ip2, netmask)))
+
+/* This macro will assist in freeing up entire link list
+ * of host_auth_spec structure.
+ */
+#define FREE_HOSTSPEC(exp) do { \
+ struct host_auth_spec *host= exp->hostspec; \
+ while (NULL != host){ \
+ struct host_auth_spec* temp = host; \
+ host = host->next; \
+ if (NULL != temp->host_addr) { \
+ GF_FREE (temp->host_addr); \
+ } \
+ GF_FREE (temp); \
+ } \
+ exp->hostspec = NULL; \
+ } while (0)
+
typedef ssize_t (*mnt3_serializer) (struct iovec outmsg, void *args);
+extern void *
+mount3udp_thread (void *argv);
+
+static inline void
+mnt3_export_free (struct mnt3_export *exp)
+{
+ if (!exp)
+ return;
+
+ if (exp->exptype == MNT3_EXPTYPE_DIR)
+ FREE_HOSTSPEC (exp);
+ GF_FREE (exp->expname);
+ GF_FREE (exp);
+}
/* Generic reply function for MOUNTv3 specific replies. */
int
mnt3svc_submit_reply (rpcsvc_request_t *req, void *arg, mnt3_serializer sfunc)
{
- struct iovec outmsg = {0, };
- struct iobuf *iob = NULL;
- struct mount3_state *ms = NULL;
- int ret = -1;
+ struct iovec outmsg = {0, };
+ struct iobuf *iob = NULL;
+ struct mount3_state *ms = NULL;
+ int ret = -1;
+ ssize_t msglen = 0;
+ struct iobref *iobref = NULL;
if (!req)
return -1;
@@ -66,6 +109,7 @@ mnt3svc_submit_reply (rpcsvc_request_t *req, void *arg, mnt3_serializer sfunc)
/* First, get the io buffer into which the reply in arg will
* be serialized.
*/
+ /* TODO: use 'xdrproc_t' instead of 'sfunc' to get the xdr-size */
iob = iobuf_get (ms->iobpool);
if (!iob) {
gf_log (GF_MNT, GF_LOG_ERROR, "Failed to get iobuf");
@@ -76,11 +120,27 @@ mnt3svc_submit_reply (rpcsvc_request_t *req, void *arg, mnt3_serializer sfunc)
/* Use the given serializer to translate the give C structure in arg
* to XDR format which will be written into the buffer in outmsg.
*/
- outmsg.iov_len = sfunc (outmsg, arg);
+ msglen = sfunc (outmsg, arg);
+ if (msglen < 0) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Failed to encode message");
+ goto ret;
+ }
+ outmsg.iov_len = msglen;
+
+ iobref = iobref_new ();
+ if (iobref == NULL) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Failed to get iobref");
+ goto ret;
+ }
+
+ ret = iobref_add (iobref, iob);
+ if (ret) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Failed to add iob to iobref");
+ goto ret;
+ }
/* Then, submit the message for transmission. */
- ret = rpcsvc_submit_message (req, outmsg, iob);
- iobuf_unref (iob);
+ ret = rpcsvc_submit_message (req, &outmsg, 1, NULL, 0, iobref);
if (ret == -1) {
gf_log (GF_MNT, GF_LOG_ERROR, "Reply submission failed");
goto ret;
@@ -88,6 +148,11 @@ mnt3svc_submit_reply (rpcsvc_request_t *req, void *arg, mnt3_serializer sfunc)
ret = 0;
ret:
+ if (NULL != iob)
+ iobuf_unref (iob);
+ if (NULL != iobref)
+ iobref_unref (iobref);
+
return ret;
}
@@ -171,40 +236,372 @@ mnt3svc_set_mountres3 (mountstat3 stat, struct nfs3_fh *fh, int *authflavor,
return res;
}
+/* Read the rmtab from the store_handle and append (or not) the entries to the
+ * mountlist.
+ *
+ * Requires the store_handle to be locked.
+ */
+static int
+__mount_read_rmtab (gf_store_handle_t *sh, struct list_head *mountlist,
+ gf_boolean_t append)
+{
+ int ret = 0;
+ unsigned int idx = 0;
+ struct mountentry *me = NULL, *tmp = NULL;
+ /* me->hostname is a char[MNTPATHLEN] */
+ char key[MNTPATHLEN + 11];
+
+ GF_ASSERT (sh && mountlist);
+
+ if (!gf_store_locked_local (sh)) {
+ gf_log (GF_MNT, GF_LOG_WARNING, "Not reading unlocked %s",
+ sh->path);
+ return -1;
+ }
+
+ if (!append) {
+ list_for_each_entry_safe (me, tmp, mountlist, mlist) {
+ list_del (&me->mlist);
+ GF_FREE (me);
+ }
+ me = NULL;
+ }
+
+ for (;;) {
+ char *value = NULL;
+
+ if (me && append) {
+ /* do not add duplicates */
+ list_for_each_entry (tmp, mountlist, mlist) {
+ if (!strcmp(tmp->hostname, me->hostname) &&
+ !strcmp(tmp->exname, me->exname)) {
+ GF_FREE (me);
+ goto dont_add;
+ }
+ }
+ list_add_tail (&me->mlist, mountlist);
+ } else if (me) {
+ list_add_tail (&me->mlist, mountlist);
+ }
+
+dont_add:
+ me = GF_CALLOC (1, sizeof (*me), gf_nfs_mt_mountentry);
+ if (!me) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Out of memory");
+ ret = -1;
+ goto out;
+ }
+
+ INIT_LIST_HEAD (&me->mlist);
+
+ snprintf (key, 9 + MNTPATHLEN, "hostname-%d", idx);
+ ret = gf_store_retrieve_value (sh, key, &value);
+ if (ret)
+ break;
+ strncpy (me->hostname, value, MNTPATHLEN);
+ GF_FREE (value);
+
+ snprintf (key, 11 + MNTPATHLEN, "mountpoint-%d", idx);
+ ret = gf_store_retrieve_value (sh, key, &value);
+ if (ret)
+ break;
+ strncpy (me->exname, value, MNTPATHLEN);
+ GF_FREE (value);
+
+ idx++;
+ gf_log (GF_MNT, GF_LOG_TRACE, "Read entries %s:%s", me->hostname, me->exname);
+ }
+ gf_log (GF_MNT, GF_LOG_DEBUG, "Read %d entries from '%s'", idx, sh->path);
+ GF_FREE (me);
+out:
+ return ret;
+}
+
+/* Overwrite the contents of the rwtab with te in-memory client list.
+ * Fail gracefully if the stora_handle is not locked.
+ */
+static void
+__mount_rewrite_rmtab(struct mount3_state *ms, gf_store_handle_t *sh)
+{
+ struct mountentry *me = NULL;
+ char key[16];
+ int fd, ret;
+ unsigned int idx = 0;
+
+ if (!gf_store_locked_local (sh)) {
+ gf_log (GF_MNT, GF_LOG_WARNING, "Not modifying unlocked %s",
+ sh->path);
+ return;
+ }
+
+ fd = gf_store_mkstemp (sh);
+ if (fd == -1) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Failed to open %s", sh->path);
+ return;
+ }
+
+ list_for_each_entry (me, &ms->mountlist, mlist) {
+ snprintf (key, 16, "hostname-%d", idx);
+ ret = gf_store_save_value (fd, key, me->hostname);
+ if (ret)
+ goto fail;
+
+ snprintf (key, 16, "mountpoint-%d", idx);
+ ret = gf_store_save_value (fd, key, me->exname);
+ if (ret)
+ goto fail;
+
+ idx++;
+ }
+
+ gf_log (GF_MNT, GF_LOG_DEBUG, "Updated rmtab with %d entries", idx);
+
+ close (fd);
+ if (gf_store_rename_tmppath (sh))
+ gf_log (GF_MNT, GF_LOG_ERROR, "Failed to overwrite rwtab %s",
+ sh->path);
+
+ return;
+
+fail:
+ gf_log (GF_MNT, GF_LOG_ERROR, "Failed to update %s", sh->path);
+ close (fd);
+ gf_store_unlink_tmppath (sh);
+}
+
+/* Read the rmtab into a clean ms->mountlist.
+ */
+static void
+mount_read_rmtab (struct mount3_state *ms)
+{
+ gf_store_handle_t *sh = NULL;
+ struct nfs_state *nfs = NULL;
+ int ret;
+
+ nfs = (struct nfs_state *)ms->nfsx->private;
+
+ ret = gf_store_handle_new (nfs->rmtab, &sh);
+ if (ret) {
+ gf_log (GF_MNT, GF_LOG_WARNING, "Failed to open '%s'",
+ nfs->rmtab);
+ return;
+ }
+
+ if (gf_store_lock (sh)) {
+ gf_log (GF_MNT, GF_LOG_WARNING, "Failed to lock '%s'",
+ nfs->rmtab);
+ goto out;
+ }
+
+ __mount_read_rmtab (sh, &ms->mountlist, _gf_false);
+ gf_store_unlock (sh);
+
+out:
+ gf_store_handle_destroy (sh);
+}
+
+/* Write the ms->mountlist to the rmtab.
+ *
+ * The rmtab could be empty, or it can exists and have been updated by a
+ * different storage server without our knowing.
+ *
+ * 1. takes the store_handle lock on the current rmtab
+ * - blocks if an other storage server rewrites the rmtab at the same time
+ * 2. [if new_rmtab] takes the store_handle lock on the new rmtab
+ * 3. reads/merges the entries from the current rmtab
+ * 4. [if new_rmtab] reads/merges the entries from the new rmtab
+ * 5. [if new_rmtab] writes the new rmtab
+ * 6. [if not new_rmtab] writes the current rmtab
+ * 7 [if new_rmtab] replaces nfs->rmtab to point to the new location
+ * 8. [if new_rmtab] releases the store_handle lock of the new rmtab
+ * 9. releases the store_handle lock of the old rmtab
+ */
+void
+mount_rewrite_rmtab (struct mount3_state *ms, char *new_rmtab)
+{
+ gf_store_handle_t *sh = NULL, *nsh = NULL;
+ struct nfs_state *nfs = NULL;
+ int ret;
+ char *rmtab = NULL;
+
+ nfs = (struct nfs_state *)ms->nfsx->private;
+
+ ret = gf_store_handle_new (nfs->rmtab, &sh);
+ if (ret) {
+ gf_log (GF_MNT, GF_LOG_WARNING, "Failed to open '%s'",
+ nfs->rmtab);
+ return;
+ }
+
+ if (gf_store_lock (sh)) {
+ gf_log (GF_MNT, GF_LOG_WARNING, "Not rewriting '%s'",
+ nfs->rmtab);
+ goto free_sh;
+ }
+
+ if (new_rmtab) {
+ ret = gf_store_handle_new (new_rmtab, &nsh);
+ if (ret) {
+ gf_log (GF_MNT, GF_LOG_WARNING, "Failed to open '%s'",
+ new_rmtab);
+ goto unlock_sh;
+ }
+
+ if (gf_store_lock (nsh)) {
+ gf_log (GF_MNT, GF_LOG_WARNING, "Not rewriting '%s'",
+ new_rmtab);
+ goto free_nsh;
+ }
+ }
+
+ /* always read the currently used rmtab */
+ __mount_read_rmtab (sh, &ms->mountlist, _gf_true);
+ if (new_rmtab) {
+ /* read the new rmtab and write changes to the new location */
+ __mount_read_rmtab (nsh, &ms->mountlist, _gf_true);
+ __mount_rewrite_rmtab (ms, nsh);
+
+ /* replace the nfs->rmtab reference to the new rmtab */
+ rmtab = gf_strdup(new_rmtab);
+ if (rmtab == NULL) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Out of memory, keeping "
+ "%s as rmtab", nfs->rmtab);
+ } else {
+ GF_FREE (nfs->rmtab);
+ nfs->rmtab = new_rmtab;
+ }
+
+ gf_store_unlock (nsh);
+ } else {
+ /* rewrite the current (unchanged location) rmtab */
+ __mount_rewrite_rmtab (ms, sh);
+ }
+
+free_nsh:
+ if (new_rmtab)
+ gf_store_handle_destroy (nsh);
+unlock_sh:
+ gf_store_unlock (sh);
+free_sh:
+ gf_store_handle_destroy (sh);
+}
+
+/* Add a new NFS-client to the ms->mountlist and update the rmtab if we can.
+ *
+ * A NFS-client will only be removed from the ms->mountlist in case the
+ * NFS-client sends a unmount request. It is possible that a NFS-client
+ * crashed/rebooted had network loss or something else prevented the NFS-client
+ * to unmount cleanly. In this case, a duplicate entry would be added to the
+ * ms->mountlist, which is wrong and we should prevent.
+ *
+ * It is fully acceptible that the ms->mountlist is not 100% correct, this is a
+ * common issue for all(?) NFS-servers.
+ */
int
mnt3svc_update_mountlist (struct mount3_state *ms, rpcsvc_request_t *req,
- xlator_t *exportxl)
+ char *expname)
{
struct mountentry *me = NULL;
+ struct mountentry *cur = NULL;
int ret = -1;
+ char *colon = NULL;
+ struct nfs_state *nfs = NULL;
+ gf_store_handle_t *sh = NULL;
- if ((!ms) || (!req) || (!exportxl))
+ if ((!ms) || (!req) || (!expname))
return -1;
- me = (struct mountentry *)CALLOC (1, sizeof (*me));
+ me = (struct mountentry *)GF_CALLOC (1, sizeof (*me),
+ gf_nfs_mt_mountentry);
if (!me)
return -1;
- strcpy (me->exname, exportxl->name);
+ nfs = (struct nfs_state *)ms->nfsx->private;
+
+ ret = gf_store_handle_new (nfs->rmtab, &sh);
+ if (ret) {
+ gf_log (GF_MNT, GF_LOG_WARNING, "Failed to open '%s'",
+ nfs->rmtab);
+ goto free_err;
+ }
+
+ strncpy (me->exname, expname, MNTPATHLEN);
+
INIT_LIST_HEAD (&me->mlist);
/* Must get the IP or hostname of the client so we
* can map it into the mount entry.
*/
- ret = rpcsvc_conn_peername (req->conn, me->hostname, MNTPATHLEN);
+ ret = rpcsvc_transport_peername (req->trans, me->hostname, MNTPATHLEN);
if (ret == -1)
- goto free_err;
+ goto free_err2;
+ colon = strrchr (me->hostname, ':');
+ if (colon) {
+ *colon = '\0';
+ }
LOCK (&ms->mountlock);
{
+ /* in case locking fails, we just don't write the rmtab */
+ if (gf_store_lock (sh)) {
+ gf_log (GF_MNT, GF_LOG_WARNING, "Failed to lock '%s'"
+ ", changes will not be written", nfs->rmtab);
+ } else {
+ __mount_read_rmtab (sh, &ms->mountlist, _gf_false);
+ }
+
+ /* do not add duplicates */
+ list_for_each_entry (cur, &ms->mountlist, mlist) {
+ if (!strcmp(cur->hostname, me->hostname) &&
+ !strcmp(cur->exname, me->exname)) {
+ GF_FREE (me);
+ goto dont_add;
+ }
+ }
list_add_tail (&me->mlist, &ms->mountlist);
+
+ /* only write the rmtab in case it was locked */
+ if (gf_store_locked_local (sh))
+ __mount_rewrite_rmtab (ms, sh);
}
+dont_add:
+ if (gf_store_locked_local (sh))
+ gf_store_unlock (sh);
+
UNLOCK (&ms->mountlock);
+free_err2:
+ gf_store_handle_destroy (sh);
+
free_err:
if (ret == -1)
- FREE (me);
+ GF_FREE (me);
+
+ return ret;
+}
+
+int
+__mnt3_get_volume_id (struct mount3_state *ms, xlator_t *mntxl,
+ uuid_t volumeid)
+{
+ int ret = -1;
+ struct mnt3_export *exp = NULL;
+
+ if ((!ms) || (!mntxl))
+ return ret;
+
+ LOCK (&ms->mountlock);
+ list_for_each_entry (exp, &ms->exportlist, explist) {
+ if (exp->vol == mntxl) {
+ uuid_copy (volumeid, exp->volumeid);
+ ret = 0;
+ goto out;
+ }
+ }
+
+out:
+ UNLOCK (&ms->mountlock);
return ret;
}
@@ -223,12 +620,16 @@ mnt3svc_lookup_mount_cbk (call_frame_t *frame, void *cookie,
int autharr[10];
int autharrlen = 0;
rpcsvc_t *svc = NULL;
+ xlator_t *mntxl = NULL;
+ uuid_t volumeid = {0, };
+ char fhstr[1024], *path = NULL;
req = (rpcsvc_request_t *)frame->local;
if (!req)
return -1;
+ mntxl = (xlator_t *)cookie;
ms = (struct mount3_state *)rpcsvc_request_program_private (req);
if (!ms) {
gf_log (GF_MNT, GF_LOG_ERROR, "mount state not found");
@@ -236,19 +637,38 @@ mnt3svc_lookup_mount_cbk (call_frame_t *frame, void *cookie,
op_errno = EINVAL;
}
- if (op_ret == -1)
+ if (op_ret == -1) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "error=%s", strerror (op_errno));
status = mnt3svc_errno_to_mnterr (op_errno);
-
+ }
if (status != MNT3_OK)
goto xmit_res;
- fh = nfs3_fh_build_root_fh (ms->nfsx->children, this, *buf);
- mnt3svc_update_mountlist (ms, req, this);
+ path = GF_CALLOC (PATH_MAX, sizeof (char), gf_nfs_mt_char);
+ if (!path) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Out of memory");
+ goto xmit_res;
+ }
+
+ snprintf (path, PATH_MAX, "/%s", mntxl->name);
+ mnt3svc_update_mountlist (ms, req, path);
+ GF_FREE (path);
+ if (gf_nfs_dvm_off (nfs_state (ms->nfsx))) {
+ fh = nfs3_fh_build_indexed_root_fh (ms->nfsx->children, mntxl);
+ goto xmit_res;
+ }
+
+ __mnt3_get_volume_id (ms, mntxl, volumeid);
+ fh = nfs3_fh_build_uuid_root_fh (volumeid);
+
xmit_res:
- gf_log (GF_MNT, GF_LOG_DEBUG, "Mount reply status: %d", status);
+ nfs3_fh_to_str (&fh, fhstr, sizeof (fhstr));
+ gf_log (GF_MNT, GF_LOG_DEBUG, "MNT reply: fh %s, status: %d", fhstr,
+ status);
if (op_ret == 0) {
svc = rpcsvc_request_service (req);
- autharrlen = rpcsvc_auth_array (svc, this->name, autharr, 10);
+ autharrlen = rpcsvc_auth_array (svc, mntxl->name, autharr,
+ 10);
}
res = mnt3svc_set_mountres3 (status, &fh, autharr, autharrlen);
@@ -260,26 +680,707 @@ xmit_res:
int
-mnt3svc_mount (rpcsvc_request_t *req, xlator_t *nfsx, xlator_t * xl)
+mnt3_match_dirpath_export (char *expname, char *dirpath)
{
- loc_t oploc = {0, };
- int ret = -1;
+ int ret = 0;
+ size_t dlen;
+
+ if ((!expname) || (!dirpath))
+ return 0;
+
+ /* Some clients send a dirpath for mount that includes the slash at the
+ * end. String compare for searching the export will fail because our
+ * exports list does not include that slash. Remove the slash to
+ * compare.
+ */
+ dlen = strlen (dirpath);
+ if (dlen && dirpath [dlen - 1] == '/')
+ dirpath [dlen - 1] = '\0';
+
+ if (dirpath[0] != '/')
+ expname++;
+
+ if (strcmp (expname, dirpath) == 0)
+ ret = 1;
+
+ return ret;
+}
+
+
+int
+mnt3svc_mount_inode (rpcsvc_request_t *req, struct mount3_state *ms,
+ xlator_t * xl, inode_t *exportinode)
+{
+ int ret = -EFAULT;
nfs_user_t nfu = {0, };
+ loc_t exportloc = {0, };
- if ((!req) || (!xl))
+ if ((!req) || (!xl) || (!ms) || (!exportinode))
return ret;
- ret = nfs_ino_loc_fill (xl->itable, 1, 0, &oploc);
+ ret = nfs_inode_loc_fill (exportinode, &exportloc, NFS_RESOLVE_EXIST);
+ if (ret < 0) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Loc fill failed for export inode"
+ ": gfid %s, volume: %s",
+ uuid_utoa (exportinode->gfid), xl->name);
+ goto err;
+ }
+
/* To service the mount request, all we need to do
* is to send a lookup fop that returns the stat
* for the root of the child volume. This is
* used to build the root fh sent to the client.
*/
nfs_request_user_init (&nfu, req);
- ret = nfs_lookup (nfsx, xl, &nfu, &oploc, mnt3svc_lookup_mount_cbk,
- (void *)req);
- nfs_loc_wipe (&oploc);
+ ret = nfs_lookup (ms->nfsx, xl, &nfu, &exportloc,
+ mnt3svc_lookup_mount_cbk, (void *)req);
+ nfs_loc_wipe (&exportloc);
+err:
+ return ret;
+}
+
+
+/* For a volume mount request, we just have to create loc on the root inode,
+ * and send a lookup. In the lookup callback the mount reply is send along with
+ * the file handle.
+ */
+int
+mnt3svc_volume_mount (rpcsvc_request_t *req, struct mount3_state *ms,
+ struct mnt3_export *exp)
+{
+ inode_t *exportinode = NULL;
+ int ret = -EFAULT;
+ uuid_t rootgfid = {0, };
+
+ if ((!req) || (!exp) || (!ms))
+ return ret;
+
+ rootgfid[15] = 1;
+ exportinode = inode_find (exp->vol->itable, rootgfid);
+ if (!exportinode) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Failed to get root inode");
+ ret = -ENOENT;
+ goto err;
+ }
+
+ ret = mnt3svc_mount_inode (req, ms, exp->vol, exportinode);
+ inode_unref (exportinode);
+
+err:
+ return ret;
+}
+
+
+/* The catch with directory exports is that the first component of the export
+ * name will be the name of the volume.
+ * Any lookup that needs to be performed to build the directory's file handle
+ * needs to start from the directory path from the root of the volume. For that
+ * we need to strip out the volume name first.
+ */
+char *
+__volume_subdir (char *dirpath, char **volname)
+{
+ char *subdir = NULL;
+ int volname_len = 0;
+
+ if (!dirpath)
+ return NULL;
+
+ if (dirpath[0] == '/')
+ dirpath++;
+
+ subdir = index (dirpath, (int)'/');
+ if (!subdir)
+ goto out;
+
+ if (!volname)
+ goto out;
+
+ if (!*volname)
+ goto out;
+
+ /* subdir points to the first / after the volume name while dirpath
+ * points to the first char of the volume name.
+ */
+ volname_len = subdir - dirpath;
+ strncpy (*volname, dirpath, volname_len);
+ *(*volname + volname_len) = '\0';
+out:
+ return subdir;
+}
+
+
+void
+mnt3_resolve_state_wipe (mnt3_resolve_t *mres)
+{
+ if (!mres)
+ return;
+
+ nfs_loc_wipe (&mres->resolveloc);
+ GF_FREE (mres);
+
+}
+
+
+/* Sets up the component argument to contain the next component in the path and
+ * sets up path as an absolute path starting from the next component.
+ */
+static char *
+setup_next_component (char *path, size_t plen, char *component, size_t clen)
+{
+ char *comp = NULL;
+ char *nextcomp = NULL;
+
+ if ((!path) || (!component))
+ return NULL;
+
+ strncpy (component, path, clen);
+ comp = index (component, (int)'/');
+ if (!comp)
+ goto err;
+
+ comp++;
+ nextcomp = index (comp, (int)'/');
+ if (nextcomp) {
+ strncpy (path, nextcomp, plen);
+ *nextcomp = '\0';
+ } else
+ path[0] = '\0';
+
+err:
+ return comp;
+}
+
+int32_t
+mnt3_resolve_subdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, inode_t *inode,
+ struct iatt *buf, dict_t *xattr,
+ struct iatt *postparent);
+
+/* There are multiple components in the directory export path and each one
+ * needs to be looked up one after the other.
+ */
+int
+__mnt3_resolve_export_subdir_comp (mnt3_resolve_t *mres)
+{
+ char dupsubdir[MNTPATHLEN];
+ char *nextcomp = NULL;
+ int ret = -EFAULT;
+ nfs_user_t nfu = {0, };
+ uuid_t gfid = {0, };
+
+ if (!mres)
+ return ret;
+
+ nextcomp = setup_next_component (mres->remainingdir,
+ sizeof (mres->remainingdir),
+ dupsubdir, sizeof (dupsubdir));
+ if (!nextcomp)
+ goto err;
+
+ /* Wipe the contents of the previous component */
+ uuid_copy (gfid, mres->resolveloc.inode->gfid);
+ nfs_loc_wipe (&mres->resolveloc);
+ ret = nfs_entry_loc_fill (mres->exp->vol->itable, gfid, nextcomp,
+ &mres->resolveloc, NFS_RESOLVE_CREATE);
+ if ((ret < 0) && (ret != -2)) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Failed to resolve and create "
+ "inode: parent gfid %s, entry %s",
+ uuid_utoa (gfid), nextcomp);
+ ret = -EFAULT;
+ goto err;
+ }
+
+ nfs_request_user_init (&nfu, mres->req);
+ ret = nfs_lookup (mres->mstate->nfsx, mres->exp->vol, &nfu,
+ &mres->resolveloc, mnt3_resolve_subdir_cbk, mres);
+
+err:
+ return ret;
+}
+
+
+int32_t
+mnt3_resolve_subdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, inode_t *inode,
+ struct iatt *buf, dict_t *xattr,
+ struct iatt *postparent)
+{
+ mnt3_resolve_t *mres = NULL;
+ mountstat3 mntstat = MNT3ERR_SERVERFAULT;
+ struct nfs3_fh fh = {{0}, };
+ int autharr[10];
+ int autharrlen = 0;
+ rpcsvc_t *svc = NULL;
+ mountres3 res = {0, };
+ xlator_t *mntxl = NULL;
+ char *path = NULL;
+
+ mres = frame->local;
+ mntxl = (xlator_t *)cookie;
+ if (op_ret == -1) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "path=%s (%s)",
+ mres->resolveloc.path, strerror (op_errno));
+ mntstat = mnt3svc_errno_to_mnterr (op_errno);
+ goto err;
+ }
+
+ inode_link (mres->resolveloc.inode, mres->resolveloc.parent,
+ mres->resolveloc.name, buf);
+
+ nfs3_fh_build_child_fh (&mres->parentfh, buf, &fh);
+ if (strlen (mres->remainingdir) <= 0) {
+ op_ret = -1;
+ mntstat = MNT3_OK;
+ path = GF_CALLOC (PATH_MAX, sizeof (char), gf_nfs_mt_char);
+ if (!path) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Memory allocation "
+ "failed");
+ goto err;
+ }
+ snprintf (path, PATH_MAX, "/%s%s", mres->exp->vol->name,
+ mres->resolveloc.path);
+ mnt3svc_update_mountlist (mres->mstate, mres->req,
+ path);
+ GF_FREE (path);
+ } else {
+ mres->parentfh = fh;
+ op_ret = __mnt3_resolve_export_subdir_comp (mres);
+ if (op_ret < 0)
+ mntstat = mnt3svc_errno_to_mnterr (-op_ret);
+ }
+err:
+ if (op_ret == -1) {
+ gf_log (GF_MNT, GF_LOG_DEBUG, "Mount reply status: %d",
+ mntstat);
+ svc = rpcsvc_request_service (mres->req);
+ autharrlen = rpcsvc_auth_array (svc, mntxl->name, autharr,
+ 10);
+
+ res = mnt3svc_set_mountres3 (mntstat, &fh, autharr, autharrlen);
+ mnt3svc_submit_reply (mres->req, (void *)&res,
+ (mnt3_serializer)xdr_serialize_mountres3);
+ mnt3_resolve_state_wipe (mres);
+ }
+
+ return 0;
+}
+
+
+
+/* We will always have to perform a hard lookup on all the components of a
+ * directory export for a mount request because in the mount reply we need the
+ * file handle of the directory. Our file handle creation code is designed with
+ * the assumption that to build a child file/dir fh, we'll always have the
+ * parent dir's fh available so that we may copy the hash array of the previous
+ * dir levels.
+ *
+ * Since we do not store the file handles anywhere, for every mount request we
+ * must resolve the file handles of every component so that the parent dir file
+ * of the exported directory can be built.
+ */
+int
+__mnt3_resolve_subdir (mnt3_resolve_t *mres)
+{
+ char dupsubdir[MNTPATHLEN];
+ char *firstcomp = NULL;
+ int ret = -EFAULT;
+ nfs_user_t nfu = {0, };
+ uuid_t rootgfid = {0, };
+
+ if (!mres)
+ return ret;
+
+ firstcomp = setup_next_component (mres->remainingdir,
+ sizeof (mres->remainingdir),
+ dupsubdir, sizeof (dupsubdir));
+ if (!firstcomp)
+ goto err;
+
+ rootgfid[15] = 1;
+ ret = nfs_entry_loc_fill (mres->exp->vol->itable, rootgfid, firstcomp,
+ &mres->resolveloc, NFS_RESOLVE_CREATE);
+ if ((ret < 0) && (ret != -2)) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Failed to resolve and create "
+ "inode for volume root: %s", mres->exp->vol->name);
+ ret = -EFAULT;
+ goto err;
+ }
+
+ nfs_request_user_init (&nfu, mres->req);
+ ret = nfs_lookup (mres->mstate->nfsx, mres->exp->vol, &nfu,
+ &mres->resolveloc, mnt3_resolve_subdir_cbk, mres);
+
+err:
+ return ret;
+}
+
+
+/**
+ * This function will verify if the client is allowed to mount
+ * the directory or not. Client's IP address will be compared with
+ * allowed IP list or range present in mnt3_export structure.
+ *
+ * @param req - RPC request. This structure contains client's IP address.
+ * @param export - mnt3_export structure. Contains allowed IP list/range.
+ *
+ * @return 0 - on Success and -EACCES on failure.
+ */
+int
+mnt3_verify_auth (rpcsvc_request_t *req, struct mnt3_export *export)
+{
+ int retvalue = -EACCES;
+ int ret = 0;
+ int shiftbits = 0;
+ uint32_t ipv4netmask = 0;
+ uint32_t routingprefix = 0;
+ struct host_auth_spec *host = NULL;
+ struct sockaddr_in *client_addr = NULL;
+ struct sockaddr_in *allowed_addr = NULL;
+ struct addrinfo *allowed_addrinfo = NULL;
+
+ /* Sanity check */
+ if ((NULL == req) ||
+ (NULL == req->trans) ||
+ (NULL == export) ||
+ (NULL == export->hostspec)) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Invalid argument");
+ return retvalue;
+ }
+
+ host = export->hostspec;
+
+
+ /* Client's IP address. */
+ client_addr = (struct sockaddr_in *)(&(req->trans->peerinfo.sockaddr));
+
+ /* Try to see if the client IP matches the allowed IP list.*/
+ while (NULL != host){
+ GF_ASSERT (host->host_addr);
+
+ if (NULL != allowed_addrinfo) {
+ freeaddrinfo (allowed_addrinfo);
+ allowed_addrinfo = NULL;
+ }
+
+ /* Get the addrinfo for the allowed host (host_addr). */
+ ret = getaddrinfo (host->host_addr,
+ NULL,
+ NULL,
+ &allowed_addrinfo);
+ if (0 != ret){
+ gf_log (GF_MNT, GF_LOG_ERROR, "getaddrinfo: %s\n",
+ gai_strerror (ret));
+ host = host->next;
+
+ /* Failed to get IP addrinfo. Continue to check other
+ * allowed IPs in the list.
+ */
+ continue;
+ }
+
+ allowed_addr = (struct sockaddr_in *)(allowed_addrinfo->ai_addr);
+
+ if (NULL == allowed_addr) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Invalid structure");
+ break;
+ }
+
+ if (AF_INET == allowed_addr->sin_family){
+ if (IPv4_ADDR_SIZE < host->routeprefix) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "invalid IP "
+ "configured for export-dir AUTH");
+ host = host->next;
+ continue;
+ }
+
+ /* -1 means no route prefix is provided. In this case
+ * the IP should be an exact match. Which is same as
+ * providing a route prefix of IPv4_ADDR_SIZE.
+ */
+ if (-1 == host->routeprefix) {
+ routingprefix = IPv4_ADDR_SIZE;
+ } else {
+ routingprefix = host->routeprefix;
+ }
+
+ /* Create a mask from the routing prefix. User provided
+ * CIDR address is split into IP address (host_addr) and
+ * routing prefix (routeprefix). This CIDR address may
+ * denote a single, distinct interface address or the
+ * beginning address of an entire network.
+ *
+ * e.g. the IPv4 block 192.168.100.0/24 represents the
+ * 256 IPv4 addresses from 192.168.100.0 to
+ * 192.168.100.255.
+ * Therefore to check if an IP matches 192.168.100.0/24
+ * we should mask the IP with FFFFFF00 and compare it
+ * with host address part of CIDR.
+ */
+ shiftbits = IPv4_ADDR_SIZE - routingprefix;
+ ipv4netmask = 0xFFFFFFFFUL << shiftbits;
+
+ /* Mask both the IPs and then check if they match
+ * or not. */
+ if (COMPARE_IPv4_ADDRS (allowed_addr,
+ client_addr,
+ ipv4netmask)){
+ retvalue = 0;
+ break;
+ }
+ }
+
+ /* Client IP didn't match the allowed IP.
+ * Check with the next allowed IP.*/
+ host = host->next;
+ }
+
+ if (NULL != allowed_addrinfo) {
+ freeaddrinfo (allowed_addrinfo);
+ }
+
+ return retvalue;
+}
+
+int
+mnt3_resolve_subdir (rpcsvc_request_t *req, struct mount3_state *ms,
+ struct mnt3_export *exp, char *subdir)
+{
+ mnt3_resolve_t *mres = NULL;
+ int ret = -EFAULT;
+ struct nfs3_fh pfh = GF_NFS3FH_STATIC_INITIALIZER;
+
+ if ((!req) || (!ms) || (!exp) || (!subdir))
+ return ret;
+
+ /* Need to check AUTH */
+ if (NULL != exp->hostspec) {
+ ret = mnt3_verify_auth (req, exp);
+ if (0 != ret) {
+ gf_log (GF_MNT,GF_LOG_ERROR,
+ "AUTH verification failed");
+ return ret;
+ }
+ }
+
+ mres = GF_CALLOC (1, sizeof (mnt3_resolve_t), gf_nfs_mt_mnt3_resolve);
+ if (!mres) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Memory allocation failed");
+ goto err;
+ }
+
+ mres->exp = exp;
+ mres->mstate = ms;
+ mres->req = req;
+ strncpy (mres->remainingdir, subdir, MNTPATHLEN);
+ if (gf_nfs_dvm_off (nfs_state (ms->nfsx)))
+ pfh = nfs3_fh_build_indexed_root_fh (mres->mstate->nfsx->children, mres->exp->vol);
+ else
+ pfh = nfs3_fh_build_uuid_root_fh (exp->volumeid);
+
+ mres->parentfh = pfh;
+ ret = __mnt3_resolve_subdir (mres);
+ if (ret < 0) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Failed to resolve export dir: %s"
+ , mres->exp->expname);
+ GF_FREE (mres);
+ }
+
+err:
+ return ret;
+}
+
+
+int
+mnt3_resolve_export_subdir (rpcsvc_request_t *req, struct mount3_state *ms,
+ struct mnt3_export *exp)
+{
+ char *volume_subdir = NULL;
+ int ret = -EFAULT;
+
+ if ((!req) || (!ms) || (!exp))
+ return ret;
+
+ volume_subdir = __volume_subdir (exp->expname, NULL);
+ if (!volume_subdir)
+ goto err;
+
+ ret = mnt3_resolve_subdir (req, ms, exp, volume_subdir);
+ if (ret < 0) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Failed to resolve export dir: %s"
+ , exp->expname);
+ goto err;
+ }
+
+err:
+ return ret;
+}
+
+
+int
+mnt3svc_mount (rpcsvc_request_t *req, struct mount3_state *ms,
+ struct mnt3_export *exp)
+{
+ int ret = -EFAULT;
+
+ if ((!req) || (!ms) || (!exp))
+ return ret;
+
+ if (exp->exptype == MNT3_EXPTYPE_VOLUME)
+ ret = mnt3svc_volume_mount (req, ms, exp);
+ else if (exp->exptype == MNT3_EXPTYPE_DIR)
+ ret = mnt3_resolve_export_subdir (req, ms, exp);
+
+ return ret;
+}
+
+
+/* mnt3_mntpath_to_xlator sets this to 1 if the mount is for a full
+* volume or 2 for a subdir in the volume.
+*/
+struct mnt3_export *
+mnt3_mntpath_to_export (struct mount3_state *ms, char *dirpath)
+{
+ struct mnt3_export *exp = NULL;
+ struct mnt3_export *found = NULL;
+
+ if ((!ms) || (!dirpath))
+ return NULL;
+
+ LOCK (&ms->mountlock);
+ list_for_each_entry (exp, &ms->exportlist, explist) {
+
+ /* Search for the an exact match with the volume */
+ if (mnt3_match_dirpath_export (exp->expname, dirpath)) {
+ found = exp;
+ gf_log (GF_MNT, GF_LOG_DEBUG, "Found export volume: "
+ "%s", exp->vol->name);
+ goto foundexp;
+ }
+ }
+
+ gf_log (GF_MNT, GF_LOG_DEBUG, "Export not found");
+foundexp:
+ UNLOCK (&ms->mountlock);
+ return found;
+}
+
+
+int
+mnt3_check_client_net (struct mount3_state *ms, rpcsvc_request_t *req,
+ xlator_t *targetxl)
+{
+
+ rpcsvc_t *svc = NULL;
+ rpc_transport_t *trans = NULL;
+ struct sockaddr_storage sastorage = {0,};
+ char peer[RPCSVC_PEER_STRLEN] = {0,};
+ int ret = -1;
+
+ if ((!ms) || (!req) || (!targetxl))
+ return -1;
+
+ svc = rpcsvc_request_service (req);
+
+ trans = rpcsvc_request_transport (req);
+ ret = rpcsvc_transport_peeraddr (trans, peer, RPCSVC_PEER_STRLEN,
+ &sastorage, sizeof (sastorage));
+ if (ret != 0) {
+ gf_log (GF_MNT, GF_LOG_WARNING, "Failed to get peer addr: %s",
+ gai_strerror (ret));
+ }
+
+ ret = rpcsvc_auth_check (svc, targetxl->name, trans);
+ if (ret == RPCSVC_AUTH_REJECT) {
+ gf_log (GF_MNT, GF_LOG_INFO, "Peer %s not allowed", peer);
+ goto err;
+ }
+
+ ret = rpcsvc_transport_privport_check (svc, targetxl->name,
+ rpcsvc_request_transport (req));
+ if (ret == RPCSVC_AUTH_REJECT) {
+ gf_log (GF_MNT, GF_LOG_INFO, "Peer %s rejected. Unprivileged "
+ "port not allowed", peer);
+ goto err;
+ }
+
+ ret = 0;
+err:
+ return ret;
+}
+
+
+int
+mnt3_parse_dir_exports (rpcsvc_request_t *req, struct mount3_state *ms,
+ char *subdir)
+{
+ char volname[1024];
+ struct mnt3_export *exp = NULL;
+ char *volname_ptr = NULL;
+ int ret = -1;
+
+ if ((!ms) || (!subdir))
+ return -1;
+
+ volname_ptr = volname;
+ subdir = __volume_subdir (subdir, &volname_ptr);
+ if (!subdir)
+ goto err;
+
+ exp = mnt3_mntpath_to_export (ms, volname);
+ if (!exp)
+ goto err;
+
+ ret = mnt3_resolve_subdir (req, ms, exp, subdir);
+ if (ret < 0) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Failed to resolve export dir: %s"
+ , subdir);
+ goto err;
+ }
+
+err:
+ return ret;
+}
+
+
+int
+mnt3_find_export (rpcsvc_request_t *req, char *path, struct mnt3_export **e)
+{
+ int ret = -EFAULT;
+ struct mount3_state *ms = NULL;
+ struct mnt3_export *exp = NULL;
+
+ if ((!req) || (!path) || (!e))
+ return -1;
+
+ ms = (struct mount3_state *) rpcsvc_request_program_private (req);
+ if (!ms) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Mount state not present");
+ rpcsvc_request_seterr (req, SYSTEM_ERR);
+ goto err;
+ }
+
+ gf_log (GF_MNT, GF_LOG_DEBUG, "dirpath: %s", path);
+ exp = mnt3_mntpath_to_export (ms, path);
+ if (exp) {
+ ret = 0;
+ *e = exp;
+ goto err;
+ }
+
+ if (!gf_mnt3_export_dirs(ms)) {
+ ret = -1;
+ goto err;
+ }
+
+ ret = mnt3_parse_dir_exports (req, ms, path);
+ if (ret == 0) {
+ ret = -2;
+ goto err;
+ }
+
+err:
return ret;
}
@@ -290,17 +1391,17 @@ mnt3svc_mnt (rpcsvc_request_t *req)
struct iovec pvec = {0, };
char path[MNTPATHLEN];
int ret = -1;
- xlator_t *targetxl = NULL;
struct mount3_state *ms = NULL;
- rpcsvc_t *svc = NULL;
mountstat3 mntstat = MNT3ERR_SERVERFAULT;
+ struct mnt3_export *exp = NULL;
+ struct nfs_state *nfs = NULL;
if (!req)
return -1;
pvec.iov_base = path;
pvec.iov_len = MNTPATHLEN;
- ret = xdr_to_mountpath (pvec, req->msg);
+ ret = xdr_to_mountpath (pvec, req->msg[0]);
if (ret == -1) {
gf_log (GF_MNT, GF_LOG_ERROR, "Failed to decode args");
rpcsvc_request_seterr (req, GARBAGE_ARGS);
@@ -316,36 +1417,39 @@ mnt3svc_mnt (rpcsvc_request_t *req)
}
ret = 0;
+ nfs = (struct nfs_state *)ms->nfsx->private;
gf_log (GF_MNT, GF_LOG_DEBUG, "dirpath: %s", path);
- targetxl = nfs_mntpath_to_xlator (ms->nfsx->children, path);
- if (!targetxl) {
+ ret = mnt3_find_export (req, path, &exp);
+ if (ret == -2) {
+ ret = 0;
+ goto rpcerr;
+ } else if (ret < 0) {
ret = -1;
mntstat = MNT3ERR_NOENT;
goto mnterr;
}
- svc = rpcsvc_request_service (req);
- ret = rpcsvc_conn_peer_check (svc->options, targetxl->name,
- rpcsvc_request_conn (req));
- if (ret == RPCSVC_AUTH_REJECT) {
- mntstat = MNT3ERR_ACCES;
+ if (!nfs_subvolume_started (nfs, exp->vol)) {
+ gf_log (GF_MNT, GF_LOG_DEBUG, "Volume %s not started",
+ exp->vol->name);
ret = -1;
- gf_log (GF_MNT, GF_LOG_TRACE, "Peer not allowed");
+ mntstat = MNT3ERR_NOENT;
goto mnterr;
}
- ret = rpcsvc_conn_privport_check (svc, targetxl->name,
- rpcsvc_request_conn (req));
+ ret = mnt3_check_client_net (ms, req, exp->vol);
if (ret == RPCSVC_AUTH_REJECT) {
mntstat = MNT3ERR_ACCES;
+ gf_log (GF_MNT, GF_LOG_DEBUG, "Client mount not allowed");
ret = -1;
- gf_log (GF_MNT, GF_LOG_TRACE, "Unprivileged port not allowed");
- goto rpcerr;
+ goto mnterr;
}
- mnt3svc_mount (req, ms->nfsx, targetxl);
+ ret = mnt3svc_mount (req, ms, exp);
+ if (ret < 0)
+ mntstat = mnt3svc_errno_to_mnterr (-ret);
mnterr:
- if (ret == -1) {
+ if (ret < 0) {
mnt3svc_mnt_error_reply (req, mntstat);
ret = 0;
}
@@ -364,8 +1468,7 @@ mnt3svc_null (rpcsvc_request_t *req)
gf_log (GF_MNT, GF_LOG_ERROR, "Got NULL request!");
return 0;
}
-
- rpcsvc_submit_generic (req, dummyvec, NULL);
+ rpcsvc_submit_generic (req, &dummyvec, 1, NULL, 0, NULL);
return 0;
}
@@ -383,29 +1486,35 @@ __build_mountlist (struct mount3_state *ms, int *count)
if ((!ms) || (!count))
return NULL;
+ /* read rmtab, other peers might have updated it */
+ mount_read_rmtab(ms);
+
*count = 0;
gf_log (GF_MNT, GF_LOG_DEBUG, "Building mount list:");
list_for_each_entry (me, &ms->mountlist, mlist) {
namelen = strlen (me->exname);
- mlist = CALLOC (1, sizeof (*mlist));
+ mlist = GF_CALLOC (1, sizeof (*mlist), gf_nfs_mt_mountbody);
if (!mlist) {
gf_log (GF_MNT, GF_LOG_ERROR, "Memory allocation"
" failed");
goto free_list;
}
+ if (!first)
+ first = mlist;
- mlist->ml_directory = CALLOC (namelen + 2, sizeof (char));
+ mlist->ml_directory = GF_CALLOC (namelen + 2, sizeof (char),
+ gf_nfs_mt_char);
if (!mlist->ml_directory) {
gf_log (GF_MNT, GF_LOG_ERROR, "Memory allocation"
" failed");
goto free_list;
}
- strcpy (mlist->ml_directory, "/");
- strcat (mlist->ml_directory, me->exname);
+ strcpy (mlist->ml_directory, me->exname);
namelen = strlen (me->hostname);
- mlist->ml_hostname = CALLOC (namelen + 2, sizeof (char));
+ mlist->ml_hostname = GF_CALLOC (namelen + 2, sizeof (char),
+ gf_nfs_mt_char);
if (!mlist->ml_hostname) {
gf_log (GF_MNT, GF_LOG_ERROR, "Memory allocation"
" failed");
@@ -422,9 +1531,6 @@ __build_mountlist (struct mount3_state *ms, int *count)
} else
prev = mlist;
- if (!first)
- first = mlist;
-
(*count)++;
}
@@ -477,8 +1583,8 @@ mnt3svc_dump (rpcsvc_request_t *req)
sfunc = (mnt3_serializer)xdr_serialize_mountlist;
mlist = mnt3svc_build_mountlist (ms, &ret);
- arg = mlist;
- sfunc = (mnt3_serializer)xdr_serialize_mountlist;
+ arg = &mlist;
+
if (!mlist) {
if (ret != 0) {
rpcsvc_request_seterr (req, SYSTEM_ERR);
@@ -501,52 +1607,71 @@ rpcerr:
int
-__mnt3svc_umount (struct mount3_state *ms, char *dirpath, char *hostname)
+mnt3svc_umount (struct mount3_state *ms, char *dirpath, char *hostname)
{
struct mountentry *me = NULL;
- char *exname = NULL;
int ret = -1;
+ gf_store_handle_t *sh = NULL;
+ struct nfs_state *nfs = NULL;
if ((!ms) || (!dirpath) || (!hostname))
return -1;
- if (list_empty (&ms->mountlist))
+ nfs = (struct nfs_state *)ms->nfsx->private;
+
+ ret = gf_store_handle_new (nfs->rmtab, &sh);
+ if (ret) {
+ gf_log (GF_MNT, GF_LOG_WARNING, "Failed to open '%s'",
+ nfs->rmtab);
return 0;
+ }
- list_for_each_entry (me, &ms->mountlist, mlist) {
- exname = dirpath+1;
- if ((strcmp (me->exname, exname) == 0) &&
- (strcmp (me->hostname, hostname) == 0))
- break;
+ ret = gf_store_lock (sh);
+ if (ret) {
+ goto out_free;
}
- if (!me)
- goto ret;
+ LOCK (&ms->mountlock);
+ {
+ __mount_read_rmtab (sh, &ms->mountlist, _gf_false);
+ if (list_empty (&ms->mountlist)) {
+ ret = 0;
+ goto out_unlock;
+ }
- gf_log (GF_MNT, GF_LOG_DEBUG, "Unmounting: dir %s, host: %s",
- me->exname, me->hostname);
- list_del (&me->mlist);
- FREE (me);
- ret = 0;
-ret:
- return ret;
-}
+ ret = -1;
+ list_for_each_entry (me, &ms->mountlist, mlist) {
+ if ((strcmp (me->exname, dirpath) == 0) &&
+ (strcmp (me->hostname, hostname) == 0)) {
+ ret = 0;
+ break;
+ }
+ }
+ /* Need this check here because at the end of the search me
+ * might still be pointing to the last entry, which may not be
+ * the one we're looking for.
+ */
+ if (ret == -1) {/* Not found in list. */
+ gf_log (GF_MNT, GF_LOG_TRACE, "Export not found");
+ goto out_unlock;
+ }
+ if (!me)
+ goto out_unlock;
-int
-mnt3svc_umount (struct mount3_state *ms, char *dirpath, char *hostname)
-{
- int ret = -1;
- if ((!ms) || (!dirpath) || (!hostname))
- return -1;
+ gf_log (GF_MNT, GF_LOG_DEBUG, "Unmounting: dir %s, host: %s",
+ me->exname, me->hostname);
- LOCK (&ms->mountlock);
- {
- ret = __mnt3svc_umount (ms, dirpath, hostname);
+ list_del (&me->mlist);
+ GF_FREE (me);
+ __mount_rewrite_rmtab (ms, sh);
}
+out_unlock:
UNLOCK (&ms->mountlock);
-
+ gf_store_unlock (sh);
+out_free:
+ gf_store_handle_destroy (sh);
return ret;
}
@@ -560,6 +1685,7 @@ mnt3svc_umnt (rpcsvc_request_t *req)
int ret = -1;
struct mount3_state *ms = NULL;
mountstat3 mstat = MNT3_OK;
+ char *colon = NULL;
if (!req)
return -1;
@@ -567,7 +1693,7 @@ mnt3svc_umnt (rpcsvc_request_t *req)
/* Remove the mount point from the exports list. */
pvec.iov_base = dirpath;
pvec.iov_len = MNTPATHLEN;
- ret = xdr_to_mountpath (pvec, req->msg);;
+ ret = xdr_to_mountpath (pvec, req->msg[0]);
if (ret == -1) {
gf_log (GF_MNT, GF_LOG_ERROR, "Failed decode args");
rpcsvc_request_seterr (req, GARBAGE_ARGS);
@@ -582,41 +1708,28 @@ mnt3svc_umnt (rpcsvc_request_t *req)
goto rpcerr;
}
- ret = rpcsvc_conn_peername (req->conn, hostname, MNTPATHLEN);
+ ret = rpcsvc_transport_peername (req->trans, hostname, MNTPATHLEN);
if (ret != 0) {
gf_log (GF_MNT, GF_LOG_ERROR, "Failed to get remote name: %s",
gai_strerror (ret));
- goto try_umount_with_addr;
- }
-
- gf_log (GF_MNT, GF_LOG_DEBUG, "dirpath: %s, hostname: %s", dirpath,
- hostname);
- ret = mnt3svc_umount (ms, dirpath, hostname);
-
- /* Unmount succeeded with the given hostname. */
- if (ret == 0)
- goto snd_reply;
-
-try_umount_with_addr:
- if (ret != 0)
- ret = rpcsvc_conn_peeraddr (req->conn, hostname, MNTPATHLEN,
- NULL, 0);
-
- if (ret != 0) {
- gf_log (GF_MNT, GF_LOG_ERROR, "Failed to get remote addr: %s",
- gai_strerror (ret));
- rpcsvc_request_seterr (req, SYSTEM_ERR);
goto rpcerr;
}
+ colon = strrchr (hostname, ':');
+ if (colon) {
+ *colon= '\0';
+ }
gf_log (GF_MNT, GF_LOG_DEBUG, "dirpath: %s, hostname: %s", dirpath,
hostname);
ret = mnt3svc_umount (ms, dirpath, hostname);
- if (ret == -1)
- mstat = MNT3ERR_INVAL;
- ret = 0;
-snd_reply:
+ if (ret == -1) {
+ ret = 0;
+ mstat = MNT3ERR_NOENT;
+ }
+ /* FIXME: also take care of the corner case where the
+ * client was resolvable at mount but not at the umount - vice-versa.
+ */
mnt3svc_submit_reply (req, &mstat,
(mnt3_serializer)xdr_serialize_mountstat3);
@@ -629,13 +1742,17 @@ int
__mnt3svc_umountall (struct mount3_state *ms)
{
struct mountentry *me = NULL;
+ struct mountentry *tmp = NULL;
if (!ms)
return -1;
- list_for_each_entry (me, &ms->mountlist, mlist) {
+ if (list_empty (&ms->mountlist))
+ return 0;
+
+ list_for_each_entry_safe (me, tmp, &ms->mountlist, mlist) {
list_del (&me->mlist);
- FREE (me);
+ GF_FREE (me);
}
return 0;
@@ -662,18 +1779,17 @@ mnt3svc_umountall (struct mount3_state *ms)
int
mnt3svc_umntall (rpcsvc_request_t *req)
{
- int ret = -1;
+ int ret = RPCSVC_ACTOR_ERROR;
struct mount3_state *ms = NULL;
mountstat3 mstat = MNT3_OK;
if (!req)
- return -1;
+ return ret;
ms = (struct mount3_state *)rpcsvc_request_program_private (req);
if (!ms) {
gf_log (GF_MNT, GF_LOG_ERROR, "Mount state not present");
rpcsvc_request_seterr (req, SYSTEM_ERR);
- ret = -1;
goto rpcerr;
}
@@ -681,13 +1797,14 @@ mnt3svc_umntall (rpcsvc_request_t *req)
mnt3svc_submit_reply (req, &mstat,
(mnt3_serializer)xdr_serialize_mountstat3);
+ ret = RPCSVC_ACTOR_SUCCESS;
rpcerr:
return ret;
}
exports
-mnt3_xlchildren_to_exports (rpcsvc_t *svc, xlator_list_t *cl)
+mnt3_xlchildren_to_exports (rpcsvc_t *svc, struct mount3_state *ms)
{
struct exportnode *elist = NULL;
struct exportnode *prev = NULL;
@@ -695,58 +1812,75 @@ mnt3_xlchildren_to_exports (rpcsvc_t *svc, xlator_list_t *cl)
size_t namelen = 0;
int ret = -1;
char *addrstr = NULL;
+ struct mnt3_export *ent = NULL;
+ struct nfs_state *nfs = NULL;
- if ((!cl) || (!svc))
+ if ((!ms) || (!svc))
return NULL;
- while (cl) {
- namelen = strlen (cl->xlator->name);
- elist = CALLOC (1, sizeof (*elist));
+ nfs = (struct nfs_state *)ms->nfsx->private;
+ if (!nfs)
+ return NULL;
+
+ LOCK (&ms->mountlock);
+ list_for_each_entry(ent, &ms->exportlist, explist) {
+
+ /* If volume is not started yet, do not list it for tools like
+ * showmount.
+ */
+ if (!nfs_subvolume_started (nfs, ent->vol))
+ continue;
+
+ namelen = strlen (ent->expname) + 1;
+ elist = GF_CALLOC (1, sizeof (*elist), gf_nfs_mt_exportnode);
if (!elist) {
gf_log (GF_MNT, GF_LOG_ERROR, "Memory allocation"
" failed");
goto free_list;
}
-
- elist->ex_dir = CALLOC (namelen + 2, sizeof (char));
+ if (!first)
+ first = elist;
+ elist->ex_dir = GF_CALLOC (namelen + 2, sizeof (char),
+ gf_nfs_mt_char);
if (!elist->ex_dir) {
gf_log (GF_MNT, GF_LOG_ERROR, "Memory allocation"
" failed");
goto free_list;
}
+ strcpy (elist->ex_dir, ent->expname);
- strcpy (elist->ex_dir, "/");
- strcat (elist->ex_dir, cl->xlator->name);
-
- addrstr = rpcsvc_volume_allowed (svc->options,cl->xlator->name);
- if (addrstr)
- addrstr = strdup (addrstr);
- else
- addrstr = strdup ("No Access");
-
- elist->ex_groups = CALLOC (1, sizeof (struct groupnode));
+ addrstr = rpcsvc_volume_allowed (svc->options,
+ ent->vol->name);
+ elist->ex_groups = GF_CALLOC (1, sizeof (struct groupnode),
+ gf_nfs_mt_groupnode);
if (!elist->ex_groups) {
gf_log (GF_MNT, GF_LOG_ERROR, "Memory allocation"
" failed");
goto free_list;
}
+ /*This check has to be done after checking
+ * elist->ex_groups allocation check to avoid resource leak;
+ */
+ if (addrstr)
+ addrstr = gf_strdup (addrstr);
+ else
+ addrstr = gf_strdup ("No Access");
+ if (!addrstr) {
+ goto free_list;
+ }
elist->ex_groups->gr_name = addrstr;
if (prev) {
prev->ex_next = elist;
prev = elist;
} else
prev = elist;
-
- if (!first)
- first = elist;
-
- cl = cl->next;
}
ret = 0;
free_list:
+ UNLOCK (&ms->mountlock);
if (ret == -1) {
xdr_free_exports_list (first);
first = NULL;
@@ -775,12 +1909,16 @@ mnt3svc_export (rpcsvc_request_t *req)
/* Using the children translator names, build the export list */
elist = mnt3_xlchildren_to_exports (rpcsvc_request_service (req),
- ms->nfsx->children);
+ ms);
+ /* Do not return error when exports list is empty. An exports list can
+ * be empty when no subvolumes have come up. No point returning error
+ * and confusing the user.
if (!elist) {
gf_log (GF_MNT, GF_LOG_ERROR, "Failed to build exports list");
- rpcsvc_request_seterr (req, SYSTEM_ERR);
+ nfs_rpcsvc_request_seterr (req, SYSTEM_ERR);
goto err;
}
+ */
/* Note how the serializer is passed to the generic reply function. */
mnt3svc_submit_reply (req, &elist,
@@ -792,16 +1930,571 @@ err:
return ret;
}
+/* just declaring, definition is way down below */
+rpcsvc_program_t mnt3prog;
+
+/* nfs3_rootfh used by mount3udp thread needs to access mount3prog.private
+ * directly as we don't have nfs xlator pointer to dereference it. But thats OK
+ */
+
+struct nfs3_fh *
+nfs3_rootfh (char* path)
+{
+ struct mount3_state *ms = NULL;
+ struct nfs3_fh *fh = NULL;
+ struct mnt3_export *exp = NULL;
+ inode_t *inode = NULL;
+ char *tmp = NULL;
+
+ ms = mnt3prog.private;
+ exp = mnt3_mntpath_to_export (ms, path);
+ if (exp == NULL)
+ goto err;
+
+ tmp = (char *)path;
+ tmp = strchr (tmp, '/');
+ if (tmp == NULL)
+ tmp = "/";
+
+ inode = inode_from_path (exp->vol->itable, tmp);
+ if (inode == NULL)
+ goto err;
+
+ fh = GF_CALLOC (1, sizeof(*fh), gf_nfs_mt_nfs3_fh);
+ if (fh == NULL)
+ goto err;
+ nfs3_build_fh (inode, exp->volumeid, fh);
+
+err:
+ if (inode)
+ inode_unref (inode);
+ return fh;
+}
+
+int
+mount3udp_add_mountlist (char *host, dirpath *expname)
+{
+ struct mountentry *me = NULL;
+ struct mount3_state *ms = NULL;
+ char *export = NULL;
+
+ ms = mnt3prog.private;
+ me = GF_CALLOC (1, sizeof (*me), gf_nfs_mt_mountentry);
+ if (!me)
+ return -1;
+ export = (char *)expname;
+ while (*export == '/')
+ export++;
+
+ strncpy (me->exname, export, MNTPATHLEN);
+ strncpy (me->hostname, host, MNTPATHLEN);
+ INIT_LIST_HEAD (&me->mlist);
+ LOCK (&ms->mountlock);
+ {
+ list_add_tail (&me->mlist, &ms->mountlist);
+ mount_rewrite_rmtab(ms, NULL);
+ }
+ UNLOCK (&ms->mountlock);
+ return 0;
+}
+
+int
+mount3udp_delete_mountlist (char *hostname, dirpath *expname)
+{
+ struct mount3_state *ms = NULL;
+ char *export = NULL;
+
+ ms = mnt3prog.private;
+ export = (char *)expname;
+ while (*export == '/')
+ export++;
+ mnt3svc_umount (ms, export, hostname);
+ return 0;
+}
+
+/**
+ * This function will parse the hostip (IP addres, IP range, or hostname)
+ * and fill the host_auth_spec structure.
+ *
+ * @param hostspec - struct host_auth_spec
+ * @param hostip - IP address, IP range (CIDR format) or hostname
+ *
+ * @return 0 - on success and -1 on failure
+ */
+int
+mnt3_export_fill_hostspec (struct host_auth_spec* hostspec, const char* hostip)
+{
+ char *ipdupstr = NULL;
+ char *savptr = NULL;
+ char *ip = NULL;
+ char *token = NULL;
+ int ret = -1;
+
+ /* Create copy of the string so that the source won't change
+ */
+ ipdupstr = gf_strdup (hostip);
+ if (NULL == ipdupstr) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Memory allocation failed");
+ goto err;
+ }
+
+ ip = strtok_r (ipdupstr, "/", &savptr);
+ hostspec->host_addr = gf_strdup (ip);
+ if (NULL == hostspec->host_addr) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Memory allocation failed");
+ goto err;
+ }
+
+ /* Check if the IP is in <IP address> / <Range> format.
+ * If yes, then strip the range and store it separately.
+ */
+ token = strtok_r (NULL, "/", &savptr);
+
+ if (NULL == token) {
+ hostspec->routeprefix = -1;
+ } else {
+ hostspec->routeprefix = atoi (token);
+ }
+
+ // success
+ ret = 0;
+err:
+ if (NULL != ipdupstr) {
+ GF_FREE (ipdupstr);
+ }
+ return ret;
+}
+
+
+/**
+ * This function will parse the AUTH parameter passed along with
+ * "export-dir" option. If AUTH parameter is present then it will be
+ * stripped from exportpath and stored in mnt3_export (exp) structure.
+ *
+ * @param exp - mnt3_export structure. Holds information needed for mount.
+ * @param exportpath - Value of "export-dir" key. Holds both export path
+ * and AUTH parameter for the path.
+ * exportpath format: <abspath>[(hostdesc[|hostspec|...])]
+ *
+ * @return This function will return 0 on success and -1 on failure.
+ */
+int
+mnt3_export_parse_auth_param (struct mnt3_export* exp, char* exportpath)
+{
+ char *token = NULL;
+ char *savPtr = NULL;
+ char *hostip = NULL;
+ struct host_auth_spec *host = NULL;
+ int ret = 0;
+
+ /* Using exportpath directly in strtok_r because we want
+ * to strip off AUTH parameter from exportpath. */
+ token = strtok_r (exportpath, "(", &savPtr);
+
+ /* Get the next token, which will be the AUTH parameter. */
+ token = strtok_r (NULL, ")", &savPtr);
+
+ if (NULL == token) {
+ /* If AUTH is not present then we should return success. */
+ return 0;
+ }
+
+ /* Free any previously allocated hostspec structure. */
+ if (NULL != exp->hostspec) {
+ GF_FREE (exp->hostspec);
+ exp->hostspec = NULL;
+ }
+
+ exp->hostspec = GF_CALLOC (1,
+ sizeof (*(exp->hostspec)),
+ gf_nfs_mt_auth_spec);
+ if (NULL == exp->hostspec){
+ gf_log (GF_MNT, GF_LOG_ERROR, "Memory allocation failed");
+ return -1;
+ }
+
+ /* AUTH parameter can have multiple entries. For each entry
+ * a host_auth_spec structure is created. */
+ host = exp->hostspec;
+
+ hostip = strtok_r (token, "|", &savPtr);
+
+ /* Parse all AUTH parameters separated by '|' */
+ while (NULL != hostip){
+ ret = mnt3_export_fill_hostspec (host, hostip);
+ if (0 != ret) {
+ gf_log(GF_MNT, GF_LOG_WARNING,
+ "Failed to parse hostspec: %s", hostip);
+ goto err;
+ }
+
+ hostip = strtok_r (NULL, "|", &savPtr);
+ if (NULL == hostip) {
+ break;
+ }
+
+ host->next = GF_CALLOC (1, sizeof (*(host)),
+ gf_nfs_mt_auth_spec);
+ if (NULL == host->next){
+ gf_log (GF_MNT,GF_LOG_ERROR,
+ "Memory allocation failed");
+ goto err;
+ }
+ host = host->next;
+ }
+
+ /* In case of success return from here */
+ return 0;
+err:
+ /* In case of failure free up hostspec structure. */
+ FREE_HOSTSPEC (exp);
+
+ return -1;
+}
+
+/**
+ * exportpath will also have AUTH options (ip address, subnet address or
+ * hostname) mentioned.
+ * exportpath format: <abspath>[(hostdesc[|hostspec|...])]
+ */
+struct mnt3_export *
+mnt3_init_export_ent (struct mount3_state *ms, xlator_t *xl, char *exportpath,
+ uuid_t volumeid)
+{
+ struct mnt3_export *exp = NULL;
+ int alloclen = 0;
+ int ret = -1;
+
+ if ((!ms) || (!xl))
+ return NULL;
+
+ exp = GF_CALLOC (1, sizeof (*exp), gf_nfs_mt_mnt3_export);
+ if (!exp) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Memory allocation failed");
+ return NULL;
+ }
+
+ if (NULL != exportpath) {
+ /* If exportpath is not NULL then we should check if AUTH
+ * parameter is present or not. If AUTH parameter is present
+ * then it will be stripped and stored in mnt3_export (exp)
+ * structure.
+ */
+ if (0 != mnt3_export_parse_auth_param (exp, exportpath)){
+ gf_log (GF_MNT, GF_LOG_ERROR,
+ "Failed to parse auth param");
+ goto err;
+ }
+ }
+
+
+ INIT_LIST_HEAD (&exp->explist);
+ if (exportpath)
+ alloclen = strlen (xl->name) + 2 + strlen (exportpath);
+ else
+ alloclen = strlen (xl->name) + 2;
+
+ exp->expname = GF_CALLOC (alloclen, sizeof (char), gf_nfs_mt_char);
+ if (!exp->expname) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Memory allocation failed");
+ goto err;
+ }
+
+ if (exportpath) {
+ gf_log (GF_MNT, GF_LOG_TRACE, "Initing dir export: %s:%s",
+ xl->name, exportpath);
+ exp->exptype = MNT3_EXPTYPE_DIR;
+ ret = snprintf (exp->expname, alloclen, "/%s%s", xl->name,
+ exportpath);
+ } else {
+ gf_log (GF_MNT, GF_LOG_TRACE, "Initing volume export: %s",
+ xl->name);
+ exp->exptype = MNT3_EXPTYPE_VOLUME;
+ ret = snprintf (exp->expname, alloclen, "/%s", xl->name);
+ }
+ if (ret < 0) {
+ gf_log (xl->name, GF_LOG_ERROR,
+ "Failed to set the export name");
+ goto err;
+ }
+ /* Just copy without discrimination, we'll determine whether to
+ * actually use it when a mount request comes in and a file handle
+ * needs to be built.
+ */
+ uuid_copy (exp->volumeid, volumeid);
+ exp->vol = xl;
+
+ /* On success we should return from here*/
+ return exp;
+err:
+ /* On failure free exp and it's members.*/
+ if (NULL != exp) {
+ mnt3_export_free (exp);
+ exp = NULL;
+ }
+
+ return exp;
+}
+
+
+int
+__mnt3_init_volume_direxports (struct mount3_state *ms, xlator_t *xlator,
+ char *optstr, uuid_t volumeid)
+{
+ struct mnt3_export *newexp = NULL;
+ int ret = -1;
+ char *savptr = NULL;
+ char *dupopt = NULL;
+ char *token = NULL;
+
+ if ((!ms) || (!xlator) || (!optstr))
+ return -1;
+
+ dupopt = gf_strdup (optstr);
+ if (!dupopt) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "gf_strdup failed");
+ goto err;
+ }
+
+ token = strtok_r (dupopt, ",", &savptr);
+ while (token) {
+ newexp = mnt3_init_export_ent (ms, xlator, token, volumeid);
+ if (!newexp) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Failed to init dir "
+ "export: %s", token);
+ ret = -1;
+ goto err;
+ }
+
+ list_add_tail (&newexp->explist, &ms->exportlist);
+ token = strtok_r (NULL, ",", &savptr);
+ }
+
+ ret = 0;
+err:
+ GF_FREE (dupopt);
+
+ return ret;
+}
+
+
+int
+__mnt3_init_volume (struct mount3_state *ms, dict_t *opts, xlator_t *xlator)
+{
+ struct mnt3_export *newexp = NULL;
+ int ret = -1;
+ char searchstr[1024];
+ char *optstr = NULL;
+ uuid_t volumeid = {0, };
+
+ if ((!ms) || (!xlator) || (!opts))
+ return -1;
+
+ uuid_clear (volumeid);
+ if (gf_nfs_dvm_off (nfs_state (ms->nfsx)))
+ goto no_dvm;
+
+ ret = snprintf (searchstr, 1024, "nfs3.%s.volume-id", xlator->name);
+ if (ret < 0) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "snprintf failed");
+ ret = -1;
+ goto err;
+ }
+
+ if (dict_get (opts, searchstr)) {
+ ret = dict_get_str (opts, searchstr, &optstr);
+ if (ret < 0) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Failed to read option"
+ ": %s", searchstr);
+ ret = -1;
+ goto err;
+ }
+ } else {
+ gf_log (GF_MNT, GF_LOG_ERROR, "DVM is on but volume-id not "
+ "given for volume: %s", xlator->name);
+ ret = -1;
+ goto err;
+ }
+
+ if (optstr) {
+ ret = uuid_parse (optstr, volumeid);
+ if (ret < 0) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Failed to parse volume "
+ "UUID");
+ ret = -1;
+ goto err;
+ }
+ }
+
+no_dvm:
+ ret = snprintf (searchstr, 1024, "nfs3.%s.export-dir", xlator->name);
+ if (ret < 0) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "snprintf failed");
+ ret = -1;
+ goto err;
+ }
+
+ if (dict_get (opts, searchstr)) {
+ ret = dict_get_str (opts, searchstr, &optstr);
+ if (ret < 0) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Failed to read option: "
+ "%s", searchstr);
+ ret = -1;
+ goto err;
+ }
+
+ ret = __mnt3_init_volume_direxports (ms, xlator, optstr,
+ volumeid);
+ if (ret == -1) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Dir export setup failed"
+ " for volume: %s", xlator->name);
+ goto err;
+ }
+ }
+
+ if (ms->export_volumes) {
+ newexp = mnt3_init_export_ent (ms, xlator, NULL, volumeid);
+ if (!newexp) {
+ ret = -1;
+ goto err;
+ }
+
+ list_add_tail (&newexp->explist, &ms->exportlist);
+ }
+ ret = 0;
+
+
+err:
+ return ret;
+}
+
+
+int
+__mnt3_init_volume_export (struct mount3_state *ms, dict_t *opts)
+{
+ int ret = -1;
+ char *optstr = NULL;
+ /* On by default. */
+ gf_boolean_t boolt = _gf_true;
+
+ if ((!ms) || (!opts))
+ return -1;
+
+ if (!dict_get (opts, "nfs3.export-volumes")) {
+ ret = 0;
+ goto err;
+ }
+
+ ret = dict_get_str (opts, "nfs3.export-volumes", &optstr);
+ if (ret < 0) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Failed to read option: "
+ "nfs3.export-volumes");
+ ret = -1;
+ goto err;
+ }
+
+ ret = gf_string2boolean (optstr, &boolt);
+ if (ret < 0) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Failed to convert"
+ " string to boolean");
+ }
+
+err:
+ if (boolt == _gf_false) {
+ gf_log (GF_MNT, GF_LOG_TRACE, "Volume exports disabled");
+ ms->export_volumes = 0;
+ } else {
+ gf_log (GF_MNT, GF_LOG_TRACE, "Volume exports enabled");
+ ms->export_volumes = 1;
+ }
+
+ return ret;
+}
+
+
+int
+__mnt3_init_dir_export (struct mount3_state *ms, dict_t *opts)
+{
+ int ret = -1;
+ char *optstr = NULL;
+ /* On by default. */
+ gf_boolean_t boolt = _gf_true;
+
+ if ((!ms) || (!opts))
+ return -1;
+
+ if (!dict_get (opts, "nfs3.export-dirs")) {
+ ret = 0;
+ goto err;
+ }
+
+ ret = dict_get_str (opts, "nfs3.export-dirs", &optstr);
+ if (ret < 0) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Failed to read option: "
+ "nfs3.export-dirs");
+ ret = -1;
+ goto err;
+ }
+
+ ret = gf_string2boolean (optstr, &boolt);
+ if (ret < 0) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Failed to convert"
+ " string to boolean");
+ }
+
+err:
+ if (boolt == _gf_false) {
+ gf_log (GF_MNT, GF_LOG_TRACE, "Dir exports disabled");
+ ms->export_dirs = 0;
+ } else {
+ gf_log (GF_MNT, GF_LOG_TRACE, "Dir exports enabled");
+ ms->export_dirs = 1;
+ }
+
+ return ret;
+}
+
+
+int
+mnt3_init_options (struct mount3_state *ms, dict_t *options)
+{
+ xlator_list_t *volentry = NULL;
+ int ret = -1;
+
+ if ((!ms) || (!options))
+ return -1;
+
+ __mnt3_init_volume_export (ms, options);
+ __mnt3_init_dir_export (ms, options);
+ volentry = ms->nfsx->children;
+ while (volentry) {
+ gf_log (GF_MNT, GF_LOG_TRACE, "Initing options for: %s",
+ volentry->xlator->name);
+ ret = __mnt3_init_volume (ms, options, volentry->xlator);
+ if (ret < 0) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Volume init failed");
+ goto err;
+ }
+
+ volentry = volentry->next;
+ }
+
+ ret = 0;
+err:
+ return ret;
+}
+
struct mount3_state *
mnt3_init_state (xlator_t *nfsx)
{
struct mount3_state *ms = NULL;
+ int ret = -1;
if (!nfsx)
return NULL;
- ms = CALLOC (1, sizeof (*ms));
+ ms = GF_CALLOC (1, sizeof (*ms), gf_nfs_mt_mount3_state);
if (!ms) {
gf_log (GF_MNT, GF_LOG_ERROR, "Memory allocation failed");
return NULL;
@@ -809,56 +2502,131 @@ mnt3_init_state (xlator_t *nfsx)
ms->iobpool = nfsx->ctx->iobuf_pool;
ms->nfsx = nfsx;
- ms->exports = nfsx->children;
+ INIT_LIST_HEAD (&ms->exportlist);
+ ret = mnt3_init_options (ms, nfsx->options);
+ if (ret < 0) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Options init failed");
+ return NULL;
+ }
+
INIT_LIST_HEAD (&ms->mountlist);
LOCK_INIT (&ms->mountlock);
return ms;
}
+int
+mount_init_state (xlator_t *nfsx)
+{
+ int ret = -1;
+ struct nfs_state *nfs = NULL;
+
+ if (!nfsx)
+ goto out;
+
+ nfs = (struct nfs_state *)nfs_state (nfsx);
+ /*Maintaining global state for MOUNT1 and MOUNT3*/
+ nfs->mstate = mnt3_init_state (nfsx);
+ if (!nfs->mstate) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to allocate"
+ "mount state");
+ goto out;
+ }
+ ret = 0;
+out:
+ return ret;
+}
+
rpcsvc_actor_t mnt3svc_actors[MOUNT3_PROC_COUNT] = {
- {"NULL", MOUNT3_NULL, mnt3svc_null, NULL, NULL},
- {"MNT", MOUNT3_MNT, mnt3svc_mnt, NULL, NULL},
- {"DUMP", MOUNT3_DUMP, mnt3svc_dump, NULL, NULL},
- {"UMNT", MOUNT3_UMNT, mnt3svc_umnt, NULL, NULL},
- {"UMNTALL", MOUNT3_UMNTALL, mnt3svc_umntall, NULL, NULL},
- {"EXPORT", MOUNT3_EXPORT, mnt3svc_export, NULL, NULL}
+ {"NULL", MOUNT3_NULL, mnt3svc_null, NULL, 0, DRC_NA},
+ {"MNT", MOUNT3_MNT, mnt3svc_mnt, NULL, 0, DRC_NA},
+ {"DUMP", MOUNT3_DUMP, mnt3svc_dump, NULL, 0, DRC_NA},
+ {"UMNT", MOUNT3_UMNT, mnt3svc_umnt, NULL, 0, DRC_NA},
+ {"UMNTALL", MOUNT3_UMNTALL, mnt3svc_umntall, NULL, 0, DRC_NA},
+ {"EXPORT", MOUNT3_EXPORT, mnt3svc_export, NULL, 0, DRC_NA}
};
/* Static init parts are assigned here, dynamic ones are done in
* mnt3svc_init and mnt3_init_state.
+ * Making MOUNT3 a synctask so that the blocking DNS calls during rpc auth
+ * gets offloaded to syncenv, keeping the main/poll thread unblocked
*/
rpcsvc_program_t mnt3prog = {
.progname = "MOUNT3",
.prognum = MOUNT_PROGRAM,
.progver = MOUNT_V3,
.progport = GF_MOUNTV3_PORT,
- .progaddrfamily = AF_INET,
- .proghost = NULL,
.actors = mnt3svc_actors,
.numactors = MOUNT3_PROC_COUNT,
+ .min_auth = AUTH_NULL,
+ .synctask = _gf_true,
};
+
rpcsvc_program_t *
mnt3svc_init (xlator_t *nfsx)
{
struct mount3_state *mstate = NULL;
+ struct nfs_state *nfs = NULL;
+ dict_t *options = NULL;
+ char *portstr = NULL;
+ int ret = -1;
+ pthread_t udp_thread;
- if (!nfsx)
+ if (!nfsx || !nfsx->private)
return NULL;
+ nfs = (struct nfs_state *)nfsx->private;
+
gf_log (GF_MNT, GF_LOG_DEBUG, "Initing Mount v3 state");
- mstate = mnt3_init_state (nfsx);
+ mstate = (struct mount3_state *)nfs->mstate;
if (!mstate) {
gf_log (GF_MNT, GF_LOG_ERROR, "Mount v3 state init failed");
goto err;
}
mnt3prog.private = mstate;
+ options = dict_new ();
+ ret = gf_asprintf (&portstr, "%d", GF_MOUNTV3_PORT);
+ if (ret == -1)
+ goto err;
+
+ ret = dict_set_dynstr (options, "transport.socket.listen-port", portstr);
+ if (ret == -1)
+ goto err;
+ ret = dict_set_str (options, "transport-type", "socket");
+ if (ret == -1) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "dict_set_str error");
+ goto err;
+ }
+
+ if (nfs->allow_insecure) {
+ ret = dict_set_str (options, "rpc-auth-allow-insecure", "on");
+ if (ret == -1) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "dict_set_str error");
+ goto err;
+ }
+ ret = dict_set_str (options, "rpc-auth.ports.insecure", "on");
+ if (ret == -1) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "dict_set_str error");
+ goto err;
+ }
+ }
+
+ ret= rpcsvc_create_listeners (nfs->rpcsvc, options, nfsx->name);
+ if (ret == -1) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Unable to create listeners");
+ dict_unref (options);
+ goto err;
+ }
+
+ if (nfs->mount_udp) {
+ pthread_create (&udp_thread, NULL, mount3udp_thread, NULL);
+ }
return &mnt3prog;
err:
return NULL;
@@ -866,12 +2634,12 @@ err:
rpcsvc_actor_t mnt1svc_actors[MOUNT1_PROC_COUNT] = {
- {"NULL", MOUNT1_NULL, mnt3svc_null, NULL, NULL},
- {{0}, },
- {"DUMP", MOUNT1_DUMP, mnt3svc_dump, NULL, NULL},
- {"UMNT", MOUNT1_UMNT, mnt3svc_umnt, NULL, NULL},
- {{0}, },
- {"EXPORT", MOUNT1_EXPORT, mnt3svc_export, NULL, NULL}
+ {"NULL", MOUNT1_NULL, mnt3svc_null, NULL, 0, DRC_NA},
+ {"MNT", MOUNT1_MNT, NULL, NULL, 0, DRC_NA },
+ {"DUMP", MOUNT1_DUMP, mnt3svc_dump, NULL, 0, DRC_NA},
+ {"UMNT", MOUNT1_UMNT, mnt3svc_umnt, NULL, 0, DRC_NA},
+ {"UMNTALL", MOUNT1_UMNTALL, NULL, NULL, 0, DRC_NA},
+ {"EXPORT", MOUNT1_EXPORT, mnt3svc_export, NULL, 0, DRC_NA}
};
rpcsvc_program_t mnt1prog = {
@@ -879,10 +2647,10 @@ rpcsvc_program_t mnt1prog = {
.prognum = MOUNT_PROGRAM,
.progver = MOUNT_V1,
.progport = GF_MOUNTV1_PORT,
- .progaddrfamily = AF_INET,
- .proghost = NULL,
.actors = mnt1svc_actors,
.numactors = MOUNT1_PROC_COUNT,
+ .min_auth = AUTH_NULL,
+ .synctask = _gf_true,
};
@@ -890,12 +2658,18 @@ rpcsvc_program_t *
mnt1svc_init (xlator_t *nfsx)
{
struct mount3_state *mstate = NULL;
+ struct nfs_state *nfs = NULL;
+ dict_t *options = NULL;
+ char *portstr = NULL;
+ int ret = -1;
- if (!nfsx)
+ if (!nfsx || !nfsx->private)
return NULL;
+ nfs = (struct nfs_state *)nfsx->private;
+
gf_log (GF_MNT, GF_LOG_DEBUG, "Initing Mount v1 state");
- mstate = mnt3_init_state (nfsx);
+ mstate = (struct mount3_state *)nfs->mstate;
if (!mstate) {
gf_log (GF_MNT, GF_LOG_ERROR, "Mount v3 state init failed");
goto err;
@@ -903,9 +2677,83 @@ mnt1svc_init (xlator_t *nfsx)
mnt1prog.private = mstate;
+ options = dict_new ();
+
+ ret = gf_asprintf (&portstr, "%d", GF_MOUNTV1_PORT);
+ if (ret == -1)
+ goto err;
+
+ ret = dict_set_dynstr (options, "transport.socket.listen-port", portstr);
+ if (ret == -1)
+ goto err;
+ ret = dict_set_str (options, "transport-type", "socket");
+ if (ret == -1) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "dict_set_str error");
+ goto err;
+ }
+
+ if (nfs->allow_insecure) {
+ ret = dict_set_str (options, "rpc-auth-allow-insecure", "on");
+ if (ret == -1) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "dict_set_str error");
+ goto err;
+ }
+ ret = dict_set_str (options, "rpc-auth.ports.insecure", "on");
+ if (ret == -1) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "dict_set_str error");
+ goto err;
+ }
+ }
+
+ ret = rpcsvc_create_listeners (nfs->rpcsvc, options, nfsx->name);
+ if (ret == -1) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Unable to create listeners");
+ dict_unref (options);
+ goto err;
+ }
+
return &mnt1prog;
err:
return NULL;
}
+int
+mount_reconfigure_state (xlator_t *nfsx, dict_t *options)
+{
+ int ret = -1;
+ struct nfs_state *nfs = NULL;
+ struct mount3_state *ms = NULL;
+ struct mnt3_export *exp = NULL;
+ struct mnt3_export *texp = NULL;
+ if ((!nfsx) || (!options))
+ return (-1);
+
+ nfs = (struct nfs_state *)nfs_state (nfsx);
+ if (!nfs)
+ return (-1);
+
+ ms = nfs->mstate;
+ if (!ms)
+ return (-1);
+
+ /*
+ * Free() up the old export list. mnt3_init_options() will
+ * rebuild the export list from scratch. Do it with locking
+ * to avoid unnecessary race conditions.
+ */
+ LOCK (&ms->mountlock);
+ list_for_each_entry_safe (exp, texp, &ms->exportlist, explist) {
+ list_del (&exp->explist);
+ mnt3_export_free (exp);
+ }
+ ret = mnt3_init_options (ms, options);
+ UNLOCK (&ms->mountlock);
+
+ if (ret < 0) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Options reconfigure failed");
+ return (-1);
+ }
+
+ return (0);
+}
diff --git a/xlators/nfs/server/src/mount3.h b/xlators/nfs/server/src/mount3.h
index 7cfd2b0cb..7fc16ed57 100644
--- a/xlators/nfs/server/src/mount3.h
+++ b/xlators/nfs/server/src/mount3.h
@@ -1,20 +1,11 @@
/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
+ Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.com>
This file is part of GlusterFS.
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
*/
#ifndef _MOUNT3_H_
@@ -33,6 +24,8 @@
#include "list.h"
#include "xdr-nfs3.h"
#include "locking.h"
+#include "nfs3-fh.h"
+#include "uuid.h"
/* Registered with portmap */
#define GF_MOUNTV3_PORT 38465
@@ -48,7 +41,16 @@ mnt3svc_init (xlator_t *nfsx);
extern rpcsvc_program_t *
mnt1svc_init (xlator_t *nfsx);
-/* Data structureused to store the list of mounts points currently
+extern int
+mount_init_state (xlator_t *nfsx);
+
+extern int
+mount_reconfigure_state (xlator_t *nfsx, dict_t *options);
+
+void
+mount_rewrite_rmtab (struct mount3_state *ms, char *new_rmtab);
+
+/* Data structure used to store the list of mounts points currently
* in use by NFS clients.
*/
struct mountentry {
@@ -60,12 +62,44 @@ struct mountentry {
char hostname[MNTPATHLEN];
};
+#define MNT3_EXPTYPE_VOLUME 1
+#define MNT3_EXPTYPE_DIR 2
+
+/* Structure to hold export-dir AUTH parameter */
+struct host_auth_spec {
+ char *host_addr; /* Allowed IP or host name */
+ int routeprefix; /* Routing prefix */
+ struct host_auth_spec *next; /* Pointer to next AUTH struct */
+};
+
+struct mnt3_export {
+ struct list_head explist;
+
+ /* The string that may contain either the volume name if the full volume
+ * is exported or the subdirectory in the volume.
+ */
+ char *expname;
+ /*
+ * IP address, hostname or subnets who are allowed to connect to expname
+ * subvolume or subdirectory
+ */
+ struct host_auth_spec* hostspec;
+ xlator_t *vol;
+ int exptype;
+
+ /* Extracted from nfs volume options if nfs.dynamicvolumes is on.
+ */
+ uuid_t volumeid;
+};
+
struct mount3_state {
xlator_t *nfsx;
/* The buffers for all network IO are got from this pool. */
struct iobuf_pool *iobpool;
- xlator_list_t *exports;
+
+ /* List of exports, can be volumes or directories in those volumes. */
+ struct list_head exportlist;
/* List of current mount points over all the exports from this
* server.
@@ -74,5 +108,24 @@ struct mount3_state {
/* Used to protect the mountlist. */
gf_lock_t mountlock;
+
+ /* Set to 0 if exporting full volumes is disabled. On by default. */
+ gf_boolean_t export_volumes;
+ gf_boolean_t export_dirs;
};
+
+#define gf_mnt3_export_dirs(mst) ((mst)->export_dirs)
+
+struct mount3_resolve_state {
+ struct mnt3_export *exp;
+ struct mount3_state *mstate;
+ rpcsvc_request_t *req;
+
+ char remainingdir[MNTPATHLEN];
+ loc_t resolveloc;
+ struct nfs3_fh parentfh;
+};
+
+typedef struct mount3_resolve_state mnt3_resolve_t;
+
#endif
diff --git a/xlators/nfs/server/src/mount3udp_svc.c b/xlators/nfs/server/src/mount3udp_svc.c
new file mode 100644
index 000000000..fb59e282c
--- /dev/null
+++ b/xlators/nfs/server/src/mount3udp_svc.c
@@ -0,0 +1,189 @@
+/*
+ Copyright (c) 2012 Gluster, Inc. <http://www.gluster.com>
+ This file is part of GlusterFS.
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
+*/
+
+
+#include "xdr-nfs3.h"
+#include "logging.h"
+#include "mem-pool.h"
+#include "nfs-mem-types.h"
+#include "mount3.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <rpc/pmap_clnt.h>
+#include <string.h>
+#include <memory.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+
+extern struct nfs3_fh* nfs3_rootfh (char *dp);
+extern mountres3 mnt3svc_set_mountres3 (mountstat3 stat, struct nfs3_fh *fh,
+ int *authflavor, u_int aflen);
+extern int
+mount3udp_add_mountlist (char *host, dirpath *expname);
+
+extern int
+mount3udp_delete_mountlist (char *host, dirpath *expname);
+
+
+/* only this thread will use this, no locking needed */
+char mnthost[INET_ADDRSTRLEN+1];
+
+mountres3 *
+mountudpproc3_mnt_3_svc(dirpath **dpp, struct svc_req *req)
+{
+ struct mountres3 *res = NULL;
+ int *autharr = NULL;
+ struct nfs3_fh *fh = NULL;
+ char *tmp = NULL;
+
+ tmp = (char *)*dpp;
+ while (*tmp == '/')
+ tmp++;
+ fh = nfs3_rootfh (tmp);
+ if (fh == NULL) {
+ gf_log (GF_MNT, GF_LOG_DEBUG, "unable to get fh for %s", tmp);
+ goto err;
+ }
+
+ res = GF_CALLOC (1, sizeof(*res), gf_nfs_mt_mountres3);
+ if (res == NULL) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "unable to allocate memory");
+ goto err;
+ }
+ autharr = GF_CALLOC (1, sizeof(*autharr), gf_nfs_mt_int);
+ if (autharr == NULL) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "unable to allocate memory");
+ goto err;
+ }
+ autharr[0] = AUTH_UNIX;
+ *res = mnt3svc_set_mountres3 (MNT3_OK, fh, autharr, 1);
+ mount3udp_add_mountlist (mnthost, *dpp);
+ return res;
+
+ err:
+ GF_FREE (fh);
+ GF_FREE (res);
+ GF_FREE (autharr);
+ return NULL;
+}
+
+mountstat3 *
+mountudpproc3_umnt_3_svc(dirpath **dp, struct svc_req *req)
+{
+ mountstat3 *stat = NULL;
+
+ stat = GF_CALLOC (1, sizeof(mountstat3), gf_nfs_mt_mountstat3);
+ if (stat == NULL) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "unable to allocate memory");
+ return NULL;
+ }
+ *stat = MNT3_OK;
+ mount3udp_delete_mountlist (mnthost, *dp);
+ return stat;
+}
+
+static void
+mountudp_program_3(struct svc_req *rqstp, register SVCXPRT *transp)
+{
+ union {
+ dirpath mountudpproc3_mnt_3_arg;
+ } argument;
+ char *result = NULL;
+ xdrproc_t _xdr_argument = NULL, _xdr_result = NULL;
+ char *(*local)(char *, struct svc_req *) = NULL;
+ mountres3 *res = NULL;
+ struct sockaddr_in *sin = NULL;
+
+ sin = svc_getcaller (transp);
+ inet_ntop (AF_INET, &sin->sin_addr, mnthost, INET_ADDRSTRLEN+1);
+
+ switch (rqstp->rq_proc) {
+ case NULLPROC:
+ (void) svc_sendreply (transp, (xdrproc_t) xdr_void,
+ (char *)NULL);
+ return;
+
+ case MOUNT3_MNT:
+ _xdr_argument = (xdrproc_t) xdr_dirpath;
+ _xdr_result = (xdrproc_t) xdr_mountres3;
+ local = (char *(*)(char *,
+ struct svc_req *)) mountudpproc3_mnt_3_svc;
+ break;
+
+ case MOUNT3_UMNT:
+ _xdr_argument = (xdrproc_t) xdr_dirpath;
+ _xdr_result = (xdrproc_t) xdr_mountstat3;
+ local = (char *(*)(char *,
+ struct svc_req *)) mountudpproc3_umnt_3_svc;
+ break;
+
+ default:
+ svcerr_noproc (transp);
+ return;
+ }
+ memset ((char *)&argument, 0, sizeof (argument));
+ if (!svc_getargs (transp, (xdrproc_t) _xdr_argument,
+ (caddr_t) &argument)) {
+ svcerr_decode (transp);
+ return;
+ }
+ result = (*local)((char *)&argument, rqstp);
+ if (result == NULL) {
+ gf_log (GF_MNT, GF_LOG_DEBUG, "PROC returned error");
+ svcerr_systemerr (transp);
+ }
+ if (result != NULL && !svc_sendreply(transp, (xdrproc_t) _xdr_result,
+ result)) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "svc_sendreply returned error");
+ svcerr_systemerr (transp);
+ }
+ if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument,
+ (caddr_t) &argument)) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "unable to free arguments");
+ }
+ if (result == NULL)
+ return;
+ /* free the result */
+ switch (rqstp->rq_proc) {
+ case MOUNT3_MNT:
+ res = (mountres3 *) result;
+ GF_FREE (res->mountres3_u.mountinfo.fhandle.fhandle3_val);
+ GF_FREE (res->mountres3_u.mountinfo.auth_flavors.auth_flavors_val);
+ GF_FREE (res);
+ break;
+
+ case MOUNT3_UMNT:
+ GF_FREE (result);
+ break;
+ }
+ return;
+}
+
+void *
+mount3udp_thread (void *argv)
+{
+ register SVCXPRT *transp = NULL;
+
+ transp = svcudp_create(RPC_ANYSOCK);
+ if (transp == NULL) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "svcudp_create error");
+ return NULL;
+ }
+ if (!svc_register(transp, MOUNT_PROGRAM, MOUNT_V3,
+ mountudp_program_3, IPPROTO_UDP)) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "svc_register error");
+ return NULL;
+ }
+
+ svc_run ();
+ gf_log (GF_MNT, GF_LOG_ERROR, "svc_run returned");
+ return NULL;
+}
diff --git a/xlators/nfs/server/src/nfs-common.c b/xlators/nfs/server/src/nfs-common.c
index 3623f041c..f74396ee8 100644
--- a/xlators/nfs/server/src/nfs-common.c
+++ b/xlators/nfs/server/src/nfs-common.c
@@ -1,20 +1,11 @@
/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
+ Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.com>
This file is part of GlusterFS.
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
*/
#ifndef _CONFIG_H
@@ -30,6 +21,7 @@
#include "iobuf.h"
#include "nfs-common.h"
#include "nfs-fops.h"
+#include "nfs-mem-types.h"
#include "rpcsvc.h"
#include "iatt.h"
@@ -87,13 +79,13 @@ nfs_mntpath_to_xlator (xlator_list_t *cl, char *path)
{
char volname[MNTPATHLEN];
char *volptr = NULL;
- int pathlen = 0;
+ size_t pathlen;
xlator_t *targetxl = NULL;
if ((!cl) || (!path))
return NULL;
- strcpy (volname, path);
+ strncpy (volname, path, MNTPATHLEN);
pathlen = strlen (volname);
gf_log (GF_NFS, GF_LOG_TRACE, "Subvolume search: %s", path);
if (volname[0] == '/')
@@ -101,7 +93,7 @@ nfs_mntpath_to_xlator (xlator_list_t *cl, char *path)
else
volptr = &volname[0];
- if (volname[pathlen - 1] == '/')
+ if (pathlen && volname[pathlen - 1] == '/')
volname[pathlen - 1] = '\0';
while (cl) {
@@ -130,7 +122,7 @@ nfs_zero_filled_stat (struct iatt *buf)
* we've already mapped the root ino to 1 so it is not guaranteed to be
* 0.
*/
- if ((buf->ia_nlink == 0) && (buf->ia_type == 0))
+ if ((buf->ia_nlink == 0) && (buf->ia_ctime == 0))
return 1;
return 0;
@@ -140,53 +132,18 @@ nfs_zero_filled_stat (struct iatt *buf)
void
nfs_loc_wipe (loc_t *loc)
{
- if (!loc)
- return;
-
- if (loc->path) {
- FREE (loc->path);
- loc->path = NULL;
- }
-
- if (loc->parent) {
- inode_unref (loc->parent);
- loc->parent = NULL;
- }
-
- if (loc->inode) {
- inode_unref (loc->inode);
- loc->inode = NULL;
- }
-
- loc->ino = 0;
+ loc_wipe (loc);
}
int
nfs_loc_copy (loc_t *dst, loc_t *src)
{
- int ret = -1;
+ int ret = -1;
- dst->ino = src->ino;
+ ret = loc_copy (dst, src);
- if (src->inode)
- dst->inode = inode_ref (src->inode);
-
- if (src->parent)
- dst->parent = inode_ref (src->parent);
-
- dst->path = strdup (src->path);
-
- if (!dst->path)
- goto out;
-
- dst->name = strrchr (dst->path, '/');
- if (dst->name)
- dst->name++;
-
- ret = 0;
-out:
- return ret;
+ return ret;
}
@@ -200,24 +157,24 @@ nfs_loc_fill (loc_t *loc, inode_t *inode, inode_t *parent, char *path)
if (inode) {
loc->inode = inode_ref (inode);
- loc->ino = inode->ino;
+ if (!uuid_is_null (inode->gfid))
+ uuid_copy (loc->gfid, inode->gfid);
}
if (parent)
loc->parent = inode_ref (parent);
- loc->path = strdup (path);
- if (!loc->path) {
- gf_log (GF_NFS, GF_LOG_ERROR, "strdup failed");
- goto loc_wipe;
+ if (path) {
+ loc->path = gf_strdup (path);
+ if (!loc->path) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "strdup failed");
+ goto loc_wipe;
+ }
+ loc->name = strrchr (loc->path, '/');
+ if (loc->name)
+ loc->name++;
}
- loc->name = strrchr (loc->path, '/');
- if (loc->name)
- loc->name++;
- else
- goto loc_wipe;
-
ret = 0;
loc_wipe:
if (ret < 0)
@@ -228,7 +185,7 @@ loc_wipe:
int
-nfs_inode_loc_fill (inode_t *inode, loc_t *loc)
+nfs_inode_loc_fill (inode_t *inode, loc_t *loc, int how)
{
char *resolvedpath = NULL;
inode_t *parent = NULL;
@@ -237,35 +194,47 @@ nfs_inode_loc_fill (inode_t *inode, loc_t *loc)
if ((!inode) || (!loc))
return ret;
- if ((inode) && (inode->ino == 1))
- goto ignore_parent;
-
- parent = inode_parent (inode, 0, NULL);
- if (!parent)
- goto err;
+ /* If gfid is not null, then the inode is already linked to
+ * the inode table, and not a newly created one. For newly
+ * created inode, inode_path returns null gfid as the path.
+ */
+ if (!uuid_is_null (inode->gfid)) {
+ ret = inode_path (inode, NULL, &resolvedpath);
+ if (ret < 0) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "path resolution failed "
+ "%s", resolvedpath);
+ goto err;
+ }
+ }
-ignore_parent:
- ret = inode_path (inode, NULL, &resolvedpath);
- if (ret < 0)
- goto err;
+ if (resolvedpath == NULL) {
+ char tmp_path[GFID_STR_PFX_LEN + 1] = {0,};
+ snprintf (tmp_path, sizeof (tmp_path), "<gfid:%s>",
+ uuid_utoa (loc->gfid));
+ resolvedpath = gf_strdup (tmp_path);
+ } else {
+ parent = inode_parent (inode, loc->pargfid, NULL);
+ }
ret = nfs_loc_fill (loc, inode, parent, resolvedpath);
- if (ret < 0)
+ if (ret < 0) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "loc fill resolution failed %s",
+ resolvedpath);
goto err;
+ }
+ ret = 0;
err:
if (parent)
inode_unref (parent);
- if (resolvedpath)
- FREE (resolvedpath);
+ GF_FREE (resolvedpath);
return ret;
}
-
int
-nfs_ino_loc_fill (inode_table_t *itable, uint64_t ino, uint64_t gen, loc_t *loc)
+nfs_gfid_loc_fill (inode_table_t *itable, uuid_t gfid, loc_t *loc, int how)
{
int ret = -EFAULT;
inode_t *inode = NULL;
@@ -273,13 +242,35 @@ nfs_ino_loc_fill (inode_table_t *itable, uint64_t ino, uint64_t gen, loc_t *loc)
if (!loc)
return ret;
- inode = inode_get (itable, ino, gen);
+ inode = inode_find (itable, gfid);
if (!inode) {
- ret = -ENOENT;
- goto err;
- }
+ gf_log (GF_NFS, GF_LOG_TRACE, "Inode not found in itable, will try to create one.");
+ if (how == NFS_RESOLVE_CREATE) {
+ gf_log (GF_NFS, GF_LOG_TRACE, "Inode needs to be created.");
+ inode = inode_new (itable);
+ if (!inode) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to "
+ "allocate memory");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ } else {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Inode not found in itable and no creation was requested.");
+ ret = -ENOENT;
+ goto err;
+ }
+ } else {
+ gf_log (GF_NFS, GF_LOG_TRACE, "Inode was found in the itable.");
+ }
- ret = nfs_inode_loc_fill (inode, loc);
+ uuid_copy (loc->gfid, gfid);
+
+ ret = nfs_inode_loc_fill (inode, loc, how);
+ if (ret < 0) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Inode loc filling failed.: %s", strerror (-ret));
+ goto err;
+ }
err:
if (inode)
@@ -289,6 +280,17 @@ err:
int
+nfs_root_loc_fill (inode_table_t *itable, loc_t *loc)
+{
+ uuid_t rootgfid = {0, };
+
+ rootgfid[15] = 1;
+ return nfs_gfid_loc_fill (itable, rootgfid, loc, NFS_RESOLVE_EXIST);
+}
+
+
+
+int
nfs_parent_inode_loc_fill (inode_t *parent, inode_t *entryinode, char *entry,
loc_t *loc)
{
@@ -299,11 +301,14 @@ nfs_parent_inode_loc_fill (inode_t *parent, inode_t *entryinode, char *entry,
return ret;
ret = inode_path (parent, entry, &path);
- if (ret < 0)
+ if (ret < 0) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "path resolution failed %s",
+ path);
goto err;
+ }
ret = nfs_loc_fill (loc, entryinode, parent, path);
-
+ GF_FREE (path);
err:
return ret;
}
@@ -316,51 +321,66 @@ err:
* On other errors, return -3. 0 on success.
*/
int
-nfs_entry_loc_fill (inode_table_t *itable, ino_t ino, uint64_t gen, char *entry,
+nfs_entry_loc_fill (inode_table_t *itable, uuid_t pargfid, char *entry,
loc_t *loc, int how)
{
inode_t *parent = NULL;
inode_t *entryinode = NULL;
int ret = -3;
char *resolvedpath = NULL;
+ int pret = -3;
if ((!itable) || (!entry) || (!loc))
return ret;
- parent = inode_get (itable, ino, gen);
+ parent = inode_find (itable, pargfid);
ret = -1;
/* Will need hard resolution now */
if (!parent)
goto err;
+ uuid_copy (loc->pargfid, pargfid);
+
ret = -2;
entryinode = inode_grep (itable, parent, entry);
if (!entryinode) {
- if (how != NFS_RESOLVE_CREATE)
- goto err;
- else {
+ if (how == NFS_RESOLVE_CREATE) {
/* Even though we'll create the inode and the loc for
* a missing inode, we still need to return -2 so
* that the caller can use the filled loc to call
* lookup.
*/
entryinode = inode_new (itable);
- nfs_parent_inode_loc_fill (parent, entryinode, entry,
- loc);
- goto err;
+ /* Cannot change ret because that must
+ * continue to have -2.
+ */
+ pret = nfs_parent_inode_loc_fill (parent, entryinode,
+ entry, loc);
+ /* Only if parent loc fill fails, should we notify error
+ * through ret, otherwise, we still need to force a
+ * lookup by returning -2.
+ */
+ if (pret < 0)
+ ret = -3;
}
+ goto err;
}
ret = inode_path (parent, entry, &resolvedpath);
if (ret < 0) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "path resolution failed %s",
+ resolvedpath);
ret = -3;
goto err;
}
ret = nfs_loc_fill (loc, entryinode, parent, resolvedpath);
- if (ret < 0)
+ if (ret < 0) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "loc_fill failed %s",
+ resolvedpath);
ret = -3;
+ }
err:
if (parent)
@@ -369,11 +389,77 @@ err:
if (entryinode)
inode_unref (entryinode);
- if (resolvedpath)
- FREE (resolvedpath);
+ GF_FREE (resolvedpath);
return ret;
}
+uint32_t
+nfs_hash_gfid (uuid_t gfid)
+{
+ uint32_t hash = 0;
+ uint64_t msb64 = 0;
+ uint64_t lsb64 = 0;
+ uint32_t a1 = 0;
+ uint32_t a2 = 0;
+ uint32_t a3 = 0;
+ uint32_t a4 = 0;
+ uint32_t b1 = 0;
+ uint32_t b2 = 0;
+ if (__is_root_gfid (gfid))
+ return 0x1;
+
+ memcpy (&msb64, &gfid[8], 8);
+ memcpy (&lsb64, &gfid[0], 8);
+
+ a1 = (msb64 << 32);
+ a2 = (msb64 >> 32);
+ a3 = (lsb64 << 32);
+ a4 = (lsb64 >> 32);
+
+ b1 = a1 ^ a4;
+ b2 = a2 ^ a3;
+
+ hash = b1 ^ b2;
+
+ return hash;
+}
+
+
+void
+nfs_fix_generation (xlator_t *this, inode_t *inode)
+{
+ uint64_t raw_ctx = 0;
+ struct nfs_inode_ctx *ictx = NULL;
+ struct nfs_state *priv = NULL;
+ int ret = -1;
+
+ if (!inode) {
+ return;
+ }
+ priv = this->private;
+
+ if (inode_ctx_get(inode,this,&raw_ctx) == 0) {
+ ictx = (struct nfs_inode_ctx *)raw_ctx;
+ ictx->generation = priv->generation;
+ }
+ else {
+ ictx = GF_CALLOC (1, sizeof (struct nfs_inode_ctx),
+ gf_nfs_mt_inode_ctx);
+ if (!ictx) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "could not allocate nfs inode ctx");
+ return;
+ }
+ INIT_LIST_HEAD(&ictx->shares);
+ ictx->generation = priv->generation;
+ ret = inode_ctx_put (inode, this, (uint64_t)ictx);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "could not store nfs inode ctx");
+ return;
+ }
+ }
+}
diff --git a/xlators/nfs/server/src/nfs-common.h b/xlators/nfs/server/src/nfs-common.h
index 20003aa71..2e97f1563 100644
--- a/xlators/nfs/server/src/nfs-common.h
+++ b/xlators/nfs/server/src/nfs-common.h
@@ -1,20 +1,11 @@
/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
+ Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.com>
This file is part of GlusterFS.
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
*/
#ifndef _NFS_COMMON_H_
@@ -30,11 +21,14 @@
#include "xlator.h"
#include "rpcsvc.h"
#include "iatt.h"
+#include "uuid.h"
-#define NFS_PATH_MAX PATH_MAX
+//NFS_PATH_MAX hard-coded to 4096 as a work around for bug 2476.
+//nfs server crashes when path received is longer than PATH_MAX
+#define NFS_PATH_MAX 4096
#define NFS_NAME_MAX NAME_MAX
-#define NFS_DEFAULT_CREATE_MODE 0644
+#define NFS_DEFAULT_CREATE_MODE 0600
extern xlator_t *
nfs_xlid_to_xlator (xlator_list_t *cl, uint8_t xlid);
@@ -64,13 +58,24 @@ nfs_loc_fill (loc_t *loc, inode_t *inode, inode_t *parent, char *path);
#define NFS_RESOLVE_CREATE 2
extern int
-nfs_inode_loc_fill (inode_t *inode, loc_t *loc);
+nfs_inode_loc_fill (inode_t *inode, loc_t *loc, int how);
extern int
-nfs_ino_loc_fill (inode_table_t *itable, uint64_t ino, uint64_t gen, loc_t *l);
+nfs_ino_loc_fill (inode_table_t *itable, uuid_t gfid, loc_t *l);
extern int
-nfs_entry_loc_fill (inode_table_t *itable, ino_t ino, uint64_t gen, char *entry,
+nfs_entry_loc_fill (inode_table_t *itable, uuid_t pargfid, char *entry,
loc_t *loc, int how);
+extern int
+nfs_root_loc_fill (inode_table_t *itable, loc_t *loc);
+
+extern uint32_t
+nfs_hash_gfid (uuid_t gfid);
+
+extern int
+nfs_gfid_loc_fill (inode_table_t *itable, uuid_t gfid, loc_t *loc, int how);
+
+void
+nfs_fix_generation (xlator_t *this, inode_t *inode);
#endif
diff --git a/xlators/nfs/server/src/nfs-fops.c b/xlators/nfs/server/src/nfs-fops.c
index e7505b5dc..236b80c76 100644
--- a/xlators/nfs/server/src/nfs-fops.c
+++ b/xlators/nfs/server/src/nfs-fops.c
@@ -1,20 +1,11 @@
/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
+ Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.com>
This file is part of GlusterFS.
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
*/
#ifndef _CONFIG_H
@@ -22,6 +13,9 @@
#include "config.h"
#endif
+#include <grp.h>
+#include <pwd.h>
+
#include "dict.h"
#include "xlator.h"
#include "iobuf.h"
@@ -31,16 +25,79 @@
#include "nfs-fops.h"
#include "inode.h"
#include "nfs-common.h"
-
+#include "nfs3-helpers.h"
+#include "nfs-mem-types.h"
#include <libgen.h>
#include <semaphore.h>
-#define nfs_stack_destroy(fram) \
- do { \
- (fram)->local = NULL; \
- STACK_DESTROY ((fram)->root); \
- } while (0) \
+void
+nfs_fix_groups (xlator_t *this, call_stack_t *root)
+{
+ struct passwd mypw;
+ char mystrs[1024];
+ struct passwd *result;
+ gid_t mygroups[GF_MAX_AUX_GROUPS];
+ int ngroups;
+ int i;
+ struct nfs_state *priv = this->private;
+ const gid_list_t *agl;
+ gid_list_t gl;
+
+ if (!priv->server_aux_gids) {
+ return;
+ }
+ agl = gid_cache_lookup(&priv->gid_cache, root->uid);
+ if (agl) {
+ for (ngroups = 0; ngroups < agl->gl_count; ngroups++)
+ root->groups[ngroups] = agl->gl_list[ngroups];
+ root->ngrps = ngroups;
+ gid_cache_release(&priv->gid_cache, agl);
+ return;
+ }
+
+ /* No cached list found. */
+ if (getpwuid_r(root->uid,&mypw,mystrs,sizeof(mystrs),&result) != 0) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "getpwuid_r(%u) failed", root->uid);
+ return;
+ }
+
+ if (!result) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "getpwuid_r(%u) found nothing", root->uid);
+ return;
+ }
+
+ gf_log (this->name, GF_LOG_TRACE, "mapped %u => %s",
+ root->uid, result->pw_name);
+
+ ngroups = GF_MAX_AUX_GROUPS;
+ if (getgrouplist(result->pw_name,root->gid,mygroups,&ngroups) == -1) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "could not map %s to group list", result->pw_name);
+ return;
+ }
+
+ /* Add the group data to the cache. */
+ gl.gl_list = GF_CALLOC(ngroups, sizeof(gid_t), gf_nfs_mt_aux_gids);
+ if (gl.gl_list) {
+ /* It's not fatal if the alloc failed. */
+ gl.gl_id = root->uid;
+ gl.gl_count = ngroups;
+ memcpy(gl.gl_list, mygroups, sizeof(gid_t) * ngroups);
+ if (gid_cache_add(&priv->gid_cache, &gl) != 1)
+ GF_FREE(gl.gl_list);
+ }
+
+ /* Copy data to the frame. */
+ for (i = 0; i < ngroups; ++i) {
+ gf_log (this->name, GF_LOG_TRACE,
+ "%s is in group %u", result->pw_name, mygroups[i]);
+ root->groups[i] = mygroups[i];
+ }
+ root->ngrps = ngroups;
+}
struct nfs_fop_local *
nfs_fop_local_init (xlator_t *nfsx)
@@ -59,13 +116,9 @@ nfs_fop_local_init (xlator_t *nfsx)
void
nfs_fop_local_wipe (xlator_t *nfsx, struct nfs_fop_local *l)
{
- struct nfs_state *nfs = NULL;
-
if ((!nfsx) || (!l))
return;
- nfs = nfsx->private;
-
if (l->iobref)
iobref_unref (l->iobref);
@@ -78,11 +131,44 @@ nfs_fop_local_wipe (xlator_t *nfsx, struct nfs_fop_local *l)
if (l->newparent)
inode_unref (l->newparent);
- mem_put (nfs->foppool, l);
+ if (l->dictgfid)
+ dict_unref (l->dictgfid);
+
+ mem_put (l);
return;
}
+#define nfs_stack_destroy(nfl, fram) \
+ do { \
+ nfs_fop_local_wipe ((nfl)->nfsx, nfl); \
+ (fram)->local = NULL; \
+ STACK_DESTROY ((fram)->root); \
+ } while (0) \
+
+
+pthread_mutex_t ctr = PTHREAD_MUTEX_INITIALIZER;
+unsigned int cval = 1;
+
+
+int
+nfs_frame_getctr ()
+{
+ uint64_t val = 0;
+
+ pthread_mutex_lock (&ctr);
+ {
+ if (cval == 0)
+ cval = 1;
+ val = cval;
+ cval++;
+ }
+ pthread_mutex_unlock (&ctr);
+
+ return val;
+}
+
+
call_frame_t *
nfs_create_frame (xlator_t *xl, nfs_user_t *nfu)
{
@@ -96,27 +182,41 @@ nfs_create_frame (xlator_t *xl, nfs_user_t *nfu)
frame = create_frame (xl, (call_pool_t *)xl->ctx->pool);
if (!frame)
goto err;
+ if (call_stack_alloc_groups (frame->root, nfu->ngrps) != 0) {
+ STACK_DESTROY (frame->root);
+ frame = NULL;
+ goto err;
+ }
+
+ frame->root->pid = NFS_PID;
frame->root->uid = nfu->uid;
frame->root->gid = nfu->gids[NFS_PRIMGID_IDX];
- if (nfu->ngrps == 1)
- goto err; /* Done, we only got primary gid */
+ frame->root->lk_owner = nfu->lk_owner;
- frame->root->ngrps = nfu->ngrps - 1;
+ if (nfu->ngrps != 1) {
+ frame->root->ngrps = nfu->ngrps - 1;
- gf_log (GF_NFS, GF_LOG_TRACE,"uid: %d, gid %d, gids: %d",
- frame->root->uid, frame->root->gid, frame->root->ngrps);
- for(y = 0, x = 1; y < frame->root->ngrps; x++,y++) {
- gf_log (GF_NFS, GF_LOG_TRACE, "gid: %d", nfu->gids[x]);
- frame->root->groups[y] = nfu->gids[x];
+ gf_log (GF_NFS, GF_LOG_TRACE,"uid: %d, gid %d, gids: %d",
+ frame->root->uid, frame->root->gid, frame->root->ngrps);
+ for(y = 0, x = 1; y < frame->root->ngrps; x++,y++) {
+ gf_log (GF_NFS, GF_LOG_TRACE, "gid: %d", nfu->gids[x]);
+ frame->root->groups[y] = nfu->gids[x];
+ }
}
+ /*
+ * It's tempting to do this *instead* of using nfu above, but we need
+ * to have those values in case nfs_fix_groups doesn't do anything.
+ */
+ nfs_fix_groups(xl,frame->root);
+
err:
return frame;
}
#define nfs_fop_handle_frame_create(fram, xla, nfuser, retval, errlabel) \
do { \
- fram = nfs_create_frame (xla, (nfuser)); \
+ fram = nfs_create_frame (xla, (nfuser)); \
if (!fram) { \
retval = (-ENOMEM); \
gf_log (GF_NFS, GF_LOG_ERROR,"Frame creation failed");\
@@ -128,28 +228,31 @@ err:
* for us to determine in the callback whether to funge the ino in the stat buf
* with 1 for the parent.
*/
-#define nfs_fop_save_root_ino(locl, loc) \
- do { \
- if ((loc)->ino == 1) \
- (locl)->rootinode = 1; \
- else if (((loc)->parent) && ((loc)->parent->ino == 1)) \
- (locl)->rootparentinode = 1; \
- } while (0) \
+#define nfs_fop_save_root_ino(locl, loc) \
+ do { \
+ if (((loc)->inode) && \
+ __is_root_gfid ((loc)->inode->gfid)) \
+ (locl)->rootinode = 1; \
+ else if (((loc)->parent) && \
+ __is_root_gfid ((loc)->parent->gfid)) \
+ (locl)->rootparentinode = 1; \
+ } while (0)
/* Do the same for an fd */
-#define nfs_fop_save_root_fd_ino(locl, fdesc) \
- do { \
- if ((fdesc)->inode->ino == 1) \
- (locl)->rootinode = 1; \
- } while (0) \
-
+#define nfs_fop_save_root_fd_ino(locl, fdesc) \
+ do { \
+ if (__is_root_gfid ((fdesc)->inode->gfid)) \
+ (locl)->rootinode = 1; \
+ } while (0)
/* Use the state saved by the previous macro to funge the ino in the appropriate
* structure.
*/
-#define nfs_fop_restore_root_ino(locl, preattr, postattr, prepar, postpar) \
+#define nfs_fop_restore_root_ino(locl, fopret, preattr, postattr, prepar, postpar) \
do { \
+ if (fopret == -1) \
+ break; \
if ((locl)->rootinode) { \
if ((preattr)) { \
((struct iatt *)(preattr))->ia_ino = 1; \
@@ -174,17 +277,21 @@ err:
/* If the newly created, inode's parent is root, we'll need to funge the ino
* in the parent attr when we receive them in the callback.
*/
-#define nfs_fop_newloc_save_root_ino(locl, newloc) \
- do { \
- if ((newloc)->ino == 1) \
- (locl)->newrootinode = 1; \
- else if (((newloc)->parent) && ((newloc)->parent->ino == 1)) \
- (locl)->newrootparentinode = 1; \
- } while (0) \
-
-
-#define nfs_fop_newloc_restore_root_ino(locl, preattr, postattr, prepar, postpar) \
+#define nfs_fop_newloc_save_root_ino(locl, newloc) \
+ do { \
+ if (((newloc)->inode) && \
+ __is_root_gfid ((newloc)->inode->gfid)) \
+ (locl)->newrootinode = 1; \
+ else if (((newloc)->parent) && \
+ __is_root_gfid ((newloc)->parent->gfid)) \
+ (locl)->newrootparentinode = 1; \
+ } while (0)
+
+#define nfs_fop_newloc_restore_root_ino(locl, fopret, preattr, postattr, prepar, postpar) \
do { \
+ if (fopret == -1) \
+ break; \
+ \
if ((locl)->newrootinode) { \
if ((preattr)) \
((struct iatt *)(preattr))->ia_ino = 1; \
@@ -198,6 +305,51 @@ err:
} \
} while (0) \
+dict_t *
+nfs_gfid_dict (inode_t *inode)
+{
+ uuid_t newgfid = {0, };
+ char *dyngfid = NULL;
+ dict_t *dictgfid = NULL;
+ int ret = -1;
+ uuid_t rootgfid = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
+
+ dyngfid = GF_CALLOC (1, sizeof (uuid_t), gf_common_mt_char);
+ uuid_generate (newgfid);
+
+ if (uuid_compare (inode->gfid, rootgfid) == 0)
+ memcpy (dyngfid, rootgfid, sizeof (uuid_t));
+ else
+ memcpy (dyngfid, newgfid, sizeof (uuid_t));
+
+ dictgfid = dict_new ();
+ if (!dictgfid) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to create gfid dict");
+ goto out;
+ }
+
+ ret = dict_set_bin (dictgfid, "gfid-req", dyngfid, sizeof (uuid_t));
+ if (ret < 0) {
+ dict_unref (dictgfid);
+ dictgfid = NULL;
+ }
+
+out:
+ return dictgfid;
+}
+
+#define nfs_fop_gfid_setup(nflcl, inode, retval, erlbl) \
+ do { \
+ if (nflcl) { \
+ (nflcl)->dictgfid = nfs_gfid_dict (inode); \
+ \
+ if (!((nflcl)->dictgfid)) { \
+ retval = -EFAULT; \
+ goto erlbl; \
+ } \
+ } \
+ } while (0) \
+
/* Fops Layer Explained
* The fops layer has three types of functions. They can all be identified by
* their names. Here are the three patterns:
@@ -212,7 +364,7 @@ err:
*
* nfs_<fopname>
* Unlike the nfs_fop_<fopname> variety, this is the stateful type of fop, in
- * that it silently performs all the relevant GlusterFS state maintainence
+ * that it silently performs all the relevant GlusterFS state maintenance
* operations on the data returned to the callbacks, leaving the caller's
* callback to just use the data returned for whatever it needs to do with that
* data, for eg. the nfs_lookup, will take care of looking up the inodes,
@@ -231,13 +383,17 @@ nfs_fop_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
struct nfs_fop_local *local = NULL;
fop_lookup_cbk_t progcbk;
+ if (op_ret == 0) {
+ nfs_fix_generation(this,inode);
+ }
+
nfl_to_prog_data (local, progcbk, frame);
- nfs_fop_restore_root_ino (local, buf, NULL, NULL, postparent);
+ nfs_fop_restore_root_ino (local, op_ret, buf, NULL, NULL, postparent);
if (progcbk)
progcbk (frame, cookie, this, op_ret, op_errno, inode, buf,
xattr, postparent);
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (local, frame);
return 0;
}
@@ -254,37 +410,83 @@ nfs_fop_lookup (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc,
return ret;
gf_log (GF_NFS, GF_LOG_TRACE, "Lookup: %s", loc->path);
- nfs_fop_handle_frame_create (frame, xl, nfu, ret, err);
+ nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);
nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);
nfs_fop_save_root_ino (nfl, loc);
+ nfs_fop_gfid_setup (nfl, loc->inode, ret, err);
- STACK_WIND_COOKIE (frame, nfs_fop_lookup_cbk, nfsx, xl,
- xl->fops->lookup, loc, NULL);
+ STACK_WIND_COOKIE (frame, nfs_fop_lookup_cbk, xl, xl,
+ xl->fops->lookup, loc, nfl->dictgfid);
ret = 0;
err:
if (ret < 0) {
if (frame)
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (nfl, frame);
}
return ret;
}
+int32_t
+nfs_fop_access_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, dict_t *xdata)
+{
+ struct nfs_fop_local *nfl = NULL;
+ fop_access_cbk_t progcbk = NULL;
+
+ nfl_to_prog_data (nfl, progcbk, frame);
+ if (progcbk)
+ progcbk (frame, cookie, this, op_ret, op_errno, xdata);
+
+ nfs_stack_destroy (nfl, frame);
+ return 0;
+}
+
+int
+nfs_fop_access (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc,
+ int32_t accesstest, fop_access_cbk_t cbk, void *local)
+{
+ call_frame_t *frame = NULL;
+ int ret = -EFAULT;
+ struct nfs_fop_local *nfl = NULL;
+ uint32_t accessbits = 0;
+
+ if ((!xl) || (!loc) || (!nfu))
+ return ret;
+
+ gf_log (GF_NFS, GF_LOG_TRACE, "Access: %s", loc->path);
+ nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);
+ nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);
+ nfs_fop_save_root_ino (nfl, loc);
+
+ accessbits = nfs3_request_to_accessbits (accesstest);
+ STACK_WIND_COOKIE (frame, nfs_fop_access_cbk, xl, xl, xl->fops->access,
+ loc, accessbits, NULL);
+ ret = 0;
+err:
+ if (ret < 0) {
+ if (frame)
+ nfs_stack_destroy (nfl, frame);
+ }
+
+ return ret;
+}
int32_t
nfs_fop_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno, struct iatt *buf)
+ int32_t op_ret, int32_t op_errno, struct iatt *buf,
+ dict_t *xdata)
{
struct nfs_fop_local *nfl = NULL;
fop_stat_cbk_t progcbk = NULL;
nfl_to_prog_data (nfl, progcbk, frame);
- nfs_fop_restore_root_ino (nfl, buf, NULL, NULL, NULL);
+ nfs_fop_restore_root_ino (nfl, op_ret, buf, NULL, NULL, NULL);
if (progcbk)
- progcbk (frame, cookie, this, op_ret, op_errno, buf);
+ progcbk (frame, cookie, this, op_ret, op_errno, buf, xdata);
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (nfl, frame);
return 0;
}
@@ -301,17 +503,17 @@ nfs_fop_stat (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc,
return ret;
gf_log (GF_NFS, GF_LOG_TRACE, "Stat: %s", loc->path);
- nfs_fop_handle_frame_create (frame, xl, nfu, ret, err);
+ nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);
nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);
nfs_fop_save_root_ino (nfl, loc);
- STACK_WIND_COOKIE (frame, nfs_fop_stat_cbk, nfsx, xl, xl->fops->stat,
- loc);
+ STACK_WIND_COOKIE (frame, nfs_fop_stat_cbk, xl, xl, xl->fops->stat,
+ loc, NULL);
ret = 0;
err:
if (ret < 0) {
if (frame)
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (nfl, frame);
}
return ret;
@@ -320,17 +522,18 @@ err:
int32_t
nfs_fop_fstat_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno, struct iatt *buf)
+ int32_t op_ret, int32_t op_errno, struct iatt *buf,
+ dict_t *xdata)
{
struct nfs_fop_local *nfl = NULL;
fop_fstat_cbk_t progcbk = NULL;
nfl_to_prog_data (nfl, progcbk, frame);
- nfs_fop_restore_root_ino (nfl, buf, NULL, NULL, NULL);
+ nfs_fop_restore_root_ino (nfl, op_ret, buf, NULL, NULL, NULL);
if (progcbk)
- progcbk (frame, cookie, this, op_ret, op_errno, buf);
+ progcbk (frame, cookie, this, op_ret, op_errno, buf, xdata);
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (nfl, frame);
return 0;
}
@@ -347,18 +550,18 @@ nfs_fop_fstat (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd,
return ret;
gf_log (GF_NFS, GF_LOG_TRACE, "FStat");
- nfs_fop_handle_frame_create (frame, xl, nfu, ret, err);
+ nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);
nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);
nfs_fop_save_root_fd_ino (nfl, fd);
- STACK_WIND_COOKIE (frame, nfs_fop_fstat_cbk, nfsx, xl, xl->fops->fstat,
- fd);
+ STACK_WIND_COOKIE (frame, nfs_fop_fstat_cbk, xl, xl, xl->fops->fstat,
+ fd, NULL);
ret = 0;
err:
if (ret < 0) {
if (frame)
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (nfl, frame);
}
return ret;
@@ -367,15 +570,15 @@ err:
int32_t
nfs_fop_opendir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno, fd_t *fd)
+ int32_t op_ret, int32_t op_errno, fd_t *fd, dict_t *xdata)
{
struct nfs_fop_local *nfl = NULL;
fop_opendir_cbk_t progcbk = NULL;
nfl_to_prog_data (nfl, progcbk, frame);
if (progcbk)
- progcbk (frame, cookie, this, op_ret, op_errno, fd);
- nfs_stack_destroy (frame);
+ progcbk (frame, cookie, this, op_ret, op_errno, fd, xdata);
+ nfs_stack_destroy (nfl, frame);
return 0;
}
@@ -392,17 +595,17 @@ nfs_fop_opendir (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
return ret;
gf_log (GF_NFS, GF_LOG_TRACE, "Opendir: %s", pathloc->path);
- nfs_fop_handle_frame_create (frame, xl, nfu, ret, err);
+ nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);
nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);
- STACK_WIND_COOKIE (frame, nfs_fop_opendir_cbk, nfsx, xl,
- xl->fops->opendir, pathloc, dirfd);
+ STACK_WIND_COOKIE (frame, nfs_fop_opendir_cbk, xl, xl,
+ xl->fops->opendir, pathloc, dirfd, NULL);
ret = 0;
err:
if (ret < 0) {
if (frame)
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (nfl, frame);
}
return ret;
@@ -410,16 +613,16 @@ err:
int
nfs_fop_flush_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno)
+ int32_t op_ret, int32_t op_errno, dict_t *xdata)
{
struct nfs_fop_local *nfl = NULL;
fop_flush_cbk_t progcbk = NULL;
nfl_to_prog_data (nfl, progcbk, frame);
if (progcbk)
- progcbk (frame, cookie, this, op_ret, op_errno);
+ progcbk (frame, cookie, this, op_ret, op_errno, xdata);
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (nfl, frame);
return 0;
}
@@ -435,16 +638,16 @@ nfs_fop_flush (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd,
if ((!nfsx) || (!xl) || (!fd) || (!nfu))
return ret;
- nfs_fop_handle_frame_create (frame, xl, nfu, ret, err);
+ nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);
nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);
- STACK_WIND_COOKIE (frame, nfs_fop_flush_cbk, nfsx, xl, xl->fops->flush,
- fd);
+ STACK_WIND_COOKIE (frame, nfs_fop_flush_cbk, xl, xl, xl->fops->flush,
+ fd, NULL);
ret = 0;
err:
if (ret < 0) {
if (frame)
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (nfl, frame);
}
return ret;
@@ -453,16 +656,17 @@ err:
int32_t
nfs_fop_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno, gf_dirent_t *entries)
+ int32_t op_ret, int32_t op_errno, gf_dirent_t *entries,
+ dict_t *xdata)
{
struct nfs_fop_local *nfl = NULL;
fop_readdirp_cbk_t progcbk = NULL;
nfl_to_prog_data (nfl, progcbk, frame);
if (progcbk)
- progcbk (frame, cookie, this, op_ret, op_errno, entries);
+ progcbk (frame, cookie, this, op_ret, op_errno, entries, xdata);
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (nfl, frame);
return 0;
}
@@ -481,17 +685,17 @@ nfs_fop_readdirp (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *dirfd,
return ret;
gf_log (GF_NFS, GF_LOG_TRACE, "readdir");
- nfs_fop_handle_frame_create (frame, xl, nfu, ret, err);
+ nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);
nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);
- STACK_WIND_COOKIE (frame, nfs_fop_readdirp_cbk, nfsx, xl,
- xl->fops->readdirp, dirfd, bufsize, offset);
+ STACK_WIND_COOKIE (frame, nfs_fop_readdirp_cbk, xl, xl,
+ xl->fops->readdirp, dirfd, bufsize, offset, 0);
ret = 0;
err:
if (ret < 0) {
if (frame)
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (nfl, frame);
}
return ret;
@@ -500,7 +704,8 @@ err:
int32_t
nfs_fop_statfs_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno, struct statvfs *buf)
+ int32_t op_ret, int32_t op_errno, struct statvfs *buf,
+ dict_t *xdata)
{
struct nfs_fop_local *nfl = NULL;
@@ -508,9 +713,9 @@ nfs_fop_statfs_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
nfl_to_prog_data (nfl, progcbk, frame);
if (progcbk)
- progcbk (frame, cookie, this, op_ret, op_errno, buf);
+ progcbk (frame, cookie, this, op_ret, op_errno, buf, xdata);
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (nfl, frame);
return 0;
}
@@ -527,16 +732,16 @@ nfs_fop_statfs (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
return ret;
gf_log (GF_NFS, GF_LOG_TRACE, "Statfs: %s", pathloc->path);
- nfs_fop_handle_frame_create (frame, xl, nfu, ret, err);
+ nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);
nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);
- STACK_WIND_COOKIE (frame, nfs_fop_statfs_cbk, nfsx, xl,
- xl->fops->statfs, pathloc);
+ STACK_WIND_COOKIE (frame, nfs_fop_statfs_cbk, xl, xl,
+ xl->fops->statfs, pathloc, NULL);
ret = 0;
err:
if (ret < 0) {
if (frame)
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (nfl, frame);
}
return ret;
@@ -547,18 +752,23 @@ int32_t
nfs_fop_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, fd_t *fd, inode_t *inode,
struct iatt *buf, struct iatt *preparent,
- struct iatt *postparent)
+ struct iatt *postparent, dict_t *xdata)
{
struct nfs_fop_local *nfl = NULL;
fop_create_cbk_t progcbk = NULL;
+ if (op_ret == 0) {
+ nfs_fix_generation(this,inode);
+ }
+
nfl_to_prog_data (nfl, progcbk, frame);
- nfs_fop_restore_root_ino (nfl, buf, NULL, preparent, postparent);
+ nfs_fop_restore_root_ino (nfl, op_ret, buf, NULL, preparent,
+ postparent);
if (progcbk)
progcbk (frame, cookie, this, op_ret, op_errno, fd, inode, buf,
- preparent, postparent);
+ preparent, postparent, NULL);
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (nfl, frame);
return 0;
}
@@ -576,17 +786,19 @@ nfs_fop_create (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
return ret;
gf_log (GF_NFS, GF_LOG_TRACE, "Create: %s", pathloc->path);
- nfs_fop_handle_frame_create (frame, xl, nfu, ret, err);
+ nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);
nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);
nfs_fop_save_root_ino (nfl, pathloc);
+ nfs_fop_gfid_setup (nfl, pathloc->inode, ret, err);
+
+ STACK_WIND_COOKIE (frame, nfs_fop_create_cbk, xl, xl, xl->fops->create,
+ pathloc, flags, mode, 0, fd, nfl->dictgfid);
- STACK_WIND_COOKIE (frame, nfs_fop_create_cbk, nfsx, xl,xl->fops->create
- , pathloc, flags, mode, fd);
ret = 0;
err:
if (ret < 0) {
if (frame)
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (nfl, frame);
}
return ret;
@@ -596,16 +808,17 @@ err:
int32_t
nfs_fop_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, struct iatt *pre,
- struct iatt *post)
+ struct iatt *post, dict_t *xdata)
{
struct nfs_fop_local *nfl = NULL;
fop_setattr_cbk_t progcbk = NULL;
nfl_to_prog_data (nfl, progcbk, frame);
- nfs_fop_restore_root_ino (nfl, pre, post, NULL, NULL);
+ nfs_fop_restore_root_ino (nfl, op_ret, pre, post, NULL, NULL);
if (progcbk)
- progcbk (frame, cookie, this, op_ret, op_errno, pre, post);
- nfs_stack_destroy (frame);
+ progcbk (frame, cookie, this, op_ret, op_errno, pre, post,
+ xdata);
+ nfs_stack_destroy (nfl, frame);
return 0;
}
@@ -624,17 +837,17 @@ nfs_fop_setattr (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
return ret;
gf_log (GF_NFS, GF_LOG_TRACE, "Setattr: %s", pathloc->path);
- nfs_fop_handle_frame_create (frame, xl, nfu, ret, err);
+ nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);
nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);
nfs_fop_save_root_ino (nfl, pathloc);
- STACK_WIND_COOKIE (frame, nfs_fop_setattr_cbk, nfsx, xl,
- xl->fops->setattr, pathloc, buf, valid);
+ STACK_WIND_COOKIE (frame, nfs_fop_setattr_cbk, xl, xl,
+ xl->fops->setattr, pathloc, buf, valid, NULL);
ret = 0;
err:
if (ret < 0) {
if (frame)
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (nfl, frame);
}
return ret;
@@ -645,17 +858,21 @@ int32_t
nfs_fop_mkdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, inode_t *inode,
struct iatt *buf, struct iatt *preparent,
- struct iatt *postparent)
+ struct iatt *postparent, dict_t *xdata)
{
struct nfs_fop_local *nfl = NULL;
fop_mkdir_cbk_t progcbk = NULL;
+ if (op_ret == 0) {
+ nfs_fix_generation(this,inode);
+ }
+
nfl_to_prog_data (nfl, progcbk, frame);
- nfs_fop_restore_root_ino (nfl, buf, NULL, preparent, postparent);
+ nfs_fop_restore_root_ino (nfl, op_ret, buf, NULL,preparent, postparent);
if (progcbk)
progcbk (frame, cookie, this, op_ret, op_errno, inode, buf,
- preparent, postparent);
- nfs_stack_destroy (frame);
+ preparent, postparent, xdata);
+ nfs_stack_destroy (nfl, frame);
return 0;
}
@@ -672,17 +889,18 @@ nfs_fop_mkdir (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
return ret;
gf_log (GF_NFS, GF_LOG_TRACE, "Mkdir: %s", pathloc->path);
- nfs_fop_handle_frame_create (frame, xl, nfu, ret, err);
+ nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);
nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);
nfs_fop_save_root_ino (nfl, pathloc);
+ nfs_fop_gfid_setup (nfl, pathloc->inode, ret, err);
- STACK_WIND_COOKIE (frame, nfs_fop_mkdir_cbk, nfsx, xl, xl->fops->mkdir,
- pathloc, mode);
+ STACK_WIND_COOKIE (frame, nfs_fop_mkdir_cbk, xl, xl, xl->fops->mkdir,
+ pathloc, mode, 0, nfl->dictgfid);
ret = 0;
err:
if (ret < 0) {
if (frame)
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (nfl, frame);
}
return ret;
@@ -693,17 +911,21 @@ int32_t
nfs_fop_symlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, inode_t *inode,
struct iatt *buf, struct iatt *preparent,
- struct iatt *postparent)
+ struct iatt *postparent, dict_t *xdata)
{
struct nfs_fop_local *nfl = NULL;
fop_symlink_cbk_t progcbk = NULL;
+ if (op_ret == 0) {
+ nfs_fix_generation(this,inode);
+ }
+
nfl_to_prog_data (nfl, progcbk, frame);
- nfs_fop_restore_root_ino (nfl, buf, NULL, preparent, postparent);
+ nfs_fop_restore_root_ino (nfl, op_ret,buf, NULL, preparent, postparent);
if (progcbk)
progcbk (frame, cookie, this, op_ret, op_errno, inode, buf,
- preparent, postparent);
- nfs_stack_destroy (frame);
+ preparent, postparent, xdata);
+ nfs_stack_destroy (nfl, frame);
return 0;
}
@@ -719,17 +941,19 @@ nfs_fop_symlink (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, char *target,
return ret;
gf_log (GF_NFS, GF_LOG_TRACE, "Symlink: %s", pathloc->path);
- nfs_fop_handle_frame_create (frame, xl, nfu, ret, err);
+ nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);
nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);
nfs_fop_save_root_ino (nfl, pathloc);
+ nfs_fop_gfid_setup (nfl, pathloc->inode, ret, err);
- STACK_WIND_COOKIE (frame, nfs_fop_symlink_cbk, nfsx, xl,
- xl->fops->symlink, target, pathloc);
+ STACK_WIND_COOKIE (frame, nfs_fop_symlink_cbk, xl, xl,
+ xl->fops->symlink, target, pathloc,
+ 0, nfl->dictgfid);
ret = 0;
err:
if (ret < 0) {
if (frame)
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (nfl, frame);
}
return ret;
@@ -739,16 +963,17 @@ err:
int32_t
nfs_fop_readlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, const char *path,
- struct iatt *buf)
+ struct iatt *buf, dict_t *xdata)
{
struct nfs_fop_local *nfl = NULL;
fop_readlink_cbk_t progcbk = NULL;
nfl_to_prog_data (nfl, progcbk, frame);
- nfs_fop_restore_root_ino (nfl, buf, NULL, NULL, NULL);
+ nfs_fop_restore_root_ino (nfl, op_ret, buf, NULL, NULL, NULL);
if (progcbk)
- progcbk (frame, cookie, this, op_ret, op_errno, path, buf);
- nfs_stack_destroy (frame);
+ progcbk (frame, cookie, this, op_ret, op_errno, path, buf,
+ xdata);
+ nfs_stack_destroy (nfl, frame);
return 0;
}
@@ -765,17 +990,17 @@ nfs_fop_readlink (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
return ret;
gf_log (GF_NFS, GF_LOG_TRACE, "Readlink: %s", pathloc->path);
- nfs_fop_handle_frame_create (frame, xl, nfu, ret, err);
+ nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);
nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);
nfs_fop_save_root_ino (nfl, pathloc);
- STACK_WIND_COOKIE (frame, nfs_fop_readlink_cbk, nfsx, xl,
- xl->fops->readlink, pathloc, size);
+ STACK_WIND_COOKIE (frame, nfs_fop_readlink_cbk, xl, xl,
+ xl->fops->readlink, pathloc, size, NULL);
ret = 0;
err:
if (ret < 0) {
if (frame)
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (nfl, frame);
}
return ret;
@@ -786,17 +1011,21 @@ int32_t
nfs_fop_mknod_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, inode_t *inode,
struct iatt *buf, struct iatt *preparent,
- struct iatt *postparent)
+ struct iatt *postparent, dict_t *xdata)
{
struct nfs_fop_local *nfl = NULL;
fop_mknod_cbk_t progcbk = NULL;
+ if (op_ret == 0) {
+ nfs_fix_generation(this,inode);
+ }
+
nfl_to_prog_data (nfl, progcbk, frame);
- nfs_fop_restore_root_ino (nfl, buf, NULL, preparent, postparent);
+ nfs_fop_restore_root_ino (nfl, op_ret,buf, NULL, preparent, postparent);
if (progcbk)
progcbk (frame, cookie, this, op_ret, op_errno, inode, buf,
- preparent, postparent);
- nfs_stack_destroy (frame);
+ preparent, postparent, xdata);
+ nfs_stack_destroy (nfl, frame);
return 0;
}
@@ -813,17 +1042,18 @@ nfs_fop_mknod (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
return ret;
gf_log (GF_NFS, GF_LOG_TRACE, "Mknod: %s", pathloc->path);
- nfs_fop_handle_frame_create (frame, xl, nfu, ret, err);
+ nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);
nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);
nfs_fop_save_root_ino (nfl, pathloc);
+ nfs_fop_gfid_setup (nfl, pathloc->inode, ret, err);
- STACK_WIND_COOKIE (frame, nfs_fop_mknod_cbk, nfsx, xl, xl->fops->mknod,
- pathloc, mode, dev);
+ STACK_WIND_COOKIE (frame, nfs_fop_mknod_cbk, xl, xl, xl->fops->mknod,
+ pathloc, mode, dev, 0, nfl->dictgfid);
ret = 0;
err:
if (ret < 0) {
if (frame)
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (nfl, frame);
}
return ret;
@@ -832,17 +1062,18 @@ err:
int32_t
nfs_fop_rmdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, struct iatt *preparent,
- struct iatt *postparent)
+ struct iatt *postparent, dict_t *xdata)
{
struct nfs_fop_local *nfl = frame->local;
fop_rmdir_cbk_t progcbk = NULL;
nfl_to_prog_data (nfl, progcbk, frame);
- nfs_fop_restore_root_ino (nfl, NULL, NULL, preparent, postparent);
+ nfs_fop_restore_root_ino (nfl, op_ret, NULL, NULL, preparent,
+ postparent);
if (progcbk)
progcbk (frame, cookie, this, op_ret, op_errno, preparent,
- postparent);
- nfs_stack_destroy (frame);
+ postparent, NULL);
+ nfs_stack_destroy (nfl, frame);
return 0;
}
@@ -860,17 +1091,17 @@ nfs_fop_rmdir (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
return ret;
gf_log (GF_NFS, GF_LOG_TRACE, "Rmdir: %s", pathloc->path);
- nfs_fop_handle_frame_create (frame, xl, nfu, ret, err);
+ nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);
nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);
nfs_fop_save_root_ino (nfl, pathloc);
- STACK_WIND_COOKIE (frame, nfs_fop_rmdir_cbk, nfsx, xl, xl->fops->rmdir,
- pathloc);
+ STACK_WIND_COOKIE (frame, nfs_fop_rmdir_cbk, xl, xl, xl->fops->rmdir,
+ pathloc, 0, NULL);
ret = 0;
err:
if (ret < 0) {
if (frame)
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (nfl, frame);
}
return ret;
@@ -881,17 +1112,18 @@ err:
int32_t
nfs_fop_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, struct iatt *preparent,
- struct iatt *postparent)
+ struct iatt *postparent, dict_t *xdata)
{
struct nfs_fop_local *nfl = frame->local;
fop_unlink_cbk_t progcbk = NULL;
nfl_to_prog_data (nfl, progcbk, frame);
- nfs_fop_restore_root_ino (nfl, NULL, NULL, preparent, postparent);
+ nfs_fop_restore_root_ino (nfl, op_ret, NULL, NULL, preparent,
+ postparent);
if (progcbk)
progcbk (frame, cookie, this, op_ret, op_errno, preparent,
- postparent);
- nfs_stack_destroy (frame);
+ postparent, xdata);
+ nfs_stack_destroy (nfl, frame);
return 0;
}
@@ -908,17 +1140,17 @@ nfs_fop_unlink (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
return ret;
gf_log (GF_NFS, GF_LOG_TRACE, "Unlink: %s", pathloc->path);
- nfs_fop_handle_frame_create (frame, xl, nfu, ret, err);
+ nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);
nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);
nfs_fop_save_root_ino (nfl, pathloc);
- STACK_WIND_COOKIE (frame, nfs_fop_unlink_cbk, nfsx, xl,
- xl->fops->unlink, pathloc);
+ STACK_WIND_COOKIE (frame, nfs_fop_unlink_cbk, xl, xl,
+ xl->fops->unlink, pathloc, 0, NULL);
ret = 0;
err:
if (ret < 0) {
if (frame)
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (nfl, frame);
}
return ret;
@@ -930,18 +1162,23 @@ int32_t
nfs_fop_link_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, inode_t *inode,
struct iatt *buf, struct iatt *preparent,
- struct iatt *postparent)
+ struct iatt *postparent, dict_t *xdata)
{
struct nfs_fop_local *nfl = NULL;
fop_link_cbk_t progcbk = NULL;
+ if (op_ret == 0) {
+ nfs_fix_generation(this,inode);
+ }
+
nfl_to_prog_data (nfl, progcbk, frame);
- nfs_fop_restore_root_ino (nfl, buf, NULL, preparent, postparent);
+ nfs_fop_restore_root_ino (nfl, op_ret, buf, NULL, preparent,
+ postparent);
if (progcbk)
progcbk (frame, cookie, this, op_ret, op_errno, inode, buf,
- preparent, postparent);
+ preparent, postparent, xdata);
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (nfl, frame);
return 0;
}
@@ -959,17 +1196,17 @@ nfs_fop_link (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *oldloc,
gf_log (GF_NFS, GF_LOG_TRACE, "Link: %s -> %s", newloc->path,
oldloc->path);
- nfs_fop_handle_frame_create (frame, xl, nfu, ret, err);
+ nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);
nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);
nfs_fop_save_root_ino (nfl, newloc);
- STACK_WIND_COOKIE (frame, nfs_fop_link_cbk, nfsx, xl, xl->fops->link,
- oldloc, newloc);
+ STACK_WIND_COOKIE (frame, nfs_fop_link_cbk, xl, xl, xl->fops->link,
+ oldloc, newloc, NULL);
ret = 0;
err:
if (ret < 0) {
if (frame)
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (nfl, frame);
}
return ret;
@@ -980,7 +1217,8 @@ int32_t
nfs_fop_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, struct iatt *buf,
struct iatt *preoldparent, struct iatt *postoldparent,
- struct iatt *prenewparent, struct iatt *postnewparent)
+ struct iatt *prenewparent, struct iatt *postnewparent,
+ dict_t *xdata)
{
struct nfs_fop_local *nfl = NULL;
@@ -989,16 +1227,17 @@ nfs_fop_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
nfl_to_prog_data (nfl, progcbk, frame);
/* The preattr arg needs to be NULL instead of @buf because it is
* possible that the new parent is not root whereas the source dir
- * could've been. That is handled in the next macro.
+ * could have been. That is handled in the next macro.
*/
- nfs_fop_restore_root_ino (nfl, NULL, NULL, preoldparent, postoldparent);
- nfs_fop_newloc_restore_root_ino (nfl, buf, NULL, prenewparent,
+ nfs_fop_restore_root_ino (nfl, op_ret, NULL, NULL, preoldparent,
+ postoldparent);
+ nfs_fop_newloc_restore_root_ino (nfl, op_ret, buf, NULL, prenewparent,
postnewparent);
if (progcbk)
progcbk (frame, cookie, this, op_ret, op_errno, buf,
preoldparent, postoldparent, prenewparent,
- postnewparent);
- nfs_stack_destroy (frame);
+ postnewparent, xdata);
+ nfs_stack_destroy (nfl, frame);
return 0;
}
@@ -1016,18 +1255,18 @@ nfs_fop_rename (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *oldloc,
gf_log (GF_NFS, GF_LOG_TRACE, "Rename: %s -> %s", oldloc->path,
newloc->path);
- nfs_fop_handle_frame_create (frame, xl, nfu, ret, err);
+ nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);
nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);
nfs_fop_save_root_ino (nfl, oldloc);
nfs_fop_newloc_save_root_ino (nfl, newloc);
- STACK_WIND_COOKIE (frame, nfs_fop_rename_cbk, nfsx, xl,
- xl->fops->rename, oldloc, newloc);
+ STACK_WIND_COOKIE (frame, nfs_fop_rename_cbk, xl, xl,
+ xl->fops->rename, oldloc, newloc, NULL);
ret = 0;
err:
if (ret < 0) {
if (frame)
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (nfl, frame);
}
return ret;
@@ -1036,22 +1275,22 @@ err:
int32_t
nfs_fop_open_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno, fd_t *fd)
+ int32_t op_ret, int32_t op_errno, fd_t *fd, dict_t *xdata)
{
struct nfs_fop_local *nfl = NULL;
fop_open_cbk_t progcbk = NULL;
nfl_to_prog_data (nfl, progcbk, frame);
if (progcbk)
- progcbk (frame, cookie, this, op_ret, op_errno, fd);
- nfs_stack_destroy (frame);
+ progcbk (frame, cookie, this, op_ret, op_errno, fd, xdata);
+ nfs_stack_destroy (nfl, frame);
return 0;
}
int
nfs_fop_open (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc,
- int32_t flags, fd_t *fd, int32_t wbflags, fop_open_cbk_t cbk,
+ int32_t flags, fd_t *fd, fop_open_cbk_t cbk,
void *local)
{
call_frame_t *frame = NULL;
@@ -1062,16 +1301,16 @@ nfs_fop_open (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc,
return ret;
gf_log (GF_NFS, GF_LOG_TRACE, "Open: %s", loc->path);
- nfs_fop_handle_frame_create (frame, xl, nfu, ret, err);
+ nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);
nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);
- STACK_WIND_COOKIE (frame, nfs_fop_open_cbk, nfsx, xl, xl->fops->open,
- loc, flags, fd, wbflags);
+ STACK_WIND_COOKIE (frame, nfs_fop_open_cbk, xl, xl, xl->fops->open,
+ loc, flags, fd, NULL);
ret = 0;
err:
if (ret < 0) {
if (frame)
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (nfl, frame);
}
return ret;
@@ -1081,17 +1320,18 @@ err:
int32_t
nfs_fop_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, struct iatt *prebuf,
- struct iatt *postbuf)
+ struct iatt *postbuf, dict_t *xdata)
{
struct nfs_fop_local *nfl = NULL;
fop_writev_cbk_t progcbk = NULL;
nfl_to_prog_data (nfl, progcbk, frame);
- nfs_fop_restore_root_ino (nfl, prebuf, postbuf, NULL, NULL);
+ nfs_fop_restore_root_ino (nfl, op_ret, prebuf, postbuf, NULL, NULL);
if (progcbk)
- progcbk (frame, cookie, this, op_ret, op_errno, prebuf,postbuf);
+ progcbk (frame, cookie, this, op_ret, op_errno, prebuf,
+ postbuf, xdata);
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (nfl, frame);
return 0;
}
@@ -1099,20 +1339,20 @@ nfs_fop_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int
nfs_fop_write (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd,
- struct iobuf *srciob, struct iovec *vector, int32_t count,
+ struct iobref *srciobref, struct iovec *vector, int32_t count,
off_t offset, fop_writev_cbk_t cbk, void *local)
{
call_frame_t *frame = NULL;
int ret = -EFAULT;
struct nfs_fop_local *nfl = NULL;
- if ((!nfsx) || (!xl) || (!fd) || (!vector) || (!nfu) || (!srciob))
+ if ((!nfsx) || (!xl) || (!fd) || (!vector) || (!nfu) || (!srciobref))
return ret;
- nfs_fop_handle_frame_create (frame, xl, nfu, ret, err);
+ nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);
nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);
nfs_fop_save_root_fd_ino (nfl, fd);
-
+/*
nfl->iobref = iobref_new ();
if (!nfl->iobref) {
gf_log (GF_NFS, GF_LOG_ERROR, "iobref creation failed");
@@ -1121,14 +1361,14 @@ nfs_fop_write (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd,
}
iobref_add (nfl->iobref, srciob);
- STACK_WIND_COOKIE (frame, nfs_fop_writev_cbk, nfsx, xl,xl->fops->writev
- , fd, vector, count, offset, nfl->iobref);
+*/
+ STACK_WIND_COOKIE (frame, nfs_fop_writev_cbk, xl, xl,xl->fops->writev,
+ fd, vector, count, offset, fd->flags, srciobref, NULL);
ret = 0;
err:
if (ret < 0) {
if (frame)
- nfs_stack_destroy (frame);
- nfs_fop_local_wipe (nfsx, nfl);
+ nfs_stack_destroy (nfl, frame);
}
return ret;
@@ -1138,16 +1378,18 @@ err:
int32_t
nfs_fop_fsync_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, struct iatt *prebuf,
- struct iatt *postbuf)
+ struct iatt *postbuf, dict_t *xdata)
{
struct nfs_fop_local *nfl = NULL;
fop_fsync_cbk_t progcbk = NULL;
nfl_to_prog_data (nfl, progcbk, frame);
- nfs_fop_restore_root_ino (nfl, prebuf, postbuf, NULL, NULL);
+ nfs_fop_restore_root_ino (nfl, op_ret, prebuf, postbuf, NULL, NULL);
if (progcbk)
- progcbk (frame, cookie, this, op_ret, op_errno, prebuf,postbuf);
- nfs_stack_destroy (frame);
+ progcbk (frame, cookie, this, op_ret, op_errno, prebuf,
+ postbuf, xdata);
+
+ nfs_stack_destroy (nfl, frame);
return 0;
}
@@ -1164,17 +1406,17 @@ nfs_fop_fsync (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd,
if ((!nfsx) || (!xl) || (!fd))
return ret;
- nfs_fop_handle_frame_create (frame, xl, nfu, ret, err);
+ nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);
nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);
nfs_fop_save_root_fd_ino (nfl, fd);
- STACK_WIND_COOKIE (frame, nfs_fop_fsync_cbk, nfsx, xl,
- xl->fops->fsync, fd, datasync);
+ STACK_WIND_COOKIE (frame, nfs_fop_fsync_cbk, xl, xl,
+ xl->fops->fsync, fd, datasync, NULL);
ret = 0;
err:
if (ret < 0) {
if (frame)
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (nfl, frame);
}
return ret;
@@ -1184,18 +1426,19 @@ err:
int32_t
nfs_fop_readv_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, struct iovec *vector,
- int32_t count, struct iatt *stbuf, struct iobref *iobref)
+ int32_t count, struct iatt *stbuf, struct iobref *iobref,
+ dict_t *xdata)
{
struct nfs_fop_local *nfl = NULL;
fop_readv_cbk_t progcbk = NULL;
nfl_to_prog_data (nfl, progcbk, frame);
- nfs_fop_restore_root_ino (nfl, stbuf, NULL, NULL, NULL);
+ nfs_fop_restore_root_ino (nfl, op_ret, stbuf, NULL, NULL, NULL);
if (progcbk)
progcbk (frame, cookie, this, op_ret, op_errno, vector, count,
- stbuf, iobref);
+ stbuf, iobref, xdata);
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (nfl, frame);
return 0;
}
@@ -1211,17 +1454,159 @@ nfs_fop_read (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd,
if ((!xl) || (!fd) || (!nfu))
return ret;
- nfs_fop_handle_frame_create (frame, xl, nfu, ret, err);
+ nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);
nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);
nfs_fop_save_root_fd_ino (nfl, fd);
- STACK_WIND_COOKIE (frame, nfs_fop_readv_cbk, nfsx, xl, xl->fops->readv,
- fd, size, offset);
+ STACK_WIND_COOKIE (frame, nfs_fop_readv_cbk, xl, xl, xl->fops->readv,
+ fd, size, offset, 0, NULL);
+ ret = 0;
+err:
+ if (ret < 0) {
+ if (frame)
+ nfs_stack_destroy (nfl, frame);
+ }
+
+ return ret;
+}
+
+int32_t
+nfs_fop_lk_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, struct gf_flock *flock,
+ dict_t *xdata)
+{
+ struct nfs_fop_local *nfl = NULL;
+ fop_lk_cbk_t progcbk = NULL;
+
+ nfl_to_prog_data (nfl, progcbk, frame);
+
+ if (!op_ret)
+ fd_lk_insert_and_merge (nfl->fd, nfl->cmd, &nfl->flock);
+
+ fd_unref (nfl->fd);
+
+ if (progcbk)
+ progcbk (frame, cookie, this, op_ret, op_errno, flock, xdata);
+
+ nfs_stack_destroy (nfl, frame);
+ return 0;
+}
+
+
+int
+nfs_fop_lk (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd,
+ int cmd, struct gf_flock *flock, fop_lk_cbk_t cbk, void *local)
+{
+ call_frame_t *frame = NULL;
+ int ret = -EFAULT;
+ struct nfs_fop_local *nfl = NULL;
+
+ if ((!xl) || (!fd) || (!nfu))
+ return ret;
+
+ nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);
+ nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);
+
+ nfl->cmd = cmd;
+ nfl->fd = fd_ref (fd);
+ nfl->flock = *flock;
+
+ STACK_WIND_COOKIE (frame, nfs_fop_lk_cbk, xl, xl, xl->fops->lk,
+ fd, cmd, flock, NULL);
+ ret = 0;
+err:
+ if (ret < 0) {
+ if (frame)
+ nfs_stack_destroy (nfl, frame);
+ }
+
+ return ret;
+}
+
+int32_t
+nfs_fop_getxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, dict_t *dict,
+ dict_t *xdata)
+{
+ struct nfs_fop_local *nfl = NULL;
+ fop_getxattr_cbk_t progcbk = NULL;
+
+ nfl_to_prog_data (nfl, progcbk, frame);
+
+ if (progcbk)
+ progcbk (frame, cookie, this, op_ret, op_errno, dict, xdata);
+
+ nfs_stack_destroy (nfl, frame);
+ return 0;
+}
+
+
+int
+nfs_fop_getxattr (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc,
+ char *name, dict_t *xdata, fop_getxattr_cbk_t cbk, void *local)
+{
+ call_frame_t *frame = NULL;
+ int ret = -EFAULT;
+ struct nfs_fop_local *nfl = NULL;
+
+ if ((!xl) || (!loc) || (!nfu))
+ return ret;
+
+ nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);
+ nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);
+
+ STACK_WIND_COOKIE (frame, nfs_fop_getxattr_cbk, xl, xl, xl->fops->getxattr,
+ loc, name, NULL);
+ ret = 0;
+err:
+ if (ret < 0) {
+ if (frame)
+ nfs_stack_destroy (nfl, frame);
+ }
+
+ return ret;
+}
+
+
+int32_t
+nfs_fop_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, dict_t *xdata)
+{
+ struct nfs_fop_local *nfl = NULL;
+ fop_setxattr_cbk_t progcbk = NULL;
+
+ nfl_to_prog_data (nfl, progcbk, frame);
+
+ if (progcbk)
+ progcbk (frame, cookie, this, op_ret, op_errno, xdata);
+
+ nfs_stack_destroy (nfl, frame);
+ return 0;
+}
+
+
+int
+nfs_fop_setxattr (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu,
+ loc_t *loc, dict_t *dict, int32_t flags, dict_t *xdata,
+ fop_setxattr_cbk_t cbk, void *local)
+{
+ call_frame_t *frame = NULL;
+ int ret = -EFAULT;
+ struct nfs_fop_local *nfl = NULL;
+
+ if ((!xl) || (!loc) || (!nfu))
+ return ret;
+
+ nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);
+ nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);
+
+ STACK_WIND_COOKIE (frame, nfs_fop_setxattr_cbk, xl, xl, xl->fops->setxattr,
+ loc, dict, flags, xdata);
ret = 0;
err:
if (ret < 0) {
if (frame)
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (nfl, frame);
}
return ret;
@@ -1231,17 +1616,18 @@ err:
int32_t
nfs_fop_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, struct iatt *prebuf,
- struct iatt *postbuf)
+ struct iatt *postbuf, dict_t *xdata)
{
struct nfs_fop_local *nfl = NULL;
fop_truncate_cbk_t progcbk = NULL;
nfl_to_prog_data (nfl, progcbk, frame);
- nfs_fop_restore_root_ino (nfl, prebuf, postbuf, NULL, NULL);
+ nfs_fop_restore_root_ino (nfl, op_ret, prebuf, postbuf, NULL, NULL);
if (progcbk)
- progcbk (frame, cookie, this, op_ret, op_errno, prebuf,postbuf);
+ progcbk (frame, cookie, this, op_ret, op_errno, prebuf,
+ postbuf, xdata);
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (nfl, frame);
return 0;
}
@@ -1257,18 +1643,18 @@ nfs_fop_truncate (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc,
if ((!nfsx) || (!xl) || (!loc) || (!nfu))
return ret;
- nfs_fop_handle_frame_create (frame, xl, nfu, ret, err);
+ nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);
nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);
nfs_fop_save_root_ino (nfl, loc);
- STACK_WIND_COOKIE (frame, nfs_fop_truncate_cbk, nfsx, xl,
- xl->fops->truncate, loc, offset);
+ STACK_WIND_COOKIE (frame, nfs_fop_truncate_cbk, xl, xl,
+ xl->fops->truncate, loc, offset, NULL);
ret = 0;
err:
if (ret < 0) {
if (frame)
- nfs_stack_destroy (frame);
+ nfs_stack_destroy (nfl, frame);
}
return ret;
diff --git a/xlators/nfs/server/src/nfs-fops.h b/xlators/nfs/server/src/nfs-fops.h
index 24fa0b99b..44e99c66b 100644
--- a/xlators/nfs/server/src/nfs-fops.h
+++ b/xlators/nfs/server/src/nfs-fops.h
@@ -1,20 +1,11 @@
/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
+ Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.com>
This file is part of GlusterFS.
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
*/
#ifndef _NFS_FOPS_H_
@@ -96,9 +87,14 @@ struct nfs_fop_local {
*/
int rootparentinode;
- char path[NFS_NAME_MAX];
- char newpath[NFS_NAME_MAX];
+ char path[NFS_NAME_MAX + 1];
+ char newpath[NFS_NAME_MAX + 1];
xlator_t *nfsx;
+ dict_t *dictgfid;
+
+ fd_t *fd;
+ int cmd;
+ struct gf_flock flock;
};
extern struct nfs_fop_local *
@@ -115,7 +111,7 @@ nfs_fop_local_wipe (xlator_t *xl, struct nfs_fop_local *l);
nflocal = nfs_fop_local_init (nf); \
if (nflocal) { \
nflocal->proglocal = plocal; \
- nflocal->progcbk = pcbk; \
+ nflocal->progcbk = *VOID(&pcbk); \
nflocal->nfsx = nf; \
if (fram) \
((call_frame_t *)fram)->local = nflocal;\
@@ -129,12 +125,11 @@ nfs_fop_local_wipe (xlator_t *xl, struct nfs_fop_local *l);
nflocal = fram->local; \
fram->local = nflocal->proglocal; \
pcbk = nflocal->progcbk; \
- nfs_fop_local_wipe (nflocal->nfsx, nflocal); \
} while (0) \
#define nfs_fop_handle_local_init(fram,nfx, nfloc, cbck,prgloc,retval,lab) \
do { \
- prog_data_to_nfl (nfx, nfloc, fram, cbck, prgloc); \
+ prog_data_to_nfl (nfx, nfloc, fram, cbck, prgloc); \
if (!nfloc) { \
gf_log (GF_NFS,GF_LOG_ERROR,"Failed to init local");\
retval = -ENOMEM; \
@@ -180,12 +175,12 @@ nfs_fop_fsync (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd,
extern int
nfs_fop_write (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd,
- struct iobuf *srciob, struct iovec *vector, int32_t count,
+ struct iobref *srciobref, struct iovec *vector, int32_t count,
off_t offset, fop_writev_cbk_t cbk, void *local);
extern int
nfs_fop_open (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc,
- int32_t flags, fd_t *fd, int32_t wbflags, fop_open_cbk_t cbk,
+ int32_t flags, fd_t *fd, fop_open_cbk_t cbk,
void *local);
extern int
@@ -233,4 +228,21 @@ extern int
nfs_fop_stat (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc,
fop_stat_cbk_t cbk, void *local);
+extern int
+nfs_fop_access (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc,
+ int32_t accesstest, fop_access_cbk_t cbk, void *local);
+
+extern int
+nfs_fop_lk (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd,
+ int cmd, struct gf_flock *flock, fop_lk_cbk_t cbk, void *local);
+
+extern int
+nfs_fop_getxattr (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc,
+ char *name, dict_t *xdata, fop_getxattr_cbk_t cbk, void *local);
+
+extern int
+nfs_fop_setxattr (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu,
+ loc_t *loc, dict_t *dict, int32_t flags, dict_t *xdata,
+ fop_setxattr_cbk_t cbk, void *local);
+
#endif
diff --git a/xlators/nfs/server/src/nfs-generics.c b/xlators/nfs/server/src/nfs-generics.c
index b248c2875..cb32b7f1b 100644
--- a/xlators/nfs/server/src/nfs-generics.c
+++ b/xlators/nfs/server/src/nfs-generics.c
@@ -1,20 +1,11 @@
/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
+ Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.com>
This file is part of GlusterFS.
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
*/
#ifndef _CONFIG_H
@@ -46,6 +37,19 @@ nfs_fstat (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd,
return ret;
}
+int
+nfs_access (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
+ int32_t accesstest, fop_access_cbk_t cbk, void *local)
+{
+ int ret = -EFAULT;
+
+ if ((!nfsx) || (!xl) || (!pathloc) || (!nfu))
+ return ret;
+
+ ret = nfs_fop_access (nfsx, xl, nfu, pathloc, accesstest, cbk, local);
+
+ return ret;
+}
int
nfs_stat (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
@@ -138,7 +142,6 @@ nfs_truncate (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
return ret;
}
-
int
nfs_read (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd, size_t size,
off_t offset, fop_readv_cbk_t cbk, void *local)
@@ -146,6 +149,28 @@ nfs_read (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd, size_t size,
return nfs_fop_read (nfsx, xl, nfu, fd, size, offset, cbk, local);
}
+int
+nfs_lk (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd,
+ int cmd, struct gf_flock *flock, fop_lk_cbk_t cbk, void *local)
+{
+ return nfs_fop_lk ( nfsx, xl, nfu, fd, cmd, flock, cbk, local);
+}
+
+int
+nfs_getxattr (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc,
+ char *name, dict_t *xdata, fop_getxattr_cbk_t cbk, void *local)
+{
+ return nfs_fop_getxattr (nfsx, xl, nfu, loc, name, xdata, cbk, local);
+}
+
+int
+nfs_setxattr (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu,
+ loc_t *loc, dict_t *dict, int32_t flags, dict_t *xdata,
+ fop_setxattr_cbk_t cbk, void *local)
+{
+ return nfs_fop_setxattr (nfsx, xl, nfu, loc, dict, flags, xdata, cbk,
+ local);
+}
int
nfs_fsync (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd,
@@ -157,11 +182,11 @@ nfs_fsync (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd,
int
nfs_write (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd,
- struct iobuf *srciob, struct iovec *vector, int32_t count,
+ struct iobref *srciobref, struct iovec *vector, int32_t count,
off_t offset, fop_writev_cbk_t cbk, void *local)
{
- return nfs_fop_write (nfsx, xl, nfu, fd, srciob, vector, count, offset,
- cbk, local);
+ return nfs_fop_write (nfsx, xl, nfu, fd, srciobref, vector, count,
+ offset, cbk, local);
}
@@ -174,7 +199,7 @@ nfs_open (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
if ((!nfsx) || (!xl) || (!pathloc) || (!nfu))
return ret;
- ret = nfs_inode_open (nfsx, xl, nfu, pathloc, flags, GF_OPEN_NOWB, cbk,
+ ret = nfs_inode_open (nfsx, xl, nfu, pathloc, flags, cbk,
local);
return ret;
}
@@ -317,3 +342,4 @@ nfs_opendir (xlator_t *nfsx, xlator_t *fopxl, nfs_user_t *nfu, loc_t *pathloc,
return nfs_inode_opendir (nfsx, fopxl, nfu, pathloc, cbk, local);
}
+
diff --git a/xlators/nfs/server/src/nfs-generics.h b/xlators/nfs/server/src/nfs-generics.h
index 55740f7b2..01876d68e 100644
--- a/xlators/nfs/server/src/nfs-generics.h
+++ b/xlators/nfs/server/src/nfs-generics.h
@@ -1,20 +1,11 @@
/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
+ Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.com>
This file is part of GlusterFS.
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
*/
#ifndef _NFS_GENERICS_H_
@@ -43,7 +34,7 @@ struct nfs_direntcache {
* different NFS versions can simply call a standard interface and have fop
* interface dependent functions be handled internally.
* This structure is part of such an abstraction. The fops layer stores any
- * state is requires in the fd. For eg, the dirent cache for a directory fd_t.
+ * state is requires in the fd. E.g. the dirent cache for a directory fd_t.
*/
typedef struct nfs_fop_fdcontext {
pthread_mutex_t lock;
@@ -92,7 +83,7 @@ nfs_fsync (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd,
extern int
nfs_write (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd,
- struct iobuf *srciob, struct iovec *vector, int32_t count,
+ struct iobref *srciobref, struct iovec *vector, int32_t count,
off_t offset, fop_writev_cbk_t cbk, void *local);
extern int
@@ -157,4 +148,21 @@ nfs_read_sync (xlator_t *xl, nfs_user_t *nfu, fd_t *fd, size_t size,
extern int
nfs_opendir (xlator_t *nfsx, xlator_t *fopxl, nfs_user_t *nfu, loc_t *pathloc,
fop_opendir_cbk_t cbk, void *local);
+
+extern int
+nfs_access (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
+ int32_t accesstest, fop_access_cbk_t cbk, void *local);
+extern int
+nfs_lk (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, fd_t *fd,
+ int cmd, struct gf_flock *flock, fop_lk_cbk_t cbk, void *local);
+
+extern int
+nfs_getxattr (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc,
+ char *name, dict_t *xdata, fop_getxattr_cbk_t cbk, void *local);
+
+extern int
+nfs_setxattr (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu,
+ loc_t *loc, dict_t *dict, int32_t flags, dict_t *xdata,
+ fop_setxattr_cbk_t cbk, void *local);
+
#endif
diff --git a/xlators/nfs/server/src/nfs-inodes.c b/xlators/nfs/server/src/nfs-inodes.c
index 4b8bad717..63d5e8a19 100644
--- a/xlators/nfs/server/src/nfs-inodes.c
+++ b/xlators/nfs/server/src/nfs-inodes.c
@@ -1,20 +1,11 @@
/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
+ Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.com>
This file is part of GlusterFS.
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
*/
#ifndef _CONFIG_H
@@ -32,6 +23,14 @@
#include <libgen.h>
+#define inodes_nfl_to_prog_data(nflocal, pcbk, fram) \
+ do { \
+ nflocal = fram->local; \
+ fram->local = nflocal->proglocal; \
+ *VOID(&pcbk) = nflocal->progcbk; \
+ nfs_fop_local_wipe (nflocal->nfsx, nflocal); \
+ } while (0) \
+
void
nfl_inodes_init (struct nfs_fop_local *nfl, inode_t *inode, inode_t *parent,
inode_t *newparent, const char *name, const char *newname)
@@ -49,10 +48,10 @@ nfl_inodes_init (struct nfs_fop_local *nfl, inode_t *inode, inode_t *parent,
nfl->newparent = inode_ref (newparent);
if (name)
- strcpy (nfl->path, name);
+ strncpy (nfl->path, name, NFS_NAME_MAX);
if (newname)
- strcpy (nfl->newpath, newname);
+ strncpy (nfl->newpath, newname, NFS_NAME_MAX);
return;
}
@@ -62,15 +61,16 @@ int32_t
nfs_inode_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, fd_t *fd, inode_t *inode
, struct iatt *buf, struct iatt *preparent,
- struct iatt *postparent)
+ struct iatt *postparent, dict_t *xdata)
{
struct nfs_fop_local *nfl = frame->local;
fop_create_cbk_t progcbk = NULL;
+ inode_t *linked_inode = NULL;
if (op_ret == -1)
goto do_not_link;
- inode_link (inode, nfl->parent, nfl->path, buf);
+ linked_inode = inode_link (inode, nfl->parent, nfl->path, buf);
do_not_link:
/* NFS does not need it, upper layers should not expect the pointer to
@@ -78,10 +78,16 @@ do_not_link:
*/
fd_unref (fd);
- nfl_to_prog_data (nfl, progcbk, frame);
+ inodes_nfl_to_prog_data (nfl, progcbk, frame);
if (progcbk)
progcbk (frame, cookie, this, op_ret, op_errno, fd, inode, buf,
- preparent, postparent);
+ preparent, postparent, xdata);
+
+ if (linked_inode) {
+ inode_lookup (linked_inode);
+ inode_unref (linked_inode);
+ }
+
return 0;
}
@@ -127,21 +133,27 @@ int32_t
nfs_inode_mkdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, inode_t *inode,
struct iatt *buf, struct iatt *preparent,
- struct iatt *postparent)
+ struct iatt *postparent, dict_t *xdata)
{
struct nfs_fop_local *nfl = frame->local;
fop_mkdir_cbk_t progcbk = NULL;
+ inode_t *linked_inode = NULL;
if (op_ret == -1)
goto do_not_link;
- inode_link (inode, nfl->parent, nfl->path, buf);
+ linked_inode = inode_link (inode, nfl->parent, nfl->path, buf);
do_not_link:
- nfl_to_prog_data (nfl, progcbk, frame);
+ inodes_nfl_to_prog_data (nfl, progcbk, frame);
if (progcbk)
progcbk (frame, cookie, this, op_ret, op_errno, inode, buf,
- preparent, postparent);
+ preparent, postparent, xdata);
+
+ if (linked_inode) {
+ inode_lookup (linked_inode);
+ inode_unref (linked_inode);
+ }
return 0;
}
@@ -172,7 +184,7 @@ err:
int32_t
nfs_inode_open_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno, fd_t *fd)
+ int32_t op_ret, int32_t op_errno, fd_t *fd, dict_t *xdata)
{
struct nfs_fop_local *nfl = NULL;
@@ -186,16 +198,16 @@ nfs_inode_open_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
/* else
fd_bind (fd);
*/
- nfl_to_prog_data (nfl, progcbk, frame);
+ inodes_nfl_to_prog_data (nfl, progcbk, frame);
if (progcbk)
- progcbk (frame, cookie, this, op_ret, op_errno, fd);
+ progcbk (frame, cookie, this, op_ret, op_errno, fd, xdata);
return 0;
}
int
nfs_inode_open (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc,
- int32_t flags, int32_t wbflags, fop_open_cbk_t cbk, void *local)
+ int32_t flags, fop_open_cbk_t cbk, void *local)
{
struct nfs_fop_local *nfl = NULL;
fd_t *newfd = NULL;
@@ -212,7 +224,7 @@ nfs_inode_open (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc,
}
nfs_fop_handle_local_init (NULL, nfsx, nfl, cbk, local, ret, fd_err);
- ret = nfs_fop_open (nfsx, xl, nfu, loc, flags, newfd, wbflags,
+ ret = nfs_fop_open (nfsx, xl, nfu, loc, flags, newfd,
nfs_inode_open_cbk, nfl);
if (ret < 0)
@@ -234,7 +246,8 @@ int32_t
nfs_inode_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, struct iatt *buf,
struct iatt *preoldparent, struct iatt *postoldparent,
- struct iatt *prenewparent, struct iatt *postnewparent)
+ struct iatt *prenewparent, struct iatt *postnewparent,
+ dict_t *xdata)
{
struct nfs_fop_local *nfl = NULL;
fop_rename_cbk_t progcbk = NULL;
@@ -247,11 +260,11 @@ nfs_inode_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
nfl->newpath, nfl->inode, buf);
do_not_link:
- nfl_to_prog_data (nfl, progcbk, frame);
+ inodes_nfl_to_prog_data (nfl, progcbk, frame);
if (progcbk)
progcbk (frame, cookie, this, op_ret, op_errno, buf,
preoldparent, postoldparent, prenewparent,
- postnewparent);
+ postnewparent, xdata);
return 0;
}
@@ -284,22 +297,29 @@ int32_t
nfs_inode_link_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, inode_t *inode,
struct iatt *buf, struct iatt *preparent,
- struct iatt *postparent)
+ struct iatt *postparent, dict_t *xdata)
{
struct nfs_fop_local *nfl = NULL;
fop_link_cbk_t progcbk = NULL;
+ inode_t *linked_inode = NULL;
if (op_ret == -1)
goto do_not_link;
nfl = frame->local;
- inode_link (inode, nfl->newparent, nfl->path, buf);
+ linked_inode = inode_link (inode, nfl->newparent, nfl->path, buf);
do_not_link:
- nfl_to_prog_data (nfl, progcbk, frame);
+ inodes_nfl_to_prog_data (nfl, progcbk, frame);
if (progcbk)
progcbk (frame, cookie, this, op_ret, op_errno, inode, buf,
- preparent, postparent);
+ preparent, postparent, xdata);
+
+ if (linked_inode) {
+ inode_lookup (linked_inode);
+ inode_unref (linked_inode);
+ }
+
return 0;
}
@@ -330,7 +350,7 @@ err:
int32_t
nfs_inode_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, struct iatt *preparent,
- struct iatt *postparent)
+ struct iatt *postparent, dict_t *xdata)
{
struct nfs_fop_local *nfl = NULL;
fop_unlink_cbk_t progcbk = NULL;
@@ -341,12 +361,13 @@ nfs_inode_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
goto do_not_unlink;
inode_unlink (nfl->inode, nfl->parent, nfl->path);
+ inode_forget (nfl->inode, 0);
do_not_unlink:
- nfl_to_prog_data (nfl, progcbk, frame);
+ inodes_nfl_to_prog_data (nfl, progcbk, frame);
if (progcbk)
progcbk (frame, cookie, this, op_ret, op_errno, preparent,
- postparent);
+ postparent, xdata);
return 0;
}
@@ -377,7 +398,7 @@ err:
int32_t
nfs_inode_rmdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, struct iatt *preparent,
- struct iatt *postparent)
+ struct iatt *postparent, dict_t *xdata)
{
struct nfs_fop_local *nfl = NULL;
fop_rmdir_cbk_t progcbk = NULL;
@@ -388,12 +409,13 @@ nfs_inode_rmdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
goto do_not_unlink;
inode_unlink (nfl->inode, nfl->parent, nfl->path);
+ inode_forget (nfl->inode, 0);
do_not_unlink:
- nfl_to_prog_data (nfl, progcbk, frame);
+ inodes_nfl_to_prog_data (nfl, progcbk, frame);
if (progcbk)
progcbk (frame, cookie, this, op_ret, op_errno, preparent,
- postparent);
+ postparent, xdata);
return 0;
}
@@ -426,23 +448,30 @@ int32_t
nfs_inode_mknod_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, inode_t *inode,
struct iatt *buf, struct iatt *preparent,
- struct iatt *postparent)
+ struct iatt *postparent, dict_t *xdata)
{
struct nfs_fop_local *nfl = NULL;
fop_mknod_cbk_t progcbk = NULL;
+ inode_t *linked_inode = NULL;
nfl = frame->local;
if (op_ret == -1)
goto do_not_link;
- inode_link (inode, nfl->parent, nfl->path, buf);
+ linked_inode = inode_link (inode, nfl->parent, nfl->path, buf);
do_not_link:
- nfl_to_prog_data (nfl, progcbk, frame);
+ inodes_nfl_to_prog_data (nfl, progcbk, frame);
if (progcbk)
progcbk (frame, cookie, this, op_ret, op_errno, inode, buf,
- preparent, postparent);
+ preparent, postparent, xdata);
+
+ if (linked_inode) {
+ inode_lookup (linked_inode);
+ inode_unref (linked_inode);
+ }
+
return 0;
}
@@ -476,22 +505,28 @@ int32_t
nfs_inode_symlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, inode_t *inode,
struct iatt *buf, struct iatt *preparent,
- struct iatt *postparent)
+ struct iatt *postparent, dict_t *xdata)
{
struct nfs_fop_local *nfl = NULL;
fop_symlink_cbk_t progcbk = NULL;
+ inode_t *linked_inode = NULL;
nfl = frame->local;
if (op_ret == -1)
goto do_not_link;
- inode_link (inode, nfl->parent, nfl->path, buf);
+ linked_inode = inode_link (inode, nfl->parent, nfl->path, buf);
do_not_link:
- nfl_to_prog_data (nfl, progcbk, frame);
+ inodes_nfl_to_prog_data (nfl, progcbk, frame);
if (progcbk)
progcbk (frame, cookie, this, op_ret, op_errno, inode, buf,
- preparent, postparent);
+ preparent, postparent, xdata);
+
+ if (linked_inode) {
+ inode_lookup (linked_inode);
+ inode_unref (linked_inode);
+ }
return 0;
}
@@ -522,21 +557,20 @@ err:
int32_t
nfs_inode_opendir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno, fd_t *fd)
+ int32_t op_ret, int32_t op_errno, fd_t *fd, dict_t *xdata)
{
struct nfs_fop_local *nfl = NULL;
fop_open_cbk_t progcbk = NULL;
- if ((op_ret == -1) && (fd))
- fd_unref (fd);
- else
+ if (op_ret != -1)
fd_bind (fd);
- nfl_to_prog_data (nfl, progcbk, frame);
+ inodes_nfl_to_prog_data (nfl, progcbk, frame);
if (progcbk)
- progcbk (frame, cookie, this, op_ret, op_errno, fd);
+ progcbk (frame, cookie, this, op_ret, op_errno, fd, xdata);
+
return 0;
}
diff --git a/xlators/nfs/server/src/nfs-inodes.h b/xlators/nfs/server/src/nfs-inodes.h
index 51a23faef..ba7a57124 100644
--- a/xlators/nfs/server/src/nfs-inodes.h
+++ b/xlators/nfs/server/src/nfs-inodes.h
@@ -1,20 +1,11 @@
/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
+ Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.com>
This file is part of GlusterFS.
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
*/
#ifndef _NFS_INODES_H_
@@ -48,7 +39,7 @@ nfs_inode_mkdir (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
extern int
nfs_inode_open (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc,
- int32_t flags, int32_t wbflags, fop_open_cbk_t cbk,
+ int32_t flags, fop_open_cbk_t cbk,
void *local);
extern int
@@ -80,6 +71,6 @@ nfs_inode_mknod (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
mode_t mode, dev_t dev, fop_mknod_cbk_t cbk, void *local);
extern int
-nfs_inode_lookup (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
+nfs_inode_lookup (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
fop_lookup_cbk_t cbk, void *local);
#endif
diff --git a/xlators/nfs/server/src/nfs-mem-types.h b/xlators/nfs/server/src/nfs-mem-types.h
new file mode 100644
index 000000000..450b6f2fe
--- /dev/null
+++ b/xlators/nfs/server/src/nfs-mem-types.h
@@ -0,0 +1,53 @@
+/*
+ Copyright (c) 2008-2011 Gluster, Inc. <http://www.gluster.com>
+ This file is part of GlusterFS.
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
+*/
+
+
+#ifndef __NFS_MEM_TYPES_H__
+#define __NFS_MEM_TYPES_H__
+
+#include "mem-types.h"
+
+enum gf_nfs_mem_types_ {
+ gf_nfs_mt_mountentry = gf_common_mt_end + 1,
+ gf_nfs_mt_mountbody,
+ gf_nfs_mt_nfs_state,
+ gf_nfs_mt_char,
+ gf_nfs_mt_exportnode,
+ gf_nfs_mt_groupnode,
+ gf_nfs_mt_mount3_state,
+ gf_nfs_mt_write3args,
+ gf_nfs_mt_nfs3_export,
+ gf_nfs_mt_nfs3_state,
+ gf_nfs_mt_entry3,
+ gf_nfs_mt_entryp3,
+ gf_nfs_mt_nfs3_fd_entry,
+ gf_nfs_mt_nfs3_fh,
+ gf_nfs_mt_nfs_initer_list,
+ gf_nfs_mt_xlator_t,
+ gf_nfs_mt_list_head,
+ gf_nfs_mt_mnt3_resolve,
+ gf_nfs_mt_mnt3_export,
+ gf_nfs_mt_int,
+ gf_nfs_mt_mountres3,
+ gf_nfs_mt_mountstat3,
+ gf_nfs_mt_inode_q,
+ gf_nfs_mt_nlm4_state,
+ gf_nfs_mt_nlm4_cm,
+ gf_nfs_mt_nlm4_fde,
+ gf_nfs_mt_nlm4_nlmclnt,
+ gf_nfs_mt_nlm4_share,
+ gf_nfs_mt_aux_gids,
+ gf_nfs_mt_inode_ctx,
+ gf_nfs_mt_auth_spec,
+ gf_nfs_mt_arr,
+ gf_nfs_mt_end
+};
+#endif
+
diff --git a/xlators/nfs/server/src/nfs.c b/xlators/nfs/server/src/nfs.c
index b598b0c69..75c8fe44e 100644
--- a/xlators/nfs/server/src/nfs.c
+++ b/xlators/nfs/server/src/nfs.c
@@ -1,20 +1,11 @@
/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
+ Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.com>
This file is part of GlusterFS.
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
*/
/* This is the primary translator source for NFS.
@@ -38,6 +29,210 @@
#include "inode.h"
#include "mount3.h"
#include "nfs3.h"
+#include "nfs-mem-types.h"
+#include "nfs3-helpers.h"
+#include "nlm4.h"
+#include "options.h"
+#include "acl3.h"
+#include "rpc-drc.h"
+
+#define STRINGIFY(val) #val
+#define TOSTRING(val) STRINGIFY(val)
+
+#define OPT_SERVER_AUX_GIDS "nfs.server-aux-gids"
+#define OPT_SERVER_GID_CACHE_TIMEOUT "nfs.server.aux-gid-timeout"
+
+/* TODO: DATADIR should be based on configure's $(localstatedir) */
+#define DATADIR "/var/lib/glusterd"
+#define NFS_DATADIR DATADIR "/nfs"
+
+/* Forward declaration */
+int nfs_add_initer (struct list_head *list, nfs_version_initer_t init);
+
+static int
+nfs_init_version (xlator_t *this, nfs_version_initer_t init)
+{
+ int ret = -1;
+ struct nfs_initer_list *version = NULL;
+ struct nfs_initer_list *tmp = NULL;
+ rpcsvc_program_t *prog = NULL;
+ struct list_head *versions = NULL;
+ struct nfs_state *nfs = NULL;
+ gf_boolean_t found = _gf_false;
+
+ if ((!this) || (!this->private) || (!init))
+ return (-1);
+
+ nfs = (struct nfs_state *)this->private;
+
+ ret = nfs_add_initer (&nfs->versions, init);
+ if (ret == -1) {
+ gf_log (GF_NFS, GF_LOG_ERROR,
+ "Failed to add protocol initializer");
+ goto err;
+ }
+
+ versions = &nfs->versions;
+ list_for_each_entry_safe (version, tmp, versions, list) {
+ prog = version->program;
+ if (version->init == init) {
+ prog = init(this);
+ if (!prog) {
+ ret = -1;
+ goto err;
+ }
+ version->program = prog;
+ found = _gf_true;
+ break;
+ }
+ }
+
+ /* program not added */
+ if (!found) {
+ gf_log (GF_NFS, GF_LOG_ERROR,
+ "Program: %s NOT found", prog->progname);
+ goto err;
+ }
+
+ /* Check if nfs.port is configured */
+ if (nfs->override_portnum)
+ prog->progport = nfs->override_portnum;
+
+ gf_log (GF_NFS, GF_LOG_DEBUG, "Starting program: %s", prog->progname);
+
+ ret = rpcsvc_program_register (nfs->rpcsvc, prog);
+ if (ret == -1) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Program: %s init failed",
+ prog->progname);
+ goto err;
+ }
+
+ /* Registration with portmapper is disabled, Nothing to do */
+ if (!nfs->register_portmap)
+ goto err;
+
+ ret = rpcsvc_program_register_portmap (prog, prog->progport);
+ if (ret == -1) {
+ gf_log (GF_NFS, GF_LOG_ERROR,
+ "Program %s registration failed",
+ prog->progname);
+ goto err;
+ }
+ ret = 0; /* All well */
+err:
+ return ret;
+}
+
+static int
+nfs_deinit_version (struct nfs_state *nfs, nfs_version_initer_t init)
+{
+ int ret = -1;
+ struct nfs_initer_list *version = NULL;
+ struct nfs_initer_list *tmp = NULL;
+ rpcsvc_program_t *prog = NULL;
+ struct list_head *versions = NULL;
+
+ if ((!nfs) || (!init))
+ return (-1);
+
+ versions = &nfs->versions;
+ list_for_each_entry_safe (version, tmp, versions, list) {
+ prog = version->program;
+ if (version->init == init) {
+ prog = version->program;
+ ret = rpcsvc_program_unregister (nfs->rpcsvc, prog);
+ if (ret != 0)
+ return (-1);
+ list_del (&version->list);
+ GF_FREE (version);
+ return (0);
+ }
+ }
+
+ return (-1);
+}
+
+static int
+nfs_reconfigure_acl3 (xlator_t *this)
+{
+ struct nfs_state *nfs = NULL;
+
+ if ((!this) || (!this->private))
+ return (-1);
+
+ nfs = (struct nfs_state *)this->private;
+
+ /* ACL is enabled */
+ if (nfs->enable_acl)
+ return nfs_init_version (this, acl3svc_init);
+
+ /* ACL is disabled */
+ return nfs_deinit_version (nfs, acl3svc_init);
+}
+
+static int
+nfs_reconfigure_nlm4 (xlator_t *this)
+{
+ struct nfs_state *nfs = NULL;
+
+ if ((!this) || (!this->private))
+ return (-1);
+
+ nfs = (struct nfs_state *)this->private;
+
+ /* NLM is enabled */
+ if (nfs->enable_nlm)
+ return nfs_init_version (this, nlm4svc_init);
+
+ /* NLM is disabled */
+ return nfs_deinit_version (nfs, nlm4svc_init);
+}
+
+static int
+nfs_program_register_portmap_all (struct nfs_state *nfs)
+{
+ struct list_head *versions = NULL;
+ struct nfs_initer_list *version = NULL;
+ struct nfs_initer_list *tmp = NULL;
+ rpcsvc_program_t *prog = NULL;
+
+ if (nfs == NULL)
+ return (-1);
+
+ versions = &nfs->versions;
+ list_for_each_entry_safe (version, tmp, versions, list) {
+ prog = version->program;
+ if (prog == NULL)
+ continue;
+ if (nfs->override_portnum)
+ prog->progport = nfs->override_portnum;
+ (void) rpcsvc_program_register_portmap (prog, prog->progport);
+ }
+
+ return (0);
+}
+
+static int
+nfs_program_unregister_portmap_all (struct nfs_state *nfs)
+{
+ struct list_head *versions = NULL;
+ struct nfs_initer_list *version = NULL;
+ struct nfs_initer_list *tmp = NULL;
+ rpcsvc_program_t *prog = NULL;
+
+ if (nfs == NULL)
+ return (-1);
+
+ versions = &nfs->versions;
+ list_for_each_entry_safe (version, tmp, versions, list) {
+ prog = version->program;
+ if (prog == NULL)
+ continue;
+ (void) rpcsvc_program_unregister_portmap (prog);
+ }
+
+ return (0);
+}
/* Every NFS version must call this function with the init function
* for its particular version.
@@ -49,7 +244,7 @@ nfs_add_initer (struct list_head *list, nfs_version_initer_t init)
if ((!list) || (!init))
return -1;
- new = CALLOC (1, sizeof (*new));
+ new = GF_CALLOC (1, sizeof (*new), gf_nfs_mt_nfs_initer_list);
if (!new) {
gf_log (GF_NFS, GF_LOG_ERROR, "Memory allocation failed");
return -1;
@@ -81,16 +276,15 @@ nfs_deinit_versions (struct list_head *versions, xlator_t *this)
*/
if (version->program)
rpcsvc_program_unregister (nfs->rpcsvc,
- *(version->program));
+ (version->program));
list_del (&version->list);
- FREE (version);
+ GF_FREE (version);
}
return 0;
}
-
int
nfs_init_versions (struct nfs_state *nfs, xlator_t *this)
{
@@ -112,19 +306,34 @@ nfs_init_versions (struct nfs_state *nfs, xlator_t *this)
}
prog = version->init (this);
- version->program = prog;
if (!prog) {
ret = -1;
goto err;
}
+ version->program = prog;
+ if (nfs->override_portnum)
+ prog->progport = nfs->override_portnum;
gf_log (GF_NFS, GF_LOG_DEBUG, "Starting program: %s",
prog->progname);
- ret = rpcsvc_program_register (nfs->rpcsvc, *prog);
+
+ ret = rpcsvc_program_register (nfs->rpcsvc, prog);
if (ret == -1) {
- gf_log (GF_NFS, GF_LOG_ERROR, "Program init failed");
+ gf_log (GF_NFS, GF_LOG_ERROR, "Program: %s init failed",
+ prog->progname);
goto err;
}
+ if (nfs->register_portmap) {
+ ret = rpcsvc_program_register_portmap (prog,
+ prog->progport);
+ if (ret == -1) {
+ gf_log (GF_NFS, GF_LOG_ERROR,
+ "Program %s registration failed",
+ prog->progname);
+ goto err;
+ }
+ }
+
}
ret = 0;
@@ -141,25 +350,43 @@ nfs_add_all_initiators (struct nfs_state *nfs)
/* Add the initializers for all versions. */
ret = nfs_add_initer (&nfs->versions, mnt3svc_init);
if (ret == -1) {
- gf_log (GF_NFS, GF_LOG_ERROR, "Failed to add protocol"
- " initializer");
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to add "
+ "MOUNT3 protocol initializer");
goto ret;
}
ret = nfs_add_initer (&nfs->versions, mnt1svc_init);
if (ret == -1) {
- gf_log (GF_NFS, GF_LOG_ERROR, "Failed to add protocol"
- " initializer");
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to add "
+ "MOUNT1 protocol initializer");
goto ret;
}
ret = nfs_add_initer (&nfs->versions, nfs3svc_init);
if (ret == -1) {
- gf_log (GF_NFS, GF_LOG_ERROR, "Failed to add protocol"
- " initializer");
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to add "
+ "NFS3 protocol initializer");
goto ret;
}
+ if (nfs->enable_nlm == _gf_true) {
+ ret = nfs_add_initer (&nfs->versions, nlm4svc_init);
+ if (ret == -1) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to add protocol"
+ " initializer");
+ goto ret;
+ }
+ }
+
+ if (nfs->enable_acl == _gf_true) {
+ ret = nfs_add_initer (&nfs->versions, acl3svc_init);
+ if (ret == -1) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to add "
+ "ACL protocol initializer");
+ goto ret;
+ }
+ }
+
ret = 0;
ret:
return ret;
@@ -202,6 +429,13 @@ nfs_subvolume_set_started (struct nfs_state *nfs, xlator_t *xl)
LOCK (&nfs->svinitlock);
{
for (;x < nfs->allsubvols; ++x) {
+ if (nfs->initedxl[x] == xl) {
+ gf_log (GF_NFS, GF_LOG_DEBUG,
+ "Volume already started %s",
+ xl->name);
+ break;
+ }
+
if (nfs->initedxl[x] == NULL) {
nfs->initedxl[x] = xl;
++nfs->upsubvols;
@@ -231,7 +465,8 @@ nfs_start_subvol_lookup_cbk (call_frame_t *frame, void *cookie,
goto err;
}
- gf_log (GF_NFS, GF_LOG_TRACE, "Started %s", this->name);
+ nfs_subvolume_set_started (this->private, ((xlator_t *)cookie));
+ gf_log (GF_NFS, GF_LOG_TRACE, "Started %s", ((xlator_t *)cookie)->name);
err:
return 0;
}
@@ -254,8 +489,7 @@ nfs_startup_subvolume (xlator_t *nfsx, xlator_t *xl)
goto err;
}
- nfs_subvolume_set_started (nfsx->private, xl);
- ret = nfs_inode_loc_fill (xl->itable->root, &rootloc);
+ ret = nfs_root_loc_fill (xl->itable, &rootloc);
if (ret == -1) {
gf_log (GF_NFS, GF_LOG_CRITICAL, "Failed to init root loc");
goto err;
@@ -356,7 +590,8 @@ nfs_init_subvolumes (struct nfs_state *nfs, xlator_list_t *cl)
}
LOCK_INIT (&nfs->svinitlock);
- nfs->initedxl = CALLOC (svcount, sizeof (xlator_t *));
+ nfs->initedxl = GF_CALLOC (svcount, sizeof (xlator_t *),
+ gf_nfs_mt_xlator_t );
if (!nfs->initedxl) {
gf_log (GF_NFS, GF_LOG_ERROR, "Failed to allocated inited xls");
ret = -1;
@@ -429,74 +664,628 @@ nfs_request_user_init (nfs_user_t *nfu, rpcsvc_request_t *req)
return;
gidarr = rpcsvc_auth_unix_auxgids (req, &gids);
- nfs_user_create (nfu, rpcsvc_request_uid (req), rpcsvc_request_gid (req)
- , gidarr, gids);
+ nfs_user_create (nfu, rpcsvc_request_uid (req),
+ rpcsvc_request_gid (req), gidarr, gids);
+
+ return;
+}
+
+void
+nfs_request_primary_user_init (nfs_user_t *nfu, rpcsvc_request_t *req,
+ uid_t uid, gid_t gid)
+{
+ gid_t *gidarr = NULL;
+ int gids = 0;
+
+ if ((!req) || (!nfu))
+ return;
+
+ gidarr = rpcsvc_auth_unix_auxgids (req, &gids);
+ nfs_user_create (nfu, uid, gid, gidarr, gids);
return;
}
-int
-init (xlator_t *this) {
+int32_t
+mem_acct_init (xlator_t *this)
+{
+ int ret = -1;
+
+ if (!this)
+ return ret;
+
+ ret = xlator_mem_acct_init (this, gf_nfs_mt_end + 1);
+
+ if (ret != 0) {
+ gf_log(this->name, GF_LOG_ERROR, "Memory accounting init"
+ "failed");
+ return ret;
+ }
+ return ret;
+}
+
+
+struct nfs_state *
+nfs_init_state (xlator_t *this)
+{
struct nfs_state *nfs = NULL;
int ret = -1;
unsigned int fopspoolsize = 0;
+ char *optstr = NULL;
+ gf_boolean_t boolt = _gf_false;
+ struct stat stbuf = {0,};
if (!this)
- return -1;
+ return NULL;
- if ((!this->children) || (!this->children->xlator)) {
- gf_log (GF_NFS, GF_LOG_ERROR, "nfs must have at least one"
- " child subvolume");
- return -1;
+ if (!this->children) {
+ gf_log (GF_NFS, GF_LOG_INFO,
+ "NFS is manually disabled: Exiting");
+ /* Nothing for nfs process to do, exit cleanly */
+ kill (getpid (), SIGTERM);
}
- nfs = CALLOC (1, sizeof (*nfs));
+ nfs = GF_CALLOC (1, sizeof (*nfs), gf_nfs_mt_nfs_state);
if (!nfs) {
gf_log (GF_NFS, GF_LOG_ERROR, "memory allocation failed");
- return -1;
+ return NULL;
}
- /* RPC service needs to be started before NFS versions can be inited. */
- nfs->rpcsvc = rpcsvc_init (this->ctx, this->options);
- if (!nfs->rpcsvc) {
- gf_log (GF_NFS, GF_LOG_ERROR, "RPC service init failed");
- goto free_nfs;
+ nfs->memfactor = GF_NFS_DEFAULT_MEMFACTOR;
+ if (dict_get (this->options, "nfs.mem-factor")) {
+ ret = dict_get_str (this->options, "nfs.mem-factor",
+ &optstr);
+ if (ret < 0) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse dict");
+ goto free_rpcsvc;
+ }
+
+ ret = gf_string2uint (optstr, &nfs->memfactor);
+ if (ret < 0) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse uint "
+ "string");
+ goto free_rpcsvc;
+ }
}
- nfs->memfactor = GF_NFS_DEFAULT_MEMFACTOR;
fopspoolsize = nfs->memfactor * GF_NFS_CONCURRENT_OPS_MULT;
/* FIXME: Really saddens me to see this as xlator wide. */
nfs->foppool = mem_pool_new (struct nfs_fop_local, fopspoolsize);
if (!nfs->foppool) {
- gf_log (GF_NFS, GF_LOG_CRITICAL, "Failed to allocate fops local"
- " pool");
+ gf_log (GF_NFS, GF_LOG_CRITICAL, "Failed to allocate fops "
+ "local pool");
goto free_rpcsvc;
}
+ nfs->dynamicvolumes = GF_NFS_DVM_OFF;
+ if (dict_get (this->options, "nfs.dynamic-volumes")) {
+ ret = dict_get_str (this->options, "nfs.dynamic-volumes",
+ &optstr);
+ if (ret < 0) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse dict");
+ goto free_foppool;
+ }
+
+ ret = gf_string2boolean (optstr, &boolt);
+ if (ret < 0) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse bool "
+ "string");
+ goto free_foppool;
+ }
+
+ if (boolt == _gf_true)
+ nfs->dynamicvolumes = GF_NFS_DVM_ON;
+ }
+
+ nfs->enable_nlm = _gf_true;
+ ret = dict_get_str_boolean (this->options, "nfs.nlm", _gf_true);
+ if (ret == _gf_false) {
+ gf_log (GF_NFS, GF_LOG_INFO, "NLM is manually disabled");
+ nfs->enable_nlm = _gf_false;
+ }
+
+ nfs->enable_acl = _gf_true;
+ ret = dict_get_str_boolean (this->options, "nfs.acl", _gf_true);
+ if (ret == _gf_false) {
+ gf_log (GF_NFS, GF_LOG_INFO, "ACL is manually disabled");
+ nfs->enable_acl = _gf_false;
+ }
+
+ nfs->enable_ino32 = 0;
+ if (dict_get (this->options, "nfs.enable-ino32")) {
+ ret = dict_get_str (this->options, "nfs.enable-ino32",
+ &optstr);
+ if (ret < 0) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse dict");
+ goto free_foppool;
+ }
+
+ ret = gf_string2boolean (optstr, &boolt);
+ if (ret < 0) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse bool "
+ "string");
+ goto free_foppool;
+ }
+
+ if (boolt == _gf_true)
+ nfs->enable_ino32 = 1;
+ }
+
+ if (dict_get (this->options, "nfs.port")) {
+ ret = dict_get_str (this->options, "nfs.port",
+ &optstr);
+ if (ret < 0) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse dict");
+ goto free_foppool;
+ }
+
+ ret = gf_string2uint (optstr, &nfs->override_portnum);
+ if (ret < 0) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse uint "
+ "string");
+ goto free_foppool;
+ }
+ }
+
+ if (dict_get(this->options, "transport.socket.listen-port") == NULL) {
+ if (nfs->override_portnum)
+ ret = gf_asprintf (&optstr, "%d",
+ nfs->override_portnum);
+ else
+ ret = gf_asprintf (&optstr, "%d", GF_NFS3_PORT);
+ if (ret == -1) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "failed mem-allocation");
+ goto free_foppool;
+ }
+ ret = dict_set_dynstr (this->options,
+ "transport.socket.listen-port", optstr);
+ if (ret == -1) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "dict_set_dynstr error");
+ goto free_foppool;
+ }
+ }
+
+ if (dict_get(this->options, "transport-type") == NULL) {
+ ret = dict_set_str (this->options, "transport-type", "socket");
+ if (ret == -1) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "dict_set_str error");
+ goto free_foppool;
+ }
+ }
+
+ nfs->mount_udp = 0;
+ if (dict_get(this->options, "nfs.mount-udp")) {
+ ret = dict_get_str (this->options, "nfs.mount-udp", &optstr);
+ if (ret == -1) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse dict");
+ goto free_foppool;
+ }
+
+ ret = gf_string2boolean (optstr, &boolt);
+ if (ret < 0) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse bool "
+ "string");
+ goto free_foppool;
+ }
+
+ if (boolt == _gf_true)
+ nfs->mount_udp = 1;
+ }
+
+ nfs->rmtab = gf_strdup (NFS_DATADIR "/rmtab");
+ if (dict_get(this->options, "nfs.mount-rmtab")) {
+ ret = dict_get_str (this->options, "nfs.mount-rmtab", &nfs->rmtab);
+ if (ret == -1) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse dict");
+ goto free_foppool;
+ }
+ }
+
+ /* support both options rpc-auth.ports.insecure and
+ * rpc-auth-allow-insecure for backward compatibility
+ */
+ nfs->allow_insecure = 1;
+ if (dict_get(this->options, "rpc-auth.ports.insecure")) {
+ ret = dict_get_str (this->options, "rpc-auth.ports.insecure",
+ &optstr);
+ if (ret < 0) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse dict");
+ goto free_foppool;
+ }
+
+ ret = gf_string2boolean (optstr, &boolt);
+ if (ret < 0) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse bool "
+ "string");
+ goto free_foppool;
+ }
+
+ if (boolt == _gf_false)
+ nfs->allow_insecure = 0;
+ }
+
+ if (dict_get(this->options, "rpc-auth-allow-insecure")) {
+ ret = dict_get_str (this->options, "rpc-auth-allow-insecure",
+ &optstr);
+ if (ret < 0) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse dict");
+ goto free_foppool;
+ }
+
+ ret = gf_string2boolean (optstr, &boolt);
+ if (ret < 0) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse bool "
+ "string");
+ goto free_foppool;
+ }
+
+ if (boolt == _gf_false)
+ nfs->allow_insecure = 0;
+ }
+
+ if (nfs->allow_insecure) {
+ /* blindly set both the options */
+ dict_del (this->options, "rpc-auth-allow-insecure");
+ ret = dict_set_str (this->options,
+ "rpc-auth-allow-insecure", "on");
+ if (ret == -1) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "dict_set_str error");
+ goto free_foppool;
+ }
+ dict_del (this->options, "rpc-auth.ports.insecure");
+ ret = dict_set_str (this->options,
+ "rpc-auth.ports.insecure", "on");
+ if (ret == -1) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "dict_set_str error");
+ goto free_foppool;
+ }
+ }
+
+ GF_OPTION_INIT (OPT_SERVER_AUX_GIDS, nfs->server_aux_gids,
+ bool, free_foppool);
+ GF_OPTION_INIT (OPT_SERVER_GID_CACHE_TIMEOUT, nfs->server_aux_gids_max_age,
+ uint32, free_foppool);
+
+ if (gid_cache_init(&nfs->gid_cache, nfs->server_aux_gids_max_age) < 0) {
+ gf_log(GF_NFS, GF_LOG_ERROR, "Failed to initialize group cache.");
+ goto free_foppool;
+ }
+
+ if (stat("/sbin/rpc.statd", &stbuf) == -1) {
+ gf_log (GF_NFS, GF_LOG_WARNING, "/sbin/rpc.statd not found. "
+ "Disabling NLM");
+ nfs->enable_nlm = _gf_false;
+ }
+
+ nfs->rpcsvc = rpcsvc_init (this, this->ctx, this->options, 0);
+ if (!nfs->rpcsvc) {
+ ret = -1;
+ gf_log (GF_NFS, GF_LOG_ERROR, "RPC service init failed");
+ goto free_foppool;
+ }
+
+ nfs->register_portmap = rpcsvc_register_portmap_enabled (nfs->rpcsvc);
+
this->private = (void *)nfs;
INIT_LIST_HEAD (&nfs->versions);
+ nfs->generation = 1965;
+
+ ret = 0;
+
+free_foppool:
+ if (ret < 0)
+ mem_pool_destroy (nfs->foppool);
+
+free_rpcsvc:
+ /*
+ * rpcsvc_deinit */
+ if (ret < 0) {
+ GF_FREE (nfs);
+ nfs = NULL;
+ }
+
+ return nfs;
+}
+
+int
+nfs_drc_init (xlator_t *this)
+{
+ int ret = -1;
+ rpcsvc_t *svc = NULL;
+
+ svc = ((struct nfs_state *)(this->private))->rpcsvc;
+ if (!svc)
+ goto out;
+
+ ret = rpcsvc_drc_init (svc, this->options);
+
+ out:
+ return ret;
+}
+
+int
+nfs_reconfigure_state (xlator_t *this, dict_t *options)
+{
+ int ret = 0;
+ int keyindx = 0;
+ char *optstr = NULL;
+ gf_boolean_t optbool;
+ uint32_t optuint32;
+ struct nfs_state *nfs = NULL;
+ char *blacklist_keys[] = {
+ "nfs.port",
+ "nfs.transport-type",
+ "nfs.mem-factor",
+ NULL};
+
+ GF_VALIDATE_OR_GOTO (GF_NFS, this, out);
+ GF_VALIDATE_OR_GOTO (GF_NFS, this->private, out);
+ GF_VALIDATE_OR_GOTO (GF_NFS, options, out);
+
+ nfs = (struct nfs_state *)this->private;
+
+ /* Black listed options can't be reconfigured, they need
+ * NFS to be restarted. There are two cases 1. SET 2. UNSET.
+ * 1. SET */
+ while (blacklist_keys[keyindx]) {
+ if (dict_get (options, blacklist_keys[keyindx])) {
+ gf_log (GF_NFS, GF_LOG_ERROR,
+ "Reconfiguring %s needs NFS restart",
+ blacklist_keys[keyindx]);
+ goto out;
+ }
+ keyindx ++;
+ }
+
+ /* UNSET for nfs.mem-factor */
+ if ((!dict_get (options, "nfs.mem-factor")) &&
+ (nfs->memfactor != GF_NFS_DEFAULT_MEMFACTOR)) {
+ gf_log (GF_NFS, GF_LOG_INFO,
+ "Reconfiguring nfs.mem-factor needs NFS restart");
+ goto out;
+ }
+
+ /* UNSET for nfs.port */
+ if ((!dict_get (options, "nfs.port")) &&
+ (nfs->override_portnum)) {
+ gf_log (GF_NFS, GF_LOG_ERROR,
+ "Reconfiguring nfs.port needs NFS restart");
+ goto out;
+ }
+
+ /* reconfig nfs.mount-rmtab */
+ optstr = NFS_DATADIR "/rmtab";
+ if (dict_get (options, "nfs.mount-rmtab")) {
+ ret = dict_get_str (options, "nfs.mount-rmtab", &optstr);
+ if (ret < 0) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to read "
+ "reconfigured option: nfs.mount-rmtab");
+ goto out;
+ }
+ gf_path_strip_trailing_slashes (optstr);
+ }
+ if (strcmp (nfs->rmtab, optstr) != 0) {
+ mount_rewrite_rmtab (nfs->mstate, optstr);
+ gf_log (GF_NFS, GF_LOG_INFO,
+ "Reconfigured nfs.mount-rmtab path: %s",
+ nfs->rmtab);
+ }
+
+ GF_OPTION_RECONF (OPT_SERVER_AUX_GIDS, optbool,
+ options, bool, out);
+ if (nfs->server_aux_gids != optbool) {
+ nfs->server_aux_gids = optbool;
+ gf_log(GF_NFS, GF_LOG_INFO, "Reconfigured %s with value %d",
+ OPT_SERVER_AUX_GIDS, optbool);
+ }
+
+ GF_OPTION_RECONF (OPT_SERVER_GID_CACHE_TIMEOUT, optuint32,
+ options, uint32, out);
+ if (nfs->server_aux_gids_max_age != optuint32) {
+ nfs->server_aux_gids_max_age = optuint32;
+ gid_cache_reconf (&nfs->gid_cache, optuint32);
+ gf_log(GF_NFS, GF_LOG_INFO, "Reconfigured %s with value %d",
+ OPT_SERVER_GID_CACHE_TIMEOUT, optuint32);
+ }
+
+ /* reconfig nfs.dynamic-volumes */
+ ret = dict_get_str_boolean (options, "nfs.dynamic-volumes",
+ GF_NFS_DVM_OFF);
+ switch (ret) {
+ case GF_NFS_DVM_ON:
+ case GF_NFS_DVM_OFF:
+ optbool = ret;
+ break;
+ default:
+ optbool = GF_NFS_DVM_OFF;
+ break;
+ }
+ if (nfs->dynamicvolumes != optbool) {
+ nfs->dynamicvolumes = optbool;
+ gf_log(GF_NFS, GF_LOG_INFO, "Reconfigured nfs.dynamic-volumes"
+ " with value %d", optbool);
+ }
+
+ optbool = _gf_false;
+ if (dict_get (options, "nfs.enable-ino32")) {
+ ret = dict_get_str_boolean (options, "nfs.enable-ino32",
+ _gf_false);
+ if (ret < 0) {
+ gf_log (GF_NFS, GF_LOG_ERROR,
+ "Failed to read reconfigured option: "
+ "nfs.enable-ino32");
+ goto out;
+ }
+ optbool = ret;
+ }
+ if (nfs->enable_ino32 != optbool) {
+ nfs->enable_ino32 = optbool;
+ gf_log(GF_NFS, GF_LOG_INFO, "Reconfigured nfs.enable-ino32"
+ " with value %d", optbool);
+ }
+
+ /* nfs.nlm is enabled by default */
+ ret = dict_get_str_boolean (options, "nfs.nlm", _gf_true);
+ if (ret < 0) {
+ optbool = _gf_true;
+ } else {
+ optbool = ret;
+ }
+ if (nfs->enable_nlm != optbool) {
+ gf_log (GF_NFS, GF_LOG_INFO, "NLM is manually %s",
+ (optbool ? "enabled":"disabled"));
+ nfs->enable_nlm = optbool;
+ nfs_reconfigure_nlm4 (this);
+ }
+
+ /* nfs.acl is enabled by default */
+ ret = dict_get_str_boolean (options, "nfs.acl", _gf_true);
+ if (ret < 0) {
+ optbool = _gf_true;
+ } else {
+ optbool = ret;
+ }
+ if (nfs->enable_acl != optbool) {
+ gf_log (GF_NFS, GF_LOG_INFO, "ACL is manually %s",
+ (optbool ? "enabled":"disabled"));
+ nfs->enable_acl = optbool;
+ nfs_reconfigure_acl3 (this);
+ }
+
+ ret = 0;
+out:
+ return ret;
+}
+
+
+/*
+ * reconfigure() for NFS server xlator.
+ */
+int
+reconfigure (xlator_t *this, dict_t *options)
+{
+ int ret = 0;
+ struct nfs_state *nfs = NULL;
+ gf_boolean_t regpmap = _gf_true;
+
+ if ((!this) || (!this->private) || (!options))
+ return (-1);
+
+ nfs = (struct nfs_state *)this->private;
+
+ /* Reconfigure nfs options */
+ ret = nfs_reconfigure_state(this, options);
+ if (ret) {
+ gf_log (GF_NFS, GF_LOG_ERROR,
+ "nfs reconfigure state failed");
+ return (-1);
+ }
+
+ /* Reconfigure nfs3 options */
+ ret = nfs3_reconfigure_state(this, options);
+ if (ret) {
+ gf_log (GF_NFS, GF_LOG_ERROR,
+ "nfs3 reconfigure state failed");
+ return (-1);
+ }
+
+ /* Reconfigure mount options */
+ ret = mount_reconfigure_state(this, options);
+ if (ret) {
+ gf_log (GF_NFS, GF_LOG_ERROR,
+ "mount reconfigure state failed");
+ return (-1);
+ }
+
+ /* Reconfigure rpc layer */
+ ret = rpcsvc_reconfigure_options (nfs->rpcsvc, options);
+ if (ret) {
+ gf_log (GF_NFS, GF_LOG_ERROR,
+ "rpcsvc reconfigure options failed");
+ return (-1);
+ }
+ regpmap = rpcsvc_register_portmap_enabled(nfs->rpcsvc);
+ if (nfs->register_portmap != regpmap) {
+ nfs->register_portmap = regpmap;
+ if (regpmap) {
+ (void) nfs_program_register_portmap_all (nfs);
+ } else {
+ (void) nfs_program_unregister_portmap_all (nfs);
+ }
+ }
+
+ /* Reconfigure drc */
+ ret = rpcsvc_drc_reconfigure (nfs->rpcsvc, options);
+ if (ret) {
+ gf_log (GF_NFS, GF_LOG_ERROR,
+ "rpcsvc DRC reconfigure failed");
+ return (-1);
+ }
+
+ return (0);
+}
+
+int
+init (xlator_t *this) {
+
+ struct nfs_state *nfs = NULL;
+ int ret = -1;
+
+ if (!this)
+ return -1;
+
+ nfs = nfs_init_state (this);
+ if (!nfs) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to init nfs option");
+ return -1;
+ }
+
ret = nfs_add_all_initiators (nfs);
if (ret == -1) {
gf_log (GF_NFS, GF_LOG_ERROR, "Failed to add initiators");
- goto free_nfs;
+ goto err;
}
ret = nfs_init_subvolumes (nfs, this->children);
if (ret == -1) {
- gf_log (GF_NFS, GF_LOG_CRITICAL, "Failed to init NFS exports");
- goto free_rpcsvc;
+ gf_log (GF_NFS, GF_LOG_CRITICAL, "Failed to init NFS "
+ "exports");
+ goto err;
}
-free_rpcsvc:
- /*
- * rpcsvc_deinit */
-free_nfs:
- if (ret == -1)
- FREE (nfs);
+ ret = mount_init_state (this);
+ if (ret == -1) {
+ gf_log (GF_NFS, GF_LOG_CRITICAL, "Failed to init Mount"
+ "state");
+ goto err;
+ }
+
+ ret = nlm4_init_state (this);
+ if (ret == -1) {
+ gf_log (GF_NFS, GF_LOG_CRITICAL, "Failed to init NLM"
+ "state");
+ goto err;
+ }
+
+ ret = nfs_init_versions (nfs, this);
+ if (ret == -1) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to initialize "
+ "protocols");
+ /* Do not return an error on this. If we dont return
+ * an error, the process keeps running and it helps
+ * to point out where the log is by doing ps ax|grep gluster.
+ */
+ ret = 0;
+ goto err;
+ }
+
+ ret = nfs_drc_init (this);
+ if (ret == 0)
+ gf_log (GF_NFS, GF_LOG_INFO, "NFS service started");
+err:
- gf_log (GF_NFS, GF_LOG_DEBUG, "NFS service started");
return ret;
}
@@ -504,39 +1293,27 @@ free_nfs:
int
notify (xlator_t *this, int32_t event, void *data, ...)
{
- struct nfs_state *nfs = NULL;
xlator_t *subvol = NULL;
- int ret = -1;
+ struct nfs_state *priv = NULL;
- nfs = (struct nfs_state *)this->private;
subvol = (xlator_t *)data;
gf_log (GF_NFS, GF_LOG_TRACE, "Notification received: %d",
event);
- switch (event)
- {
- case GF_EVENT_CHILD_UP:
- {
- nfs_startup_subvolume (this, subvol);
- if ((nfs->upsubvols == nfs->allsubvols) &&
- (!nfs->subvols_started)) {
- nfs->subvols_started = 1;
- gf_log (GF_NFS, GF_LOG_TRACE, "All children up,"
- " starting RPC");
- ret = nfs_init_versions (nfs, this);
- if (ret == -1)
- gf_log (GF_NFS, GF_LOG_CRITICAL,
- "Failed to initialize "
- "protocols");
- }
- break;
- }
- case GF_EVENT_PARENT_UP:
- {
- default_notify (this, GF_EVENT_PARENT_UP, data);
- break;
- }
+ switch (event) {
+ case GF_EVENT_CHILD_UP:
+ nfs_startup_subvolume (this, subvol);
+ break;
+
+ case GF_EVENT_CHILD_MODIFIED:
+ priv = this->private;
+ ++(priv->generation);
+ break;
+
+ case GF_EVENT_PARENT_UP:
+ default_notify (this, GF_EVENT_PARENT_UP, data);
+ break;
}
return 0;
@@ -555,35 +1332,263 @@ fini (xlator_t *this)
return 0;
}
-struct xlator_cbks cbks = { };
-struct xlator_mops mops = { };
-struct xlator_fops fops = { };
+int32_t
+nfs_forget (xlator_t *this, inode_t *inode)
+{
+ uint64_t ctx = 0;
+ struct nfs_inode_ctx *ictx = NULL;
+
+ if (inode_ctx_del (inode, this, &ctx))
+ return -1;
+
+ ictx = (struct nfs_inode_ctx *)ctx;
+ GF_FREE (ictx);
+
+ return 0;
+}
+
+gf_boolean_t
+_nfs_export_is_for_vol (char *exname, char *volname)
+{
+ gf_boolean_t ret = _gf_false;
+ char *tmp = NULL;
+
+ tmp = exname;
+ if (tmp[0] == '/')
+ tmp++;
+
+ if (!strcmp (tmp, volname))
+ ret = _gf_true;
+
+ return ret;
+}
+
+int
+nfs_priv_to_dict (xlator_t *this, dict_t *dict)
+{
+ int ret = -1;
+ struct nfs_state *priv = NULL;
+ struct mountentry *mentry = NULL;
+ char *volname = NULL;
+ char key[1024] = {0,};
+ int count = 0;
+
+ GF_VALIDATE_OR_GOTO (THIS->name, this, out);
+ GF_VALIDATE_OR_GOTO (THIS->name, dict, out);
+
+ priv = this->private;
+ GF_ASSERT (priv);
+
+ ret = dict_get_str (dict, "volname", &volname);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Could not get volname");
+ goto out;
+ }
+
+ list_for_each_entry (mentry, &priv->mstate->mountlist, mlist) {
+ if (!_nfs_export_is_for_vol (mentry->exname, volname))
+ continue;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "client%d.hostname", count);
+ ret = dict_set_str (dict, key, mentry->hostname);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Error writing hostname to dict");
+ goto out;
+ }
+
+ /* No connection data available yet in nfs server.
+ * Hence, setting to 0 to prevent cli failing
+ */
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "client%d.bytesread", count);
+ ret = dict_set_uint64 (dict, key, 0);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Error writing bytes read to dict");
+ goto out;
+ }
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "client%d.byteswrite", count);
+ ret = dict_set_uint64 (dict, key, 0);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Error writing bytes write to dict");
+ goto out;
+ }
+
+ count++;
+ }
+
+ ret = dict_set_int32 (dict, "clientcount", count);
+ if (ret)
+ gf_log (this->name, GF_LOG_ERROR,
+ "Error writing client count to dict");
+
+out:
+ gf_log (THIS->name, GF_LOG_DEBUG, "Returning %d", ret);
+ return ret;
+}
+
+extern int32_t
+nlm_priv (xlator_t *this);
+
+int32_t
+nfs_priv (xlator_t *this)
+{
+ int32_t ret = -1;
+
+ /* DRC needs the global drc structure, xl is of no use to it. */
+ ret = rpcsvc_drc_priv (((struct nfs_state *)(this->private))->rpcsvc->drc);
+ if (ret) {
+ gf_log (this->name, GF_LOG_DEBUG, "Statedump of DRC failed");
+ goto out;
+ }
+ ret = nlm_priv (this);
+ if (ret) {
+ gf_log (this->name, GF_LOG_DEBUG, "Statedump of NLM failed");
+ goto out;
+ }
+ out:
+ return ret;
+}
+
+
+struct xlator_cbks cbks = {
+ .forget = nfs_forget,
+};
+
+struct xlator_fops fops;
+
+struct xlator_dumpops dumpops = {
+ .priv = nfs_priv,
+ .priv_to_dict = nfs_priv_to_dict,
+};
+
+/* TODO: If needed, per-volume options below can be extended to be export
++ * specific also because after export-dir is introduced, a volume is not
++ * neccessarily an export whereas different subdirectories within that volume
++ * can be and may need these options to be specified separately.
++ */
struct volume_options options[] = {
{ .key = {"nfs3.read-size"},
.type = GF_OPTION_TYPE_SIZET,
- .description = "Size in which the client should issue read requests"
- " to the Gluster NFSv3 server. Must be a multiple of"
- " 4KiB."
+ .min = GF_NFS3_RTMIN,
+ .max = GF_NFS3_RTMAX,
+ .default_value = TOSTRING(GF_NFS3_RTPREF),
+ .description = "Size in which the client should issue read requests "
+ "to the Gluster NFSv3 server. Must be a multiple of "
+ "4KB (4096). Min and Max supported values are 4KB "
+ "(4096) and 1MB (1048576) respectively. If the "
+ "specified value is within the supported range but "
+ "not a multiple of 4096, it is rounded up to the "
+ "nearest multiple of 4096."
},
{ .key = {"nfs3.write-size"},
.type = GF_OPTION_TYPE_SIZET,
- .description = "Size in which the client should issue write requests"
- " to the Gluster NFSv3 server. Must be a multiple of"
- " 4KiB."
+ .min = GF_NFS3_WTMIN,
+ .max = GF_NFS3_WTMAX,
+ .default_value = TOSTRING(GF_NFS3_WTPREF),
+ .description = "Size in which the client should issue write requests "
+ "to the Gluster NFSv3 server. Must be a multiple of "
+ "1KB (1024). Min and Max supported values are "
+ "4KB (4096) and 1MB(1048576) respectively. If the "
+ "specified value is within the supported range but "
+ "not a multiple of 4096, it is rounded up to the "
+ "nearest multiple of 4096."
},
{ .key = {"nfs3.readdir-size"},
.type = GF_OPTION_TYPE_SIZET,
+ .min = GF_NFS3_DTMIN,
+ .max = GF_NFS3_DTMAX,
+ .default_value = TOSTRING(GF_NFS3_DTPREF),
.description = "Size in which the client should issue directory "
- " reading requests."
+ "reading requests to the Gluster NFSv3 server. Must "
+ "be a multiple of 1KB (1024). Min and Max supported "
+ "values are 4KB (4096) and 1MB (1048576) respectively."
+ "If the specified value is within the supported range "
+ "but not a multiple of 4096, it is rounded up to the "
+ "nearest multiple of 4096."
},
{ .key = {"nfs3.*.volume-access"},
.type = GF_OPTION_TYPE_STR,
+ .value = {"read-only", "read-write"},
+ .default_value = "read-write",
.description = "Type of access desired for this subvolume: "
" read-only, read-write(default)"
},
+ { .key = {"nfs3.*.trusted-write"},
+ .type = GF_OPTION_TYPE_BOOL,
+ .default_value = "off",
+ .description = "On an UNSTABLE write from client, return STABLE flag"
+ " to force client to not send a COMMIT request. In "
+ "some environments, combined with a replicated "
+ "GlusterFS setup, this option can improve write "
+ "performance. This flag allows user to trust Gluster"
+ " replication logic to sync data to the disks and "
+ "recover when required. COMMIT requests if received "
+ "will be handled in a default manner by fsyncing."
+ " STABLE writes are still handled in a sync manner. "
+ "Off by default."
+
+ },
+ { .key = {"nfs3.*.trusted-sync"},
+ .type = GF_OPTION_TYPE_BOOL,
+ .default_value = "off",
+ .description = "All writes and COMMIT requests are treated as async."
+ " This implies that no write requests are guaranteed"
+ " to be on server disks when the write reply is "
+ "received at the NFS client. Trusted sync includes "
+ " trusted-write behaviour. Off by default."
+
+ },
+ { .key = {"nfs3.*.export-dir"},
+ .type = GF_OPTION_TYPE_PATH,
+ .default_value = "",
+ .description = "By default, all subvolumes of nfs are exported as "
+ "individual exports. There are cases where a "
+ "subdirectory or subdirectories in the volume need to "
+ "be exported separately. This option can also be used "
+ "in conjunction with nfs3.export-volumes option to "
+ "restrict exports only to the subdirectories specified"
+ " through this option. Must be an absolute path. Along"
+ " with path allowed list of IPs/hostname can be "
+ "associated with each subdirectory. If provided "
+ "connection will allowed only from these IPs. By "
+ "default connections from all IPs are allowed. "
+ "Format: <dir>[(hostspec[|hostspec|...])][,...]. Where"
+ " hostspec can be an IP address, hostname or an IP "
+ "range in CIDR notation. "
+ "e.g. /foo(192.168.1.0/24|host1|10.1.1.8),/host2."
+ " NOTE: Care must be taken while configuring this "
+ "option as invalid entries and/or unreachable DNS "
+ "servers can introduce unwanted delay in all the mount"
+ " calls."
+ },
+ { .key = {"nfs3.export-dirs"},
+ .type = GF_OPTION_TYPE_BOOL,
+ .default_value = "on",
+ .description = "By default, all subvolumes of nfs are exported as "
+ "individual exports. There are cases where a "
+ "subdirectory or subdirectories in the volume need to "
+ "be exported separately. Enabling this option allows "
+ "any directory on a volumes to be exported separately."
+ "Directory exports are enabled by default."
+ },
+ { .key = {"nfs3.export-volumes"},
+ .type = GF_OPTION_TYPE_BOOL,
+ .default_value = "on",
+ .description = "Enable or disable exporting whole volumes, instead "
+ "if used in conjunction with nfs3.export-dir, can "
+ "allow setting up only subdirectories as exports. On "
+ "by default."
+ },
{ .key = {"rpc-auth.auth-unix"},
.type = GF_OPTION_TYPE_BOOL,
+ .default_value = "on",
.description = "Disable or enable the AUTH_UNIX authentication type."
"Must always be enabled for better interoperability."
"However, can be disabled if needed. Enabled by"
@@ -591,14 +1596,26 @@ struct volume_options options[] = {
},
{ .key = {"rpc-auth.auth-null"},
.type = GF_OPTION_TYPE_BOOL,
+ .default_value = "on",
.description = "Disable or enable the AUTH_NULL authentication type."
"Must always be enabled. This option is here only to"
" avoid unrecognized option warnings"
},
{ .key = {"rpc-auth.auth-unix.*"},
.type = GF_OPTION_TYPE_BOOL,
+ .default_value = "on",
+ .description = "Disable or enable the AUTH_UNIX authentication type "
+ "for a particular exported volume overriding defaults"
+ " and general setting for AUTH_UNIX scheme. Must "
+ "always be enabled for better interoperability."
+ "However, can be disabled if needed. Enabled by"
+ "default."
+ },
+ { .key = {"rpc-auth.auth-unix.*.allow"},
+ .type = GF_OPTION_TYPE_STR,
+ .default_value = "on",
.description = "Disable or enable the AUTH_UNIX authentication type "
- "for a particular exported volume over-riding defaults"
+ "for a particular exported volume overriding defaults"
" and general setting for AUTH_UNIX scheme. Must "
"always be enabled for better interoperability."
"However, can be disabled if needed. Enabled by"
@@ -606,42 +1623,48 @@ struct volume_options options[] = {
},
{ .key = {"rpc-auth.auth-null.*"},
.type = GF_OPTION_TYPE_BOOL,
+ .default_value = "on",
.description = "Disable or enable the AUTH_NULL authentication type "
- "for a particular exported volume over-riding defaults"
+ "for a particular exported volume overriding defaults"
" and general setting for AUTH_NULL. Must always be "
"enabled. This option is here only to avoid "
"unrecognized option warnings."
},
{ .key = {"rpc-auth.addr.allow"},
- .type = GF_OPTION_TYPE_STR,
+ .type = GF_OPTION_TYPE_INTERNET_ADDRESS_LIST,
+ .default_value = "all",
.description = "Allow a comma separated list of addresses and/or"
" hostnames to connect to the server. By default, all"
- " connections are disallowed. This allows users to "
+ " connections are allowed. This allows users to "
"define a general rule for all exported volumes."
},
{ .key = {"rpc-auth.addr.reject"},
- .type = GF_OPTION_TYPE_STR,
+ .type = GF_OPTION_TYPE_INTERNET_ADDRESS_LIST,
+ .default_value = "none",
.description = "Reject a comma separated list of addresses and/or"
" hostnames from connecting to the server. By default,"
- " all connections are disallowed. This allows users to"
+ " all connections are allowed. This allows users to"
"define a general rule for all exported volumes."
},
{ .key = {"rpc-auth.addr.*.allow"},
- .type = GF_OPTION_TYPE_STR,
+ .type = GF_OPTION_TYPE_INTERNET_ADDRESS_LIST,
+ .default_value = "all",
.description = "Allow a comma separated list of addresses and/or"
" hostnames to connect to the server. By default, all"
- " connections are disallowed. This allows users to "
+ " connections are allowed. This allows users to "
"define a rule for a specific exported volume."
},
{ .key = {"rpc-auth.addr.*.reject"},
- .type = GF_OPTION_TYPE_STR,
+ .type = GF_OPTION_TYPE_INTERNET_ADDRESS_LIST,
+ .default_value = "none",
.description = "Reject a comma separated list of addresses and/or"
" hostnames from connecting to the server. By default,"
- " all connections are disallowed. This allows users to"
+ " all connections are allowed. This allows users to"
"define a rule for a specific exported volume."
},
{ .key = {"rpc-auth.ports.insecure"},
.type = GF_OPTION_TYPE_BOOL,
+ .default_value = "off",
.description = "Allow client connections from unprivileged ports. By "
"default only privileged ports are allowed. This is a"
"global setting in case insecure ports are to be "
@@ -649,23 +1672,154 @@ struct volume_options options[] = {
},
{ .key = {"rpc-auth.ports.*.insecure"},
.type = GF_OPTION_TYPE_BOOL,
+ .default_value = "off",
.description = "Allow client connections from unprivileged ports. By "
"default only privileged ports are allowed. Use this"
- " option to set enable or disable insecure ports for "
- "a specific subvolume and to over-ride global setting "
- " set by the previous option."
+ " option to enable or disable insecure ports for "
+ "a specific subvolume and to override the global "
+ "setting set by the previous option."
},
{ .key = {"rpc-auth.addr.namelookup"},
.type = GF_OPTION_TYPE_BOOL,
- .description = "Users have the option of turning off name lookup for"
- " incoming client connections using this option. In some "
+ .default_value = "off",
+ .description = "Users have the option of turning on name lookup for"
+ " incoming client connections using this option. Use this "
+ "option to turn on name lookups during address-based "
+ "authentication. Turning this on will enable you to"
+ " use hostnames in nfs.rpc-auth-* filters. In some "
"setups, the name server can take too long to reply to DNS "
- "queries resulting in timeouts of mount requests. Use this "
- "option to turn off name lookups during address "
- "authentication. Note, turning this off will prevent you from"
- " using hostnames in rpc-auth.addr.* filters. By default, "
- " name lookup is on."
+ "queries resulting in timeouts of mount requests. By "
+ "default, name lookup is off"
+ },
+ { .key = {"nfs.dynamic-volumes"},
+ .type = GF_OPTION_TYPE_BOOL,
+ .default_value = "off",
+ .description = "Internal option set to tell gnfs to use a different"
+ " scheme for encoding file handles when DVM is being"
+ " used."
+ },
+ { .key = {"nfs3.*.volume-id"},
+ .type = GF_OPTION_TYPE_STR,
+ .default_value = "",
+ .description = "When nfs.dynamic-volumes is set, gnfs expects every "
+ "subvolume to have this option set for it, so that "
+ "gnfs can use this option to identify the volume. "
+ "If all subvolumes do not have this option set, an "
+ "error is reported."
+ },
+ { .key = {"nfs.enable-ino32"},
+ .type = GF_OPTION_TYPE_BOOL,
+ .default_value = "no",
+ .description = "For nfs clients or apps that do not support 64-bit "
+ "inode numbers, use this option to make NFS return "
+ "32-bit inode numbers instead. Disabled by default, so"
+ " NFS returns 64-bit inode numbers."
+ },
+ { .key = {"rpc.register-with-portmap"},
+ .type = GF_OPTION_TYPE_BOOL,
+ .default_value = "on",
+ .description = "For systems that need to run multiple nfs servers, "
+ "only one registration is possible with "
+ "portmap service. Use this option to turn off portmap "
+ "registration for Gluster NFS. On by default"
+ },
+ { .key = {"rpc.outstanding-rpc-limit"},
+ .type = GF_OPTION_TYPE_INT,
+ .min = RPCSVC_MIN_OUTSTANDING_RPC_LIMIT,
+ .max = RPCSVC_MAX_OUTSTANDING_RPC_LIMIT,
+ .default_value = TOSTRING(RPCSVC_DEFAULT_OUTSTANDING_RPC_LIMIT),
+ .description = "Parameter to throttle the number of incoming RPC "
+ "requests from a client. 0 means no limit (can "
+ "potentially run out of memory)"
+ },
+ { .key = {"nfs.port"},
+ .type = GF_OPTION_TYPE_INT,
+ .min = 1,
+ .max = 0xffff,
+ .default_value = TOSTRING(GF_NFS3_PORT),
+ .description = "Use this option on systems that need Gluster NFS to "
+ "be associated with a non-default port number."
+ },
+ { .key = {"nfs.mem-factor"},
+ .type = GF_OPTION_TYPE_INT,
+ .min = 1,
+ .max = 1024,
+ .default_value = TOSTRING(GF_NFS_DEFAULT_MEMFACTOR),
+ .description = "Use this option to make NFS be faster on systems by "
+ "using more memory. This option specifies a multiple "
+ "that determines the total amount of memory used. "
+ "Default value is 15. Increase to use more memory in "
+ "order to improve performance for certain use cases."
+ "Please consult gluster-users list before using this "
+ "option."
+ },
+ { .key = {"nfs.*.disable"},
+ .type = GF_OPTION_TYPE_BOOL,
+ .default_value = "false",
+ .description = "This option is used to start or stop NFS server"
+ "for individual volume."
},
- { .key = {NULL} },
-};
+ { .key = {"nfs.nlm"},
+ .type = GF_OPTION_TYPE_BOOL,
+ .default_value = "on",
+ .description = "This option, if set to 'off', disables NLM server "
+ "by not registering the service with the portmapper."
+ " Set it to 'on' to re-enable it. Default value: 'on'"
+ },
+
+ { .key = {"nfs.mount-udp"},
+ .type = GF_OPTION_TYPE_BOOL,
+ .default_value = "off",
+ .description = "set the option to 'on' to enable mountd on UDP. "
+ "Required for some Solaris and AIX NFS clients. "
+ "The need for enabling this option often depends "
+ "on the usage of NLM."
+ },
+ { .key = {"nfs.mount-rmtab"},
+ .type = GF_OPTION_TYPE_PATH,
+ .default_value = DATADIR "/rmtab",
+ .description = "Set the location of the cache file that is used to "
+ "list all the NFS-clients that have connected "
+ "through the MOUNT protocol. If this is on shared "
+ "storage, all GlusterFS servers will update and "
+ "output (with 'showmount') the same list."
+ },
+ { .key = {OPT_SERVER_AUX_GIDS},
+ .type = GF_OPTION_TYPE_BOOL,
+ .default_value = "off",
+ .description = "Let the server look up which groups a user belongs "
+ "to, overwriting the list passed from the client. "
+ "This enables support for group lists longer than "
+ "can be passed through the NFS protocol, but is not "
+ "secure unless users and groups are well synchronized "
+ "between clients and servers."
+ },
+ { .key = {OPT_SERVER_GID_CACHE_TIMEOUT},
+ .type = GF_OPTION_TYPE_INT,
+ .min = 0,
+ .max = 3600,
+ .default_value = "5",
+ .description = "Number of seconds to cache auxiliary-GID data, when "
+ OPT_SERVER_AUX_GIDS " is set."
+ },
+ { .key = {"nfs.acl"},
+ .type = GF_OPTION_TYPE_BOOL,
+ .default_value = "on",
+ .description = "This option is used to control ACL support for NFS."
+ },
+ { .key = {"nfs.drc"},
+ .type = GF_OPTION_TYPE_STR,
+ .default_value = "on",
+ .description = "Enable Duplicate Request Cache in gNFS server to "
+ "improve correctness of non-idempotent operations like "
+ "write, delete, link, et al"
+ },
+ { .key = {"nfs.drc-size"},
+ .type = GF_OPTION_TYPE_INT,
+ .default_value = "0x20000",
+ .description = "Sets the number of non-idempotent "
+ "requests to cache in drc"
+ },
+ { .key = {NULL} },
+};
diff --git a/xlators/nfs/server/src/nfs.h b/xlators/nfs/server/src/nfs.h
index b49738345..00c7f8046 100644
--- a/xlators/nfs/server/src/nfs.h
+++ b/xlators/nfs/server/src/nfs.h
@@ -1,20 +1,11 @@
/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
+ Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.com>
This file is part of GlusterFS.
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
*/
#ifndef __NFS_H__
@@ -28,6 +19,8 @@
#include "rpcsvc.h"
#include "dict.h"
#include "xlator.h"
+#include "lkowner.h"
+#include "gidcache.h"
#define GF_NFS "nfs"
@@ -42,6 +35,15 @@
#define GF_NFS_MIN_MEMFACTOR 1
#define GF_NFS_MAX_MEMFACTOR 30
+#define GF_NFS_DVM_ON 1
+#define GF_NFS_DVM_OFF 0
+
+/* This corresponds to the max 16 number of group IDs that are sent through an
+ * RPC request. Since NFS is the only one going to set this, we can be safe
+ * in keeping this size hardcoded.
+ */
+#define GF_REQUEST_MAXGROUPS 16
+
/* Callback into a version-specific NFS protocol.
* The return type is used by the nfs.c code to register the protocol.
* with the RPC service.
@@ -55,10 +57,12 @@ struct nfs_initer_list {
rpcsvc_program_t *program;
};
-
struct nfs_state {
rpcsvc_t *rpcsvc;
struct list_head versions;
+ struct mount3_state *mstate;
+ struct nfs3_state *nfs3state;
+ struct nlm4_state *nlm4state;
struct mem_pool *foppool;
unsigned int memfactor;
xlator_list_t *subvols;
@@ -68,8 +72,32 @@ struct nfs_state {
int upsubvols;
xlator_t **initedxl;
int subvols_started;
+ int dynamicvolumes;
+ int enable_ino32;
+ unsigned int override_portnum;
+ int allow_insecure;
+ int enable_nlm;
+ int enable_acl;
+ int mount_udp;
+ char *rmtab;
+ struct rpc_clnt *rpc_clnt;
+ gf_boolean_t server_aux_gids;
+ uint32_t server_aux_gids_max_age;
+ gid_cache_t gid_cache;
+ uint32_t generation;
+ gf_boolean_t register_portmap;
};
+struct nfs_inode_ctx {
+ struct list_head shares;
+ uint32_t generation;
+};
+
+#define gf_nfs_dvm_on(nfsstt) (((struct nfs_state *)nfsstt)->dynamicvolumes == GF_NFS_DVM_ON)
+#define gf_nfs_dvm_off(nfsstt) (((struct nfs_state *)nfsstt)->dynamicvolumes == GF_NFS_DVM_OFF)
+#define __gf_nfs_enable_ino32(nfsstt) (((struct nfs_state *)nfsstt)->enable_ino32)
+#define gf_nfs_this_private ((struct nfs_state *)((xlator_t *)THIS)->private)
+#define gf_nfs_enable_ino32() (__gf_nfs_enable_ino32(gf_nfs_this_private))
/* We have one gid more than the glusterfs maximum since we pass the primary
* gid as the first element of the array.
@@ -83,6 +111,7 @@ typedef struct nfs_user_info {
uid_t uid;
gid_t gids[NFS_NGROUPS];
int ngrps;
+ gf_lkowner_t lk_owner;
} nfs_user_t;
extern int
@@ -95,4 +124,12 @@ nfs_user_create (nfs_user_t *newnfu, uid_t uid, gid_t gid, gid_t *auxgids,
extern void
nfs_request_user_init (nfs_user_t *nfu, rpcsvc_request_t *req);
+extern void
+nfs_request_primary_user_init (nfs_user_t *nfu, rpcsvc_request_t *req,
+ uid_t uid, gid_t gid);
+extern int
+nfs_subvolume_started (struct nfs_state *nfs, xlator_t *xl);
+
+extern void
+nfs_fix_groups (xlator_t *this, call_stack_t *root);
#endif
diff --git a/xlators/nfs/server/src/nfs3-fh.c b/xlators/nfs/server/src/nfs3-fh.c
index c7eb78fb3..e199c56dc 100644
--- a/xlators/nfs/server/src/nfs3-fh.c
+++ b/xlators/nfs/server/src/nfs3-fh.c
@@ -1,20 +1,11 @@
/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
+ Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.com>
This file is part of GlusterFS.
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
*/
#ifndef _CONFIG_H
@@ -31,6 +22,7 @@
#include "nfs3-fh.h"
#include "nfs-common.h"
#include "iatt.h"
+#include "common-utils.h"
int
@@ -45,19 +37,16 @@ nfs3_fh_validate (struct nfs3_fh *fh)
if (fh->ident[1] != GF_NFSFH_IDENT1)
return 0;
- return 1;
-}
+ if (fh->ident[2] != GF_NFSFH_IDENT2)
+ return 0;
+ if (fh->ident[3] != GF_NFSFH_IDENT3)
+ return 0;
-xlator_t *
-nfs3_fh_to_xlator (xlator_list_t *cl, struct nfs3_fh *fh)
-{
- if ((!cl) || (!fh))
- return NULL;
-
- return nfs_xlid_to_xlator (cl, fh->xlatorid);
+ return 1;
}
+
void
nfs3_fh_init (struct nfs3_fh *fh, struct iatt *buf)
{
@@ -66,128 +55,90 @@ nfs3_fh_init (struct nfs3_fh *fh, struct iatt *buf)
fh->ident[0] = GF_NFSFH_IDENT0;
fh->ident[1] = GF_NFSFH_IDENT1;
+ fh->ident[2] = GF_NFSFH_IDENT2;
+ fh->ident[3] = GF_NFSFH_IDENT3;
- fh->hashcount = 0;
- fh->gen = buf->ia_gen;
- fh->ino = buf->ia_ino;
-
+ uuid_copy (fh->gfid, buf->ia_gfid);
}
struct nfs3_fh
-nfs3_fh_build_root_fh (xlator_list_t *cl, xlator_t *xl, struct iatt buf)
+nfs3_fh_build_indexed_root_fh (xlator_list_t *cl, xlator_t *xl)
{
struct nfs3_fh fh = {{0}, };
+ struct iatt buf = {0, };
+ uuid_t root = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
+
if ((!cl) || (!xl))
return fh;
+ uuid_copy (buf.ia_gfid, root);
nfs3_fh_init (&fh, &buf);
- fh.xlatorid = nfs_xlator_to_xlid (cl, xl);
- fh.ino = 1;
- fh.gen = 0;
+ fh.exportid [15] = nfs_xlator_to_xlid (cl, xl);
+
return fh;
}
-int
-nfs3_fh_is_root_fh (struct nfs3_fh *fh)
+struct nfs3_fh
+nfs3_fh_build_uuid_root_fh (uuid_t volumeid)
{
- if (!fh)
- return 0;
+ struct nfs3_fh fh = {{0}, };
+ struct iatt buf = {0, };
+ uuid_t root = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
- if (fh->hashcount == 0)
- return 1;
+ uuid_copy (buf.ia_gfid, root);
+ nfs3_fh_init (&fh, &buf);
+ uuid_copy (fh.exportid, volumeid);
- return 0;
+ return fh;
}
-nfs3_hash_entry_t
-nfs3_fh_hash_entry (ino_t ino, uint64_t gen)
+int
+nfs3_fh_is_root_fh (struct nfs3_fh *fh)
{
- nfs3_hash_entry_t hash = 0;
- int shiftsize = 48;
- nfs3_hash_entry_t inomsb = 0;
- nfs3_hash_entry_t inolsb = 0;
- nfs3_hash_entry_t inols23b = 0;
-
- nfs3_hash_entry_t genmsb = 0;
- nfs3_hash_entry_t genlsb = 0;
- nfs3_hash_entry_t genls23b = 0;
-
- hash = ino;
- while (shiftsize != 0) {
- hash ^= (ino >> shiftsize);
- shiftsize -= 16;
- }
-/*
- gf_log ("FILEHANDLE", GF_LOG_TRACE, "INO %"PRIu64, ino);
- gf_log ("FILEHANDLE",GF_LOG_TRACE, "PRI HASH %d", hash);
-*/
- inomsb = (ino >> 56);
-// gf_log ("FILEHANDLE", GF_LOG_TRACE, "inomsb %d", inomsb);
+ uuid_t rootgfid = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
- inolsb = ((ino << 56) >> 56);
-// gf_log ("FILEHANDLE", GF_LOG_TRACE, "inolsb %d", inolsb);
-
- inolsb = (inolsb << 8);
-// gf_log ("FILEHANDLE", GF_LOG_TRACE, "inolsb to inomsb %d", inolsb);
- inols23b = ((ino << 40) >> 48);
-// gf_log ("FILEHANDLE", GF_LOG_TRACE, "inols23b %d", inols23b);
-
- inols23b = (inols23b << 8);
-// gf_log ("FILEHDNALE", GF_LOG_TRACE, "inols23b %d", inols23b);
-
- genmsb = (gen >> 56);
-// gf_log ("FILEHANDLE", GF_LOG_TRACE, "inomsb %d", inomsb);
-
- genlsb = ((gen << 56) >> 56);
-// gf_log ("FILEHANDLE", GF_LOG_TRACE, "inolsb %d", inolsb);
-
- genlsb = (genlsb << 8);
-// gf_log ("FILEHANDLE", GF_LOG_TRACE, "inolsb to inomsb %d", inolsb);
-
- genls23b = ((gen << 40) >> 48);
-// gf_log ("FILEHANDLE", GF_LOG_TRACE, "inols23b %d", inols23b);
-
- genls23b = (genls23b << 8);
-// gf_log ("FILEHDNALE", GF_LOG_TRACE, "inols23b %d", inols23b);
+ if (!fh)
+ return 0;
- hash ^= inolsb ^ inomsb ^ inols23b ^ genmsb ^ genlsb ^ genls23b;
- return hash;
+ if (uuid_compare (fh->gfid, rootgfid) == 0)
+ return 1;
+ return 0;
}
void
-nfs3_fh_to_str (struct nfs3_fh *fh, char *str)
+nfs3_fh_to_str (struct nfs3_fh *fh, char *str, size_t len)
{
+ char gfid[GF_UUID_BUF_SIZE];
+ char exportid[GF_UUID_BUF_SIZE];
+
if ((!fh) || (!str))
return;
- sprintf (str, "FH: hashcount %d, xlid %d, gen %"PRIu64", ino %"PRIu64,
- fh->hashcount, fh->xlatorid, fh->gen, fh->ino);
+ snprintf (str, len, "FH: exportid %s, gfid %s",
+ uuid_utoa_r (fh->exportid, exportid),
+ uuid_utoa_r (fh->gfid, gfid));
}
-
void
nfs3_log_fh (struct nfs3_fh *fh)
{
-// int x = 0;
+ char gfidstr[512];
+ char exportidstr[512];
+
if (!fh)
return;
- gf_log ("nfs3-fh", GF_LOG_TRACE, "filehandle: hashcount %d, xlid %d, "
- "gen %"PRIu64", ino %"PRIu64, fh->hashcount, fh->xlatorid,
- fh->gen, fh->ino);
-/*
- for (; x < fh->hashcount; ++x)
- gf_log ("FILEHANDLE", GF_LOG_TRACE, "Hash %d: %d", x,
- fh->entryhash[x]);
-*/
+ gf_log ("nfs3-fh", GF_LOG_TRACE, "filehandle: exportid "
+ "0x%s, gfid 0x%s",
+ uuid_utoa_r (fh->exportid, exportidstr),
+ uuid_utoa_r (fh->gfid, gfidstr));
}
-
int
nfs3_fh_build_parent_fh (struct nfs3_fh *child, struct iatt *newstat,
struct nfs3_fh *newfh)
@@ -196,50 +147,35 @@ nfs3_fh_build_parent_fh (struct nfs3_fh *child, struct iatt *newstat,
return -1;
nfs3_fh_init (newfh, newstat);
- newfh->xlatorid = child->xlatorid;
- if ((newstat->ia_ino == 1) && (newstat->ia_gen == 0)) {
- newfh->ino = 1;
- newfh->gen = 0;
- goto done;
- }
-
- newfh->hashcount = child->hashcount - 1;
- memcpy (newfh->entryhash, child->entryhash,
- newfh->hashcount * GF_NFSFH_ENTRYHASH_SIZE);
-
-done:
-// nfs3_log_fh (newfh);
+ uuid_copy (newfh->exportid, child->exportid);
return 0;
}
+int
+nfs3_build_fh (inode_t *inode, uuid_t exportid, struct nfs3_fh *newfh)
+{
+ if (!newfh || !inode)
+ return -1;
+ newfh->ident[0] = GF_NFSFH_IDENT0;
+ newfh->ident[1] = GF_NFSFH_IDENT1;
+ newfh->ident[2] = GF_NFSFH_IDENT2;
+ newfh->ident[3] = GF_NFSFH_IDENT3;
+ uuid_copy (newfh->gfid, inode->gfid);
+ uuid_copy (newfh->exportid, exportid);
+ return 0;
+}
int
nfs3_fh_build_child_fh (struct nfs3_fh *parent, struct iatt *newstat,
struct nfs3_fh *newfh)
{
- int entry = 0;
-
if ((!parent) || (!newstat) || (!newfh))
return -1;
nfs3_fh_init (newfh, newstat);
- newfh->xlatorid = parent->xlatorid;
- if ((newstat->ia_ino == 1) && (newstat->ia_gen == 0)) {
- newfh->ino = 1;
- newfh->gen = 0;
- goto done;
- }
-
- newfh->hashcount = parent->hashcount + 1;
- memcpy (newfh->entryhash, parent->entryhash,
- parent->hashcount * GF_NFSFH_ENTRYHASH_SIZE);
- entry = newfh->hashcount - 1;
- newfh->entryhash[entry] = nfs3_fh_hash_entry (parent->ino, parent->gen);
-
-done:
-// nfs3_log_fh (newfh);
+ uuid_copy (newfh->exportid, parent->exportid);
return 0;
}
@@ -248,24 +184,5 @@ done:
uint32_t
nfs3_fh_compute_size (struct nfs3_fh *fh)
{
- if (!fh)
- return 0;
-
- return (GF_NFSFH_STATIC_SIZE +
- (fh->hashcount * GF_NFSFH_ENTRYHASH_SIZE));
-}
-
-int
-nfs3_fh_hash_index_is_beyond (struct nfs3_fh *fh, int hashidx)
-{
- if (!fh)
- return 1;
-
- if (fh->hashcount >= hashidx)
- return 0;
- else
- return 1;
-
- return 1;
+ return GF_NFSFH_STATIC_SIZE;
}
-
diff --git a/xlators/nfs/server/src/nfs3-fh.h b/xlators/nfs/server/src/nfs3-fh.h
index f526edf43..1049cdc96 100644
--- a/xlators/nfs/server/src/nfs3-fh.h
+++ b/xlators/nfs/server/src/nfs3-fh.h
@@ -1,20 +1,11 @@
/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
+ Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.com>
This file is part of GlusterFS.
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
*/
#ifndef _NFS_FH_H_
@@ -29,62 +20,62 @@
#include "xdr-nfs3.h"
#include "iatt.h"
#include <sys/types.h>
+#include "uuid.h"
/* BIG FAT WARNING: The file handle code is tightly coupled to NFSv3 file
* handles for now. This will change if and when we need v4. */
#define GF_NFSFH_IDENT0 ':'
#define GF_NFSFH_IDENT1 'O'
-#define GF_NFSFH_IDENT_SIZE (sizeof(char) * 2)
-#define GF_NFSFH_STATIC_SIZE (GF_NFSFH_IDENT_SIZE + sizeof (uint16_t) + sizeof (uint16_t) + sizeof (uint64_t) + sizeof(uint64_t))
-#define GF_NFSFH_MAX_HASH_BYTES (NFS3_FHSIZE - GF_NFSFH_STATIC_SIZE)
-
-/* Each hash element in the file handle is of 2 bytes thus giving
- * us theoretically 65536 unique entries in a directory.
- */
-typedef uint16_t nfs3_hash_entry_t;
-#define GF_NFSFH_ENTRYHASH_SIZE (sizeof (nfs3_hash_entry_t))
-#define GF_NFSFH_MAXHASHES ((int)(GF_NFSFH_MAX_HASH_BYTES / GF_NFSFH_ENTRYHASH_SIZE))
+#define GF_NFSFH_IDENT2 'G'
+#define GF_NFSFH_IDENT3 'L'
+#define GF_NFSFH_IDENT_SIZE (sizeof(char) * 4)
+#define GF_NFSFH_STATIC_SIZE (GF_NFSFH_IDENT_SIZE + (2*sizeof (uuid_t)))
+#define nfs3_fh_exportid_to_index(exprtid) ((uint16_t)exprtid[15])
/* ATTENTION: Change in size of the structure below should be reflected in the
* GF_NFSFH_STATIC_SIZE.
*/
struct nfs3_fh {
/* Used to ensure that a bunch of bytes are actually a GlusterFS NFS
- * file handle. Should contain ":O"
+ * file handle. Should contain ":OGL"
*/
- char ident[2];
-
- /* Number of file/ino hash elements that follow the ino. */
- uint16_t hashcount;
-
- /* Basically, the position/index of an xlator among the children of
- * the NFS xlator.
+ char ident[4];
+
+ /* UUID that identifies an export. The value stored in exportid
+ * depends on the usage of gluster nfs. If the DVM is enabled using
+ * the nfs.dynamic-volumes option then exportid will contain the UUID
+ * of the volume so that gnfs is able to identify volumes uniquely
+ * through volume additions,deletions,migrations, etc.
+ *
+ * When not using dvm, exportid contains the index of the volume
+ * based on the position of the volume in the list of subvolumes
+ * for gnfs.
*/
- uint16_t xlatorid;
- uint64_t gen;
- uint64_t ino;
- nfs3_hash_entry_t entryhash[GF_NFSFH_MAXHASHES];
+ uuid_t exportid;
+
+ /* File/dir gfid. */
+ uuid_t gfid;
+ /* This structure must be exactly NFS3_FHSIZE (64) bytes long.
+ Having the structure shorter results in buffer overflows
+ during XDR decoding.
+ */
+ unsigned char padding[NFS3_FHSIZE - GF_NFSFH_STATIC_SIZE];
} __attribute__((__packed__));
+#define GF_NFS3FH_STATIC_INITIALIZER {{0},}
extern uint32_t
nfs3_fh_compute_size (struct nfs3_fh *fh);
-extern int
-nfs3_fh_hash_index_is_beyond (struct nfs3_fh *fh, int hashidx);
-
extern uint16_t
-nfs3_fh_hash_entry (ino_t ino, uint64_t gen);
+nfs3_fh_hash_entry (uuid_t gfid);
extern int
nfs3_fh_validate (struct nfs3_fh *fh);
-extern xlator_t *
-nfs3_fh_to_xlator (xlator_list_t *cl, struct nfs3_fh *fh);
-
extern struct nfs3_fh
-nfs3_fh_build_root_fh (xlator_list_t *cl, xlator_t *xl, struct iatt buf);
+nfs3_fh_build_indexed_root_fh (xlator_list_t *cl, xlator_t *xl);
extern int
nfs3_fh_is_root_fh (struct nfs3_fh *fh);
@@ -97,9 +88,16 @@ extern void
nfs3_log_fh (struct nfs3_fh *fh);
extern void
-nfs3_fh_to_str (struct nfs3_fh *fh, char *str);
+nfs3_fh_to_str (struct nfs3_fh *fh, char *str, size_t len);
extern int
nfs3_fh_build_parent_fh (struct nfs3_fh *child, struct iatt *newstat,
struct nfs3_fh *newfh);
+
+extern struct nfs3_fh
+nfs3_fh_build_uuid_root_fh (uuid_t volumeid);
+
+extern int
+nfs3_build_fh (inode_t *inode, uuid_t exportid, struct nfs3_fh *newfh);
+
#endif
diff --git a/xlators/nfs/server/src/nfs3-helpers.c b/xlators/nfs/server/src/nfs3-helpers.c
index 72861dfd0..9059fc341 100644
--- a/xlators/nfs/server/src/nfs3-helpers.c
+++ b/xlators/nfs/server/src/nfs3-helpers.c
@@ -1,20 +1,11 @@
/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
+ Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.com>
This file is part of GlusterFS.
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
*/
#ifndef _CONFIG_H
@@ -33,9 +24,18 @@
#include "nfs-inodes.h"
#include "nfs-generics.h"
#include "nfs3-helpers.h"
+#include "nfs-mem-types.h"
#include "iatt.h"
+#include "common-utils.h"
#include <string.h>
+extern int
+nfs3_set_root_looked_up (struct nfs3_state *nfs3, struct nfs3_fh *rootfh);
+
+extern int
+nfs3_is_root_looked_up (struct nfs3_state *nfs3, struct nfs3_fh *rootfh);
+
+
#define nfs3_call_resume(cst) \
do { \
if (((cst)) && (cst)->resume_fn) \
@@ -66,7 +66,7 @@ struct nfs3stat_strerror nfs3stat_strerror_table[] = {
{ NFS3ERR_XDEV, "Attempt to do a cross-device hard link"},
{ NFS3ERR_NODEV, "No such device" },
{ NFS3ERR_NOTDIR, "Not a directory" },
- { NFS3ERR_ISDIR, "Not a directory" },
+ { NFS3ERR_ISDIR, "Is a directory" },
{ NFS3ERR_INVAL, "Invalid argument for operation" },
{ NFS3ERR_FBIG, "File too large" },
{ NFS3ERR_NOSPC, "No space left on device" },
@@ -90,13 +90,34 @@ struct nfs3stat_strerror nfs3stat_strerror_table[] = {
};
+uint64_t
+nfs3_iatt_gfid_to_ino (struct iatt *buf)
+{
+ uint64_t ino = 0;
+
+ if (!buf)
+ return 0;
+
+ if (gf_nfs_enable_ino32()) {
+ ino = (uint32_t )nfs_hash_gfid (buf->ia_gfid);
+ goto hashout;
+ }
+
+ /* from posix its guaranteed to send unique ino */
+ ino = buf->ia_ino;
+
+hashout:
+ return ino;
+}
+
+
void
-nfs3_map_xlid_to_statdev (struct iatt *ia, uint16_t xlid)
+nfs3_map_deviceid_to_statdev (struct iatt *ia, uint64_t deviceid)
{
if (!ia)
return;
- ia->ia_dev = xlid;
+ ia->ia_dev = deviceid;
}
@@ -217,6 +238,15 @@ nfs3_errno_to_nfsstat3 (int errnum)
case ESTALE:
stat = NFS3ERR_STALE;
+ break;
+
+ case ENOTCONN:
+ stat = NFS3ERR_IO;
+ break;
+
+ case EDQUOT:
+ stat = NFS3ERR_DQUOT;
+ break;
default:
stat = NFS3ERR_SERVERFAULT;
@@ -226,6 +256,20 @@ nfs3_errno_to_nfsstat3 (int errnum)
return stat;
}
+/*
+ * Special case: If op_ret is -1, it's very unusual op_errno being
+ * 0 which means something came wrong from upper layer(s). If it
+ * happens by any means, then set NFS3 status to NFS3ERR_SERVERFAULT.
+ */
+inline nfsstat3
+nfs3_cbk_errno_status (int32_t op_ret, int32_t op_errno)
+{
+ if ((op_ret == -1) && (op_errno == 0)) {
+ return NFS3ERR_SERVERFAULT;
+ }
+
+ return nfs3_errno_to_nfsstat3 (op_errno);
+}
void
nfs3_fill_lookup3res_error (lookup3res *res, nfsstat3 stat,
@@ -245,6 +289,9 @@ nfs3_stat_to_fattr3 (struct iatt *buf)
{
fattr3 fa = {0, };
+ if (buf == NULL)
+ goto out;
+
if (IA_ISDIR (buf->ia_type))
fa.type = NF3DIR;
else if (IA_ISREG (buf->ia_type))
@@ -303,27 +350,18 @@ nfs3_stat_to_fattr3 (struct iatt *buf)
}
fa.fsid = buf->ia_dev;
- fa.fileid = buf->ia_ino;
- /* FIXME: Handle time resolutions for sub-second granularity */
- if (buf->ia_atime == 9669) {
- fa.mtime.seconds = 0;
- fa.mtime.nseconds = 0;
- fa.atime.seconds = 0;
- fa.atime.nseconds = 0;
- } else {
- fa.mtime.seconds = buf->ia_mtime;
- fa.mtime.nseconds = 0;
- fa.atime.seconds = buf->ia_atime;
- fa.atime.seconds = 0;
- fa.atime.nseconds = 0;
- }
+ fa.fileid = nfs3_iatt_gfid_to_ino (buf);
fa.atime.seconds = buf->ia_atime;
- fa.atime.nseconds = 0;
+ fa.atime.nseconds = buf->ia_atime_nsec;
fa.ctime.seconds = buf->ia_ctime;
- fa.ctime.nseconds = 0;
+ fa.ctime.nseconds = buf->ia_ctime_nsec;
+
+ fa.mtime.seconds = buf->ia_mtime;
+ fa.mtime.nseconds = buf->ia_mtime_nsec;
+out:
return fa;
}
@@ -366,11 +404,10 @@ nfs3_stat_to_pre_op_attr (struct iatt *pre)
poa.attributes_follow = TRUE;
poa.pre_op_attr_u.attributes.size = pre->ia_size;
- if (pre->ia_atime == 9669)
- poa.pre_op_attr_u.attributes.mtime.seconds = 0;
- else
- poa.pre_op_attr_u.attributes.mtime.seconds = pre->ia_mtime;
+ poa.pre_op_attr_u.attributes.mtime.seconds = pre->ia_mtime;
+ poa.pre_op_attr_u.attributes.mtime.nseconds = pre->ia_mtime_nsec;
poa.pre_op_attr_u.attributes.ctime.seconds = pre->ia_ctime;
+ poa.pre_op_attr_u.attributes.ctime.nseconds = pre->ia_ctime_nsec;
out:
return poa;
@@ -393,15 +430,8 @@ nfs3_fill_lookup3res_success (lookup3res *res, nfsstat3 stat,
obj.attributes_follow = FALSE;
dir.attributes_follow = FALSE;
- if (buf) {
- nfs3_map_xlid_to_statdev (buf, fh->xlatorid);
- obj = nfs3_stat_to_post_op_attr (buf);
- }
-
- if (postparent) {
- nfs3_map_xlid_to_statdev (postparent, fh->xlatorid);
- dir = nfs3_stat_to_post_op_attr (postparent);
- }
+ obj = nfs3_stat_to_post_op_attr (buf);
+ dir = nfs3_stat_to_post_op_attr (postparent);
res->lookup3res_u.resok.obj_attributes = obj;
res->lookup3res_u.resok.dir_attributes = dir;
@@ -410,10 +440,13 @@ nfs3_fill_lookup3res_success (lookup3res *res, nfsstat3 stat,
void
nfs3_fill_lookup3res (lookup3res *res, nfsstat3 stat, struct nfs3_fh *newfh,
- struct iatt *buf, struct iatt *postparent)
+ struct iatt *buf, struct iatt *postparent,
+ uint64_t deviceid)
{
memset (res, 0, sizeof (*res));
+ nfs3_map_deviceid_to_statdev (buf, deviceid);
+ nfs3_map_deviceid_to_statdev (postparent, deviceid);
if (stat != NFS3_OK)
nfs3_fill_lookup3res_error (res, stat, postparent);
else
@@ -430,7 +463,7 @@ nfs3_extract_getattr_fh (getattr3args *args)
void
nfs3_fill_getattr3res (getattr3res *res, nfsstat3 stat, struct iatt *buf,
- uint16_t xlid)
+ uint64_t deviceid)
{
memset (res, 0, sizeof (*res));
@@ -438,7 +471,7 @@ nfs3_fill_getattr3res (getattr3res *res, nfsstat3 stat, struct iatt *buf,
if (stat != NFS3_OK)
return;
- nfs3_map_xlid_to_statdev (buf, xlid);
+ nfs3_map_deviceid_to_statdev (buf, deviceid);
res->getattr3res_u.resok.obj_attributes = nfs3_stat_to_fattr3 (buf);
}
@@ -453,7 +486,7 @@ nfs3_extract_fsinfo_fh (fsinfo3args *args)
void
nfs3_fill_fsinfo3res (struct nfs3_state *nfs3, fsinfo3res *res,
- nfsstat3 status, struct iatt *fsroot, uint16_t xlid)
+ nfsstat3 status, struct iatt *fsroot, uint64_t deviceid)
{
fsinfo3resok resok = {{0}, };
nfstime3 tdelta = GF_NFS3_TIMEDELTA_SECS;
@@ -463,7 +496,7 @@ nfs3_fill_fsinfo3res (struct nfs3_state *nfs3, fsinfo3res *res,
if (status != NFS3_OK)
return;
- nfs3_map_xlid_to_statdev (fsroot, xlid);
+ nfs3_map_deviceid_to_statdev (fsroot, deviceid);
resok.obj_attributes = nfs3_stat_to_post_op_attr (fsroot);
resok.rtmax = nfs3->readsize;
resok.rtpref = nfs3->readsize;
@@ -472,7 +505,7 @@ nfs3_fill_fsinfo3res (struct nfs3_state *nfs3, fsinfo3res *res,
resok.wtpref = nfs3->writesize;
resok.wtmult = GF_NFS3_WTMULT;
resok.dtpref = nfs3->readdirsize;
- resok.maxfilesize = GF_NFS3_MAXFILE;
+ resok.maxfilesize = GF_NFS3_MAXFILESIZE;
resok.time_delta = tdelta;
resok.properties = GF_NFS3_FS_PROP;
@@ -527,197 +560,148 @@ nfs3_prep_access3args (access3args *args, struct nfs3_fh *fh)
args->object.data.data_val = (void *)fh;
}
+#define POSIX_READ 4
+#define POSIX_WRITE 2
+#define POSIX_EXEC 1
uint32_t
-nfs3_owner_accessbits (ia_prot_t prot, ia_type_t type, uint32_t request)
+nfs3_accessbits (int32_t accbits)
{
- uint32_t accresult = 0;
+ uint32_t accresult = 0;
- if (IA_PROT_RUSR (prot) && (request & ACCESS3_READ))
+ if (accbits & POSIX_READ)
accresult |= ACCESS3_READ;
- if (request & ACCESS3_LOOKUP)
- if ((IA_ISDIR (type)) && (IA_PROT_XUSR (prot)))
- accresult |= ACCESS3_LOOKUP;
-
- if ((IA_PROT_WUSR (prot) && (request & ACCESS3_MODIFY)))
- accresult |= ACCESS3_MODIFY;
-
- if ((IA_PROT_WUSR (prot) && (request & ACCESS3_EXTEND)))
- accresult |= ACCESS3_EXTEND;
-
- /* ACCESS3_DELETE is ignored for now since that requires
- * knowing the permissions on the parent directory.
- */
+ if (accbits & POSIX_WRITE)
+ accresult |= (ACCESS3_MODIFY | ACCESS3_EXTEND | ACCESS3_DELETE);
- if (request & ACCESS3_EXECUTE)
- if (IA_PROT_XUSR (prot) && (!IA_ISDIR (type)))
- accresult |= ACCESS3_EXECUTE;
+ /* lookup on directory allowed only in case of execute permission */
+ if (accbits & POSIX_EXEC)
+ accresult |= (ACCESS3_EXECUTE | ACCESS3_LOOKUP);
return accresult;
}
-
uint32_t
-nfs3_group_accessbits (ia_prot_t prot, ia_type_t type, uint32_t request)
+nfs3_request_to_accessbits (int32_t accbits)
{
- uint32_t accresult = 0;
-
- if (IA_PROT_RGRP (prot) && (request & ACCESS3_READ))
- accresult |= ACCESS3_READ;
+ uint32_t acc_request = 0;
- if (request & ACCESS3_LOOKUP)
- if ((IA_ISDIR (type)) && IA_PROT_RGRP (prot))
- accresult |= ACCESS3_LOOKUP;
+ if (accbits & ACCESS3_READ)
+ acc_request |= POSIX_READ;
- if (IA_PROT_WGRP (prot) && (request & ACCESS3_MODIFY))
- accresult |= ACCESS3_MODIFY;
-
- if (IA_PROT_WGRP (prot) && (request & ACCESS3_EXTEND))
- accresult |= ACCESS3_EXTEND;
-
- /* ACCESS3_DELETE is ignored for now since that requires
- * knowing the permissions on the parent directory.
- */
+ if (accbits & (ACCESS3_MODIFY | ACCESS3_EXTEND | ACCESS3_DELETE))
+ acc_request |= POSIX_WRITE;
- if (request & ACCESS3_EXECUTE)
- if (IA_PROT_XGRP (prot) && (!IA_ISDIR (type)))
- accresult |= ACCESS3_EXECUTE;
+ /* For lookup on directory check for execute permission */
+ if (accbits & (ACCESS3_EXECUTE | ACCESS3_LOOKUP))
+ acc_request |= POSIX_EXEC;
- return accresult;
+ return acc_request;
}
-
-
-uint32_t
-nfs3_other_accessbits (ia_prot_t prot, ia_type_t type, uint32_t request)
+void
+nfs3_fill_access3res (access3res *res, nfsstat3 status, int32_t accbits,
+ int32_t reqaccbits)
{
- uint32_t accresult = 0;
-
- if (IA_PROT_ROTH (prot) && (request & ACCESS3_READ))
- accresult |= ACCESS3_READ;
-
- if (request & ACCESS3_LOOKUP)
- if (IA_ISDIR (type) && IA_PROT_ROTH (prot))
- accresult |= ACCESS3_LOOKUP;
-
- if (IA_PROT_WOTH (prot) && (request & ACCESS3_MODIFY))
- accresult |= ACCESS3_MODIFY;
-
- if (IA_PROT_WOTH (prot) && (request & ACCESS3_EXTEND))
- accresult |= ACCESS3_EXTEND;
+ uint32_t accres = 0;
- /* ACCESS3_DELETE is ignored for now since that requires
- * knowing the permissions on the parent directory.
- */
+ memset (res, 0, sizeof (*res));
+ res->status = status;
+ if (status != NFS3_OK)
+ return;
- if (request & ACCESS3_EXECUTE)
- if (IA_PROT_XOTH (prot) && (!IA_ISDIR (type)))
- accresult |= ACCESS3_EXECUTE;
+ accres = nfs3_accessbits (accbits);
- return accresult;
+ /* do not answer what was not asked */
+ res->access3res_u.resok.access = accres & reqaccbits;
}
-
-uint32_t
-nfs3_superuser_accessbits (ia_prot_t prot, ia_type_t type, uint32_t request)
+void
+nfs3_prep_readdir3args (readdir3args *ra, struct nfs3_fh *fh)
{
- uint32_t accresult = 0;
-
- if (request & ACCESS3_READ)
- accresult |= ACCESS3_READ;
-
- if (request & ACCESS3_LOOKUP)
- if (IA_ISDIR (type))
- accresult |= ACCESS3_LOOKUP;
+ memset (ra, 0, sizeof (*ra));
+ ra->dir.data.data_val = (void *)fh;
+}
- if (request & ACCESS3_MODIFY)
- accresult |= ACCESS3_MODIFY;
- if (request & ACCESS3_EXTEND)
- accresult |= ACCESS3_EXTEND;
+int
+nfs3_is_dot_entry (char *entry)
+{
+ int ret = 0;
- /* ACCESS3_DELETE is ignored for now since that requires
- * knowing the permissions on the parent directory.
- */
+ if (!entry)
+ return 0;
- if (request & ACCESS3_EXECUTE)
- if ((IA_PROT_XOTH (prot) || IA_PROT_XUSR (prot) ||
- IA_PROT_XGRP (prot)) && (!IA_ISDIR (type)))
- accresult |= ACCESS3_EXECUTE;
+ if (strcmp (entry, ".") == 0)
+ ret = 1;
- return accresult;
+ return ret;
}
-uint32_t
-nfs3_stat_to_accessbits (struct iatt *buf, uint32_t request, uid_t uid,
- gid_t gid)
+int
+nfs3_is_parentdir_entry (char *entry)
{
- uint32_t accresult = 0;
- ia_prot_t prot = {0, };
- ia_type_t type = 0;
+ int ret = 0;
- prot = buf->ia_prot;
- type = buf->ia_type;
+ if (!entry)
+ return 0;
- if (uid == 0)
- accresult = nfs3_superuser_accessbits (prot, type, request);
- else if (buf->ia_uid == uid)
- accresult = nfs3_owner_accessbits (prot, type, request);
- else if (buf->ia_gid == gid)
- accresult = nfs3_group_accessbits (prot, type, request);
- else
- accresult = nfs3_other_accessbits (prot, type, request);
+ if (strcmp (entry, "..") == 0)
+ ret = 1;
- return accresult;
+ return ret;
}
void
-nfs3_fill_access3res (access3res *res, nfsstat3 status, struct iatt *buf,
- uint32_t accbits, uid_t uid, gid_t gid, uint16_t xlid)
+nfs3_funge_root_dotdot_dirent (gf_dirent_t *ent, struct nfs3_fh *dfh)
{
- post_op_attr objattr;
- uint32_t accres = 0;
-
- memset (res, 0, sizeof (*res));
- res->status = status;
- if (status != NFS3_OK)
+ if ((!ent) || (!dfh))
return;
- nfs3_map_xlid_to_statdev (buf, xlid);
- objattr = nfs3_stat_to_post_op_attr (buf);
- accres = nfs3_stat_to_accessbits (buf, accbits, uid, gid);
+ if (nfs3_fh_is_root_fh (dfh) &&
+ nfs3_is_parentdir_entry (ent->d_name)) {
+ ent->d_ino = 1;
+ ent->d_stat.ia_ino = 1;
+ }
- res->access3res_u.resok.obj_attributes = objattr;
- res->access3res_u.resok.access = accres;
-}
+ if (nfs3_fh_is_root_fh (dfh) &&
+ nfs3_is_dot_entry (ent->d_name)) {
+ ent->d_ino = 1;
+ ent->d_stat.ia_ino = 1;
+ }
-void
-nfs3_prep_readdir3args (readdir3args *ra, struct nfs3_fh *fh)
-{
- memset (ra, 0, sizeof (*ra));
- ra->dir.data.data_val = (void *)fh;
}
entry3 *
-nfs3_fill_entry3 (gf_dirent_t *entry)
+nfs3_fill_entry3 (gf_dirent_t *entry, struct nfs3_fh *dfh)
{
entry3 *ent = NULL;
- if (!entry)
+ if ((!entry) || (!dfh))
return NULL;
- ent = CALLOC (1, sizeof (*ent));
+ ent = GF_CALLOC (1, sizeof (*ent), gf_nfs_mt_entry3);
if (!ent)
return NULL;
gf_log (GF_NFS3, GF_LOG_TRACE, "Entry: %s", entry->d_name);
+
+ /* If the entry is . or .., we need to replace the physical ino and gen
+ * with 1 and 0 respectively if the directory is root. This funging is
+ * needed because there is no parent directory of the root. In that
+ * sense the behavior we provide is similar to the output of the
+ * command: "stat /.."
+ */
+ entry->d_ino = nfs3_iatt_gfid_to_ino (&entry->d_stat);
+ nfs3_funge_root_dotdot_dirent (entry, dfh);
ent->fileid = entry->d_ino;
ent->cookie = entry->d_off;
- ent->name = CALLOC ((strlen (entry->d_name) + 1), sizeof (char));
+ ent->name = GF_CALLOC ((strlen (entry->d_name) + 1), sizeof (char),
+ gf_nfs_mt_char);
if (!ent->name) {
- FREE (ent);
+ GF_FREE (ent);
ent = NULL;
goto err;
}
@@ -754,7 +738,7 @@ nfs3_fh_to_post_op_fh3 (struct nfs3_fh *fh)
pfh.handle_follows = 1;
- fhp = CALLOC (1, sizeof (*fh));
+ fhp = GF_CALLOC (1, sizeof (*fh), gf_nfs_mt_char);
if (!fhp)
return pfh;
@@ -765,7 +749,7 @@ nfs3_fh_to_post_op_fh3 (struct nfs3_fh *fh)
entryp3 *
-nfs3_fill_entryp3 (gf_dirent_t *entry, struct nfs3_fh *dirfh)
+nfs3_fill_entryp3 (gf_dirent_t *entry, struct nfs3_fh *dirfh, uint64_t devid)
{
entryp3 *ent = NULL;
struct nfs3_fh newfh = {{0}, };
@@ -773,24 +757,33 @@ nfs3_fill_entryp3 (gf_dirent_t *entry, struct nfs3_fh *dirfh)
if ((!entry) || (!dirfh))
return NULL;
+ /* If the entry is . or .., we need to replace the physical ino and gen
+ * with 1 and 0 respectively if the directory is root. This funging is
+ * needed because there is no parent directory of the root. In that
+ * sense the behavior we provide is similar to the output of the
+ * command: "stat /.."
+ */
+ entry->d_ino = nfs3_iatt_gfid_to_ino (&entry->d_stat);
+ nfs3_funge_root_dotdot_dirent (entry, dirfh);
gf_log (GF_NFS3, GF_LOG_TRACE, "Entry: %s, ino: %"PRIu64,
entry->d_name, entry->d_ino);
- ent = CALLOC (1, sizeof (*ent));
+ ent = GF_CALLOC (1, sizeof (*ent), gf_nfs_mt_entryp3);
if (!ent)
return NULL;
ent->fileid = entry->d_ino;
ent->cookie = entry->d_off;
- ent->name = CALLOC ((strlen (entry->d_name) + 1), sizeof (char));
+ ent->name = GF_CALLOC ((strlen (entry->d_name) + 1), sizeof (char),
+ gf_nfs_mt_char);
if (!ent->name) {
- FREE (ent);
+ GF_FREE (ent);
ent = NULL;
goto err;
}
strcpy (ent->name, entry->d_name);
nfs3_fh_build_child_fh (dirfh, &entry->d_stat, &newfh);
- nfs3_map_xlid_to_statdev (&entry->d_stat, dirfh->xlatorid);
+ nfs3_map_deviceid_to_statdev (&entry->d_stat, devid);
ent->name_attributes = nfs3_stat_to_post_op_attr (&entry->d_stat);
ent->name_handle = nfs3_fh_to_post_op_fh3 (&newfh);
err:
@@ -799,9 +792,10 @@ err:
void
-nfs3_fill_readdir3res (readdir3res *res, nfsstat3 stat, uint64_t cverf,
- struct iatt *dirstat, gf_dirent_t *entries, count3 count,
- int is_eof, uint16_t xlid)
+nfs3_fill_readdir3res (readdir3res *res, nfsstat3 stat, struct nfs3_fh *dirfh,
+ uint64_t cverf, struct iatt *dirstat,
+ gf_dirent_t *entries, count3 count, int is_eof,
+ uint64_t deviceid)
{
post_op_attr dirattr;
entry3 *ent = NULL;
@@ -815,7 +809,7 @@ nfs3_fill_readdir3res (readdir3res *res, nfsstat3 stat, uint64_t cverf,
if (stat != NFS3_OK)
return;
- nfs3_map_xlid_to_statdev (dirstat, xlid);
+ nfs3_map_deviceid_to_statdev (dirstat, deviceid);
dirattr = nfs3_stat_to_post_op_attr (dirstat);
res->readdir3res_u.resok.dir_attributes = dirattr;
res->readdir3res_u.resok.reply.eof = (bool_t)is_eof;
@@ -831,7 +825,7 @@ nfs3_fill_readdir3res (readdir3res *res, nfsstat3 stat, uint64_t cverf,
(strcmp (entries->d_name, "..") == 0))
goto nextentry;
*/
- ent = nfs3_fill_entry3 (entries);
+ ent = nfs3_fill_entry3 (entries, dirfh);
if (!ent)
break;
@@ -856,10 +850,11 @@ nfs3_fill_readdir3res (readdir3res *res, nfsstat3 stat, uint64_t cverf,
void
-nfs3_fill_readdirp3res (readdirp3res *res, nfsstat3 stat, struct nfs3_fh *dirfh,
- uint64_t cverf, struct iatt *dirstat,
- gf_dirent_t *entries, count3 dircount, count3 maxcount,
- int is_eof)
+nfs3_fill_readdirp3res (readdirp3res *res, nfsstat3 stat,
+ struct nfs3_fh *dirfh, uint64_t cverf,
+ struct iatt *dirstat, gf_dirent_t *entries,
+ count3 dircount, count3 maxcount, int is_eof,
+ uint64_t deviceid)
{
post_op_attr dirattr;
entryp3 *ent = NULL;
@@ -874,7 +869,7 @@ nfs3_fill_readdirp3res (readdirp3res *res, nfsstat3 stat, struct nfs3_fh *dirfh,
if (stat != NFS3_OK)
return;
- nfs3_map_xlid_to_statdev (dirstat, dirfh->xlatorid);
+ nfs3_map_deviceid_to_statdev (dirstat, deviceid);
dirattr = nfs3_stat_to_post_op_attr (dirstat);
res->readdirp3res_u.resok.dir_attributes = dirattr;
res->readdirp3res_u.resok.reply.eof = (bool_t)is_eof;
@@ -892,7 +887,7 @@ nfs3_fill_readdirp3res (readdirp3res *res, nfsstat3 stat, struct nfs3_fh *dirfh,
(strcmp (entries->d_name, "..") == 0))
goto nextentry;
*/
- ent = nfs3_fill_entryp3 (entries, dirfh);
+ ent = nfs3_fill_entryp3 (entries, dirfh, deviceid);
if (!ent)
break;
@@ -937,9 +932,9 @@ nfs3_free_readdirp3res (readdirp3res *res)
while (ent) {
next = ent->nextentry;
- FREE (ent->name);
- FREE (ent->name_handle.post_op_fh3_u.handle.data.data_val);
- FREE (ent);
+ GF_FREE (ent->name);
+ GF_FREE (ent->name_handle.post_op_fh3_u.handle.data.data_val);
+ GF_FREE (ent);
ent = next;
}
@@ -960,8 +955,8 @@ nfs3_free_readdir3res (readdir3res *res)
while (ent) {
next = ent->nextentry;
- FREE (ent->name);
- FREE (ent);
+ GF_FREE (ent->name);
+ GF_FREE (ent);
ent = next;
}
@@ -978,7 +973,7 @@ nfs3_prep_fsstat3args (fsstat3args *args, struct nfs3_fh *fh)
void
nfs3_fill_fsstat3res (fsstat3res *res, nfsstat3 stat, struct statvfs *fsbuf,
- struct iatt *postbuf, uint16_t xlid)
+ struct iatt *postbuf, uint64_t deviceid)
{
post_op_attr poa;
fsstat3resok resok;
@@ -988,11 +983,11 @@ nfs3_fill_fsstat3res (fsstat3res *res, nfsstat3 stat, struct statvfs *fsbuf,
if (stat != NFS3_OK)
return;
- nfs3_map_xlid_to_statdev (postbuf, xlid);
+ nfs3_map_deviceid_to_statdev (postbuf, deviceid);
poa = nfs3_stat_to_post_op_attr (postbuf);
resok.tbytes = (size3)(fsbuf->f_frsize * fsbuf->f_blocks);
- resok.fbytes = (size3)(fsbuf->f_bsize * fsbuf->f_bfree);
- resok.abytes = (size3)(fsbuf->f_bsize * fsbuf->f_bavail);
+ resok.fbytes = (size3)(fsbuf->f_frsize * fsbuf->f_bfree);
+ resok.abytes = (size3)(fsbuf->f_frsize * fsbuf->f_bavail);
resok.tfiles = (size3)(fsbuf->f_files);
resok.ffiles = (size3)(fsbuf->f_ffree);
resok.afiles = (size3)(fsbuf->f_favail);
@@ -1137,7 +1132,7 @@ nfs3_stat_to_wcc_data (struct iatt *pre, struct iatt *post)
void
nfs3_fill_create3res (create3res *res, nfsstat3 stat, struct nfs3_fh *newfh,
struct iatt *newbuf, struct iatt *preparent,
- struct iatt *postparent)
+ struct iatt *postparent, uint64_t deviceid)
{
post_op_attr poa = {0, };
wcc_data dirwcc = {{0}, };
@@ -1148,14 +1143,12 @@ nfs3_fill_create3res (create3res *res, nfsstat3 stat, struct nfs3_fh *newfh,
return;
nfs3_fill_post_op_fh3 (newfh, &res->create3res_u.resok.obj);
- nfs3_map_xlid_to_statdev (newbuf, newfh->xlatorid);
+ nfs3_map_deviceid_to_statdev (newbuf, deviceid);
poa = nfs3_stat_to_post_op_attr (newbuf);
res->create3res_u.resok.obj_attributes = poa;
- if (preparent) {
- nfs3_map_xlid_to_statdev (preparent, newfh->xlatorid);
- nfs3_map_xlid_to_statdev (postparent, newfh->xlatorid);
- dirwcc = nfs3_stat_to_wcc_data (preparent, postparent);
- }
+ nfs3_map_deviceid_to_statdev (preparent, deviceid);
+ nfs3_map_deviceid_to_statdev (postparent, deviceid);
+ dirwcc = nfs3_stat_to_wcc_data (preparent, postparent);
res->create3res_u.resok.dir_wcc = dirwcc;
}
@@ -1179,7 +1172,7 @@ nfs3_prep_setattr3args (setattr3args *args, struct nfs3_fh *fh)
void
nfs3_fill_setattr3res (setattr3res *res, nfsstat3 stat, struct iatt *preop,
- struct iatt *postop, uint16_t xlid)
+ struct iatt *postop, uint64_t deviceid)
{
wcc_data wcc;
memset (res, 0, sizeof (*res));
@@ -1187,8 +1180,8 @@ nfs3_fill_setattr3res (setattr3res *res, nfsstat3 stat, struct iatt *preop,
if (stat != NFS3_OK)
return;
- nfs3_map_xlid_to_statdev (preop, xlid);
- nfs3_map_xlid_to_statdev (postop, xlid);
+ nfs3_map_deviceid_to_statdev (preop, deviceid);
+ nfs3_map_deviceid_to_statdev (postop, deviceid);
wcc = nfs3_stat_to_wcc_data (preop, postop);
res->setattr3res_u.resok.obj_wcc = wcc;
}
@@ -1207,7 +1200,7 @@ nfs3_prep_mkdir3args (mkdir3args *args, struct nfs3_fh *dirfh, char *name)
void
nfs3_fill_mkdir3res (mkdir3res *res, nfsstat3 stat, struct nfs3_fh *fh,
struct iatt *buf, struct iatt *preparent,
- struct iatt *postparent)
+ struct iatt *postparent, uint64_t deviceid)
{
wcc_data dirwcc;
post_op_attr poa;
@@ -1218,10 +1211,10 @@ nfs3_fill_mkdir3res (mkdir3res *res, nfsstat3 stat, struct nfs3_fh *fh,
return;
nfs3_fill_post_op_fh3 (fh, &res->mkdir3res_u.resok.obj);
- nfs3_map_xlid_to_statdev (buf, fh->xlatorid);
+ nfs3_map_deviceid_to_statdev (buf, deviceid);
poa = nfs3_stat_to_post_op_attr (buf);
- nfs3_map_xlid_to_statdev (preparent, fh->xlatorid);
- nfs3_map_xlid_to_statdev (postparent, fh->xlatorid);
+ nfs3_map_deviceid_to_statdev (preparent, deviceid);
+ nfs3_map_deviceid_to_statdev (postparent, deviceid);
dirwcc = nfs3_stat_to_wcc_data (preparent, postparent);
res->mkdir3res_u.resok.obj_attributes = poa;
res->mkdir3res_u.resok.dir_wcc = dirwcc;
@@ -1243,7 +1236,7 @@ nfs3_prep_symlink3args (symlink3args *args, struct nfs3_fh *dirfh, char *name,
void
nfs3_fill_symlink3res (symlink3res *res, nfsstat3 stat, struct nfs3_fh *fh,
struct iatt *buf, struct iatt *preparent,
- struct iatt *postparent)
+ struct iatt *postparent, uint64_t deviceid)
{
wcc_data dirwcc;
post_op_attr poa;
@@ -1254,10 +1247,10 @@ nfs3_fill_symlink3res (symlink3res *res, nfsstat3 stat, struct nfs3_fh *fh,
return;
nfs3_fill_post_op_fh3 (fh, &res->symlink3res_u.resok.obj);
- nfs3_map_xlid_to_statdev (buf, fh->xlatorid);
+ nfs3_map_deviceid_to_statdev (buf, deviceid);
poa = nfs3_stat_to_post_op_attr (buf);
- nfs3_map_xlid_to_statdev (postparent, fh->xlatorid);
- nfs3_map_xlid_to_statdev (preparent, fh->xlatorid);
+ nfs3_map_deviceid_to_statdev (postparent, deviceid);
+ nfs3_map_deviceid_to_statdev (preparent, deviceid);
dirwcc = nfs3_stat_to_wcc_data (preparent, postparent);
res->symlink3res_u.resok.obj_attributes = poa;
res->symlink3res_u.resok.dir_wcc = dirwcc;
@@ -1276,7 +1269,7 @@ nfs3_prep_readlink3args (readlink3args *args, struct nfs3_fh *fh)
void
nfs3_fill_readlink3res (readlink3res *res, nfsstat3 stat, char *path,
- struct iatt *buf, uint16_t xlid)
+ struct iatt *buf, uint64_t deviceid)
{
post_op_attr poa;
@@ -1286,7 +1279,7 @@ nfs3_fill_readlink3res (readlink3res *res, nfsstat3 stat, char *path,
if (stat != NFS3_OK)
return;
- nfs3_map_xlid_to_statdev (buf, xlid);
+ nfs3_map_deviceid_to_statdev (buf, deviceid);
poa = nfs3_stat_to_post_op_attr (buf);
res->readlink3res_u.resok.data = (void *)path;
res->readlink3res_u.resok.symlink_attributes = poa;
@@ -1305,7 +1298,7 @@ nfs3_prep_mknod3args (mknod3args *args, struct nfs3_fh *fh, char *name)
void
nfs3_fill_mknod3res (mknod3res *res, nfsstat3 stat, struct nfs3_fh *fh,
struct iatt *buf, struct iatt *preparent,
- struct iatt *postparent)
+ struct iatt *postparent, uint64_t deviceid)
{
post_op_attr poa;
wcc_data wccdir;
@@ -1316,10 +1309,10 @@ nfs3_fill_mknod3res (mknod3res *res, nfsstat3 stat, struct nfs3_fh *fh,
return;
nfs3_fill_post_op_fh3 (fh, &res->mknod3res_u.resok.obj);
- nfs3_map_xlid_to_statdev (buf, fh->xlatorid);
+ nfs3_map_deviceid_to_statdev (buf, deviceid);
poa = nfs3_stat_to_post_op_attr (buf);
- nfs3_map_xlid_to_statdev (preparent, fh->xlatorid);
- nfs3_map_xlid_to_statdev (postparent, fh->xlatorid);
+ nfs3_map_deviceid_to_statdev (preparent, deviceid);
+ nfs3_map_deviceid_to_statdev (postparent, deviceid);
wccdir = nfs3_stat_to_wcc_data (preparent, postparent);
res->mknod3res_u.resok.obj_attributes = poa;
res->mknod3res_u.resok.dir_wcc = wccdir;
@@ -1329,7 +1322,7 @@ nfs3_fill_mknod3res (mknod3res *res, nfsstat3 stat, struct nfs3_fh *fh,
void
nfs3_fill_remove3res (remove3res *res, nfsstat3 stat, struct iatt *preparent,
- struct iatt *postparent, uint16_t xlid)
+ struct iatt *postparent, uint64_t deviceid)
{
wcc_data dirwcc;
@@ -1338,8 +1331,8 @@ nfs3_fill_remove3res (remove3res *res, nfsstat3 stat, struct iatt *preparent,
if (stat != NFS3_OK)
return;
- nfs3_map_xlid_to_statdev (preparent, xlid);
- nfs3_map_xlid_to_statdev (postparent, xlid);
+ nfs3_map_deviceid_to_statdev (preparent, deviceid);
+ nfs3_map_deviceid_to_statdev (postparent, deviceid);
dirwcc = nfs3_stat_to_wcc_data (preparent, postparent);
res->remove3res_u.resok.dir_wcc = dirwcc;
}
@@ -1365,7 +1358,7 @@ nfs3_prep_rmdir3args (rmdir3args *args, struct nfs3_fh *fh, char *name)
void
nfs3_fill_rmdir3res (rmdir3res *res, nfsstat3 stat, struct iatt *preparent,
- struct iatt *postparent, uint16_t xlid)
+ struct iatt *postparent, uint64_t deviceid)
{
wcc_data dirwcc;
memset (res, 0, sizeof (*res));
@@ -1374,8 +1367,8 @@ nfs3_fill_rmdir3res (rmdir3res *res, nfsstat3 stat, struct iatt *preparent,
if (stat != NFS3_OK)
return;
- nfs3_map_xlid_to_statdev (postparent, xlid);
- nfs3_map_xlid_to_statdev (preparent, xlid);
+ nfs3_map_deviceid_to_statdev (postparent, deviceid);
+ nfs3_map_deviceid_to_statdev (preparent, deviceid);
dirwcc = nfs3_stat_to_wcc_data (preparent, postparent);
res->rmdir3res_u.resok.dir_wcc = dirwcc;
}
@@ -1395,7 +1388,7 @@ nfs3_prep_link3args (link3args *args, struct nfs3_fh *target,
void
nfs3_fill_link3res (link3res *res, nfsstat3 stat, struct iatt *buf,
struct iatt *preparent, struct iatt *postparent,
- uint16_t xlid)
+ uint64_t deviceid)
{
post_op_attr poa;
wcc_data dirwcc;
@@ -1405,9 +1398,9 @@ nfs3_fill_link3res (link3res *res, nfsstat3 stat, struct iatt *buf,
if (stat != NFS3_OK)
return;
- nfs3_map_xlid_to_statdev (preparent, xlid);
- nfs3_map_xlid_to_statdev (postparent, xlid);
- nfs3_map_xlid_to_statdev (buf, xlid);
+ nfs3_map_deviceid_to_statdev (preparent, deviceid);
+ nfs3_map_deviceid_to_statdev (postparent, deviceid);
+ nfs3_map_deviceid_to_statdev (buf,deviceid);
poa = nfs3_stat_to_post_op_attr (buf);
dirwcc = nfs3_stat_to_wcc_data (preparent, postparent);
res->link3res_u.resok.file_attributes = poa;
@@ -1434,7 +1427,7 @@ void
nfs3_fill_rename3res (rename3res *res, nfsstat3 stat, struct iatt *buf,
struct iatt *preoldparent, struct iatt *postoldparent,
struct iatt *prenewparent, struct iatt *postnewparent,
- uint16_t xlid)
+ uint64_t deviceid)
{
wcc_data dirwcc;
@@ -1444,11 +1437,11 @@ nfs3_fill_rename3res (rename3res *res, nfsstat3 stat, struct iatt *buf,
if (stat != NFS3_OK)
return;
- nfs3_map_xlid_to_statdev (preoldparent, xlid);
- nfs3_map_xlid_to_statdev (postoldparent, xlid);
- nfs3_map_xlid_to_statdev (prenewparent, xlid);
- nfs3_map_xlid_to_statdev (postnewparent, xlid);
- nfs3_map_xlid_to_statdev (buf, xlid);
+ nfs3_map_deviceid_to_statdev (preoldparent, deviceid);
+ nfs3_map_deviceid_to_statdev (postoldparent, deviceid);
+ nfs3_map_deviceid_to_statdev (prenewparent, deviceid);
+ nfs3_map_deviceid_to_statdev (postnewparent, deviceid);
+ nfs3_map_deviceid_to_statdev (buf, deviceid);
dirwcc = nfs3_stat_to_wcc_data (preoldparent, postoldparent);
res->rename3res_u.resok.fromdir_wcc = dirwcc;
dirwcc = nfs3_stat_to_wcc_data (prenewparent, postnewparent);
@@ -1467,7 +1460,7 @@ nfs3_prep_write3args (write3args *args, struct nfs3_fh *fh)
void
nfs3_fill_write3res (write3res *res, nfsstat3 stat, count3 count,
stable_how stable, uint64_t wverf, struct iatt *prestat,
- struct iatt *poststat, uint16_t xlid)
+ struct iatt *poststat, uint64_t deviceid)
{
write3resok resok;
memset (res, 0, sizeof (*res));
@@ -1475,8 +1468,8 @@ nfs3_fill_write3res (write3res *res, nfsstat3 stat, count3 count,
if (stat != NFS3_OK)
return;
- nfs3_map_xlid_to_statdev (prestat, xlid);
- nfs3_map_xlid_to_statdev (poststat, xlid);
+ nfs3_map_deviceid_to_statdev (prestat, deviceid);
+ nfs3_map_deviceid_to_statdev (poststat, deviceid);
resok.file_wcc = nfs3_stat_to_wcc_data (prestat, poststat);
resok.count = count;
resok.committed = stable;
@@ -1496,15 +1489,16 @@ nfs3_prep_commit3args (commit3args *args, struct nfs3_fh *fh)
void
nfs3_fill_commit3res (commit3res *res, nfsstat3 stat, uint64_t wverf,
- struct iatt *prestat, struct iatt *poststat,uint16_t xlid)
+ struct iatt *prestat, struct iatt *poststat,
+ uint64_t deviceid)
{
memset (res, 0, sizeof (*res));
res->status = stat;
if (stat != NFS3_OK)
return;
- nfs3_map_xlid_to_statdev (poststat, xlid);
- nfs3_map_xlid_to_statdev (prestat, xlid);
+ nfs3_map_deviceid_to_statdev (poststat, deviceid);
+ nfs3_map_deviceid_to_statdev (prestat, deviceid);
res->commit3res_u.resok.file_wcc = nfs3_stat_to_wcc_data (prestat,
poststat);
memcpy (res->commit3res_u.resok.verf, &wverf, sizeof (wverf));
@@ -1512,7 +1506,7 @@ nfs3_fill_commit3res (commit3res *res, nfsstat3 stat, uint64_t wverf,
void
nfs3_fill_read3res (read3res *res, nfsstat3 stat, count3 count,
- struct iatt *poststat, int is_eof, uint16_t xlid)
+ struct iatt *poststat, int is_eof, uint64_t deviceid)
{
post_op_attr poa;
@@ -1521,13 +1515,12 @@ nfs3_fill_read3res (read3res *res, nfsstat3 stat, count3 count,
if (stat != NFS3_OK)
return;
- nfs3_map_xlid_to_statdev (poststat, xlid);
+ nfs3_map_deviceid_to_statdev (poststat, deviceid);
poa = nfs3_stat_to_post_op_attr (poststat);
res->read3res_u.resok.file_attributes = poa;
res->read3res_u.resok.count = count;
res->read3res_u.resok.eof = is_eof;
res->read3res_u.resok.data.data_len = count;
-
}
@@ -1541,7 +1534,7 @@ nfs3_prep_read3args (read3args *args, struct nfs3_fh *fh)
void
nfs3_fill_pathconf3res (pathconf3res *res, nfsstat3 stat, struct iatt *buf,
- uint16_t xlid)
+ uint64_t deviceid)
{
pathconf3resok resok;
@@ -1550,7 +1543,7 @@ nfs3_fill_pathconf3res (pathconf3res *res, nfsstat3 stat, struct iatt *buf,
if (stat != NFS3_OK)
return;
- nfs3_map_xlid_to_statdev (buf, xlid);
+ nfs3_map_deviceid_to_statdev (buf, deviceid);
resok.obj_attributes = nfs3_stat_to_post_op_attr (buf);
resok.linkmax = 256;
resok.name_max = NFS_NAME_MAX;
@@ -1621,594 +1614,1826 @@ err:
}
-/* When remove a file, we need to unref the cached fd for an inode but this
- * needs to happen only when the file was in fact opened. However, it is
- * possible that fd_lookup on a file returns an fd because the file was in
- * process of being created(which also returns an fd) but since this fd was not
- * opened through this path, in the NFS3 remove path, we'll end up removing the
- * reference that belongs to someone else. That means, nfs3 remove path should
- * not unref unless it is sure that the file was cached open also. If it was,
- * only then perform the fd_unref, else not.
- *
- * We determine that using a flag in the inode context.
- */
-int
-nfs3_set_inode_opened (xlator_t *nfsxl, inode_t *inode)
+void
+nfs3_stat_to_errstr (uint32_t xid, char *op, nfsstat3 stat, int pstat,
+ char *errstr, size_t len)
{
- if ((!nfsxl) || (!inode))
- return -1;
+ if ((!op) || (!errstr))
+ return;
- inode_ctx_put (inode, nfsxl, GF_NFS3_FD_CACHED);
+ snprintf (errstr, len, "XID: %x, %s: NFS: %d(%s), POSIX: %d(%s)",
+ xid, op,stat, nfsstat3_strerror (stat), pstat,
+ strerror (pstat));
+}
- return 0;
+void
+nfs3_log_common_call (uint32_t xid, char *op, struct nfs3_fh *fh)
+{
+ char fhstr[1024];
+
+ if (THIS->ctx->log.loglevel < GF_LOG_DEBUG)
+ return;
+
+ nfs3_fh_to_str (fh, fhstr, sizeof (fhstr));
+ gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, %s: args: %s", xid, op,
+ fhstr);
}
-/* Returns 1 if inode was cached open, otherwise 0 */
-int
-nfs3_cached_inode_opened (xlator_t *nfsxl, inode_t *inode)
+void
+nfs3_log_fh_entry_call (uint32_t xid, char *op, struct nfs3_fh *fh,
+ char *name)
{
- int ret = -1;
- uint64_t cflag = 0;
+ char fhstr[1024];
- if ((!nfsxl) || (!inode))
- return -1;
+ if (THIS->ctx->log.loglevel < GF_LOG_DEBUG)
+ return;
+ nfs3_fh_to_str (fh, fhstr, sizeof (fhstr));
+ gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, %s: args: %s, name: %s", xid,
+ op, fhstr, name);
+}
- ret = inode_ctx_get (inode, nfsxl, &cflag);
- if (ret == -1)
- ret = 0;
- else if (cflag == GF_NFS3_FD_CACHED)
- ret = 1;
- return ret;
+void
+nfs3_log_rename_call (uint32_t xid, struct nfs3_fh *src, char *sname,
+ struct nfs3_fh *dst, char *dname)
+{
+ char sfhstr[1024];
+ char dfhstr[1024];
+
+ if (THIS->ctx->log.loglevel < GF_LOG_DEBUG)
+ return;
+ nfs3_fh_to_str (src, sfhstr, sizeof (sfhstr));
+ nfs3_fh_to_str (dst, dfhstr, sizeof (dfhstr));
+ gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, RENAME: args: Src: %s, "
+ "name: %s, Dst: %s, name: %s", xid, sfhstr, sname, dfhstr,
+ dname);
}
-int32_t
-nfs3_dir_open_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno, fd_t *fd)
+
+void
+nfs3_log_create_call (uint32_t xid, struct nfs3_fh *fh, char *name,
+ createmode3 mode)
{
- nfs3_call_state_t *cs = NULL;
+ char fhstr[1024];
+ char *modestr = NULL;
+ char exclmode[] = "EXCLUSIVE";
+ char unchkd[] = "UNCHECKED";
+ char guarded[] = "GUARDED";
- cs = frame->local;
- if (op_ret == -1) {
- cs->resolve_ret = -1;
- cs->resolve_errno = op_errno;
- nfs3_call_resume (cs);
- goto err;
- }
+ if (THIS->ctx->log.loglevel < GF_LOG_DEBUG)
+ return;
+ nfs3_fh_to_str (fh, fhstr, sizeof (fhstr));
+ if (mode == EXCLUSIVE)
+ modestr = exclmode;
+ else if (mode == GUARDED)
+ modestr = guarded;
+ else
+ modestr = unchkd;
- cs->fd = fd_ref (fd);
- nfs3_set_inode_opened (cs->nfsx, cs->resolvedloc.inode);
- gf_log (GF_NFS3, GF_LOG_TRACE, "FD_REF: %d", fd->refcount);
- nfs3_call_resume (cs);
-err:
- return 0;
+ gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, CREATE: args: %s, name: %s,"
+ " mode: %s", xid, fhstr, name, modestr);
}
-int
-__nfs3_dir_open_and_resume (nfs3_call_state_t *cs)
+void
+nfs3_log_mknod_call (uint32_t xid, struct nfs3_fh *fh, char *name, int type)
{
- nfs_user_t nfu = {0, };
- int ret = -EFAULT;
+ char fhstr[1024];
+ char *modestr = NULL;
+ char chr[] = "CHAR";
+ char blk[] = "BLK";
+ char sock[] = "SOCK";
+ char fifo[] = "FIFO";
- if (!cs)
- return ret;
+ if (THIS->ctx->log.loglevel < GF_LOG_DEBUG)
+ return;
+ nfs3_fh_to_str (fh, fhstr, sizeof (fhstr));
+ if (type == NF3CHR)
+ modestr = chr;
+ else if (type == NF3BLK)
+ modestr = blk;
+ else if (type == NF3SOCK)
+ modestr = sock;
+ else
+ modestr = fifo;
- nfs_user_root_create (&nfu);
- ret = nfs_opendir (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
- nfs3_dir_open_cbk, cs);
- return ret;
+ gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, MKNOD: args: %s, name: %s,"
+ " type: %s", xid, fhstr, name, modestr);
}
-int
-nfs3_dir_open_and_resume (nfs3_call_state_t *cs, nfs3_resume_fn_t resume)
+
+void
+nfs3_log_symlink_call (uint32_t xid, struct nfs3_fh *fh, char *name, char *tgt)
{
- fd_t *fd = NULL;
- int ret = -EFAULT;
+ char fhstr[1024];
- if ((!cs))
- return ret;
+ if (THIS->ctx->log.loglevel < GF_LOG_DEBUG)
+ return;
+ nfs3_fh_to_str (fh, fhstr, sizeof (fhstr));
+ gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, SYMLINK: args: %s, name: %s,"
+ " target: %s", xid, fhstr, name, tgt);
+}
- cs->resume_fn = resume;
- gf_log (GF_NFS3, GF_LOG_TRACE, "Opening: %s", cs->resolvedloc.path);
- fd = fd_lookup (cs->resolvedloc.inode, 0);
- if (fd) {
- gf_log (GF_NFS3, GF_LOG_TRACE, "fd found in state: ref: %d", fd->refcount);
- cs->fd = fd_ref (fd); /* Gets unrefd when the call state is wiped. */
- cs->resolve_ret = 0;
- nfs3_call_resume (cs);
- ret = 0;
- goto err;
- }
- ret = __nfs3_dir_open_and_resume (cs);
+void
+nfs3_log_link_call (uint32_t xid, struct nfs3_fh *fh, char *name,
+ struct nfs3_fh *tgt)
+{
+ char dfhstr[1024];
+ char tfhstr[1024];
-err:
- return ret;
+ if (THIS->ctx->log.loglevel < GF_LOG_DEBUG)
+ return;
+ nfs3_fh_to_str (fh, dfhstr, sizeof (dfhstr));
+ nfs3_fh_to_str (tgt, tfhstr, sizeof (tfhstr));
+ gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, LINK: args: %s, name: %s,"
+ " target: %s", xid, dfhstr, name, tfhstr);
}
-int
-nfs3_flush_open_wait_call_states (nfs3_call_state_t *cs, fd_t *openedfd)
+void
+nfs3_log_rw_call (uint32_t xid, char *op, struct nfs3_fh *fh, offset3 offt,
+ count3 count, int stablewrite)
{
- struct list_head *inode_q = NULL;
- uint64_t ctxaddr = 0;
- int ret = 0;
- nfs3_call_state_t *cstmp = NULL;
+ char fhstr[1024];
- if (!cs)
- return -1;
+ if (THIS->ctx->log.loglevel < GF_LOG_DEBUG)
+ return;
+ nfs3_fh_to_str (fh, fhstr, sizeof (fhstr));
+ if (stablewrite == -1)
+ gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, %s: args: %s, offset:"
+ " %"PRIu64", count: %"PRIu32, xid, op, fhstr, offt,
+ count);
+ else
+ gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, %s: args: %s, offset:"
+ " %"PRIu64", count: %"PRIu32", %s", xid, op, fhstr,
+ offt, count,
+ (stablewrite == UNSTABLE)?"UNSTABLE":"STABLE");
- gf_log (GF_NFS3, GF_LOG_TRACE, "Flushing call state");
- ret = inode_ctx_get (cs->resolvedloc.inode, cs->nfsx, &ctxaddr);
- if (ret == -1) {
- gf_log (GF_NFS3, GF_LOG_TRACE, "No inode queue present");
- goto out;
- }
+}
- inode_q = (struct list_head *)(long)ctxaddr;
- if (!inode_q)
- goto out;
- list_for_each_entry_safe (cs, cstmp, inode_q, openwait_q) {
- gf_log (GF_NFS3, GF_LOG_TRACE, "Calling resume");
- cs->resolve_ret = 0;
- if (openedfd) {
- gf_log (GF_NFS3, GF_LOG_TRACE, "Opening uncached fd done: %d",
- openedfd->refcount);
- cs->fd = fd_ref (openedfd);
- }
- nfs3_call_resume (cs);
- }
+int
+nfs3_getattr_loglevel (nfsstat3 stat) {
-out:
- return 0;
-}
+ int ll = GF_LOG_DEBUG;
+ switch (stat) {
+ case NFS3ERR_PERM:
+ ll = GF_LOG_WARNING;
+ break;
-int
-__nfs3_fdcache_update_entry (struct nfs3_state *nfs3, fd_t *fd)
-{
- uint64_t ctxaddr = 0;
- struct nfs3_fd_entry *fde = NULL;
+ case NFS3ERR_NOENT:
+ ll = GF_LOG_WARNING;
+ break;
- gf_log (GF_NFS3, GF_LOG_TRACE, "Updating fd: 0x%lx", (long int)fd);
- fd_ctx_get (fd, nfs3->nfsx, &ctxaddr);
- fde = (struct nfs3_fd_entry *)(long)ctxaddr;
- list_del (&fde->list);
- list_add_tail (&fde->list, &nfs3->fdlru);
+ case NFS3ERR_ACCES:
+ ll = GF_LOG_WARNING;
+ break;
- return 0;
+ case NFS3ERR_EXIST:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_XDEV:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NODEV:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_IO:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NXIO:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTDIR:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_ISDIR:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_INVAL:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOSPC:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_ROFS:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_FBIG:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_MLINK:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NAMETOOLONG:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTEMPTY:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_SERVERFAULT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTSUPP:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_BADHANDLE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_STALE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_DQUOT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ default:
+ ll = GF_LOG_DEBUG;
+ break;
+ }
+
+ return ll;
}
int
-nfs3_fdcache_update (struct nfs3_state *nfs3, fd_t *fd)
-{
- if ((!nfs3) || (!fd))
- return -1;
+nfs3_setattr_loglevel (nfsstat3 stat) {
+
+ int ll = GF_LOG_DEBUG;
+
+ switch (stat) {
+
+ case NFS3ERR_NOENT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_EXIST:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_XDEV:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NODEV:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_IO:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NXIO:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTDIR:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_ISDIR:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_INVAL:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOSPC:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_ROFS:
+ ll = GF_LOG_WARNING;
+ break;
- LOCK (&nfs3->fdlrulock);
- {
- __nfs3_fdcache_update_entry (nfs3, fd);
+ case NFS3ERR_FBIG:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_MLINK:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NAMETOOLONG:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTEMPTY:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_SERVERFAULT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTSUPP:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_BADHANDLE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_STALE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_DQUOT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ default:
+ ll = GF_LOG_DEBUG;
+ break;
}
- UNLOCK (&nfs3->fdlrulock);
- return 0;
+ return ll;
}
int
-__nfs3_fdcache_remove_entry (struct nfs3_state *nfs3, struct nfs3_fd_entry *fde)
-{
- gf_log (GF_NFS3, GF_LOG_TRACE, "Removing fd: 0x%lx: %d",
- (long int)fde->cachedfd, fde->cachedfd->refcount);
- list_del (&fde->list);
- fd_ctx_del (fde->cachedfd, nfs3->nfsx, NULL);
- fd_unref (fde->cachedfd);
- FREE (fde);
- --nfs3->fdcount;
+nfs3_lookup_loglevel (nfsstat3 stat) {
- return 0;
+ int ll = GF_LOG_DEBUG;
+
+ switch (stat) {
+
+ case NFS3ERR_PERM:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_ACCES:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_EXIST:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_XDEV:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NODEV:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_IO:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NXIO:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTDIR:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_ISDIR:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_INVAL:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOSPC:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_ROFS:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_FBIG:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_MLINK:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NAMETOOLONG:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTEMPTY:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_SERVERFAULT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTSUPP:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_BADHANDLE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_STALE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_DQUOT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ default:
+ ll = GF_LOG_DEBUG;
+ break;
+ }
+
+ return ll;
}
int
-nfs3_fdcache_remove (struct nfs3_state *nfs3, fd_t *fd)
-{
- struct nfs3_fd_entry *fde = NULL;
- uint64_t ctxaddr = 0;
+nfs3_access_loglevel (nfsstat3 stat) {
- if ((!nfs3) || (!fd))
- return -1;
+ int ll = GF_LOG_DEBUG;
+
+ switch (stat) {
+
+ case NFS3ERR_NOENT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_EXIST:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_XDEV:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NODEV:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_IO:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NXIO:
+ ll = GF_LOG_WARNING;
+ break;
- LOCK (&nfs3->fdlrulock);
- {
- fd_ctx_get (fd, nfs3->nfsx, &ctxaddr);
- fde = (struct nfs3_fd_entry *)(long)ctxaddr;
- __nfs3_fdcache_remove_entry (nfs3, fde);
+ case NFS3ERR_NOTDIR:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_ISDIR:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_INVAL:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOSPC:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_ROFS:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_FBIG:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_MLINK:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NAMETOOLONG:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTEMPTY:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_SERVERFAULT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTSUPP:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_BADHANDLE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_STALE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_DQUOT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ default:
+ ll = GF_LOG_DEBUG;
+ break;
}
- UNLOCK (&nfs3->fdlrulock);
- return 0;
+ return ll;
}
int
-__nfs3_fdcache_replace (struct nfs3_state *nfs3)
-{
- struct nfs3_fd_entry *fde = NULL;
- struct nfs3_fd_entry *tmp = NULL;
+nfs3_readlink_loglevel (nfsstat3 stat) {
- if (!nfs3)
- return -1;
+ int ll = GF_LOG_DEBUG;
- if (nfs3->fdcount <= GF_NFS3_FDCACHE_SIZE)
- return 0;
+ switch (stat) {
- list_for_each_entry_safe (fde, tmp, &nfs3->fdlru, list)
+ case NFS3ERR_EXIST:
+ ll = GF_LOG_WARNING;
break;
- __nfs3_fdcache_remove_entry (nfs3, fde);
+ case NFS3ERR_XDEV:
+ ll = GF_LOG_WARNING;
+ break;
- return 0;
-}
+ case NFS3ERR_NODEV:
+ ll = GF_LOG_WARNING;
+ break;
+ case NFS3ERR_IO:
+ ll = GF_LOG_WARNING;
+ break;
+ case NFS3ERR_NXIO:
+ ll = GF_LOG_WARNING;
+ break;
-int
-nfs3_fdcache_add (struct nfs3_state *nfs3, fd_t *fd)
-{
- struct nfs3_fd_entry *fde = NULL;
- int ret = -1;
+ case NFS3ERR_NOTDIR:
+ ll = GF_LOG_WARNING;
+ break;
- if ((!nfs3) || (!fd))
- return -1;
+ case NFS3ERR_ISDIR:
+ ll = GF_LOG_WARNING;
+ break;
- fde = CALLOC (1, sizeof (*fd));
- if (!fde) {
- gf_log (GF_NFS3, GF_LOG_ERROR, "fd entry allocation failed");
- goto out;
- }
+ case NFS3ERR_INVAL:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOSPC:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_ROFS:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_FBIG:
+ ll = GF_LOG_WARNING;
+ break;
- /* Already refd by caller. */
- fde->cachedfd = fd;
- INIT_LIST_HEAD (&fde->list);
-
- LOCK (&nfs3->fdlrulock);
- {
- gf_log (GF_NFS3, GF_LOG_TRACE, "Adding fd: 0x%lx",
- (long int) fd);
- fd_ctx_set (fd, nfs3->nfsx, (uintptr_t)fde);
- fd_bind (fd);
- list_add_tail (&fde->list, &nfs3->fdlru);
- ++nfs3->fdcount;
- __nfs3_fdcache_replace (nfs3);
+ case NFS3ERR_MLINK:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTEMPTY:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_SERVERFAULT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTSUPP:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_BADHANDLE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_STALE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_DQUOT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ default:
+ ll = GF_LOG_DEBUG;
+ break;
}
- UNLOCK (&nfs3->fdlrulock);
-out:
- return ret;
+ return ll;
}
+int
+nfs3_read_loglevel (nfsstat3 stat) {
-int32_t
-nfs3_file_open_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno, fd_t *fd)
-{
- nfs3_call_state_t *cs = NULL;
- struct nfs3_state *nfs3 = NULL;
+ int ll = GF_LOG_DEBUG;
- cs = frame->local;
- if (op_ret == -1) {
- gf_log (GF_NFS3, GF_LOG_TRACE, "Opening uncached fd failed");
- cs->resolve_ret = -1;
- cs->resolve_errno = op_errno;
- fd = NULL;
- } else {
- gf_log (GF_NFS3, GF_LOG_TRACE, "Opening uncached fd done: %d",
- fd->refcount);
+ switch (stat) {
+
+ case NFS3ERR_NOENT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_EXIST:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_XDEV:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NODEV:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_IO:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NXIO:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTDIR:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_ISDIR:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_INVAL:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOSPC:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_ROFS:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_FBIG:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_MLINK:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NAMETOOLONG:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTEMPTY:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_SERVERFAULT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTSUPP:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_BADHANDLE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_STALE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_DQUOT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ default:
+ ll = GF_LOG_DEBUG;
+ break;
}
- nfs3 = rpcsvc_request_program_private (cs->req);
- nfs3_flush_open_wait_call_states (cs, fd);
- nfs3_fdcache_add (nfs3, fd);
- return 0;
+ return ll;
}
-/* Returns 1 if the current call is the first one to be queued. If so, the
- * caller will need to send the open fop. If this is a non-first call to be
- * queued, it means the fd opening is in progress.
- *
- * Returns 0, if this is a non-first call.
- */
+
int
-__nfs3_queue_call_state (nfs3_call_state_t *cs)
-{
- struct list_head *inode_q = NULL;
- int ret = -1;
- uint64_t ctxaddr = 0;
+nfs3_write_loglevel (nfsstat3 stat) {
- ret = __inode_ctx_get (cs->resolvedloc.inode, cs->nfsx, &ctxaddr);
- if (ret == 0) {
- inode_q = (struct list_head *)(long)ctxaddr;
- goto attach_cs;
- }
+ int ll = GF_LOG_DEBUG;
- inode_q = CALLOC (1, sizeof (*inode_q));
- if (!inode_q)
- goto err;
+ switch (stat) {
- gf_log (GF_NFS3, GF_LOG_TRACE, "Initing inode queue");
- INIT_LIST_HEAD (inode_q);
- __inode_ctx_put (cs->resolvedloc.inode, cs->nfsx, (uintptr_t)inode_q);
+ case NFS3ERR_NOENT:
+ ll = GF_LOG_WARNING;
+ break;
-attach_cs:
- if (list_empty (inode_q)) {
- gf_log (GF_NFS3, GF_LOG_TRACE, "First call in queue");
- ret = 1;
- } else
- ret = 0;
+ case NFS3ERR_EXIST:
+ ll = GF_LOG_WARNING;
+ break;
- gf_log (GF_NFS3, GF_LOG_TRACE, "Queueing call state");
- list_add_tail (&cs->openwait_q, inode_q);
+ case NFS3ERR_XDEV:
+ ll = GF_LOG_WARNING;
+ break;
-err:
- return ret;
+ case NFS3ERR_NODEV:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_IO:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NXIO:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTDIR:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_ISDIR:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_INVAL:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOSPC:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_ROFS:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_FBIG:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_MLINK:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NAMETOOLONG:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTEMPTY:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_SERVERFAULT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTSUPP:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_BADHANDLE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_STALE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_DQUOT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ default:
+ ll = GF_LOG_DEBUG;
+ break;
+ }
+
+ return ll;
}
int
-nfs3_queue_call_state (nfs3_call_state_t *cs)
-{
- int ret = 0;
- if (!cs)
- return -1;
+nfs3_create_loglevel (nfsstat3 stat) {
+
+ int ll = GF_LOG_DEBUG;
+
+ switch (stat) {
+
+ case NFS3ERR_NOENT:
+ ll = GF_LOG_WARNING;
+ break;
- LOCK (&cs->resolvedloc.inode->lock);
- {
- ret = __nfs3_queue_call_state (cs);
+ case NFS3ERR_EXIST:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_XDEV:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NODEV:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_IO:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NXIO:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTDIR:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_ISDIR:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_INVAL:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_FBIG:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_MLINK:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTEMPTY:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_SERVERFAULT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTSUPP:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_BADHANDLE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_STALE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ default:
+ ll = GF_LOG_DEBUG;
+ break;
}
- UNLOCK (&cs->resolvedloc.inode->lock);
- return ret;
+ return ll;
}
int
-__nfs3_file_open_and_resume (nfs3_call_state_t *cs)
-{
- nfs_user_t nfu = {0, };
- int ret = -EFAULT;
+nfs3_mkdir_loglevel (nfsstat3 stat) {
- if (!cs)
- return ret;
+ int ll = GF_LOG_DEBUG;
- ret = nfs3_queue_call_state (cs);
- if (ret != 1) {
- ret = 0;
- goto out;
+ switch (stat) {
+
+ case NFS3ERR_NOENT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_XDEV:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NODEV:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_IO:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NXIO:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTDIR:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_ISDIR:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_INVAL:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_FBIG:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_MLINK:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTEMPTY:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_SERVERFAULT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTSUPP:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_BADHANDLE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_STALE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_DQUOT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ default:
+ ll = GF_LOG_DEBUG;
+ break;
}
- nfs_user_root_create (&nfu);
- gf_log (GF_NFS3, GF_LOG_TRACE, "Opening uncached fd");
- ret = nfs_open (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, O_RDWR,
- nfs3_file_open_cbk, cs);
-out:
- return ret;
+ return ll;
}
-
int
-nfs3_file_open_and_resume (nfs3_call_state_t *cs, nfs3_resume_fn_t resume)
-{
- fd_t *fd = NULL;
- int ret = -EFAULT;
- struct nfs3_state *nfs3 = NULL;
+nfs3_symlink_loglevel (nfsstat3 stat) {
- if ((!cs))
- return ret;
+ int ll = GF_LOG_DEBUG;
- cs->resume_fn = resume;
- gf_log (GF_NFS3, GF_LOG_TRACE, "Opening: %s", cs->resolvedloc.path);
- fd = fd_lookup (cs->resolvedloc.inode, 0);
- if (fd) {
- nfs3 = rpcsvc_request_program_private (cs->req);
- /* Already refd by fd_lookup, so no need to ref again. */
- gf_log (GF_NFS3, GF_LOG_TRACE, "fd found in state: %d",
- fd->refcount);
- nfs3_fdcache_update (nfs3, fd);
- cs->fd = fd; /* Gets unrefd when the call state is wiped. */
- cs->resolve_ret = 0;
- nfs3_call_resume (cs);
- ret = 0;
- goto err;
- }
+ switch (stat) {
- ret = __nfs3_file_open_and_resume (cs);
+ case NFS3ERR_XDEV:
+ ll = GF_LOG_WARNING;
+ break;
-err:
- return ret;
-}
+ case NFS3ERR_NODEV:
+ ll = GF_LOG_WARNING;
+ break;
+ case NFS3ERR_IO:
+ ll = GF_LOG_WARNING;
+ break;
-void
-nfs3_stat_to_errstr (uint32_t xid, char *op, nfsstat3 stat, int pstat,
- char *errstr)
-{
- if ((!op) || (!errstr))
- return;
+ case NFS3ERR_NXIO:
+ ll = GF_LOG_WARNING;
+ break;
- sprintf (errstr, "XID: %x, %s: NFS: %d(%s), POSIX: %d(%s)", xid, op,
- stat, nfsstat3_strerror (stat), pstat, strerror (pstat));
-}
+ case NFS3ERR_NOTDIR:
+ ll = GF_LOG_WARNING;
+ break;
-void
-nfs3_log_common_call (uint32_t xid, char *op, struct nfs3_fh *fh)
-{
- char fhstr[1024];
+ case NFS3ERR_ISDIR:
+ ll = GF_LOG_WARNING;
+ break;
- nfs3_fh_to_str (fh, fhstr);
- gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, %s: args: %s", xid, op,
- fhstr);
+ case NFS3ERR_INVAL:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_FBIG:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_MLINK:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTEMPTY:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_SERVERFAULT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTSUPP:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_BADHANDLE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_STALE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_DQUOT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ default:
+ ll = GF_LOG_DEBUG;
+ break;
+ }
+
+ return ll;
}
-void
-nfs3_log_fh_entry_call (uint32_t xid, char *op, struct nfs3_fh *fh,
- char *name)
-{
- char fhstr[1024];
+int
+nfs3_mknod_loglevel (nfsstat3 stat) {
- nfs3_fh_to_str (fh, fhstr);
- gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, %s: args: %s, name: %s", xid,
- op, fhstr, name);
+ int ll = GF_LOG_DEBUG;
+
+ switch (stat) {
+
+ case NFS3ERR_NOENT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_XDEV:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NODEV:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_IO:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NXIO:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTDIR:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_ISDIR:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_INVAL:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_FBIG:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_MLINK:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTEMPTY:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_SERVERFAULT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTSUPP:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_BADHANDLE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_STALE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ default:
+ ll = GF_LOG_DEBUG;
+ break;
+ }
+
+ return ll;
}
+int
+nfs3_remove_loglevel (nfsstat3 stat) {
-void
-nfs3_log_rename_call (uint32_t xid, struct nfs3_fh *src, char *sname,
- struct nfs3_fh *dst, char *dname)
-{
- char sfhstr[1024];
- char dfhstr[1024];
+ int ll = GF_LOG_DEBUG;
- nfs3_fh_to_str (src, sfhstr);
- nfs3_fh_to_str (dst, dfhstr);
- gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, RENAME: args: Src: %s, "
- "name: %s, Dst: %s, name: %s", xid, sfhstr, sname, dfhstr,
- dname);
+ switch (stat) {
+
+ case NFS3ERR_EXIST:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_XDEV:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NODEV:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_IO:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NXIO:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTDIR:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_INVAL:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOSPC:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_FBIG:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_MLINK:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_SERVERFAULT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTSUPP:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_BADHANDLE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_STALE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_DQUOT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ default:
+ ll = GF_LOG_DEBUG;
+ break;
+ }
+
+ return ll;
}
+int
+nfs3_rmdir_loglevel (nfsstat3 stat) {
-void
-nfs3_log_create_call (uint32_t xid, struct nfs3_fh *fh, char *name,
- createmode3 mode)
-{
- char fhstr[1024];
- char *modestr = NULL;
- char exclmode[] = "EXCLUSIVE";
- char unchkd[] = "UNCHECKED";
- char guarded[] = "GUARDED";
+ int ll = GF_LOG_DEBUG;
- nfs3_fh_to_str (fh, fhstr);
- if (mode == EXCLUSIVE)
- modestr = exclmode;
- else if (mode == GUARDED)
- modestr = guarded;
- else
- modestr = unchkd;
+ switch (stat) {
- gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, CREATE: args: %s, name: %s,"
- " mode: %s", xid, fhstr, name, modestr);
+ case NFS3ERR_EXIST:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_XDEV:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NODEV:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_IO:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NXIO:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTDIR:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_INVAL:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOSPC:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_FBIG:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_MLINK:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_SERVERFAULT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTSUPP:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_BADHANDLE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_STALE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_DQUOT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ default:
+ ll = GF_LOG_DEBUG;
+ break;
+ }
+
+ return ll;
}
-void
-nfs3_log_mknod_call (uint32_t xid, struct nfs3_fh *fh, char *name, int type)
-{
- char fhstr[1024];
- char *modestr = NULL;
- char chr[] = "CHAR";
- char blk[] = "BLK";
- char sock[] = "SOCK";
- char fifo[] = "FIFO";
+int
+nfs3_rename_loglevel (nfsstat3 stat) {
- nfs3_fh_to_str (fh, fhstr);
- if (type == NF3CHR)
- modestr = chr;
- else if (type == NF3BLK)
- modestr = blk;
- else if (type == NF3SOCK)
- modestr = sock;
- else
- modestr = fifo;
+ int ll = GF_LOG_DEBUG;
- gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, MKNOD: args: %s, name: %s,"
- " type: %s", xid, fhstr, name, modestr);
+ switch (stat) {
+
+ case NFS3ERR_XDEV:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NODEV:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_IO:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NXIO:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTDIR:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_ISDIR:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_INVAL:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOSPC:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_FBIG:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_MLINK:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTEMPTY:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_SERVERFAULT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTSUPP:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_BADHANDLE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_STALE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_DQUOT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ default:
+ ll = GF_LOG_DEBUG;
+ break;
+ }
+
+ return ll;
}
+int
+nfs3_link_loglevel (nfsstat3 stat) {
-void
-nfs3_log_symlink_call (uint32_t xid, struct nfs3_fh *fh, char *name, char *tgt)
-{
- char fhstr[1024];
+ int ll = GF_LOG_DEBUG;
- nfs3_fh_to_str (fh, fhstr);
- gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, SYMLINK: args: %s, name: %s,"
- " target: %s", xid, fhstr, name, tgt);
+ switch (stat) {
+
+ case NFS3ERR_XDEV:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NODEV:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_IO:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NXIO:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_INVAL:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_FBIG:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_MLINK:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTEMPTY:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_SERVERFAULT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTSUPP:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_BADHANDLE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_STALE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_DQUOT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ default:
+ ll = GF_LOG_DEBUG;
+ break;
+ }
+
+ return ll;
}
-void
-nfs3_log_link_call (uint32_t xid, struct nfs3_fh *fh, char *name,
- struct nfs3_fh *tgt)
-{
- char dfhstr[1024];
- char tfhstr[1024];
+int
+nfs3_readdir_loglevel (nfsstat3 stat) {
- nfs3_fh_to_str (fh, dfhstr);
- nfs3_fh_to_str (tgt, tfhstr);
- gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, LINK: args: %s, name: %s,"
- " target: %s", xid, dfhstr, name, tfhstr);
+ int ll = GF_LOG_DEBUG;
+
+ switch (stat) {
+
+ case NFS3ERR_NOENT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_EXIST:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_XDEV:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NODEV:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_IO:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NXIO:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTDIR:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_ISDIR:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_INVAL:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOSPC:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_ROFS:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_FBIG:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_MLINK:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NAMETOOLONG:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTEMPTY:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_SERVERFAULT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTSUPP:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_BADHANDLE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_STALE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_DQUOT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ default:
+ ll = GF_LOG_DEBUG;
+ break;
+ }
+
+ return ll;
}
-void
-nfs3_log_rw_call (uint32_t xid, char *op, struct nfs3_fh *fh, offset3 offt,
- count3 count, int stablewrite)
-{
- char fhstr[1024];
+int
+nfs3_fsstat_loglevel (nfsstat3 stat) {
- nfs3_fh_to_str (fh, fhstr);
- if (stablewrite == -1)
- gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, %s: args: %s, offset:"
- " %"PRIu64", count: %"PRIu32, xid, op, fhstr, offt,
- count);
- else
- gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, %s: args: %s, offset:"
- " %"PRIu64", count: %"PRIu32", %s", xid, op, fhstr,
- offt, count,
- (stablewrite == UNSTABLE)?"UNSTABLE":"STABLE");
+ int ll = GF_LOG_DEBUG;
+
+ switch (stat) {
+
+ case NFS3ERR_PERM:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOENT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_ACCES:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_EXIST:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_XDEV:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NODEV:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_IO:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NXIO:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTDIR:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_ISDIR:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_INVAL:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOSPC:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_ROFS:
+ ll = GF_LOG_WARNING;
+ break;
+ case NFS3ERR_FBIG:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_MLINK:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NAMETOOLONG:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTEMPTY:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_SERVERFAULT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_NOTSUPP:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_BADHANDLE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_STALE:
+ ll = GF_LOG_WARNING;
+ break;
+
+ case NFS3ERR_DQUOT:
+ ll = GF_LOG_WARNING;
+ break;
+
+ default:
+ ll = GF_LOG_DEBUG;
+ break;
+ }
+
+ return ll;
}
+struct nfs3op_str {
+ int op;
+ char str[100];
+};
+
+struct nfs3op_str nfs3op_strings[] = {
+ { NFS3_NULL, "NULL"},
+ { NFS3_GETATTR, "GETATTR"},
+ { NFS3_SETATTR, "SETATTR"},
+ { NFS3_LOOKUP, "LOOKUP"},
+ { NFS3_ACCESS, "ACCESS"},
+ { NFS3_READLINK, "READLINK"},
+ { NFS3_READ, "READ"},
+ { NFS3_WRITE, "WRITE"},
+ { NFS3_CREATE, "CREATE"},
+ { NFS3_MKDIR, "MKDIR"},
+ { NFS3_SYMLINK, "SYMLINK"},
+ { NFS3_MKNOD, "MKNOD"},
+ { NFS3_REMOVE, "REMOVE"},
+ { NFS3_RMDIR, "RMDIR"},
+ { NFS3_RENAME, "RENAME"},
+ { NFS3_LINK, "LINK"},
+ { NFS3_READDIR, "READDIR"},
+ { NFS3_READDIRP, "READDIRP"},
+ { NFS3_FSSTAT, "FSSTAT"},
+ { NFS3_FSINFO, "FSINFO"},
+ { NFS3_PATHCONF, "PATHCONF"},
+ { NFS3_COMMIT, "COMMIT"},
+};
+
+int
+nfs3_loglevel (int nfs_op, nfsstat3 stat) {
+
+ int ll = GF_LOG_DEBUG;
+
+ switch (nfs_op) {
+ case NFS3_GETATTR:
+ ll = nfs3_getattr_loglevel (stat);
+ break;
+
+ case NFS3_SETATTR:
+ ll = nfs3_setattr_loglevel (stat);
+ break;
+
+ case NFS3_LOOKUP:
+ ll = nfs3_lookup_loglevel (stat);
+ break;
+
+ case NFS3_ACCESS:
+ ll = nfs3_access_loglevel (stat);
+ break;
+
+ case NFS3_READLINK:
+ ll = nfs3_readlink_loglevel (stat);
+ break;
+
+ case NFS3_READ:
+ ll = nfs3_read_loglevel (stat);
+ break;
+
+ case NFS3_WRITE:
+ ll = nfs3_write_loglevel (stat);
+ break;
+
+ case NFS3_CREATE:
+ ll = nfs3_create_loglevel (stat);
+ break;
+
+ case NFS3_MKDIR:
+ ll = nfs3_mkdir_loglevel (stat);
+ break;
+
+ case NFS3_SYMLINK:
+ ll = nfs3_symlink_loglevel (stat);
+ break;
+
+ case NFS3_MKNOD:
+ ll = nfs3_mknod_loglevel (stat);
+ break;
+
+ case NFS3_REMOVE:
+ ll = nfs3_remove_loglevel (stat);
+ break;
+
+ case NFS3_RMDIR:
+ ll = nfs3_rmdir_loglevel (stat);
+ break;
+
+ case NFS3_RENAME:
+ ll = nfs3_rename_loglevel (stat);
+ break;
+
+ case NFS3_LINK:
+ ll = nfs3_link_loglevel (stat);
+ break;
+
+ case NFS3_READDIR:
+ ll = nfs3_readdir_loglevel (stat);
+ break;
+
+ case NFS3_READDIRP:
+ ll = nfs3_readdir_loglevel (stat);
+ break;
+
+ case NFS3_FSSTAT:
+ ll = nfs3_fsstat_loglevel (stat);
+ break;
+
+ case NFS3_FSINFO:
+ ll = nfs3_fsstat_loglevel (stat);
+ break;
+
+ case NFS3_PATHCONF:
+ ll = nfs3_fsstat_loglevel (stat);
+ break;
+
+ case NFS3_COMMIT:
+ ll = nfs3_write_loglevel (stat);
+ break;
+
+ default:
+ ll = GF_LOG_DEBUG;
+ break;
+ }
+
+ return ll;
+}
void
-nfs3_log_common_res (uint32_t xid, char *op, nfsstat3 stat, int pstat)
+nfs3_log_common_res (uint32_t xid, int op, nfsstat3 stat, int pstat)
{
char errstr[1024];
+ int ll = nfs3_loglevel (op, stat);
- nfs3_stat_to_errstr (xid, op, stat, pstat, errstr);
- gf_log (GF_NFS3, GF_LOG_DEBUG, "%s", errstr);
+ if (THIS->ctx->log.loglevel < ll)
+ return;
+ nfs3_stat_to_errstr (xid, nfs3op_strings[op].str, stat, pstat, errstr, sizeof (errstr));
+ gf_log (GF_NFS3, ll, "%s", errstr);
}
void
nfs3_log_readlink_res (uint32_t xid, nfsstat3 stat, int pstat, char *linkpath)
{
char errstr[1024];
+ int ll = nfs3_loglevel (NFS3_READLINK, stat);
+
+ if (THIS->ctx->log.loglevel < ll)
+ return;
- nfs3_stat_to_errstr (xid, "READLINK", stat, pstat, errstr);
- gf_log (GF_NFS3, GF_LOG_DEBUG, "%s, target: %s", errstr, linkpath);
+ nfs3_stat_to_errstr (xid, "READLINK", stat, pstat, errstr, sizeof (errstr));
+ gf_log (GF_NFS3, ll, "%s, target: %s",
+ errstr, linkpath);
}
void
nfs3_log_read_res (uint32_t xid, nfsstat3 stat, int pstat, count3 count,
- int is_eof)
+ int is_eof, struct iovec *vec, int32_t veccount)
{
char errstr[1024];
+ int ll = GF_LOG_DEBUG;
- nfs3_stat_to_errstr (xid, "READ", stat, pstat, errstr);
- gf_log (GF_NFS3, GF_LOG_DEBUG, "%s, count: %"PRIu32", is_eof: %d",
- errstr, count, is_eof);
+ ll = nfs3_loglevel (NFS3_READ, stat);
+ if (THIS->ctx->log.loglevel < ll)
+ return;
+ nfs3_stat_to_errstr (xid, "READ", stat, pstat, errstr, sizeof (errstr));
+ if (vec)
+ gf_log (GF_NFS3, ll, "%s, count: %"PRIu32", is_eof:"
+ " %d, vector: count: %d, len: %zd", errstr, count,
+ is_eof, veccount, vec->iov_len);
+ else
+ gf_log (GF_NFS3, ll, "%s, count: %"PRIu32", is_eof:"
+ " %d", errstr, count, is_eof);
}
@@ -2217,25 +3442,32 @@ nfs3_log_write_res (uint32_t xid, nfsstat3 stat, int pstat, count3 count,
int stable, uint64_t wverf)
{
char errstr[1024];
+ int ll = nfs3_loglevel (NFS3_WRITE, stat);
- nfs3_stat_to_errstr (xid, "WRITE", stat, pstat, errstr);
- gf_log (GF_NFS3, GF_LOG_DEBUG, "%s, count: %"PRIu32", %s,wverf: %"PRIu64
+ if (THIS->ctx->log.loglevel < ll)
+ return;
+
+ nfs3_stat_to_errstr (xid, "WRITE", stat, pstat, errstr, sizeof (errstr));
+ gf_log (GF_NFS3, ll, "%s, count: %"PRIu32", %s,wverf: %"PRIu64
, errstr, count, (stable == UNSTABLE)?"UNSTABLE":"STABLE",
wverf);
}
void
-nfs3_log_newfh_res (uint32_t xid, char *op, nfsstat3 stat, int pstat,
+nfs3_log_newfh_res (uint32_t xid, int op, nfsstat3 stat, int pstat,
struct nfs3_fh *newfh)
{
char errstr[1024];
char fhstr[1024];
+ int ll = nfs3_loglevel (op, stat);
- nfs3_stat_to_errstr (xid, op, stat, pstat, errstr);
- nfs3_fh_to_str (newfh, fhstr);
+ if (THIS->ctx->log.loglevel < ll)
+ return;
+ nfs3_stat_to_errstr (xid, nfs3op_strings[op].str, stat, pstat, errstr, sizeof (errstr));
+ nfs3_fh_to_str (newfh, fhstr, sizeof (fhstr));
- gf_log (GF_NFS3, GF_LOG_DEBUG, "%s, %s", errstr, fhstr);
+ gf_log (GF_NFS3, nfs3_loglevel (op, stat), "%s, %s", errstr, fhstr);
}
@@ -2244,9 +3476,12 @@ nfs3_log_readdir_res (uint32_t xid, nfsstat3 stat, int pstat, uint64_t cverf,
count3 count, int is_eof)
{
char errstr[1024];
+ int ll = nfs3_loglevel (NFS3_READDIR, stat);
- nfs3_stat_to_errstr (xid, "READDIR", stat, pstat, errstr);
- gf_log (GF_NFS3, GF_LOG_DEBUG, "%s, count: %"PRIu32", cverf: %"PRIu64
+ if (THIS->ctx->log.loglevel < ll)
+ return;
+ nfs3_stat_to_errstr (xid, "READDIR", stat, pstat, errstr, sizeof (errstr));
+ gf_log (GF_NFS3, ll, "%s, count: %"PRIu32", cverf: %"PRIu64
", is_eof: %d", errstr, count, cverf, is_eof);
}
@@ -2256,9 +3491,12 @@ nfs3_log_readdirp_res (uint32_t xid, nfsstat3 stat, int pstat, uint64_t cverf,
count3 dircount, count3 maxcount, int is_eof)
{
char errstr[1024];
+ int ll = nfs3_loglevel (NFS3_READDIRP, stat);
- nfs3_stat_to_errstr (xid, "READDIRPLUS", stat, pstat, errstr);
- gf_log (GF_NFS3, GF_LOG_DEBUG, "%s, dircount: %"PRIu32", maxcount: %"
+ if (THIS->ctx->log.loglevel < ll)
+ return;
+ nfs3_stat_to_errstr (xid, "READDIRPLUS", stat, pstat, errstr, sizeof (errstr));
+ gf_log (GF_NFS3, ll, "%s, dircount: %"PRIu32", maxcount: %"
PRIu32", cverf: %"PRIu64", is_eof: %d", errstr, dircount,
maxcount, cverf, is_eof);
}
@@ -2268,9 +3506,12 @@ void
nfs3_log_commit_res (uint32_t xid, nfsstat3 stat, int pstat, uint64_t wverf)
{
char errstr[1024];
+ int ll = nfs3_loglevel (NFS3_COMMIT, stat);
- nfs3_stat_to_errstr (xid, "COMMIT", stat, pstat, errstr);
- gf_log (GF_NFS3, GF_LOG_DEBUG, "%s, wverf: %"PRIu64, errstr, wverf);
+ if (THIS->ctx->log.loglevel < ll)
+ return;
+ nfs3_stat_to_errstr (xid, "COMMIT", stat, pstat, errstr, sizeof (errstr));
+ gf_log (GF_NFS3, ll, "%s, wverf: %"PRIu64, errstr, wverf);
}
@@ -2280,7 +3521,10 @@ nfs3_log_readdir_call (uint32_t xid, struct nfs3_fh *fh, count3 dircount,
{
char fhstr[1024];
- nfs3_fh_to_str (fh, fhstr);
+ if (THIS->ctx->log.loglevel < GF_LOG_DEBUG)
+ return;
+
+ nfs3_fh_to_str (fh, fhstr, sizeof (fhstr));
if (maxcount == 0)
gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, READDIR: args: %s,"
@@ -2301,9 +3545,11 @@ nfs3_fh_resolve_inode_done (nfs3_call_state_t *cs, inode_t *inode)
return ret;
gf_log (GF_NFS3, GF_LOG_TRACE, "FH inode resolved");
- ret = nfs_inode_loc_fill (inode, &cs->resolvedloc);
- if (ret < 0)
+ ret = nfs_inode_loc_fill (inode, &cs->resolvedloc, NFS_RESOLVE_EXIST);
+ if (ret < 0) {
+ gf_log (GF_NFS3, GF_LOG_ERROR, "inode loc fill failed");
goto err;
+ }
nfs3_call_resume (cs);
@@ -2311,54 +3557,6 @@ err:
return ret;
}
-#define GF_NFS3_FHRESOLVE_FOUND 1
-#define GF_NFS3_FHRESOLVE_NOTFOUND 2
-#define GF_NFS3_FHRESOLVE_DIRFOUND 3
-
-int
-nfs3_fh_resolve_check_entry (struct nfs3_fh *fh, gf_dirent_t *candidate,
- int hashidx)
-{
- struct iatt *ia = NULL;
- int ret = GF_NFS3_FHRESOLVE_NOTFOUND;
- nfs3_hash_entry_t entryhash = 0;
-
- if ((!fh) || (!candidate))
- return ret;
-
- if ((strcmp (candidate->d_name, ".") == 0) ||
- (strcmp (candidate->d_name, "..") == 0))
- goto found_entry;
-
- ia = &candidate->d_stat;
- if ((ia->ia_gen == fh->gen) && (ia->ia_ino == fh->ino)) {
- gf_log (GF_NFS3, GF_LOG_TRACE, "Found entry: gen: %"PRId64
- " ino: %"PRId64", name: %s", ia->ia_gen, ia->ia_ino,
- candidate->d_name);
- ret = GF_NFS3_FHRESOLVE_FOUND;
- goto found_entry;
- }
-
- /* This condition ensures that we never have to be afraid of having
- * a directory hash conflict with a file hash. The consequence of
- * this condition is that we can now have unlimited files in a directory
- * and upto 65536 sub-directories in a directory.
- */
- if (!IA_ISDIR (candidate->d_stat.ia_type))
- goto found_entry;
- entryhash = fh->entryhash[hashidx];
- if (entryhash == nfs3_fh_hash_entry (ia->ia_ino, ia->ia_gen)) {
- gf_log (GF_NFS3, GF_LOG_TRACE, "Found hash match: %s: %d",
- candidate->d_name, entryhash);
- ret = GF_NFS3_FHRESOLVE_DIRFOUND;
- goto found_entry;
- }
-
-found_entry:
-
- return ret;
-}
-
int32_t
nfs3_fh_resolve_entry_lookup_cbk (call_frame_t *frame, void *cookie,
@@ -2368,342 +3566,83 @@ nfs3_fh_resolve_entry_lookup_cbk (call_frame_t *frame, void *cookie,
struct iatt *postparent)
{
nfs3_call_state_t *cs = NULL;
+ inode_t *linked_inode = NULL;
cs = frame->local;
cs->resolve_ret = op_ret;
cs->resolve_errno = op_errno;
if (op_ret == -1) {
- gf_log (GF_NFS3, GF_LOG_TRACE, "Lookup failed: %s: %s",
+ gf_log (GF_NFS3, (op_errno == ENOENT ? GF_LOG_TRACE : GF_LOG_ERROR),
+ "Lookup failed: %s: %s",
cs->resolvedloc.path, strerror (op_errno));
goto err;
} else
gf_log (GF_NFS3, GF_LOG_TRACE, "Entry looked up: %s",
cs->resolvedloc.path);
- inode_link (inode, cs->resolvedloc.parent, cs->resolvedloc.name, buf);
+ memcpy (&cs->stbuf, buf, sizeof (*buf));
+ memcpy (&cs->postparent, postparent, sizeof (*postparent));
+ linked_inode = inode_link (inode, cs->resolvedloc.parent,
+ cs->resolvedloc.name, buf);
+ if (linked_inode) {
+ inode_lookup (linked_inode);
+ inode_unref (cs->resolvedloc.inode);
+ cs->resolvedloc.inode = linked_inode;
+ }
err:
nfs3_call_resume (cs);
return 0;
}
-
-int32_t
-nfs3_fh_resolve_readdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno,
- gf_dirent_t *entries);
-
-int
-nfs3_fh_resolve_found_entry (nfs3_call_state_t *cs, gf_dirent_t *candidate)
-{
- uint64_t dirino = 0;
- uint64_t dirgen = 0;
- int ret = 0;
- nfs_user_t nfu = {0, };
-
- if ((!cs) || (!candidate))
- return -EFAULT;
-
- dirino = cs->resolvedloc.inode->ino;
- dirgen = cs->resolvedloc.inode->generation;
-
- nfs_loc_wipe (&cs->resolvedloc);
- ret = nfs_entry_loc_fill (cs->vol->itable, dirino, dirgen,
- candidate->d_name, &cs->resolvedloc,
- NFS_RESOLVE_CREATE);
- if (ret == -ENOENT) {
- gf_log (GF_NFS3, GF_LOG_TRACE, "Entry not in itable, needs"
- " lookup");
- nfs_user_root_create (&nfu);
- ret = nfs_lookup (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
- nfs3_fh_resolve_entry_lookup_cbk,
- cs);
- } else {
- gf_log (GF_NFS3, GF_LOG_TRACE, "Entry got from itable");
- nfs3_call_resume (cs);
- }
-
- return ret;
-}
-
-
int32_t
-nfs3_fh_resolve_parent_lookup_cbk (call_frame_t *frame, void *cookie,
+nfs3_fh_resolve_inode_lookup_cbk (call_frame_t *frame, void *cookie,
xlator_t *this, int32_t op_ret,
int32_t op_errno, inode_t *inode,
struct iatt *buf, dict_t *xattr,
struct iatt *postparent)
{
nfs3_call_state_t *cs = NULL;
+ inode_t *linked_inode = NULL;
cs = frame->local;
cs->resolve_ret = op_ret;
cs->resolve_errno = op_errno;
if (op_ret == -1) {
- gf_log (GF_NFS3, GF_LOG_TRACE, "Lookup failed: %s: %s",
+ gf_log (GF_NFS3, (op_errno == ENOENT ? GF_LOG_TRACE : GF_LOG_ERROR),
+ "Lookup failed: %s: %s",
cs->resolvedloc.path, strerror (op_errno));
nfs3_call_resume (cs);
goto err;
- } else
- gf_log (GF_NFS3, GF_LOG_TRACE, "Entry looked up: %s",
- cs->resolvedloc.path);
-
- inode_link (inode, cs->resolvedloc.parent, cs->resolvedloc.name, buf);
- nfs3_fh_resolve_entry_hard (cs);
-
-err:
- return 0;
-}
-
-
-int
-nfs3_fh_resolve_found_parent (nfs3_call_state_t *cs, gf_dirent_t *candidate)
-{
- uint64_t dirino = 0;
- uint64_t dirgen = 0;
- int ret = 0;
- nfs_user_t nfu = {0, };
-
- if ((!cs) || (!candidate))
- return -EFAULT;
-
- dirino = cs->resolvedloc.inode->ino;
- dirgen = cs->resolvedloc.inode->generation;
-
- nfs_loc_wipe (&cs->resolvedloc);
- ret = nfs_entry_loc_fill (cs->vol->itable, dirino, dirgen,
- candidate->d_name, &cs->resolvedloc,
- NFS_RESOLVE_CREATE);
- if (ret == -ENOENT) {
- nfs_user_root_create (&nfu);
- ret = nfs_lookup (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
- nfs3_fh_resolve_parent_lookup_cbk,
- cs);
- } else
- nfs3_fh_resolve_entry_hard (cs);
-
- return ret;
-}
-
-
-int
-nfs3_fh_resolve_found (nfs3_call_state_t *cs, gf_dirent_t *candidate)
-{
- int ret = 0;
-
- if ((!cs) || (!candidate))
- return -EFAULT;
-
- if (!cs->resolventry) {
- gf_log (GF_NFS3, GF_LOG_TRACE, "Candidate entry was found");
- ret = nfs3_fh_resolve_found_entry (cs, candidate);
- } else {
- gf_log (GF_NFS3, GF_LOG_TRACE, "Entry's parent was found");
- ret = nfs3_fh_resolve_found_parent (cs, candidate);
}
- return ret;
-}
-
-
-int32_t
-nfs3_fh_resolve_opendir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno, fd_t *fd)
-{
- nfs3_call_state_t *cs = NULL;
- int ret = -EFAULT;
- nfs_user_t nfu = {0, };
-
- cs = frame->local;
- cs->resolve_ret = op_ret;
- cs->resolve_errno = op_errno;
-
- if (op_ret == -1) {
- gf_log (GF_NFS3, GF_LOG_TRACE, "Dir open failed: %s: %s",
- cs->resolvedloc.path, strerror (op_errno));
- nfs3_call_resume (cs);
- goto err;
- } else
- gf_log (GF_NFS3, GF_LOG_TRACE, "Reading directory: %s",
- cs->resolvedloc.path);
+ memcpy (&cs->stbuf, buf, sizeof(*buf));
+ memcpy (&cs->postparent, buf, sizeof(*postparent));
+ linked_inode = inode_link (inode, cs->resolvedloc.parent,
+ cs->resolvedloc.name, buf);
+ if (linked_inode) {
+ inode_lookup (linked_inode);
+ inode_unref (cs->resolvedloc.inode);
+ cs->resolvedloc.inode = linked_inode;
+ }
- nfs_user_root_create (&nfu);
- /* This function can be called in a recursive code path, so if another
- * directory was opened in an earlier call, we must unref through this
- * reference before opening another fd_t.
+ /* If it is an entry lookup and we landed in the callback for hard
+ * inode resolution, it means the parent inode was not available and
+ * had to be resolved first. Now that is done, lets head back into
+ * entry resolution.
*/
- if (cs->resolve_dir_fd)
- fd_unref (cs->resolve_dir_fd);
-
- cs->resolve_dir_fd = fd_ref (fd);
- ret = nfs_readdirp (cs->nfsx, cs->vol, &nfu, fd, GF_NFS3_DTPREF, 0,
- nfs3_fh_resolve_readdir_cbk, cs);
-
-err:
- return ret;
-}
-
-int32_t
-nfs3_fh_resolve_dir_lookup_cbk (call_frame_t *frame, void *cookie,
- xlator_t *this, int32_t op_ret,int32_t op_errno,
- inode_t *inode, struct iatt *buf, dict_t *xattr,
- struct iatt *postparent)
-{
- nfs3_call_state_t *cs = NULL;
- nfs_user_t nfu = {0, };
-
- cs = frame->local;
- cs->resolve_ret = op_ret;
- cs->resolve_errno = op_errno;
-
- if (op_ret == -1) {
- gf_log (GF_NFS3, GF_LOG_TRACE, "Lookup failed: %s: %s",
- cs->resolvedloc.path, strerror (op_errno));
- nfs3_call_resume (cs);
- goto err;
- } else
- gf_log (GF_NFS3, GF_LOG_TRACE, "Dir will be opened: %s",
- cs->resolvedloc.path);
-
- nfs_user_root_create (&nfu);
- inode_link (inode, cs->resolvedloc.parent, cs->resolvedloc.name, buf);
- nfs_opendir (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
- nfs3_fh_resolve_opendir_cbk, cs);
-
+ if (cs->resolventry)
+ nfs3_fh_resolve_entry_hard (cs);
+ else
+ nfs3_call_resume (cs);
err:
return 0;
}
-int
-nfs3_fh_resolve_dir_hard (nfs3_call_state_t *cs, uint64_t ino, uint64_t gen,
- char *entry)
-{
- int ret = -EFAULT;
- nfs_user_t nfu = {0, };
-
- if (!cs)
- return ret;
-
- cs->hashidx++;
- nfs_loc_wipe (&cs->resolvedloc);
- if (nfs3_fh_hash_index_is_beyond (&cs->resolvefh, cs->hashidx)) {
- gf_log (GF_NFS3, GF_LOG_TRACE, "Hash index is beyond: idx %d, "
- " fh idx: %d", cs->hashidx, cs->resolvefh.hashcount);
- nfs3_call_resume_estale (cs);
- ret = 0;
- goto out;
- }
-
- nfs_user_root_create (&nfu);
- gf_log (GF_NFS3, GF_LOG_TRACE, "FH hard dir resolution: ino:"
- " %"PRIu64", gen: %"PRIu64", entry: %s, hashidx: %d",
- ino, gen, entry, cs->hashidx);
- ret = nfs_entry_loc_fill (cs->vol->itable, ino, gen, entry,
- &cs->resolvedloc, NFS_RESOLVE_CREATE);
-
- if (ret == 0) {
- gf_log (GF_NFS3, GF_LOG_TRACE, "Dir will be opened: %s",
- cs->resolvedloc.path);
- ret = nfs_opendir (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
- nfs3_fh_resolve_opendir_cbk, cs);
- } else if (ret == -ENOENT) {
- gf_log (GF_NFS3, GF_LOG_TRACE, "Dir needs lookup: %s",
- cs->resolvedloc.path);
- ret = nfs_lookup (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
- nfs3_fh_resolve_dir_lookup_cbk, cs);
- }
-out:
- return ret;
-}
-
-
-int
-nfs3_fh_resolve_check_response (nfs3_call_state_t *cs, gf_dirent_t *candidate,
- int response, off_t last_offt)
-{
- uint64_t dirino = 0;
- uint64_t dirgen = 0;
- int ret = -EFAULT;
- nfs_user_t nfu = {0, };
-
- if (!cs)
- return ret;
-
- dirino = cs->resolvedloc.inode->ino;
- dirgen = cs->resolvedloc.inode->generation;
-
- if (response == GF_NFS3_FHRESOLVE_DIRFOUND)
- ret = nfs3_fh_resolve_dir_hard (cs, dirino, dirgen,
- candidate->d_name);
- else if (response == GF_NFS3_FHRESOLVE_FOUND)
- nfs3_fh_resolve_found (cs, candidate);
- else if (response == GF_NFS3_FHRESOLVE_NOTFOUND) {
- nfs_user_root_create (&nfu);
- ret = nfs_readdirp (cs->nfsx, cs->vol, &nfu, cs->resolve_dir_fd,
- GF_NFS3_DTPREF, last_offt,
- nfs3_fh_resolve_readdir_cbk, cs);
- }
-
- return 0;
-}
-
-int
-nfs3_fh_resolve_search_dir (nfs3_call_state_t *cs, gf_dirent_t *entries)
-{
- gf_dirent_t *candidate = NULL;
- int ret = GF_NFS3_FHRESOLVE_NOTFOUND;
- off_t lastoff = 0;
-
- if ((!cs) || (!entries))
- return -EFAULT;
-
- if (list_empty (&entries->list))
- goto not_found;
-
- list_for_each_entry (candidate, &entries->list, list) {
- lastoff = candidate->d_off;
- gf_log (GF_NFS3, GF_LOG_TRACE, "Candidate: %s, ino: %"PRIu64
- ", gen: %"PRIu64, candidate->d_name, candidate->d_ino,
- candidate->d_stat.ia_gen);
- ret = nfs3_fh_resolve_check_entry (&cs->resolvefh, candidate,
- cs->hashidx);
- if (ret != GF_NFS3_FHRESOLVE_NOTFOUND)
- break;
- }
-
-not_found:
- nfs3_fh_resolve_check_response (cs, candidate, ret, lastoff);
- return ret;
-}
-
-
-int32_t
-nfs3_fh_resolve_readdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno,
- gf_dirent_t *entries)
-{
- nfs3_call_state_t *cs = NULL;
-
- cs = frame->local;
- if (op_ret <= 0) {
- gf_log (GF_NFS3, GF_LOG_TRACE, "Directory read done: %s: %s",
- cs->resolvedloc.path, strerror (op_ret));
- cs->resolve_ret = -1;
- cs->resolve_errno = ENOENT;
- nfs3_call_resume (cs);
- goto err;
- }
-
- nfs3_fh_resolve_search_dir (cs, entries);
-
-err:
- return 0;
-}
-
/* Needs no extra argument since it knows that the fh to be resolved is in
* resolvefh and that it needs to start looking from the root.
*/
@@ -2716,33 +3655,21 @@ nfs3_fh_resolve_inode_hard (nfs3_call_state_t *cs)
if (!cs)
return ret;
- cs->hashidx++;
+ gf_log (GF_NFS3, GF_LOG_TRACE, "FH hard resolution for: gfid 0x%s",
+ uuid_utoa (cs->resolvefh.gfid));
+ cs->hardresolved = 1;
nfs_loc_wipe (&cs->resolvedloc);
- if (nfs3_fh_hash_index_is_beyond (&cs->resolvefh, cs->hashidx)) {
- gf_log (GF_NFS3, GF_LOG_TRACE, "Hash index is beyond: idx %d, "
- " fh idx: %d", cs->hashidx, cs->resolvefh.hashcount);
- nfs3_call_resume_estale (cs);
- ret = 0;
+ ret = nfs_gfid_loc_fill (cs->vol->itable, cs->resolvefh.gfid,
+ &cs->resolvedloc, NFS_RESOLVE_CREATE);
+ if (ret < 0) {
+ gf_log (GF_NFS3, GF_LOG_ERROR, "Failed to fill loc using gfid: "
+ "%s", strerror (-ret));
goto out;
}
nfs_user_root_create (&nfu);
- gf_log (GF_NFS3, GF_LOG_TRACE, "FH hard resolution: ino:"
- " %"PRIu64", gen: %"PRIu64", hashidx: %d", cs->resolvefh.ino,
- cs->resolvefh.gen, cs->hashidx);
- ret = nfs_ino_loc_fill (cs->vol->itable, 1, 0, &cs->resolvedloc);
-
- if (ret == 0) {
- gf_log (GF_NFS3, GF_LOG_TRACE, "Dir will be opened: %s",
- cs->resolvedloc.path);
- ret = nfs_opendir (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
- nfs3_fh_resolve_opendir_cbk, cs);
- } else if (ret == -ENOENT) {
- gf_log (GF_NFS3, GF_LOG_TRACE, "Dir needs lookup: %s",
- cs->resolvedloc.path);
- ret = nfs_lookup (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
- nfs3_fh_resolve_dir_lookup_cbk, cs);
- }
+ ret = nfs_lookup (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
+ nfs3_fh_resolve_inode_lookup_cbk, cs);
out:
return ret;
@@ -2760,20 +3687,33 @@ nfs3_fh_resolve_entry_hard (nfs3_call_state_t *cs)
nfs_loc_wipe (&cs->resolvedloc);
nfs_user_root_create (&nfu);
- gf_log (GF_NFS3, GF_LOG_TRACE, "FH hard resolution: ino:"
- " %"PRIu64", gen: %"PRIu64", entry: %s, hashidx: %d",
- cs->resolvefh.ino, cs->resolvefh.gen, cs->resolventry,
- cs->hashidx);
+ gf_log (GF_NFS3, GF_LOG_TRACE, "FH hard resolution: gfid: %s "
+ ", entry: %s", uuid_utoa (cs->resolvefh.gfid),
+ cs->resolventry);
- ret = nfs_entry_loc_fill (cs->vol->itable, cs->resolvefh.ino,
- cs->resolvefh.gen, cs->resolventry,
- &cs->resolvedloc, NFS_RESOLVE_CREATE);
+ ret = nfs_entry_loc_fill (cs->vol->itable, cs->resolvefh.gfid,
+ cs->resolventry, &cs->resolvedloc,
+ NFS_RESOLVE_CREATE);
if (ret == -2) {
gf_log (GF_NFS3, GF_LOG_TRACE, "Entry needs lookup: %s",
cs->resolvedloc.path);
- ret = nfs_lookup (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
- nfs3_fh_resolve_entry_lookup_cbk, cs);
+ /* If the NFS op is lookup, let the resume callback
+ * handle the sending of the lookup fop. Similarly,
+ * if the NFS op is create, let the create call
+ * go ahead in the resume callback so that an EEXIST gets
+ * handled at posix without an extra fop at this point.
+ */
+ if (nfs3_lookup_op (cs) ||
+ (nfs3_create_op (cs) && !nfs3_create_exclusive_op (cs))) {
+ cs->lookuptype = GF_NFS3_FRESH;
+ cs->resolve_ret = 0;
+ nfs3_call_resume (cs);
+ } else {
+ cs->hardresolved = 1;
+ nfs_lookup (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
+ nfs3_fh_resolve_entry_lookup_cbk, cs);
+ }
ret = 0;
} else if (ret == -1) {
gf_log (GF_NFS3, GF_LOG_TRACE, "Entry needs parent lookup: %s",
@@ -2797,8 +3737,8 @@ nfs3_fh_resolve_inode (nfs3_call_state_t *cs)
return ret;
gf_log (GF_NFS3, GF_LOG_TRACE, "FH needs inode resolution");
- inode = inode_get (cs->vol->itable, cs->resolvefh.ino,
- cs->resolvefh.gen);
+ uuid_copy (cs->resolvedloc.gfid, cs->resolvefh.gfid);
+ inode = inode_find (cs->vol->itable, cs->resolvefh.gfid);
if (!inode)
ret = nfs3_fh_resolve_inode_hard (cs);
else
@@ -2818,16 +3758,97 @@ nfs3_fh_resolve_entry (nfs3_call_state_t *cs)
if (!cs)
return ret;
- ret = nfs3_fh_resolve_entry_hard (cs);
+ return nfs3_fh_resolve_entry_hard (cs);
+}
+
+
+int
+nfs3_fh_resolve_resume (nfs3_call_state_t *cs)
+{
+ int ret = -EFAULT;
+
+ if (!cs)
+ return ret;
+
+ if (cs->resolve_ret < 0)
+ goto err_resume_call;
+
+ if (!cs->resolventry)
+ ret = nfs3_fh_resolve_inode (cs);
+ else
+ ret = nfs3_fh_resolve_entry (cs);
+
+err_resume_call:
if (ret < 0) {
cs->resolve_ret = -1;
- cs->resolve_errno = ESTALE;
+ cs->resolve_errno = EFAULT;
nfs3_call_resume (cs);
+ ret = 0;
}
+ return ret;
+}
+
+
+int32_t
+nfs3_fh_resolve_root_lookup_cbk (call_frame_t *frame, void *cookie,
+ xlator_t *this, int32_t op_ret,
+ int32_t op_errno, inode_t *inode,
+ struct iatt *buf, dict_t *xattr,
+ struct iatt *postparent)
+{
+ nfs3_call_state_t *cs = NULL;
+
+ cs = frame->local;
+ cs->resolve_ret = op_ret;
+ cs->resolve_errno = op_errno;
+
+ if (op_ret == -1) {
+ gf_log (GF_NFS3, GF_LOG_ERROR, "Root lookup failed: %s",
+ strerror (op_errno));
+ goto err;
+ } else
+ gf_log (GF_NFS3, GF_LOG_TRACE, "Root looked up: %s",
+ cs->resolvedloc.path);
+
+ nfs3_set_root_looked_up (cs->nfs3state, &cs->resolvefh);
+err:
+ nfs3_fh_resolve_resume (cs);
return 0;
}
+
+int
+nfs3_fh_resolve_root (nfs3_call_state_t *cs)
+{
+ int ret = -EFAULT;
+ nfs_user_t nfu = {0, };
+
+ if (!cs)
+ return ret;
+
+ if (nfs3_is_root_looked_up (cs->nfs3state, &cs->resolvefh)) {
+ ret = nfs3_fh_resolve_resume (cs);
+ goto out;
+ }
+
+ nfs_user_root_create (&nfu);
+ gf_log (GF_NFS3, GF_LOG_TRACE, "Root needs lookup");
+ ret = nfs_root_loc_fill (cs->vol->itable, &cs->resolvedloc);
+ if (ret < 0) {
+ gf_log (GF_NFS3, GF_LOG_ERROR, "Failed to lookup root from itable: %s",
+ strerror (-ret));
+ goto out;
+ }
+
+ ret = nfs_lookup (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
+ nfs3_fh_resolve_root_lookup_cbk, cs);
+
+out:
+ return ret;
+}
+
+
int
nfs3_fh_resolve_and_resume (nfs3_call_state_t *cs, struct nfs3_fh *fh,
char *entry, nfs3_resume_fn_t resum_fn)
@@ -2841,18 +3862,20 @@ nfs3_fh_resolve_and_resume (nfs3_call_state_t *cs, struct nfs3_fh *fh,
cs->resolvefh = *fh;
cs->hashidx = 0;
- if (!entry)
- ret = nfs3_fh_resolve_inode (cs);
- else {
- cs->resolventry = strdup (entry);
+ /* Check if the resolution is:
+ * a. fh resolution
+ *
+ * or
+ *
+ * b. (fh, basename) resolution
+ */
+ if (entry) { /* b */
+ cs->resolventry = gf_strdup (entry);
if (!cs->resolventry)
goto err;
-
- ret = nfs3_fh_resolve_entry (cs);
}
+ ret = nfs3_fh_resolve_root (cs);
err:
return ret;
}
-
-
diff --git a/xlators/nfs/server/src/nfs3-helpers.h b/xlators/nfs/server/src/nfs3-helpers.h
index a282bce67..4de1d5623 100644
--- a/xlators/nfs/server/src/nfs3-helpers.h
+++ b/xlators/nfs/server/src/nfs3-helpers.h
@@ -1,20 +1,11 @@
/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
+ Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.com>
This file is part of GlusterFS.
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
*/
#ifndef _NFS3_HELPER_H_
@@ -44,9 +35,13 @@ nfs3_extract_lookup_name (lookup3args *args);
extern nfsstat3
nfs3_errno_to_nfsstat3 (int errnum);
+extern nfsstat3
+nfs3_cbk_errno_status (int32_t, int32_t);
+
extern void
nfs3_fill_lookup3res (lookup3res *res, nfsstat3 stat, struct nfs3_fh *newfh,
- struct iatt *stbuf, struct iatt *postparent);
+ struct iatt *stbuf, struct iatt *postparent,
+ uint64_t deviceid);
extern post_op_attr
nfs3_stat_to_post_op_attr (struct iatt *buf);
@@ -56,14 +51,14 @@ nfs3_extract_getattr_fh (getattr3args *args);
extern void
nfs3_fill_getattr3res (getattr3res *res, nfsstat3 stat, struct iatt *buf,
- uint16_t xlid);
+ uint64_t deviceid);
extern struct nfs3_fh
nfs3_extract_fsinfo_fh (fsinfo3args *args);
extern void
nfs3_fill_fsinfo3res (struct nfs3_state *nfs3, fsinfo3res *res,
- nfsstat3 status, struct iatt *fsroot, uint16_t xlid);
+ nfsstat3 status, struct iatt *fsroot,uint64_t deviceid);
/* Functions containing _prep_ are used specifically to work around
* the memory allocations that happen inside Sun RPC library.
@@ -98,8 +93,8 @@ extern void
nfs3_prep_access3args (access3args *args, struct nfs3_fh *fh);
extern void
-nfs3_fill_access3res (access3res *res, nfsstat3 status, struct iatt *buf,
- uint32_t accbits, uid_t uid, gid_t gid, uint16_t xlid);
+nfs3_fill_access3res (access3res *res, nfsstat3 status, int32_t accbits,
+ int32_t reqaccbits);
extern char *
nfs3_fhcache_getpath (struct nfs3_state *nfs3, struct nfs3_fh *fh);
@@ -111,18 +106,20 @@ extern void
nfs3_prep_readdir3args (readdir3args *ra, struct nfs3_fh *fh);
extern void
-nfs3_fill_readdir3res (readdir3res *res, nfsstat3 stat, uint64_t cverf,
- struct iatt *dirstat, gf_dirent_t *entries,count3 count,
- int is_eof, uint16_t xlid);
+nfs3_fill_readdir3res (readdir3res *res, nfsstat3 stat, struct nfs3_fh *dfh,
+ uint64_t cverf, struct iatt *dirstat,
+ gf_dirent_t *entries, count3 count, int is_eof,
+ uint64_t deviceid);
extern void
nfs3_prep_readdirp3args (readdirp3args *ra, struct nfs3_fh *fh);
extern void
-nfs3_fill_readdirp3res (readdirp3res *res, nfsstat3 stat, struct nfs3_fh *dirfh,
- uint64_t cverf, struct iatt *dirstat,
- gf_dirent_t *entries, count3 dircount, count3 maxcount,
- int is_eof);
+nfs3_fill_readdirp3res (readdirp3res *res, nfsstat3 stat,
+ struct nfs3_fh *dirfh, uint64_t cverf,
+ struct iatt *dirstat, gf_dirent_t *entries,
+ count3 dircount, count3 maxcount, int is_eof,
+ uint64_t deviceid);
extern void
nfs3_free_readdirp3res (readdirp3res *res);
@@ -135,14 +132,14 @@ nfs3_prep_fsstat3args (fsstat3args *args, struct nfs3_fh *fh);
extern void
nfs3_fill_fsstat3res (fsstat3res *res, nfsstat3 stat, struct statvfs *fsbuf,
- struct iatt *postbuf, uint16_t xlid);
+ struct iatt *postbuf, uint64_t deviceid);
extern int32_t
nfs3_sattr3_to_setattr_valid (sattr3 *sattr, struct iatt *buf, mode_t *omode);
extern void
nfs3_fill_create3res (create3res *res, nfsstat3 stat, struct nfs3_fh *newfh,
struct iatt *newbuf, struct iatt *preparent,
- struct iatt *postparent);
+ struct iatt *postparent, uint64_t deviceid);
extern void
nfs3_prep_create3args (create3args *args, struct nfs3_fh *fh, char *name);
@@ -152,7 +149,7 @@ nfs3_prep_setattr3args (setattr3args *args, struct nfs3_fh *fh);
extern void
nfs3_fill_setattr3res (setattr3res *res, nfsstat3 stat, struct iatt *preop,
- struct iatt *postop, uint16_t xlid);
+ struct iatt *postop, uint64_t deviceid);
extern void
nfs3_prep_mkdir3args (mkdir3args *args, struct nfs3_fh *dirfh, char *name);
@@ -160,7 +157,7 @@ nfs3_prep_mkdir3args (mkdir3args *args, struct nfs3_fh *dirfh, char *name);
extern void
nfs3_fill_mkdir3res (mkdir3res *res, nfsstat3 stat, struct nfs3_fh *fh,
struct iatt *buf, struct iatt *preparent,
- struct iatt *postparent);
+ struct iatt *postparent, uint64_t deviceid);
extern void
nfs3_prep_symlink3args (symlink3args *args, struct nfs3_fh *dirfh, char *name,
@@ -169,14 +166,14 @@ nfs3_prep_symlink3args (symlink3args *args, struct nfs3_fh *dirfh, char *name,
extern void
nfs3_fill_symlink3res (symlink3res *res, nfsstat3 stat, struct nfs3_fh *fh,
struct iatt *buf, struct iatt *preparent,
- struct iatt *postparent);
+ struct iatt *postparent, uint64_t deviceid);
extern void
nfs3_prep_readlink3args (readlink3args *args, struct nfs3_fh *fh);
extern void
nfs3_fill_readlink3res (readlink3res *res, nfsstat3 stat, char *path,
- struct iatt *buf, uint16_t xlid);
+ struct iatt *buf, uint64_t deviceid);
extern void
nfs3_prep_mknod3args (mknod3args *args, struct nfs3_fh *fh, char *name);
@@ -184,17 +181,17 @@ nfs3_prep_mknod3args (mknod3args *args, struct nfs3_fh *fh, char *name);
extern void
nfs3_fill_mknod3res (mknod3res *res, nfsstat3 stat, struct nfs3_fh *fh,
struct iatt *buf, struct iatt *preparent,
- struct iatt *postparent);
+ struct iatt *postparent, uint64_t deviceid);
extern void
nfs3_fill_remove3res (remove3res *res, nfsstat3 stat, struct iatt *preparent,
- struct iatt *postparent, uint16_t xlid);
+ struct iatt *postparent, uint64_t deviceid);
extern void
nfs3_prep_remove3args (remove3args *args, struct nfs3_fh *fh, char *name);
extern void
nfs3_fill_rmdir3res (rmdir3res *res, nfsstat3 stat, struct iatt *preparent,
- struct iatt *postparent, uint16_t xlid);
+ struct iatt *postparent, uint64_t deviceid);
extern void
nfs3_prep_rmdir3args (rmdir3args *args, struct nfs3_fh *fh, char *name);
@@ -202,7 +199,7 @@ nfs3_prep_rmdir3args (rmdir3args *args, struct nfs3_fh *fh, char *name);
extern void
nfs3_fill_link3res (link3res *res, nfsstat3 stat, struct iatt *buf,
struct iatt *preparent, struct iatt *postparent,
- uint16_t xlid);
+ uint64_t deviceid);
extern void
nfs3_prep_link3args (link3args *args, struct nfs3_fh *target,
@@ -217,7 +214,7 @@ extern void
nfs3_fill_rename3res (rename3res *res, nfsstat3 stat, struct iatt *buf,
struct iatt *preoldparent, struct iatt *postoldparent,
struct iatt *prenewparent, struct iatt *postnewparent,
- uint16_t xlid);
+ uint64_t deviceid);
extern void
nfs3_prep_write3args (write3args *args, struct nfs3_fh *fh);
@@ -225,7 +222,7 @@ nfs3_prep_write3args (write3args *args, struct nfs3_fh *fh);
extern void
nfs3_fill_write3res (write3res *res, nfsstat3 stat, count3 count,
stable_how stable, uint64_t wverf, struct iatt *prestat,
- struct iatt *poststat, uint16_t xlid);
+ struct iatt *poststat, uint64_t deviceid);
extern void
nfs3_prep_commit3args (commit3args *args, struct nfs3_fh *fh);
@@ -233,11 +230,11 @@ nfs3_prep_commit3args (commit3args *args, struct nfs3_fh *fh);
extern void
nfs3_fill_commit3res (commit3res *res, nfsstat3 stat, uint64_t wverf,
struct iatt *prestat, struct iatt *poststat,
- uint16_t xlid);
+ uint64_t deviceid);
extern void
nfs3_fill_read3res (read3res *res, nfsstat3 stat, count3 count,
- struct iatt *poststat, int is_eof, uint16_t xlid);
+ struct iatt *poststat, int is_eof, uint64_t deviceid);
extern void
nfs3_prep_read3args (read3args *args, struct nfs3_fh *fh);
@@ -247,27 +244,27 @@ nfs3_prep_pathconf3args (pathconf3args *args, struct nfs3_fh *fh);
extern void
nfs3_fill_pathconf3res (pathconf3res *res, nfsstat3 stat, struct iatt *buf,
- uint16_t xlid);
+ uint64_t deviceid);
extern int
nfs3_cached_inode_opened (xlator_t *nfsxl, inode_t *inode);
extern void
-nfs3_log_common_res (uint32_t xid, char *op, nfsstat3 stat, int pstat);
+nfs3_log_common_res (uint32_t xid, int op, nfsstat3 stat, int pstat);
extern void
nfs3_log_readlink_res (uint32_t xid, nfsstat3 stat, int pstat, char *linkpath);
extern void
nfs3_log_read_res (uint32_t xid, nfsstat3 stat, int pstat, count3 count,
- int is_eof);
+ int is_eof, struct iovec *vec, int32_t vcount);
extern void
nfs3_log_write_res (uint32_t xid, nfsstat3 stat, int pstat, count3 count,
int stable, uint64_t wverf);
extern void
-nfs3_log_newfh_res (uint32_t xid, char *op, nfsstat3 stat, int pstat,
+nfs3_log_newfh_res (uint32_t xid, int op, nfsstat3 stat, int pstat,
struct nfs3_fh *newfh);
extern void
@@ -328,15 +325,13 @@ nfs3_fh_resolve_and_resume (nfs3_call_state_t *cs, struct nfs3_fh *fh,
char *entry, nfs3_resume_fn_t resum_fn);
extern int
-nfs3_file_open_and_resume (nfs3_call_state_t *cs, nfs3_resume_fn_t resume);
-
-extern int
-nfs3_dir_open_and_resume (nfs3_call_state_t *cs, nfs3_resume_fn_t resume);
-
-extern int
nfs3_verify_dircookie (struct nfs3_state *nfs3, fd_t *dirfd, cookie3 cookie,
uint64_t cverf, nfsstat3 *stat);
extern int
-nfs3_fdcache_remove (struct nfs3_state *nfs3, fd_t *fd);
+nfs3_is_parentdir_entry (char *entry);
+
+uint32_t
+nfs3_request_to_accessbits (int32_t accbits);
+
#endif
diff --git a/xlators/nfs/server/src/nfs3.c b/xlators/nfs/server/src/nfs3.c
index 57d9f576e..f914c3193 100644
--- a/xlators/nfs/server/src/nfs3.c
+++ b/xlators/nfs/server/src/nfs3.c
@@ -1,20 +1,11 @@
/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
+ Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.com>
This file is part of GlusterFS.
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
*/
#ifndef _CONFIG_H
@@ -32,11 +23,15 @@
#include "nfs3.h"
#include "mem-pool.h"
#include "logging.h"
+#include "nfs-common.h"
#include "nfs-fops.h"
#include "nfs-inodes.h"
#include "nfs-generics.h"
#include "nfs3-helpers.h"
-
+#include "nfs-mem-types.h"
+#include "nfs.h"
+#include "xdr-rpc.h"
+#include "xdr-generic.h"
#include <sys/socket.h>
#include <sys/uio.h>
@@ -47,6 +42,8 @@
do { \
if ((str)) { \
if (strlen ((str)) > (len)) { \
+ gf_log (GF_NFS3, GF_LOG_ERROR, "strlen "\
+ "too long"); \
status = NFS3ERR_NAMETOOLONG; \
retval = -ENAMETOOLONG; \
goto label; \
@@ -57,7 +54,7 @@
#define nfs3_validate_nfs3_state(request, state, status, label, retval) \
do { \
state = rpcsvc_request_program_private (request); \
- if (!nfs3) { \
+ if (!state) { \
gf_log (GF_NFS3, GF_LOG_ERROR, "NFSv3 state " \
"missing from RPC request"); \
status = NFS3ERR_SERVERFAULT; \
@@ -66,12 +63,87 @@
} \
} while (0); \
-#define nfs3_export_access(nfs3state, xlid) ((nfs3state)->exports[xlid]).access
-#define nfs3_check_rw_volaccess(nfs3state, xlid, status, label) \
- do { \
- if (nfs3_export_access (nfs3state,xlid)!=GF_NFS3_VOLACCESS_RW){\
- gf_log (GF_NFS3, GF_LOG_TRACE, "No read-write access");\
+struct nfs3_export *
+__nfs3_get_export_by_index (struct nfs3_state *nfs3, uuid_t exportid)
+{
+ struct nfs3_export *exp = NULL;
+ int index = 0;
+ int searchindex = 0;
+
+ searchindex = nfs3_fh_exportid_to_index (exportid);
+ list_for_each_entry (exp, &nfs3->exports, explist) {
+ if (searchindex == index)
+ goto found;
+
+ ++index;
+ }
+
+ exp = NULL;
+ gf_log (GF_NFS, GF_LOG_ERROR, "searchindex=%d not found", searchindex);
+found:
+ return exp;
+}
+
+
+struct nfs3_export *
+__nfs3_get_export_by_volumeid (struct nfs3_state *nfs3, uuid_t exportid)
+{
+ struct nfs3_export *exp = NULL;
+
+ list_for_each_entry (exp, &nfs3->exports, explist) {
+ if (!uuid_compare (exportid, exp->volumeid))
+ goto found;
+ }
+
+ exp = NULL;
+found:
+ return exp;
+}
+
+
+struct nfs3_export *
+__nfs3_get_export_by_exportid (struct nfs3_state *nfs3, uuid_t exportid)
+{
+ struct nfs3_export *exp = NULL;
+
+ if (!nfs3)
+ return exp;
+
+ if (gf_nfs_dvm_off (nfs_state(nfs3->nfsx)))
+ exp = __nfs3_get_export_by_index (nfs3, exportid);
+ else
+ exp = __nfs3_get_export_by_volumeid (nfs3, exportid);
+
+ return exp;
+}
+
+
+int
+nfs3_export_access (struct nfs3_state *nfs3, uuid_t exportid)
+{
+ int ret = GF_NFS3_VOLACCESS_RO;
+ struct nfs3_export *exp = NULL;
+
+ GF_VALIDATE_OR_GOTO (GF_NFS3, nfs3, err);
+
+ exp = __nfs3_get_export_by_exportid (nfs3, exportid);
+
+ if (!exp) {
+ gf_log (GF_NFS3, GF_LOG_ERROR, "Failed to get export by ID");
+ goto err;
+ }
+
+ ret = exp->access;
+
+err:
+ return ret;
+}
+
+#define nfs3_check_rw_volaccess(nfs3state, exid, status, label) \
+ do { \
+ if (nfs3_export_access (nfs3state,exid)!=GF_NFS3_VOLACCESS_RW){\
+ gf_log (GF_NFS3, GF_LOG_ERROR, "No read-write access");\
status = NFS3ERR_ROFS; \
goto label; \
} \
@@ -79,17 +151,87 @@
-#define nfs3_map_fh_to_volume(nfs3state, handle, rqst, volume, status, label) \
+xlator_t *
+nfs3_fh_to_xlator (struct nfs3_state *nfs3, struct nfs3_fh *fh)
+{
+ xlator_t *vol = NULL;
+ struct nfs3_export *exp = NULL;
+
+ GF_VALIDATE_OR_GOTO (GF_NFS3, nfs3, out);
+ GF_VALIDATE_OR_GOTO (GF_NFS3, fh, out);
+
+ exp = __nfs3_get_export_by_exportid (nfs3, fh->exportid);
+ if (!exp)
+ goto out;
+
+ vol = exp->subvol;
+out:
+ return vol;
+}
+
+
+int
+nfs3_is_root_looked_up (struct nfs3_state *nfs3, struct nfs3_fh *rootfh)
+{
+ struct nfs3_export *exp = NULL;
+ int ret = 0;
+
+ GF_VALIDATE_OR_GOTO (GF_NFS3, nfs3, out);
+ GF_VALIDATE_OR_GOTO (GF_NFS3, rootfh, out);
+
+ exp = __nfs3_get_export_by_exportid (nfs3, rootfh->exportid);
+ if (!exp)
+ goto out;
+
+ ret = exp->rootlookedup;
+out:
+ return ret;
+}
+
+
+int
+nfs3_set_root_looked_up (struct nfs3_state *nfs3, struct nfs3_fh *rootfh)
+{
+ struct nfs3_export *exp = NULL;
+ int ret = 0;
+
+ GF_VALIDATE_OR_GOTO (GF_NFS3, nfs3, out);
+ GF_VALIDATE_OR_GOTO (GF_NFS3, rootfh, out);
+
+ exp = __nfs3_get_export_by_exportid (nfs3, rootfh->exportid);
+ if (!exp)
+ goto out;
+
+ exp->rootlookedup = 1;
+out:
+ return ret;
+}
+
+
+#define nfs3_map_fh_to_volume(nfs3state, handle, req, volume, status, label) \
do { \
- volume = nfs3_fh_to_xlator ((nfs3state)->exportslist, handle); \
+ char exportid[256], gfid[256]; \
+ rpc_transport_t *trans = NULL; \
+ volume = nfs3_fh_to_xlator ((nfs3state), handle); \
if (!volume) { \
- gf_log (GF_NFS3, GF_LOG_ERROR, "Failed to map " \
- "FH to vol"); \
+ uuid_unparse (handle->exportid, exportid); \
+ uuid_unparse (handle->gfid, gfid); \
+ trans = rpcsvc_request_transport (req); \
+ GF_LOG_OCCASIONALLY (nfs3state->occ_logger, \
+ GF_NFS3, GF_LOG_ERROR, "Failed to map " \
+ "FH to vol: client=%s, exportid=%s, " \
+ "gfid=%s", trans->peerinfo.identifier, \
+ exportid, gfid); \
+ GF_LOG_OCCASIONALLY (nfs3state->occ_logger, \
+ GF_NFS3, GF_LOG_ERROR, "Stale nfs " \
+ "client %s must be trying to connect to"\
+ " a deleted volume, please unmount it.",\
+ trans->peerinfo.identifier); \
status = NFS3ERR_STALE; \
goto label; \
} else { \
- gf_log (GF_NFS3, GF_LOG_TRACE, "FH to Volume: %s"\
- ,volume->name); \
+ gf_log (GF_NFS3, GF_LOG_TRACE, "FH to Volume:" \
+ "%s", volume->name); \
rpcsvc_request_set_private (req, volume); \
} \
} while (0); \
@@ -97,17 +239,29 @@
#define nfs3_validate_gluster_fh(handle, status, errlabel) \
do { \
- if ((handle)) { \
- if (!nfs3_fh_validate (handle)) { \
- status = NFS3ERR_BADHANDLE; \
- goto errlabel; \
- } \
+ if (!nfs3_fh_validate (handle)) { \
+ gf_log (GF_NFS3, GF_LOG_ERROR, "Bad Handle"); \
+ status = NFS3ERR_BADHANDLE; \
+ goto errlabel; \
} \
} while (0) \
#define nfs3_check_fh_resolve_status(cst, nfstat, erlabl) \
do { \
- if ((cst)->resolve_ret == -1) { \
+ xlator_t *xlatorp = NULL; \
+ char buf[256], gfid[256]; \
+ rpc_transport_t *trans = NULL; \
+ if ((cst)->resolve_ret < 0) { \
+ trans = rpcsvc_request_transport (cst->req); \
+ xlatorp = nfs3_fh_to_xlator (cst->nfs3state, \
+ &cst->resolvefh); \
+ uuid_unparse (cst->resolvefh.gfid, gfid); \
+ snprintf (buf, sizeof (buf), "(%s) %s : %s", \
+ trans->peerinfo.identifier, \
+ xlatorp ? xlatorp->name : "ERR", \
+ gfid ); \
+ gf_log (GF_NFS3, GF_LOG_ERROR, "%s: %s", \
+ strerror(cst->resolve_errno), buf); \
nfstat = nfs3_errno_to_nfsstat3 (cst->resolve_errno);\
goto erlabl; \
} \
@@ -115,32 +269,121 @@
#define nfs3_check_new_fh_resolve_status(cst, nfstat, erlabl) \
do { \
- if (((cst)->resolve_ret == -1) && \
+ xlator_t *xlatorp = NULL; \
+ char buf[256], gfid[256]; \
+ rpc_transport_t *trans = NULL; \
+ if (((cst)->resolve_ret < 0) && \
((cst)->resolve_errno != ENOENT)) { \
+ trans = rpcsvc_request_transport (cst->req); \
+ xlatorp = nfs3_fh_to_xlator (cst->nfs3state, \
+ &cst->resolvefh); \
+ uuid_unparse (cst->resolvefh.gfid, gfid); \
+ snprintf (buf, sizeof (buf), "(%s) %s : %s", \
+ trans->peerinfo.identifier, \
+ xlatorp ? xlatorp->name : "ERR", \
+ gfid); \
+ gf_log (GF_NFS3, GF_LOG_ERROR, "%s: %s", \
+ strerror(cst->resolve_errno), buf); \
nfstat = nfs3_errno_to_nfsstat3 (cs->resolve_errno);\
goto erlabl; \
} \
} while (0) \
+int
+__nfs3_get_volume_id (struct nfs3_state *nfs3, xlator_t *xl,
+ uuid_t volumeid)
+{
+ int ret = -1;
+ struct nfs3_export *exp = NULL;
+
+ GF_VALIDATE_OR_GOTO (GF_NFS3, nfs3, out);
+ GF_VALIDATE_OR_GOTO (GF_NFS3, xl, out);
+
+ list_for_each_entry (exp, &nfs3->exports, explist) {
+ if (exp->subvol == xl) {
+ uuid_copy (volumeid, exp->volumeid);
+ ret = 0;
+ goto out;
+ }
+ }
+
+out:
+ return ret;
+}
+
+
#define nfs3_funge_solaris_zerolen_fh(nfs3st, fhd, enam, nfsst, erl) \
do { \
xlator_t *fungexl = NULL; \
+ uuid_t zero = {0, }; \
fungexl =nfs_mntpath_to_xlator ((nfs3st)->exportslist,enam);\
if (!fungexl) { \
(nfsst) = NFS3ERR_NOENT; \
goto erl; \
} \
\
- (fhd)->xlatorid = nfs_xlator_to_xlid ((nfs3st)->exportslist, \
- fungexl); \
- (fhd)->gen = 0; \
- (fhd)->ino = 1; \
+ uuid_copy ((fhd)->gfid, zero); \
+ (fhd)->gfid[15] = 1; \
(enam) = NULL; \
+ if ((gf_nfs_dvm_off (nfs_state (nfs3st->nfsx)))) \
+ (fhd)->exportid[15] = nfs_xlator_to_xlid ((nfs3st)->exportslist, fungexl); \
+ else { \
+ if(__nfs3_get_volume_id ((nfs3st), fungexl, (fhd)->exportid) < 0) { \
+ (nfsst) = NFS3ERR_STALE; \
+ goto erl; \
+ } \
+ } \
+ } while (0) \
+
+
+#define nfs3_volume_started_check(nf3stt, vlm, rtval, erlbl) \
+ do { \
+ if ((!nfs_subvolume_started (nfs_state (nf3stt->nfsx), vlm))){\
+ gf_log (GF_NFS3, GF_LOG_ERROR, "Volume is disabled: %s",\
+ vlm->name); \
+ rtval = RPCSVC_ACTOR_IGNORE; \
+ goto erlbl; \
+ } \
} while (0) \
int
+nfs3_export_sync_trusted (struct nfs3_state *nfs3, uuid_t exportid)
+{
+ struct nfs3_export *exp = NULL;
+ int ret = 0;
+
+ GF_VALIDATE_OR_GOTO (GF_NFS3, nfs3, err);
+
+ exp = __nfs3_get_export_by_exportid (nfs3, exportid);
+ if (!exp)
+ goto err;
+
+ ret = exp->trusted_sync;
+err:
+ return ret;
+}
+
+
+int
+nfs3_export_write_trusted (struct nfs3_state *nfs3, uuid_t exportid)
+{
+ struct nfs3_export *exp = NULL;
+ int ret = 0;
+
+ GF_VALIDATE_OR_GOTO (GF_NFS3, nfs3, err);
+
+ exp = __nfs3_get_export_by_exportid (nfs3, exportid);
+ if (!exp)
+ goto err;
+
+ ret = exp->trusted_write;
+err:
+ return ret;
+}
+
+int
nfs3_solaris_zerolen_fh (struct nfs3_fh *fh, int fhlen)
{
if (!fh)
@@ -167,12 +410,15 @@ nfs3_call_state_init (struct nfs3_state *s, rpcsvc_request_t *req, xlator_t *v)
{
nfs3_call_state_t *cs = NULL;
- if ((!s) || (!req) || (!v))
- return NULL;
+ GF_VALIDATE_OR_GOTO (GF_NFS3, s, err);
+ GF_VALIDATE_OR_GOTO (GF_NFS3, req, err);
+ GF_VALIDATE_OR_GOTO (GF_NFS3, v, err);
cs = (nfs3_call_state_t *) mem_get (s->localpool);
- if (!cs)
+ if (!cs) {
+ gf_log (GF_NFS3, GF_LOG_ERROR, "out of memory");
return NULL;
+ }
memset (cs, 0, sizeof (*cs));
INIT_LIST_HEAD (&cs->entries.list);
@@ -182,42 +428,39 @@ nfs3_call_state_init (struct nfs3_state *s, rpcsvc_request_t *req, xlator_t *v)
cs->vol = v;
cs->nfsx = s->nfsx;
cs->nfs3state = s;
-
+err:
return cs;
}
void
nfs3_call_state_wipe (nfs3_call_state_t *cs)
{
- struct nfs3_state *nfs3 = NULL;
if (!cs)
return;
- nfs3 = cs->nfs3state;
if (cs->fd) {
- gf_log (GF_NFS3, GF_LOG_TRACE, "fd ref: %d", cs->fd->refcount);
+ gf_log (GF_NFS3, GF_LOG_TRACE, "fd 0x%lx ref: %d",
+ (long)cs->fd, cs->fd->refcount);
fd_unref (cs->fd);
}
- if (cs->resolve_dir_fd)
- fd_unref (cs->resolve_dir_fd);
-
- if (cs->resolventry)
- FREE (cs->resolventry);
+ GF_FREE (cs->resolventry);
- if (cs->pathname)
- FREE (cs->pathname);
+ GF_FREE (cs->pathname);
if (!list_empty (&cs->entries.list))
gf_dirent_free (&cs->entries);
- list_del (&cs->openwait_q);
nfs_loc_wipe (&cs->oploc);
nfs_loc_wipe (&cs->resolvedloc);
if (cs->iob)
iobuf_unref (cs->iob);
+ if (cs->iobref)
+ iobref_unref (cs->iobref);
+ if (cs->trans)
+ rpc_transport_unref (cs->trans);
memset (cs, 0, sizeof (*cs));
- mem_put (nfs3->localpool, cs);
+ mem_put (cs);
/* Already refd by fd_lookup, so no need to ref again. */
}
@@ -253,6 +496,8 @@ nfs3_serialize_reply (rpcsvc_request_t *req, void *arg, nfs3_serializer sfunc,
/* First, get the io buffer into which the reply in arg will
* be serialized.
*/
+ /* TODO: get rid of 'sfunc' and use 'xdrproc_t' so we
+ can have 'xdr_sizeof' */
iob = iobuf_get (nfs3->iobpool);
if (!iob) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Failed to get iobuf");
@@ -291,6 +536,7 @@ nfs3svc_submit_reply (rpcsvc_request_t *req, void *arg, nfs3_serializer sfunc)
struct iovec outmsg = {0, };
struct iobuf *iob = NULL;
int ret = -1;
+ struct iobref *iobref = NULL;
if (!req)
return -1;
@@ -301,14 +547,20 @@ nfs3svc_submit_reply (rpcsvc_request_t *req, void *arg, nfs3_serializer sfunc)
goto ret;
}
- /* Then, submit the message for transmission. */
- ret = rpcsvc_submit_message (req, outmsg, iob);
+ iobref = iobref_new ();
+ if (!iobref) {
+ gf_log (GF_NFS3, GF_LOG_ERROR, "failed on iobref_new()");
+ goto ret;
+ }
- /* Now that we've done our job of handing the message to the RPC layer
- * we can safely unref the iob in the hope that RPC layer must have
- * ref'ed the iob on receiving into the txlist.
- */
- iobuf_unref (iob);
+ ret = iobref_add (iobref, iob);
+ if (ret) {
+ gf_log (GF_NFS3, GF_LOG_ERROR, "Failed to add iob to iobref");
+ goto ret;
+ }
+
+ /* Then, submit the message for transmission. */
+ ret = rpcsvc_submit_message (req, &outmsg, 1, NULL, 0, iobref);
if (ret == -1) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Reply submission failed");
goto ret;
@@ -316,6 +568,14 @@ nfs3svc_submit_reply (rpcsvc_request_t *req, void *arg, nfs3_serializer sfunc)
ret = 0;
ret:
+ /* Now that we've done our job of handing the message to the RPC layer
+ * we can safely unref the iob in the hope that RPC layer must have
+ * ref'ed the iob on receiving into the txlist.
+ */
+ if (NULL != iob)
+ iobuf_unref (iob);
+ if (NULL != iobref)
+ iobref_unref (iobref);
return ret;
}
@@ -323,11 +583,12 @@ ret:
int
nfs3svc_submit_vector_reply (rpcsvc_request_t *req, void *arg,
nfs3_serializer sfunc, struct iovec *payload,
- struct iobref *piobref)
+ int vcount, struct iobref *iobref)
{
struct iovec outmsg = {0, };
struct iobuf *iob = NULL;
int ret = -1;
+ int new_iobref = 0;
if (!req)
return -1;
@@ -335,37 +596,64 @@ nfs3svc_submit_vector_reply (rpcsvc_request_t *req, void *arg,
iob = nfs3_serialize_reply (req, arg, sfunc, &outmsg);
if (!iob) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Failed to serialize reply");
- goto err;
+ goto ret;
+ }
+ if (iobref == NULL) {
+ iobref = iobref_new ();
+ if (!iobref) {
+ gf_log (GF_NFS3, GF_LOG_ERROR, "failed on iobref_new");
+ goto ret;
+ }
+ new_iobref = 1;
}
- ret = rpcsvc_request_attach_vector (req, outmsg, iob, NULL, 0);
- iobuf_unref (iob);
-
- if (piobref)
- ret = rpcsvc_request_attach_vector (req, *payload, NULL, piobref
- , 1);
+ ret = iobref_add (iobref, iob);
+ if (ret) {
+ gf_log (GF_NFS3, GF_LOG_ERROR, "Failed to add iob to iobref");
+ goto ret;
+ }
- if (ret == -1)
- goto err;
- ret = rpcsvc_submit_vectors (req);
-err:
+ /* Then, submit the message for transmission. */
+ ret = rpcsvc_submit_message (req, &outmsg, 1, payload, vcount, iobref);
+ if (ret == -1) {
+ gf_log (GF_NFS3, GF_LOG_ERROR, "Reply submission failed");
+ goto ret;
+ }
+ ret = 0;
+ret:
+ /* Now that we've done our job of handing the message to the RPC layer
+ * we can safely unref the iob in the hope that RPC layer must have
+ * ref'ed the iob on receiving into the txlist.
+ */
+ if (NULL != iob)
+ iobuf_unref (iob);
+ if (new_iobref)
+ iobref_unref (iobref);
return ret;
}
-
-uint16_t
-nfs3_request_xlator_id (rpcsvc_request_t *rq)
+uint64_t
+nfs3_request_xlator_deviceid (rpcsvc_request_t *rq)
{
struct nfs3_state *nfs3 = NULL;
xlator_t *xl = NULL;
+ uint64_t devid = 0;
+ uuid_t volumeid = {0, };
if (!rq)
return 0;
xl = rpcsvc_request_private (rq);
nfs3 = rpcsvc_request_program_private (rq);
- return nfs_xlator_to_xlid (nfs3->exportslist, xl);
+ if (gf_nfs_dvm_off (nfs_state (nfs3->nfsx)))
+ devid = (uint64_t)nfs_xlator_to_xlid (nfs3->exportslist, xl);
+ else {
+ __nfs3_get_volume_id (nfs3, xl, volumeid);
+ memcpy (&devid, &volumeid[8], sizeof (devid));
+ }
+
+ return devid;
}
@@ -375,8 +663,7 @@ nfs3svc_null (rpcsvc_request_t *req)
struct iovec dummyvec = {0, };
if (!req)
return RPCSVC_ACTOR_ERROR;
-
- rpcsvc_submit_generic (req, dummyvec, NULL);
+ rpcsvc_submit_generic (req, &dummyvec, 1, NULL, 0, NULL);
return RPCSVC_ACTOR_SUCCESS;
}
@@ -385,10 +672,10 @@ int
nfs3_getattr_reply (rpcsvc_request_t *req, nfsstat3 status, struct iatt *buf)
{
getattr3res res;
- uint16_t xlid = 0;
+ uint64_t deviceid = 0;
- xlid = nfs3_request_xlator_id (req);
- nfs3_fill_getattr3res (&res, status, buf, xlid);
+ deviceid = nfs3_request_xlator_deviceid (req);
+ nfs3_fill_getattr3res (&res, status, buf, deviceid);
nfs3svc_submit_reply (req, &res,
(nfs3_serializer)xdr_serialize_getattr3res);
@@ -402,18 +689,29 @@ nfs3svc_getattr_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
struct iatt *buf, dict_t *xattr,
struct iatt *postparent)
{
- rpcsvc_request_t *req = NULL;
nfsstat3 status = NFS3_OK;
nfs3_call_state_t *cs = NULL;
cs = frame->local;
- req = cs->req;
- if (op_ret == -1)
- status = nfs3_errno_to_nfsstat3 (op_errno);
+ /*
+ * Somewhat counter-intuitively, we don't need to look for sh-failed
+ * here. Failing this getattr will generate a new lookup from the
+ * client, and nfs_fop_lookup_cbk will detect any self-heal failures.
+ */
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "GETATTR", status,
- op_errno);
+ if (op_ret == -1) {
+ gf_log (GF_NFS, GF_LOG_WARNING,
+ "%x: %s => -1 (%s)", rpcsvc_request_xid (cs->req),
+ cs->resolvedloc.path, strerror (op_errno));
+ status = nfs3_cbk_errno_status (op_ret, op_errno);
+ }
+ else {
+ nfs_fix_generation(this,inode);
+ }
+
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_GETATTR,
+ status, op_errno);
nfs3_getattr_reply (cs->req, status, buf);
nfs3_call_state_wipe (cs);
@@ -424,20 +722,23 @@ nfs3svc_getattr_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t
nfs3svc_getattr_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno, struct iatt *buf)
+ int32_t op_ret, int32_t op_errno, struct iatt *buf,
+ dict_t *xdata)
{
- rpcsvc_request_t *req = NULL;
nfsstat3 status = NFS3_OK;
nfs3_call_state_t *cs = NULL;
cs = frame->local;
- req = cs->req;
- if (op_ret == -1)
- status = nfs3_errno_to_nfsstat3 (op_errno);
+ if (op_ret == -1) {
+ gf_log (GF_NFS, GF_LOG_WARNING,
+ "%x: %s => -1 (%s)", rpcsvc_request_xid (cs->req),
+ cs->resolvedloc.path, strerror (op_errno));
+ status = nfs3_cbk_errno_status (op_ret, op_errno);
+ }
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "GETATTR", status,
- op_errno);
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_GETATTR,
+ status, op_errno);
nfs3_getattr_reply (cs->req, status, buf);
nfs3_call_state_wipe (cs);
@@ -453,6 +754,9 @@ nfs3_getattr_resume (void *carg)
int ret = -EFAULT;
nfs_user_t nfu = {0, };
nfs3_call_state_t *cs = NULL;
+ uint64_t raw_ctx = 0;
+ struct nfs_inode_ctx *ictx = NULL;
+ struct nfs_state *priv = NULL;
if (!carg)
return ret;
@@ -465,14 +769,42 @@ nfs3_getattr_resume (void *carg)
* for the root to have been looked up when the getattr on the root is
* sent. AND, this causes a problem for stat-prefetch in that it
* expects even the root inode to have been looked up.
- */
- if (cs->resolvedloc.inode->ino == 1)
+
+ if (__is_root_gfid (cs->resolvedloc.inode->gfid))
ret = nfs_lookup (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
nfs3svc_getattr_lookup_cbk, cs);
else
ret = nfs_stat (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
- nfs3svc_getattr_stat_cbk, cs);
+ */
+
+ if (cs->hardresolved) {
+ ret = -EFAULT;
+ stat = NFS3_OK;
+ goto nfs3err;
+ }
+
+ /*
+ * If brick state changed, we need to force a proper lookup cycle (as
+ * would happen in native protocol) to do self-heal checks. We detect
+ * this by comparing the generation number for the last successful
+ * creation/lookup on the inode to the current number, so inodes that
+ * haven't been validated since the state change are affected.
+ */
+ if (inode_ctx_get(cs->resolvedloc.inode,cs->nfsx,&raw_ctx) == 0) {
+ ictx = (struct nfs_inode_ctx *)raw_ctx;
+ priv = cs->nfsx->private;
+ if (ictx->generation != priv->generation) {
+ ret = nfs_lookup (cs->nfsx, cs->vol, &nfu,
+ &cs->resolvedloc,
+ nfs3svc_getattr_lookup_cbk, cs);
+ goto check_err;
+ }
+ }
+
+ ret = nfs_stat (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
+ nfs3svc_getattr_stat_cbk, cs);
+check_err:
if (ret < 0) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Stat fop failed: %s: %s",
cs->oploc.path, strerror (-ret));
@@ -481,9 +813,9 @@ nfs3_getattr_resume (void *carg)
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "GETATTR",
- stat, -ret);
- nfs3_getattr_reply (cs->req, stat, NULL);
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req),
+ NFS3_GETATTR, stat, -ret);
+ nfs3_getattr_reply (cs->req, stat, &cs->stbuf);
nfs3_call_state_wipe (cs);
ret = 0;
}
@@ -501,13 +833,14 @@ nfs3_getattr (rpcsvc_request_t *req, struct nfs3_fh *fh)
struct nfs3_state *nfs3 = NULL;
nfs3_call_state_t *cstate = NULL;
- if ((!req) || (!fh))
- return -1;
+ GF_VALIDATE_OR_GOTO (GF_NFS3, req, out);
+ GF_VALIDATE_OR_GOTO (GF_NFS3, fh, out);
nfs3_log_common_call (rpcsvc_request_xid (req), "GETATTR", fh);
nfs3_validate_gluster_fh (fh, stat, nfs3err);
nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret);
nfs3_map_fh_to_volume (nfs3, fh, req, vol, stat, nfs3err);
+ nfs3_volume_started_check (nfs3, vol, ret, out);
nfs3_handle_call_state_init (nfs3, cstate, req, vol, stat, nfs3err);
ret = nfs3_fh_resolve_and_resume (cstate, fh, NULL,nfs3_getattr_resume);
@@ -516,13 +849,13 @@ nfs3_getattr (rpcsvc_request_t *req, struct nfs3_fh *fh)
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (req), "GETATTR", stat,
- -ret);
+ nfs3_log_common_res (rpcsvc_request_xid (req), NFS3_GETATTR,
+ stat, -ret);
nfs3_getattr_reply (req, stat, NULL);
ret = 0;
nfs3_call_state_wipe (cstate);
}
-
+out:
return ret;
}
@@ -538,14 +871,14 @@ nfs3svc_getattr (rpcsvc_request_t *req)
return ret;
nfs3_prep_getattr3args (&args, &fh);
- if (xdr_to_getattr3args (req->msg, &args) <= 0) {
+ if (xdr_to_getattr3args (req->msg[0], &args) <= 0) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Error decoding args");
rpcsvc_request_seterr (req, GARBAGE_ARGS);
goto rpcerr;
}
ret = nfs3_getattr (req, &fh);
- if (ret < 0) {
+ if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
gf_log (GF_NFS3, GF_LOG_ERROR, "GETATTR procedure failed");
rpcsvc_request_seterr (req, SYSTEM_ERR);
ret = RPCSVC_ACTOR_ERROR;
@@ -561,10 +894,10 @@ nfs3_setattr_reply (rpcsvc_request_t *req, nfsstat3 stat, struct iatt *preop,
struct iatt *postop)
{
setattr3res res = {0, };
- uint16_t xlid = 0;
+ uint64_t deviceid = 0;
- xlid = nfs3_request_xlator_id (req);
- nfs3_fill_setattr3res (&res, stat, preop, postop, xlid);
+ deviceid = nfs3_request_xlator_deviceid (req);
+ nfs3_fill_setattr3res (&res, stat, preop, postop, deviceid);
nfs3svc_submit_reply (req, (void *)&res,
(nfs3_serializer) xdr_serialize_setattr3res);
return 0;
@@ -574,7 +907,7 @@ nfs3_setattr_reply (rpcsvc_request_t *req, nfsstat3 stat, struct iatt *preop,
int32_t
nfs3svc_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, struct iatt *prebuf,
- struct iatt *postbuf)
+ struct iatt *postbuf, dict_t *xdata)
{
nfsstat3 stat = NFS3ERR_SERVERFAULT;
struct iatt *prestat = NULL;
@@ -582,7 +915,10 @@ nfs3svc_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
cs = frame->local;
if (op_ret == -1) {
- stat = nfs3_errno_to_nfsstat3 (op_errno);
+ gf_log (GF_NFS, GF_LOG_WARNING,
+ "%x: %s => -1 (%s)", rpcsvc_request_xid (cs->req),
+ cs->resolvedloc.path, strerror (op_errno));
+ stat = nfs3_cbk_errno_status (op_ret, op_errno);
goto nfs3err;
}
@@ -597,7 +933,7 @@ nfs3svc_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
stat = NFS3_OK;
nfs3err:
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "SETATTR", stat,
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_SETATTR, stat,
op_errno);
nfs3_setattr_reply (cs->req, stat, prestat, postbuf);
nfs3_call_state_wipe (cs);
@@ -609,7 +945,7 @@ nfs3err:
int32_t
nfs3svc_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, struct iatt *preop,
- struct iatt *postop)
+ struct iatt *postop, dict_t *xdata)
{
nfsstat3 stat = NFS3ERR_SERVERFAULT;
int ret = -1;
@@ -619,29 +955,25 @@ nfs3svc_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
cs = frame->local;
if (op_ret == -1) {
- stat = nfs3_errno_to_nfsstat3 (op_errno);
+ gf_log (GF_NFS, GF_LOG_WARNING,
+ "%x: %s => -1 (%s)", rpcsvc_request_xid (cs->req),
+ cs->resolvedloc.path, strerror (op_errno));
+ stat = nfs3_cbk_errno_status (op_ret, op_errno);
goto nfs3err;
}
- /* If the first stat was got from the guarded setattr callback, then
- * we'll need to use that stat instead of the preop returned here.
+ prebuf = preop;
+ /* Store the current preop in case we need to send a truncate,
+ * in which case the preop to be returned will be this one.
*/
- if (cs->preparent.ia_ino != 0)
- prebuf = &cs->preparent;
- else {
- prebuf = preop;
- /* Store the current preop in case we need to send a truncate,
- * in which case the preop to be returned will be this one.
- */
- cs->preparent = *preop;
- }
+ cs->preparent = *preop;
- ret = 0;
/* Only truncate if the size is not already same as the requested
* truncation and also only if this is not a directory.
*/
if ((gf_attr_size_set (cs->setattr_valid)) &&
- (!IA_ISDIR (postop->ia_type))) {
+ (!IA_ISDIR (postop->ia_type)) &&
+ (preop->ia_size != cs->stbuf.ia_size)) {
nfs_request_user_init (&nfu, cs->req);
ret = nfs_truncate (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
cs->stbuf.ia_size, nfs3svc_truncate_cbk,cs);
@@ -655,8 +987,8 @@ nfs3svc_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "SETATTR",
- stat, op_errno);
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req),
+ NFS3_SETATTR, stat, op_errno);
nfs3_setattr_reply (cs->req, stat, prebuf, postop);
nfs3_call_state_wipe (cs);
}
@@ -668,7 +1000,8 @@ nfs3err:
int32_t
nfs3svc_setattr_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno, struct iatt *buf)
+ int32_t op_ret, int32_t op_errno, struct iatt *buf,
+ dict_t *xdata)
{
int ret = -EFAULT;
@@ -678,12 +1011,15 @@ nfs3svc_setattr_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
cs = frame->local;
if (op_ret == -1) {
- stat = nfs3_errno_to_nfsstat3 (op_errno);
+ gf_log (GF_NFS, GF_LOG_WARNING,
+ "%x: %s => -1 (%s)", rpcsvc_request_xid (cs->req),
+ cs->resolvedloc.path, strerror (op_errno));
+ stat = nfs3_cbk_errno_status (op_ret, op_errno);
goto nfs3err;
}
if (buf->ia_ctime != cs->timestamp.seconds) {
- gf_log (GF_NFS3, GF_LOG_TRACE, "Timestamps not in sync");
+ gf_log (GF_NFS3, GF_LOG_ERROR, "Timestamps not in sync");
stat = NFS3ERR_NOT_SYNC;
goto nfs3err;
}
@@ -698,8 +1034,8 @@ nfs3svc_setattr_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "SETATTR",
- stat, op_errno);
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req),
+ NFS3_SETATTR, stat, op_errno);
nfs3_setattr_reply (cs->req, stat, NULL, NULL);
nfs3_call_state_wipe (cs);
}
@@ -722,22 +1058,17 @@ nfs3_setattr_resume (void *carg)
cs = (nfs3_call_state_t *)carg;
nfs3_check_fh_resolve_status (cs, stat, nfs3err);
nfs_request_user_init (&nfu, cs->req);
- /* If no ctime check is required, head straight to setting the attrs. */
- if (cs->sattrguardcheck)
- ret = nfs_stat (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
- nfs3svc_setattr_stat_cbk, cs);
- else
- ret = nfs_setattr (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
- &cs->stbuf, cs->setattr_valid,
- nfs3svc_setattr_cbk, cs);
+ ret = nfs_setattr (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
+ &cs->stbuf, cs->setattr_valid,
+ nfs3svc_setattr_cbk, cs);
if (ret < 0)
stat = nfs3_errno_to_nfsstat3 (-ret);
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "SETATTR",
- stat, -ret);
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req),
+ NFS3_SETATTR, stat, -ret);
nfs3_setattr_reply (cs->req, stat, NULL, NULL);
nfs3_call_state_wipe (cs);
}
@@ -756,16 +1087,17 @@ nfs3_setattr (rpcsvc_request_t *req, struct nfs3_fh *fh, sattr3 *sattr,
struct nfs3_state *nfs3 = NULL;
nfs3_call_state_t *cs = NULL;
- if ((!req) || (!fh) || (!sattr) || (!guard)) {
- gf_log (GF_NFS3, GF_LOG_ERROR, "Bad arguments");
- return -1;
- }
+ GF_VALIDATE_OR_GOTO (GF_NFS3, req, out);
+ GF_VALIDATE_OR_GOTO (GF_NFS3, fh, out);
+ GF_VALIDATE_OR_GOTO (GF_NFS3, sattr, out);
+ GF_VALIDATE_OR_GOTO (GF_NFS3, guard, out);
nfs3_log_common_call (rpcsvc_request_xid (req), "SETATTR", fh);
nfs3_validate_gluster_fh (fh, stat, nfs3err);
nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret);
nfs3_map_fh_to_volume (nfs3, fh, req, vol, stat, nfs3err);
- nfs3_check_rw_volaccess (nfs3, fh->xlatorid, stat, nfs3err);
+ nfs3_volume_started_check (nfs3, vol, ret, out);
+ nfs3_check_rw_volaccess (nfs3, fh->exportid, stat, nfs3err);
nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);
cs->setattr_valid = nfs3_sattr3_to_setattr_valid (sattr, &cs->stbuf,
@@ -782,6 +1114,7 @@ nfs3_setattr (rpcsvc_request_t *req, struct nfs3_fh *fh, sattr3 *sattr,
if (!cs->setattr_valid) {
ret = -EINVAL; /* Force a reply */
stat = NFS3_OK;
+ gf_log (GF_NFS3, GF_LOG_ERROR, "cs->setattr_valid is invalid");
goto nfs3err;
}
@@ -791,8 +1124,8 @@ nfs3_setattr (rpcsvc_request_t *req, struct nfs3_fh *fh, sattr3 *sattr,
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (req), "SETATTR", stat,
- -ret);
+ nfs3_log_common_res (rpcsvc_request_xid (req), NFS3_SETATTR,
+ stat, -ret);
nfs3_setattr_reply (req, stat, NULL, NULL);
nfs3_call_state_wipe (cs);
/* Ret must be 0 after this so that the caller does not
@@ -800,7 +1133,7 @@ nfs3err:
*/
ret = 0;
}
-
+out:
return ret;
}
@@ -813,18 +1146,17 @@ nfs3svc_setattr (rpcsvc_request_t *req)
setattr3args args;
int ret = RPCSVC_ACTOR_ERROR;
- if (!req)
- return ret;
+ GF_VALIDATE_OR_GOTO (GF_NFS3, req, rpcerr);
nfs3_prep_setattr3args (&args, &fh);
- if (xdr_to_setattr3args (req->msg, &args) <= 0) {
+ if (xdr_to_setattr3args (req->msg[0], &args) <= 0) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Error decoding args");
rpcsvc_request_seterr (req, GARBAGE_ARGS);
goto rpcerr;
}
ret = nfs3_setattr (req, &fh, &args.new_attributes, &args.guard);
- if (ret < 0) {
+ if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
gf_log (GF_NFS3, GF_LOG_ERROR, "SETATTR procedure failed");
rpcsvc_request_seterr (req, SYSTEM_ERR);
ret = RPCSVC_ACTOR_ERROR;
@@ -841,12 +1173,44 @@ nfs3_lookup_reply (rpcsvc_request_t *req, nfsstat3 stat, struct nfs3_fh *newfh,
struct iatt *stbuf, struct iatt *postparent)
{
lookup3res res = {0, };
+ uint64_t deviceid = 0;
- nfs3_fill_lookup3res (&res, stat, newfh, stbuf, postparent);
+ deviceid = nfs3_request_xlator_deviceid (req);
+ nfs3_fill_lookup3res (&res, stat, newfh, stbuf, postparent, deviceid);
return nfs3svc_submit_reply (req, &res,
(nfs3_serializer)xdr_serialize_lookup3res);
}
+int
+nfs3_lookup_resume (void *carg);
+
+
+int
+nfs3_fresh_lookup (nfs3_call_state_t *cs)
+{
+ int ret = -EFAULT;
+ char *oldresolventry = NULL;
+
+ GF_VALIDATE_OR_GOTO (GF_NFS3, cs, err);
+ gf_log (GF_NFS3, GF_LOG_DEBUG, "inode needs fresh lookup");
+ inode_unlink (cs->resolvedloc.inode, cs->resolvedloc.parent,
+ cs->resolventry);
+ nfs_loc_wipe (&cs->resolvedloc);
+
+ /* Store pointer to currently allocated resolventry because it gets over
+ * written in fh_resolve_and_resume.
+ */
+ oldresolventry = cs->resolventry;
+ cs->lookuptype = GF_NFS3_FRESH;
+ ret = nfs3_fh_resolve_and_resume (cs, &cs->resolvefh, cs->resolventry,
+ nfs3_lookup_resume);
+ /* Allocated in the previous call to fh_resolve_and_resume using the
+ * same call_state.
+ */
+ GF_FREE (oldresolventry);
+err:
+ return ret;
+}
int
nfs3svc_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
@@ -856,21 +1220,37 @@ nfs3svc_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
struct nfs3_fh newfh = {{0}, };
nfsstat3 status = NFS3_OK;
nfs3_call_state_t *cs = NULL;
+ inode_t *oldinode = NULL;
cs = frame->local;
if (op_ret == -1) {
- status = nfs3_errno_to_nfsstat3 (op_errno);
+ gf_log (GF_NFS,
+ (op_errno == ENOENT ? GF_LOG_TRACE : GF_LOG_WARNING),
+ "%x: %s => -1 (%s)", rpcsvc_request_xid (cs->req),
+ cs->resolvedloc.path, strerror (op_errno));
+ status = nfs3_cbk_errno_status (op_ret, op_errno);
goto xmit_res;
}
nfs3_fh_build_child_fh (&cs->parent, buf, &newfh);
-
+ oldinode = inode_link (inode, cs->resolvedloc.parent,
+ cs->resolvedloc.name, buf);
xmit_res:
- nfs3_log_newfh_res (rpcsvc_request_xid (cs->req), "LOOKUP", status,
+ /* Only send fresh lookup if it was a revalidate that failed. */
+ if ((op_ret == -1) && (nfs3_is_revalidate_lookup (cs))) {
+ op_ret = nfs3_fresh_lookup (cs);
+ goto out;
+ }
+
+ nfs3_log_newfh_res (rpcsvc_request_xid (cs->req), NFS3_LOOKUP, status,
op_errno, &newfh);
nfs3_lookup_reply (cs->req, status, &newfh, buf, postparent);
nfs3_call_state_wipe (cs);
-
+out:
+ if (oldinode) {
+ inode_lookup (oldinode);
+ inode_unref (oldinode);
+ }
return 0;
}
@@ -884,17 +1264,38 @@ nfs3svc_lookup_parentdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
struct nfs3_fh newfh = {{0}, };
nfsstat3 status = NFS3_OK;
nfs3_call_state_t *cs = NULL;
+ uuid_t volumeid = {0, };
+ struct nfs3_state *nfs3 = NULL;
cs = frame->local;
if (op_ret == -1) {
- status = nfs3_errno_to_nfsstat3 (op_errno);
+ gf_log (GF_NFS, GF_LOG_WARNING,
+ "%x: %s => -1 (%s)", rpcsvc_request_xid (cs->req),
+ cs->resolvedloc.path, strerror (op_errno));
+ status = nfs3_cbk_errno_status (op_ret, op_errno);
goto xmit_res;
}
- nfs3_fh_build_parent_fh (&cs->fh, buf, &newfh);
+ nfs3 = cs->nfs3state;
+ /* If the buf inode shows that this is a root dir's buf, then the file
+ * handle needs to be specially crafted, in all other cases, we'll just
+ * create the handle normally using the buffer of the parent dir.
+ */
+ if (buf->ia_ino != 1) {
+ nfs3_fh_build_parent_fh (&cs->fh, buf, &newfh);
+ goto xmit_res;
+ }
+
+ if (gf_nfs_dvm_off (nfs_state (nfs3->nfsx)))
+ newfh = nfs3_fh_build_indexed_root_fh (nfs3->exportslist,
+ cs->vol);
+ else {
+ __nfs3_get_volume_id (nfs3, cs->vol, volumeid);
+ newfh = nfs3_fh_build_uuid_root_fh (volumeid);
+ }
xmit_res:
- nfs3_log_newfh_res (rpcsvc_request_xid (cs->req), "LOOKUP", status,
+ nfs3_log_newfh_res (rpcsvc_request_xid (cs->req), NFS3_LOOKUP, status,
op_errno, &newfh);
nfs3_lookup_reply (cs->req, status, &newfh, buf, postparent);
nfs3_call_state_wipe (cs);
@@ -913,8 +1314,11 @@ nfs3_lookup_parentdir_resume (void *carg)
nfs3_call_state_t *cs = NULL;
inode_t *parent = NULL;
- if (!carg)
- return ret;
+ if (!carg) {
+ gf_log (GF_NFS3, GF_LOG_ERROR, "Invalid argument,"
+ " carg value NULL");
+ return EINVAL;
+ }
cs = (nfs3_call_state_t *)carg;
nfs3_check_fh_resolve_status (cs, stat, nfs3err);
@@ -922,18 +1326,38 @@ nfs3_lookup_parentdir_resume (void *carg)
/* At this point now, the loc in cs is for the directory file handle
* sent by the client. This loc needs to be transformed into a loc that
* represents the parent dir of cs->resolvedloc.inode.
+ *
+ * EXCEPT in the case where the .. is a parent of the root directory.
+ * In this case we'll be returning the file handle and attributes of the
+ * root itself.
*/
nfs_request_user_init (&nfu, cs->req);
/* Save the file handle from the LOOKUP request. We'll use this to
- * build the file handle of the parent directory.
+ * build the file handle of the parent directory in case the parent is
+ * not root dir.
*/
cs->fh = cs->resolvefh;
- parent = inode_ref (cs->resolvedloc.parent);
- nfs_loc_wipe (&cs->resolvedloc);
- ret = nfs_inode_loc_fill (parent, &cs->resolvedloc);
- if (ret < 0)
- goto errtostat;
+
+ /* If fh is that of the root, the resolvedloc will already contain
+ * the loc for root. After that, we'll send lookup for the root dir
+ * itself since we cannot send the lookup on the parent of root.
+ *
+ * For all other cases, we'll send the lookup on the parent of the
+ * given directory file handle.
+ */
+ if (!nfs3_fh_is_root_fh (&cs->fh)) {
+ parent = inode_ref (cs->resolvedloc.parent);
+ nfs_loc_wipe (&cs->resolvedloc);
+ ret = nfs_inode_loc_fill (parent, &cs->resolvedloc,
+ NFS_RESOLVE_CREATE);
+
+ if (ret < 0) {
+ gf_log (GF_NFS3, GF_LOG_ERROR, "nfs_inode_loc_fill"
+ " error");
+ goto errtostat;
+ }
+ }
ret = nfs_lookup (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
nfs3svc_lookup_parentdir_cbk, cs);
@@ -943,7 +1367,7 @@ errtostat:
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "LOOKUP",
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_LOOKUP,
stat, -ret);
nfs3_lookup_reply (cs->req, stat, NULL, NULL, NULL);
nfs3_call_state_wipe (cs);
@@ -963,14 +1387,25 @@ nfs3_lookup_resume (void *carg)
int ret = -EFAULT;
nfs_user_t nfu = {0, };
nfs3_call_state_t *cs = NULL;
+ struct nfs3_fh newfh = {{0},};
- if (!carg)
- return ret;
+ if (!carg) {
+ gf_log (GF_NFS3, GF_LOG_ERROR, "Invalid argument,"
+ " carg value NULL");
+ return EINVAL;
+ }
cs = (nfs3_call_state_t *)carg;
nfs3_check_fh_resolve_status (cs, stat, nfs3err);
- nfs_request_user_init (&nfu, cs->req);
cs->parent = cs->resolvefh;
+
+ if (cs->hardresolved) {
+ stat = NFS3_OK;
+ nfs3_fh_build_child_fh (&cs->parent, &cs->stbuf, &newfh);
+ goto nfs3err;
+ }
+
+ nfs_request_user_init (&nfu, cs->req);
ret = nfs_lookup (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
nfs3svc_lookup_cbk, cs);
if (ret < 0)
@@ -978,9 +1413,10 @@ nfs3_lookup_resume (void *carg)
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "LOOKUP",
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_LOOKUP,
stat, -ret);
- nfs3_lookup_reply (cs->req, stat, NULL, NULL, NULL);
+ nfs3_lookup_reply (cs->req, stat, &newfh, &cs->stbuf,
+ &cs->postparent);
nfs3_call_state_wipe (cs);
}
@@ -989,21 +1425,6 @@ nfs3err:
int
-nfs3_is_parentdir_entry (char *entry)
-{
- int ret = 0;
-
- if (!entry)
- return 0;
-
- if (strcmp (entry, "..") == 0)
- ret = 1;
-
- return ret;
-}
-
-
-int
nfs3_lookup (rpcsvc_request_t *req, struct nfs3_fh *fh, int fhlen, char *name)
{
xlator_t *vol = NULL;
@@ -1012,12 +1433,12 @@ nfs3_lookup (rpcsvc_request_t *req, struct nfs3_fh *fh, int fhlen, char *name)
struct nfs3_state *nfs3 = NULL;
nfs3_call_state_t *cs = NULL;
- if ((!req) || (!fh) || (!name)) {
- gf_log (GF_NFS3, GF_LOG_ERROR, "Bad arguments");
- return -1;
- }
+ GF_VALIDATE_OR_GOTO (GF_NFS3, req, out);
+ GF_VALIDATE_OR_GOTO (GF_NFS3, fh, out);
+ GF_VALIDATE_OR_GOTO (GF_NFS3, name, out);
- nfs3_log_fh_entry_call (rpcsvc_request_xid (req), "LOOKUP", fh, name);
+ nfs3_log_fh_entry_call (rpcsvc_request_xid (req), "LOOKUP", fh,
+ name);
nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret);
if (nfs3_solaris_zerolen_fh (fh, fhlen))
nfs3_funge_solaris_zerolen_fh (nfs3, fh, name, stat, nfs3err);
@@ -1025,21 +1446,22 @@ nfs3_lookup (rpcsvc_request_t *req, struct nfs3_fh *fh, int fhlen, char *name)
nfs3_validate_gluster_fh (fh, stat, nfs3err);
nfs3_validate_strlen_or_goto (name, NFS_NAME_MAX, nfs3err, stat, ret);
nfs3_map_fh_to_volume (nfs3, fh, req, vol, stat, nfs3err);
+ nfs3_volume_started_check (nfs3, vol, ret, out);
nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);
- if (!nfs3_is_parentdir_entry (name))
- ret = nfs3_fh_resolve_and_resume (cs, fh, name,
- nfs3_lookup_resume);
- else
- ret = nfs3_fh_resolve_and_resume (cs, fh, NULL,
- nfs3_lookup_parentdir_resume);
+ cs->lookuptype = GF_NFS3_REVALIDATE;
+ ret = nfs3_fh_resolve_and_resume (cs, fh, name,
+ nfs3_lookup_resume);
- if (ret < 0)
+ if (ret < 0) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "failed to start hard reslove");
stat = nfs3_errno_to_nfsstat3 (-ret);
+ }
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (req), "LOOKUP", stat,
+ nfs3_log_common_res (rpcsvc_request_xid (req), NFS3_LOOKUP,
+ stat,
-ret);
nfs3_lookup_reply (req, stat, NULL, NULL, NULL);
nfs3_call_state_wipe (cs);
@@ -1048,7 +1470,7 @@ nfs3err:
*/
ret = 0;
}
-
+out:
return ret;
}
@@ -1061,18 +1483,17 @@ nfs3svc_lookup (rpcsvc_request_t *req)
lookup3args args;
int ret = RPCSVC_ACTOR_ERROR;
- if (!req)
- return ret;
+ GF_VALIDATE_OR_GOTO (GF_NFS, req, rpcerr);
nfs3_prep_lookup3args (&args, &fh, name);
- if (xdr_to_lookup3args (req->msg, &args) <= 0) {
+ if (xdr_to_lookup3args (req->msg[0], &args) <= 0) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Error decoding args");
rpcsvc_request_seterr (req, GARBAGE_ARGS);
goto rpcerr;
}
ret = nfs3_lookup (req, &fh, args.what.dir.data.data_len, name);
- if (ret < 0) {
+ if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
gf_log (GF_NFS3, GF_LOG_ERROR, "LOOKUP procedure failed");
rpcsvc_request_seterr (req, SYSTEM_ERR);
ret = RPCSVC_ACTOR_ERROR;
@@ -1084,16 +1505,12 @@ rpcerr:
int
-nfs3_access_reply (rpcsvc_request_t *req, nfsstat3 status, struct iatt *buf,
- uint32_t accbits)
+nfs3_access_reply (rpcsvc_request_t *req, nfsstat3 status, int32_t accbits,
+ int32_t reqaccbits)
{
access3res res;
- uint16_t xlid = 0;
- xlid = nfs3_request_xlator_id (req);
- nfs3_fill_access3res (&res, status, buf, accbits,
- rpcsvc_request_uid (req), rpcsvc_request_gid (req)
- , xlid);
+ nfs3_fill_access3res (&res, status, accbits, reqaccbits);
nfs3svc_submit_reply (req, &res,
(nfs3_serializer)xdr_serialize_access3res);
return 0;
@@ -1102,19 +1519,22 @@ nfs3_access_reply (rpcsvc_request_t *req, nfsstat3 status, struct iatt *buf,
int32_t
nfs3svc_access_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno, struct iatt *buf)
+ int32_t op_ret, int32_t op_errno, dict_t *xdata)
{
nfsstat3 status = NFS3_OK;
nfs3_call_state_t *cs = NULL;
cs = frame->local;
- if (op_ret == -1)
- status = nfs3_errno_to_nfsstat3 (op_errno);
-
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "ACCESS", status,
+ if (op_ret == -1) {
+ gf_log (GF_NFS, GF_LOG_WARNING,
+ "%x: %s => -1 (%s)", rpcsvc_request_xid (cs->req),
+ cs->resolvedloc.path, strerror (op_errno));
+ status = nfs3_cbk_errno_status (op_ret, op_errno);
+ }
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_ACCESS, status,
op_errno);
- nfs3_access_reply (cs->req, status, buf, cs->accessbits);
+ nfs3_access_reply (cs->req, status, op_errno, cs->accessbits);
nfs3_call_state_wipe (cs);
return 0;
@@ -1128,23 +1548,26 @@ nfs3_access_resume (void *carg)
nfs_user_t nfu = {0, };
nfs3_call_state_t *cs = NULL;
- if (!carg)
- return ret;
+ if (!carg) {
+ gf_log (GF_NFS3, GF_LOG_ERROR, "Invalid argument,"
+ " carg value NULL");
+ return EINVAL;
+ }
cs = (nfs3_call_state_t *)carg;
nfs3_check_fh_resolve_status (cs, stat, nfs3err);
cs->fh = cs->resolvefh;
nfs_request_user_init (&nfu, cs->req);
- ret = nfs_stat (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
- nfs3svc_access_cbk, cs);
+ ret = nfs_access (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
+ cs->accessbits, nfs3svc_access_cbk, cs);
if (ret < 0)
stat = nfs3_errno_to_nfsstat3 (-ret);
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "ACCESS",
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_ACCESS,
stat, -ret);
- nfs3_access_reply (cs->req, stat, NULL, 0);
+ nfs3_access_reply (cs->req, stat, 0, 0);
nfs3_call_state_wipe (cs);
ret = 0;
}
@@ -1162,13 +1585,13 @@ nfs3_access (rpcsvc_request_t *req, struct nfs3_fh *fh, uint32_t accbits)
int ret = -EFAULT;
nfs3_call_state_t *cs = NULL;
- if ((!req) || (!fh))
- return -1;
-
+ GF_VALIDATE_OR_GOTO (GF_NFS, req, out);
+ GF_VALIDATE_OR_GOTO (GF_NFS, fh, out);
nfs3_log_common_call (rpcsvc_request_xid (req), "ACCESS", fh);
nfs3_validate_gluster_fh (fh, stat, nfs3err);
nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret);
nfs3_map_fh_to_volume (nfs3, fh, req, vol, stat, nfs3err);
+ nfs3_volume_started_check (nfs3, vol, ret, out);
nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);
cs->accessbits = accbits;
@@ -1178,13 +1601,13 @@ nfs3_access (rpcsvc_request_t *req, struct nfs3_fh *fh, uint32_t accbits)
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (req), "ACCESS", stat,
- -ret);
- nfs3_access_reply (req, stat, NULL, 0);
+ nfs3_log_common_res (rpcsvc_request_xid (req), NFS3_ACCESS,
+ stat, -ret);
+ nfs3_access_reply (req, stat, 0, 0);
nfs3_call_state_wipe (cs);
ret = 0;
}
-
+out:
return ret;
}
@@ -1200,14 +1623,14 @@ nfs3svc_access (rpcsvc_request_t *req)
return ret;
nfs3_prep_access3args (&args, &fh);
- if (xdr_to_access3args (req->msg, &args) <= 0) {
+ if (xdr_to_access3args (req->msg[0], &args) <= 0) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Error decoding args");
rpcsvc_request_seterr (req, GARBAGE_ARGS);
goto rpcerr;
}
ret = nfs3_access (req, &fh, args.access);
- if (ret < 0) {
+ if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
gf_log (GF_NFS3, GF_LOG_ERROR, "ACCESS procedure failed");
rpcsvc_request_seterr (req, SYSTEM_ERR);
ret = RPCSVC_ACTOR_ERROR;
@@ -1223,10 +1646,10 @@ nfs3_readlink_reply (rpcsvc_request_t *req, nfsstat3 stat, char *path,
struct iatt *buf)
{
readlink3res res = {0, };
- uint16_t xlid = 0;
+ uint64_t deviceid = 0;
- xlid = nfs3_request_xlator_id (req);
- nfs3_fill_readlink3res (&res, stat, path, buf, xlid);
+ deviceid = nfs3_request_xlator_deviceid (req);
+ nfs3_fill_readlink3res (&res, stat, path, buf, deviceid);
nfs3svc_submit_reply (req, (void *)&res,
(nfs3_serializer)xdr_serialize_readlink3res);
@@ -1237,14 +1660,17 @@ nfs3_readlink_reply (rpcsvc_request_t *req, nfsstat3 stat, char *path,
int32_t
nfs3svc_readlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, const char *path,
- struct iatt *buf)
+ struct iatt *buf, dict_t *xdata)
{
nfsstat3 stat = NFS3ERR_SERVERFAULT;
nfs3_call_state_t *cs = NULL;
cs = frame->local;
if (op_ret == -1) {
- stat = nfs3_errno_to_nfsstat3 (op_errno);
+ gf_log (GF_NFS, GF_LOG_WARNING,
+ "%x: %s => -1 (%s)", rpcsvc_request_xid (cs->req),
+ cs->resolvedloc.path, strerror (op_errno));
+ stat = nfs3_cbk_errno_status (op_ret, op_errno);
goto nfs3err;
}
@@ -1281,8 +1707,8 @@ nfs3_readlink_resume (void *carg)
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "READLINK",
- stat, -ret);
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req),
+ NFS3_READLINK, stat, -ret);
nfs3_readlink_reply (cs->req, stat, NULL, NULL);
nfs3_call_state_wipe (cs);
}
@@ -1309,6 +1735,7 @@ nfs3_readlink (rpcsvc_request_t *req, struct nfs3_fh *fh)
nfs3_validate_gluster_fh (fh, stat, nfs3err);
nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret);
nfs3_map_fh_to_volume (nfs3, fh, req, vol, stat, nfs3err);
+ nfs3_volume_started_check (nfs3, vol, ret, out);
nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);
ret = nfs3_fh_resolve_and_resume (cs, fh, NULL, nfs3_readlink_resume);
@@ -1317,8 +1744,8 @@ nfs3_readlink (rpcsvc_request_t *req, struct nfs3_fh *fh)
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (req), "READLINK", stat,
- -ret);
+ nfs3_log_common_res (rpcsvc_request_xid (req), NFS3_READLINK,
+ stat, -ret);
nfs3_readlink_reply (req, stat, NULL, NULL);
nfs3_call_state_wipe (cs);
/* Ret must be 0 after this so that the caller does not
@@ -1326,7 +1753,7 @@ nfs3err:
*/
ret = 0;
}
-
+out:
return ret;
}
@@ -1342,14 +1769,14 @@ nfs3svc_readlink (rpcsvc_request_t *req)
return ret;
nfs3_prep_readlink3args (&args, &fh);
- if (xdr_to_readlink3args (req->msg, &args) <= 0) {
+ if (xdr_to_readlink3args (req->msg[0], &args) <= 0) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Error decoding args");
rpcsvc_request_seterr (req, GARBAGE_ARGS);
goto rpcerr;
}
ret = nfs3_readlink (req, &fh);
- if (ret < 0) {
+ if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
gf_log (GF_NFS3, GF_LOG_ERROR, "READLINK procedure failed");
rpcsvc_request_seterr (req, SYSTEM_ERR);
ret = RPCSVC_ACTOR_ERROR;
@@ -1361,27 +1788,29 @@ rpcerr:
int
-nfs3_read_reply (rpcsvc_request_t *req, nfsstat3 stat,
- count3 count, struct iovec *vec, struct iobref *iobref,
+nfs3_read_reply (rpcsvc_request_t *req, nfsstat3 stat, count3 count,
+ struct iovec *vec, int vcount, struct iobref *iobref,
struct iatt *poststat, int is_eof)
{
read3res res = {0, };
- uint16_t xlid = 0;
+ uint64_t deviceid = 0;
- xlid = nfs3_request_xlator_id (req);
- nfs3_fill_read3res (&res, stat, count, poststat, is_eof, xlid);
+ deviceid = nfs3_request_xlator_deviceid (req);
+ nfs3_fill_read3res (&res, stat, count, poststat, is_eof, deviceid);
if (stat == NFS3_OK) {
+ xdr_vector_round_up (vec, vcount, count);
/* iob can be zero if the file size was zero. If so, op_ret
* would be 0 and count = 0.
*/
+
if (count != 0) {
- xdr_bytes_round_up (vec, 1048576);
nfs3svc_submit_vector_reply (req, (void *)&res,
(nfs3_serializer)
xdr_serialize_read3res_nocopy,
- vec, iobref);
+ vec, vcount, iobref);
} else
- nfs3svc_submit_reply (req, (void *)&res,
+
+ nfs3svc_submit_reply (req, (void *)&res,
(nfs3_serializer)
xdr_serialize_read3res_nocopy);
} else
@@ -1396,7 +1825,8 @@ nfs3_read_reply (rpcsvc_request_t *req, nfsstat3 stat,
int32_t
nfs3svc_read_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, struct iovec *vector,
- int32_t count, struct iatt *stbuf, struct iobref *iobref)
+ int32_t count, struct iatt *stbuf, struct iobref *iobref,
+ dict_t *xdata)
{
nfsstat3 stat = NFS3ERR_SERVERFAULT;
int is_eof = 0;
@@ -1404,7 +1834,10 @@ nfs3svc_read_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
cs = frame->local;
if (op_ret == -1) {
- stat = nfs3_errno_to_nfsstat3 (op_errno);
+ gf_log (GF_NFS, GF_LOG_WARNING,
+ "%x: %s => -1 (%s)", rpcsvc_request_xid (cs->req),
+ cs->resolvedloc.path, strerror (op_errno));
+ stat = nfs3_cbk_errno_status (op_ret, op_errno);
goto err;
} else
stat = NFS3_OK;
@@ -1414,8 +1847,9 @@ nfs3svc_read_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
err:
nfs3_log_read_res (rpcsvc_request_xid (cs->req), stat, op_errno,
- op_ret, is_eof);
- nfs3_read_reply (cs->req, stat, op_ret, vector, iobref, stbuf, is_eof);
+ op_ret, is_eof, vector, count);
+ nfs3_read_reply (cs->req, stat, op_ret, vector, count, iobref, stbuf,
+ is_eof);
nfs3_call_state_wipe (cs);
return 0;
@@ -1442,9 +1876,9 @@ nfs3_read_fd_resume (void *carg)
stat = nfs3_errno_to_nfsstat3 (-ret);
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "READ", stat,
- -ret);
- nfs3_read_reply (cs->req, stat, 0, NULL, NULL, NULL, 0);
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_READ,
+ stat, -ret);
+ nfs3_read_reply (cs->req, stat, 0, NULL, 0, NULL, NULL, 0);
nfs3_call_state_wipe (cs);
}
@@ -1458,21 +1892,27 @@ nfs3_read_resume (void *carg)
nfsstat3 stat = NFS3ERR_SERVERFAULT;
int ret = -EFAULT;
nfs3_call_state_t *cs = NULL;
+ fd_t *fd = NULL;
if (!carg)
return ret;
cs = (nfs3_call_state_t *)carg;
nfs3_check_fh_resolve_status (cs, stat, nfs3err);
- ret = nfs3_file_open_and_resume (cs, nfs3_read_fd_resume);
- if (ret < 0)
- stat = nfs3_errno_to_nfsstat3 (-ret);
+ fd = fd_anonymous (cs->resolvedloc.inode);
+ if (!fd) {
+ gf_log (GF_NFS3, GF_LOG_ERROR, "Failed to create anonymous fd");
+ goto nfs3err;
+ }
+ cs->fd = fd;
+ nfs3_read_fd_resume (cs);
+ ret = 0;
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "READ", stat,
- -ret);
- nfs3_read_reply (cs->req, stat, 0, NULL, NULL, NULL, 0);
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_READ,
+ stat, -ret);
+ nfs3_read_reply (cs->req, stat, 0, NULL,0, NULL, NULL, 0);
nfs3_call_state_wipe (cs);
}
@@ -1494,11 +1934,12 @@ nfs3_read (rpcsvc_request_t *req, struct nfs3_fh *fh, offset3 offset,
return -1;
}
- nfs3_log_rw_call (rpcsvc_request_xid (req), "READ", fh, offset, count,
- -1);
+ nfs3_log_rw_call (rpcsvc_request_xid (req), "READ", fh, offset,
+ count, -1);
nfs3_validate_gluster_fh (fh, stat, nfs3err);
nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret);
nfs3_map_fh_to_volume (nfs3, fh, req, vol, stat, nfs3err);
+ nfs3_volume_started_check (nfs3, vol, ret, out);
nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);
cs->datacount = count;
@@ -1509,13 +1950,13 @@ nfs3_read (rpcsvc_request_t *req, struct nfs3_fh *fh, offset3 offset,
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (req), "READ", stat,
+ nfs3_log_common_res (rpcsvc_request_xid (req), NFS3_READ, stat,
-ret);
- nfs3_read_reply (req, stat, 0, NULL, NULL, NULL, 0);
+ nfs3_read_reply (req, stat, 0, NULL,0, NULL, NULL, 0);
nfs3_call_state_wipe (cs);
ret = 0;
}
-
+out:
return ret;
}
@@ -1531,14 +1972,14 @@ nfs3svc_read (rpcsvc_request_t *req)
return ret;
nfs3_prep_read3args (&args, &fh);
- if (xdr_to_read3args (req->msg, &args) <= 0) {
+ if (xdr_to_read3args (req->msg[0], &args) <= 0) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Error decoding args");
rpcsvc_request_seterr (req, GARBAGE_ARGS);
goto rpcerr;
}
ret = nfs3_read (req, &fh, args.offset, args.count);
- if (ret < 0) {
+ if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
gf_log (GF_NFS3, GF_LOG_ERROR, "READ procedure failed");
rpcsvc_request_seterr (req, SYSTEM_ERR);
ret = RPCSVC_ACTOR_ERROR;
@@ -1555,11 +1996,11 @@ nfs3_write_reply (rpcsvc_request_t *req, nfsstat3 stat, count3 count,
struct iatt *poststat)
{
write3res res = {0, };
- uint16_t xlid = 0;
+ uint64_t deviceid = 0;
- xlid = nfs3_request_xlator_id (req);
+ deviceid = nfs3_request_xlator_deviceid (req);
nfs3_fill_write3res (&res, stat, count, stable, wverf, prestat,
- poststat, xlid);
+ poststat, deviceid);
nfs3svc_submit_reply (req, (void *)&res,
(nfs3_serializer)xdr_serialize_write3res);
@@ -1569,7 +2010,7 @@ nfs3_write_reply (rpcsvc_request_t *req, nfsstat3 stat, count3 count,
int32_t
nfs3svc_write_fsync_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, struct iatt *prebuf,
- struct iatt *postbuf)
+ struct iatt *postbuf, dict_t *xdata)
{
struct nfs3_state *nfs3 = NULL;
nfsstat3 stat = NFS3ERR_SERVERFAULT;
@@ -1578,9 +2019,12 @@ nfs3svc_write_fsync_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
cs = frame->local;
nfs3 = rpcsvc_request_program_private (cs->req);
- if (op_ret == -1)
- stat = nfs3_errno_to_nfsstat3 (op_errno);
- else
+ if (op_ret == -1) {
+ gf_log (GF_NFS, GF_LOG_WARNING,
+ "%x: %s => -1 (%s)", rpcsvc_request_xid (cs->req),
+ cs->resolvedloc.path, strerror (op_errno));
+ stat = nfs3_cbk_errno_status (op_ret, op_errno);
+ } else
stat = NFS3_OK;
nfs3_log_write_res (rpcsvc_request_xid (cs->req), stat, op_errno,
@@ -1592,52 +2036,68 @@ nfs3svc_write_fsync_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
}
+
+/*
+ * Before going into the write reply logic, here is a matrix that shows the
+ * requirements for a write reply as given by RFC1813.
+ *
+ * Requested Write Type || Possible Returns
+ * ==============================================
+ * FILE_SYNC || FILE_SYNC
+ * DATA_SYNC || DATA_SYNC or FILE_SYNC
+ * UNSTABLE || DATA_SYNC or FILE_SYNC or UNSTABLE
+ *
+ * Write types other than UNSTABLE are together called STABLE.
+ * RS - Return Stable
+ * RU - Return Unstable
+ * WS - Write Stable
+ * WU - Write Unstable
+ *
+ *+============================================+
+ *| Vol Opts -> || trusted-write| trusted-sync |
+ *| Write Type || | |
+ *|-------------||--------------|--------------|
+ *| STABLE || WS | WU |
+ *| || RS | RS |
+ *|-------------||--------------|--------------|
+ *| UNSTABLE || WU | WU |
+ *| || RS | RS |
+ *|-------------||--------------|--------------|
+ *| COMMIT || fsync | getattr |
+ *+============================================+
+ *
+ *
+ */
int32_t
nfs3svc_write_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, struct iatt *prebuf,
- struct iatt *postbuf)
+ struct iatt *postbuf, dict_t *xdata)
{
nfsstat3 stat = NFS3ERR_SERVERFAULT;
- int ret = -EFAULT;
- nfs_user_t nfu = {0, };
nfs3_call_state_t *cs = NULL;
struct nfs3_state *nfs3 = NULL;
cs = frame->local;
nfs3 = rpcsvc_request_program_private (cs->req);
if (op_ret == -1) {
- stat = nfs3_errno_to_nfsstat3 (op_errno);
+ gf_log (GF_NFS, GF_LOG_WARNING,
+ "%x: %s => -1 (%s)", rpcsvc_request_xid (cs->req),
+ cs->resolvedloc.path, strerror (op_errno));
+ stat = nfs3_cbk_errno_status (op_ret, op_errno);
goto err;
}
- /* So that we do send a reply if an unstable write was requested. */
- ret = -1;
stat = NFS3_OK;
cs->maxcount = op_ret;
- if (cs->writetype == UNSTABLE)
- goto err;
-
- nfs_request_user_init (&nfu, cs->req);
- /* Store the current preattr so that this can be used as the pre attr
- * when fsync returns. We dont want to use the preattr in fsync because
- * the write fop happened before the fsync.
- */
- cs->stbuf = *prebuf;
- ret = nfs_fsync (cs->nfsx, cs->vol, &nfu, cs->fd, 0,
- nfs3svc_write_fsync_cbk, cs);
- if (ret < 0)
- stat = nfs3_errno_to_nfsstat3 (-ret);
err:
- if (ret < 0) {
- nfs3_log_write_res (rpcsvc_request_xid (cs->req), stat,
- op_errno, cs->maxcount, cs->writetype,
- nfs3->serverstart);
- nfs3_write_reply (cs->req, stat, cs->maxcount,
- cs->writetype, nfs3->serverstart, prebuf,
- postbuf);
- nfs3_call_state_wipe (cs);
- }
+ nfs3_log_write_res (rpcsvc_request_xid (cs->req), stat,
+ op_errno, cs->maxcount, cs->writetype,
+ nfs3->serverstart);
+ nfs3_write_reply (cs->req, stat, cs->maxcount,
+ cs->writetype, nfs3->serverstart, prebuf,
+ postbuf);
+ nfs3_call_state_wipe (cs);
return 0;
}
@@ -1665,8 +2125,9 @@ __nfs3_write_resume (nfs3_call_state_t *cs)
* opaque data buffers to multiples of 4 bytes.
*/
cs->datavec.iov_len = cs->datacount;
- ret = nfs_write (cs->nfsx, cs->vol, &nfu, cs->fd, cs->iob, &cs->datavec,
- 1, cs->dataoffset, nfs3svc_write_cbk, cs);
+ ret = nfs_write (cs->nfsx, cs->vol, &nfu, cs->fd, cs->iobref,
+ &cs->datavec, 1, cs->dataoffset, nfs3svc_write_cbk,
+ cs);
return ret;
}
@@ -1678,46 +2139,45 @@ nfs3_write_resume (void *carg)
nfsstat3 stat = NFS3ERR_SERVERFAULT;
int ret = -EFAULT;
nfs3_call_state_t *cs = NULL;
+ fd_t *fd = NULL;
if (!carg)
return ret;
cs = (nfs3_call_state_t *)carg;
nfs3_check_fh_resolve_status (cs, stat, nfs3err);
-
- ret = __nfs3_write_resume (cs);
- if (ret < 0)
- stat = nfs3_errno_to_nfsstat3 (-ret);
-nfs3err:
- if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "WRITE",
- stat, -ret);
- nfs3_write_reply (cs->req, stat, 0, cs->writetype, 0, NULL,
- NULL);
- nfs3_call_state_wipe (cs);
+ fd = fd_anonymous (cs->resolvedloc.inode);
+ if (!fd) {
+ gf_log (GF_NFS3, GF_LOG_ERROR, "Failed to create anonymous fd");
+ goto nfs3err;
}
- return ret;
-}
+ cs->fd = fd; /* Gets unrefd when the call state is wiped. */
-int
-nfs3_write_open_resume (void *carg)
-{
- nfsstat3 stat = NFS3ERR_SERVERFAULT;
- int ret = -EFAULT;
- nfs3_call_state_t *cs = NULL;
-
- if (!carg)
- return ret;
+/*
+ enum stable_how {
+ UNSTABLE = 0,
+ DATA_SYNC = 1,
+ FILE_SYNC = 2,
+ };
+*/
+ switch (cs->writetype) {
+ case UNSTABLE:
+ break;
+ case DATA_SYNC:
+ fd->flags |= O_DSYNC;
+ break;
+ case FILE_SYNC:
+ fd->flags |= O_SYNC;
+ break;
+ }
- cs = (nfs3_call_state_t *)carg;
- nfs3_check_fh_resolve_status (cs, stat, nfs3err);
- ret = nfs3_file_open_and_resume (cs, nfs3_write_resume);
+ ret = __nfs3_write_resume (cs);
if (ret < 0)
stat = nfs3_errno_to_nfsstat3 (-ret);
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "WRITE",
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_WRITE,
stat, -ret);
nfs3_write_reply (cs->req, stat, 0, cs->writetype, 0, NULL,
NULL);
@@ -1727,11 +2187,10 @@ nfs3err:
}
-
int
nfs3_write (rpcsvc_request_t *req, struct nfs3_fh *fh, offset3 offset,
count3 count, stable_how stable, struct iovec payload,
- struct iobuf *iob)
+ struct iobref *iobref)
{
xlator_t *vol = NULL;
nfsstat3 stat = NFS3ERR_SERVERFAULT;
@@ -1744,33 +2203,34 @@ nfs3_write (rpcsvc_request_t *req, struct nfs3_fh *fh, offset3 offset,
return -1;
}
- nfs3_log_rw_call (rpcsvc_request_xid (req), "WRITE", fh, offset, count,
- stable);
+ nfs3_log_rw_call (rpcsvc_request_xid (req), "WRITE", fh, offset,
+ count, stable);
nfs3_validate_gluster_fh (fh, stat, nfs3err);
nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret);
nfs3_map_fh_to_volume (nfs3, fh, req, vol, stat, nfs3err);
- nfs3_check_rw_volaccess (nfs3, fh->xlatorid, stat, nfs3err);
+ nfs3_volume_started_check (nfs3, vol, ret, out);
+ nfs3_check_rw_volaccess (nfs3, fh->exportid, stat, nfs3err);
nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);
cs->datacount = count;
cs->dataoffset = offset;
cs->writetype = stable;
- cs->iob = iob;
+ cs->iobref = iobref;
cs->datavec = payload;
- ret = nfs3_fh_resolve_and_resume (cs, fh, NULL, nfs3_write_open_resume);
+ ret = nfs3_fh_resolve_and_resume (cs, fh, NULL, nfs3_write_resume);
if (ret < 0)
stat = nfs3_errno_to_nfsstat3 (-ret);
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (req), "WRITE", stat,
- -ret);
+ nfs3_log_common_res (rpcsvc_request_xid (req), NFS3_WRITE,
+ stat, -ret);
nfs3_write_reply (req, stat, 0, stable, 0, NULL, NULL);
nfs3_call_state_wipe (cs);
ret = 0;
}
-
+out:
return ret;
}
@@ -1782,95 +2242,45 @@ nfs3err:
int
-nfs3svc_write_vecsizer (rpcsvc_request_t *req, ssize_t *readsize, int *newbuf)
+nfs3svc_write_vecsizer (int state, ssize_t *readsize, char *base_addr,
+ char *curr_addr)
{
- ssize_t ret = RPCSVC_ACTOR_ERROR;
- int state = 0;
- uint32_t fhlen = 0;
- uint32_t fhlen_n = 0;
- write3args *args = NULL;
+ int ret = 0;
+ uint32_t fhlen = 0;
+ uint32_t fhlen_n = 0;
- if (!req)
- return ret;
-
- state = (long)rpcsvc_request_private (req);
- *newbuf = 0;
if (state == 0) {
- rpcsvc_request_set_private (req, NFS3_VECWRITE_READFHLEN);
+ ret = NFS3_VECWRITE_READFHLEN;
*readsize = 4;
- ret = 0;
} else if (state == NFS3_VECWRITE_READFHLEN) {
- fhlen_n = *(uint32_t *)req->msg.iov_base;
+ fhlen_n = *(uint32_t *)(curr_addr - 4);
fhlen = ntohl (fhlen_n);
*readsize = xdr_length_round_up (fhlen, NFS3_FHSIZE);
- rpcsvc_request_set_private (req, NFS3_VECWRITE_READFH);
- ret = 0;
+ ret = NFS3_VECWRITE_READFH;
} else if (state == NFS3_VECWRITE_READFH) {
*readsize = NFS3_WRITE_POSTFH_SIZE;
- rpcsvc_request_set_private (req, NFS3_VECWRITE_READREST);
- ret = 0;
+ ret = NFS3_VECWRITE_READREST;
} else if (state == NFS3_VECWRITE_READREST) {
- args = CALLOC (1, sizeof (*args));
- if (!args)
- goto rpcerr;
-
- if (xdr_to_write3args_nocopy (req->msg, args, NULL) <= 0) {
- gf_log (GF_NFS3, GF_LOG_ERROR, "Error decoding args");
- rpcsvc_request_seterr (req, GARBAGE_ARGS);
- goto rpcerr;
- }
- rpcsvc_request_set_private (req, args);
- ret = xdr_length_round_up (args->data.data_len, 1048576);
- *readsize = ret;
- *newbuf = 1;
ret = 0;
- }
- ret = 0;
-
-rpcerr:
- return ret;
-}
-
-
-int
-nfs3svc_write_vec (rpcsvc_request_t *req, struct iobuf *iob)
-{
- write3args *args = NULL;
- int ret = RPCSVC_ACTOR_ERROR;
- struct iovec payload = {0, };
-
- if ((!req) || (!iob))
- return ret;
-
- args = rpcsvc_request_private (req);
- iobuf_to_iovec (iob, &payload);
- iobuf_ref (iob);
- ret = nfs3_write (req, (struct nfs3_fh *)args->file.data.data_val,
- args->offset, args->count, args->stable, payload,iob);
- xdr_free_write3args_nocopy (args);
- if (ret < 0) {
- gf_log (GF_NFS3, GF_LOG_ERROR, "WRITE procedure failed");
- rpcsvc_request_seterr (req, SYSTEM_ERR);
- ret = RPCSVC_ACTOR_ERROR;
- }
+ *readsize = 0;
+ } else
+ gf_log ("nfs", GF_LOG_ERROR, "state wrong");
return ret;
}
-
int
nfs3svc_write (rpcsvc_request_t *req)
{
struct nfs3_fh fh = {{0}, };
write3args args;
int ret = RPCSVC_ACTOR_ERROR;
- struct iovec payload = {0, };
if (!req)
return ret;
nfs3_prep_write3args (&args, &fh);
- if (xdr_to_write3args_nocopy (req->msg, &args, &payload) <= 0) {
+ if (xdr_to_write3args (req->msg[0], &args) <= 0) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Error decoding args");
rpcsvc_request_seterr (req, GARBAGE_ARGS);
goto rpcerr;
@@ -1881,10 +2291,10 @@ nfs3svc_write (rpcsvc_request_t *req)
* ourselves because the RPC call handler who called us will unref its
* own ref of the record's iobuf when it is done handling the request.
*/
- rpcsvc_request_record_ref (req);
+
ret = nfs3_write (req, &fh, args.offset, args.count, args.stable,
- payload, rpcsvc_request_record_iob (req));
- if (ret < 0) {
+ req->msg[1], rpcsvc_request_iobref_ref (req));
+ if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
gf_log (GF_NFS3, GF_LOG_ERROR, "WRITE procedure failed");
rpcsvc_request_seterr (req, SYSTEM_ERR);
ret = RPCSVC_ACTOR_ERROR;
@@ -1901,8 +2311,11 @@ nfs3_create_reply (rpcsvc_request_t *req, nfsstat3 stat, struct nfs3_fh *newfh,
struct iatt *postparent)
{
create3res res = {0, };
+ uint64_t deviceid = 0;
- nfs3_fill_create3res (&res, stat, newfh, newbuf, preparent, postparent);
+ deviceid = nfs3_request_xlator_deviceid (req);
+ nfs3_fill_create3res (&res, stat, newfh, newbuf, preparent, postparent,
+ deviceid);
nfs3svc_submit_reply (req, (void *)&res,
(nfs3_serializer)xdr_serialize_create3res);
return 0;
@@ -1912,20 +2325,23 @@ nfs3_create_reply (rpcsvc_request_t *req, nfsstat3 stat, struct nfs3_fh *newfh,
int32_t
nfs3svc_create_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno,
- struct iatt *preop, struct iatt *postop)
+ struct iatt *preop, struct iatt *postop, dict_t *xdata)
{
nfsstat3 stat = NFS3ERR_SERVERFAULT;
nfs3_call_state_t *cs = NULL;
cs = frame->local;
if (op_ret == -1) {
- stat = nfs3_errno_to_nfsstat3 (op_errno);
+ gf_log (GF_NFS, GF_LOG_WARNING,
+ "%x: %s => -1 (%s)", rpcsvc_request_xid (cs->req),
+ cs->resolvedloc.path, strerror (op_errno));
+ stat = nfs3_cbk_errno_status (op_ret, op_errno);
goto nfs3err;
}
stat = NFS3_OK;
nfs3err:
- nfs3_log_newfh_res (rpcsvc_request_xid (cs->req), "CREATE", stat,
+ nfs3_log_newfh_res (rpcsvc_request_xid (cs->req), NFS3_CREATE, stat,
op_errno, &cs->fh);
nfs3_create_reply (cs->req, stat, &cs->fh, postop, &cs->preparent,
&cs->postparent);
@@ -1939,20 +2355,26 @@ int32_t
nfs3svc_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, fd_t *fd, inode_t *inode,
struct iatt *buf, struct iatt *preparent,
- struct iatt *postparent)
+ struct iatt *postparent, dict_t *xdata)
{
nfsstat3 stat = NFS3ERR_SERVERFAULT;
int ret = -EFAULT;
nfs_user_t nfu = {0, };
nfs3_call_state_t *cs = NULL;
+ inode_t *oldinode = NULL;
cs = frame->local;
if (op_ret == -1) {
- stat = nfs3_errno_to_nfsstat3 (op_errno);
+ gf_log (GF_NFS, GF_LOG_WARNING,
+ "%x: %s => -1 (%s)", rpcsvc_request_xid (cs->req),
+ cs->resolvedloc.path, strerror (op_errno));
+ stat = nfs3_cbk_errno_status (op_ret, op_errno);
goto nfs3err;
}
nfs3_fh_build_child_fh (&cs->parent, buf, &cs->fh);
+ oldinode = inode_link (inode, cs->resolvedloc.parent,
+ cs->resolvedloc.name, buf);
/* Means no attributes were required to be set. */
if (!cs->setattr_valid) {
@@ -1964,14 +2386,20 @@ nfs3svc_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
cs->preparent = *preparent;
cs->postparent = *postparent;
nfs_request_user_init (&nfu, cs->req);
+ uuid_copy (cs->resolvedloc.gfid, inode->gfid);
ret = nfs_setattr (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,&cs->stbuf,
cs->setattr_valid, nfs3svc_create_setattr_cbk, cs);
if (ret < 0)
stat = nfs3_errno_to_nfsstat3 (-ret);
nfs3err:
+ if (oldinode) {
+ inode_lookup (oldinode);
+ inode_unref (oldinode);
+ }
+
if (ret < 0) {
- nfs3_log_newfh_res (rpcsvc_request_xid (cs->req), "CREATE",
+ nfs3_log_newfh_res (rpcsvc_request_xid (cs->req), NFS3_CREATE,
stat, op_errno, &cs->fh);
nfs3_create_reply (cs->req, stat, &cs->fh, buf, preparent,
postparent);
@@ -1987,16 +2415,30 @@ nfs3_create_common (nfs3_call_state_t *cs)
int ret = -EFAULT;
int flags = 0;
nfs_user_t nfu = {0, };
+ uid_t uid = 0;
+ gid_t gid = 0;
if (!cs)
return ret;
- if ((cs->createmode == UNCHECKED) || (cs->createmode = EXCLUSIVE))
- flags = O_RDWR;
- else if (cs->createmode == GUARDED)
+ if (cs->createmode == GUARDED)
flags = (O_RDWR | O_EXCL);
+ else
+ flags = O_RDWR;
- nfs_request_user_init (&nfu, cs->req);
+ if (gf_attr_uid_set (cs->setattr_valid)) {
+ uid = cs->stbuf.ia_uid;
+ cs->setattr_valid &= ~GF_SET_ATTR_UID;
+ } else
+ uid = rpcsvc_request_uid (cs->req);
+
+ if (gf_attr_gid_set (cs->setattr_valid)) {
+ gid = cs->stbuf.ia_gid;
+ cs->setattr_valid &= ~GF_SET_ATTR_GID;
+ } else
+ gid = rpcsvc_request_gid (cs->req);
+
+ nfs_request_primary_user_init (&nfu, cs->req, uid, gid);
/* We can avoid sending the setattr call later if only the mode is
* required to be set. This is possible because the create fop allows
* us to specify a mode arg.
@@ -2016,7 +2458,8 @@ nfs3_create_common (nfs3_call_state_t *cs)
int32_t
nfs3svc_create_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno, struct iatt *buf)
+ int32_t op_ret, int32_t op_errno, struct iatt *buf,
+ dict_t *xdata)
{
int ret = -EFAULT;
nfsstat3 stat = NFS3ERR_SERVERFAULT;
@@ -2026,21 +2469,35 @@ nfs3svc_create_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
cs = frame->local;
nfs_request_user_init (&nfu, cs->req);
if (op_ret == -1) {
+ gf_log (GF_NFS, GF_LOG_WARNING,
+ "%x: %s => -1 (%s)", rpcsvc_request_xid (cs->req),
+ cs->resolvedloc.path, strerror (op_errno));
ret = -op_errno;
- stat = nfs3_errno_to_nfsstat3 (op_errno);
+ stat = nfs3_cbk_errno_status (op_ret, op_errno);
goto nfs3err;
}
- if (cs->preparent.ia_mtime == buf->ia_mtime)
+ if ((cs->stbuf.ia_mtime == buf->ia_mtime) &&
+ (cs->stbuf.ia_atime == buf->ia_atime)) {
+ gf_log (GF_NFS3, GF_LOG_DEBUG,
+ "Create req retransmitted verf %x %x",
+ cs->stbuf.ia_mtime, cs->stbuf.ia_atime);
stat = NFS3_OK;
- else
+ nfs3_fh_build_child_fh (&cs->parent, buf, &cs->fh);
+ } else {
+ gf_log (GF_NFS3, GF_LOG_DEBUG,
+ "File already exist new_verf %x %x"
+ "old_verf %x %x", cs->stbuf.ia_mtime,
+ cs->stbuf.ia_atime,
+ buf->ia_mtime, buf->ia_atime);
stat = NFS3ERR_EXIST;
+ }
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "CREATE",
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_CREATE,
stat, op_errno);
- nfs3_create_reply (cs->req, stat, NULL, NULL, NULL, NULL);
+ nfs3_create_reply (cs->req, stat, &cs->fh, buf, NULL, NULL);
nfs3_call_state_wipe (cs);
}
@@ -2057,9 +2514,15 @@ nfs3_create_exclusive (nfs3_call_state_t *cs)
if (!cs)
return ret;
- /* HACK warning. */
- cs->preparent.ia_mtime = cs->cookieverf;
- cs->preparent.ia_atime = 9669;
+ /* Storing verifier as a mtime and atime attribute, to store it
+ * in stable storage */
+ memcpy (&cs->stbuf.ia_atime, &cs->cookieverf,
+ sizeof (cs->stbuf.ia_atime));
+ memcpy (&cs->stbuf.ia_mtime,
+ ((char *) &cs->cookieverf) + sizeof (cs->stbuf.ia_atime),
+ sizeof (cs->stbuf.ia_mtime));
+ cs->setattr_valid |= GF_SET_ATTR_ATIME;
+ cs->setattr_valid |= GF_SET_ATTR_MTIME;
nfs_request_user_init (&nfu, cs->req);
/* If the file already existed we need to get that attributes so we can
@@ -2073,15 +2536,7 @@ nfs3_create_exclusive (nfs3_call_state_t *cs)
goto nfs3err;
}
- if (cs->setattr_valid & GF_SET_ATTR_MODE) {
- cs->setattr_valid &= ~GF_SET_ATTR_MODE;
- ret = nfs_create (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
- O_RDWR, cs->mode, nfs3svc_create_cbk, cs);
- } else
- ret = nfs_create (cs->nfsx, cs->vol, &nfu, &cs->oploc, O_RDWR,
- NFS_DEFAULT_CREATE_MODE, nfs3svc_create_cbk,
- cs);
-
+ ret = nfs3_create_common (cs);
nfs3err:
return ret;
}
@@ -2110,7 +2565,7 @@ nfs3_create_resume (void *carg)
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "CREATE",
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_CREATE,
stat, -ret);
nfs3_create_reply (cs->req, stat, NULL, NULL, NULL, NULL);
nfs3_call_state_wipe (cs);
@@ -2137,12 +2592,17 @@ nfs3_create (rpcsvc_request_t *req, struct nfs3_fh *dirfh, char *name,
nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret);
nfs3_validate_strlen_or_goto (name, NFS_NAME_MAX, nfs3err, stat, ret);
nfs3_map_fh_to_volume (nfs3, dirfh, req, vol, stat, nfs3err);
- nfs3_check_rw_volaccess (nfs3, dirfh->xlatorid, stat, nfs3err);
+ nfs3_volume_started_check (nfs3, vol, ret, out);
+ nfs3_check_rw_volaccess (nfs3, dirfh->exportid, stat, nfs3err);
nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);
cs->cookieverf = cverf;
- cs->setattr_valid = nfs3_sattr3_to_setattr_valid (sattr, NULL,
- &cs->mode);
+ /*In Exclusive create client is supposed to send cverf instead of
+ * sattr*/
+ if (mode != EXCLUSIVE)
+ cs->setattr_valid = nfs3_sattr3_to_setattr_valid (sattr,
+ &cs->stbuf,
+ &cs->mode);
cs->createmode = mode;
cs->parent = *dirfh;
@@ -2152,13 +2612,13 @@ nfs3_create (rpcsvc_request_t *req, struct nfs3_fh *dirfh, char *name,
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (req), "CREATE", stat,
- -ret);
+ nfs3_log_common_res (rpcsvc_request_xid (req), NFS3_CREATE,
+ stat, -ret);
nfs3_create_reply (req, stat, NULL, NULL, NULL, NULL);
nfs3_call_state_wipe (cs);
ret = 0;
}
-
+out:
return ret;
}
@@ -2166,26 +2626,29 @@ nfs3err:
int
nfs3svc_create (rpcsvc_request_t *req)
{
- char name[NFS_PATH_MAX];
- struct nfs3_fh dirfh = {{0}, };
- create3args args;
- int ret = RPCSVC_ACTOR_ERROR;
- uint64_t cverf = 0;
+ char name[NFS_PATH_MAX];
+ struct nfs3_fh dirfh = {{0}, };
+ create3args args;
+ int ret = RPCSVC_ACTOR_ERROR;
+ uint64_t cverf = 0;
+ uint64_t *cval;
if (!req)
return ret;
nfs3_prep_create3args (&args, &dirfh, name);
- if (xdr_to_create3args (req->msg, &args) <= 0) {
+ if (xdr_to_create3args (req->msg[0], &args) <= 0) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Error decoding args");
rpcsvc_request_seterr (req, GARBAGE_ARGS);
goto rpcerr;
}
- cverf = *(uint64_t *)args.how.createhow3_u.verf;
+ cval = (uint64_t *)args.how.createhow3_u.verf;
+ cverf = *cval;
+
ret = nfs3_create (req, &dirfh, name, args.how.mode,
&args.how.createhow3_u.obj_attributes, cverf);
- if (ret < 0) {
+ if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
gf_log (GF_NFS3, GF_LOG_ERROR, "CREATE procedure failed");
rpcsvc_request_seterr (req, SYSTEM_ERR);
ret = RPCSVC_ACTOR_ERROR;
@@ -2202,8 +2665,11 @@ nfs3_mkdir_reply (rpcsvc_request_t *req, nfsstat3 stat, struct nfs3_fh *fh,
struct iatt *postparent)
{
mkdir3res res = {0, };
+ uint64_t deviceid = 0;
- nfs3_fill_mkdir3res (&res, stat, fh, buf, preparent, postparent);
+ deviceid = nfs3_request_xlator_deviceid (req);
+ nfs3_fill_mkdir3res (&res, stat, fh, buf, preparent, postparent,
+ deviceid);
nfs3svc_submit_reply (req, &res,
(nfs3_serializer)xdr_serialize_mkdir3res);
return 0;
@@ -2212,20 +2678,23 @@ nfs3_mkdir_reply (rpcsvc_request_t *req, nfsstat3 stat, struct nfs3_fh *fh,
int32_t
nfs3svc_mkdir_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno,
- struct iatt *preop, struct iatt *postop)
+ struct iatt *preop, struct iatt *postop, dict_t *xdata)
{
nfsstat3 stat = NFS3ERR_SERVERFAULT;
nfs3_call_state_t *cs = NULL;
cs = frame->local;
if (op_ret == -1) {
- stat = nfs3_errno_to_nfsstat3 (op_errno);
+ gf_log (GF_NFS, GF_LOG_WARNING,
+ "%x: %s => -1 (%s)", rpcsvc_request_xid (cs->req),
+ cs->resolvedloc.path, strerror (op_errno));
+ stat = nfs3_cbk_errno_status (op_ret, op_errno);
goto nfs3err;
}
stat = NFS3_OK;
nfs3err:
- nfs3_log_newfh_res (rpcsvc_request_xid (cs->req), "MKDIR", stat,
+ nfs3_log_newfh_res (rpcsvc_request_xid (cs->req), NFS3_MKDIR, stat,
op_errno, &cs->fh);
nfs3_mkdir_reply (cs->req, stat, &cs->fh, postop, &cs->preparent,
&cs->postparent);
@@ -2239,7 +2708,7 @@ int32_t
nfs3svc_mkdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, inode_t *inode,
struct iatt *buf, struct iatt *preparent,
- struct iatt *postparent)
+ struct iatt *postparent, dict_t *xdata)
{
nfsstat3 stat = NFS3ERR_SERVERFAULT;
int ret = -EFAULT;
@@ -2248,7 +2717,10 @@ nfs3svc_mkdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
cs = frame->local;
if (op_ret == -1) {
- stat = nfs3_errno_to_nfsstat3 (op_errno);
+ gf_log (GF_NFS, GF_LOG_WARNING,
+ "%x: %s => -1 (%s)", rpcsvc_request_xid (cs->req),
+ cs->resolvedloc.path, strerror (op_errno));
+ stat = nfs3_cbk_errno_status (op_ret, op_errno);
goto nfs3err;
}
@@ -2270,8 +2742,8 @@ nfs3svc_mkdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
nfs3err:
if (ret < 0) {
- nfs3_log_newfh_res (rpcsvc_request_xid (cs->req), "MKDIR", stat,
- op_errno, &cs->fh);
+ nfs3_log_newfh_res (rpcsvc_request_xid (cs->req), NFS3_MKDIR,
+ stat, op_errno, &cs->fh);
nfs3_mkdir_reply (cs->req, stat, &cs->fh, buf, preparent,
postparent);
nfs3_call_state_wipe (cs);
@@ -2309,8 +2781,8 @@ nfs3_mkdir_resume (void *carg)
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "MKDIR",stat,
- -ret);
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_MKDIR,
+ stat, -ret);
nfs3_mkdir_reply (cs->req, stat, NULL, NULL, NULL, NULL);
nfs3_call_state_wipe (cs);
}
@@ -2335,16 +2807,18 @@ nfs3_mkdir (rpcsvc_request_t *req, struct nfs3_fh *dirfh, char *name,
return -1;
}
- nfs3_log_fh_entry_call (rpcsvc_request_xid (req), "MKDIR", dirfh, name);
+ nfs3_log_fh_entry_call (rpcsvc_request_xid (req), "MKDIR", dirfh,
+ name);
nfs3_validate_gluster_fh (dirfh, stat, nfs3err);
nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret);
nfs3_validate_strlen_or_goto (name, NFS_NAME_MAX, nfs3err, stat, ret);
nfs3_map_fh_to_volume (nfs3, dirfh, req, vol, stat, nfs3err);
- nfs3_check_rw_volaccess (nfs3, dirfh->xlatorid, stat, nfs3err);
+ nfs3_volume_started_check (nfs3, vol, ret, out);
+ nfs3_check_rw_volaccess (nfs3, dirfh->exportid, stat, nfs3err);
nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);
cs->parent = *dirfh;
- cs->setattr_valid = nfs3_sattr3_to_setattr_valid (sattr, NULL,
+ cs->setattr_valid = nfs3_sattr3_to_setattr_valid (sattr, &cs->stbuf,
&cs->mode);
ret = nfs3_fh_resolve_and_resume (cs, dirfh, name, nfs3_mkdir_resume);
if (ret < 0)
@@ -2352,13 +2826,13 @@ nfs3_mkdir (rpcsvc_request_t *req, struct nfs3_fh *dirfh, char *name,
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (req), "MKDIR", stat,
- -ret);
+ nfs3_log_common_res (rpcsvc_request_xid (req), NFS3_MKDIR,
+ stat, -ret);
nfs3_mkdir_reply (req, stat, NULL, NULL, NULL, NULL);
nfs3_call_state_wipe (cs);
ret = 0;
}
-
+out:
return ret;
}
@@ -2374,14 +2848,14 @@ nfs3svc_mkdir (rpcsvc_request_t *req)
if (!req)
return ret;
nfs3_prep_mkdir3args (&args, &dirfh, name);
- if (xdr_to_mkdir3args (req->msg, &args) <= 0) {
+ if (xdr_to_mkdir3args (req->msg[0], &args) <= 0) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Error decoding args");
rpcsvc_request_seterr (req, GARBAGE_ARGS);
goto rpcerr;
}
ret = nfs3_mkdir (req, &dirfh, name, &args.attributes);
- if (ret < 0) {
+ if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
gf_log (GF_NFS3, GF_LOG_ERROR, "MKDIR procedure failed");
rpcsvc_request_seterr (req, SYSTEM_ERR);
ret = RPCSVC_ACTOR_ERROR;
@@ -2398,8 +2872,11 @@ nfs3_symlink_reply (rpcsvc_request_t *req, nfsstat3 stat, struct nfs3_fh *fh,
struct iatt *postparent)
{
symlink3res res = {0, };
+ uint64_t deviceid = 0;
- nfs3_fill_symlink3res (&res, stat, fh, buf, preparent, postparent);
+ deviceid = nfs3_request_xlator_deviceid (req);
+ nfs3_fill_symlink3res (&res, stat, fh, buf, preparent, postparent,
+ deviceid);
nfs3svc_submit_reply (req, (void *)&res,
(nfs3_serializer)xdr_serialize_symlink3res);
@@ -2411,14 +2888,17 @@ int32_t
nfs3svc_symlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, inode_t *inode,
struct iatt *buf, struct iatt *preparent,
- struct iatt *postparent)
+ struct iatt *postparent, dict_t *xdata)
{
nfsstat3 stat = NFS3ERR_SERVERFAULT;
nfs3_call_state_t *cs = NULL;
cs = frame->local;
if (op_ret == -1) {
- stat = nfs3_errno_to_nfsstat3 (op_errno);
+ gf_log (GF_NFS, GF_LOG_WARNING,
+ "%x: %s => -1 (%s)", rpcsvc_request_xid (cs->req),
+ cs->resolvedloc.path, strerror (op_errno));
+ stat = nfs3_cbk_errno_status (op_ret, op_errno);
goto nfs3err;
}
@@ -2426,7 +2906,7 @@ nfs3svc_symlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
stat = NFS3_OK;
nfs3err:
- nfs3_log_newfh_res (rpcsvc_request_xid (cs->req), "SYMLINK", stat,
+ nfs3_log_newfh_res (rpcsvc_request_xid (cs->req), NFS3_SYMLINK, stat,
op_errno, &cs->fh);
nfs3_symlink_reply (cs->req, stat, &cs->fh, buf, preparent,
postparent);
@@ -2456,8 +2936,8 @@ nfs3_symlink_resume (void *carg)
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "SYMLINK",
- stat, -ret);
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req),
+ NFS3_SYMLINK, stat, -ret);
nfs3_symlink_reply (cs->req, stat, NULL, NULL, NULL, NULL);
nfs3_call_state_wipe (cs);
}
@@ -2481,16 +2961,18 @@ nfs3_symlink (rpcsvc_request_t *req, struct nfs3_fh *dirfh, char *name,
return -1;
}
- nfs3_log_symlink_call (rpcsvc_request_xid (req), dirfh, name, target);
+ nfs3_log_symlink_call (rpcsvc_request_xid (req), dirfh, name,
+ target);
nfs3_validate_gluster_fh (dirfh, stat, nfs3err);
nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret);
nfs3_validate_strlen_or_goto (name, NFS_NAME_MAX, nfs3err, stat, ret);
nfs3_map_fh_to_volume (nfs3, dirfh, req, vol, stat, nfs3err);
- nfs3_check_rw_volaccess (nfs3, dirfh->xlatorid, stat, nfs3err);
+ nfs3_volume_started_check (nfs3, vol, ret, out);
+ nfs3_check_rw_volaccess (nfs3, dirfh->exportid, stat, nfs3err);
nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);
cs->parent = *dirfh;
- cs->pathname = strdup (target);
+ cs->pathname = gf_strdup (target);
if (!cs->pathname) {
ret = -1;
stat = NFS3ERR_SERVERFAULT;
@@ -2503,8 +2985,8 @@ nfs3_symlink (rpcsvc_request_t *req, struct nfs3_fh *dirfh, char *name,
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (req), "SYMLINK", stat,
- -ret);
+ nfs3_log_common_res (rpcsvc_request_xid (req), NFS3_SYMLINK,
+ stat, -ret);
nfs3_symlink_reply (req, stat, NULL, NULL, NULL, NULL);
nfs3_call_state_wipe (cs);
/* Ret must be 0 after this so that the caller does not
@@ -2512,7 +2994,7 @@ nfs3err:
*/
ret = 0;
}
-
+out:
return ret;
}
@@ -2529,7 +3011,7 @@ nfs3svc_symlink (rpcsvc_request_t *req)
if (!req)
return ret;
nfs3_prep_symlink3args (&args, &dirfh, name, target);
- if (xdr_to_symlink3args (req->msg, &args) <= 0) {
+ if (xdr_to_symlink3args (req->msg[0], &args) <= 0) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Error decoding args");
rpcsvc_request_seterr (req, GARBAGE_ARGS);
goto rpcerr;
@@ -2537,7 +3019,7 @@ nfs3svc_symlink (rpcsvc_request_t *req)
ret = nfs3_symlink (req, &dirfh, name, target,
&args.symlink.symlink_attributes);
- if (ret < 0) {
+ if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
gf_log (GF_NFS3, GF_LOG_ERROR, "SYMLINK procedure failed");
rpcsvc_request_seterr (req, SYSTEM_ERR);
ret = RPCSVC_ACTOR_ERROR;
@@ -2554,7 +3036,11 @@ nfs3_mknod_reply (rpcsvc_request_t *req, nfsstat3 stat, struct nfs3_fh *fh,
struct iatt *postparent)
{
mknod3res res = {0, };
- nfs3_fill_mknod3res (&res, stat, fh, buf, preparent, postparent);
+ uint64_t deviceid = 0;
+
+ deviceid = nfs3_request_xlator_deviceid (req);
+ nfs3_fill_mknod3res (&res, stat, fh, buf, preparent, postparent,
+ deviceid);
nfs3svc_submit_reply (req, (void *)&res,
(nfs3_serializer)xdr_serialize_mknod3res);
@@ -2564,20 +3050,23 @@ nfs3_mknod_reply (rpcsvc_request_t *req, nfsstat3 stat, struct nfs3_fh *fh,
int32_t
nfs3svc_mknod_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno,
- struct iatt *preop, struct iatt *postop)
+ struct iatt *preop, struct iatt *postop, dict_t *xdata)
{
nfsstat3 stat = NFS3ERR_SERVERFAULT;
nfs3_call_state_t *cs = NULL;
cs = frame->local;
if (op_ret == -1) {
- stat = nfs3_errno_to_nfsstat3 (op_errno);
+ gf_log (GF_NFS, GF_LOG_WARNING,
+ "%x: %s => -1 (%s)", rpcsvc_request_xid (cs->req),
+ cs->resolvedloc.path, strerror (op_errno));
+ stat = nfs3_cbk_errno_status (op_ret, op_errno);
goto nfs3err;
}
stat = NFS3_OK;
nfs3err:
- nfs3_log_newfh_res (rpcsvc_request_xid (cs->req), "MKNOD", stat,
+ nfs3_log_newfh_res (rpcsvc_request_xid (cs->req), NFS3_MKNOD, stat,
op_errno, &cs->fh);
nfs3_mknod_reply (cs->req, stat, &cs->fh, postop, &cs->preparent,
&cs->postparent);
@@ -2591,7 +3080,7 @@ int32_t
nfs3svc_mknod_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, inode_t *inode,
struct iatt *buf, struct iatt *preparent,
- struct iatt *postparent)
+ struct iatt *postparent, dict_t *xdata)
{
nfsstat3 stat = NFS3ERR_SERVERFAULT;
int ret = -1;
@@ -2600,7 +3089,10 @@ nfs3svc_mknod_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
cs = frame->local;
if (op_ret == -1) {
- stat = nfs3_errno_to_nfsstat3 (op_errno);
+ gf_log (GF_NFS, GF_LOG_WARNING,
+ "%x: %s => -1 (%s)", rpcsvc_request_xid (cs->req),
+ cs->resolvedloc.path, strerror (op_errno));
+ stat = nfs3_cbk_errno_status (op_ret, op_errno);
goto nfs3err;
}
@@ -2622,7 +3114,8 @@ nfs3svc_mknod_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
stat = nfs3_errno_to_nfsstat3 (-ret);
nfs3err:
if (ret < 0) {
- nfs3_log_newfh_res (rpcsvc_request_xid (cs->req), "MKNOD", stat,
+ nfs3_log_newfh_res (rpcsvc_request_xid (cs->req), NFS3_MKNOD,
+ stat,
op_errno, &cs->fh);
nfs3_mknod_reply (cs->req, stat, &cs->fh, buf, preparent,
postparent);
@@ -2720,8 +3213,8 @@ nfs3_mknod_resume (void *carg)
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "MKNOD",stat,
- -ret);
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_MKNOD,
+ stat, -ret);
nfs3_mknod_reply (cs->req, stat, NULL, NULL, NULL, NULL);
nfs3_call_state_wipe (cs);
}
@@ -2747,12 +3240,14 @@ nfs3_mknod (rpcsvc_request_t *req, struct nfs3_fh *fh, char *name,
return -1;
}
- nfs3_log_mknod_call (rpcsvc_request_xid (req), fh, name,nodedata->type);
+ nfs3_log_mknod_call (rpcsvc_request_xid (req), fh, name,
+ nodedata->type);
nfs3_validate_gluster_fh (fh, stat, nfs3err);
nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret);
nfs3_validate_strlen_or_goto (name, NFS_NAME_MAX, nfs3err, stat, ret);
nfs3_map_fh_to_volume (nfs3, fh, req, vol, stat, nfs3err);
- nfs3_check_rw_volaccess (nfs3, fh->xlatorid, stat, nfs3err);
+ nfs3_volume_started_check (nfs3, vol, ret, out);
+ nfs3_check_rw_volaccess (nfs3, fh->exportid, stat, nfs3err);
nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);
cs->mknodtype = nodedata->type;
@@ -2761,13 +3256,15 @@ nfs3_mknod (rpcsvc_request_t *req, struct nfs3_fh *fh, char *name,
case NF3BLK:
cs->devnums = nodedata->mknoddata3_u.device.spec;
sattr = &nodedata->mknoddata3_u.device.dev_attributes;
- cs->setattr_valid = nfs3_sattr3_to_setattr_valid (sattr, NULL,
+ cs->setattr_valid = nfs3_sattr3_to_setattr_valid (sattr,
+ &cs->stbuf,
&cs->mode);
break;
case NF3SOCK:
case NF3FIFO:
sattr = &nodedata->mknoddata3_u.pipe_attributes;
- cs->setattr_valid = nfs3_sattr3_to_setattr_valid (sattr, NULL,
+ cs->setattr_valid = nfs3_sattr3_to_setattr_valid (sattr,
+ &cs->stbuf,
&cs->mode);
break;
default:
@@ -2782,8 +3279,8 @@ nfs3_mknod (rpcsvc_request_t *req, struct nfs3_fh *fh, char *name,
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (req), "MKNOD", stat,
- -ret);
+ nfs3_log_common_res (rpcsvc_request_xid (req), NFS3_MKNOD,
+ stat, -ret);
nfs3_mknod_reply (req, stat, NULL, NULL, NULL, NULL);
/* Ret must be 0 after this so that the caller does not
* also send an RPC reply.
@@ -2791,7 +3288,7 @@ nfs3err:
nfs3_call_state_wipe (cs);
ret = 0;
}
-
+out:
return ret;
}
@@ -2807,14 +3304,14 @@ nfs3svc_mknod (rpcsvc_request_t *req)
if (!req)
return ret;
nfs3_prep_mknod3args (&args, &fh, name);
- if (xdr_to_mknod3args (req->msg, &args) <= 0) {
+ if (xdr_to_mknod3args (req->msg[0], &args) <= 0) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Error decoding args");
rpcsvc_request_seterr (req, GARBAGE_ARGS);
goto rpcerr;
}
ret = nfs3_mknod (req, &fh, name, &args.what);
- if (ret < 0) {
+ if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
gf_log (GF_NFS3, GF_LOG_ERROR, "MKNOD procedure failed");
rpcsvc_request_seterr (req, SYSTEM_ERR);
ret = RPCSVC_ACTOR_ERROR;
@@ -2829,10 +3326,10 @@ nfs3_remove_reply (rpcsvc_request_t *req, nfsstat3 stat, struct iatt *preparent
, struct iatt *postparent)
{
remove3res res = {0, };
- uint16_t xlid = 0;
+ uint64_t deviceid = 0;
- xlid = nfs3_request_xlator_id (req);
- nfs3_fill_remove3res (&res, stat, preparent, postparent, xlid);
+ deviceid = nfs3_request_xlator_deviceid (req);
+ nfs3_fill_remove3res (&res, stat, preparent, postparent, deviceid);
nfs3svc_submit_reply (req, (void *)&res,
(nfs3_serializer)xdr_serialize_remove3res);
return 0;
@@ -2843,34 +3340,25 @@ nfs3_remove_reply (rpcsvc_request_t *req, nfsstat3 stat, struct iatt *preparent
int32_t
nfs3svc_remove_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, struct iatt *preparent,
- struct iatt *postparent)
+ struct iatt *postparent, dict_t *xdata)
{
nfsstat3 stat = NFS3ERR_SERVERFAULT;
- fd_t *openfd = NULL;
nfs3_call_state_t *cs = NULL;
- struct nfs3_state *nfs3 = NULL;
cs = frame->local;
if (op_ret == -1) {
- stat = nfs3_errno_to_nfsstat3 (op_errno);
- goto do_not_unref_cached_fd;
+ gf_log (GF_NFS, GF_LOG_WARNING,
+ "%x: %s => -1 (%s)", rpcsvc_request_xid (cs->req),
+ cs->resolvedloc.path, strerror (op_errno));
+ stat = nfs3_cbk_errno_status (op_ret, op_errno);
}
- stat = NFS3_OK;
- /* Close any cached fds so that when any currently active write
- * finishes, the file is finally removed.
- */
- openfd = fd_lookup (cs->resolvedloc.inode, 0);
- nfs3 = rpcsvc_request_program_private (cs->req);
- if (openfd) {
- fd_unref (openfd);
- nfs3_fdcache_remove (nfs3, openfd);
- }
-
-do_not_unref_cached_fd:
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "REMOVE", stat,
+
+ if (op_ret == 0)
+ stat = NFS3_OK;
+
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_REMOVE, stat,
op_errno);
nfs3_remove_reply (cs->req, stat, preparent, postparent);
- inode_unref (cs->resolvedloc.inode);
nfs3_call_state_wipe (cs);
return 0;
@@ -2917,7 +3405,7 @@ nfs3_remove_resume (void *carg)
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "REMOVE",
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_REMOVE,
stat, -ret);
nfs3_remove_reply (cs->req, stat, NULL, NULL);
nfs3_call_state_wipe (cs);
@@ -2941,12 +3429,14 @@ nfs3_remove (rpcsvc_request_t *req, struct nfs3_fh *fh, char *name)
return -1;
}
- nfs3_log_fh_entry_call (rpcsvc_request_xid (req), "REMOVE", fh, name);
+ nfs3_log_fh_entry_call (rpcsvc_request_xid (req), "REMOVE", fh,
+ name);
nfs3_validate_gluster_fh (fh, stat, nfs3err);
nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret);
nfs3_validate_strlen_or_goto (name, NFS_NAME_MAX, nfs3err, stat, ret);
nfs3_map_fh_to_volume (nfs3, fh, req, vol, stat, nfs3err);
- nfs3_check_rw_volaccess (nfs3, fh->xlatorid, stat, nfs3err);
+ nfs3_volume_started_check (nfs3, vol, ret, out);
+ nfs3_check_rw_volaccess (nfs3, fh->exportid, stat, nfs3err);
nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);
ret = nfs3_fh_resolve_and_resume (cs, fh, name, nfs3_remove_resume);
@@ -2955,8 +3445,8 @@ nfs3_remove (rpcsvc_request_t *req, struct nfs3_fh *fh, char *name)
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (req), "REMOVE", stat,
- -ret);
+ nfs3_log_common_res (rpcsvc_request_xid (req), NFS3_REMOVE,
+ stat, -ret);
nfs3_remove_reply (req, stat, NULL, NULL);
nfs3_call_state_wipe (cs);
/* Ret must be 0 after this so that the caller does not
@@ -2964,7 +3454,7 @@ nfs3err:
*/
ret = 0;
}
-
+out:
return ret;
}
@@ -2980,14 +3470,14 @@ nfs3svc_remove (rpcsvc_request_t *req)
if (!req)
return ret;
nfs3_prep_remove3args (&args, &fh, name);
- if (xdr_to_remove3args (req->msg, &args) <= 0) {
+ if (xdr_to_remove3args (req->msg[0], &args) <= 0) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Error decoding args");
rpcsvc_request_seterr (req, GARBAGE_ARGS);
goto rpcerr;
}
ret = nfs3_remove (req, &fh, name);
- if (ret < 0) {
+ if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
gf_log (GF_NFS3, GF_LOG_ERROR, "REMOVE procedure failed");
rpcsvc_request_seterr (req, SYSTEM_ERR);
ret = RPCSVC_ACTOR_ERROR;
@@ -3003,10 +3493,10 @@ nfs3_rmdir_reply (rpcsvc_request_t *req, nfsstat3 stat, struct iatt *preparent,
struct iatt *postparent)
{
rmdir3res res = {0, };
- uint16_t xlid = 0;
+ uint64_t deviceid = 0;
- xlid = nfs3_request_xlator_id (req);
- nfs3_fill_rmdir3res (&res, stat, preparent, postparent, xlid);
+ deviceid = nfs3_request_xlator_deviceid (req);
+ nfs3_fill_rmdir3res (&res, stat, preparent, postparent, deviceid);
nfs3svc_submit_reply (req, (void *)&res,
(nfs3_serializer)xdr_serialize_rmdir3res);
return 0;
@@ -3016,20 +3506,22 @@ nfs3_rmdir_reply (rpcsvc_request_t *req, nfsstat3 stat, struct iatt *preparent,
int32_t
nfs3svc_rmdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, struct iatt *preparent,
- struct iatt *postparent)
+ struct iatt *postparent, dict_t *xdata)
{
nfsstat3 stat = NFS3ERR_SERVERFAULT;
nfs3_call_state_t *cs = NULL;
cs = frame->local;
- if (op_ret == -1)
- stat = nfs3_errno_to_nfsstat3 (op_errno);
- else {
- inode_unref (cs->resolvedloc.inode);
+ if (op_ret == -1) {
+ gf_log (GF_NFS, GF_LOG_WARNING,
+ "%x: %s => -1 (%s)", rpcsvc_request_xid (cs->req),
+ cs->resolvedloc.path, strerror (op_errno));
+ stat = nfs3_cbk_errno_status (op_ret, op_errno);
+ } else {
stat = NFS3_OK;
}
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "RMDIR", stat,
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_RMDIR, stat,
op_errno);
nfs3_rmdir_reply (cs->req, stat, preparent, postparent);
nfs3_call_state_wipe (cs);
@@ -3058,7 +3550,7 @@ nfs3_rmdir_resume (void *carg)
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "RMDIR",
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_RMDIR,
stat, -ret);
nfs3_rmdir_reply (cs->req, stat, NULL, NULL);
nfs3_call_state_wipe (cs);
@@ -3083,12 +3575,14 @@ nfs3_rmdir (rpcsvc_request_t *req, struct nfs3_fh *fh, char *name)
return -1;
}
- nfs3_log_fh_entry_call (rpcsvc_request_xid (req), "RMDIR", fh, name);
+ nfs3_log_fh_entry_call (rpcsvc_request_xid (req), "RMDIR", fh,
+ name);
nfs3_validate_gluster_fh (fh, stat, nfs3err);
nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret);
nfs3_validate_strlen_or_goto (name, NFS_NAME_MAX, nfs3err, stat, ret);
nfs3_map_fh_to_volume (nfs3, fh, req, vol, stat, nfs3err);
- nfs3_check_rw_volaccess (nfs3, fh->xlatorid, stat, nfs3err);
+ nfs3_volume_started_check (nfs3, vol, ret, out);
+ nfs3_check_rw_volaccess (nfs3, fh->exportid, stat, nfs3err);
nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);
ret = nfs3_fh_resolve_and_resume (cs, fh, name, nfs3_rmdir_resume);
@@ -3097,8 +3591,8 @@ nfs3_rmdir (rpcsvc_request_t *req, struct nfs3_fh *fh, char *name)
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (req), "RMDIR", stat,
- -ret);
+ nfs3_log_common_res (rpcsvc_request_xid (req), NFS3_RMDIR,
+ stat, -ret);
nfs3_rmdir_reply (req, stat, NULL, NULL);
nfs3_call_state_wipe (cs);
/* Ret must be 0 after this so that the caller does not
@@ -3106,7 +3600,7 @@ nfs3err:
*/
ret = 0;
}
-
+out:
return ret;
}
@@ -3122,14 +3616,14 @@ nfs3svc_rmdir (rpcsvc_request_t *req)
if (!req)
return ret;
nfs3_prep_rmdir3args (&args, &fh, name);
- if (xdr_to_rmdir3args (req->msg, &args) <= 0) {
+ if (xdr_to_rmdir3args (req->msg[0], &args) <= 0) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Error decoding args");
rpcsvc_request_seterr (req, GARBAGE_ARGS);
goto rpcerr;
}
ret = nfs3_rmdir (req, &fh, name);
- if (ret < 0) {
+ if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
gf_log (GF_NFS3, GF_LOG_ERROR, "RMDIR procedure failed");
rpcsvc_request_seterr (req, SYSTEM_ERR);
ret = RPCSVC_ACTOR_ERROR;
@@ -3146,11 +3640,11 @@ nfs3_rename_reply (rpcsvc_request_t *req, nfsstat3 stat, struct iatt *buf,
struct iatt *prenewparent, struct iatt *postnewparent)
{
rename3res res = {0, };
- uint16_t xlid = 0;
+ uint64_t deviceid = 0;
- xlid = nfs3_request_xlator_id (req);
+ deviceid = nfs3_request_xlator_deviceid (req);
nfs3_fill_rename3res (&res, stat, buf, preoldparent, postoldparent,
- prenewparent, postnewparent, xlid);
+ prenewparent, postnewparent, deviceid);
nfs3svc_submit_reply (req, (void *)&res,
(nfs3_serializer) xdr_serialize_rename3res);
@@ -3164,7 +3658,8 @@ int32_t
nfs3svc_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, struct iatt *buf,
struct iatt *preoldparent, struct iatt *postoldparent,
- struct iatt *prenewparent, struct iatt *postnewparent)
+ struct iatt *prenewparent, struct iatt *postnewparent,
+ dict_t *xdata)
{
int ret = -EFAULT;
nfsstat3 stat = NFS3ERR_SERVERFAULT;
@@ -3172,13 +3667,18 @@ nfs3svc_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
cs = frame->local;
if (op_ret == -1) {
- stat = nfs3_errno_to_nfsstat3 (op_errno);
+ gf_log (GF_NFS, GF_LOG_WARNING,
+ "%x: rename %s -> %s => -1 (%s)",
+ rpcsvc_request_xid (cs->req), cs->oploc.path,
+ cs->resolvedloc.path, strerror (op_errno));
+ stat = nfs3_cbk_errno_status (op_ret, op_errno);
goto nfs3err;
}
stat = NFS3_OK;
nfs3err:
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "RENAME", stat,-ret);
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_RENAME, stat,
+ -ret);
nfs3_rename_reply (cs->req, stat, buf, preoldparent, postoldparent,
prenewparent, postnewparent);
nfs3_call_state_wipe (cs);
@@ -3208,7 +3708,7 @@ nfs3_rename_resume_dst (void *carg)
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "RENAME",
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_RENAME,
stat, -ret);
nfs3_rename_reply (cs->req, stat, NULL, NULL, NULL, NULL, NULL);
nfs3_call_state_wipe (cs);
@@ -3236,6 +3736,7 @@ nfs3_rename_resume_src (void *carg)
*/
nfs_loc_copy (&cs->oploc, &cs->resolvedloc);
nfs_loc_wipe (&cs->resolvedloc);
+ GF_FREE (cs->resolventry);
ret = nfs3_fh_resolve_and_resume (cs, &cs->fh, cs->pathname,
nfs3_rename_resume_dst);
@@ -3244,7 +3745,7 @@ nfs3_rename_resume_src (void *carg)
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "RENAME",
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_RENAME,
stat, -ret);
nfs3_rename_reply (cs->req, stat, NULL, NULL, NULL, NULL, NULL);
nfs3_call_state_wipe (cs);
@@ -3277,14 +3778,15 @@ nfs3_rename (rpcsvc_request_t *req, struct nfs3_fh *olddirfh, char *oldname,
nfs3_validate_strlen_or_goto(oldname, NFS_NAME_MAX, nfs3err, stat, ret);
nfs3_validate_strlen_or_goto(newname, NFS_NAME_MAX, nfs3err, stat, ret);
nfs3_map_fh_to_volume (nfs3, olddirfh, req, vol, stat, nfs3err);
- nfs3_check_rw_volaccess (nfs3, olddirfh->xlatorid, stat, nfs3err);
+ nfs3_volume_started_check (nfs3, vol, ret, out);
+ nfs3_check_rw_volaccess (nfs3, olddirfh->exportid, stat, nfs3err);
nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);
/* While we resolve the source (fh, name) pair, we need to keep a copy
* of the dest (fh,name) pair.
*/
cs->fh = *newdirfh;
- cs->pathname = strdup (newname);
+ cs->pathname = gf_strdup (newname);
if (!cs->pathname) {
stat = NFS3ERR_SERVERFAULT;
ret = -1;
@@ -3298,8 +3800,8 @@ nfs3_rename (rpcsvc_request_t *req, struct nfs3_fh *olddirfh, char *oldname,
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (req), "RENAME", stat,
- -ret);
+ nfs3_log_common_res (rpcsvc_request_xid (req), NFS3_RENAME,
+ stat, -ret);
nfs3_rename_reply (req, stat, NULL, NULL, NULL, NULL, NULL);
nfs3_call_state_wipe (cs);
/* Ret must be 0 after this so that the caller does not
@@ -3307,7 +3809,7 @@ nfs3err:
*/
ret = 0;
}
-
+out:
return ret;
}
@@ -3325,14 +3827,14 @@ nfs3svc_rename (rpcsvc_request_t *req)
if (!req)
return ret;
nfs3_prep_rename3args (&args, &olddirfh, oldname, &newdirfh, newname);
- if (xdr_to_rename3args (req->msg, &args) <= 0) {
+ if (xdr_to_rename3args (req->msg[0], &args) <= 0) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Error decoding args");
rpcsvc_request_seterr (req, GARBAGE_ARGS);
goto rpcerr;
}
ret = nfs3_rename (req, &olddirfh, oldname, &newdirfh, newname);
- if (ret < 0) {
+ if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
gf_log (GF_NFS3, GF_LOG_ERROR, "RENAME procedure failed");
rpcsvc_request_seterr (req, SYSTEM_ERR);
ret = RPCSVC_ACTOR_ERROR;
@@ -3348,10 +3850,10 @@ nfs3_link_reply (rpcsvc_request_t *req, nfsstat3 stat, struct iatt *buf,
struct iatt *preparent, struct iatt *postparent)
{
link3res res = {0, };
- uint16_t xlid = 0;
+ uint64_t deviceid = 0;
- xlid = nfs3_request_xlator_id (req);
- nfs3_fill_link3res (&res, stat, buf, preparent, postparent, xlid);
+ deviceid = nfs3_request_xlator_deviceid (req);
+ nfs3_fill_link3res (&res, stat, buf, preparent, postparent, deviceid);
nfs3svc_submit_reply (req, (void *)&res,
(nfs3_serializer)xdr_serialize_link3res);
@@ -3363,18 +3865,22 @@ int32_t
nfs3svc_link_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, inode_t *inode,
struct iatt *buf, struct iatt *preparent,
- struct iatt *postparent)
+ struct iatt *postparent, dict_t *xdata)
{
nfsstat3 stat = NFS3ERR_SERVERFAULT;
nfs3_call_state_t *cs = NULL;
cs = frame->local;
- if (op_ret == -1)
- stat = nfs3_errno_to_nfsstat3 (op_errno);
- else
+ if (op_ret == -1) {
+ gf_log (GF_NFS, GF_LOG_WARNING,
+ "%x: link %s <- %s => -1 (%s)",
+ rpcsvc_request_xid (cs->req), cs->oploc.path,
+ cs->resolvedloc.path, strerror (op_errno));
+ stat = nfs3_cbk_errno_status (op_ret, op_errno);
+ } else
stat = NFS3_OK;
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "LINK", stat,
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_LINK, stat,
op_errno);
nfs3_link_reply (cs->req, stat, buf, preparent, postparent);
nfs3_call_state_wipe (cs);
@@ -3405,8 +3911,8 @@ nfs3_link_resume_lnk (void *carg)
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "LINK", stat,
- -ret);
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_LINK,
+ stat, -ret);
nfs3_link_reply (cs->req, stat, NULL, NULL, NULL);
nfs3_call_state_wipe (cs);
}
@@ -3436,8 +3942,8 @@ nfs3_link_resume_tgt (void *carg)
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "LINK", stat,
- -ret);
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_LINK,
+ stat, -ret);
nfs3_link_reply (cs->req, stat, NULL, NULL, NULL);
nfs3_call_state_wipe (cs);
}
@@ -3466,11 +3972,12 @@ nfs3_link (rpcsvc_request_t *req, struct nfs3_fh *targetfh,
nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret);
nfs3_validate_strlen_or_goto(newname, NFS_NAME_MAX, nfs3err, stat, ret);
nfs3_map_fh_to_volume (nfs3, dirfh, req, vol, stat, nfs3err);
- nfs3_check_rw_volaccess (nfs3, dirfh->xlatorid, stat, nfs3err);
+ nfs3_volume_started_check (nfs3, vol, ret, out);
+ nfs3_check_rw_volaccess (nfs3, dirfh->exportid, stat, nfs3err);
nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);
cs->fh = *dirfh;
- cs->pathname = strdup (newname);
+ cs->pathname = gf_strdup (newname);
if (!cs->pathname) {
stat = NFS3ERR_SERVERFAULT;
ret = -1;
@@ -3484,7 +3991,7 @@ nfs3_link (rpcsvc_request_t *req, struct nfs3_fh *targetfh,
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (req), "LINK", stat,
+ nfs3_log_common_res (rpcsvc_request_xid (req), NFS3_LINK, stat,
-ret);
nfs3_link_reply (req, stat, NULL, NULL, NULL);
nfs3_call_state_wipe (cs);
@@ -3493,7 +4000,7 @@ nfs3err:
*/
ret = 0;
}
-
+out:
return ret;
}
@@ -3509,14 +4016,14 @@ nfs3svc_link (rpcsvc_request_t *req)
if (!req)
return ret;
nfs3_prep_link3args (&args, &targetfh, &dirfh, newpath);
- if (xdr_to_link3args (req->msg, &args) <= 0) {
+ if (xdr_to_link3args (req->msg[0], &args) <= 0) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Error decoding args");
rpcsvc_request_seterr (req, GARBAGE_ARGS);
goto rpcerr;
}
ret = nfs3_link (req, &targetfh, &dirfh, newpath);
- if (ret < 0) {
+ if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
gf_log (GF_NFS3, GF_LOG_ERROR, "LINK procedure failed");
rpcsvc_request_seterr (req, SYSTEM_ERR);
ret = RPCSVC_ACTOR_ERROR;
@@ -3532,10 +4039,12 @@ nfs3_readdirp_reply (rpcsvc_request_t *req, nfsstat3 stat,struct nfs3_fh *dirfh,
uint64_t cverf, struct iatt *dirstat, gf_dirent_t *entries,
count3 dircount, count3 maxcount, int is_eof)
{
- readdirp3res res = {0, };
+ readdirp3res res = {0, };
+ uint64_t deviceid = 0;
+ deviceid = nfs3_request_xlator_deviceid (req);
nfs3_fill_readdirp3res (&res, stat, dirfh, cverf, dirstat, entries,
- dircount, maxcount, is_eof);
+ dircount, maxcount, is_eof, deviceid);
nfs3svc_submit_reply (req, (void *)&res,
(nfs3_serializer) xdr_serialize_readdirp3res);
nfs3_free_readdirp3res (&res);
@@ -3545,16 +4054,16 @@ nfs3_readdirp_reply (rpcsvc_request_t *req, nfsstat3 stat,struct nfs3_fh *dirfh,
int
-nfs3_readdir_reply (rpcsvc_request_t *req, nfsstat3 stat, uint64_t cverf,
- struct iatt *dirstat, gf_dirent_t *entries, count3 count,
- int is_eof)
+nfs3_readdir_reply (rpcsvc_request_t *req, nfsstat3 stat, struct nfs3_fh *dirfh,
+ uint64_t cverf, struct iatt *dirstat, gf_dirent_t *entries,
+ count3 count, int is_eof)
{
readdir3res res = {0, };
- uint16_t xlid = 0;
+ uint64_t deviceid = 0;
- xlid = nfs3_request_xlator_id (req);
- nfs3_fill_readdir3res (&res, stat, cverf, dirstat, entries, count,
- is_eof, xlid);
+ deviceid = nfs3_request_xlator_deviceid (req);
+ nfs3_fill_readdir3res (&res, stat, dirfh, cverf, dirstat, entries, count
+ , is_eof, deviceid);
nfs3svc_submit_reply (req, (void *)&res,
(nfs3_serializer) xdr_serialize_readdir3res);
nfs3_free_readdir3res (&res);
@@ -3565,7 +4074,8 @@ nfs3_readdir_reply (rpcsvc_request_t *req, nfsstat3 stat, uint64_t cverf,
int32_t
nfs3svc_readdir_fstat_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno, struct iatt *buf)
+ int32_t op_ret, int32_t op_errno, struct iatt *buf,
+ dict_t *xdata)
{
nfsstat3 stat = NFS3ERR_SERVERFAULT;
int is_eof = 0;
@@ -3573,7 +4083,10 @@ nfs3svc_readdir_fstat_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
cs = frame->local;
if (op_ret == -1) {
- stat = nfs3_errno_to_nfsstat3 (op_errno);
+ gf_log (GF_NFS, GF_LOG_WARNING,
+ "%x: %s => -1 (%s)", rpcsvc_request_xid (cs->req),
+ cs->resolvedloc.path, strerror (op_errno));
+ stat = nfs3_cbk_errno_status (op_ret, op_errno);
goto nfs3err;
}
@@ -3591,9 +4104,9 @@ nfs3err:
nfs3_log_readdir_res (rpcsvc_request_xid (cs->req), stat,
op_errno, (uintptr_t)cs->fd,
cs->dircount, is_eof);
- nfs3_readdir_reply (cs->req, stat, (uintptr_t)cs->fd,
- buf, &cs->entries, cs->dircount,
- is_eof);
+ nfs3_readdir_reply (cs->req, stat, &cs->parent,
+ (uintptr_t)cs->fd, buf, &cs->entries,
+ cs->dircount, is_eof);
} else {
nfs3_log_readdirp_res (rpcsvc_request_xid (cs->req), stat,
op_errno, (uintptr_t)cs->fd,
@@ -3605,11 +4118,9 @@ nfs3err:
}
if (is_eof) {
- gf_log (GF_NFS3, GF_LOG_TRACE, "EOF REF: %d", cs->fd->refcount);
- fd_unref (cs->fd);
+ /* do nothing */
}
- gf_log (GF_NFS3, GF_LOG_TRACE, "CS WIPE REF: %d", cs->fd->refcount);
nfs3_call_state_wipe (cs);
return 0;
}
@@ -3617,7 +4128,8 @@ nfs3err:
int32_t
nfs3svc_readdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno, gf_dirent_t *entries)
+ int32_t op_ret, int32_t op_errno, gf_dirent_t *entries,
+ dict_t *xdata)
{
nfsstat3 stat = NFS3ERR_SERVERFAULT;
int ret = -EFAULT;
@@ -3626,7 +4138,10 @@ nfs3svc_readdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
cs = frame->local;
if (op_ret == -1) {
- stat = nfs3_errno_to_nfsstat3 (op_errno);
+ gf_log (GF_NFS, GF_LOG_WARNING,
+ "%x: %s => -1 (%s)", rpcsvc_request_xid (cs->req),
+ cs->resolvedloc.path, strerror (op_errno));
+ stat = nfs3_cbk_errno_status (op_ret, op_errno);
goto err;
}
@@ -3646,12 +4161,12 @@ err:
goto ret;
if (cs->maxcount == 0) {
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "READDIR",
- stat, op_errno);
- nfs3_readdir_reply (cs->req, stat, 0, NULL, NULL, 0, 0);
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req),
+ NFS3_READDIR, stat, op_errno);
+ nfs3_readdir_reply (cs->req, stat, NULL, 0, NULL, NULL, 0, 0);
} else {
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "READDIRP"
- , stat, op_errno);
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req),
+ NFS3_READDIRP, stat, op_errno);
nfs3_readdirp_reply (cs->req, stat, NULL, 0, NULL, NULL,
0, 0, 0);
}
@@ -3660,7 +4175,6 @@ err:
* so that next time the dir is read, we'll get any changed directory
* entries.
*/
- fd_unref (cs->fd);
nfs3_call_state_wipe (cs);
ret:
return 0;
@@ -3708,11 +4222,12 @@ nfs3err:
if (ret < 0) {
if (cs->maxcount == 0) {
nfs3_log_common_res (rpcsvc_request_xid (cs->req),
- "READDIR", stat, -ret);
- nfs3_readdir_reply (cs->req, stat, 0, NULL, NULL, 0, 0);
+ NFS3_READDIR, stat, -ret);
+ nfs3_readdir_reply (cs->req, stat, NULL, 0, NULL, NULL,
+ 0, 0);
} else {
nfs3_log_common_res (rpcsvc_request_xid (cs->req),
- "READDIRP", stat, -ret);
+ NFS3_READDIRP, stat, -ret);
nfs3_readdirp_reply (cs->req, stat, NULL, 0, NULL, NULL,
0, 0, 0);
}
@@ -3723,19 +4238,59 @@ nfs3err:
}
+int32_t
+nfs3svc_readdir_opendir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, fd_t *fd,
+ dict_t *xdata)
+{
+ /*
+ * We don't really need this, it's just an artifact of forcing the
+ * opendir to happen.
+ */
+ if (fd) {
+ fd_unref(fd);
+ }
+
+ return 0;
+}
+
+
int
nfs3_readdir_open_resume (void *carg)
{
nfsstat3 stat = NFS3ERR_SERVERFAULT;
int ret = -EFAULT;
nfs3_call_state_t *cs = NULL;
+ nfs_user_t nfu = {0, };
if (!carg)
return ret;
cs = (nfs3_call_state_t *)carg;
nfs3_check_fh_resolve_status (cs, stat, nfs3err);
- ret = nfs3_dir_open_and_resume (cs, nfs3_readdir_read_resume);
+ cs->fd = fd_anonymous (cs->resolvedloc.inode);
+ if (!cs->fd) {
+ gf_log (GF_NFS3, GF_LOG_ERROR, "Faile to create anonymous fd");
+ goto nfs3err;
+ }
+
+ /*
+ * NFS client will usually send us a readdirp without an opendir,
+ * which would cause us to skip our usual self-heal checks which occur
+ * in opendir for native protocol. To make sure those checks do happen,
+ * our most reliable option is to do our own opendir for any readdirp
+ * at the beginning of the directory.
+ */
+ if (cs->cookie == 0) {
+ nfs_request_user_init (&nfu, cs->req);
+ ret = nfs_opendir (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
+ nfs3svc_readdir_opendir_cbk, cs);
+ if (ret < 0) {
+ gf_log (GF_NFS3, GF_LOG_ERROR, "auto-opendir failed");
+ }
+ }
+
+ ret = nfs3_readdir_read_resume (cs);
if (ret < 0)
stat = nfs3_errno_to_nfsstat3 (-ret);
@@ -3743,11 +4298,12 @@ nfs3err:
if (ret < 0) {
if (cs->maxcount == 0) {
nfs3_log_common_res (rpcsvc_request_xid (cs->req),
- "READDIR", stat, -ret);
- nfs3_readdir_reply (cs->req, stat, 0, NULL, NULL, 0, 0);
+ NFS3_READDIR, stat, -ret);
+ nfs3_readdir_reply (cs->req, stat, NULL, 0, NULL, NULL,
+ 0, 0);
} else {
nfs3_log_common_res (rpcsvc_request_xid (cs->req),
- "READDIRP", stat, -ret);
+ NFS3_READDIRP, stat, -ret);
nfs3_readdirp_reply (cs->req, stat, NULL, 0, NULL, NULL,
0, 0, 0);
}
@@ -3774,10 +4330,12 @@ nfs3_readdir (rpcsvc_request_t *req, struct nfs3_fh *fh, cookie3 cookie,
return -1;
}
- nfs3_log_readdir_call (rpcsvc_request_xid (req), fh, dircount,maxcount);
+ nfs3_log_readdir_call (rpcsvc_request_xid (req), fh, dircount,
+ maxcount);
nfs3_validate_gluster_fh (fh, stat, nfs3err);
nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret);
nfs3_map_fh_to_volume (nfs3, fh, req, vol, stat, nfs3err);
+ nfs3_volume_started_check (nfs3, vol, ret, out);
nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);
cs->cookieverf = cverf;
@@ -3793,12 +4351,13 @@ nfs3_readdir (rpcsvc_request_t *req, struct nfs3_fh *fh, cookie3 cookie,
nfs3err:
if (ret < 0) {
if (maxcount == 0) {
- nfs3_log_common_res (rpcsvc_request_xid (req), "READDIR"
- , stat, -ret);
- nfs3_readdir_reply (req, stat, 0, NULL, NULL, 0, 0);
+ nfs3_log_common_res (rpcsvc_request_xid (req),
+ NFS3_READDIR, stat, -ret);
+ nfs3_readdir_reply (req, stat, NULL, 0, NULL, NULL, 0,
+ 0);
} else {
- nfs3_log_common_res (rpcsvc_request_xid (req),"READDIRP"
- , stat, -ret);
+ nfs3_log_common_res (rpcsvc_request_xid (req),
+ NFS3_READDIRP, stat, -ret);
nfs3_readdirp_reply (req, stat, NULL, 0, NULL, NULL, 0,
0, 0);
}
@@ -3808,7 +4367,7 @@ nfs3err:
ret = 0;
nfs3_call_state_wipe (cs);
}
-
+out:
return ret;
}
@@ -3820,19 +4379,21 @@ nfs3svc_readdir (rpcsvc_request_t *req)
struct nfs3_fh fh = {{0},};
int ret = RPCSVC_ACTOR_ERROR;
uint64_t verf = 0;
+ uint64_t *cval;
if (!req)
return ret;
nfs3_prep_readdir3args (&ra, &fh);
- if (xdr_to_readdir3args (req->msg, &ra) <= 0) {
+ if (xdr_to_readdir3args (req->msg[0], &ra) <= 0) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Error decoding args");
rpcsvc_request_seterr (req, GARBAGE_ARGS);
goto rpcerr;
}
+ cval = (uint64_t *) ra.cookieverf;
+ verf = *cval;
- verf = *(uint64_t *)ra.cookieverf;
ret = nfs3_readdir (req, &fh, ra.cookie, verf, ra.count, 0);
- if (ret < 0) {
+ if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
gf_log (GF_NFS3, GF_LOG_ERROR, "READDIR procedure failed");
rpcsvc_request_seterr (req, SYSTEM_ERR);
ret = RPCSVC_ACTOR_ERROR;
@@ -3850,20 +4411,22 @@ nfs3svc_readdirp (rpcsvc_request_t *req)
struct nfs3_fh fh = {{0},};
int ret = RPCSVC_ACTOR_ERROR;
uint64_t cverf = 0;
+ uint64_t *cval;
if (!req)
return ret;
nfs3_prep_readdirp3args (&ra, &fh);
- if (xdr_to_readdirp3args (req->msg, &ra) <= 0) {
+ if (xdr_to_readdirp3args (req->msg[0], &ra) <= 0) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Error decoding args");
rpcsvc_request_seterr (req, GARBAGE_ARGS);
goto rpcerr;
}
+ cval = (uint64_t *) ra.cookieverf;
+ cverf = *cval;
- cverf = *(uint64_t *)ra.cookieverf;
ret = nfs3_readdir (req, &fh, ra.cookie, cverf, ra.dircount,
ra.maxcount);
- if (ret < 0) {
+ if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
gf_log (GF_NFS3, GF_LOG_ERROR, "READDIRP procedure failed");
rpcsvc_request_seterr (req, SYSTEM_ERR);
ret = RPCSVC_ACTOR_ERROR;
@@ -3879,10 +4442,10 @@ nfs3_fsstat_reply (rpcsvc_request_t *req, nfsstat3 stat, struct statvfs *fsbuf,
struct iatt *postbuf)
{
fsstat3res res = {0, };
- uint16_t xlid = 0;
+ uint64_t deviceid = 0;
- xlid = nfs3_request_xlator_id (req);
- nfs3_fill_fsstat3res (&res, stat, fsbuf, postbuf, xlid);
+ deviceid = nfs3_request_xlator_deviceid (req);
+ nfs3_fill_fsstat3res (&res, stat, fsbuf, postbuf, deviceid);
return nfs3svc_submit_reply (req, &res,
(nfs3_serializer)xdr_serialize_fsstat3res);
@@ -3891,18 +4454,22 @@ nfs3_fsstat_reply (rpcsvc_request_t *req, nfsstat3 stat, struct statvfs *fsbuf,
int32_t
nfs3_fsstat_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno, struct iatt *buf)
+ int32_t op_ret, int32_t op_errno, struct iatt *buf,
+ dict_t *xdata)
{
nfsstat3 stat = NFS3ERR_SERVERFAULT;
nfs3_call_state_t *cs = NULL;
cs = frame->local;
- if (op_ret == -1)
- stat = nfs3_errno_to_nfsstat3 (op_errno);
- else
+ if (op_ret == -1) {
+ gf_log (GF_NFS, GF_LOG_WARNING,
+ "%x: %s => -1 (%s)", rpcsvc_request_xid (cs->req),
+ cs->resolvedloc.path, strerror (op_errno));
+ stat = nfs3_cbk_errno_status (op_ret, op_errno);
+ } else
stat = NFS3_OK;
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "FSTAT", stat,
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_FSSTAT, stat,
op_errno);
nfs3_fsstat_reply (cs->req, stat, &cs->fsstat, buf);
nfs3_call_state_wipe (cs);
@@ -3912,7 +4479,8 @@ nfs3_fsstat_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t
nfs3_fsstat_statfs_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno, struct statvfs *buf)
+ int32_t op_ret, int32_t op_errno, struct statvfs *buf,
+ dict_t *xdata)
{
nfs_user_t nfu = {0, };
int ret = -EFAULT;
@@ -3921,8 +4489,11 @@ nfs3_fsstat_statfs_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
cs = frame->local;
if (op_ret == -1) {
+ gf_log (GF_NFS, GF_LOG_WARNING,
+ "%x: %s => -1 (%s)", rpcsvc_request_xid (cs->req),
+ cs->resolvedloc.path, strerror (op_errno));
ret = -op_errno;
- stat = nfs3_errno_to_nfsstat3 (op_errno);
+ stat = nfs3_cbk_errno_status (op_ret, op_errno);
goto err;
}
@@ -3938,7 +4509,7 @@ nfs3_fsstat_statfs_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "FSTAT",
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_FSSTAT,
stat, -ret);
nfs3_fsstat_reply (cs->req, stat, NULL, NULL);
nfs3_call_state_wipe (cs);
@@ -3970,8 +4541,8 @@ nfs3_fsstat_resume (void *carg)
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "FSTAT",
- stat, -ret);
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_FSSTAT,
+ stat, -ret);
nfs3_fsstat_reply (cs->req, stat, NULL, NULL);
nfs3_call_state_wipe (cs);
}
@@ -3999,6 +4570,7 @@ nfs3_fsstat (rpcsvc_request_t *req, struct nfs3_fh *fh)
nfs3_validate_gluster_fh (fh, stat, nfs3err);
nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret);
nfs3_map_fh_to_volume (nfs3, fh, req, vol, stat, nfs3err);
+ nfs3_volume_started_check (nfs3, vol, ret, out);
nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);
ret = nfs3_fh_resolve_and_resume (cs, fh, NULL, nfs3_fsstat_resume);
@@ -4007,8 +4579,8 @@ nfs3_fsstat (rpcsvc_request_t *req, struct nfs3_fh *fh)
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (req), "FSTAT", stat,
- -ret);
+ nfs3_log_common_res (rpcsvc_request_xid (req), NFS3_FSSTAT,
+ stat, -ret);
nfs3_fsstat_reply (req, stat, NULL, NULL);
nfs3_call_state_wipe (cs);
/* Ret must be 0 after this so that the caller does not
@@ -4016,7 +4588,7 @@ nfs3err:
*/
ret = 0;
}
-
+out:
return ret;
}
@@ -4031,14 +4603,14 @@ nfs3svc_fsstat (rpcsvc_request_t *req)
if (!req)
return ret;
nfs3_prep_fsstat3args (&args, &fh);
- if (xdr_to_fsstat3args (req->msg, &args) <= 0) {
+ if (xdr_to_fsstat3args (req->msg[0], &args) <= 0) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Error decoding args");
rpcsvc_request_seterr (req, GARBAGE_ARGS);
goto rpcerr;
}
ret = nfs3_fsstat (req, &fh);
- if (ret < 0) {
+ if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
gf_log (GF_NFS3, GF_LOG_ERROR, "FSTAT procedure failed");
rpcsvc_request_seterr (req, SYSTEM_ERR);
ret = RPCSVC_ACTOR_ERROR;
@@ -4054,11 +4626,11 @@ nfs3_fsinfo_reply (rpcsvc_request_t *req, nfsstat3 status, struct iatt *fsroot)
{
fsinfo3res res;
struct nfs3_state *nfs3 = NULL;
- uint16_t xlid = 0;
+ uint64_t deviceid = 0;
- xlid = nfs3_request_xlator_id (req);
+ deviceid = nfs3_request_xlator_deviceid (req);
nfs3 = rpcsvc_request_program_private (req);
- nfs3_fill_fsinfo3res (nfs3, &res, status, fsroot, xlid);
+ nfs3_fill_fsinfo3res (nfs3, &res, status, fsroot, deviceid);
nfs3svc_submit_reply (req, &res,
(nfs3_serializer)xdr_serialize_fsinfo3res);
@@ -4068,19 +4640,23 @@ nfs3_fsinfo_reply (rpcsvc_request_t *req, nfsstat3 status, struct iatt *fsroot)
int32_t
nfs3svc_fsinfo_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno, struct iatt *buf)
+ int32_t op_ret, int32_t op_errno, struct iatt *buf,
+ dict_t *xdata)
{
nfsstat3 status = NFS3ERR_SERVERFAULT;
nfs3_call_state_t *cs = NULL;
cs = frame->local;
- if (op_ret == -1)
- status = nfs3_errno_to_nfsstat3 (op_errno);
- else
+ if (op_ret == -1) {
+ gf_log (GF_NFS, GF_LOG_WARNING,
+ "%x: %s => -1 (%s)", rpcsvc_request_xid (cs->req),
+ cs->resolvedloc.path, strerror (op_errno));
+ status = nfs3_cbk_errno_status (op_ret, op_errno);
+ }else
status = NFS3_OK;
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "FSINFO", status,
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_FSINFO, status,
op_errno);
nfs3_fsinfo_reply (cs->req, status, buf);
@@ -4113,7 +4689,7 @@ nfs3_fsinfo_resume (void *carg)
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "FSINFO",
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_FSINFO,
stat, -ret);
nfs3_fsinfo_reply (cs->req, stat, NULL);
nfs3_call_state_wipe (cs);
@@ -4141,6 +4717,7 @@ nfs3_fsinfo (rpcsvc_request_t *req, struct nfs3_fh *fh)
nfs3_validate_gluster_fh (fh, stat, nfs3err);
nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret);
nfs3_map_fh_to_volume (nfs3, fh, req, vol, stat, nfs3err);
+ nfs3_volume_started_check (nfs3, vol, ret, out);
nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);
ret = nfs3_fh_resolve_and_resume (cs, fh, NULL, nfs3_fsinfo_resume);
@@ -4149,13 +4726,13 @@ nfs3_fsinfo (rpcsvc_request_t *req, struct nfs3_fh *fh)
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (req), "FSINFO", stat,
- -ret);
+ nfs3_log_common_res (rpcsvc_request_xid (req), NFS3_FSINFO,
+ stat, -ret);
nfs3_fsinfo_reply (req, stat, NULL);
nfs3_call_state_wipe (cs);
ret = 0;
}
-
+out:
return ret;
}
@@ -4171,14 +4748,14 @@ nfs3svc_fsinfo (rpcsvc_request_t *req)
return ret;
nfs3_prep_fsinfo3args (&args, &root);
- if (xdr_to_fsinfo3args (req->msg, &args) <= 0) {
+ if (xdr_to_fsinfo3args (req->msg[0], &args) <= 0) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Error decoding arguments");
rpcsvc_request_seterr (req, GARBAGE_ARGS);
goto rpcerr;
}
ret = nfs3_fsinfo (req, &root);
- if (ret < 0) {
+ if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
gf_log (GF_NFS3, GF_LOG_ERROR, "FSINFO procedure failed");
rpcsvc_request_seterr (req, SYSTEM_ERR);
ret = RPCSVC_ACTOR_ERROR;
@@ -4193,10 +4770,10 @@ int
nfs3_pathconf_reply (rpcsvc_request_t *req, nfsstat3 stat, struct iatt *buf)
{
pathconf3res res = {0, };
- uint16_t xlid = 0;
+ uint64_t deviceid = 0;
- xlid = nfs3_request_xlator_id (req);
- nfs3_fill_pathconf3res (&res, stat, buf, xlid);
+ deviceid = nfs3_request_xlator_deviceid (req);
+ nfs3_fill_pathconf3res (&res, stat, buf, deviceid);
nfs3svc_submit_reply (req, (void *)&res,
(nfs3_serializer)xdr_serialize_pathconf3res);
return 0;
@@ -4205,16 +4782,20 @@ nfs3_pathconf_reply (rpcsvc_request_t *req, nfsstat3 stat, struct iatt *buf)
int32_t
nfs3svc_pathconf_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno, struct iatt *buf)
+ int32_t op_ret, int32_t op_errno, struct iatt *buf,
+ dict_t *xdata)
{
struct iatt *sbuf = NULL;
nfs3_call_state_t *cs = NULL;
nfsstat3 stat = NFS3ERR_SERVERFAULT;
cs = frame->local;
- if (op_ret == -1)
- stat = nfs3_errno_to_nfsstat3 (op_errno);
- else {
+ if (op_ret == -1) {
+ gf_log (GF_NFS, GF_LOG_WARNING,
+ "%x: %s => -1 (%s)", rpcsvc_request_xid (cs->req),
+ cs->resolvedloc.path, strerror (op_errno));
+ stat = nfs3_cbk_errno_status (op_ret, op_errno);
+ } else {
/* If stat fop failed, we can still send the other components
* in a pathconf reply.
*/
@@ -4222,7 +4803,7 @@ nfs3svc_pathconf_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
stat = NFS3_OK;
}
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "PATHCONF", stat,
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_PATHCONF, stat,
op_errno);
nfs3_pathconf_reply (cs->req, stat, sbuf);
nfs3_call_state_wipe (cs);
@@ -4251,8 +4832,8 @@ nfs3_pathconf_resume (void *carg)
stat = nfs3_errno_to_nfsstat3 (-ret);
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "PATHCONF",
- stat, -ret);
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req),
+ NFS3_PATHCONF, stat, -ret);
nfs3_pathconf_reply (cs->req, stat, NULL);
nfs3_call_state_wipe (cs);
}
@@ -4278,6 +4859,7 @@ nfs3_pathconf (rpcsvc_request_t *req, struct nfs3_fh *fh)
nfs3_validate_gluster_fh (fh, stat, nfs3err);
nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret);
nfs3_map_fh_to_volume (nfs3, fh, req, vol, stat, nfs3err);
+ nfs3_volume_started_check (nfs3, vol, ret, out);
nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);
ret = nfs3_fh_resolve_and_resume (cs, fh, NULL, nfs3_pathconf_resume);
@@ -4286,8 +4868,8 @@ nfs3_pathconf (rpcsvc_request_t *req, struct nfs3_fh *fh)
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (req), "PATHCONF", stat,
- -ret);
+ nfs3_log_common_res (rpcsvc_request_xid (req), NFS3_PATHCONF,
+ stat, -ret);
nfs3_pathconf_reply (req, stat, NULL);
nfs3_call_state_wipe (cs);
/* Ret must be 0 after this so that the caller does not
@@ -4295,7 +4877,7 @@ nfs3err:
*/
ret = 0;
}
-
+out:
return ret;
}
@@ -4310,14 +4892,14 @@ nfs3svc_pathconf (rpcsvc_request_t *req)
if (!req)
return ret;
nfs3_prep_pathconf3args (&args, &fh);
- if (xdr_to_pathconf3args (req->msg, &args) <= 0) {
+ if (xdr_to_pathconf3args (req->msg[0], &args) <= 0) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Error decoding args");
rpcsvc_request_seterr (req, GARBAGE_ARGS);
goto rpcerr;
}
ret = nfs3_pathconf (req, &fh);
- if (ret < 0) {
+ if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
gf_log (GF_NFS3, GF_LOG_ERROR, "PATHCONF procedure failed");
rpcsvc_request_seterr (req, SYSTEM_ERR);
ret = RPCSVC_ACTOR_ERROR;
@@ -4332,10 +4914,10 @@ nfs3_commit_reply (rpcsvc_request_t *req, nfsstat3 stat, uint64_t wverf,
struct iatt *prestat, struct iatt *poststat)
{
commit3res res = {0, };
- uint16_t xlid = 0;
+ uint64_t deviceid = 0;
- xlid = nfs3_request_xlator_id (req);
- nfs3_fill_commit3res (&res, stat, wverf, prestat, poststat, xlid);
+ deviceid = nfs3_request_xlator_deviceid (req);
+ nfs3_fill_commit3res (&res, stat, wverf, prestat, poststat, deviceid);
nfs3svc_submit_reply (req, (void *)&res,
(nfs3_serializer)xdr_serialize_commit3res);
@@ -4345,23 +4927,25 @@ nfs3_commit_reply (rpcsvc_request_t *req, nfsstat3 stat, uint64_t wverf,
int32_t
nfs3svc_commit_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno, struct iatt *prebuf,
- struct iatt *postbuf)
+ int32_t op_ret, int32_t op_errno, dict_t *xdata)
{
nfsstat3 stat = NFS3ERR_SERVERFAULT;
nfs3_call_state_t *cs = NULL;
struct nfs3_state *nfs3 = NULL;
cs = frame->local;
- if (op_ret == -1)
- stat = nfs3_errno_to_nfsstat3 (op_errno);
- else
+ if (op_ret == -1) {
+ gf_log (GF_NFS, GF_LOG_WARNING,
+ "%x: %s => -1 (%s)", rpcsvc_request_xid (cs->req),
+ cs->resolvedloc.path, strerror (op_errno));
+ stat = nfs3_cbk_errno_status (op_ret, op_errno);
+ } else
stat = NFS3_OK;
nfs3 = rpcsvc_request_program_private (cs->req);
nfs3_log_commit_res (rpcsvc_request_xid (cs->req), stat, op_errno,
nfs3->serverstart);
- nfs3_commit_reply (cs->req, stat, nfs3->serverstart, prebuf, postbuf);
+ nfs3_commit_reply (cs->req, stat, nfs3->serverstart, NULL, NULL);
nfs3_call_state_wipe (cs);
return 0;
@@ -4380,22 +4964,30 @@ nfs3_commit_resume (void *carg)
cs = (nfs3_call_state_t *)carg;
nfs3_check_fh_resolve_status (cs, stat, nfs3err);
+
+ if (nfs3_export_sync_trusted (cs->nfs3state, cs->resolvefh.exportid)) {
+ ret = -1;
+ stat = NFS3_OK;
+ goto nfs3err;
+ }
+
nfs_request_user_init (&nfu, cs->req);
- ret = nfs_fsync (cs->nfsx, cs->vol, &nfu, cs->fd, 0,
+ ret = nfs_flush (cs->nfsx, cs->vol, &nfu, cs->fd,
nfs3svc_commit_cbk, cs);
if (ret < 0)
stat = nfs3_errno_to_nfsstat3 (-ret);
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "COMMIT",
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_COMMIT,
stat, -ret);
- nfs3_commit_reply (cs->req, stat, 0, NULL, NULL);
+ nfs3_commit_reply (cs->req, stat, cs->nfs3state->serverstart,
+ NULL, NULL);
nfs3_call_state_wipe (cs);
ret = 0;
}
- return ret;
+ return 0;
}
@@ -4411,13 +5003,18 @@ nfs3_commit_open_resume (void *carg)
cs = (nfs3_call_state_t *)carg;
nfs3_check_fh_resolve_status (cs, stat, nfs3err);
+ cs->fd = fd_anonymous (cs->resolvedloc.inode);
+ if (!cs->fd) {
+ gf_log (GF_NFS3, GF_LOG_ERROR, "Failed to create anonymous fd.");
+ goto nfs3err;
+ }
- ret = nfs3_file_open_and_resume (cs, nfs3_commit_resume);
+ ret = nfs3_commit_resume (cs);
if (ret < 0)
stat = nfs3_errno_to_nfsstat3 (-ret);
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (cs->req), "COMMIT",
+ nfs3_log_common_res (rpcsvc_request_xid (cs->req), NFS3_COMMIT,
stat, -ret);
nfs3_commit_reply (cs->req, stat, 0, NULL, NULL);
nfs3_call_state_wipe (cs);
@@ -4443,12 +5040,13 @@ nfs3_commit (rpcsvc_request_t *req, struct nfs3_fh *fh, offset3 offset,
return -1;
}
- nfs3_log_rw_call (rpcsvc_request_xid (req), "COMMIT", fh, offset, count,
- -1);
+ nfs3_log_rw_call (rpcsvc_request_xid (req), "COMMIT", fh, offset,
+ count, -1);
nfs3_validate_gluster_fh (fh, stat, nfs3err);
nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret);
nfs3_map_fh_to_volume (nfs3, fh, req, vol, stat, nfs3err);
- nfs3_check_rw_volaccess (nfs3, fh->xlatorid, stat, nfs3err);
+ nfs3_volume_started_check (nfs3, vol, ret, out);
+ nfs3_check_rw_volaccess (nfs3, fh->exportid, stat, nfs3err);
nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);
cs->datacount = count;
@@ -4460,13 +5058,13 @@ nfs3_commit (rpcsvc_request_t *req, struct nfs3_fh *fh, offset3 offset,
nfs3err:
if (ret < 0) {
- nfs3_log_common_res (rpcsvc_request_xid (req), "COMMIT", stat,
- -ret);
+ nfs3_log_common_res (rpcsvc_request_xid (req), NFS3_COMMIT,
+ stat, -ret);
nfs3_commit_reply (req, stat, 0, NULL, NULL);
nfs3_call_state_wipe (cs);
ret = 0;
}
-
+out:
return ret;
}
@@ -4482,14 +5080,14 @@ nfs3svc_commit (rpcsvc_request_t *req)
if (!req)
return ret;
nfs3_prep_commit3args (&args, &fh);
- if (xdr_to_commit3args (req->msg, &args) <= 0) {
+ if (xdr_to_commit3args (req->msg[0], &args) <= 0) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Error decoding args");
rpcsvc_request_seterr (req, GARBAGE_ARGS);
goto rpcerr;
}
ret = nfs3_commit (req, &fh, args.offset, args.count);
- if (ret < 0) {
+ if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
gf_log (GF_NFS3, GF_LOG_ERROR, "COMMIT procedure failed");
rpcsvc_request_seterr (req, SYSTEM_ERR);
ret = RPCSVC_ACTOR_ERROR;
@@ -4501,28 +5099,28 @@ rpcerr:
rpcsvc_actor_t nfs3svc_actors[NFS3_PROC_COUNT] = {
- {"NULL", NFS3_NULL, nfs3svc_null, NULL, NULL},
- {"GETATTR", NFS3_GETATTR, nfs3svc_getattr,NULL, NULL},
- {"SETATTR", NFS3_SETATTR, nfs3svc_setattr,NULL, NULL},
- {"LOOKUP", NFS3_LOOKUP, nfs3svc_lookup, NULL, NULL},
- {"ACCESS", NFS3_ACCESS, nfs3svc_access, NULL, NULL},
- {"READLINK", NFS3_READLINK, nfs3svc_readlink,NULL, NULL},
- {"READ", NFS3_READ, nfs3svc_read, NULL, NULL},
- {"WRITE", NFS3_WRITE, nfs3svc_write, nfs3svc_write_vec, nfs3svc_write_vecsizer},
- {"CREATE", NFS3_CREATE, nfs3svc_create, NULL, NULL},
- {"MKDIR", NFS3_MKDIR, nfs3svc_mkdir, NULL, NULL},
- {"SYMLINK", NFS3_SYMLINK, nfs3svc_symlink,NULL, NULL},
- {"MKNOD", NFS3_MKNOD, nfs3svc_mknod, NULL, NULL},
- {"REMOVE", NFS3_REMOVE, nfs3svc_remove, NULL, NULL},
- {"RMDIR", NFS3_RMDIR, nfs3svc_rmdir, NULL, NULL},
- {"RENAME", NFS3_RENAME, nfs3svc_rename, NULL, NULL},
- {"LINK", NFS3_LINK, nfs3svc_link, NULL, NULL},
- {"READDIR", NFS3_READDIR, nfs3svc_readdir,NULL, NULL},
- {"READDIRPLUS", NFS3_READDIRP, nfs3svc_readdirp,NULL, NULL},
- {"FSSTAT", NFS3_FSSTAT, nfs3svc_fsstat, NULL, NULL},
- {"FSINFO", NFS3_FSINFO, nfs3svc_fsinfo, NULL, NULL},
- {"PATHCONF", NFS3_PATHCONF, nfs3svc_pathconf,NULL, NULL},
- {"COMMIT", NFS3_COMMIT, nfs3svc_commit, NULL, NULL}
+ {"NULL", NFS3_NULL, nfs3svc_null, NULL, 0, DRC_IDEMPOTENT},
+ {"GETATTR", NFS3_GETATTR, nfs3svc_getattr, NULL, 0, DRC_IDEMPOTENT},
+ {"SETATTR", NFS3_SETATTR, nfs3svc_setattr, NULL, 0, DRC_NON_IDEMPOTENT},
+ {"LOOKUP", NFS3_LOOKUP, nfs3svc_lookup, NULL, 0, DRC_IDEMPOTENT},
+ {"ACCESS", NFS3_ACCESS, nfs3svc_access, NULL, 0, DRC_IDEMPOTENT},
+ {"READLINK", NFS3_READLINK, nfs3svc_readlink, NULL, 0, DRC_IDEMPOTENT},
+ {"READ", NFS3_READ, nfs3svc_read, NULL, 0, DRC_IDEMPOTENT},
+ {"WRITE", NFS3_WRITE, nfs3svc_write, nfs3svc_write_vecsizer, 0, DRC_NON_IDEMPOTENT},
+ {"CREATE", NFS3_CREATE, nfs3svc_create, NULL, 0, DRC_NON_IDEMPOTENT},
+ {"MKDIR", NFS3_MKDIR, nfs3svc_mkdir, NULL, 0, DRC_NON_IDEMPOTENT},
+ {"SYMLINK", NFS3_SYMLINK, nfs3svc_symlink, NULL, 0, DRC_NON_IDEMPOTENT},
+ {"MKNOD", NFS3_MKNOD, nfs3svc_mknod, NULL, 0, DRC_NON_IDEMPOTENT},
+ {"REMOVE", NFS3_REMOVE, nfs3svc_remove, NULL, 0, DRC_NON_IDEMPOTENT},
+ {"RMDIR", NFS3_RMDIR, nfs3svc_rmdir, NULL, 0, DRC_NON_IDEMPOTENT},
+ {"RENAME", NFS3_RENAME, nfs3svc_rename, NULL, 0, DRC_NON_IDEMPOTENT},
+ {"LINK", NFS3_LINK, nfs3svc_link, NULL, 0, DRC_NON_IDEMPOTENT},
+ {"READDIR", NFS3_READDIR, nfs3svc_readdir, NULL, 0, DRC_IDEMPOTENT},
+ {"READDIRPLUS", NFS3_READDIRP, nfs3svc_readdirp, NULL, 0, DRC_IDEMPOTENT},
+ {"FSSTAT", NFS3_FSSTAT, nfs3svc_fsstat, NULL, 0, DRC_IDEMPOTENT},
+ {"FSINFO", NFS3_FSINFO, nfs3svc_fsinfo, NULL, 0, DRC_IDEMPOTENT},
+ {"PATHCONF", NFS3_PATHCONF, nfs3svc_pathconf, NULL, 0, DRC_IDEMPOTENT},
+ {"COMMIT", NFS3_COMMIT, nfs3svc_commit, NULL, 0, DRC_IDEMPOTENT}
};
@@ -4531,33 +5129,56 @@ rpcsvc_program_t nfs3prog = {
.prognum = NFS_PROGRAM,
.progver = NFS_V3,
.progport = GF_NFS3_PORT,
- .progaddrfamily = AF_INET,
- .proghost = NULL,
.actors = nfs3svc_actors,
.numactors = NFS3_PROC_COUNT,
- .conn_destroy = NULL,
- .conn_init = NULL,
/* Requests like FSINFO are sent before an auth scheme
* is inited by client. See RFC 2623, Section 2.3.2. */
.min_auth = AUTH_NULL,
};
+/*
+ * This function rounds up the input value to multiple of 4096. Min and Max
+ * supported I/O size limits are 4KB (GF_NFS3_FILE_IO_SIZE_MIN) and
+ * 1MB (GF_NFS3_FILE_IO_SIZE_MAX).
+ */
+void
+nfs3_iosize_roundup_4KB (uint64_t *ioszptr)
+{
+ uint64_t iosize;
+ uint64_t iopages;
+
+ if (!ioszptr)
+ return;
+
+ iosize = *ioszptr;
+ iopages = (iosize + GF_NFS3_IO_SIZE -1) >> GF_NFS3_IO_SHIFT;
+ iosize = (iopages * GF_NFS3_IO_SIZE);
+
+ /* Double check - boundary conditions */
+ if (iosize < GF_NFS3_FILE_IO_SIZE_MIN) {
+ iosize = GF_NFS3_FILE_IO_SIZE_MIN;
+ } else if (iosize > GF_NFS3_FILE_IO_SIZE_MAX) {
+ iosize = GF_NFS3_FILE_IO_SIZE_MAX;
+ }
+
+ *ioszptr = iosize;
+}
int
-nfs3_init_options (struct nfs3_state *nfs3, xlator_t *nfsx)
+nfs3_init_options (struct nfs3_state *nfs3, dict_t *options)
{
int ret = -1;
char *optstr = NULL;
uint64_t size64 = 0;
- if ((!nfs3) || (!nfsx))
+ if ((!nfs3) || (!options))
return -1;
/* nfs3.read-size */
nfs3->readsize = GF_NFS3_RTPREF;
- if (dict_get (nfsx->options, "nfs3.read-size")) {
- ret = dict_get_str (nfsx->options, "nfs3.read-size", &optstr);
+ if (dict_get (options, "nfs3.read-size")) {
+ ret = dict_get_str (options, "nfs3.read-size", &optstr);
if (ret < 0) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Failed to read "
" option: nfs3.read-size");
@@ -4566,19 +5187,21 @@ nfs3_init_options (struct nfs3_state *nfs3, xlator_t *nfsx)
}
ret = gf_string2bytesize (optstr, &size64);
- nfs3->readsize = size64;
if (ret == -1) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Failed to format"
" option: nfs3.read-size");
ret = -1;
goto err;
}
+
+ nfs3_iosize_roundup_4KB (&size64);
+ nfs3->readsize = size64;
}
/* nfs3.write-size */
nfs3->writesize = GF_NFS3_WTPREF;
- if (dict_get (nfsx->options, "nfs3.write-size")) {
- ret = dict_get_str (nfsx->options, "nfs3.write-size", &optstr);
+ if (dict_get (options, "nfs3.write-size")) {
+ ret = dict_get_str (options, "nfs3.write-size", &optstr);
if (ret < 0) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Failed to read "
" option: nfs3.write-size");
@@ -4587,19 +5210,21 @@ nfs3_init_options (struct nfs3_state *nfs3, xlator_t *nfsx)
}
ret = gf_string2bytesize (optstr, &size64);
- nfs3->writesize = size64;
if (ret == -1) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Failed to format"
" option: nfs3.write-size");
ret = -1;
goto err;
}
+
+ nfs3_iosize_roundup_4KB (&size64);
+ nfs3->writesize = size64;
}
/* nfs3.readdir.size */
nfs3->readdirsize = GF_NFS3_DTPREF;
- if (dict_get (nfsx->options, "nfs3.readdir-size")) {
- ret = dict_get_str (nfsx->options,"nfs3.readdir-size", &optstr);
+ if (dict_get (options, "nfs3.readdir-size")) {
+ ret = dict_get_str (options,"nfs3.readdir-size", &optstr);
if (ret < 0) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Failed to read"
" option: nfs3.readdir-size");
@@ -4608,15 +5233,16 @@ nfs3_init_options (struct nfs3_state *nfs3, xlator_t *nfsx)
}
ret = gf_string2bytesize (optstr, &size64);
- nfs3->readdirsize = size64;
if (ret == -1) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Failed to format"
" option: nfs3.readdir-size");
ret = -1;
goto err;
}
- }
+ nfs3_iosize_roundup_4KB (&size64);
+ nfs3->readdirsize = size64;
+ }
/* We want to use the size of the biggest param for the io buffer size.
*/
@@ -4627,7 +5253,7 @@ nfs3_init_options (struct nfs3_state *nfs3, xlator_t *nfsx)
nfs3->iobsize = nfs3->readdirsize;
/* But this is the true size of each iobuf. We need this size to
- * accomodate the NFS headers also in the same buffer. */
+ * accommodate the NFS headers also in the same buffer. */
nfs3->iobsize = nfs3->iobsize * 2;
/* mem-factor */
@@ -4638,16 +5264,66 @@ err:
}
int
-nfs3_init_subvolume_options (struct nfs3_export *exp, dict_t *options)
+nfs3_init_subvolume_options (xlator_t *nfsx,
+ struct nfs3_export *exp,
+ dict_t *options)
{
int ret = -1;
char *optstr = NULL;
char searchkey[1024];
char *name = NULL;
+ gf_boolean_t boolt = _gf_false;
+ uuid_t volumeid = {0, };
- if ((!exp) || (!options))
+ if ((!nfsx) || (!exp))
return -1;
+ /* For init, fetch options from xlator but for
+ * reconfigure, take the parameter */
+ if (!options)
+ options = nfsx->options;
+
+ if (!options)
+ return (-1);
+
+ uuid_clear (volumeid);
+ if (gf_nfs_dvm_off (nfs_state (nfsx)))
+ goto no_dvm;
+
+ ret = snprintf (searchkey, 1024, "nfs3.%s.volume-id",exp->subvol->name);
+ if (ret < 0) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "snprintf failed");
+ ret = -1;
+ goto err;
+ }
+
+ if (dict_get (options, searchkey)) {
+ ret = dict_get_str (options, searchkey, &optstr);
+ if (ret < 0) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Failed to read option"
+ ": %s", searchkey);
+ ret = -1;
+ goto err;
+ }
+ } else {
+ gf_log (GF_MNT, GF_LOG_ERROR, "DVM is on but volume-id not "
+ "given for volume: %s", exp->subvol->name);
+ ret = -1;
+ goto err;
+ }
+
+ if (optstr) {
+ ret = uuid_parse (optstr, volumeid);
+ if (ret < 0) {
+ gf_log (GF_MNT, GF_LOG_ERROR, "Failed to parse volume "
+ "UUID");
+ ret = -1;
+ goto err;
+ }
+ uuid_copy (exp->volumeid, volumeid);
+ }
+
+no_dvm:
/* Volume Access */
name = exp->subvol->name;
ret = snprintf (searchkey, 1024, "nfs3.%s.volume-access", name);
@@ -4688,71 +5364,133 @@ nfs3_init_subvolume_options (struct nfs3_export *exp, dict_t *options)
}
}
- gf_log (GF_NFS3, GF_LOG_TRACE, "%s: %s", exp->subvol->name,
- (exp->access == GF_NFS3_VOLACCESS_RO)?"read-only":"read-write");
+ exp->trusted_sync = 0;
+ ret = snprintf (searchkey, 1024, "nfs3.%s.trusted-sync", name);
+ if (ret < 0) {
+ gf_log (GF_NFS3, GF_LOG_ERROR, "snprintf failed");
+ ret = -1;
+ goto err;
+ }
+
+ if (dict_get (options, searchkey)) {
+ ret = dict_get_str (options, searchkey, &optstr);
+ if (ret < 0) {
+ gf_log (GF_NFS3, GF_LOG_ERROR, "Failed to read "
+ " option: %s", searchkey);
+ ret = -1;
+ goto err;
+ }
+
+ ret = gf_string2boolean (optstr, &boolt);
+ if (ret < 0) {
+ gf_log (GF_NFS3, GF_LOG_ERROR, "Failed to convert str "
+ "to gf_boolean_t");
+ ret = -1;
+ goto err;
+ }
+
+ if (boolt == _gf_true)
+ exp->trusted_sync = 1;
+ }
+
+ exp->trusted_write = 0;
+ ret = snprintf (searchkey, 1024, "nfs3.%s.trusted-write", name);
+ if (ret < 0) {
+ gf_log (GF_NFS3, GF_LOG_ERROR, "snprintf failed");
+ ret = -1;
+ goto err;
+ }
+
+ if (dict_get (options, searchkey)) {
+ ret = dict_get_str (options, searchkey, &optstr);
+ if (ret < 0) {
+ gf_log (GF_NFS3, GF_LOG_ERROR, "Failed to read "
+ " option: %s", searchkey);
+ ret = -1;
+ goto err;
+ }
+
+ ret = gf_string2boolean (optstr, &boolt);
+ if (ret < 0) {
+ gf_log (GF_NFS3, GF_LOG_ERROR, "Failed to convert str "
+ "to gf_boolean_t");
+ ret = -1;
+ goto err;
+ }
+
+ if (boolt == _gf_true)
+ exp->trusted_write = 1;
+ }
+
+ /* If trusted-sync is on, then we also switch on trusted-write because
+ * tw is included in ts. In write logic, we're then only checking for
+ * tw.
+ */
+ if (exp->trusted_sync)
+ exp->trusted_write = 1;
+
+ gf_log (GF_NFS3, GF_LOG_TRACE, "%s: %s, %s, %s", exp->subvol->name,
+ (exp->access == GF_NFS3_VOLACCESS_RO)?"read-only":"read-write",
+ (exp->trusted_sync == 0)?"no trusted_sync":"trusted_sync",
+ (exp->trusted_write == 0)?"no trusted_write":"trusted_write");
ret = 0;
err:
return ret;
}
-int
-nfs3_init_subvolume (struct nfs3_state *nfs3, xlator_t *nfsx, xlator_t *subvol,
- int xlid)
+struct nfs3_export *
+nfs3_init_subvolume (struct nfs3_state *nfs3, xlator_t *subvol)
{
int ret = -1;
struct nfs3_export *exp = NULL;
- if ((!nfs3) || (!nfsx) || (!subvol))
- return -1;
+ if ((!nfs3) || (!subvol))
+ return NULL;
- exp = &nfs3->exports[xlid];
+ exp = GF_CALLOC (1, sizeof (*exp), gf_nfs_mt_nfs3_export);
exp->subvol = subvol;
-
+ INIT_LIST_HEAD (&exp->explist);
gf_log (GF_NFS3, GF_LOG_TRACE, "Initing state: %s", exp->subvol->name);
- ret = nfs3_init_subvolume_options (exp, nfsx->options);
- if (ret == -1)
+ ret = nfs3_init_subvolume_options (nfs3->nfsx, exp, NULL);
+ if (ret == -1) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Failed to init subvol");
+ goto exp_free;
+ }
- return ret;
+ ret = 0;
+exp_free:
+ if (ret < 0) {
+ GF_FREE (exp);
+ exp = NULL;
+ }
+
+ return exp;
}
int
-nfs3_init_subvolumes (struct nfs3_state *nfs3, xlator_t *nfsx)
+nfs3_init_subvolumes (struct nfs3_state *nfs3)
{
- int xl_count = 0;
int ret = -1;
struct xlator_list *xl_list = NULL;
+ struct nfs3_export *exp = NULL;
- if ((!nfs3) || (!nfsx))
+ if (!nfs3)
return -1;
- xl_list = nfsx->children;
- while (xl_list) {
- ++xl_count;
- xl_list = xl_list->next;
- }
-
- nfs3->exports = CALLOC (xl_count, sizeof (struct nfs3_export));
- if (!nfs3->exports) {
- gf_log (GF_NFS3, GF_LOG_ERROR, "Memory allocation failed");
- goto err;
- }
+ xl_list = nfs3->nfsx->children;
- xl_list = nfsx->children;
- xl_count = 0; /* Re-using xl_count. */
while (xl_list) {
- ret = nfs3_init_subvolume (nfs3, nfsx, xl_list->xlator,
- xl_count);
- if (ret == -1) {
+ exp = nfs3_init_subvolume (nfs3, xl_list->xlator);
+ if (!exp) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Failed to init subvol: "
"%s", xl_list->xlator->name);
goto err;
}
+ list_add_tail (&exp->explist, &nfs3->exports);
xl_list = xl_list->next;
- ++xl_count;
}
ret = 0;
@@ -4767,18 +5505,20 @@ nfs3_init_state (xlator_t *nfsx)
struct nfs3_state *nfs3 = NULL;
int ret = -1;
unsigned int localpool = 0;
-
+ struct nfs_state *nfs = NULL;
if (!nfsx)
return NULL;
- nfs3 = (struct nfs3_state *)CALLOC (1, sizeof (*nfs3));
+ nfs3 = (struct nfs3_state *)GF_CALLOC (1, sizeof (*nfs3),
+ gf_nfs_mt_nfs3_state);
if (!nfs3) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Memory allocation failed");
return NULL;
}
- ret = nfs3_init_options (nfs3, nfsx);
+ nfs = nfsx->private;
+ ret = nfs3_init_options (nfs3, nfsx->options);
if (ret == -1) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Failed to init options");
goto ret;
@@ -4797,7 +5537,8 @@ nfs3_init_state (xlator_t *nfsx)
nfs3->nfsx = nfsx;
nfs3->exportslist = nfsx->children;
- ret = nfs3_init_subvolumes (nfs3, nfsx);
+ INIT_LIST_HEAD (&nfs3->exports);
+ ret = nfs3_init_subvolumes (nfs3);
if (ret == -1) {
gf_log (GF_NFS3, GF_LOG_ERROR, "Failed to init per-subvolume "
"state");
@@ -4809,6 +5550,13 @@ nfs3_init_state (xlator_t *nfsx)
LOCK_INIT (&nfs3->fdlrulock);
nfs3->fdcount = 0;
+ ret = rpcsvc_create_listeners (nfs->rpcsvc, nfsx->options, nfsx->name);
+ if (ret == -1) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Unable to create listeners");
+ goto free_localpool;
+ }
+
+ nfs->nfs3state = nfs3;
ret = 0;
free_localpool:
@@ -4817,7 +5565,7 @@ free_localpool:
ret:
if (ret == -1) {
- FREE (nfs3);
+ GF_FREE (nfs3);
nfs3 = NULL;
}
@@ -4844,4 +5592,39 @@ nfs3svc_init (xlator_t *nfsx)
return &nfs3prog;
}
+int
+nfs3_reconfigure_state (xlator_t *nfsx, dict_t *options)
+{
+ int ret = -1;
+ struct nfs3_export *exp = NULL;
+ struct nfs_state *nfs = NULL;
+ struct nfs3_state *nfs3 = NULL;
+
+ if ((!nfsx) || (!nfsx->private) || (!options))
+ goto out;
+
+ nfs = (struct nfs_state *)nfsx->private;
+ nfs3 = nfs->nfs3state;
+ if (!nfs3)
+ goto out;
+
+ ret = nfs3_init_options (nfs3, options);
+ if (ret) {
+ gf_log (GF_NFS3, GF_LOG_ERROR,
+ "Failed to reconfigure options");
+ goto out;
+ }
+
+ list_for_each_entry (exp, &nfs3->exports, explist) {
+ ret = nfs3_init_subvolume_options (nfsx, exp, options);
+ if (ret) {
+ gf_log (GF_NFS3, GF_LOG_ERROR,
+ "Failed to reconfigure subvol options");
+ goto out;
+ }
+ }
+ ret = 0;
+out:
+ return ret;
+}
diff --git a/xlators/nfs/server/src/nfs3.h b/xlators/nfs/server/src/nfs3.h
index bb5fbb750..0c35445a4 100644
--- a/xlators/nfs/server/src/nfs3.h
+++ b/xlators/nfs/server/src/nfs3.h
@@ -1,20 +1,11 @@
/*
- Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
+ Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.com>
This file is part of GlusterFS.
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
*/
#ifndef _NFS3_H_
@@ -34,11 +25,12 @@
#include "nfs-common.h"
#include "xdr-nfs3.h"
#include "mem-pool.h"
-
+#include "nlm4.h"
+#include "acl3-xdr.h"
+#include "acl3.h"
#include <sys/statvfs.h>
#define GF_NFS3 GF_NFS"-nfsv3"
-#define GF_NFS3_PORT 38467
#define GF_NFS3_DEFAULT_MEMFACTOR 15
#define GF_NFS3_IOBPOOL_MULT GF_NFS_CONCURRENT_OPS_MULT
@@ -47,16 +39,39 @@
/* Static values used for FSINFO
-FIXME: This should be configurable */
-#define GF_NFS3_RTMAX (64 * GF_UNIT_KB)
-#define GF_NFS3_RTPREF (64 * GF_UNIT_KB)
-#define GF_NFS3_RTMULT (4 * GF_UNIT_KB)
-#define GF_NFS3_WTMAX (64 * GF_UNIT_KB)
-#define GF_NFS3_WTPREF (64 * GF_UNIT_KB)
-#define GF_NFS3_WTMULT (4 * GF_UNIT_KB)
-#define GF_NFS3_DTMIN (4 * GF_UNIT_KB)
-#define GF_NFS3_DTPREF (64 * GF_UNIT_KB)
-#define GF_NFS3_MAXFILE (1 * GF_UNIT_PB)
+ * To change the maximum rsize and wsize supported by the NFS client, adjust
+ * GF_NFS3_FILE_IO_SIZE_MAX. The Gluster NFS server defaults to 1MB(1048576)
+ * (same as kernel NFS server). For slower network, rsize/wsize can be trimmed
+ * to 16/32/64-KB. rsize and wsize can be tuned through nfs.read-size and
+ * nfs.write-size respectively.
+ *
+ * NB: For Kernel-NFS, NFS_MAX_FILE_IO_SIZE is 1048576U (1MB).
+ */
+#define GF_NFS3_FILE_IO_SIZE_MAX (1 * GF_UNIT_MB) /* 1048576 */
+#define GF_NFS3_FILE_IO_SIZE_MIN (4 * GF_UNIT_KB) /* 4096 */
+
+#define GF_NFS3_FILE_IO_SIZE_DEF GF_NFS3_FILE_IO_SIZE_MAX
+
+#define GF_NFS3_RTMAX GF_NFS3_FILE_IO_SIZE_MAX
+#define GF_NFS3_RTMIN GF_NFS3_FILE_IO_SIZE_MIN
+#define GF_NFS3_RTPREF GF_NFS3_FILE_IO_SIZE_DEF
+#define GF_NFS3_RTMULT GF_NFS3_FILE_IO_SIZE_MIN
+
+#define GF_NFS3_WTMAX GF_NFS3_FILE_IO_SIZE_MAX
+#define GF_NFS3_WTMIN GF_NFS3_FILE_IO_SIZE_MIN
+#define GF_NFS3_WTPREF GF_NFS3_FILE_IO_SIZE_DEF
+#define GF_NFS3_WTMULT GF_NFS3_FILE_IO_SIZE_MIN
+
+/* This can be tuned through nfs.readdir-size */
+#define GF_NFS3_DTMAX GF_NFS3_FILE_IO_SIZE_MAX
+#define GF_NFS3_DTMIN GF_NFS3_FILE_IO_SIZE_MIN
+#define GF_NFS3_DTPREF GF_NFS3_FILE_IO_SIZE_DEF
+
+#define GF_NFS3_MAXFILESIZE (1 * GF_UNIT_PB)
+
+#define GF_NFS3_IO_SIZE 4096 /* 4-KB */
+#define GF_NFS3_IO_SHIFT 12 /* 2^12 = 4KB */
+
/* FIXME: Handle time resolutions */
#define GF_NFS3_TIMEDELTA_SECS {1,0}
#define GF_NFS3_TIMEDELTA_NSECS {0,1}
@@ -82,14 +97,19 @@ struct nfs3_fd_entry {
/* Per subvolume nfs3 specific state */
struct nfs3_export {
+ struct list_head explist;
xlator_t *subvol;
+ uuid_t volumeid;
int access;
+ int trusted_sync;
+ int trusted_write;
+ int rootlookedup;
};
#define GF_NFS3_DEFAULT_VOLACCESS (GF_NFS3_VOLACCESS_RW)
/* The NFSv3 protocol state */
-struct nfs3_state {
+typedef struct nfs3_state {
/* The NFS xlator pointer. The NFS xlator can be running
* multiple versions of the NFS protocol.
@@ -106,7 +126,7 @@ struct nfs3_state {
*/
xlator_list_t *exportslist;
- struct nfs3_export *exports;
+ struct list_head exports;
/* Mempool for allocations of struct nfs3_local */
struct mem_pool *localpool;
@@ -114,21 +134,48 @@ struct nfs3_state {
uint64_t serverstart;
/* NFSv3 Protocol configurables */
- size_t readsize;
- size_t writesize;
- size_t readdirsize;
+ uint64_t readsize;
+ uint64_t writesize;
+ uint64_t readdirsize;
/* Size of the iobufs used, depends on the sizes of the three params
* above.
*/
- size_t iobsize;
+ uint64_t iobsize;
unsigned int memfactor;
struct list_head fdlru;
gf_lock_t fdlrulock;
int fdcount;
-};
+ uint32_t occ_logger;
+} nfs3_state_t;
+
+typedef enum nfs3_lookup_type {
+ GF_NFS3_REVALIDATE = 1,
+ GF_NFS3_FRESH,
+} nfs3_lookup_type_t;
+
+typedef union args_ {
+ nlm4_stat nlm4_stat;
+ nlm4_holder nlm4_holder;
+ nlm4_lock nlm4_lock;
+ nlm4_share nlm4_share;
+ nlm4_testrply nlm4_testrply;
+ nlm4_testres nlm4_testres;
+ nlm4_testargs nlm4_testargs;
+ nlm4_res nlm4_res;
+ nlm4_lockargs nlm4_lockargs;
+ nlm4_cancargs nlm4_cancargs;
+ nlm4_unlockargs nlm4_unlockargs;
+ nlm4_shareargs nlm4_shareargs;
+ nlm4_shareres nlm4_shareres;
+ nlm4_freeallargs nlm4_freeallargs;
+ getaclargs getaclargs;
+ setaclargs setaclargs;
+ getaclreply getaclreply;
+ setaclreply setaclreply;
+} args;
typedef int (*nfs3_resume_fn_t) (void *cs);
@@ -175,6 +222,7 @@ struct nfs3_local {
count3 datacount;
offset3 dataoffset;
struct iobuf *iob;
+ struct iobref *iobref;
createmode3 createmode;
uint64_t cookieverf;
int sattrguardcheck;
@@ -186,6 +234,7 @@ struct nfs3_local {
mode_t mode;
/* NFSv3 FH resolver state */
+ int hardresolved;
struct nfs3_fh resolvefh;
loc_t resolvedloc;
int resolve_ret;
@@ -193,11 +242,44 @@ struct nfs3_local {
int hashidx;
fd_t *resolve_dir_fd;
char *resolventry;
+ nfs3_lookup_type_t lookuptype;
+ gf_dirent_t *hashmatch;
+ gf_dirent_t *entrymatch;
+ off_t lastentryoffset;
+ struct flock flock;
+ args args;
+ nlm4_lkowner_t lkowner;
+ char cookiebytes[1024];
+ struct nfs3_fh lockfh;
+ int monitor;
+ rpc_transport_t *trans;
+ call_frame_t *frame;
+
+ /* ACL */
+ aclentry aclentry[NFS_ACL_MAX_ENTRIES];
+ aclentry daclentry[NFS_ACL_MAX_ENTRIES];
+ int aclcount;
+ char aclxattr[NFS_ACL_MAX_ENTRIES*8 + 4];
+ int daclcount;
+ char daclxattr[NFS_ACL_MAX_ENTRIES*8 + 4];
};
+#define nfs3_is_revalidate_lookup(cst) ((cst)->lookuptype == GF_NFS3_REVALIDATE)
+#define nfs3_lookup_op(cst) (rpcsvc_request_procnum(cst->req) == NFS3_LOOKUP)
+#define nfs3_create_op(cst) (rpcsvc_request_procnum(cst->req) == NFS3_CREATE)
+#define nfs3_create_exclusive_op(cst) ((cst)->createmode == EXCLUSIVE)
+
typedef struct nfs3_local nfs3_call_state_t;
+/* Queue of ops waiting for open fop to return. */
+struct inode_op_queue {
+ struct list_head opq;
+ pthread_mutex_t qlock;
+};
extern rpcsvc_program_t *
nfs3svc_init (xlator_t *nfsx);
+
+extern int
+nfs3_reconfigure_state (xlator_t *nfsx, dict_t *options);
#endif
diff --git a/xlators/nfs/server/src/nlm4.c b/xlators/nfs/server/src/nlm4.c
new file mode 100644
index 000000000..5c5d87412
--- /dev/null
+++ b/xlators/nfs/server/src/nlm4.c
@@ -0,0 +1,2525 @@
+/*
+ Copyright (c) 2012 Gluster, Inc. <http://www.gluster.com>
+ This file is part of GlusterFS.
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
+*/
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include "defaults.h"
+#include "rpcsvc.h"
+#include "dict.h"
+#include "xlator.h"
+#include "nfs.h"
+#include "mem-pool.h"
+#include "logging.h"
+#include "nfs-fops.h"
+#include "inode.h"
+#include "mount3.h"
+#include "nfs3.h"
+#include "nfs-mem-types.h"
+#include "nfs3-helpers.h"
+#include "nfs3-fh.h"
+#include "nlm4.h"
+#include "nlm4-xdr.h"
+#include "msg-nfs3.h"
+#include "nfs-generics.h"
+#include "rpc-clnt.h"
+#include "nsm-xdr.h"
+#include "nlmcbk-xdr.h"
+#include "run.h"
+#include <unistd.h>
+#include <rpc/pmap_clnt.h>
+#include <rpc/rpc.h>
+#include <rpc/xdr.h>
+#include <statedump.h>
+
+/* TODO:
+ * 1) 2 opens racing .. creating an fd leak.
+ * 2) use mempool for nlmclnt - destroy if no fd exists, create during 1st call
+ */
+
+typedef ssize_t (*nlm4_serializer) (struct iovec outmsg, void *args);
+
+extern void nfs3_call_state_wipe (nfs3_call_state_t *cs);
+
+struct list_head nlm_client_list;
+gf_lock_t nlm_client_list_lk;
+
+/* race on this is harmless */
+int nlm_grace_period = 50;
+
+#define nlm4_validate_nfs3_state(request, state, status, label, retval) \
+ do { \
+ state = rpcsvc_request_program_private (request); \
+ if (!state) { \
+ gf_log (GF_NLM, GF_LOG_ERROR, "NFSv3 state " \
+ "missing from RPC request"); \
+ rpcsvc_request_seterr (req, SYSTEM_ERR); \
+ status = nlm4_failed; \
+ goto label; \
+ } \
+ } while (0); \
+
+nfs3_call_state_t *
+nfs3_call_state_init (struct nfs3_state *s, rpcsvc_request_t *req, xlator_t *v);
+
+#define nlm4_handle_call_state_init(nfs3state, calls, rq, opstat, errlabel)\
+ do { \
+ calls = nlm4_call_state_init ((nfs3state), (rq)); \
+ if (!calls) { \
+ gf_log (GF_NLM, GF_LOG_ERROR, "Failed to " \
+ "init call state"); \
+ opstat = nlm4_failed; \
+ rpcsvc_request_seterr (req, SYSTEM_ERR); \
+ goto errlabel; \
+ } \
+ } while (0) \
+
+#define nlm4_validate_gluster_fh(handle, status, errlabel) \
+ do { \
+ if (!nfs3_fh_validate (handle)) { \
+ status = nlm4_stale_fh; \
+ goto errlabel; \
+ } \
+ } while (0) \
+
+xlator_t *
+nfs3_fh_to_xlator (struct nfs3_state *nfs3, struct nfs3_fh *fh);
+
+#define nlm4_map_fh_to_volume(nfs3state, handle, req, volume, status, label) \
+ do { \
+ char exportid[256], gfid[256]; \
+ rpc_transport_t *trans = NULL; \
+ volume = nfs3_fh_to_xlator ((nfs3state), &handle); \
+ if (!volume) { \
+ uuid_unparse (handle.exportid, exportid); \
+ uuid_unparse (handle.gfid, gfid); \
+ trans = rpcsvc_request_transport (req); \
+ gf_log (GF_NLM, GF_LOG_ERROR, "Failed to map " \
+ "FH to vol: client=%s, exportid=%s, gfid=%s",\
+ trans->peerinfo.identifier, exportid, \
+ gfid); \
+ gf_log (GF_NLM, GF_LOG_ERROR, \
+ "Stale nfs client %s must be trying to "\
+ "connect to a deleted volume, please " \
+ "unmount it.", trans->peerinfo.identifier);\
+ status = nlm4_stale_fh; \
+ goto label; \
+ } else { \
+ gf_log (GF_NLM, GF_LOG_TRACE, "FH to Volume: %s"\
+ ,volume->name); \
+ rpcsvc_request_set_private (req, volume); \
+ } \
+ } while (0); \
+
+#define nlm4_volume_started_check(nfs3state, vlm, rtval, erlbl) \
+ do { \
+ if ((!nfs_subvolume_started (nfs_state (nfs3state->nfsx), vlm))){\
+ gf_log (GF_NLM, GF_LOG_ERROR, "Volume is disabled: %s",\
+ vlm->name); \
+ rtval = RPCSVC_ACTOR_IGNORE; \
+ goto erlbl; \
+ } \
+ } while (0) \
+
+#define nlm4_check_fh_resolve_status(cst, nfstat, erlabl) \
+ do { \
+ xlator_t *xlatorp = NULL; \
+ char buf[256], gfid[256]; \
+ rpc_transport_t *trans = NULL; \
+ if ((cst)->resolve_ret < 0) { \
+ trans = rpcsvc_request_transport (cst->req); \
+ xlatorp = nfs3_fh_to_xlator (cst->nfs3state, \
+ &cst->resolvefh); \
+ uuid_unparse (cst->resolvefh.gfid, gfid); \
+ snprintf (buf, sizeof (buf), "(%s) %s : %s", \
+ trans->peerinfo.identifier, \
+ xlatorp ? xlatorp->name : "ERR", \
+ gfid); \
+ gf_log (GF_NLM, GF_LOG_ERROR, "Unable to resolve FH"\
+ ": %s", buf); \
+ nfstat = nlm4_errno_to_nlm4stat (cst->resolve_errno);\
+ goto erlabl; \
+ } \
+ } while (0) \
+
+
+void
+nlm4_prep_nlm4_testargs (nlm4_testargs *args, struct nfs3_fh *fh,
+ nlm4_lkowner_t *oh, char *cookiebytes)
+{
+ memset (args, 0, sizeof (*args));
+ args->alock.fh.n_bytes = (void *)fh;
+ args->alock.oh.n_bytes = (void *)oh;
+ args->cookie.n_bytes = (void *)cookiebytes;
+}
+
+void
+nlm4_prep_nlm4_lockargs (nlm4_lockargs *args, struct nfs3_fh *fh,
+ nlm4_lkowner_t *oh, char *cookiebytes)
+{
+ memset (args, 0, sizeof (*args));
+ args->alock.fh.n_bytes = (void *)fh;
+ args->alock.oh.n_bytes = (void *)oh;
+ args->cookie.n_bytes = (void *)cookiebytes;
+}
+
+void
+nlm4_prep_nlm4_cancargs (nlm4_cancargs *args, struct nfs3_fh *fh,
+ nlm4_lkowner_t *oh, char *cookiebytes)
+{
+ memset (args, 0, sizeof (*args));
+ args->alock.fh.n_bytes = (void *)fh;
+ args->alock.oh.n_bytes = (void *)oh;
+ args->cookie.n_bytes = (void *)cookiebytes;
+}
+
+void
+nlm4_prep_nlm4_unlockargs (nlm4_unlockargs *args, struct nfs3_fh *fh,
+ nlm4_lkowner_t *oh, char *cookiebytes)
+{
+ memset (args, 0, sizeof (*args));
+ args->alock.fh.n_bytes = (void *)fh;
+ args->alock.oh.n_bytes = (void *)oh;
+ args->cookie.n_bytes = (void *)cookiebytes;
+}
+
+void
+nlm4_prep_shareargs (nlm4_shareargs *args, struct nfs3_fh *fh,
+ nlm4_lkowner_t *oh, char *cookiebytes)
+{
+ memset (args, 0, sizeof (*args));
+ args->share.fh.n_bytes = (void *)fh;
+ args->share.oh.n_bytes = (void *)oh;
+ args->cookie.n_bytes = (void *)cookiebytes;
+}
+
+void
+nlm4_prep_freeallargs (nlm4_freeallargs *args, nlm4_lkowner_t *oh)
+{
+ memset (args, 0, sizeof (*args));
+ args->name = (void *)oh;
+}
+
+void
+nlm_copy_lkowner (gf_lkowner_t *dst, netobj *src)
+{
+ dst->len = src->n_len;
+ memcpy (dst->data, src->n_bytes, dst->len);
+}
+
+int
+nlm_is_oh_same_lkowner (gf_lkowner_t *a, netobj *b)
+{
+ if (!a || !b) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "invalid args");
+ return -1;
+ }
+
+ return (a->len == b->n_len &&
+ !memcmp (a->data, b->n_bytes, a->len));
+}
+
+nlm4_stats
+nlm4_errno_to_nlm4stat (int errnum)
+{
+ nlm4_stats stat = nlm4_denied;
+
+ switch (errnum) {
+ case 0:
+ stat = nlm4_granted;
+ break;
+ case EROFS:
+ stat = nlm4_rofs;
+ break;
+ case ESTALE:
+ stat = nlm4_stale_fh;
+ break;
+ case ENOLCK:
+ stat = nlm4_failed;
+ break;
+ default:
+ stat = nlm4_denied;
+ break;
+ }
+
+ return stat;
+}
+
+nfs3_call_state_t *
+nlm4_call_state_init (struct nfs3_state *s, rpcsvc_request_t *req)
+{
+ nfs3_call_state_t *cs = NULL;
+
+ if ((!s) || (!req))
+ return NULL;
+
+ cs = (nfs3_call_state_t *) mem_get (s->localpool);
+ if (!cs)
+ return NULL;
+
+ memset (cs, 0, sizeof (*cs));
+ INIT_LIST_HEAD (&cs->entries.list);
+ INIT_LIST_HEAD (&cs->openwait_q);
+ cs->operrno = EINVAL;
+ cs->req = req;
+ cs->nfsx = s->nfsx;
+ cs->nfs3state = s;
+ cs->monitor = 1;
+
+ return cs;
+}
+
+int
+nlm_monitor (char *caller_name)
+{
+ nlm_client_t *nlmclnt = NULL;
+ int monitor = -1;
+
+ LOCK (&nlm_client_list_lk);
+ list_for_each_entry (nlmclnt, &nlm_client_list, nlm_clients) {
+ if (!strcmp(caller_name, nlmclnt->caller_name)) {
+ monitor = nlmclnt->nsm_monitor;
+ nlmclnt->nsm_monitor = 1;
+ break;
+ }
+ }
+ UNLOCK (&nlm_client_list_lk);
+
+ if (monitor == -1)
+ gf_log (GF_NLM, GF_LOG_ERROR, "%s was not found in "
+ "the nlmclnt list", caller_name);
+
+ return monitor;
+}
+
+rpc_clnt_t *
+nlm_get_rpc_clnt (char *caller_name)
+{
+ nlm_client_t *nlmclnt = NULL;
+ int nlmclnt_found = 0;
+ rpc_clnt_t *rpc_clnt = NULL;
+
+ LOCK (&nlm_client_list_lk);
+ list_for_each_entry (nlmclnt, &nlm_client_list, nlm_clients) {
+ if (!strcmp(caller_name, nlmclnt->caller_name)) {
+ nlmclnt_found = 1;
+ break;
+ }
+ }
+ if (!nlmclnt_found)
+ goto ret;
+ if (nlmclnt->rpc_clnt)
+ rpc_clnt = rpc_clnt_ref (nlmclnt->rpc_clnt);
+ret:
+ UNLOCK (&nlm_client_list_lk);
+ return rpc_clnt;
+}
+
+int
+nlm_set_rpc_clnt (rpc_clnt_t *rpc_clnt, char *caller_name)
+{
+ nlm_client_t *nlmclnt = NULL;
+ int nlmclnt_found = 0;
+ int ret = -1;
+
+ LOCK (&nlm_client_list_lk);
+ list_for_each_entry (nlmclnt, &nlm_client_list, nlm_clients) {
+ if (!strcmp(caller_name, nlmclnt->caller_name)) {
+ nlmclnt_found = 1;
+ break;
+ }
+ }
+
+ if (!nlmclnt_found) {
+ nlmclnt = GF_CALLOC (1, sizeof(*nlmclnt),
+ gf_nfs_mt_nlm4_nlmclnt);
+ if (nlmclnt == NULL)
+ goto ret;
+
+ INIT_LIST_HEAD(&nlmclnt->fdes);
+ INIT_LIST_HEAD(&nlmclnt->nlm_clients);
+ INIT_LIST_HEAD(&nlmclnt->shares);
+
+ list_add (&nlmclnt->nlm_clients, &nlm_client_list);
+ nlmclnt->caller_name = gf_strdup (caller_name);
+ }
+
+ if (nlmclnt->rpc_clnt == NULL) {
+ nlmclnt->rpc_clnt = rpc_clnt_ref (rpc_clnt);
+ }
+ ret = 0;
+ret:
+ UNLOCK (&nlm_client_list_lk);
+ return ret;
+}
+
+int
+nlm_unset_rpc_clnt (rpc_clnt_t *rpc)
+{
+ nlm_client_t *nlmclnt = NULL;
+ rpc_clnt_t *rpc_clnt = NULL;
+
+ LOCK (&nlm_client_list_lk);
+ list_for_each_entry (nlmclnt, &nlm_client_list, nlm_clients) {
+ if (rpc == nlmclnt->rpc_clnt) {
+ rpc_clnt = nlmclnt->rpc_clnt;
+ nlmclnt->rpc_clnt = NULL;
+ break;
+ }
+ }
+ UNLOCK (&nlm_client_list_lk);
+ if (rpc_clnt == NULL) {
+ return -1;
+ }
+ if (rpc_clnt) {
+ /* cleanup the saved-frames before last unref */
+ rpc_clnt_connection_cleanup (&rpc_clnt->conn);
+
+ rpc_clnt_unref (rpc_clnt);
+ }
+ return 0;
+}
+
+int
+nlm_add_nlmclnt (char *caller_name)
+{
+ nlm_client_t *nlmclnt = NULL;
+ int nlmclnt_found = 0;
+ int ret = -1;
+
+ LOCK (&nlm_client_list_lk);
+ list_for_each_entry (nlmclnt, &nlm_client_list, nlm_clients) {
+ if (!strcmp(caller_name, nlmclnt->caller_name)) {
+ nlmclnt_found = 1;
+ break;
+ }
+ }
+ if (!nlmclnt_found) {
+ nlmclnt = GF_CALLOC (1, sizeof(*nlmclnt),
+ gf_nfs_mt_nlm4_nlmclnt);
+ if (nlmclnt == NULL) {
+ gf_log (GF_NLM, GF_LOG_DEBUG, "malloc error");
+ goto ret;
+ }
+
+ INIT_LIST_HEAD(&nlmclnt->fdes);
+ INIT_LIST_HEAD(&nlmclnt->nlm_clients);
+ INIT_LIST_HEAD(&nlmclnt->shares);
+
+ list_add (&nlmclnt->nlm_clients, &nlm_client_list);
+ nlmclnt->caller_name = gf_strdup (caller_name);
+ }
+ ret = 0;
+ret:
+ UNLOCK (&nlm_client_list_lk);
+ return ret;
+}
+
+int
+nlm4svc_submit_reply (rpcsvc_request_t *req, void *arg, nlm4_serializer sfunc)
+{
+ struct iovec outmsg = {0, };
+ struct iobuf *iob = NULL;
+ struct nfs3_state *nfs3 = NULL;
+ int ret = -1;
+ ssize_t msglen = 0;
+ struct iobref *iobref = NULL;
+
+ if (!req)
+ return -1;
+
+ nfs3 = (struct nfs3_state *)rpcsvc_request_program_private (req);
+ if (!nfs3) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "mount state not found");
+ goto ret;
+ }
+
+ /* First, get the io buffer into which the reply in arg will
+ * be serialized.
+ */
+ iob = iobuf_get (nfs3->iobpool);
+ if (!iob) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "Failed to get iobuf");
+ goto ret;
+ }
+
+ iobuf_to_iovec (iob, &outmsg);
+ /* Use the given serializer to translate the give C structure in arg
+ * to XDR format which will be written into the buffer in outmsg.
+ */
+ msglen = sfunc (outmsg, arg);
+ if (msglen < 0) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "Failed to encode message");
+ goto ret;
+ }
+ outmsg.iov_len = msglen;
+
+ iobref = iobref_new ();
+ if (iobref == NULL) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "Failed to get iobref");
+ goto ret;
+ }
+
+ ret = iobref_add (iobref, iob);
+ if (ret) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "Failed to add iob to iobref");
+ goto ret;
+ }
+
+ /* Then, submit the message for transmission. */
+ ret = rpcsvc_submit_message (req, &outmsg, 1, NULL, 0, iobref);
+ if (ret == -1) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "Reply submission failed");
+ goto ret;
+ }
+
+ ret = 0;
+ret:
+ if (iob)
+ iobuf_unref (iob);
+ if (iobref)
+ iobref_unref (iobref);
+
+ return ret;
+}
+
+typedef int (*nlm4_resume_fn_t) (void *cs);
+
+int32_t
+nlm4_file_open_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, fd_t *fd, dict_t *xdata)
+{
+ nfs3_call_state_t *cs = frame->local;
+
+ if (op_ret == 0)
+ fd_bind (cs->fd);
+ cs->resolve_ret = op_ret;
+ cs->resume_fn (cs);
+ frame->local = NULL;
+ STACK_DESTROY (frame->root);
+ return 0;
+}
+
+void *
+nsm_monitor(void *arg)
+{
+ CLIENT *clnt = NULL;
+ enum clnt_stat ret;
+ struct mon nsm_mon;
+ struct sm_stat_res res;
+ struct timeval tout = { 5, 0 };
+ char *host = NULL;
+
+ host = arg;
+ nsm_mon.mon_id.mon_name = gf_strdup(host);
+ nsm_mon.mon_id.my_id.my_name = gf_strdup("localhost");
+ nsm_mon.mon_id.my_id.my_prog = NLMCBK_PROGRAM;
+ nsm_mon.mon_id.my_id.my_vers = NLMCBK_V1;
+ nsm_mon.mon_id.my_id.my_proc = NLMCBK_SM_NOTIFY;
+ /* nothing to put in the private data */
+#define SM_PROG 100024
+#define SM_VERS 1
+#define SM_MON 2
+
+ /* create a connection to nsm on the localhost */
+ clnt = clnt_create("localhost", SM_PROG, SM_VERS, "tcp");
+ if(!clnt)
+ {
+ gf_log (GF_NLM, GF_LOG_ERROR, "%s",
+ clnt_spcreateerror ("Clnt_create()"));
+ goto out;
+ }
+
+ ret = clnt_call(clnt, SM_MON,
+ (xdrproc_t) xdr_mon, (caddr_t) & nsm_mon,
+ (xdrproc_t) xdr_sm_stat_res, (caddr_t) & res, tout);
+ if(ret != RPC_SUCCESS)
+ {
+ gf_log (GF_NLM, GF_LOG_ERROR, "clnt_call(): %s",
+ clnt_sperrno(ret));
+ goto out;
+ }
+ if(res.res_stat != STAT_SUCC)
+ {
+ gf_log (GF_NLM, GF_LOG_ERROR, "clnt_call(): %s",
+ clnt_sperrno(ret));
+ goto out;
+ }
+
+out:
+ GF_FREE(nsm_mon.mon_id.mon_name);
+ GF_FREE(nsm_mon.mon_id.my_id.my_name);
+ if (clnt != NULL)
+ clnt_destroy(clnt);
+ return NULL;
+}
+
+nlm_client_t *
+__nlm_get_uniq (char *caller_name)
+{
+ nlm_client_t *nlmclnt = NULL;
+
+ if (!caller_name)
+ return NULL;
+
+ list_for_each_entry (nlmclnt, &nlm_client_list, nlm_clients) {
+ if (!strcmp(caller_name, nlmclnt->caller_name))
+ return nlmclnt;
+ }
+
+ return NULL;
+}
+
+nlm_client_t *
+nlm_get_uniq (char *caller_name)
+{
+ nlm_client_t *nlmclnt = NULL;
+
+ LOCK (&nlm_client_list_lk);
+ nlmclnt = __nlm_get_uniq (caller_name);
+ UNLOCK (&nlm_client_list_lk);
+
+ return nlmclnt;
+}
+
+
+int
+nlm4_file_open_and_resume(nfs3_call_state_t *cs, nlm4_resume_fn_t resume)
+{
+ fd_t *fd = NULL;
+ int ret = -1;
+ int flags = 0;
+ nlm_client_t *nlmclnt = NULL;
+ call_frame_t *frame = NULL;
+
+ if (cs->args.nlm4_lockargs.exclusive == _gf_false)
+ flags = O_RDONLY;
+ else
+ flags = O_WRONLY;
+
+ nlmclnt = nlm_get_uniq (cs->args.nlm4_lockargs.alock.caller_name);
+ if (nlmclnt == NULL) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "nlm_get_uniq() returned NULL");
+ ret = -ENOLCK;
+ goto err;
+ }
+ cs->resume_fn = resume;
+ fd = fd_lookup_uint64 (cs->resolvedloc.inode, (uint64_t)nlmclnt);
+ if (fd) {
+ cs->fd = fd;
+ cs->resolve_ret = 0;
+ cs->resume_fn(cs);
+ ret = 0;
+ goto err;
+ }
+
+ fd = fd_create_uint64 (cs->resolvedloc.inode, (uint64_t)nlmclnt);
+ if (fd == NULL) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "fd_create_uint64() returned NULL");
+ ret = -ENOLCK;
+ goto err;
+ }
+
+ cs->fd = fd;
+
+ frame = create_frame (cs->nfsx, cs->nfsx->ctx->pool);
+ if (!frame) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "unable to create frame");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ frame->root->pid = NFS_PID;
+ frame->root->uid = rpcsvc_request_uid (cs->req);
+ frame->root->gid = rpcsvc_request_gid (cs->req);
+ frame->local = cs;
+ nfs_fix_groups (cs->nfsx, frame->root);
+
+ STACK_WIND_COOKIE (frame, nlm4_file_open_cbk, cs->vol, cs->vol,
+ cs->vol->fops->open, &cs->resolvedloc, flags,
+ cs->fd, NULL);
+ ret = 0;
+err:
+ return ret;
+}
+
+int
+nlm4_generic_reply (rpcsvc_request_t *req, netobj cookie, nlm4_stats stat)
+{
+ nlm4_res res;
+
+ memset (&res, 0, sizeof (res));
+ res.cookie = cookie;
+ res.stat.stat = stat;
+
+ nlm4svc_submit_reply (req, (void *)&res,
+ (nlm4_serializer)xdr_serialize_nlm4_res);
+ return 0;
+}
+
+int
+nlm4svc_null (rpcsvc_request_t *req)
+{
+ struct iovec dummyvec = {0, };
+
+ if (!req) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "Got NULL request!");
+ return 0;
+ }
+ rpcsvc_submit_generic (req, &dummyvec, 1, NULL, 0, NULL);
+ return 0;
+}
+
+int
+nlm4_gf_flock_to_holder (nlm4_holder *holder, struct gf_flock *flock)
+{
+ switch (flock->l_type) {
+ case GF_LK_F_WRLCK:
+ holder->exclusive = 1;
+ break;
+ }
+
+ holder->svid = flock->l_pid;
+ holder->l_offset = flock->l_start;
+ holder->l_len = flock->l_len;
+ return 0;
+}
+
+int
+nlm4_lock_to_gf_flock (struct gf_flock *flock, nlm4_lock *lock, int excl)
+{
+ flock->l_pid = lock->svid;
+ flock->l_start = lock->l_offset;
+ flock->l_len = lock->l_len;
+ if (excl)
+ flock->l_type = F_WRLCK;
+ else
+ flock->l_type = F_RDLCK;
+ flock->l_whence = SEEK_SET;
+ nlm_copy_lkowner (&flock->l_owner, &lock->oh);
+ return 0;
+}
+
+rpc_clnt_procedure_t nlm4_clnt_actors[NLM4_PROC_COUNT] = {
+ [NLM4_NULL] = {"NULL", NULL},
+ [NLM4_GRANTED] = {"GRANTED", NULL},
+};
+
+char *nlm4_clnt_names[NLM4_PROC_COUNT] = {
+ [NLM4_NULL] = "NULL",
+ [NLM4_GRANTED] = "GRANTED",
+};
+
+rpc_clnt_prog_t nlm4clntprog = {
+ .progname = "NLMv4",
+ .prognum = NLM_PROGRAM,
+ .progver = NLM_V4,
+ .numproc = NLM4_PROC_COUNT,
+ .proctable = nlm4_clnt_actors,
+ .procnames = nlm4_clnt_names,
+};
+
+int
+nlm4_test_reply (nfs3_call_state_t *cs, nlm4_stats stat, struct gf_flock *flock)
+{
+ nlm4_testres res;
+
+ memset (&res, 0, sizeof (res));
+ res.cookie = cs->args.nlm4_testargs.cookie;
+ res.stat.stat = stat;
+ if (stat == nlm4_denied)
+ nlm4_gf_flock_to_holder (&res.stat.nlm4_testrply_u.holder,
+ flock);
+
+ nlm4svc_submit_reply (cs->req, (void *)&res,
+ (nlm4_serializer)xdr_serialize_nlm4_testres);
+ return 0;
+}
+
+int
+nlm4svc_test_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, struct gf_flock *flock,
+ dict_t *xdata)
+{
+ nlm4_stats stat = nlm4_denied;
+ nfs3_call_state_t *cs = NULL;
+
+ cs = frame->local;
+ if (op_ret == -1) {
+ stat = nlm4_errno_to_nlm4stat (op_errno);
+ goto err;
+ } else if (flock->l_type == F_UNLCK)
+ stat = nlm4_granted;
+
+err:
+ nlm4_test_reply (cs, stat, flock);
+ nfs3_call_state_wipe (cs);
+ return 0;
+}
+
+int
+nlm4_test_fd_resume (void *carg)
+{
+ int ret = -EFAULT;
+ nfs_user_t nfu = {0, };
+ nfs3_call_state_t *cs = NULL;
+ struct gf_flock flock = {0, };
+
+ if (!carg)
+ return ret;
+
+ cs = (nfs3_call_state_t *)carg;
+ nfs_request_user_init (&nfu, cs->req);
+ nlm4_lock_to_gf_flock (&flock, &cs->args.nlm4_testargs.alock,
+ cs->args.nlm4_testargs.exclusive);
+ nlm_copy_lkowner (&nfu.lk_owner, &cs->args.nlm4_testargs.alock.oh);
+ ret = nfs_lk (cs->nfsx, cs->vol, &nfu, cs->fd, F_GETLK, &flock,
+ nlm4svc_test_cbk, cs);
+
+ return ret;
+}
+
+
+int
+nlm4_test_resume (void *carg)
+{
+ nlm4_stats stat = nlm4_failed;
+ int ret = -1;
+ nfs3_call_state_t *cs = NULL;
+ fd_t *fd = NULL;
+
+ if (!carg)
+ return ret;
+
+ cs = (nfs3_call_state_t *)carg;
+ nlm4_check_fh_resolve_status (cs, stat, nlm4err);
+ fd = fd_anonymous (cs->resolvedloc.inode);
+ if (!fd)
+ goto nlm4err;
+ cs->fd = fd;
+ ret = nlm4_test_fd_resume (cs);
+
+nlm4err:
+ if (ret < 0) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "unable to open_and_resume");
+ stat = nlm4_errno_to_nlm4stat (-ret);
+ nlm4_test_reply (cs, stat, NULL);
+ nfs3_call_state_wipe (cs);
+ }
+
+ return ret;
+}
+
+int
+nlm4svc_test (rpcsvc_request_t *req)
+{
+ xlator_t *vol = NULL;
+ nlm4_stats stat = nlm4_failed;
+ struct nfs_state *nfs = NULL;
+ nfs3_state_t *nfs3 = NULL;
+ nfs3_call_state_t *cs = NULL;
+ int ret = RPCSVC_ACTOR_ERROR;
+ struct nfs3_fh fh = {{0}, };
+
+ if (!req)
+ return ret;
+
+ nlm4_validate_nfs3_state (req, nfs3, stat, rpcerr, ret);
+ nfs = nfs_state (nfs3->nfsx);
+ nlm4_handle_call_state_init (nfs->nfs3state, cs, req,
+ stat, rpcerr);
+
+ nlm4_prep_nlm4_testargs (&cs->args.nlm4_testargs, &fh, &cs->lkowner,
+ cs->cookiebytes);
+ if (xdr_to_nlm4_testargs(req->msg[0], &cs->args.nlm4_testargs) <= 0) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "Error decoding args");
+ rpcsvc_request_seterr (req, GARBAGE_ARGS);
+ goto rpcerr;
+ }
+
+ nlm4_validate_gluster_fh (&fh, stat, nlm4err);
+ nlm4_map_fh_to_volume (cs->nfs3state, fh, req, vol, stat, nlm4err);
+
+ if (nlm_grace_period) {
+ gf_log (GF_NLM, GF_LOG_WARNING, "NLM in grace period");
+ stat = nlm4_denied_grace_period;
+ nlm4_test_reply (cs, stat, NULL);
+ nfs3_call_state_wipe (cs);
+ return 0;
+ }
+
+ cs->vol = vol;
+ nlm4_volume_started_check (nfs3, vol, ret, rpcerr);
+
+ ret = nfs3_fh_resolve_and_resume (cs, &fh,
+ NULL, nlm4_test_resume);
+
+nlm4err:
+ if (ret < 0) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "unable to resolve and resume");
+ nlm4_test_reply (cs, stat, NULL);
+ nfs3_call_state_wipe (cs);
+ return 0;
+ }
+
+rpcerr:
+ if (ret < 0)
+ nfs3_call_state_wipe (cs);
+
+ return ret;
+}
+
+int
+nlm4svc_send_granted_cbk (struct rpc_req *req, struct iovec *iov, int count,
+ void *myframe)
+{
+ STACK_DESTROY (((call_frame_t*)myframe)->root);
+ return 0;
+}
+
+void
+nlm4svc_send_granted (nfs3_call_state_t *cs);
+
+int
+nlm_rpcclnt_notify (struct rpc_clnt *rpc_clnt, void *mydata,
+ rpc_clnt_event_t fn, void *data)
+{
+ int ret = 0;
+ char *caller_name = NULL;
+ nfs3_call_state_t *cs = NULL;
+
+ cs = mydata;
+ caller_name = cs->args.nlm4_lockargs.alock.caller_name;
+
+ switch (fn) {
+ case RPC_CLNT_CONNECT:
+ ret = nlm_set_rpc_clnt (rpc_clnt, caller_name);
+ if (ret == -1) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "Failed to set rpc clnt");
+ goto err;
+ }
+ rpc_clnt_unref (rpc_clnt);
+ nlm4svc_send_granted (cs);
+
+ break;
+
+ case RPC_CLNT_MSG:
+ break;
+
+ case RPC_CLNT_DISCONNECT:
+ nlm_unset_rpc_clnt (rpc_clnt);
+ break;
+ }
+
+ err:
+ return 0;
+}
+
+void *
+nlm4_establish_callback (void *csarg)
+{
+ int ret = -1;
+ nfs3_call_state_t *cs = NULL;
+ union gf_sock_union sock_union;
+ dict_t *options = NULL;
+ char peerip[INET6_ADDRSTRLEN+1] = {0};
+ char *portstr = NULL;
+ char myip[INET6_ADDRSTRLEN+1] = {0};
+ rpc_clnt_t *rpc_clnt = NULL;
+ int port = -1;
+
+
+ cs = (nfs3_call_state_t *) csarg;
+ glusterfs_this_set (cs->nfsx);
+
+ rpc_transport_get_peeraddr (cs->trans, NULL, 0, &sock_union.storage,
+ sizeof (sock_union.storage));
+
+ switch (sock_union.sa.sa_family) {
+ case AF_INET6:
+ /* can not come here as NLM listens on IPv4 */
+ gf_log (GF_NLM, GF_LOG_ERROR, "NLM is not supported on IPv6 in"
+ " this release");
+ goto err;
+/*
+ inet_ntop (AF_INET6,
+ &((struct sockaddr_in6 *)sockaddr)->sin6_addr,
+ peerip, INET6_ADDRSTRLEN+1);
+ break;
+*/
+ case AF_INET:
+ inet_ntop (AF_INET, &sock_union.sin.sin_addr, peerip,
+ INET6_ADDRSTRLEN+1);
+ inet_ntop (AF_INET, &(((struct sockaddr_in *)&cs->trans->myinfo.sockaddr)->sin_addr),
+ myip, INET6_ADDRSTRLEN + 1);
+
+ break;
+ default:
+ break;
+ /* FIXME: handle the error */
+ }
+
+ /* looks like libc rpc supports only ipv4 */
+ port = pmap_getport (&sock_union.sin, NLM_PROGRAM,
+ NLM_V4, IPPROTO_TCP);
+
+ if (port == 0) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "Unable to get NLM port of the "
+ "client. Is the firewall running on client?");
+ goto err;
+ }
+
+ options = dict_new();
+ ret = dict_set_str (options, "transport-type", "socket");
+ if (ret == -1) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "dict_set_str error");
+ goto err;
+ }
+
+ ret = dict_set_dynstr (options, "remote-host", gf_strdup (peerip));
+ if (ret == -1) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "dict_set_str error");
+ goto err;
+ }
+
+ ret = gf_asprintf (&portstr, "%d", port);
+ if (ret == -1)
+ goto err;
+
+ ret = dict_set_dynstr (options, "remote-port",
+ portstr);
+ if (ret == -1) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "dict_set_dynstr error");
+ goto err;
+ }
+
+ /* needed in case virtual IP is used */
+ ret = dict_set_dynstr (options, "transport.socket.source-addr",
+ gf_strdup (myip));
+ if (ret == -1)
+ goto err;
+
+ ret = dict_set_str (options, "auth-null", "on");
+ if (ret == -1) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "dict_set_dynstr error");
+ goto err;
+ }
+
+ /* TODO: is 32 frames in transit enough ? */
+ rpc_clnt = rpc_clnt_new (options, cs->nfsx->ctx, "NLM-client", 32);
+ if (rpc_clnt == NULL) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "rpc_clnt NULL");
+ goto err;
+ }
+
+ ret = rpc_clnt_register_notify (rpc_clnt, nlm_rpcclnt_notify, cs);
+ if (ret == -1) {
+ gf_log (GF_NLM, GF_LOG_ERROR,"rpc_clnt_register_connect error");
+ goto err;
+ }
+
+ /* After this connect succeeds, granted msg is sent in notify */
+ ret = rpc_transport_connect (rpc_clnt->conn.trans, port);
+
+ if (ret == -1 && EINPROGRESS == errno)
+ ret = 0;
+
+err:
+ if (ret == -1 && rpc_clnt) {
+ rpc_clnt_unref (rpc_clnt);
+ }
+
+ return rpc_clnt;
+}
+
+void
+nlm4svc_send_granted (nfs3_call_state_t *cs)
+{
+ int ret = -1;
+ rpc_clnt_t *rpc_clnt = NULL;
+ struct iovec outmsg = {0, };
+ nlm4_testargs testargs;
+ struct iobuf *iobuf = NULL;
+ struct iobref *iobref = NULL;
+ char peerip[INET6_ADDRSTRLEN+1];
+ union gf_sock_union sock_union;
+
+ rpc_clnt = nlm_get_rpc_clnt (cs->args.nlm4_lockargs.alock.caller_name);
+ if (rpc_clnt == NULL) {
+ nlm4_establish_callback ((void*)cs);
+ return;
+ }
+
+ rpc_transport_get_peeraddr (cs->trans, NULL, 0, &sock_union.storage,
+ sizeof (sock_union.storage));
+
+ switch (sock_union.sa.sa_family) {
+ case AF_INET6:
+ inet_ntop (AF_INET6, &sock_union.sin6.sin6_addr, peerip,
+ INET6_ADDRSTRLEN+1);
+ break;
+ case AF_INET:
+ inet_ntop (AF_INET, &sock_union.sin.sin_addr, peerip,
+ INET6_ADDRSTRLEN+1);
+ break;
+ default:
+ break;
+ }
+
+ testargs.cookie = cs->args.nlm4_lockargs.cookie;
+ testargs.exclusive = cs->args.nlm4_lockargs.exclusive;
+ testargs.alock = cs->args.nlm4_lockargs.alock;
+
+ iobuf = iobuf_get (cs->nfs3state->iobpool);
+ if (!iobuf) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "Failed to get iobuf");
+ goto ret;
+ }
+
+ iobuf_to_iovec (iobuf, &outmsg);
+ /* Use the given serializer to translate the give C structure in arg
+ * to XDR format which will be written into the buffer in outmsg.
+ */
+ outmsg.iov_len = xdr_serialize_nlm4_testargs (outmsg, &testargs);
+
+ iobref = iobref_new ();
+ if (iobref == NULL) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "Failed to get iobref");
+ goto ret;
+ }
+
+ ret = iobref_add (iobref, iobuf);
+ if (ret) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "Failed to add iob to iobref");
+ goto ret;
+ }
+
+ ret = rpc_clnt_submit (rpc_clnt, &nlm4clntprog, NLM4_GRANTED,
+ nlm4svc_send_granted_cbk, &outmsg, 1,
+ NULL, 0, iobref, cs->frame, NULL, 0,
+ NULL, 0, NULL);
+
+ if (ret < 0) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "rpc_clnt_submit error");
+ goto ret;
+ }
+ret:
+ if (iobref)
+ iobref_unref (iobref);
+ if (iobuf)
+ iobuf_unref (iobuf);
+
+ rpc_clnt_unref (rpc_clnt);
+ nfs3_call_state_wipe (cs);
+ return;
+}
+
+int
+nlm_cleanup_fds (char *caller_name)
+{
+ int nlmclnt_found = 0;
+ nlm_fde_t *fde = NULL, *tmp = NULL;
+ nlm_client_t *nlmclnt = NULL;
+
+ LOCK (&nlm_client_list_lk);
+ list_for_each_entry (nlmclnt,
+ &nlm_client_list, nlm_clients) {
+ if (!strcmp(caller_name, nlmclnt->caller_name)) {
+ nlmclnt_found = 1;
+ break;
+ }
+ }
+
+ if (!nlmclnt_found)
+ goto ret;
+
+ if (list_empty (&nlmclnt->fdes))
+ goto ret;
+
+ list_for_each_entry_safe (fde, tmp, &nlmclnt->fdes, fde_list) {
+ fd_unref (fde->fd);
+ list_del (&fde->fde_list);
+ GF_FREE (fde);
+ }
+
+ret:
+ UNLOCK (&nlm_client_list_lk);
+ return 0;
+}
+
+void
+nlm_search_and_delete (fd_t *fd, char *caller_name)
+{
+ nlm_fde_t *fde = NULL;
+ nlm_client_t *nlmclnt = NULL;
+ int nlmclnt_found = 0;
+ int fde_found = 0;
+ int transit_cnt = 0;
+
+ LOCK (&nlm_client_list_lk);
+ list_for_each_entry (nlmclnt,
+ &nlm_client_list, nlm_clients) {
+ if (!strcmp(caller_name, nlmclnt->caller_name)) {
+ nlmclnt_found = 1;
+ break;
+ }
+ }
+
+ if (!nlmclnt_found)
+ goto ret;
+
+ list_for_each_entry (fde, &nlmclnt->fdes, fde_list) {
+ if (fde->fd == fd) {
+ fde_found = 1;
+ break;
+ }
+ }
+
+ if (!fde_found)
+ goto ret;
+ transit_cnt = fde->transit_cnt;
+ if (transit_cnt)
+ goto ret;
+ list_del (&fde->fde_list);
+
+ret:
+ UNLOCK (&nlm_client_list_lk);
+
+ if (fde_found && !transit_cnt) {
+ fd_unref (fde->fd);
+ GF_FREE (fde);
+ }
+ return;
+}
+
+int
+nlm_dec_transit_count (fd_t *fd, char *caller_name)
+{
+ nlm_fde_t *fde = NULL;
+ nlm_client_t *nlmclnt = NULL;
+ int nlmclnt_found = 0;
+ int fde_found = 0;
+ int transit_cnt = -1;
+
+ LOCK (&nlm_client_list_lk);
+ list_for_each_entry (nlmclnt,
+ &nlm_client_list, nlm_clients) {
+ if (!strcmp(caller_name, nlmclnt->caller_name)) {
+ nlmclnt_found = 1;
+ break;
+ }
+ }
+
+ if (!nlmclnt_found) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "nlmclnt not found");
+ nlmclnt = NULL;
+ goto ret;
+ }
+
+ list_for_each_entry (fde, &nlmclnt->fdes, fde_list) {
+ if (fde->fd == fd) {
+ fde_found = 1;
+ break;
+ }
+ }
+
+ if (fde_found) {
+ transit_cnt = --fde->transit_cnt;
+ goto ret;
+ }
+ret:
+
+ UNLOCK (&nlm_client_list_lk);
+ return transit_cnt;
+}
+
+
+nlm_client_t *
+nlm_search_and_add (fd_t *fd, char *caller_name)
+{
+ nlm_fde_t *fde = NULL;
+ nlm_client_t *nlmclnt = NULL;
+ int nlmclnt_found = 0;
+ int fde_found = 0;
+
+ LOCK (&nlm_client_list_lk);
+ list_for_each_entry (nlmclnt,
+ &nlm_client_list, nlm_clients) {
+ if (!strcmp(caller_name, nlmclnt->caller_name)) {
+ nlmclnt_found = 1;
+ break;
+ }
+ }
+
+ if (!nlmclnt_found) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "nlmclnt not found");
+ nlmclnt = NULL;
+ goto ret;
+ }
+
+ list_for_each_entry (fde, &nlmclnt->fdes, fde_list) {
+ if (fde->fd == fd) {
+ fde_found = 1;
+ break;
+ }
+ }
+
+ if (fde_found)
+ goto ret;
+
+ fde = GF_CALLOC (1, sizeof (*fde), gf_nfs_mt_nlm4_fde);
+
+ fde->fd = fd_ref (fd);
+ list_add (&fde->fde_list, &nlmclnt->fdes);
+ret:
+ if (nlmclnt_found && fde)
+ fde->transit_cnt++;
+ UNLOCK (&nlm_client_list_lk);
+ return nlmclnt;
+}
+
+int
+nlm4svc_lock_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, struct gf_flock *flock,
+ dict_t *xdata)
+{
+ nlm4_stats stat = nlm4_denied;
+ int transit_cnt = -1;
+ char *caller_name = NULL;
+ nfs3_call_state_t *cs = NULL;
+ pthread_t thr;
+
+ cs = frame->local;
+ caller_name = cs->args.nlm4_lockargs.alock.caller_name;
+ transit_cnt = nlm_dec_transit_count (cs->fd, caller_name);
+
+ if (op_ret == -1) {
+ if (transit_cnt == 0)
+ nlm_search_and_delete (cs->fd, caller_name);
+ stat = nlm4_errno_to_nlm4stat (op_errno);
+ goto err;
+ } else {
+ stat = nlm4_granted;
+ if (cs->monitor && !nlm_monitor (caller_name)) {
+ /* FIXME: handle nsm_monitor failure */
+ pthread_create (&thr, NULL, nsm_monitor, (void*)caller_name);
+ }
+ }
+
+err:
+ if (cs->args.nlm4_lockargs.block) {
+ cs->frame = copy_frame (frame);
+ frame->local = NULL;
+ nlm4svc_send_granted (cs);
+ } else {
+ nlm4_generic_reply (cs->req, cs->args.nlm4_lockargs.cookie,
+ stat);
+ nfs3_call_state_wipe (cs);
+ }
+ return 0;
+}
+
+int
+nlm4_lock_fd_resume (void *carg)
+{
+ nlm4_stats stat = nlm4_denied;
+ int ret = -EFAULT;
+ nfs_user_t nfu = {0, };
+ nfs3_call_state_t *cs = NULL;
+ struct gf_flock flock = {0, };
+
+ if (!carg)
+ return ret;
+
+ cs = (nfs3_call_state_t *)carg;
+ nlm4_check_fh_resolve_status (cs, stat, nlm4err);
+ (void) nlm_search_and_add (cs->fd,
+ cs->args.nlm4_lockargs.alock.caller_name);
+ nfs_request_user_init (&nfu, cs->req);
+ nlm4_lock_to_gf_flock (&flock, &cs->args.nlm4_lockargs.alock,
+ cs->args.nlm4_lockargs.exclusive);
+ nlm_copy_lkowner (&nfu.lk_owner, &cs->args.nlm4_lockargs.alock.oh);
+ if (cs->args.nlm4_lockargs.block) {
+ nlm4_generic_reply (cs->req, cs->args.nlm4_lockargs.cookie,
+ nlm4_blocked);
+ ret = nfs_lk (cs->nfsx, cs->vol, &nfu, cs->fd, F_SETLKW,
+ &flock, nlm4svc_lock_cbk, cs);
+ /* FIXME: handle error from nfs_lk() specially by just
+ * cleaning up cs and unblock the client lock request.
+ */
+ ret = 0;
+ } else
+ ret = nfs_lk (cs->nfsx, cs->vol, &nfu, cs->fd, F_SETLK,
+ &flock, nlm4svc_lock_cbk, cs);
+
+nlm4err:
+ if (ret < 0) {
+ stat = nlm4_errno_to_nlm4stat (-ret);
+ gf_log (GF_NLM, GF_LOG_ERROR, "unable to call lk()");
+ nlm4_generic_reply (cs->req, cs->args.nlm4_lockargs.cookie,
+ stat);
+ nfs3_call_state_wipe (cs);
+ }
+
+ return ret;
+}
+
+
+int
+nlm4_lock_resume (void *carg)
+{
+ nlm4_stats stat = nlm4_failed;
+ int ret = -1;
+ nfs3_call_state_t *cs = NULL;
+
+ if (!carg)
+ return ret;
+
+ cs = (nfs3_call_state_t *)carg;
+ nlm4_check_fh_resolve_status (cs, stat, nlm4err);
+ ret = nlm4_file_open_and_resume (cs, nlm4_lock_fd_resume);
+
+nlm4err:
+ if (ret < 0) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "unable to open and resume");
+ stat = nlm4_errno_to_nlm4stat (-ret);
+ nlm4_generic_reply (cs->req, cs->args.nlm4_lockargs.cookie,
+ stat);
+ nfs3_call_state_wipe (cs);
+ }
+
+ return ret;
+}
+
+int
+nlm4svc_lock_common (rpcsvc_request_t *req, int mon)
+{
+ int ret = RPCSVC_ACTOR_ERROR;
+ nlm4_stats stat = nlm4_failed;
+ struct nfs3_fh fh = {{0}, };
+ xlator_t *vol = NULL;
+ nfs3_state_t *nfs3 = NULL;
+ nfs3_call_state_t *cs = NULL;
+ struct nfs_state *nfs = NULL;
+
+ if (!req)
+ return ret;
+
+ nlm4_validate_nfs3_state (req, nfs3, stat, rpcerr, ret);
+ nfs = nfs_state (nfs3->nfsx);
+ nlm4_handle_call_state_init (nfs->nfs3state, cs, req,
+ stat, rpcerr);
+
+ nlm4_prep_nlm4_lockargs (&cs->args.nlm4_lockargs, &cs->lockfh,
+ &cs->lkowner, cs->cookiebytes);
+ if (xdr_to_nlm4_lockargs(req->msg[0], &cs->args.nlm4_lockargs) <= 0) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "Error decoding args");
+ rpcsvc_request_seterr (req, GARBAGE_ARGS);
+ goto rpcerr;
+ }
+
+ fh = cs->lockfh;
+ cs->monitor = mon;
+ nlm4_validate_gluster_fh (&fh, stat, nlm4err);
+ nlm4_map_fh_to_volume (cs->nfs3state, fh, req, vol, stat, nlm4err);
+
+ if (nlm_grace_period && !cs->args.nlm4_lockargs.reclaim) {
+ gf_log (GF_NLM, GF_LOG_WARNING, "NLM in grace period");
+ stat = nlm4_denied_grace_period;
+ nlm4_generic_reply (req, cs->args.nlm4_unlockargs.cookie, stat);
+ nfs3_call_state_wipe (cs);
+ return 0;
+ }
+
+ cs->vol = vol;
+ cs->trans = rpcsvc_request_transport_ref(req);
+ nlm4_volume_started_check (nfs3, vol, ret, rpcerr);
+
+ ret = nlm_add_nlmclnt (cs->args.nlm4_lockargs.alock.caller_name);
+
+ ret = nfs3_fh_resolve_and_resume (cs, &fh,
+ NULL, nlm4_lock_resume);
+
+nlm4err:
+ if (ret < 0) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "unable to resolve and resume");
+ nlm4_generic_reply (cs->req, cs->args.nlm4_lockargs.cookie,
+ stat);
+ nfs3_call_state_wipe (cs);
+ return 0;
+ }
+
+rpcerr:
+ if (ret < 0) {
+ nfs3_call_state_wipe (cs);
+ }
+
+ return ret;
+}
+
+int
+nlm4svc_lock (rpcsvc_request_t *req)
+{
+ return nlm4svc_lock_common (req, 1);
+}
+
+int
+nlm4svc_nm_lock (rpcsvc_request_t *req)
+{
+ return nlm4svc_lock_common (req, 0);
+}
+
+int
+nlm4svc_cancel_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, struct gf_flock *flock,
+ dict_t *xdata)
+{
+ nlm4_stats stat = nlm4_denied;
+ nfs3_call_state_t *cs = NULL;
+
+ cs = frame->local;
+ if (op_ret == -1) {
+ stat = nlm4_errno_to_nlm4stat (op_errno);
+ goto err;
+ } else
+ stat = nlm4_granted;
+
+err:
+ nlm4_generic_reply (cs->req, cs->args.nlm4_cancargs.cookie,
+ stat);
+ nfs3_call_state_wipe (cs);
+ return 0;
+}
+
+int
+nlm4_cancel_fd_resume (void *carg)
+{
+ int ret = -EFAULT;
+ nfs_user_t nfu = {0, };
+ nfs3_call_state_t *cs = NULL;
+ struct gf_flock flock = {0, };
+
+ if (!carg)
+ return ret;
+
+ cs = (nfs3_call_state_t *)carg;
+ nfs_request_user_init (&nfu, cs->req);
+ nlm4_lock_to_gf_flock (&flock, &cs->args.nlm4_cancargs.alock,
+ cs->args.nlm4_cancargs.exclusive);
+ nlm_copy_lkowner (&nfu.lk_owner, &cs->args.nlm4_cancargs.alock.oh);
+ flock.l_type = F_UNLCK;
+ ret = nfs_lk (cs->nfsx, cs->vol, &nfu, cs->fd, F_SETLK,
+ &flock, nlm4svc_cancel_cbk, cs);
+
+ return ret;
+}
+
+int
+nlm4_cancel_resume (void *carg)
+{
+ nlm4_stats stat = nlm4_failed;
+ int ret = -EFAULT;
+ nfs3_call_state_t *cs = NULL;
+ nlm_client_t *nlmclnt = NULL;
+
+ if (!carg)
+ return ret;
+
+ cs = (nfs3_call_state_t *)carg;
+ nlm4_check_fh_resolve_status (cs, stat, nlm4err);
+
+ nlmclnt = nlm_get_uniq (cs->args.nlm4_cancargs.alock.caller_name);
+ if (nlmclnt == NULL) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "nlm_get_uniq() returned NULL");
+ goto nlm4err;
+ }
+ cs->fd = fd_lookup_uint64 (cs->resolvedloc.inode, (uint64_t)nlmclnt);
+ if (cs->fd == NULL) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "fd_lookup_uint64 retrned NULL");
+ goto nlm4err;
+ }
+ ret = nlm4_cancel_fd_resume (cs);
+
+nlm4err:
+ if (ret < 0) {
+ gf_log (GF_NLM, GF_LOG_WARNING, "unable to unlock_fd_resume()");
+ stat = nlm4_errno_to_nlm4stat (-ret);
+ nlm4_generic_reply (cs->req, cs->args.nlm4_cancargs.cookie,
+ stat);
+
+ nfs3_call_state_wipe (cs);
+ }
+ /* clean up is taken care of */
+ return 0;
+}
+
+int
+nlm4svc_cancel (rpcsvc_request_t *req)
+{
+ xlator_t *vol = NULL;
+ nlm4_stats stat = nlm4_failed;
+ struct nfs_state *nfs = NULL;
+ nfs3_state_t *nfs3 = NULL;
+ nfs3_call_state_t *cs = NULL;
+ int ret = RPCSVC_ACTOR_ERROR;
+ struct nfs3_fh fh = {{0}, };
+
+ if (!req)
+ return ret;
+
+ nlm4_validate_nfs3_state (req, nfs3, stat, rpcerr, ret);
+ nfs = nfs_state (nfs3->nfsx);
+ nlm4_handle_call_state_init (nfs->nfs3state, cs, req,
+ stat, rpcerr);
+
+ nlm4_prep_nlm4_cancargs (&cs->args.nlm4_cancargs, &fh, &cs->lkowner,
+ cs->cookiebytes);
+ if (xdr_to_nlm4_cancelargs(req->msg[0], &cs->args.nlm4_cancargs) <= 0) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "Error decoding args");
+ rpcsvc_request_seterr (req, GARBAGE_ARGS);
+ goto rpcerr;
+ }
+
+ nlm4_validate_gluster_fh (&fh, stat, nlm4err);
+ nlm4_map_fh_to_volume (cs->nfs3state, fh, req, vol, stat, nlm4err);
+
+ if (nlm_grace_period) {
+ gf_log (GF_NLM, GF_LOG_WARNING, "NLM in grace period");
+ stat = nlm4_denied_grace_period;
+ nlm4_generic_reply (req, cs->args.nlm4_unlockargs.cookie, stat);
+ nfs3_call_state_wipe (cs);
+ return 0;
+ }
+
+ cs->vol = vol;
+ nlm4_volume_started_check (nfs3, vol, ret, rpcerr);
+
+ ret = nfs3_fh_resolve_and_resume (cs, &fh,
+ NULL, nlm4_cancel_resume);
+
+nlm4err:
+ if (ret < 0) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "unable to resolve and resume");
+ nlm4_generic_reply (cs->req, cs->args.nlm4_cancargs.cookie,
+ stat);
+ nfs3_call_state_wipe (cs);
+ return 0;
+ }
+
+rpcerr:
+ if (ret < 0) {
+ nfs3_call_state_wipe (cs);
+ }
+ return ret;
+}
+
+int
+nlm4svc_unlock_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, struct gf_flock *flock,
+ dict_t *xdata)
+{
+ nlm4_stats stat = nlm4_denied;
+ nfs3_call_state_t *cs = NULL;
+
+ cs = frame->local;
+ if (op_ret == -1) {
+ stat = nlm4_errno_to_nlm4stat (op_errno);
+ goto err;
+ } else {
+ stat = nlm4_granted;
+ if (flock->l_type == F_UNLCK)
+ nlm_search_and_delete (cs->fd,
+ cs->args.nlm4_unlockargs.alock.caller_name);
+ }
+
+err:
+ nlm4_generic_reply (cs->req, cs->args.nlm4_unlockargs.cookie, stat);
+ nfs3_call_state_wipe (cs);
+ return 0;
+}
+
+int
+nlm4_unlock_fd_resume (void *carg)
+{
+ int ret = -EFAULT;
+ nfs_user_t nfu = {0, };
+ nfs3_call_state_t *cs = NULL;
+ struct gf_flock flock = {0, };
+
+ if (!carg)
+ return ret;
+ cs = (nfs3_call_state_t *)carg;
+ nfs_request_user_init (&nfu, cs->req);
+ nlm4_lock_to_gf_flock (&flock, &cs->args.nlm4_unlockargs.alock, 0);
+ nlm_copy_lkowner (&nfu.lk_owner, &cs->args.nlm4_unlockargs.alock.oh);
+ flock.l_type = F_UNLCK;
+ ret = nfs_lk (cs->nfsx, cs->vol, &nfu, cs->fd, F_SETLK,
+ &flock, nlm4svc_unlock_cbk, cs);
+
+ return ret;
+}
+
+int
+nlm4_unlock_resume (void *carg)
+{
+ nlm4_stats stat = nlm4_failed;
+ int ret = -1;
+ nfs3_call_state_t *cs = NULL;
+ nlm_client_t *nlmclnt = NULL;
+
+ if (!carg)
+ return ret;
+
+ cs = (nfs3_call_state_t *)carg;
+ nlm4_check_fh_resolve_status (cs, stat, nlm4err);
+
+ nlmclnt = nlm_get_uniq (cs->args.nlm4_unlockargs.alock.caller_name);
+ if (nlmclnt == NULL) {
+ stat = nlm4_granted;
+ gf_log (GF_NLM, GF_LOG_WARNING, "nlm_get_uniq() returned NULL");
+ goto nlm4err;
+ }
+ cs->fd = fd_lookup_uint64 (cs->resolvedloc.inode, (uint64_t)nlmclnt);
+ if (cs->fd == NULL) {
+ stat = nlm4_granted;
+ gf_log (GF_NLM, GF_LOG_WARNING, "fd_lookup_uint64() returned "
+ "NULL");
+ goto nlm4err;
+ }
+ ret = nlm4_unlock_fd_resume (cs);
+
+nlm4err:
+ if (ret < 0) {
+ gf_log (GF_NLM, GF_LOG_WARNING, "unable to unlock_fd_resume");
+ stat = nlm4_errno_to_nlm4stat (-ret);
+ nlm4_generic_reply (cs->req, cs->args.nlm4_unlockargs.cookie,
+ stat);
+
+ nfs3_call_state_wipe (cs);
+ }
+ /* we have already taken care of cleanup */
+ return 0;
+}
+
+int
+nlm4svc_unlock (rpcsvc_request_t *req)
+{
+ xlator_t *vol = NULL;
+ nlm4_stats stat = nlm4_failed;
+ struct nfs_state *nfs = NULL;
+ nfs3_state_t *nfs3 = NULL;
+ nfs3_call_state_t *cs = NULL;
+ int ret = RPCSVC_ACTOR_ERROR;
+ struct nfs3_fh fh = {{0}, };
+
+ if (!req)
+ return ret;
+
+ nlm4_validate_nfs3_state (req, nfs3, stat, rpcerr, ret);
+ nfs = nfs_state (nfs3->nfsx);
+ nlm4_handle_call_state_init (nfs->nfs3state, cs, req,
+ stat, rpcerr);
+
+ nlm4_prep_nlm4_unlockargs (&cs->args.nlm4_unlockargs, &fh, &cs->lkowner,
+ cs->cookiebytes);
+ if (xdr_to_nlm4_unlockargs(req->msg[0], &cs->args.nlm4_unlockargs) <= 0)
+ {
+ gf_log (GF_NLM, GF_LOG_ERROR, "Error decoding args");
+ rpcsvc_request_seterr (req, GARBAGE_ARGS);
+ goto rpcerr;
+ }
+
+ nlm4_validate_gluster_fh (&fh, stat, nlm4err);
+ nlm4_map_fh_to_volume (cs->nfs3state, fh, req, vol, stat, nlm4err);
+
+ if (nlm_grace_period) {
+ gf_log (GF_NLM, GF_LOG_WARNING, "NLM in grace period");
+ stat = nlm4_denied_grace_period;
+ nlm4_generic_reply (req, cs->args.nlm4_unlockargs.cookie, stat);
+ nfs3_call_state_wipe (cs);
+ return 0;
+ }
+
+ cs->vol = vol;
+ /* FIXME: check if trans is being used at all for unlock */
+ cs->trans = rpcsvc_request_transport_ref(req);
+ nlm4_volume_started_check (nfs3, vol, ret, rpcerr);
+
+ ret = nfs3_fh_resolve_and_resume (cs, &fh,
+ NULL, nlm4_unlock_resume);
+
+nlm4err:
+ if (ret < 0) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "unable to resolve and resume");
+ nlm4_generic_reply (req, cs->args.nlm4_unlockargs.cookie, stat);
+ nfs3_call_state_wipe (cs);
+ return 0;
+ }
+
+rpcerr:
+ if (ret < 0) {
+ nfs3_call_state_wipe (cs);
+ }
+ return ret;
+}
+
+int
+nlm4_share_reply (nfs3_call_state_t *cs, nlm4_stats stat)
+{
+ nlm4_shareres res = {{0}, 0, 0};
+
+ if (!cs)
+ return -1;
+
+ res.cookie = cs->args.nlm4_shareargs.cookie;
+ res.stat = stat;
+ res.sequence = 0;
+
+ nlm4svc_submit_reply (cs->req, (void *)&res,
+ (nlm4_serializer)xdr_serialize_nlm4_shareres);
+ return 0;
+}
+
+nlm_share_t *
+nlm4_share_new ()
+{
+ nlm_share_t *share = NULL;
+
+ share = GF_CALLOC (1, sizeof (nlm_share_t),
+ gf_nfs_mt_nlm4_share);
+ if (!share)
+ goto out;
+
+ INIT_LIST_HEAD (&share->client_list);
+ INIT_LIST_HEAD (&share->inode_list);
+ out:
+ return share;
+}
+
+int
+nlm4_add_share_to_inode (nlm_share_t *share)
+{
+ int ret = -1;
+ uint64_t ctx = 0;
+ struct list_head *head = NULL;
+ xlator_t *this = NULL;
+ inode_t *inode = NULL;
+ struct nfs_inode_ctx *ictx = NULL;
+ struct nfs_state *priv = NULL;
+
+ this = THIS;
+ priv = this->private;
+ inode = share->inode;
+ ret = inode_ctx_get (inode, this, &ctx);
+
+ if (ret == -1) {
+ ictx = GF_CALLOC (1, sizeof (struct nfs_inode_ctx),
+ gf_nfs_mt_inode_ctx);
+ if (!ictx ) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "could not allocate nfs inode ctx");
+ ret = -1;
+ goto out;
+ }
+ ictx->generation = priv->generation;
+
+ head = &ictx->shares;
+ INIT_LIST_HEAD (head);
+
+ ret = inode_ctx_put (inode, this, (uint64_t)ictx);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "could not store share list");
+ goto out;
+ }
+ }
+ else {
+ ictx = (struct nfs_inode_ctx *)ctx;
+ head = &ictx->shares;
+ }
+
+ list_add (&share->inode_list, head);
+
+ out:
+ if (ret && head)
+ GF_FREE (head);
+
+ return ret;
+}
+
+int
+nlm4_approve_share_reservation (nfs3_call_state_t *cs)
+{
+ int ret = -1;
+ uint64_t ctx = 0;
+ fsh_mode req_mode = 0;
+ fsh_access req_access = 0;
+ inode_t *inode = NULL;
+ nlm_share_t *share = NULL;
+ struct list_head *head = NULL;
+ struct nfs_inode_ctx *ictx = NULL;
+
+ if (!cs)
+ goto out;
+
+ inode = cs->resolvedloc.inode;
+
+ ret = inode_ctx_get (inode, THIS, &ctx);
+ if (ret) {
+ ret = 0;
+ goto out;
+ }
+ ictx = (struct nfs_inode_ctx *)ctx;
+
+ head = &ictx->shares;
+ if (!head || list_empty (head))
+ goto out;
+
+ req_mode = cs->args.nlm4_shareargs.share.mode;
+ req_access = cs->args.nlm4_shareargs.share.access;
+
+ list_for_each_entry (share, head, inode_list) {
+ ret = (((req_mode & share->access) == 0) &&
+ ((req_access & share->mode) == 0));
+ if (!ret) {
+ ret = -1;
+ goto out;
+ }
+ }
+ ret = 0;
+
+ out:
+ return ret;
+}
+
+int
+nlm4_create_share_reservation (nfs3_call_state_t *cs)
+{
+ int ret = -1;
+ nlm_share_t *share = NULL;
+ nlm_client_t *client = NULL;
+ inode_t *inode = NULL;
+
+ LOCK (&nlm_client_list_lk);
+
+ inode = inode_ref (cs->resolvedloc.inode);
+ if (!inode) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "inode not found");
+ goto out;
+ }
+
+ client = __nlm_get_uniq (cs->args.nlm4_shareargs.share.caller_name);
+ if (!client) {
+ /* DO NOT add client. the client is supposed
+ to be here, since nlm4svc_share adds it */
+ gf_log (GF_NLM, GF_LOG_ERROR, "client not found");
+ goto out;
+ }
+
+ ret = nlm4_approve_share_reservation (cs);
+ if (ret)
+ goto out;
+
+ share = nlm4_share_new ();
+ if (!share) {
+ ret = -1;
+ goto out;
+ }
+
+ share->inode = inode;
+ share->mode = cs->args.nlm4_shareargs.share.mode;
+ share->access = cs->args.nlm4_shareargs.share.access;
+ nlm_copy_lkowner (&share->lkowner,
+ &cs->args.nlm4_shareargs.share.oh);
+
+ ret = nlm4_add_share_to_inode (share);
+ if (ret)
+ goto out;
+
+ list_add (&share->client_list, &client->shares);
+
+ out:
+ if (ret && inode) {
+ inode_unref (inode);
+ GF_FREE (share);
+ }
+
+ UNLOCK (&nlm_client_list_lk);
+ return ret;
+}
+
+/*
+ SHARE and UNSHARE calls DO NOT perform STACK_WIND,
+ the (non-monitored) share reservations are maintained
+ at *nfs xlator level only*, in memory
+*/
+int
+nlm4_share_resume (void *call_state)
+{
+ int ret = -1;
+ nlm4_stats stat = nlm4_failed;
+ nfs3_call_state_t *cs = NULL;
+
+ if (!call_state)
+ return ret;
+
+ cs = (nfs3_call_state_t *)call_state;
+ nlm4_check_fh_resolve_status (cs, stat, out);
+
+ ret = nlm4_create_share_reservation (cs);
+ if (!ret)
+ stat = nlm4_granted;
+
+ out:
+ nlm4_share_reply (cs, stat);
+ nfs3_call_state_wipe (cs);
+ return 0;
+}
+
+int
+nlm4svc_share (rpcsvc_request_t *req)
+{
+ nlm4_stats stat = nlm4_failed;
+ xlator_t *vol = NULL;
+ nfs3_state_t *nfs3 = NULL;
+ nfs3_call_state_t *cs = NULL;
+ struct nfs_state *nfs = NULL;
+ struct nfs3_fh fh = {{0}, };
+ int ret = RPCSVC_ACTOR_ERROR;
+
+ if (!req)
+ return ret;
+
+ nlm4_validate_nfs3_state (req, nfs3, stat, rpcerr, ret);
+ nfs = nfs_state (nfs3->nfsx);
+ nlm4_handle_call_state_init (nfs->nfs3state, cs, req,
+ stat, rpcerr);
+
+ nlm4_prep_shareargs (&cs->args.nlm4_shareargs, &cs->lockfh,
+ &cs->lkowner, cs->cookiebytes);
+
+ if (xdr_to_nlm4_shareargs (req->msg[0],
+ &cs->args.nlm4_shareargs) <= 0) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "Error decoding SHARE args");
+ rpcsvc_request_seterr (req, GARBAGE_ARGS);
+ goto rpcerr;
+ }
+
+ fh = cs->lockfh;
+ nlm4_validate_gluster_fh (&fh, stat, nlm4err);
+ nlm4_map_fh_to_volume (cs->nfs3state, fh, req,
+ vol, stat, nlm4err);
+
+ if (nlm_grace_period && !cs->args.nlm4_shareargs.reclaim) {
+ gf_log (GF_NLM, GF_LOG_DEBUG, "NLM in grace period");
+ stat = nlm4_denied_grace_period;
+ nlm4_share_reply (cs, stat);
+ nfs3_call_state_wipe (cs);
+ return 0;
+ }
+
+ cs->vol = vol;
+ cs->trans = rpcsvc_request_transport_ref(req);
+ nlm4_volume_started_check (nfs3, vol, ret, rpcerr);
+
+ ret = nlm_add_nlmclnt (cs->args.nlm4_shareargs.share.caller_name);
+
+ ret = nfs3_fh_resolve_and_resume (cs, &fh, NULL, nlm4_share_resume);
+
+ nlm4err:
+ if (ret < 0) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "SHARE call failed");
+ nlm4_share_reply (cs, stat);
+ nfs3_call_state_wipe (cs);
+ return 0;
+ }
+
+ rpcerr:
+ if (ret < 0)
+ nfs3_call_state_wipe (cs);
+
+ return ret;
+}
+
+int
+nlm4_remove_share_reservation (nfs3_call_state_t *cs)
+{
+ int ret = -1;
+ uint64_t ctx = 0;
+ fsh_mode req_mode = 0;
+ fsh_access req_access = 0;
+ nlm_share_t *share = NULL;
+ nlm_share_t *tmp = NULL;
+ nlm_client_t *client = NULL;
+ char *caller = NULL;
+ inode_t *inode = NULL;
+ xlator_t *this = NULL;
+ struct list_head *head = NULL;
+ nlm4_shareargs *args = NULL;
+ struct nfs_inode_ctx *ictx = NULL;
+
+ LOCK (&nlm_client_list_lk);
+
+ args = &cs->args.nlm4_shareargs;
+ caller = args->share.caller_name;
+
+ client = __nlm_get_uniq (caller);
+ if (!client) {
+ gf_log (GF_NLM, GF_LOG_ERROR,
+ "client not found: %s", caller);
+ goto out;
+ }
+
+ inode = cs->resolvedloc.inode;
+ if (!inode) {
+ gf_log (GF_NLM, GF_LOG_ERROR,
+ "inode not found: client: %s", caller);
+ goto out;
+ }
+
+ this = THIS;
+ ret = inode_ctx_get (inode, this, &ctx);
+ if (ret) {
+ gf_log (GF_NLM, GF_LOG_ERROR,
+ "no shares found for inode:"
+ "gfid: %s; client: %s",
+ inode->gfid, caller);
+ goto out;
+ }
+ ictx = (struct nfs_inode_ctx *)ctx;
+
+ head = &ictx->shares;
+ if (list_empty (head)) {
+ ret = -1;
+ goto out;
+ }
+
+ ret = 0;
+ req_mode = args->share.mode;
+ req_access = args->share.access;
+
+ list_for_each_entry_safe (share, tmp, head, inode_list) {
+ ret = ((req_mode == share->mode) &&
+ (req_access == share->access) &&
+ nlm_is_oh_same_lkowner (&share->lkowner, &args->share.oh));
+ if (ret) {
+ list_del (&share->client_list);
+ list_del (&share->inode_list);
+ inode_unref (share->inode);
+ GF_FREE (share);
+ break;
+ }
+ }
+
+ ret = 0;
+ out:
+ UNLOCK (&nlm_client_list_lk);
+ return ret;
+
+}
+
+int
+nlm4_unshare_resume (void *call_state)
+{
+ int ret = -1;
+ nlm4_stats stat = nlm4_failed;
+ nfs3_call_state_t *cs = NULL;
+
+ if (!call_state)
+ return ret;
+
+ cs = (nfs3_call_state_t *)call_state;
+
+ nlm4_check_fh_resolve_status (cs, stat, out);
+ ret = nlm4_remove_share_reservation (cs);
+ if (!ret)
+ stat = nlm4_granted;
+
+ out:
+ nlm4_share_reply (cs, stat);
+ nfs3_call_state_wipe (cs);
+ return 0;
+}
+
+int
+nlm4svc_unshare (rpcsvc_request_t *req)
+{
+ nlm4_stats stat = nlm4_failed;
+ xlator_t *vol = NULL;
+ nfs3_state_t *nfs3 = NULL;
+ nfs3_call_state_t *cs = NULL;
+ struct nfs_state *nfs = NULL;
+ struct nfs3_fh fh = {{0}, };
+ int ret = RPCSVC_ACTOR_ERROR;
+
+ if (!req)
+ return ret;
+
+ nlm4_validate_nfs3_state (req, nfs3, stat, rpcerr, ret);
+ nfs = nfs_state (nfs3->nfsx);
+ nlm4_handle_call_state_init (nfs->nfs3state, cs, req,
+ stat, rpcerr);
+
+ nlm4_prep_shareargs (&cs->args.nlm4_shareargs, &cs->lockfh,
+ &cs->lkowner, cs->cookiebytes);
+
+ if (xdr_to_nlm4_shareargs (req->msg[0],
+ &cs->args.nlm4_shareargs) <= 0) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "Error decoding UNSHARE args");
+ rpcsvc_request_seterr (req, GARBAGE_ARGS);
+ goto rpcerr;
+ }
+
+ fh = cs->lockfh;
+ nlm4_validate_gluster_fh (&fh, stat, nlm4err);
+ nlm4_map_fh_to_volume (cs->nfs3state, fh, req,
+ vol, stat, nlm4err);
+
+ if (nlm_grace_period && !cs->args.nlm4_shareargs.reclaim) {
+ gf_log (GF_NLM, GF_LOG_DEBUG, "NLM in grace period");
+ stat = nlm4_denied_grace_period;
+ nlm4_share_reply (cs, stat);
+ nfs3_call_state_wipe (cs);
+ return 0;
+ }
+
+ cs->vol = vol;
+ cs->trans = rpcsvc_request_transport_ref(req);
+ nlm4_volume_started_check (nfs3, vol, ret, rpcerr);
+
+ ret = nfs3_fh_resolve_and_resume (cs, &fh, NULL,
+ nlm4_unshare_resume);
+
+ nlm4err:
+ if (ret < 0) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "UNSHARE call failed");
+ nlm4_share_reply (cs, stat);
+ ret = 0;
+ return 0;
+ }
+
+ rpcerr:
+ if (ret < 0)
+ nfs3_call_state_wipe (cs);
+
+ return ret;
+}
+
+int
+nlm4_free_all_shares (char *caller_name)
+{
+ nlm_share_t *share = NULL;
+ nlm_share_t *tmp = NULL;
+ nlm_client_t *client = NULL;
+
+ LOCK (&nlm_client_list_lk);
+
+ client = __nlm_get_uniq (caller_name);
+ if (!client) {
+ gf_log (GF_NLM, GF_LOG_DEBUG,
+ "client not found: %s", caller_name);
+ goto out;
+ }
+
+ list_for_each_entry_safe (share, tmp, &client->shares, client_list) {
+ list_del (&share->inode_list);
+ list_del (&share->client_list);
+ inode_unref (share->inode);
+ GF_FREE (share);
+ }
+ out:
+ UNLOCK (&nlm_client_list_lk);
+ return 0;
+}
+
+int
+nlm4svc_free_all (rpcsvc_request_t *req)
+{
+ int ret = RPCSVC_ACTOR_ERROR;
+ nlm4_stats stat = nlm4_failed;
+ nfs3_state_t *nfs3 = NULL;
+ nfs3_call_state_t *cs = NULL;
+ struct nfs_state *nfs = NULL;
+
+ nlm4_validate_nfs3_state (req, nfs3, stat, err, ret);
+ nfs = nfs_state (nfs3->nfsx);
+ nlm4_handle_call_state_init (nfs->nfs3state, cs,
+ req, stat, err);
+
+ nlm4_prep_freeallargs (&cs->args.nlm4_freeallargs,
+ &cs->lkowner);
+
+ if (xdr_to_nlm4_freeallargs (req->msg[0],
+ &cs->args.nlm4_freeallargs) <= 0) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "Error decoding FREE_ALL args");
+ rpcsvc_request_seterr (req, GARBAGE_ARGS);
+ goto err;
+ }
+
+ ret = nlm4_free_all_shares (cs->args.nlm4_freeallargs.name);
+ if (ret)
+ goto err;
+
+ ret = nlm_cleanup_fds (cs->args.nlm4_freeallargs.name);
+ if (ret)
+ goto err;
+
+ err:
+ nfs3_call_state_wipe (cs);
+ if (ret)
+ gf_log (GF_NLM, GF_LOG_DEBUG,
+ "error in free all; stat: %d", stat);
+ return ret;
+
+}
+
+void
+nlm4svc_sm_notify (struct nlm_sm_status *status)
+{
+ gf_log (GF_NLM, GF_LOG_INFO, "sm_notify: %s, state: %d",
+ status->mon_name,
+ status->state);
+ nlm_cleanup_fds (status->mon_name);
+}
+
+rpcsvc_actor_t nlm4svc_actors[NLM4_PROC_COUNT] = {
+ /* 0 */
+ {"NULL", NLM4_NULL, nlm4svc_null, NULL, 0, DRC_IDEMPOTENT},
+ {"TEST", NLM4_TEST, nlm4svc_test, NULL, 0, DRC_IDEMPOTENT},
+ {"LOCK", NLM4_LOCK, nlm4svc_lock, NULL, 0, DRC_NON_IDEMPOTENT},
+ {"CANCEL", NLM4_CANCEL, nlm4svc_cancel, NULL, 0, DRC_NON_IDEMPOTENT},
+ {"UNLOCK", NLM4_UNLOCK, nlm4svc_unlock, NULL, 0, DRC_NON_IDEMPOTENT},
+ /* 5 */
+ {"GRANTED", NLM4_GRANTED, NULL, NULL, 0, DRC_NA},
+ {"TEST", NLM4_TEST_MSG, NULL, NULL, 0, DRC_NA},
+ {"LOCK", NLM4_LOCK_MSG, NULL, NULL, 0, DRC_NA},
+ {"CANCEL", NLM4_CANCEL_MSG, NULL, NULL, 0, DRC_NA},
+ {"UNLOCK", NLM4_UNLOCK_MSG, NULL, NULL, 0, DRC_NA},
+ /* 10 */
+ {"GRANTED", NLM4_GRANTED_MSG, NULL, NULL, 0, DRC_NA},
+ {"TEST", NLM4_TEST_RES, NULL, NULL, 0, DRC_NA},
+ {"LOCK", NLM4_LOCK_RES, NULL, NULL, 0, DRC_NA},
+ {"CANCEL", NLM4_CANCEL_RES, NULL, NULL, 0, DRC_NA},
+ {"UNLOCK", NLM4_UNLOCK_RES, NULL, NULL, 0, DRC_NA},
+ /* 15 ; procedures 17,18,19 are not defined by nlm */
+ {"GRANTED", NLM4_GRANTED_RES, NULL, NULL, 0, DRC_NA},
+ {"SM_NOTIFY", NLM4_SM_NOTIFY, NULL, NULL, 0, DRC_NA},
+ {"SEVENTEEN", NLM4_SEVENTEEN, NULL, NULL, 0, DRC_NA},
+ {"EIGHTEEN", NLM4_EIGHTEEN, NULL, NULL, 0, DRC_NA},
+ {"NINETEEN", NLM4_NINETEEN, NULL, NULL, 0, DRC_NA},
+ /* 20 */
+ {"SHARE", NLM4_SHARE, nlm4svc_share, NULL, 0, DRC_NON_IDEMPOTENT},
+ {"UNSHARE", NLM4_UNSHARE, nlm4svc_unshare, NULL, 0, DRC_NON_IDEMPOTENT},
+ {"NM_LOCK", NLM4_NM_LOCK, nlm4svc_nm_lock, NULL, 0, DRC_NON_IDEMPOTENT},
+ {"FREE_ALL", NLM4_FREE_ALL, nlm4svc_free_all, NULL, 0, DRC_IDEMPOTENT},
+};
+
+rpcsvc_program_t nlm4prog = {
+ .progname = "NLM4",
+ .prognum = NLM_PROGRAM,
+ .progver = NLM_V4,
+ .progport = GF_NLM4_PORT,
+ .actors = nlm4svc_actors,
+ .numactors = NLM4_PROC_COUNT,
+ .min_auth = AUTH_NULL,
+};
+
+
+int
+nlm4_init_state (xlator_t *nfsx)
+{
+ return 0;
+}
+
+extern void *nsm_thread (void *argv);
+
+void nlm_grace_period_over(void *arg)
+{
+ nlm_grace_period = 0;
+}
+
+rpcsvc_program_t *
+nlm4svc_init(xlator_t *nfsx)
+{
+ struct nfs3_state *ns = NULL;
+ struct nfs_state *nfs = NULL;
+ dict_t *options = NULL;
+ int ret = -1;
+ char *portstr = NULL;
+ pthread_t thr;
+ struct timespec timeout = {0,};
+ FILE *pidfile = NULL;
+ pid_t pid = -1;
+ static gf_boolean_t nlm4_inited = _gf_false;
+
+ /* Already inited */
+ if (nlm4_inited)
+ return &nlm4prog;
+
+ nfs = (struct nfs_state*)nfsx->private;
+
+ ns = nfs->nfs3state;
+ if (!ns) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "NLM4 init failed");
+ goto err;
+ }
+ nlm4prog.private = ns;
+
+ options = dict_new ();
+
+ ret = gf_asprintf (&portstr, "%d", GF_NLM4_PORT);
+ if (ret == -1)
+ goto err;
+
+ ret = dict_set_dynstr (options, "transport.socket.listen-port",
+ portstr);
+ if (ret == -1)
+ goto err;
+ ret = dict_set_str (options, "transport-type", "socket");
+ if (ret == -1) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "dict_set_str error");
+ goto err;
+ }
+
+ if (nfs->allow_insecure) {
+ ret = dict_set_str (options, "rpc-auth-allow-insecure", "on");
+ if (ret == -1) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "dict_set_str error");
+ goto err;
+ }
+ ret = dict_set_str (options, "rpc-auth.ports.insecure", "on");
+ if (ret == -1) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "dict_set_str error");
+ goto err;
+ }
+ }
+
+ ret = dict_set_str (options, "transport.address-family", "inet");
+ if (ret == -1) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "dict_set_str error");
+ goto err;
+ }
+
+ ret = rpcsvc_create_listeners (nfs->rpcsvc, options, "NLM");
+ if (ret == -1) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "Unable to create listeners");
+ dict_unref (options);
+ goto err;
+ }
+ INIT_LIST_HEAD(&nlm_client_list);
+ LOCK_INIT (&nlm_client_list_lk);
+
+ /* unlink sm-notify.pid so that when we restart rpc.statd/sm-notify
+ * it thinks that the machine has restarted and sends NOTIFY to clients.
+ */
+ ret = unlink ("/var/run/sm-notify.pid");
+ if (ret == -1 && errno != ENOENT) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "unable to unlink sm-notify");
+ goto err;
+ }
+ /* temporary work around to restart statd, not distro/OS independant.
+ * Need to figure out a more graceful way
+ * killall will cause problems on solaris.
+ */
+
+ pidfile = fopen ("/var/run/rpc.statd.pid", "r");
+ if (pidfile) {
+ ret = fscanf (pidfile, "%d", &pid);
+ if (ret <= 0) {
+ gf_log (GF_NLM, GF_LOG_WARNING, "unable to get pid of "
+ "rpc.statd");
+ ret = runcmd ("killall", "-9", "rpc.statd", NULL);
+ } else
+ kill (pid, SIGKILL);
+
+ fclose (pidfile);
+ } else {
+ gf_log (GF_NLM, GF_LOG_WARNING, "opening the pid file of "
+ "rpc.statd failed (%s)", strerror (errno));
+ /* if ret == -1, do nothing - case either statd was not
+ * running or was running in valgrind mode
+ */
+ ret = runcmd ("killall", "-9", "rpc.statd", NULL);
+ }
+
+ ret = unlink ("/var/run/rpc.statd.pid");
+ if (ret == -1 && errno != ENOENT) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "unable to unlink rpc.statd");
+ goto err;
+ }
+
+ ret = runcmd ("/sbin/rpc.statd", NULL);
+ if (ret == -1) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "unable to start rpc.statd");
+ goto err;
+ }
+ pthread_create (&thr, NULL, nsm_thread, (void*)NULL);
+
+ timeout.tv_sec = nlm_grace_period;
+ timeout.tv_nsec = 0;
+
+ gf_timer_call_after (nfsx->ctx, timeout, nlm_grace_period_over, NULL);
+ nlm4_inited = _gf_true;
+ return &nlm4prog;
+err:
+ return NULL;
+}
+
+int32_t
+nlm_priv (xlator_t *this)
+{
+ int32_t ret = -1;
+ uint32_t client_count = 0;
+ uint64_t file_count = 0;
+ nlm_client_t *client = NULL;
+ nlm_fde_t *fde = NULL;
+ char key[GF_DUMP_MAX_BUF_LEN] = {0};
+ char gfid_str[64] = {0};
+
+ gf_proc_dump_add_section("nfs.nlm");
+
+ if (TRY_LOCK (&nlm_client_list_lk))
+ goto out;
+
+ list_for_each_entry (client, &nlm_client_list, nlm_clients) {
+
+ gf_proc_dump_build_key (key, "client", "%d.hostname", client_count);
+ gf_proc_dump_write (key, "%s\n", client->caller_name);
+
+ file_count = 0;
+ list_for_each_entry (fde, &client->fdes, fde_list) {
+ gf_proc_dump_build_key (key, "file", "%ld.gfid", file_count);
+ memset (gfid_str, 0, 64);
+ uuid_utoa_r (fde->fd->inode->gfid, gfid_str);
+ gf_proc_dump_write (key, "%s", gfid_str);
+ file_count++;
+ }
+
+ gf_proc_dump_build_key (key, "client", "files-locked");
+ gf_proc_dump_write (key, "%ld\n", file_count);
+ client_count++;
+ }
+
+ gf_proc_dump_build_key (key, "nlm", "client-count");
+ gf_proc_dump_write (key, "%d", client_count);
+ ret = 0;
+ UNLOCK (&nlm_client_list_lk);
+
+ out:
+ if (ret) {
+ gf_proc_dump_build_key (key, "nlm", "statedump_error");
+ gf_proc_dump_write (key, "Unable to dump nlm state because "
+ "nlm_client_list_lk lock couldn't be acquired");
+ }
+
+ return ret;
+}
diff --git a/xlators/nfs/server/src/nlm4.h b/xlators/nfs/server/src/nlm4.h
new file mode 100644
index 000000000..9b5d54081
--- /dev/null
+++ b/xlators/nfs/server/src/nlm4.h
@@ -0,0 +1,77 @@
+/*
+ Copyright (c) 2012 Gluster, Inc. <http://www.gluster.com>
+ This file is part of GlusterFS.
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
+*/
+
+#ifndef _NLM4_H_
+#define _NLM4_H_
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <signal.h>
+#include "rpcsvc.h"
+#include "dict.h"
+#include "xlator.h"
+#include "iobuf.h"
+#include "nfs.h"
+#include "list.h"
+#include "xdr-nfs3.h"
+#include "locking.h"
+#include "nfs3-fh.h"
+#include "uuid.h"
+#include "nlm4-xdr.h"
+#include "lkowner.h"
+
+/* Registered with portmap */
+#define GF_NLM4_PORT 38468
+#define GF_NLM GF_NFS"-NLM"
+
+extern rpcsvc_program_t *
+nlm4svc_init (xlator_t *nfsx);
+
+extern int
+nlm4_init_state (xlator_t *nfsx);
+
+#define NLM_PROGRAM 100021
+#define NLM_V4 4
+
+typedef struct nlm4_lwowner {
+ char temp[1024];
+} nlm4_lkowner_t;
+
+typedef struct nlm_client {
+ struct sockaddr_storage sa;
+ pid_t uniq;
+ struct list_head nlm_clients;
+ struct list_head fdes;
+ struct list_head shares;
+ struct rpc_clnt *rpc_clnt;
+ char *caller_name;
+ int nsm_monitor;
+} nlm_client_t;
+
+typedef struct nlm_share {
+ struct list_head client_list;
+ struct list_head inode_list;
+ gf_lkowner_t lkowner;
+ inode_t *inode;
+ fsh_mode mode;
+ fsh_access access;
+} nlm_share_t;
+
+typedef struct nlm_fde {
+ struct list_head fde_list;
+ fd_t *fd;
+ int transit_cnt;
+} nlm_fde_t;
+
+#endif
diff --git a/xlators/nfs/server/src/nlmcbk_svc.c b/xlators/nfs/server/src/nlmcbk_svc.c
new file mode 100644
index 000000000..e1b588765
--- /dev/null
+++ b/xlators/nfs/server/src/nlmcbk_svc.c
@@ -0,0 +1,117 @@
+/*
+ Copyright (c) 2012 Gluster, Inc. <http://www.gluster.com>
+ This file is part of GlusterFS.
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
+*/
+
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#include "nlmcbk-xdr.h"
+#include "nlm4.h"
+#include "logging.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <rpc/pmap_clnt.h>
+#include <string.h>
+#include <memory.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#ifndef SIG_PF
+#define SIG_PF void(*)(int)
+#endif
+
+void
+nlm4svc_sm_notify (struct nlm_sm_status *status);
+
+void *nlmcbk_sm_notify_0_svc(struct nlm_sm_status *status, struct svc_req *req)
+{
+ nlm4svc_sm_notify (status);
+ return NULL;
+}
+
+static void
+nlmcbk_program_0(struct svc_req *rqstp, register SVCXPRT *transp)
+{
+ union {
+ struct nlm_sm_status nlmcbk_sm_notify_0_arg;
+ } argument;
+ char *result;
+ xdrproc_t _xdr_argument, _xdr_result;
+ char *(*local)(char *, struct svc_req *);
+
+ switch (rqstp->rq_proc) {
+ case NULLPROC:
+ (void) svc_sendreply (transp, (xdrproc_t) xdr_void, (char *)NULL);
+ return;
+
+ case NLMCBK_SM_NOTIFY:
+ _xdr_argument = (xdrproc_t) xdr_nlm_sm_status;
+ _xdr_result = (xdrproc_t) xdr_void;
+ local = (char *(*)(char *, struct svc_req *)) nlmcbk_sm_notify_0_svc;
+ break;
+
+ default:
+ svcerr_noproc (transp);
+ return;
+ }
+ memset ((char *)&argument, 0, sizeof (argument));
+ if (!svc_getargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) {
+ svcerr_decode (transp);
+ return;
+ }
+ result = (*local)((char *)&argument, rqstp);
+ if (!svc_sendreply(transp, (xdrproc_t) _xdr_result, result)) {
+ svcerr_systemerr (transp);
+ }
+
+ if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "unable to free arguments");
+ return;
+ }
+ return;
+}
+
+void *
+nsm_thread (void *argv)
+{
+ register SVCXPRT *transp;
+ int ret = 0;
+
+ ret = pmap_unset (NLMCBK_PROGRAM, NLMCBK_V1);
+ if (ret == 0) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "pmap_unset failed");
+ return NULL;
+ }
+ transp = svcudp_create(RPC_ANYSOCK);
+ if (transp == NULL) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "cannot create udp service.");
+ return NULL;
+ }
+ if (!svc_register(transp, NLMCBK_PROGRAM, NLMCBK_V1, nlmcbk_program_0, IPPROTO_UDP)) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "unable to register (NLMCBK_PROGRAM, NLMCBK_V0, udp).");
+ return NULL;
+ }
+
+ transp = svctcp_create(RPC_ANYSOCK, 0, 0);
+ if (transp == NULL) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "cannot create tcp service.");
+ return NULL;
+ }
+ if (!svc_register(transp, NLMCBK_PROGRAM, NLMCBK_V1, nlmcbk_program_0, IPPROTO_TCP)) {
+ gf_log (GF_NLM, GF_LOG_ERROR, "unable to register (NLMCBK_PROGRAM, NLMCBK_V0, tcp).");
+ return NULL;
+ }
+
+ svc_run ();
+ gf_log (GF_NLM, GF_LOG_ERROR, "svc_run returned");
+ return NULL;
+ /* NOTREACHED */
+}