summaryrefslogtreecommitdiffstats
path: root/xlators/nfs/server/src/nfs3.c
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/nfs/server/src/nfs3.c')
-rw-r--r--xlators/nfs/server/src/nfs3.c2372
1 files changed, 1580 insertions, 792 deletions
diff --git a/xlators/nfs/server/src/nfs3.c b/xlators/nfs/server/src/nfs3.c
index 4129a1880..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);
@@ -181,42 +427,40 @@ nfs3_call_state_init (struct nfs3_state *s, rpcsvc_request_t *req, xlator_t *v)
cs->req = req;
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 = rpcsvc_request_program_private (cs->req);
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. */
}
@@ -252,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");
@@ -290,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;
@@ -300,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;
@@ -315,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;
}
@@ -322,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;
@@ -334,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;
}
@@ -374,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;
}
@@ -384,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);
@@ -401,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);
@@ -423,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);
@@ -452,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;
@@ -464,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));
@@ -480,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;
}
@@ -500,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);
@@ -515,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;
}
@@ -537,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;
@@ -560,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;
@@ -573,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;
@@ -581,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;
}
@@ -596,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);
@@ -608,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;
@@ -618,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);
@@ -654,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);
}
@@ -667,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;
@@ -677,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;
}
@@ -697,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);
}
@@ -721,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);
}
@@ -755,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,
@@ -781,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;
}
@@ -790,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
@@ -799,7 +1133,7 @@ nfs3err:
*/
ret = 0;
}
-
+out:
return ret;
}
@@ -812,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;
@@ -840,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,
@@ -855,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;
}
@@ -883,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 = 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;
}
- nfs3_fh_build_parent_fh (&cs->fh, buf, &newfh);
+ 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);
@@ -912,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);
@@ -921,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);
@@ -942,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);
@@ -962,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)
@@ -977,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);
}
@@ -988,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;
@@ -1011,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);
@@ -1024,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);
@@ -1047,7 +1470,7 @@ nfs3err:
*/
ret = 0;
}
-
+out:
return ret;
}
@@ -1060,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;
@@ -1083,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;
@@ -1101,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;
@@ -1127,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;
}
@@ -1161,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;
@@ -1177,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;
}
@@ -1199,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;
@@ -1222,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);
@@ -1236,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;
}
@@ -1280,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);
}
@@ -1308,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);
@@ -1316,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
@@ -1325,7 +1753,7 @@ nfs3err:
*/
ret = 0;
}
-
+out:
return ret;
}
@@ -1341,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;
@@ -1360,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
@@ -1395,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;
@@ -1403,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;
@@ -1413,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;
@@ -1441,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);
}
@@ -1457,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);
}
@@ -1493,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;
@@ -1508,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;
}
@@ -1530,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;
@@ -1554,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);
@@ -1568,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;
@@ -1577,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,
@@ -1591,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;
}
@@ -1664,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;
}
@@ -1677,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);
@@ -1726,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;
@@ -1743,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;
}
@@ -1781,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;
-
- if (!req)
- return ret;
+ int ret = 0;
+ uint32_t fhlen = 0;
+ uint32_t fhlen_n = 0;
- 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;
@@ -1880,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;
@@ -1900,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;
@@ -1911,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);
@@ -1938,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) {
@@ -1963,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);
@@ -1986,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.
@@ -2015,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;
@@ -2025,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);
}
@@ -2056,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
@@ -2072,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;
}
@@ -2109,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);
@@ -2136,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;
@@ -2151,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;
}
@@ -2165,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;
@@ -2201,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;
@@ -2211,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);
@@ -2238,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;
@@ -2247,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;
}
@@ -2269,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);
@@ -2308,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);
}
@@ -2334,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)
@@ -2351,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;
}
@@ -2373,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;
@@ -2397,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);
@@ -2410,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;
}
@@ -2425,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);
@@ -2455,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);
}
@@ -2480,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;
@@ -2502,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
@@ -2511,7 +2994,7 @@ nfs3err:
*/
ret = 0;
}
-
+out:
return ret;
}
@@ -2528,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;
@@ -2536,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;
@@ -2553,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);
@@ -2563,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);
@@ -2590,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;
@@ -2599,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;
}
@@ -2621,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);
@@ -2719,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);
}
@@ -2746,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;
@@ -2760,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:
@@ -2781,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.
@@ -2790,7 +3288,7 @@ nfs3err:
nfs3_call_state_wipe (cs);
ret = 0;
}
-
+out:
return ret;
}
@@ -2806,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;
@@ -2828,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;
@@ -2842,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;
@@ -2916,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);
@@ -2940,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);
@@ -2954,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
@@ -2963,7 +3454,7 @@ nfs3err:
*/
ret = 0;
}
-
+out:
return ret;
}
@@ -2979,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;
@@ -3002,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;
@@ -3015,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);
@@ -3057,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);
@@ -3082,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);
@@ -3096,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
@@ -3105,7 +3600,7 @@ nfs3err:
*/
ret = 0;
}
-
+out:
return ret;
}
@@ -3121,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;
@@ -3145,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);
@@ -3163,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;
@@ -3171,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);
@@ -3207,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);
@@ -3235,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);
@@ -3243,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);
@@ -3276,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;
@@ -3297,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
@@ -3306,7 +3809,7 @@ nfs3err:
*/
ret = 0;
}
-
+out:
return ret;
}
@@ -3324,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;
@@ -3347,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);
@@ -3362,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);
@@ -3404,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);
}
@@ -3435,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);
}
@@ -3465,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;
@@ -3483,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);
@@ -3492,7 +4000,7 @@ nfs3err:
*/
ret = 0;
}
-
+out:
return ret;
}
@@ -3508,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;
@@ -3531,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);
@@ -3544,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);
@@ -3564,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;
@@ -3572,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;
}
@@ -3588,27 +4102,25 @@ nfs3svc_readdir_fstat_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
nfs3err:
if (cs->maxcount == 0) {
nfs3_log_readdir_res (rpcsvc_request_xid (cs->req), stat,
- op_errno, (uint64_t)cs->fd,
+ op_errno, (uintptr_t)cs->fd,
cs->dircount, is_eof);
- nfs3_readdir_reply (cs->req, stat, (uint64_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, (uint64_t)cs->fd,
+ op_errno, (uintptr_t)cs->fd,
cs->dircount, cs->maxcount, is_eof);
nfs3_readdirp_reply (cs->req, stat, &cs->parent,
- (uint64_t)cs->fd, buf,
+ (uintptr_t)cs->fd, buf,
&cs->entries, cs->dircount,
cs->maxcount, is_eof);
}
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;
}
@@ -3616,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;
@@ -3625,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;
}
@@ -3645,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);
}
@@ -3659,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;
@@ -3707,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);
}
@@ -3722,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);
@@ -3742,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);
}
@@ -3773,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;
@@ -3792,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);
}
@@ -3807,7 +4367,7 @@ nfs3err:
ret = 0;
nfs3_call_state_wipe (cs);
}
-
+out:
return ret;
}
@@ -3819,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;
@@ -3849,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;
@@ -3878,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);
@@ -3890,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);
@@ -3911,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;
@@ -3920,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;
}
@@ -3937,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);
@@ -3969,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);
}
@@ -3998,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);
@@ -4006,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
@@ -4015,7 +4588,7 @@ nfs3err:
*/
ret = 0;
}
-
+out:
return ret;
}
@@ -4030,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;
@@ -4053,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);
@@ -4067,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);
@@ -4112,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);
@@ -4140,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);
@@ -4148,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;
}
@@ -4170,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;
@@ -4192,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;
@@ -4204,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.
*/
@@ -4221,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);
@@ -4250,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);
}
@@ -4277,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);
@@ -4285,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
@@ -4294,7 +4877,7 @@ nfs3err:
*/
ret = 0;
}
-
+out:
return ret;
}
@@ -4309,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;
@@ -4331,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);
@@ -4344,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;
@@ -4379,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;
}
@@ -4410,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);
@@ -4442,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;
@@ -4459,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;
}
@@ -4481,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;
@@ -4500,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}
};
@@ -4530,32 +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;
+ 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");
@@ -4563,19 +5186,22 @@ nfs3_init_options (struct nfs3_state *nfs3, xlator_t *nfsx)
goto err;
}
- ret = gf_string2bytesize (optstr, &nfs3->readsize);
+ ret = gf_string2bytesize (optstr, &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");
@@ -4583,19 +5209,22 @@ nfs3_init_options (struct nfs3_state *nfs3, xlator_t *nfsx)
goto err;
}
- ret = gf_string2bytesize (optstr, &nfs3->writesize);
+ ret = gf_string2bytesize (optstr, &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");
@@ -4603,15 +5232,17 @@ nfs3_init_options (struct nfs3_state *nfs3, xlator_t *nfsx)
goto err;
}
- ret = gf_string2bytesize (optstr, &nfs3->readdirsize);
+ ret = gf_string2bytesize (optstr, &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.
*/
@@ -4622,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 */
@@ -4633,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);
@@ -4683,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;
@@ -4762,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;
@@ -4792,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");
@@ -4804,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:
@@ -4812,7 +5565,7 @@ free_localpool:
ret:
if (ret == -1) {
- FREE (nfs3);
+ GF_FREE (nfs3);
nfs3 = NULL;
}
@@ -4839,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;
+}