glusterfs  8.2
About: GlusterFS is a network/cluster filesystem. The storage server (or each in a cluster) runs glusterfsd and the clients use mount command or glusterfs client to mount the exported filesystem. Release series 8.x (latest version).
  Fossies Dox: glusterfs-8.2.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

nfs3.c
Go to the documentation of this file.
1 /*
2  Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.com>
3  This file is part of GlusterFS.
4 
5  This file is licensed to you under your choice of the GNU Lesser
6  General Public License, version 3 or any later version (LGPLv3 or
7  later), or the GNU General Public License, version 2 (GPLv2), in all
8  cases as published by the Free Software Foundation.
9 */
10 
11 #include "rpcsvc.h"
12 #include <glusterfs/dict.h>
13 #include <glusterfs/xlator.h>
14 #include "mount3.h"
15 #include "xdr-nfs3.h"
16 #include "msg-nfs3.h"
17 #include <glusterfs/iobuf.h>
18 #include "nfs3.h"
19 #include <glusterfs/mem-pool.h>
20 #include <glusterfs/logging.h>
21 #include "nfs-common.h"
22 #include "nfs-fops.h"
23 #include "nfs-inodes.h"
24 #include "nfs-generics.h"
25 #include "nfs3-helpers.h"
26 #include "nfs-mem-types.h"
27 #include "nfs.h"
28 #include "xdr-rpc.h"
29 #include "xdr-generic.h"
30 #include "nfs-messages.h"
31 #include "glfs-internal.h"
32 
33 #include <sys/socket.h>
34 #include <sys/uio.h>
35 #include <sys/statvfs.h>
36 #include <time.h>
37 
38 #define nfs3_validate_strlen_or_goto(str, len, label, status, retval) \
39  do { \
40  if ((str)) { \
41  if (strlen((str)) > (len)) { \
42  gf_msg(GF_NFS3, GF_LOG_ERROR, ENAMETOOLONG, \
43  NFS_MSG_STR_TOO_LONG, "strlen too long"); \
44  status = NFS3ERR_NAMETOOLONG; \
45  retval = -ENAMETOOLONG; \
46  goto label; \
47  } \
48  } \
49  } while (0);
50 
51 #define nfs3_validate_nfs3_state(request, state, status, label, retval) \
52  do { \
53  state = rpcsvc_request_program_private(request); \
54  if (!state) { \
55  gf_msg(GF_NFS3, GF_LOG_ERROR, EFAULT, NFS_MSG_STATE_MISSING, \
56  "NFSv3 state " \
57  "missing from RPC request"); \
58  status = NFS3ERR_SERVERFAULT; \
59  ret = -EFAULT; \
60  goto label; \
61  } \
62  } while (0);
63 
64 struct nfs3_export *
65 __nfs3_get_export_by_index(struct nfs3_state *nfs3, uuid_t exportid)
66 {
67  struct nfs3_export *exp = NULL;
68  int index = 0;
69  int searchindex = 0;
70 
71  searchindex = nfs3_fh_exportid_to_index(exportid);
72  list_for_each_entry(exp, &nfs3->exports, explist)
73  {
74  if (searchindex == index)
75  goto found;
76 
77  ++index;
78  }
79 
80  exp = NULL;
82  "searchindex=%d not found", searchindex);
83 found:
84  return exp;
85 }
86 
87 struct nfs3_export *
88 __nfs3_get_export_by_volumeid(struct nfs3_state *nfs3, uuid_t exportid)
89 {
90  struct nfs3_export *exp = NULL;
91 
92  list_for_each_entry(exp, &nfs3->exports, explist)
93  {
94  if (!gf_uuid_compare(exportid, exp->volumeid))
95  goto found;
96  }
97 
98  exp = NULL;
99 found:
100  return exp;
101 }
102 
103 struct nfs3_export *
104 __nfs3_get_export_by_exportid(struct nfs3_state *nfs3, uuid_t exportid)
105 {
106  struct nfs3_export *exp = NULL;
107 
108  if (!nfs3)
109  return exp;
110 
111  if (gf_nfs_dvm_off(nfs_state(nfs3->nfsx)))
112  exp = __nfs3_get_export_by_index(nfs3, exportid);
113  else
114  exp = __nfs3_get_export_by_volumeid(nfs3, exportid);
115 
116  return exp;
117 }
118 
119 int
120 nfs3_export_access(struct nfs3_state *nfs3, uuid_t exportid)
121 {
122  int ret = GF_NFS3_VOLACCESS_RO;
123  struct nfs3_export *exp = NULL;
124 
126 
127  exp = __nfs3_get_export_by_exportid(nfs3, exportid);
128 
129  if (!exp) {
131  "Failed to get export by ID");
132  goto err;
133  }
134 
135  ret = exp->access;
136 
137 err:
138  return ret;
139 }
140 
141 #define nfs3_check_rw_volaccess(nfs3state, exid, status, label) \
142  do { \
143  if (nfs3_export_access(nfs3state, exid) != GF_NFS3_VOLACCESS_RW) { \
144  gf_msg(GF_NFS3, GF_LOG_ERROR, EACCES, NFS_MSG_NO_RW_ACCESS, \
145  "No read-write access"); \
146  status = NFS3ERR_ROFS; \
147  goto label; \
148  } \
149  } while (0)
150 
151 xlator_t *
152 nfs3_fh_to_xlator(struct nfs3_state *nfs3, struct nfs3_fh *fh)
153 {
154  xlator_t *vol = NULL;
155  struct nfs3_export *exp = NULL;
156 
159 
160  exp = __nfs3_get_export_by_exportid(nfs3, fh->exportid);
161  if (!exp)
162  goto out;
163 
164  vol = exp->subvol;
165 out:
166  return vol;
167 }
168 
169 int
170 nfs3_is_root_looked_up(struct nfs3_state *nfs3, struct nfs3_fh *rootfh)
171 {
172  struct nfs3_export *exp = NULL;
173  int ret = 0;
174 
176  GF_VALIDATE_OR_GOTO(GF_NFS3, rootfh, out);
177 
178  exp = __nfs3_get_export_by_exportid(nfs3, rootfh->exportid);
179  if (!exp)
180  goto out;
181 
182  ret = exp->rootlookedup;
183 out:
184  return ret;
185 }
186 
187 int
188 nfs3_set_root_looked_up(struct nfs3_state *nfs3, struct nfs3_fh *rootfh)
189 {
190  struct nfs3_export *exp = NULL;
191  int ret = 0;
192 
194  GF_VALIDATE_OR_GOTO(GF_NFS3, rootfh, out);
195 
196  exp = __nfs3_get_export_by_exportid(nfs3, rootfh->exportid);
197  if (!exp)
198  goto out;
199 
200  exp->rootlookedup = 1;
201 out:
202  return ret;
203 }
204 
205 #define nfs3_map_fh_to_volume(nfs3state, handle, req, volume, status, label) \
206  do { \
207  char exportid[256], gfid[256]; \
208  rpc_transport_t *trans = NULL; \
209  volume = nfs3_fh_to_xlator((nfs3state), handle); \
210  if (!volume) { \
211  gf_uuid_unparse(handle->exportid, exportid); \
212  gf_uuid_unparse(handle->gfid, gfid); \
213  trans = rpcsvc_request_transport(req); \
214  GF_LOG_OCCASIONALLY(nfs3state->occ_logger, GF_NFS3, GF_LOG_ERROR, \
215  "Failed to map " \
216  "FH to vol: client=%s, exportid=%s, " \
217  "gfid=%s", \
218  trans->peerinfo.identifier, exportid, gfid); \
219  GF_LOG_OCCASIONALLY(nfs3state->occ_logger, GF_NFS3, GF_LOG_ERROR, \
220  "Stale nfs " \
221  "client %s must be trying to connect to" \
222  " a deleted volume, please unmount it.", \
223  trans->peerinfo.identifier); \
224  status = NFS3ERR_STALE; \
225  goto label; \
226  } else { \
227  gf_msg_trace(GF_NFS3, 0, \
228  "FH to Volume:" \
229  "%s", \
230  volume->name); \
231  rpcsvc_request_set_private(req, volume); \
232  } \
233  } while (0);
234 
235 #define nfs3_validate_gluster_fh(handle, status, errlabel) \
236  do { \
237  if (!nfs3_fh_validate(handle)) { \
238  gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_BAD_HANDLE, \
239  "Bad Handle"); \
240  status = NFS3ERR_BADHANDLE; \
241  goto errlabel; \
242  } \
243  } while (0)
244 
245 #define nfs3_check_fh_auth_status(cst, nfstat, is_write_op, erlabl) \
246  do { \
247  int auth_ret = 0; \
248  int auth_errno = 0; \
249  xlator_t *xlatorp = NULL; \
250  char buf[256], gfid[GF_UUID_BUF_SIZE]; \
251  rpc_transport_t *trans = NULL; \
252  \
253  auth_ret = auth_errno = nfs3_fh_auth_nfsop(cst, is_write_op); \
254  if (auth_ret < 0) { \
255  trans = rpcsvc_request_transport(cst->req); \
256  xlatorp = nfs3_fh_to_xlator(cst->nfs3state, &cst->resolvefh); \
257  gf_uuid_unparse(cst->resolvefh.gfid, gfid); \
258  sprintf(buf, "(%s) %s : %s", trans->peerinfo.identifier, \
259  xlatorp ? xlatorp->name : "ERR", gfid); \
260  gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_RESOLVE_FH_FAIL, \
261  "Unable to " \
262  "resolve FH: %s", \
263  buf); \
264  nfstat = nfs3_errno_to_nfsstat3(-auth_errno); \
265  goto erlabl; \
266  } \
267  } while (0)
268 
269 #define nfs3_check_fh_resolve_status(cst, nfstat, erlabl) \
270  do { \
271  xlator_t *xlatorp = NULL; \
272  char buf[256], gfid[GF_UUID_BUF_SIZE]; \
273  rpc_transport_t *trans = NULL; \
274  if ((cst)->resolve_ret < 0) { \
275  trans = rpcsvc_request_transport(cst->req); \
276  xlatorp = nfs3_fh_to_xlator(cst->nfs3state, &cst->resolvefh); \
277  gf_uuid_unparse(cst->resolvefh.gfid, gfid); \
278  snprintf(buf, sizeof(buf), "(%s) %s : %s", \
279  trans->peerinfo.identifier, \
280  xlatorp ? xlatorp->name : "ERR", gfid); \
281  gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_RESOLVE_STAT, "%s: %s", \
282  strerror(cst->resolve_errno), buf); \
283  nfstat = nfs3_errno_to_nfsstat3(cst->resolve_errno); \
284  goto erlabl; \
285  } \
286  } while (0)
287 
288 #define nfs3_check_new_fh_resolve_status(cst, nfstat, erlabl) \
289  do { \
290  xlator_t *xlatorp = NULL; \
291  char buf[256], gfid[GF_UUID_BUF_SIZE]; \
292  rpc_transport_t *trans = NULL; \
293  if (((cst)->resolve_ret < 0) && ((cst)->resolve_errno != ENOENT)) { \
294  trans = rpcsvc_request_transport(cst->req); \
295  xlatorp = nfs3_fh_to_xlator(cst->nfs3state, &cst->resolvefh); \
296  gf_uuid_unparse(cst->resolvefh.gfid, gfid); \
297  snprintf(buf, sizeof(buf), "(%s) %s : %s", \
298  trans->peerinfo.identifier, \
299  xlatorp ? xlatorp->name : "ERR", gfid); \
300  gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_RESOLVE_STAT, "%s: %s", \
301  strerror(cst->resolve_errno), buf); \
302  nfstat = nfs3_errno_to_nfsstat3(cs->resolve_errno); \
303  goto erlabl; \
304  } \
305  } while (0)
306 
307 int
309 {
310  int ret = -1;
311  struct nfs3_export *exp = NULL;
312 
315 
316  list_for_each_entry(exp, &nfs3->exports, explist)
317  {
318  if (exp->subvol == xl) {
320  ret = 0;
321  goto out;
322  }
323  }
324 
325 out:
326  return ret;
327 }
328 
329 static int
331  struct nfs3_fh *fhd, char *name)
332 {
333  xlator_t *fungexl = NULL;
334  struct nfs_state *nfs = NULL;
335  glfs_t *fs = NULL;
336  loc_t loc = {
337  0,
338  };
339  int ret = -1;
340  char *subdir = NULL;
341  char volname[NAME_MAX] = {
342  0,
343  };
344 
345  fungexl = nfs_mntpath_to_xlator(nfs3st->exportslist, name);
346  if (!fungexl) {
347  gf_msg_trace(GF_NFS3, 0, "failed to find xlator for volume");
348  ret = -ENOENT;
349  goto out;
350  }
351  /* fungexl is valid, set for nfs3_request_xlator_deviceid() */
352  rpcsvc_request_set_private(req, fungexl);
353 
354  /* Permission checks are done through mnt3_parse_dir_exports(). The
355  * "nfs.export-dir" option gets checked as well. */
356  nfs = nfs_state(nfs3st->nfsx);
357  ret = mnt3_parse_dir_exports(req, nfs->mstate, name, _gf_false);
358  if (ret) {
359  gf_msg_trace(GF_NFS3, -ret, "mounting not possible");
360  goto out;
361  }
362 
363  /* glfs_resolve_at copied from UDP MNT support */
364  fs = glfs_new_from_ctx(fungexl->ctx);
365  if (!fs) {
366  gf_msg_trace(GF_NFS3, 0, "failed to create glfs instance");
367  ret = -ENOENT;
368  goto out;
369  }
370 
371  /* split name "volname/sub/dir/s" into pieces */
372  subdir = mnt3_get_volume_subdir(name, (char **)&volname);
373 
374  ret = glfs_resolve_at(fs, fungexl, NULL, subdir, &loc, NULL, 1, 0);
375  if (ret != 0) {
376  gf_msg_trace(GF_NFS3, 0, "failed to resolve %s", subdir);
377  ret = -ENOENT;
378  goto out;
379  }
380 
381  /* resolved subdir, copy gfid for the fh */
382  gf_uuid_copy(fhd->gfid, loc.gfid);
383  loc_wipe(&loc);
384 
385  if (gf_nfs_dvm_off(nfs_state(nfs3st->nfsx)))
386  fhd->exportid[15] = nfs_xlator_to_xlid(nfs3st->exportslist, fungexl);
387  else {
388  if (__nfs3_get_volume_id(nfs3st, fungexl, fhd->exportid) < 0) {
389  ret = -ESTALE;
390  goto out;
391  }
392  }
393 
394  ret = 0;
395 out:
396  if (fs)
397  glfs_free_from_ctx(fs);
398 
399  return ret;
400 }
401 
402 /*
403  * This macro checks if the volume is started or not.
404  * If it is not started, it closes the client connection & logs it.
405  *
406  * Why do we do this?
407  *
408  * There is a "race condition" where gNFSd may start listening for RPC requests
409  * prior to the volume being started. Presumably, that is why this macro exists
410  * in the first place. In the NFS kernel client (specifically Linux's NFS
411  * kernel client), they establish a TCP connection to our endpoint and
412  * (re-)send requests. If we ignore the request, and return nothing back,
413  * the NFS kernel client waits forever for our response. If for some reason,
414  * the TCP connection were to die, and re-establish, the requests are
415  * retransmitted and everything begins working as expected
416  *
417  * Now, this is clearly bad behavior on the client side,
418  * but in order to make every user's life easier,
419  * gNFSd should simply disconnect the TCP connection if it sees requests
420  * before it is ready to accept them.
421  *
422  */
423 
424 #define nfs3_volume_started_check(nf3stt, vlm, rtval, erlbl) \
425  do { \
426  if ((!nfs_subvolume_started(nfs_state(nf3stt->nfsx), vlm))) { \
427  gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_VOL_DISABLE, \
428  "Volume is disabled: %s", vlm->name); \
429  nfs3_disconnect_transport(req->trans); \
430  rtval = RPCSVC_ACTOR_IGNORE; \
431  goto erlbl; \
432  } \
433  } while (0)
434 
435 void
437 {
438  int ret = 0;
439 
440  GF_VALIDATE_OR_GOTO(GF_NFS3, transport, out);
441 
442  ret = rpc_transport_disconnect(transport, _gf_false);
443  if (ret != 0) {
445  "Unable to close client connection to %s.",
446  transport->peerinfo.identifier);
447  } else {
448  gf_log(GF_NFS3, GF_LOG_WARNING, "Closed client connection to %s.",
449  transport->peerinfo.identifier);
450  }
451 out:
452  return;
453 }
454 
455 int
456 nfs3_export_sync_trusted(struct nfs3_state *nfs3, uuid_t exportid)
457 {
458  struct nfs3_export *exp = NULL;
459  int ret = 0;
460 
462 
463  exp = __nfs3_get_export_by_exportid(nfs3, exportid);
464  if (!exp)
465  goto err;
466 
467  ret = exp->trusted_sync;
468 err:
469  return ret;
470 }
471 
472 int
473 nfs3_export_write_trusted(struct nfs3_state *nfs3, uuid_t exportid)
474 {
475  struct nfs3_export *exp = NULL;
476  int ret = 0;
477 
479 
480  exp = __nfs3_get_export_by_exportid(nfs3, exportid);
481  if (!exp)
482  goto err;
483 
484  ret = exp->trusted_write;
485 err:
486  return ret;
487 }
488 
489 int
490 nfs3_solaris_zerolen_fh(struct nfs3_fh *fh, int fhlen)
491 {
492  if (!fh)
493  return 0;
494 
495  if (nfs3_fh_validate(fh))
496  return 0;
497 
498  if (fhlen == 0) {
499  gf_msg_trace(GF_NFS3, 0, "received WebNFS request");
500  return 1;
501  }
502 
503  return 0;
504 }
505 
506 /* Function pointer that represents the generic prototypes of functions used
507  * to serialize NFS3 message structures into the XDR format.
508  * For usage, see the nfs3svc_XXX_cbk functions.
509  */
510 typedef ssize_t (*nfs3_serializer)(struct iovec outmsg, void *args);
511 
512 static void
514 {
515  if (cs->fd) {
516  gf_msg_trace(GF_NFS3, 0, "fd 0x%lx ref: %" PRId64, (long)cs->fd,
517  GF_ATOMIC_GET(cs->fd->refcount));
518  fd_unref(cs->fd);
519  }
520 
521  GF_FREE(cs->resolventry);
522 
523  GF_FREE(cs->pathname);
524 
525  if (!list_empty(&cs->entries.list))
526  gf_dirent_free(&cs->entries);
527 
528  nfs_loc_wipe(&cs->oploc);
530  if (cs->iob)
531  iobuf_unref(cs->iob);
532  if (cs->iobref)
533  iobref_unref(cs->iobref);
534  if (cs->trans)
536  memset(cs, 0, sizeof(*cs));
537  mem_put(cs);
538  /* Already refd by fd_lookup, so no need to ref again. */
539 }
540 
543 {
544  nfs3_call_state_t *cs = NULL;
545 
548  /* GF_VALIDATE_OR_GOTO (GF_NFS3, v, err); NLM sets this later */
549 
550  cs = (nfs3_call_state_t *)mem_get(s->localpool);
551  if (!cs) {
553  "out of memory");
554  return NULL;
555  }
556 
557  memset(cs, 0, sizeof(*cs));
561  cs->operrno = EINVAL;
562  cs->req = req;
563  cs->vol = v;
564  cs->nfsx = s->nfsx;
565  cs->nfs3state = s;
566 err:
567  return cs;
568 }
569 
570 void
572 {
573  if (!cs) {
574  gf_log_callingfn("nfs", GF_LOG_WARNING, "nfs calling state NULL");
575  return;
576  }
577  GF_REF_PUT(cs);
578 }
579 
580 #define nfs3_handle_call_state_init(nfs3state, calls, rq, vl, opstat, \
581  errlabel) \
582  do { \
583  calls = nfs3_call_state_init((nfs3state), (rq), (vl)); \
584  if (!calls) { \
585  gf_msg(GF_NFS3, GF_LOG_ERROR, 0, NFS_MSG_INIT_CALL_STAT_FAIL, \
586  "Failed to" \
587  " init call state"); \
588  opstat = NFS3ERR_SERVERFAULT; \
589  goto errlabel; \
590  } \
591  } while (0)
592 
593 struct iobuf *
595  struct iovec *outmsg)
596 {
597  struct nfs3_state *nfs3 = NULL;
598  struct iobuf *iob = NULL;
599  ssize_t retlen = -1;
600 
601  nfs3 = (struct nfs3_state *)rpcsvc_request_program_private(req);
602  if (!nfs3) {
604  "NFSv3 state not found in RPC request");
605  goto ret;
606  }
607 
608  /* First, get the io buffer into which the reply in arg will
609  * be serialized.
610  */
611  /* TODO: get rid of 'sfunc' and use 'xdrproc_t' so we
612  can have 'xdr_sizeof' */
613  iob = iobuf_get(nfs3->iobpool);
614  if (!iob) {
616  "Failed to get iobuf");
617  goto ret;
618  }
619 
620  iobuf_to_iovec(iob, outmsg);
621  /* Use the given serializer to translate the give C structure in arg
622  * to XDR format which will be written into the buffer in outmsg.
623  */
624  /* retlen is used to received the error since size_t is unsigned and we
625  * need -1 for error notification during encoding.
626  */
627  retlen = sfunc(*outmsg, arg);
628  if (retlen == -1) {
630  "Failed to encode message");
631  goto ret;
632  }
633 
634  outmsg->iov_len = retlen;
635 ret:
636  if (retlen == -1) {
637  iobuf_unref(iob);
638  iob = NULL;
639  }
640 
641  return iob;
642 }
643 
644 /* Generic reply function for NFSv3 specific replies. */
645 int
647 {
648  struct iovec outmsg = {
649  0,
650  };
651  struct iobuf *iob = NULL;
652  int ret = -1;
653  struct iobref *iobref = NULL;
654 
655  if (!req)
656  return -1;
657 
658  iob = nfs3_serialize_reply(req, arg, sfunc, &outmsg);
659  if (!iob) {
661  "Failed to serialize reply");
662  goto ret;
663  }
664 
665  iobref = iobref_new();
666  if (!iobref) {
668  "failed on iobref_new()");
669  goto ret;
670  }
671 
672  ret = iobref_add(iobref, iob);
673  if (ret) {
675  "Failed to add iob to iobref");
676  goto ret;
677  }
678 
679  /* Then, submit the message for transmission. */
680  ret = rpcsvc_submit_message(req, &outmsg, 1, NULL, 0, iobref);
681  if (ret == -1) {
683  "Reply submission failed");
684  goto ret;
685  }
686 
687  ret = 0;
688 ret:
689  /* Now that we've done our job of handing the message to the RPC layer
690  * we can safely unref the iob in the hope that RPC layer must have
691  * ref'ed the iob on receiving into the txlist.
692  */
693  if (NULL != iob)
694  iobuf_unref(iob);
695  if (NULL != iobref)
697  return ret;
698 }
699 
700 int
702  nfs3_serializer sfunc, struct iovec *payload,
703  int vcount, struct iobref *iobref)
704 {
705  struct iovec outmsg = {
706  0,
707  };
708  struct iobuf *iob = NULL;
709  int ret = -1;
710  int new_iobref = 0;
711 
712  if (!req)
713  return -1;
714 
715  iob = nfs3_serialize_reply(req, arg, sfunc, &outmsg);
716  if (!iob) {
718  "Failed to serialize reply");
719  goto ret;
720  }
721  if (iobref == NULL) {
722  iobref = iobref_new();
723  if (!iobref) {
725  "failed on iobref_new");
726  goto ret;
727  }
728  new_iobref = 1;
729  }
730 
731  ret = iobref_add(iobref, iob);
732  if (ret) {
734  "Failed to add iob to iobref");
735  goto ret;
736  }
737 
738  /* Then, submit the message for transmission. */
739  ret = rpcsvc_submit_message(req, &outmsg, 1, payload, vcount, iobref);
740  if (ret == -1) {
742  "Reply submission failed");
743  goto ret;
744  }
745 
746  ret = 0;
747 ret:
748  /* Now that we've done our job of handing the message to the RPC layer
749  * we can safely unref the iob in the hope that RPC layer must have
750  * ref'ed the iob on receiving into the txlist.
751  */
752  if (NULL != iob)
753  iobuf_unref(iob);
754  if (new_iobref)
756  return ret;
757 }
758 
759 uint64_t
761 {
762  struct nfs3_state *nfs3 = NULL;
763  xlator_t *xl = NULL;
764  uint64_t devid = 0;
765  uuid_t volumeid = {
766  0,
767  };
768 
769  if (!rq)
770  return 0;
771 
772  xl = rpcsvc_request_private(rq);
774  if (nfs3 && (gf_nfs_dvm_off(nfs_state(nfs3->nfsx))))
775  devid = (uint64_t)nfs_xlator_to_xlid(nfs3->exportslist, xl);
776  else {
777  __nfs3_get_volume_id(nfs3, xl, volumeid);
778  memcpy(&devid, &volumeid[8], sizeof(devid));
779  }
780 
781  return devid;
782 }
783 
784 int
786 {
787  struct iovec dummyvec = {
788  0,
789  };
790  if (!req)
791  return RPCSVC_ACTOR_ERROR;
792  rpcsvc_submit_generic(req, &dummyvec, 1, NULL, 0, NULL);
793  return RPCSVC_ACTOR_SUCCESS;
794 }
795 
796 int
798 {
799  getattr3res res;
800  uint64_t deviceid = 0;
801 
802  deviceid = nfs3_request_xlator_deviceid(req);
803  nfs3_fill_getattr3res(&res, status, buf, deviceid);
805 
806  return 0;
807 }
808 
809 int32_t
811  int32_t op_ret, int32_t op_errno, inode_t *inode,
812  struct iatt *buf, dict_t *xattr,
813  struct iatt *postparent)
814 {
815  nfsstat3 status = NFS3_OK;
816  nfs3_call_state_t *cs = NULL;
817 
818  cs = frame->local;
819 
820  /*
821  * Somewhat counter-intuitively, we don't need to look for sh-failed
822  * here. Failing this getattr will generate a new lookup from the
823  * client, and nfs_fop_lookup_cbk will detect any self-heal failures.
824  */
825 
826  if (op_ret == -1) {
827  status = nfs3_cbk_errno_status(op_ret, op_errno);
828  } else {
829  nfs_fix_generation(this, inode);
830  }
831 
833  op_errno, cs->resolvedloc.path);
834 
835  nfs3_getattr_reply(cs->req, status, buf);
837 
838  return 0;
839 }
840 
841 int32_t
842 nfs3svc_getattr_stat_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
843  int32_t op_ret, int32_t op_errno, struct iatt *buf,
844  dict_t *xdata)
845 {
846  nfsstat3 status = NFS3_OK;
847  nfs3_call_state_t *cs = NULL;
848 
849  cs = frame->local;
850 
851  if (op_ret == -1) {
852  /* Prevent crashes for the case where this call fails
853  * and buf is left in a NULL state, yet the op_errno == 0.
854  */
855  if (!buf && op_errno == 0) {
856  op_errno = EIO;
857  }
858  status = nfs3_cbk_errno_status(op_ret, op_errno);
859  }
860 
862  op_errno, cs->resolvedloc.path);
863 
864  nfs3_getattr_reply(cs->req, status, buf);
866 
867  return 0;
868 }
869 
870 int
872 {
874  int ret = -EFAULT;
875  nfs_user_t nfu = {
876  0,
877  };
878  nfs3_call_state_t *cs = NULL;
879  uint64_t raw_ctx = 0;
880  struct nfs_inode_ctx *ictx = NULL;
881  struct nfs_state *priv = NULL;
882 
883  if (!carg)
884  return ret;
885 
886  cs = (nfs3_call_state_t *)carg;
887  nfs3_check_fh_auth_status(cs, stat, _gf_false, nfs3err);
888  nfs3_check_fh_resolve_status(cs, stat, nfs3err);
889  nfs_request_user_init(&nfu, cs->req);
890  /* If inode which is to be getattr'd is the root, we need to do a
891  * lookup instead because after a server reboot, it is not necessary
892  * for the root to have been looked up when the getattr on the root is
893  * sent. AND, this causes a problem for stat-prefetch in that it
894  * expects even the root inode to have been looked up.
895 
896  if (__is_root_gfid (cs->resolvedloc.inode->gfid))
897  ret = nfs_lookup (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
898  nfs3svc_getattr_lookup_cbk, cs);
899  else
900  ret = nfs_stat (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
901  */
902 
903  if (cs->hardresolved) {
904  ret = -EFAULT;
905  stat = NFS3_OK;
906  goto nfs3err;
907  }
908 
909  /*
910  * If brick state changed, we need to force a proper lookup cycle (as
911  * would happen in native protocol) to do self-heal checks. We detect
912  * this by comparing the generation number for the last successful
913  * creation/lookup on the inode to the current number, so inodes that
914  * haven't been validated since the state change are affected.
915  */
916  if (inode_ctx_get(cs->resolvedloc.inode, cs->nfsx, &raw_ctx) == 0) {
917  ictx = (struct nfs_inode_ctx *)(uintptr_t)raw_ctx;
918  priv = cs->nfsx->private;
919  if (ictx->generation != priv->generation) {
920  ret = nfs_lookup(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
922  goto check_err;
923  }
924  }
925 
926  ret = nfs_stat(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
928 
929 check_err:
930  if (ret < 0) {
932  "Stat fop failed: %s: %s", cs->oploc.path, strerror(-ret));
933  stat = nfs3_errno_to_nfsstat3(-ret);
934  }
935 
936 nfs3err:
937  if (ret < 0) {
939  -ret, cs->resolvedloc.path);
940  nfs3_getattr_reply(cs->req, stat, &cs->stbuf);
942  ret = 0;
943  }
944 
945  return ret;
946 }
947 
948 int
950 {
951  xlator_t *vol = NULL;
953  int ret = -EFAULT;
954  struct nfs3_state *nfs3 = NULL;
955  nfs3_call_state_t *cstate = NULL;
956 
959 
960  nfs3_log_common_call(rpcsvc_request_xid(req), "GETATTR", fh);
961  nfs3_validate_gluster_fh(fh, stat, nfs3err);
962  nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
963  nfs3_map_fh_to_volume(nfs3, fh, req, vol, stat, nfs3err);
964  nfs3_volume_started_check(nfs3, vol, ret, out);
965  nfs3_handle_call_state_init(nfs3, cstate, req, vol, stat, nfs3err);
966 
967  ret = nfs3_fh_resolve_and_resume(cstate, fh, NULL, nfs3_getattr_resume);
968  if (ret < 0)
969  stat = nfs3_errno_to_nfsstat3(-ret);
970 
971 nfs3err:
972  if (ret < 0) {
974  NULL);
975  nfs3_getattr_reply(req, stat, NULL);
976  ret = 0;
977  nfs3_call_state_wipe(cstate);
978  }
979 out:
980  return ret;
981 }
982 
983 int
985 {
986  struct nfs3_fh fh = {
987  {0},
988  };
990  int ret = RPCSVC_ACTOR_ERROR;
991 
992  if (!req)
993  return ret;
994 
996  if (xdr_to_getattr3args(req->msg[0], &args) <= 0) {
998  "Error decoding args");
999  rpcsvc_request_seterr(req, GARBAGE_ARGS);
1000  goto rpcerr;
1001  }
1002 
1003  ret = nfs3_getattr(req, &fh);
1004  if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
1006  "GETATTR procedure failed");
1007  rpcsvc_request_seterr(req, SYSTEM_ERR);
1008  ret = RPCSVC_ACTOR_ERROR;
1009  }
1010 
1011 rpcerr:
1012  return ret;
1013 }
1014 
1015 int
1017  struct iatt *postop)
1018 {
1019  setattr3res res = {
1020  0,
1021  };
1022  uint64_t deviceid = 0;
1023 
1024  deviceid = nfs3_request_xlator_deviceid(req);
1025  nfs3_fill_setattr3res(&res, stat, preop, postop, deviceid);
1026  nfs3svc_submit_reply(req, (void *)&res,
1028  return 0;
1029 }
1030 
1031 int32_t
1032 nfs3svc_truncate_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
1033  int32_t op_ret, int32_t op_errno, struct iatt *prebuf,
1034  struct iatt *postbuf, dict_t *xdata)
1035 {
1037  struct iatt *prestat = NULL;
1038  nfs3_call_state_t *cs = NULL;
1039 
1040  cs = frame->local;
1041  if (op_ret == -1) {
1042  stat = nfs3_cbk_errno_status(op_ret, op_errno);
1043  goto nfs3err;
1044  }
1045 
1046  /* If the first stat was got from the guarded setattr callback, or
1047  * from an earlier setattr call then we'll need to use that stat
1048  * instead of the preop returned here.
1049  */
1050  if (cs->preparent.ia_ino != 0)
1051  prestat = &cs->preparent;
1052  else
1053  prestat = prebuf;
1054 
1055  stat = NFS3_OK;
1056 nfs3err:
1058  op_errno, cs->resolvedloc.path);
1059  nfs3_setattr_reply(cs->req, stat, prestat, postbuf);
1061 
1062  return 0;
1063 }
1064 
1065 int32_t
1066 nfs3svc_setattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
1067  int32_t op_ret, int32_t op_errno, struct iatt *preop,
1068  struct iatt *postop, dict_t *xdata)
1069 {
1071  int ret = -1;
1072  struct iatt *prebuf = NULL;
1073  nfs_user_t nfu = {
1074  0,
1075  };
1076  nfs3_call_state_t *cs = NULL;
1077 
1078  cs = frame->local;
1079  if (op_ret == -1) {
1080  stat = nfs3_cbk_errno_status(op_ret, op_errno);
1081  goto nfs3err;
1082  }
1083 
1084  prebuf = preop;
1085  /* Store the current preop in case we need to send a truncate,
1086  * in which case the preop to be returned will be this one.
1087  */
1088  cs->preparent = *preop;
1089 
1090  /* Only truncate if the size is not already same as the requested
1091  * truncation and also only if this is not a directory.
1092  */
1093  if ((gf_attr_size_set(cs->setattr_valid)) && (!IA_ISDIR(postop->ia_type)) &&
1094  (preop->ia_size != cs->attr_in.ia_size)) {
1095  nfs_request_user_init(&nfu, cs->req);
1096  ret = nfs_truncate(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
1098 
1099  if (ret < 0)
1100  stat = nfs3_errno_to_nfsstat3(-ret);
1101  } else {
1102  ret = -1; /* Force a reply in the branch below. */
1103  stat = NFS3_OK;
1104  }
1105 
1106 nfs3err:
1107  if (ret < 0) {
1109  op_errno, cs->resolvedloc.path);
1110  nfs3_setattr_reply(cs->req, stat, prebuf, postop);
1112  }
1113 
1114  return 0;
1115 }
1116 
1117 int32_t
1118 nfs3svc_setattr_stat_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
1119  int32_t op_ret, int32_t op_errno, struct iatt *buf,
1120  dict_t *xdata)
1121 {
1122  int ret = -EFAULT;
1124  nfs_user_t nfu = {
1125  0,
1126  };
1127  nfs3_call_state_t *cs = NULL;
1128 
1129  cs = frame->local;
1130  if (op_ret == -1) {
1131  stat = nfs3_cbk_errno_status(op_ret, op_errno);
1132  goto nfs3err;
1133  }
1134 
1135  if (buf->ia_ctime != cs->timestamp.seconds) {
1137  "Timestamps not in sync");
1138  stat = NFS3ERR_NOT_SYNC;
1139  goto nfs3err;
1140  }
1141 
1142  /* Not a clean way but no motivation to add a new member to local. */
1143  cs->preparent = *buf;
1144  nfs_request_user_init(&nfu, cs->req);
1145  ret = nfs_setattr(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, &cs->stbuf,
1147  if (ret < 0)
1148  stat = nfs3_errno_to_nfsstat3(-ret);
1149 
1150 nfs3err:
1151  if (ret < 0) {
1153  op_errno, cs->resolvedloc.path);
1154  nfs3_setattr_reply(cs->req, stat, NULL, NULL);
1156  }
1157 
1158  return 0;
1159 }
1160 
1161 int
1163 {
1165  int ret = -EFAULT;
1166  nfs_user_t nfu = {
1167  0,
1168  };
1169  nfs3_call_state_t *cs = NULL;
1170 
1171  if (!carg)
1172  return ret;
1173 
1174  cs = (nfs3_call_state_t *)carg;
1175  nfs3_check_fh_resolve_status(cs, stat, nfs3err);
1176  nfs_request_user_init(&nfu, cs->req);
1177  ret = nfs_setattr(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, &cs->attr_in,
1179 
1180  if (ret < 0)
1181  stat = nfs3_errno_to_nfsstat3(-ret);
1182 
1183 nfs3err:
1184  if (ret < 0) {
1186  -ret, cs->resolvedloc.path);
1187  nfs3_setattr_reply(cs->req, stat, NULL, NULL);
1189  }
1190 
1191  return ret;
1192 }
1193 
1194 int
1195 nfs3_setattr(rpcsvc_request_t *req, struct nfs3_fh *fh, sattr3 *sattr,
1196  sattrguard3 *guard)
1197 {
1198  xlator_t *vol = NULL;
1200  int ret = -EFAULT;
1201  struct nfs3_state *nfs3 = NULL;
1202  nfs3_call_state_t *cs = NULL;
1203 
1206  GF_VALIDATE_OR_GOTO(GF_NFS3, sattr, out);
1207  GF_VALIDATE_OR_GOTO(GF_NFS3, guard, out);
1208 
1209  nfs3_log_common_call(rpcsvc_request_xid(req), "SETATTR", fh);
1210  nfs3_validate_gluster_fh(fh, stat, nfs3err);
1211  nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
1212  nfs3_map_fh_to_volume(nfs3, fh, req, vol, stat, nfs3err);
1213  nfs3_volume_started_check(nfs3, vol, ret, out);
1214  nfs3_check_rw_volaccess(nfs3, fh->exportid, stat, nfs3err);
1215  nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
1216 
1217  cs->setattr_valid = nfs3_sattr3_to_setattr_valid(sattr, &cs->attr_in, NULL);
1218  if (guard->check) {
1219  gf_msg_trace(GF_NFS3, 0, "Guard check required");
1220  cs->timestamp = guard->sattrguard3_u.obj_ctime;
1221  cs->sattrguardcheck = 1;
1222  } else {
1223  gf_msg_trace(GF_NFS3, 0, "Guard check not required");
1224  cs->sattrguardcheck = 0;
1225  }
1226 
1227  if (!cs->setattr_valid) {
1228  ret = -EINVAL; /* Force a reply */
1229  stat = NFS3_OK;
1231  "cs->setattr_valid is invalid");
1232  goto nfs3err;
1233  }
1234 
1235  ret = nfs3_fh_resolve_and_resume(cs, fh, NULL, nfs3_setattr_resume);
1236  if (ret < 0)
1237  stat = nfs3_errno_to_nfsstat3(-ret);
1238 
1239 nfs3err:
1240  if (ret < 0) {
1242  cs ? cs->resolvedloc.path : NULL);
1243  nfs3_setattr_reply(req, stat, NULL, NULL);
1245  /* Ret must be 0 after this so that the caller does not
1246  * also send an RPC reply.
1247  */
1248  ret = 0;
1249  }
1250 out:
1251  return ret;
1252 }
1253 
1254 int
1256 {
1257  struct nfs3_fh fh = {
1258  {0},
1259  };
1261  int ret = RPCSVC_ACTOR_ERROR;
1262 
1263  GF_VALIDATE_OR_GOTO(GF_NFS3, req, rpcerr);
1264 
1266  if (xdr_to_setattr3args(req->msg[0], &args) <= 0) {
1268  "Error decoding args");
1269  rpcsvc_request_seterr(req, GARBAGE_ARGS);
1270  goto rpcerr;
1271  }
1272 
1273  ret = nfs3_setattr(req, &fh, &args.new_attributes, &args.guard);
1274  if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
1276  "SETATTR procedure failed");
1277  rpcsvc_request_seterr(req, SYSTEM_ERR);
1278  ret = RPCSVC_ACTOR_ERROR;
1279  }
1280 
1281 rpcerr:
1282  return ret;
1283 }
1284 
1285 int
1287  struct iatt *stbuf, struct iatt *postparent)
1288 {
1289  lookup3res res = {
1290  0,
1291  };
1292  uint64_t deviceid = 0;
1293 
1294  deviceid = nfs3_request_xlator_deviceid(req);
1295  nfs3_fill_lookup3res(&res, stat, newfh, stbuf, postparent, deviceid);
1296  return nfs3svc_submit_reply(req, &res,
1298 }
1299 
1300 int
1301 nfs3_lookup_resume(void *carg);
1302 
1303 int
1305 {
1306  int ret = -EFAULT;
1307  char *oldresolventry = NULL;
1308 
1310  gf_msg_debug(GF_NFS3, 0, "inode needs fresh lookup");
1312  cs->resolventry);
1313  nfs_loc_wipe(&cs->resolvedloc);
1314 
1315  /* Store pointer to currently allocated resolventry because it gets over
1316  * written in fh_resolve_and_resume.
1317  */
1318  oldresolventry = cs->resolventry;
1319  cs->lookuptype = GF_NFS3_FRESH;
1320  ret = nfs3_fh_resolve_and_resume(cs, &cs->resolvefh, cs->resolventry,
1322  /* Allocated in the previous call to fh_resolve_and_resume using the
1323  * same call_state.
1324  */
1325  GF_FREE(oldresolventry);
1326 err:
1327  return ret;
1328 }
1329 
1330 int
1331 nfs3svc_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
1332  int32_t op_ret, int32_t op_errno, inode_t *inode,
1333  struct iatt *buf, dict_t *xattr, struct iatt *postparent)
1334 {
1335  struct nfs3_fh newfh = {
1336  {0},
1337  };
1338  nfsstat3 status = NFS3_OK;
1339  nfs3_call_state_t *cs = NULL;
1340  inode_t *oldinode = NULL;
1341 
1342  cs = frame->local;
1343  if (op_ret == -1) {
1344  status = nfs3_cbk_errno_status(op_ret, op_errno);
1345  goto xmit_res;
1346  }
1347 
1348  nfs3_fh_build_child_fh(&cs->parent, buf, &newfh);
1349  oldinode = inode_link(inode, cs->resolvedloc.parent, cs->resolvedloc.name,
1350  buf);
1351 xmit_res:
1352  /* Only send fresh lookup if it was a revalidate that failed. */
1353  if ((op_ret == -1) && (nfs3_is_revalidate_lookup(cs))) {
1354  op_ret = nfs3_fresh_lookup(cs);
1355  goto out;
1356  }
1357 
1359  op_errno, &newfh, cs->resolvedloc.path);
1360  nfs3_lookup_reply(cs->req, status, &newfh, buf, postparent);
1362 out:
1363  if (oldinode) {
1364  inode_lookup(oldinode);
1365  inode_unref(oldinode);
1366  }
1367  return 0;
1368 }
1369 
1370 int
1372  int32_t op_ret, int32_t op_errno, inode_t *inode,
1373  struct iatt *buf, dict_t *xattr,
1374  struct iatt *postparent)
1375 {
1376  struct nfs3_fh newfh = {
1377  {0},
1378  };
1379  nfsstat3 status = NFS3_OK;
1380  nfs3_call_state_t *cs = NULL;
1381  uuid_t volumeid = {
1382  0,
1383  };
1384  uuid_t mountid = {
1385  1,
1386  };
1387  struct nfs3_state *nfs3 = NULL;
1388 
1389  cs = frame->local;
1390  if (op_ret == -1) {
1391  status = nfs3_cbk_errno_status(op_ret, op_errno);
1392  goto xmit_res;
1393  }
1394 
1395  nfs3 = cs->nfs3state;
1396  /* If the buf inode shows that this is a root dir's buf, then the file
1397  * handle needs to be specially crafted, in all other cases, we'll just
1398  * create the handle normally using the buffer of the parent dir.
1399  */
1400  if (buf->ia_ino != 1) {
1401  nfs3_fh_build_parent_fh(&cs->fh, buf, &newfh);
1402  goto xmit_res;
1403  }
1404 
1405  if (gf_nfs_dvm_off(nfs_state(nfs3->nfsx)))
1406  newfh = nfs3_fh_build_indexed_root_fh(nfs3->exportslist, cs->vol);
1407  else {
1408  __nfs3_get_volume_id(nfs3, cs->vol, volumeid);
1409  newfh = nfs3_fh_build_uuid_root_fh(volumeid, mountid);
1410  }
1411 
1412 xmit_res:
1414  op_errno, &newfh, cs->resolvedloc.path);
1415  nfs3_lookup_reply(cs->req, status, &newfh, buf, postparent);
1417 
1418  return 0;
1419 }
1420 
1421 int
1423 {
1425  int ret = -EFAULT;
1426  nfs_user_t nfu = {
1427  0,
1428  };
1429  nfs3_call_state_t *cs = NULL;
1430  inode_t *parent = NULL;
1431 
1432  if (!carg) {
1434  "Invalid argument, carg value NULL");
1435  return EINVAL;
1436  }
1437 
1438  cs = (nfs3_call_state_t *)carg;
1439  nfs3_check_fh_auth_status(cs, stat, _gf_false, nfs3err);
1440  nfs3_check_fh_resolve_status(cs, stat, nfs3err);
1441 
1442  /* At this point now, the loc in cs is for the directory file handle
1443  * sent by the client. This loc needs to be transformed into a loc that
1444  * represents the parent dir of cs->resolvedloc.inode.
1445  *
1446  * EXCEPT in the case where the .. is a parent of the root directory.
1447  * In this case we'll be returning the file handle and attributes of the
1448  * root itself.
1449  */
1450  nfs_request_user_init(&nfu, cs->req);
1451 
1452  /* Save the file handle from the LOOKUP request. We'll use this to
1453  * build the file handle of the parent directory in case the parent is
1454  * not root dir.
1455  */
1456  cs->fh = cs->resolvefh;
1457 
1458  /* If fh is that of the root, the resolvedloc will already contain
1459  * the loc for root. After that, we'll send lookup for the root dir
1460  * itself since we cannot send the lookup on the parent of root.
1461  *
1462  * For all other cases, we'll send the lookup on the parent of the
1463  * given directory file handle.
1464  */
1465  if (!nfs3_fh_is_root_fh(&cs->fh)) {
1466  parent = inode_ref(cs->resolvedloc.parent);
1467  nfs_loc_wipe(&cs->resolvedloc);
1468  ret = nfs_inode_loc_fill(parent, &cs->resolvedloc, NFS_RESOLVE_CREATE);
1469 
1470  if (ret < 0) {
1472  "nfs_inode_loc_fill"
1473  " error");
1474  goto errtostat;
1475  }
1476  }
1477 
1478  ret = nfs_lookup(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
1480 errtostat:
1481  if (ret < 0)
1482  stat = nfs3_errno_to_nfsstat3(-ret);
1483 
1484 nfs3err:
1485  if (ret < 0) {
1487  -ret, cs->resolvedloc.path);
1488  nfs3_lookup_reply(cs->req, stat, NULL, NULL, NULL);
1490  }
1491 
1492  if (parent)
1493  inode_unref(parent);
1494 
1495  return ret;
1496 }
1497 
1498 int
1500 {
1502  int ret = -EFAULT;
1503  nfs_user_t nfu = {
1504  0,
1505  };
1506  nfs3_call_state_t *cs = NULL;
1507  struct nfs3_fh newfh = {
1508  {0},
1509  };
1510 
1511  if (!carg) {
1513  "Invalid argument, carg value NULL");
1514  return EINVAL;
1515  }
1516 
1517  cs = (nfs3_call_state_t *)carg;
1518  nfs3_check_fh_auth_status(cs, stat, _gf_false, nfs3err);
1519  nfs3_check_fh_resolve_status(cs, stat, nfs3err);
1520  cs->parent = cs->resolvefh;
1521 
1522  if (cs->hardresolved) {
1523  stat = NFS3_OK;
1524  nfs3_fh_build_child_fh(&cs->parent, &cs->stbuf, &newfh);
1525  goto nfs3err;
1526  }
1527 
1528  nfs_request_user_init(&nfu, cs->req);
1529  ret = nfs_lookup(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
1530  nfs3svc_lookup_cbk, cs);
1531  if (ret < 0)
1532  stat = nfs3_errno_to_nfsstat3(-ret);
1533 
1534 nfs3err:
1535  if (ret < 0) {
1537  -ret, cs->resolvedloc.path);
1538  nfs3_lookup_reply(cs->req, stat, &newfh, &cs->stbuf, &cs->postparent);
1540  }
1541 
1542  return ret;
1543 }
1544 
1545 int
1546 nfs3_lookup(rpcsvc_request_t *req, struct nfs3_fh *fh, int fhlen, char *name)
1547 {
1548  xlator_t *vol = NULL;
1550  int ret = -EFAULT;
1551  struct nfs3_state *nfs3 = NULL;
1552  nfs3_call_state_t *cs = NULL;
1553 
1557 
1558  nfs3_log_fh_entry_call(rpcsvc_request_xid(req), "LOOKUP", fh, name);
1559  nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
1560  if (nfs3_solaris_zerolen_fh(fh, fhlen)) {
1561  ret = nfs3_funge_webnfs_zerolen_fh(req, nfs3, fh, name);
1562  if (ret < 0)
1563  goto nfs3err;
1564 
1565  /* this fh means we're doing a mount, name is no more useful */
1566  name = NULL;
1567  } else
1568  nfs3_validate_gluster_fh(fh, stat, nfs3err);
1569  nfs3_validate_strlen_or_goto(name, NFS_NAME_MAX, nfs3err, stat, ret);
1570  nfs3_map_fh_to_volume(nfs3, fh, req, vol, stat, nfs3err);
1571  nfs3_volume_started_check(nfs3, vol, ret, out);
1572  nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
1573 
1576 
1577  if (ret < 0) {
1579  "failed to start hard resolve");
1580  }
1581 
1582 nfs3err:
1583  if (ret < 0) {
1584  stat = nfs3_errno_to_nfsstat3(-ret);
1586  cs ? cs->resolvedloc.path : NULL);
1587  nfs3_lookup_reply(req, stat, NULL, NULL, NULL);
1588  if (cs)
1590  /* Ret must be 0 after this so that the caller does not
1591  * also send an RPC reply.
1592  */
1593  ret = 0;
1594  }
1595 out:
1596  return ret;
1597 }
1598 
1599 int
1601 {
1602  char name[NFS_PATH_MAX];
1603  struct nfs3_fh fh = {
1604  {0},
1605  };
1606  lookup3args args;
1607  int ret = RPCSVC_ACTOR_ERROR;
1608 
1609  GF_VALIDATE_OR_GOTO(GF_NFS, req, rpcerr);
1610 
1612  if (xdr_to_lookup3args(req->msg[0], &args) <= 0) {
1614  "Error decoding args");
1615  rpcsvc_request_seterr(req, GARBAGE_ARGS);
1616  goto rpcerr;
1617  }
1618 
1619  ret = nfs3_lookup(req, &fh, args.what.dir.data.data_len, name);
1620  if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
1622  "LOOKUP procedure failed");
1623  rpcsvc_request_seterr(req, SYSTEM_ERR);
1624  ret = RPCSVC_ACTOR_ERROR;
1625  }
1626 
1627 rpcerr:
1628  return ret;
1629 }
1630 
1631 int
1632 nfs3_access_reply(rpcsvc_request_t *req, nfsstat3 status, int32_t accbits,
1633  int32_t reqaccbits)
1634 {
1635  access3res res;
1636 
1637  nfs3_fill_access3res(&res, status, accbits, reqaccbits);
1639  return 0;
1640 }
1641 
1642 int32_t
1643 nfs3svc_access_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
1644  int32_t op_ret, int32_t op_errno, dict_t *xdata)
1645 {
1646  nfsstat3 status = NFS3_OK;
1647  nfs3_call_state_t *cs = NULL;
1648 
1649  cs = frame->local;
1650 
1651  if (op_ret == -1) {
1652  status = nfs3_cbk_errno_status(op_ret, op_errno);
1653  }
1654 
1656  op_errno, cs->resolvedloc.path);
1657  nfs3_access_reply(cs->req, status, op_errno, cs->accessbits);
1659 
1660  return 0;
1661 }
1662 
1663 int
1665 {
1667  int ret = -EFAULT;
1668  nfs_user_t nfu = {
1669  0,
1670  };
1671  nfs3_call_state_t *cs = NULL;
1672 
1673  if (!carg) {
1675  "Invalid argument, carg value NULL");
1676  return EINVAL;
1677  }
1678 
1679  cs = (nfs3_call_state_t *)carg;
1680 
1681  /* Additional checks on the NFS file handle
1682  * go here. The path for an NFS ACCESS call
1683  * goes like this:
1684  * nfs3_access -> nfs3_fh_resolve_and_resume -> nfs3_resolve_resume ->
1685  * nfs3_access_resume -> <macro/function performs check on FH> ->
1686  * <continue or return from function based on check.> ('goto nfs3err'
1687  * terminates this function and writes the appropriate response to the
1688  * client). It is important that you do NOT stick any sort of check
1689  * on the file handle outside of the nfs3_##OP_resume functions.
1690  */
1691  nfs3_check_fh_auth_status(cs, stat, _gf_false, nfs3err);
1692  nfs3_check_fh_resolve_status(cs, stat, nfs3err);
1693  cs->fh = cs->resolvefh;
1694  nfs_request_user_init(&nfu, cs->req);
1695  ret = nfs_access(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, cs->accessbits,
1696  nfs3svc_access_cbk, cs);
1697  if (ret < 0)
1698  stat = nfs3_errno_to_nfsstat3(-ret);
1699 
1700 nfs3err:
1701  if (ret < 0) {
1703  -ret, cs->resolvedloc.path);
1704  nfs3_access_reply(cs->req, stat, 0, 0);
1706  ret = 0;
1707  }
1708 
1709  return ret;
1710 }
1711 
1712 int
1713 nfs3_access(rpcsvc_request_t *req, struct nfs3_fh *fh, uint32_t accbits)
1714 {
1715  xlator_t *vol = NULL;
1716  struct nfs3_state *nfs3 = NULL;
1718  int ret = -EFAULT;
1719  nfs3_call_state_t *cs = NULL;
1720 
1723  nfs3_log_common_call(rpcsvc_request_xid(req), "ACCESS", fh);
1724  nfs3_validate_gluster_fh(fh, stat, nfs3err);
1725  nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
1726  nfs3_map_fh_to_volume(nfs3, fh, req, vol, stat, nfs3err);
1727  nfs3_volume_started_check(nfs3, vol, ret, out);
1728  nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
1729  cs->accessbits = accbits;
1730 
1731  ret = nfs3_fh_resolve_and_resume(cs, fh, NULL, nfs3_access_resume);
1732  if (ret < 0)
1733  stat = nfs3_errno_to_nfsstat3(-ret);
1734 
1735 nfs3err:
1736  if (ret < 0) {
1738  cs ? cs->resolvedloc.path : NULL);
1739  nfs3_access_reply(req, stat, 0, 0);
1741  ret = 0;
1742  }
1743 out:
1744  return ret;
1745 }
1746 
1747 int
1749 {
1750  struct nfs3_fh fh = {
1751  {0},
1752  };
1753  access3args args;
1754  int ret = RPCSVC_ACTOR_ERROR;
1755 
1756  if (!req)
1757  return ret;
1758 
1759  nfs3_prep_access3args(&args, &fh);
1760  if (xdr_to_access3args(req->msg[0], &args) <= 0) {
1762  "Error decoding args");
1763  rpcsvc_request_seterr(req, GARBAGE_ARGS);
1764  goto rpcerr;
1765  }
1766 
1767  ret = nfs3_access(req, &fh, args.access);
1768  if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
1770  "ACCESS procedure failed");
1771  rpcsvc_request_seterr(req, SYSTEM_ERR);
1772  ret = RPCSVC_ACTOR_ERROR;
1773  }
1774 
1775 rpcerr:
1776  return ret;
1777 }
1778 
1779 int
1781  struct iatt *buf)
1782 {
1783  readlink3res res = {
1784  0,
1785  };
1786  uint64_t deviceid = 0;
1787 
1788  deviceid = nfs3_request_xlator_deviceid(req);
1789  nfs3_fill_readlink3res(&res, stat, path, buf, deviceid);
1790  nfs3svc_submit_reply(req, (void *)&res,
1792 
1793  return 0;
1794 }
1795 
1796 int32_t
1797 nfs3svc_readlink_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
1798  int32_t op_ret, int32_t op_errno, const char *path,
1799  struct iatt *buf, dict_t *xdata)
1800 {
1802  nfs3_call_state_t *cs = NULL;
1803 
1804  cs = frame->local;
1805  if (op_ret == -1) {
1806  stat = nfs3_cbk_errno_status(op_ret, op_errno);
1807  goto nfs3err;
1808  }
1809 
1810  stat = NFS3_OK;
1811 
1812 nfs3err:
1813  nfs3_log_readlink_res(rpcsvc_request_xid(cs->req), stat, op_errno,
1814  (char *)path, cs->resolvedloc.path);
1815  nfs3_readlink_reply(cs->req, stat, (char *)path, buf);
1817 
1818  return 0;
1819 }
1820 
1821 int
1823 {
1825  int ret = -EFAULT;
1826  nfs3_call_state_t *cs = NULL;
1827  nfs_user_t nfu = {
1828  0,
1829  };
1830 
1831  if (!carg)
1832  return ret;
1833 
1834  cs = (nfs3_call_state_t *)carg;
1835  nfs3_check_fh_auth_status(cs, stat, _gf_false, nfs3err);
1836  nfs3_check_fh_resolve_status(cs, stat, nfs3err);
1837  nfs_request_user_init(&nfu, cs->req);
1838  ret = nfs_readlink(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
1839  nfs3svc_readlink_cbk, cs);
1840  if (ret < 0)
1841  stat = nfs3_errno_to_nfsstat3(-ret);
1842 
1843 nfs3err:
1844  if (ret < 0) {
1846  -ret, cs->resolvedloc.path);
1847  nfs3_readlink_reply(cs->req, stat, NULL, NULL);
1849  }
1850 
1851  return ret;
1852 }
1853 
1854 int
1856 {
1857  xlator_t *vol = NULL;
1859  int ret = -EFAULT;
1860  struct nfs3_state *nfs3 = NULL;
1861  nfs3_call_state_t *cs = NULL;
1862 
1863  if ((!req) || (!fh)) {
1865  "Bad arguments");
1866  return -1;
1867  }
1868 
1869  nfs3_log_common_call(rpcsvc_request_xid(req), "READLINK", fh);
1870  nfs3_validate_gluster_fh(fh, stat, nfs3err);
1871  nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
1872  nfs3_map_fh_to_volume(nfs3, fh, req, vol, stat, nfs3err);
1873  nfs3_volume_started_check(nfs3, vol, ret, out);
1874  nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
1875 
1876  ret = nfs3_fh_resolve_and_resume(cs, fh, NULL, nfs3_readlink_resume);
1877  if (ret < 0)
1878  stat = nfs3_errno_to_nfsstat3(-ret);
1879 
1880 nfs3err:
1881  if (ret < 0) {
1883  cs ? cs->resolvedloc.path : NULL);
1884  nfs3_readlink_reply(req, stat, NULL, NULL);
1886  /* Ret must be 0 after this so that the caller does not
1887  * also send an RPC reply.
1888  */
1889  ret = 0;
1890  }
1891 out:
1892  return ret;
1893 }
1894 
1895 int
1897 {
1898  struct nfs3_fh fh = {
1899  {0},
1900  };
1902  int ret = RPCSVC_ACTOR_ERROR;
1903 
1904  if (!req)
1905  return ret;
1906 
1908  if (xdr_to_readlink3args(req->msg[0], &args) <= 0) {
1910  "Error decoding args");
1911  rpcsvc_request_seterr(req, GARBAGE_ARGS);
1912  goto rpcerr;
1913  }
1914 
1915  ret = nfs3_readlink(req, &fh);
1916  if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
1918  "READLINK procedure failed");
1919  rpcsvc_request_seterr(req, SYSTEM_ERR);
1920  ret = RPCSVC_ACTOR_ERROR;
1921  }
1922 
1923 rpcerr:
1924  return ret;
1925 }
1926 
1927 int
1929  struct iovec *vec, int vcount, struct iobref *iobref,
1930  struct iatt *poststat, int is_eof)
1931 {
1932  read3res res = {
1933  0,
1934  };
1935  uint64_t deviceid = 0;
1936 
1937  deviceid = nfs3_request_xlator_deviceid(req);
1938  nfs3_fill_read3res(&res, stat, count, poststat, is_eof, deviceid);
1939  if (stat == NFS3_OK) {
1940  xdr_vector_round_up(vec, vcount, count);
1941  /* iob can be zero if the file size was zero. If so, op_ret
1942  * would be 0 and count = 0.
1943  */
1944 
1945  if (count != 0) {
1947  req, (void *)&res,
1949  iobref);
1950  } else
1951 
1953  req, (void *)&res,
1955  } else
1956  nfs3svc_submit_reply(req, (void *)&res,
1958 
1959  return 0;
1960 }
1961 
1962 int32_t
1963 nfs3svc_read_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
1964  int32_t op_ret, int32_t op_errno, struct iovec *vector,
1965  int32_t count, struct iatt *stbuf, struct iobref *iobref,
1966  dict_t *xdata)
1967 {
1969  int is_eof = 0;
1970  nfs3_call_state_t *cs = NULL;
1971 
1972  cs = frame->local;
1973  if (op_ret == -1) {
1974  stat = nfs3_cbk_errno_status(op_ret, op_errno);
1975  goto err;
1976  } else
1977  stat = NFS3_OK;
1978 
1979  if (op_errno == ENOENT)
1980  is_eof = 1;
1981 
1982 err:
1983  nfs3_log_read_res(rpcsvc_request_xid(cs->req), stat, op_errno, op_ret,
1984  is_eof, vector, count, cs->resolvedloc.path);
1985  nfs3_read_reply(cs->req, stat, op_ret, vector, count, iobref, stbuf,
1986  is_eof);
1988 
1989  return 0;
1990 }
1991 
1992 int
1994 {
1996  int ret = -EFAULT;
1997  nfs_user_t nfu = {
1998  0,
1999  };
2000  nfs3_call_state_t *cs = NULL;
2001 
2002  if (!carg)
2003  return ret;
2004 
2005  cs = (nfs3_call_state_t *)carg;
2006  nfs3_check_fh_resolve_status(cs, stat, nfs3err);
2007  nfs_request_user_init(&nfu, cs->req);
2008  ret = nfs_read(cs->nfsx, cs->vol, &nfu, cs->fd, cs->datacount,
2009  cs->dataoffset, nfs3svc_read_cbk, cs);
2010  if (ret < 0)
2011  stat = nfs3_errno_to_nfsstat3(-ret);
2012 nfs3err:
2013  if (ret < 0) {
2015  cs->resolvedloc.path);
2016  nfs3_read_reply(cs->req, stat, 0, NULL, 0, NULL, NULL, 0);
2018  }
2019 
2020  return ret;
2021 }
2022 
2023 int
2024 nfs3_read_resume(void *carg)
2025 {
2027  int ret = -EFAULT;
2028  nfs3_call_state_t *cs = NULL;
2029  fd_t *fd = NULL;
2030 
2031  if (!carg)
2032  return ret;
2033 
2034  cs = (nfs3_call_state_t *)carg;
2035  nfs3_check_fh_auth_status(cs, stat, _gf_false, nfs3err);
2036  nfs3_check_fh_resolve_status(cs, stat, nfs3err);
2037  fd = fd_anonymous(cs->resolvedloc.inode);
2038  if (!fd) {
2040  "Failed to create anonymous fd");
2041  goto nfs3err;
2042  }
2043 
2044  cs->fd = fd;
2045  nfs3_read_fd_resume(cs);
2046  ret = 0;
2047 nfs3err:
2048  if (ret < 0) {
2050  cs->resolvedloc.path);
2051  nfs3_read_reply(cs->req, stat, 0, NULL, 0, NULL, NULL, 0);
2053  }
2054 
2055  return ret;
2056 }
2057 
2058 int
2059 nfs3_read(rpcsvc_request_t *req, struct nfs3_fh *fh, offset3 offset,
2060  count3 count)
2061 {
2062  xlator_t *vol = NULL;
2064  int ret = -EFAULT;
2065  struct nfs3_state *nfs3 = NULL;
2066  nfs3_call_state_t *cs = NULL;
2067 
2068  if ((!req) || (!fh)) {
2070  "Bad arguments");
2071  return -1;
2072  }
2073 
2074  nfs3_log_rw_call(rpcsvc_request_xid(req), "READ", fh, offset, count, -1);
2075  nfs3_validate_gluster_fh(fh, stat, nfs3err);
2076  nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
2077  nfs3_map_fh_to_volume(nfs3, fh, req, vol, stat, nfs3err);
2078  nfs3_volume_started_check(nfs3, vol, ret, out);
2079  nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
2080 
2081  cs->datacount = count;
2082  cs->dataoffset = offset;
2083  ret = nfs3_fh_resolve_and_resume(cs, fh, NULL, nfs3_read_resume);
2084  if (ret < 0)
2085  stat = nfs3_errno_to_nfsstat3(-ret);
2086 
2087 nfs3err:
2088  if (ret < 0) {
2090  cs ? cs->resolvedloc.path : NULL);
2091  nfs3_read_reply(req, stat, 0, NULL, 0, NULL, NULL, 0);
2093  ret = 0;
2094  }
2095 out:
2096  return ret;
2097 }
2098 
2099 int
2101 {
2102  struct nfs3_fh fh = {
2103  {0},
2104  };
2105  read3args args;
2106  int ret = RPCSVC_ACTOR_ERROR;
2107 
2108  if (!req)
2109  return ret;
2110 
2111  nfs3_prep_read3args(&args, &fh);
2112  if (xdr_to_read3args(req->msg[0], &args) <= 0) {
2114  "Error decoding args");
2115  rpcsvc_request_seterr(req, GARBAGE_ARGS);
2116  goto rpcerr;
2117  }
2118 
2119  ret = nfs3_read(req, &fh, args.offset, args.count);
2120  if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
2122  "READ procedure failed");
2123  rpcsvc_request_seterr(req, SYSTEM_ERR);
2124  ret = RPCSVC_ACTOR_ERROR;
2125  }
2126 
2127 rpcerr:
2128  return ret;
2129 }
2130 
2131 int
2133  stable_how stable, uint64_t wverf, struct iatt *prestat,
2134  struct iatt *poststat)
2135 {
2136  write3res res = {
2137  0,
2138  };
2139  uint64_t deviceid = 0;
2140 
2141  deviceid = nfs3_request_xlator_deviceid(req);
2142  nfs3_fill_write3res(&res, stat, count, stable, wverf, prestat, poststat,
2143  deviceid);
2144  nfs3svc_submit_reply(req, (void *)&res,
2146 
2147  return 0;
2148 }
2149 
2150 int32_t
2151 nfs3svc_write_fsync_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
2152  int32_t op_ret, int32_t op_errno, struct iatt *prebuf,
2153  struct iatt *postbuf, dict_t *xdata)
2154 {
2155  struct nfs3_state *nfs3 = NULL;
2157  nfs3_call_state_t *cs = NULL;
2158 
2159  cs = frame->local;
2160  nfs3 = rpcsvc_request_program_private(cs->req);
2161 
2162  if (op_ret == -1) {
2163  stat = nfs3_cbk_errno_status(op_ret, op_errno);
2164  } else
2165  stat = NFS3_OK;
2166 
2167  nfs3_log_write_res(rpcsvc_request_xid(cs->req), stat, op_errno,
2168  cs->maxcount, cs->writetype, nfs3->serverstart,
2169  cs->resolvedloc.path);
2170  nfs3_write_reply(cs->req, stat, cs->maxcount, cs->writetype,
2171  nfs3->serverstart, &cs->stbuf, postbuf);
2173  return 0;
2174 }
2175 
2176 /*
2177  * Before going into the write reply logic, here is a matrix that shows the
2178  * requirements for a write reply as given by RFC1813.
2179  *
2180  * Requested Write Type || Possible Returns
2181  * ==============================================
2182  * FILE_SYNC || FILE_SYNC
2183  * DATA_SYNC || DATA_SYNC or FILE_SYNC
2184  * UNSTABLE || DATA_SYNC or FILE_SYNC or UNSTABLE
2185  *
2186  * Write types other than UNSTABLE are together called STABLE.
2187  * RS - Return Stable
2188  * RU - Return Unstable
2189  * WS - Write Stable
2190  * WU - Write Unstable
2191  *
2192  *+============================================+
2193  *| Vol Opts -> || trusted-write| trusted-sync |
2194  *| Write Type || | |
2195  *|-------------||--------------|--------------|
2196  *| STABLE || WS | WU |
2197  *| || RS | RS |
2198  *|-------------||--------------|--------------|
2199  *| UNSTABLE || WU | WU |
2200  *| || RS | RS |
2201  *|-------------||--------------|--------------|
2202  *| COMMIT || fsync | getattr |
2203  *+============================================+
2204  *
2205  *
2206  */
2207 int32_t
2208 nfs3svc_write_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
2209  int32_t op_ret, int32_t op_errno, struct iatt *prebuf,
2210  struct iatt *postbuf, dict_t *xdata)
2211 {
2213  nfs3_call_state_t *cs = NULL;
2214  struct nfs3_state *nfs3 = NULL;
2215 
2216  cs = frame->local;
2217  nfs3 = rpcsvc_request_program_private(cs->req);
2218  if (op_ret == -1) {
2219  stat = nfs3_cbk_errno_status(op_ret, op_errno);
2220  goto err;
2221  }
2222 
2223  stat = NFS3_OK;
2224  cs->maxcount = op_ret;
2225 
2226 err:
2227  nfs3_log_write_res(rpcsvc_request_xid(cs->req), stat, op_errno,
2228  cs->maxcount, cs->writetype, nfs3->serverstart,
2229  cs->resolvedloc.path);
2230  nfs3_write_reply(cs->req, stat, cs->maxcount, cs->writetype,
2231  nfs3->serverstart, prebuf, postbuf);
2233 
2234  return 0;
2235 }
2236 
2237 int
2239 {
2240  int ret = -EFAULT;
2241  nfs_user_t nfu = {
2242  0,
2243  };
2244 
2245  if (!cs)
2246  return ret;
2247 
2248  nfs_request_user_init(&nfu, cs->req);
2249  /* It is possible that the RPC record contains more bytes than
2250  * than the size of write requested in this request. This means,
2251  * that in the RPC message buffer, there could be more bytes
2252  * beyind the @count bytes. Since @payload is referring to the write
2253  * data directly inside the RPC request buffer(..since we performed a
2254  * no-copy deXDRing..), we might end up writing more data than
2255  * requested, because till now payload.iov_len accounts for all the
2256  * bytes not just the write request bytes. These extra bytes are present
2257  * as a requirement of the XDR encoding to round up the all string and
2258  * opaque data buffers to multiples of 4 bytes.
2259  */
2260  cs->datavec.iov_len = cs->datacount;
2261  ret = nfs_write(cs->nfsx, cs->vol, &nfu, cs->fd, cs->iobref, &cs->datavec,
2262  1, cs->dataoffset, nfs3svc_write_cbk, cs);
2263 
2264  return ret;
2265 }
2266 
2267 int
2269 {
2271  int ret = -EFAULT;
2272  nfs3_call_state_t *cs = NULL;
2273  fd_t *fd = NULL;
2274 
2275  if (!carg)
2276  return ret;
2277 
2278  cs = (nfs3_call_state_t *)carg;
2279  nfs3_check_fh_auth_status(cs, stat, _gf_true, nfs3err);
2280  nfs3_check_fh_resolve_status(cs, stat, nfs3err);
2281  fd = fd_anonymous(cs->resolvedloc.inode);
2282  if (!fd) {
2284  "Failed to create anonymous fd");
2285  goto nfs3err;
2286  }
2287 
2288  cs->fd = fd; /* Gets unrefd when the call state is wiped. */
2289 
2290  ret = __nfs3_write_resume(cs);
2291  if (ret < 0)
2292  stat = nfs3_errno_to_nfsstat3(-ret);
2293 nfs3err:
2294  if (ret < 0) {
2296  cs->resolvedloc.path);
2297  nfs3_write_reply(cs->req, stat, 0, cs->writetype, 0, NULL, NULL);
2299  }
2300  return ret;
2301 }
2302 
2303 int
2304 nfs3_write(rpcsvc_request_t *req, struct nfs3_fh *fh, offset3 offset,
2305  count3 count, stable_how stable, struct iovec payload,
2306  struct iobref *iobref)
2307 {
2308  xlator_t *vol = NULL;
2310  int ret = -EFAULT;
2311  struct nfs3_state *nfs3 = NULL;
2312  nfs3_call_state_t *cs = NULL;
2313 
2314  if ((!req) || (!fh) || (!payload.iov_base)) {
2316  "Bad arguments");
2317  return -1;
2318  }
2319 
2320  nfs3_log_rw_call(rpcsvc_request_xid(req), "WRITE", fh, offset, count,
2321  stable);
2322  nfs3_validate_gluster_fh(fh, stat, nfs3err);
2323  nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
2324  nfs3_map_fh_to_volume(nfs3, fh, req, vol, stat, nfs3err);
2325  nfs3_volume_started_check(nfs3, vol, ret, out);
2326  nfs3_check_rw_volaccess(nfs3, fh->exportid, stat, nfs3err);
2327  nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
2328  cs->datacount = count;
2329  cs->dataoffset = offset;
2330  cs->writetype = stable;
2331  cs->iobref = iobref;
2332  cs->datavec = payload;
2333 
2334  ret = nfs3_fh_resolve_and_resume(cs, fh, NULL, nfs3_write_resume);
2335  if (ret < 0)
2336  stat = nfs3_errno_to_nfsstat3(-ret);
2337 
2338 nfs3err:
2339  if (ret < 0) {
2341  cs ? cs->resolvedloc.path : NULL);
2342  nfs3_write_reply(req, stat, 0, stable, 0, NULL, NULL);
2344  ret = 0;
2345  }
2346 out:
2347  return ret;
2348 }
2349 
2350 #define NFS3_VECWRITE_READFHLEN 1
2351 #define NFS3_VECWRITE_READFH 2
2352 #define NFS3_VECWRITE_READREST 3
2353 
2354 #define NFS3_WRITE_POSTFH_SIZE 20
2355 
2356 int
2357 nfs3svc_write_vecsizer(int state, ssize_t *readsize, char *base_addr,
2358  char *curr_addr)
2359 {
2360  int ret = 0;
2361  uint32_t fhlen = 0;
2362  uint32_t fhlen_n = 0;
2363 
2364  if (state == 0) {
2366  *readsize = 4;
2367  } else if (state == NFS3_VECWRITE_READFHLEN) {
2368  fhlen_n = *(uint32_t *)(curr_addr - 4);
2369  fhlen = ntohl(fhlen_n);
2371  ret = NFS3_VECWRITE_READFH;
2372  } else if (state == NFS3_VECWRITE_READFH) {
2374  ret = NFS3_VECWRITE_READREST;
2375  } else if (state == NFS3_VECWRITE_READREST) {
2376  ret = 0;
2377  *readsize = 0;
2378  } else
2379  gf_msg("nfs", GF_LOG_ERROR, 0, NFS_MSG_STATE_WRONG, "state wrong");
2380 
2381  return ret;
2382 }
2383 
2384 int
2386 {
2387  struct nfs3_fh fh = {
2388  {0},
2389  };
2390  write3args args;
2391  int ret = RPCSVC_ACTOR_ERROR;
2392 
2393  if (!req)
2394  return ret;
2395  nfs3_prep_write3args(&args, &fh);
2396  if (xdr_to_write3args(req->msg[0], &args) <= 0) {
2398  "Error decoding args");
2399  rpcsvc_request_seterr(req, GARBAGE_ARGS);
2400  goto rpcerr;
2401  }
2402 
2403  /* To ensure that the iobuf for the current record does not
2404  * get returned to the iobpool, we need to keep a reference for
2405  * ourselves because the RPC call handler who called us will unref its
2406  * own ref of the record's iobuf when it is done handling the request.
2407  */
2408 
2409  ret = nfs3_write(req, &fh, args.offset, args.count, args.stable,
2410  req->msg[1], rpcsvc_request_iobref_ref(req));
2411  if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
2413  "WRITE procedure failed");
2414  rpcsvc_request_seterr(req, SYSTEM_ERR);
2415  ret = RPCSVC_ACTOR_ERROR;
2416  }
2417 
2418 rpcerr:
2419  return ret;
2420 }
2421 
2422 int
2424  struct iatt *newbuf, struct iatt *preparent,
2425  struct iatt *postparent)
2426 {
2427  create3res res = {
2428  0,
2429  };
2430  uint64_t deviceid = 0;
2431 
2432  deviceid = nfs3_request_xlator_deviceid(req);
2433  nfs3_fill_create3res(&res, stat, newfh, newbuf, preparent, postparent,
2434  deviceid);
2435  nfs3svc_submit_reply(req, (void *)&res,
2437  return 0;
2438 }
2439 
2440 int32_t
2442  int32_t op_ret, int32_t op_errno, struct iatt *preop,
2443  struct iatt *postop, dict_t *xdata)
2444 {
2446  nfs3_call_state_t *cs = NULL;
2447 
2448  cs = frame->local;
2449  if (op_ret == -1) {
2450  stat = nfs3_cbk_errno_status(op_ret, op_errno);
2451  goto nfs3err;
2452  }
2453 
2454  stat = NFS3_OK;
2455 nfs3err:
2456  nfs3_log_newfh_res(rpcsvc_request_xid(cs->req), NFS3_CREATE, stat, op_errno,
2457  &cs->fh, cs->resolvedloc.path);
2458  nfs3_create_reply(cs->req, stat, &cs->fh, postop, &cs->preparent,
2459  &cs->postparent);
2461 
2462  return 0;
2463 }
2464 
2465 int32_t
2466 nfs3svc_create_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
2467  int32_t op_ret, int32_t op_errno, fd_t *fd, inode_t *inode,
2468  struct iatt *buf, struct iatt *preparent,
2469  struct iatt *postparent, dict_t *xdata)
2470 {
2472  int ret = -EFAULT;
2473  nfs_user_t nfu = {
2474  0,
2475  };
2476  nfs3_call_state_t *cs = NULL;
2477  inode_t *oldinode = NULL;
2478 
2479  cs = frame->local;
2480  if (op_ret == -1) {
2481  stat = nfs3_cbk_errno_status(op_ret, op_errno);
2482  goto nfs3err;
2483  }
2484 
2485  nfs3_fh_build_child_fh(&cs->parent, buf, &cs->fh);
2486  oldinode = inode_link(inode, cs->resolvedloc.parent, cs->resolvedloc.name,
2487  buf);
2488 
2489  /* Means no attributes were required to be set. */
2490  if (!cs->setattr_valid) {
2491  stat = NFS3_OK;
2492  ret = -1;
2493  goto nfs3err;
2494  }
2495 
2496  cs->preparent = *preparent;
2497  cs->postparent = *postparent;
2498  nfs_request_user_init(&nfu, cs->req);
2499  gf_uuid_copy(cs->resolvedloc.gfid, oldinode->gfid);
2500  ret = nfs_setattr(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, &cs->stbuf,
2502  if (ret < 0)
2503  stat = nfs3_errno_to_nfsstat3(-ret);
2504 
2505 nfs3err:
2506  if (oldinode) {
2507  inode_lookup(oldinode);
2508  inode_unref(oldinode);
2509  }
2510 
2511  if (ret < 0) {
2513  op_errno, &cs->fh, cs->resolvedloc.path);
2514  nfs3_create_reply(cs->req, stat, &cs->fh, buf, preparent, postparent);
2516  }
2517 
2518  return 0;
2519 }
2520 
2521 int
2523 {
2524  int ret = -EFAULT;
2525  int flags = 0;
2526  nfs_user_t nfu = {
2527  0,
2528  };
2529  uid_t uid = 0;
2530  gid_t gid = 0;
2531 
2532  if (!cs)
2533  return ret;
2534 
2535  if (cs->createmode == GUARDED)
2536  flags = (O_RDWR | O_EXCL);
2537  else
2538  flags = O_RDWR;
2539 
2540  if (gf_attr_uid_set(cs->setattr_valid)) {
2541  uid = cs->stbuf.ia_uid;
2543  } else
2544  uid = rpcsvc_request_uid(cs->req);
2545 
2546  if (gf_attr_gid_set(cs->setattr_valid)) {
2547  gid = cs->stbuf.ia_gid;
2549  } else
2550  gid = rpcsvc_request_gid(cs->req);
2551 
2552  nfs_request_primary_user_init(&nfu, cs->req, uid, gid);
2553  /* We can avoid sending the setattr call later if only the mode is
2554  * required to be set. This is possible because the create fop allows
2555  * us to specify a mode arg.
2556  */
2557  if (cs->setattr_valid & GF_SET_ATTR_MODE) {
2559  ret = nfs_create(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, flags,
2560  cs->mode, nfs3svc_create_cbk, cs);
2561  } else
2562  ret = nfs_create(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, flags,
2564 
2565  return ret;
2566 }
2567 
2568 int32_t
2569 nfs3svc_create_stat_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
2570  int32_t op_ret, int32_t op_errno, struct iatt *buf,
2571  dict_t *xdata)
2572 {
2573  int ret = -EFAULT;
2575  nfs_user_t nfu = {
2576  0,
2577  };
2578  nfs3_call_state_t *cs = NULL;
2579 
2580  cs = frame->local;
2581  nfs_request_user_init(&nfu, cs->req);
2582  if (op_ret == -1) {
2583  ret = -op_errno;
2584  stat = nfs3_cbk_errno_status(op_ret, op_errno);
2585  goto nfs3err;
2586  }
2587 
2588  if ((cs->stbuf.ia_mtime == buf->ia_mtime) &&
2589  (cs->stbuf.ia_atime == buf->ia_atime)) {
2590  gf_msg_debug(GF_NFS3, 0,
2591  "Create req retransmitted verf %" PRId64 " %" PRId64,
2592  cs->stbuf.ia_mtime, cs->stbuf.ia_atime);
2593  stat = NFS3_OK;
2594  nfs3_fh_build_child_fh(&cs->parent, buf, &cs->fh);
2595  } else {
2596  gf_msg_debug(GF_NFS3, 0,
2597  "File already exist new_verf %" PRId64 " %" PRId64
2598  "old_verf %" PRId64 " %" PRId64,
2599  cs->stbuf.ia_mtime, cs->stbuf.ia_atime, buf->ia_mtime,
2600  buf->ia_atime);
2601  stat = NFS3ERR_EXIST;
2602  }
2603 
2604 nfs3err:
2605  if (ret < 0) {
2607  op_errno, cs->resolvedloc.path);
2608  nfs3_create_reply(cs->req, stat, &cs->fh, buf, NULL, NULL);
2610  }
2611 
2612  return 0;
2613 }
2614 
2615 int
2617 {
2618  int ret = -EFAULT;
2619  nfs_user_t nfu = {
2620  0,
2621  };
2622 
2623  if (!cs)
2624  return ret;
2625 
2626  /* Storing verifier as a mtime and atime attribute, to store it
2627  * in stable storage */
2628  memcpy(&cs->stbuf.ia_atime, &cs->cookieverf, sizeof(cs->stbuf.ia_atime));
2629  memcpy(&cs->stbuf.ia_mtime,
2630  ((char *)&cs->cookieverf) + sizeof(cs->stbuf.ia_atime),
2631  sizeof(cs->stbuf.ia_mtime));
2634  nfs_request_user_init(&nfu, cs->req);
2635 
2636  /* If the file already existed we need to get that attributes so we can
2637  * compare and check whether a previous create operation was
2638  * interrupted due to server failure or dropped packets.
2639  */
2640  if ((cs->resolve_ret == 0) ||
2641  ((cs->resolve_ret == -1) && (cs->resolve_errno != ENOENT))) {
2642  ret = nfs_stat(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
2644  goto nfs3err;
2645  }
2646 
2647  ret = nfs3_create_common(cs);
2648 nfs3err:
2649  return ret;
2650 }
2651 
2652 int
2654 {
2656  int ret = -EFAULT;
2657  nfs3_call_state_t *cs = NULL;
2658 
2659  if (!carg)
2660  return ret;
2661 
2662  cs = (nfs3_call_state_t *)carg;
2663  nfs3_check_fh_auth_status(cs, stat, _gf_true, nfs3err);
2664  nfs3_check_new_fh_resolve_status(cs, stat, nfs3err);
2665  if (cs->createmode == EXCLUSIVE)
2666  ret = nfs3_create_exclusive(cs);
2667  else
2668  ret = nfs3_create_common(cs);
2669 
2670  /* Handle a failure return from either of the create functions above. */
2671  if (ret < 0)
2672  stat = nfs3_errno_to_nfsstat3(-ret);
2673 
2674 nfs3err:
2675  if (ret < 0) {
2677  -ret, cs->resolvedloc.path);
2678  nfs3_create_reply(cs->req, stat, NULL, NULL, NULL, NULL);
2680  }
2681 
2682  return ret;
2683 }
2684 
2685 int
2686 nfs3_create(rpcsvc_request_t *req, struct nfs3_fh *dirfh, char *name,
2687  createmode3 mode, sattr3 *sattr, uint64_t cverf)
2688 {
2689  xlator_t *vol = NULL;
2691  int ret = -EFAULT;
2692  struct nfs3_state *nfs3 = NULL;
2693  nfs3_call_state_t *cs = NULL;
2694 
2695  if ((!req) || (!dirfh) || (!name) || (!sattr))
2696  return -1;
2697 
2698  nfs3_log_create_call(rpcsvc_request_xid(req), dirfh, name, mode);
2699  nfs3_validate_gluster_fh(dirfh, stat, nfs3err);
2700  nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
2701  nfs3_validate_strlen_or_goto(name, NFS_NAME_MAX, nfs3err, stat, ret);
2702  nfs3_map_fh_to_volume(nfs3, dirfh, req, vol, stat, nfs3err);
2703  nfs3_volume_started_check(nfs3, vol, ret, out);
2704  nfs3_check_rw_volaccess(nfs3, dirfh->exportid, stat, nfs3err);
2705  nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
2706 
2707  cs->cookieverf = cverf;
2708  /*In Exclusive create client is supposed to send cverf instead of
2709  * sattr*/
2710  if (mode != EXCLUSIVE)
2712  &cs->mode);
2713  cs->createmode = mode;
2714  cs->parent = *dirfh;
2715 
2717  if (ret < 0)
2718  stat = nfs3_errno_to_nfsstat3(-ret);
2719 
2720 nfs3err:
2721  if (ret < 0) {
2723  cs ? cs->resolvedloc.path : NULL);
2724  nfs3_create_reply(req, stat, NULL, NULL, NULL, NULL);
2726  ret = 0;
2727  }
2728 out:
2729  return ret;
2730 }
2731 
2732 int
2734 {
2735  char name[NFS_PATH_MAX];
2736  struct nfs3_fh dirfh = {
2737  {0},
2738  };
2739  create3args args;
2740  int ret = RPCSVC_ACTOR_ERROR;
2741  uint64_t cverf = 0;
2742  uint64_t *cval;
2743 
2744  if (!req)
2745  return ret;
2746 
2747  nfs3_prep_create3args(&args, &dirfh, name);
2748  if (xdr_to_create3args(req->msg[0], &args) <= 0) {
2750  "Error decoding args");
2751  rpcsvc_request_seterr(req, GARBAGE_ARGS);
2752  goto rpcerr;
2753  }
2754 
2755  cval = (uint64_t *)args.how.createhow3_u.verf;
2756  cverf = *cval;
2757 
2758  ret = nfs3_create(req, &dirfh, name, args.how.mode,
2759  &args.how.createhow3_u.obj_attributes, cverf);
2760  if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
2762  "CREATE procedure failed");
2763  rpcsvc_request_seterr(req, SYSTEM_ERR);
2764  ret = RPCSVC_ACTOR_ERROR;
2765  }
2766 
2767 rpcerr:
2768  return ret;
2769 }
2770 
2771 int
2773  struct iatt *buf, struct iatt *preparent,
2774  struct iatt *postparent)
2775 {
2776  mkdir3res res = {
2777  0,
2778  };
2779  uint64_t deviceid = 0;
2780 
2781  deviceid = nfs3_request_xlator_deviceid(req);
2782  nfs3_fill_mkdir3res(&res, stat, fh, buf, preparent, postparent, deviceid);
2784  return 0;
2785 }
2786 
2787 int32_t
2789  int32_t op_ret, int32_t op_errno, struct iatt *preop,
2790  struct iatt *postop, dict_t *xdata)
2791 {
2793  nfs3_call_state_t *cs = NULL;
2794 
2795  cs = frame->local;
2796  if (op_ret == -1) {
2797  stat = nfs3_cbk_errno_status(op_ret, op_errno);
2798  goto nfs3err;
2799  }
2800 
2801  stat = NFS3_OK;
2802 nfs3err:
2803  nfs3_log_newfh_res(rpcsvc_request_xid(cs->req), NFS3_MKDIR, stat, op_errno,
2804  &cs->fh, cs->resolvedloc.path);
2805  nfs3_mkdir_reply(cs->req, stat, &cs->fh, postop, &cs->preparent,
2806  &cs->postparent);
2808 
2809  return 0;
2810 }
2811 
2812 int32_t
2813 nfs3svc_mkdir_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
2814  int32_t op_ret, int32_t op_errno, inode_t *inode,
2815  struct iatt *buf, struct iatt *preparent,
2816  struct iatt *postparent, dict_t *xdata)
2817 {
2819  int ret = -EFAULT;
2820  nfs_user_t nfu = {
2821  0,
2822  };
2823  nfs3_call_state_t *cs = NULL;
2824 
2825  cs = frame->local;
2826  if (op_ret == -1) {
2827  stat = nfs3_cbk_errno_status(op_ret, op_errno);
2828  goto nfs3err;
2829  }
2830 
2831  nfs3_fh_build_child_fh(&cs->parent, buf, &cs->fh);
2832 
2833  /* Means no attributes were required to be set. */
2834  if (!cs->setattr_valid) {
2835  stat = NFS3_OK;
2836  goto nfs3err;
2837  }
2838 
2839  cs->preparent = *preparent;
2840  cs->postparent = *postparent;
2841  nfs_request_user_init(&nfu, cs->req);
2842  ret = nfs_setattr(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, &cs->stbuf,
2844  if (ret < 0)
2845  stat = nfs3_errno_to_nfsstat3(-ret);
2846 
2847 nfs3err:
2848  if (ret < 0) {
2850  op_errno, &cs->fh, cs->resolvedloc.path);
2851  nfs3_mkdir_reply(cs->req, stat, &cs->fh, buf, preparent, postparent);
2853  }
2854 
2855  return 0;
2856 }
2857 
2858 int
2860 {
2862  int ret = -EFAULT;
2863  nfs_user_t nfu = {
2864  0,
2865  };
2866  nfs3_call_state_t *cs = NULL;
2867 
2868  if (!carg)
2869  return ret;
2870 
2871  cs = (nfs3_call_state_t *)carg;
2872  nfs3_check_new_fh_resolve_status(cs, stat, nfs3err);
2873  nfs_request_user_init(&nfu, cs->req);
2874 
2875  if (gf_attr_mode_set(cs->setattr_valid)) {
2877  ret = nfs_mkdir(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, cs->mode,
2878  nfs3svc_mkdir_cbk, cs);
2879  } else
2880  ret = nfs_mkdir(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, cs->mode,
2881  nfs3svc_mkdir_cbk, cs);
2882 
2883  if (ret < 0)
2884  stat = nfs3_errno_to_nfsstat3(-ret);
2885 
2886 nfs3err:
2887  if (ret < 0) {
2889  cs->resolvedloc.path);
2890  nfs3_mkdir_reply(cs->req, stat, NULL, NULL, NULL, NULL);
2892  }
2893 
2894  return 0;
2895 }
2896 
2897 int
2898 nfs3_mkdir(rpcsvc_request_t *req, struct nfs3_fh *dirfh, char *name,
2899  sattr3 *sattr)
2900 {
2901  xlator_t *vol = NULL;
2903  int ret = -EFAULT;
2904  struct nfs3_state *nfs3 = NULL;
2905  nfs3_call_state_t *cs = NULL;
2906 
2907  if ((!req) || (!dirfh) || (!name) || (!sattr)) {
2909  "Bad arguments");
2910  return -1;
2911  }
2912 
2913  nfs3_log_fh_entry_call(rpcsvc_request_xid(req), "MKDIR", dirfh, name);
2914  nfs3_validate_gluster_fh(dirfh, stat, nfs3err);
2915  nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
2916  nfs3_validate_strlen_or_goto(name, NFS_NAME_MAX, nfs3err, stat, ret);
2917  nfs3_map_fh_to_volume(nfs3, dirfh, req, vol, stat, nfs3err);
2918  nfs3_volume_started_check(nfs3, vol, ret, out);
2919  nfs3_check_rw_volaccess(nfs3, dirfh->exportid, stat, nfs3err);
2920  nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
2921 
2922  cs->parent = *dirfh;
2924  &cs->mode);
2926  if (ret < 0)
2927  stat = nfs3_errno_to_nfsstat3(-ret);
2928 
2929 nfs3err:
2930  if (ret < 0) {
2932  cs ? cs->resolvedloc.path : NULL);
2933  nfs3_mkdir_reply(req, stat, NULL, NULL, NULL, NULL);
2935  ret = 0;
2936  }
2937 out:
2938  return ret;
2939 }
2940 
2941 int
2943 {
2944  char name[NFS_PATH_MAX];
2945  struct nfs3_fh dirfh = {
2946  {0},
2947  };
2948  mkdir3args args;
2949  int ret = RPCSVC_ACTOR_ERROR;
2950 
2951  if (!req)
2952  return ret;
2953  nfs3_prep_mkdir3args(&args, &dirfh, name);
2954  if (xdr_to_mkdir3args(req->msg[0], &args) <= 0) {
2956  "Error decoding args");
2957  rpcsvc_request_seterr(req, GARBAGE_ARGS);
2958  goto rpcerr;
2959  }
2960 
2961  ret = nfs3_mkdir(req, &dirfh, name, &args.attributes);
2962  if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
2964  "MKDIR procedure failed");
2965  rpcsvc_request_seterr(req, SYSTEM_ERR);
2966  ret = RPCSVC_ACTOR_ERROR;
2967  }
2968 
2969 rpcerr:
2970  return ret;
2971 }
2972 
2973 int
2975  struct iatt *buf, struct iatt *preparent,
2976  struct iatt *postparent)
2977 {
2978  symlink3res res = {
2979  0,
2980  };
2981  uint64_t deviceid = 0;
2982 
2983  deviceid = nfs3_request_xlator_deviceid(req);
2984  nfs3_fill_symlink3res(&res, stat, fh, buf, preparent, postparent, deviceid);
2985  nfs3svc_submit_reply(req, (void *)&res,
2987 
2988  return 0;
2989 }
2990 
2991 int32_t
2992 nfs3svc_symlink_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
2993  int32_t op_ret, int32_t op_errno, inode_t *inode,
2994  struct iatt *buf, struct iatt *preparent,
2995  struct iatt *postparent, dict_t *xdata)
2996 {
2998  nfs3_call_state_t *cs = NULL;
2999 
3000  cs = frame->local;
3001  if (op_ret == -1) {
3002  stat = nfs3_cbk_errno_status(op_ret, op_errno);
3003  goto nfs3err;
3004  }
3005 
3006  nfs3_fh_build_child_fh(&cs->parent, buf, &cs->fh);
3007  stat = NFS3_OK;
3008 
3009 nfs3err:
3011  op_errno, &cs->fh, cs->resolvedloc.path);
3012  nfs3_symlink_reply(cs->req, stat, &cs->fh, buf, preparent, postparent);
3014  return 0;
3015 }
3016 
3017 int
3019 {
3021  int ret = -EFAULT;
3022  nfs3_call_state_t *cs = NULL;
3023  nfs_user_t nfu = {
3024  0,
3025  };
3026 
3027  if (!carg)
3028  return ret;
3029 
3030  cs = (nfs3_call_state_t *)carg;
3031  nfs3_check_new_fh_resolve_status(cs, stat, nfs3err);
3032  nfs_request_user_init(&nfu, cs->req);
3033  ret = nfs_symlink(cs->nfsx, cs->vol, &nfu, cs->pathname, &cs->resolvedloc,
3034  nfs3svc_symlink_cbk, cs);
3035  if (ret < 0)
3036  stat = nfs3_errno_to_nfsstat3(-ret);
3037 
3038 nfs3err:
3039  if (ret < 0) {
3041  -ret, cs->resolvedloc.path);
3042  nfs3_symlink_reply(cs->req, stat, NULL, NULL, NULL, NULL);
3044  }
3045 
3046  return ret;
3047 }
3048 
3049 int
3050 nfs3_symlink(rpcsvc_request_t *req, struct nfs3_fh *dirfh, char *name,
3051  char *target, sattr3 *sattr)
3052 {
3053  xlator_t *vol = NULL;
3055  int ret = -EFAULT;
3056  struct nfs3_state *nfs3 = NULL;
3057  nfs3_call_state_t *cs = NULL;
3058 
3059  if ((!req) || (!dirfh) || (!name) || (!target) || (!sattr)) {
3061  "Bad arguments");
3062  return -1;
3063  }
3064 
3065  nfs3_log_symlink_call(rpcsvc_request_xid(req), dirfh, name, target);
3066  nfs3_validate_gluster_fh(dirfh, stat, nfs3err);
3067  nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
3068  nfs3_validate_strlen_or_goto(name, NFS_NAME_MAX, nfs3err, stat, ret);
3069  nfs3_map_fh_to_volume(nfs3, dirfh, req, vol, stat, nfs3err);
3070  nfs3_volume_started_check(nfs3, vol, ret, out);
3071  nfs3_check_rw_volaccess(nfs3, dirfh->exportid, stat, nfs3err);
3072  nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
3073 
3074  cs->parent = *dirfh;
3075  cs->pathname = gf_strdup(target);
3076  if (!cs->pathname) {
3077  ret = -1;
3078  stat = NFS3ERR_SERVERFAULT;
3079  goto nfs3err;
3080  }
3081 
3083  if (ret < 0)
3084  stat = nfs3_errno_to_nfsstat3(-ret);
3085 
3086 nfs3err:
3087  if (ret < 0) {
3089  cs ? cs->resolvedloc.path : NULL);
3090  nfs3_symlink_reply(req, stat, NULL, NULL, NULL, NULL);
3092  /* Ret must be 0 after this so that the caller does not
3093  * also send an RPC reply.
3094  */
3095  ret = 0;
3096  }
3097 out:
3098  return ret;
3099 }
3100 
3101 int
3103 {
3104  char name[NFS_PATH_MAX];
3105  struct nfs3_fh dirfh = {
3106  {0},
3107  };
3108  char target[NFS_PATH_MAX];
3110  int ret = RPCSVC_ACTOR_ERROR;
3111 
3112  if (!req)
3113  return ret;
3114  nfs3_prep_symlink3args(&args, &dirfh, name, target);
3115  if (xdr_to_symlink3args(req->msg[0], &args) <= 0) {
3117  "Error decoding args");
3118  rpcsvc_request_seterr(req, GARBAGE_ARGS);
3119  goto rpcerr;
3120  }
3121 
3122  ret = nfs3_symlink(req, &dirfh, name, target,
3123  &args.symlink.symlink_attributes);
3124  if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
3126  "SYMLINK procedure failed");
3127  rpcsvc_request_seterr(req, SYSTEM_ERR);
3128  ret = RPCSVC_ACTOR_ERROR;
3129  }
3130 
3131 rpcerr:
3132  return ret;
3133 }
3134 
3135 static int
3137  struct iatt *buf, struct iatt *preparent,
3138  struct iatt *postparent)
3139 {
3140  mknod3res res = {
3141  0,
3142  };
3143  uint64_t deviceid = 0;
3144 
3145  deviceid = nfs3_request_xlator_deviceid(req);
3146  nfs3_fill_mknod3res(&res, stat, fh, buf, preparent, postparent, deviceid);
3147  nfs3svc_submit_reply(req, (void *)&res,
3149 
3150  return 0;
3151 }
3152 
3153 int32_t
3155  int32_t op_ret, int32_t op_errno, struct iatt *preop,
3156  struct iatt *postop, dict_t *xdata)
3157 {
3159  nfs3_call_state_t *cs = NULL;
3160 
3161  cs = frame->local;
3162  if (op_ret == -1) {
3163  stat = nfs3_cbk_errno_status(op_ret, op_errno);
3164  goto nfs3err;
3165  }
3166 
3167  stat = NFS3_OK;
3168 nfs3err:
3169  nfs3_log_newfh_res(rpcsvc_request_xid(cs->req), NFS3_MKNOD, stat, op_errno,
3170  &cs->fh, cs->resolvedloc.path);
3171  nfs3_mknod_reply(cs->req, stat, &cs->fh, postop, &cs->preparent,
3172  &cs->postparent);
3174  return 0;
3175 }
3176 
3177 int32_t
3178 nfs3svc_mknod_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
3179  int32_t op_ret, int32_t op_errno, inode_t *inode,
3180  struct iatt *buf, struct iatt *preparent,
3181  struct iatt *postparent, dict_t *xdata)
3182 {
3184  int ret = -1;
3185  nfs_user_t nfu = {
3186  0,
3187  };
3188  nfs3_call_state_t *cs = NULL;
3189 
3190  cs = frame->local;
3191  if (op_ret == -1) {
3192  stat = nfs3_cbk_errno_status(op_ret, op_errno);
3193  goto nfs3err;
3194  }
3195 
3196  nfs3_fh_build_child_fh(&cs->parent, buf, &cs->fh);
3197 
3198  /* Means no attributes were required to be set. */
3199  if (!cs->setattr_valid) {
3200  stat = NFS3_OK;
3201  ret = -1;
3202  goto nfs3err;
3203  }
3204 
3205  cs->preparent = *preparent;
3206  cs->postparent = *postparent;
3207  nfs_request_user_init(&nfu, cs->req);
3208  ret = nfs_setattr(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, &cs->stbuf,
3210  if (ret < 0)
3211  stat = nfs3_errno_to_nfsstat3(-ret);
3212 nfs3err:
3213  if (ret < 0) {
3215  op_errno, &cs->fh, cs->resolvedloc.path);
3216  nfs3_mknod_reply(cs->req, stat, &cs->fh, buf, preparent, postparent);
3218  }
3219 
3220  return 0;
3221 }
3222 
3223 static int
3225 {
3226  int ret = -EFAULT;
3227  dev_t devnum = 0;
3228  mode_t mode = 0;
3229  nfs_user_t nfu = {
3230  0,
3231  };
3232 
3233  if (!cs)
3234  return ret;
3235 
3236  devnum = makedev(cs->devnums.specdata1, cs->devnums.specdata2);
3237  if (cs->mknodtype == NF3CHR)
3238  mode = S_IFCHR;
3239  else
3240  mode = S_IFBLK;
3241 
3242  nfs_request_user_init(&nfu, cs->req);
3243  if (gf_attr_mode_set(cs->setattr_valid)) {
3245  mode |= cs->mode;
3246  ret = nfs_mknod(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, mode, devnum,
3247  nfs3svc_mknod_cbk, cs);
3248  } else
3249  ret = nfs_mknod(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, mode, devnum,
3250  nfs3svc_mknod_cbk, cs);
3251 
3252  return ret;
3253 }
3254 
3255 static int
3257 {
3258  int ret = -EFAULT;
3259  nfs_user_t nfu = {
3260  0,
3261  };
3262 
3263  if (!cs)
3264  return ret;
3265 
3266  nfs_request_user_init(&nfu, cs->req);
3267  if (gf_attr_mode_set(cs->setattr_valid)) {
3269  mode |= cs->mode;
3270  ret = nfs_mknod(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, mode, 0,
3271  nfs3svc_mknod_cbk, cs);
3272  } else
3273  ret = nfs_mknod(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, mode, 0,
3274  nfs3svc_mknod_cbk, cs);
3275 
3276  return ret;
3277 }
3278 
3279 static int
3281 {
3283  int ret = -EFAULT;
3284  nfs3_call_state_t *cs = NULL;
3285 
3286  if (!carg)
3287  return ret;
3288 
3289  cs = (nfs3_call_state_t *)carg;
3290  nfs3_check_new_fh_resolve_status(cs, stat, nfs3err);
3291  switch (cs->mknodtype) {
3292  case NF3CHR:
3293  case NF3BLK:
3294  ret = nfs3_mknod_device(cs);
3295  break;
3296  case NF3SOCK:
3297  ret = nfs3_mknod_fifo(cs, S_IFSOCK);
3298  break;
3299  case NF3FIFO:
3300  ret = nfs3_mknod_fifo(cs, S_IFIFO);
3301  break;
3302  default:
3303  ret = -EBADF;
3304  break;
3305  }
3306 
3307  if (ret < 0)
3308  stat = nfs3_errno_to_nfsstat3(-ret);
3309 
3310 nfs3err:
3311  if (ret < 0) {
3313  cs->resolvedloc.path);
3314  nfs3_mknod_reply(cs->req, stat, NULL, NULL, NULL, NULL);
3316  }
3317 
3318  return ret;
3319 }
3320 
3321 int
3322 nfs3_mknod(rpcsvc_request_t *req, struct nfs3_fh *fh, char *name,
3323  mknoddata3 *nodedata)
3324 {
3325  xlator_t *vol = NULL;
3327  int ret = -EFAULT;
3328  struct nfs3_state *nfs3 = NULL;
3329  nfs3_call_state_t *cs = NULL;
3330  sattr3 *sattr = NULL;
3331 
3332  if ((!req) || (!fh) || (!name) || (!nodedata)) {
3334  "Bad arguments");
3335  return -1;
3336  }
3337 
3338  nfs3_log_mknod_call(rpcsvc_request_xid(req), fh, name, nodedata->type);
3339  nfs3_validate_gluster_fh(fh, stat, nfs3err);
3340  nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
3341  nfs3_validate_strlen_or_goto(name, NFS_NAME_MAX, nfs3err, stat, ret);
3342  nfs3_map_fh_to_volume(nfs3, fh, req, vol, stat, nfs3err);
3343  nfs3_volume_started_check(nfs3, vol, ret, out);
3344  nfs3_check_rw_volaccess(nfs3, fh->exportid, stat, nfs3err);
3345  nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
3346 
3347  cs->mknodtype = nodedata->type;
3348  switch (nodedata->type) {
3349  case NF3CHR:
3350  case NF3BLK:
3351  cs->devnums = nodedata->mknoddata3_u.device.spec;
3352  sattr = &nodedata->mknoddata3_u.device.dev_attributes;
3354  &cs->mode);
3355  break;
3356  case NF3SOCK:
3357  case NF3FIFO:
3358  sattr = &nodedata->mknoddata3_u.pipe_attributes;
3360  &cs->mode);
3361  break;
3362  default:
3363  ret = -EBADF;
3364  goto nfs3err;
3365  }
3366 
3367  cs->parent = *fh;
3369  if (ret < 0)
3370  stat = nfs3_errno_to_nfsstat3(-ret);
3371 
3372 nfs3err:
3373  if (ret < 0) {
3375  cs ? cs->resolvedloc.path : NULL);
3376  nfs3_mknod_reply(req, stat, NULL, NULL, NULL, NULL);
3377  /* Ret must be 0 after this so that the caller does not
3378  * also send an RPC reply.
3379  */
3381  ret = 0;
3382  }
3383 out:
3384  return ret;
3385 }
3386 
3387 int
3389 {
3390  char name[NFS_PATH_MAX];
3391  struct nfs3_fh fh = {
3392  {0},
3393  };
3394  mknod3args args;
3395  int ret = RPCSVC_ACTOR_ERROR;
3396 
3397  if (!req)
3398  return ret;
3399  nfs3_prep_mknod3args(&args, &fh, name);
3400  if (xdr_to_mknod3args(req->msg[0], &args) <= 0) {
3402  "Error decoding args");
3403  rpcsvc_request_seterr(req, GARBAGE_ARGS);
3404  goto rpcerr;
3405  }
3406 
3407  ret = nfs3_mknod(req, &fh, name, &args.what);
3408  if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
3410  "MKNOD procedure failed");
3411  rpcsvc_request_seterr(req, SYSTEM_ERR);
3412  ret = RPCSVC_ACTOR_ERROR;
3413  }
3414 
3415 rpcerr:
3416  return ret;
3417 }
3418 
3419 int
3420 nfs3_remove_reply(rpcsvc_request_t *req, nfsstat3 stat, struct iatt *preparent,
3421  struct iatt *postparent)
3422 {
3423  remove3res res = {
3424  0,
3425  };
3426  uint64_t deviceid = 0;
3427 
3428  deviceid = nfs3_request_xlator_deviceid(req);
3429  nfs3_fill_remove3res(&res, stat, preparent, postparent, deviceid);
3430  nfs3svc_submit_reply(req, (void *)&res,
3432  return 0;
3433 }
3434 
3435 int32_t
3436 nfs3svc_remove_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
3437  int32_t op_ret, int32_t op_errno, struct iatt *preparent,
3438  struct iatt *postparent, dict_t *xdata)
3439 {
3441  nfs3_call_state_t *cs = NULL;
3442 
3443  cs = frame->local;
3444  if (op_ret == -1) {
3445  stat = nfs3_cbk_errno_status(op_ret, op_errno);
3446  }
3447 
3448  if (op_ret == 0)
3449  stat = NFS3_OK;
3450 
3452  op_errno, cs->resolvedloc.path);
3453  nfs3_remove_reply(cs->req, stat, preparent, postparent);
3455 
3456  return 0;
3457 }
3458 
3459 int
3461 {
3462  int ret = -EFAULT;
3463  nfs_user_t nfu = {
3464  0,
3465  };
3466  ia_type_t type = 0;
3467 
3468  if (!cs)
3469  return ret;
3470  type = cs->resolvedloc.inode->ia_type;
3471  nfs_request_user_init(&nfu, cs->req);
3472  if (IA_ISDIR(type))
3473  ret = nfs_rmdir(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
3474  nfs3svc_remove_cbk, cs);
3475  else
3476  ret = nfs_unlink(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
3477  nfs3svc_remove_cbk, cs);
3478 
3479  return ret;
3480 }
3481 
3482 int
3484 {
3486  int ret = -EFAULT;
3487  nfs3_call_state_t *cs = NULL;
3488 
3489  if (!carg)
3490  return ret;
3491 
3492  cs = (nfs3_call_state_t *)carg;
3493  nfs3_check_fh_resolve_status(cs, stat, nfs3err);
3494  ret = __nfs3_remove(cs);
3495  if (ret < 0)
3496  stat = nfs3_errno_to_nfsstat3(-ret);
3497 
3498 nfs3err:
3499  if (ret < 0) {
3501  -ret, cs->resolvedloc.path);
3502  nfs3_remove_reply(cs->req, stat, NULL, NULL);
3504  }
3505 
3506  return ret;
3507 }
3508 
3509 int
3510 nfs3_remove(rpcsvc_request_t *req, struct nfs3_fh *fh, char *name)
3511 {
3512  xlator_t *vol = NULL;
3514  int ret = -EFAULT;
3515  struct nfs3_state *nfs3 = NULL;
3516  nfs3_call_state_t *cs = NULL;
3517 
3518  if ((!req) || (!fh) || (!name)) {
3520  "Bad arguments");
3521  return -1;
3522  }
3523 
3524  nfs3_log_fh_entry_call(rpcsvc_request_xid(req), "REMOVE", fh, name);
3525  nfs3_validate_gluster_fh(fh, stat, nfs3err);
3526  nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
3527  nfs3_validate_strlen_or_goto(name, NFS_NAME_MAX, nfs3err, stat, ret);
3528  nfs3_map_fh_to_volume(nfs3, fh, req, vol, stat, nfs3err);
3529  nfs3_volume_started_check(nfs3, vol, ret, out);
3530  nfs3_check_rw_volaccess(nfs3, fh->exportid, stat, nfs3err);
3531  nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
3532 
3534  if (ret < 0)
3535  stat = nfs3_errno_to_nfsstat3(-ret);
3536 
3537 nfs3err:
3538  if (ret < 0) {
3540  cs ? cs->resolvedloc.path : NULL);
3541  nfs3_remove_reply(req, stat, NULL, NULL);
3543  /* Ret must be 0 after this so that the caller does not
3544  * also send an RPC reply.
3545  */
3546  ret = 0;
3547  }
3548 out:
3549  return ret;
3550 }
3551 
3552 int
3554 {
3555  char name[NFS_PATH_MAX];
3556  struct nfs3_fh fh = {
3557  {0},
3558  };
3559  remove3args args;
3560  int ret = RPCSVC_ACTOR_ERROR;
3561 
3562  if (!req)
3563  return ret;
3565  if (xdr_to_remove3args(req->msg[0], &args) <= 0) {
3567  "Error decoding args");
3568  rpcsvc_request_seterr(req, GARBAGE_ARGS);
3569  goto rpcerr;
3570  }
3571 
3572  ret = nfs3_remove(req, &fh, name);
3573  if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
3575  "REMOVE procedure failed");
3576  rpcsvc_request_seterr(req, SYSTEM_ERR);
3577  ret = RPCSVC_ACTOR_ERROR;
3578  }
3579 
3580 rpcerr:
3581  return ret;
3582 }
3583 
3584 int
3585 nfs3_rmdir_reply(rpcsvc_request_t *req, nfsstat3 stat, struct iatt *preparent,
3586  struct iatt *postparent)
3587 {
3588  rmdir3res res = {
3589  0,
3590  };
3591  uint64_t deviceid = 0;
3592 
3593  deviceid = nfs3_request_xlator_deviceid(req);
3594  nfs3_fill_rmdir3res(&res, stat, preparent, postparent, deviceid);
3595  nfs3svc_submit_reply(req, (void *)&res,
3597  return 0;
3598 }
3599 
3600 int32_t
3601 nfs3svc_rmdir_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
3602  int32_t op_ret, int32_t op_errno, struct iatt *preparent,
3603  struct iatt *postparent, dict_t *xdata)
3604 {
3606  nfs3_call_state_t *cs = NULL;
3607 
3608  cs = frame->local;
3609  if (op_ret == -1) {
3611  "%x: %s => -1 (%s)", rpcsvc_request_xid(cs->req),
3612  cs->resolvedloc.path, strerror(op_errno));
3613  stat = nfs3_cbk_errno_status(op_ret, op_errno);
3614  } else {
3615  stat = NFS3_OK;
3616  }
3617 
3618  nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_RMDIR, stat, op_errno,
3619  cs->resolvedloc.path);
3620  nfs3_rmdir_reply(cs->req, stat, preparent, postparent);
3622 
3623  return 0;
3624 }
3625 
3626 int
3628 {
3630  int ret = -EFAULT;
3631  nfs3_call_state_t *cs = NULL;
3632  nfs_user_t nfu = {
3633  0,
3634  };
3635 
3636  if (!carg)
3637  return ret;
3638 
3639  cs = (nfs3_call_state_t *)carg;
3640  nfs3_check_fh_resolve_status(cs, stat, nfs3err);
3641  nfs_request_user_init(&nfu, cs->req);
3642  ret = nfs_rmdir(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
3643  nfs3svc_rmdir_cbk, cs);
3644  if (ret < 0)
3645  stat = nfs3_errno_to_nfsstat3(-ret);
3646 
3647 nfs3err:
3648  if (ret < 0) {
3650  cs->resolvedloc.path);
3651  nfs3_rmdir_reply(cs->req, stat, NULL, NULL);
3653  }
3654 
3655  return ret;
3656 }
3657 
3658 int
3659 nfs3_rmdir(rpcsvc_request_t *req, struct nfs3_fh *fh, char *name)
3660 {
3661  xlator_t *vol = NULL;
3663  int ret = -EFAULT;
3664  struct nfs3_state *nfs3 = NULL;
3665  nfs3_call_state_t *cs = NULL;
3666 
3667  if ((!req) || (!fh) || (!name)) {
3669  "Bad arguments");
3670  return -1;
3671  }
3672 
3673  nfs3_log_fh_entry_call(rpcsvc_request_xid(req), "RMDIR", fh, name);
3674  nfs3_validate_gluster_fh(fh, stat, nfs3err);
3675  nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
3676  nfs3_validate_strlen_or_goto(name, NFS_NAME_MAX, nfs3err, stat, ret);
3677  nfs3_map_fh_to_volume(nfs3, fh, req, vol, stat, nfs3err);
3678  nfs3_volume_started_check(nfs3, vol, ret, out);
3679  nfs3_check_rw_volaccess(nfs3, fh->exportid, stat, nfs3err);
3680  nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
3681 
3683  if (ret < 0)
3684  stat = nfs3_errno_to_nfsstat3(-ret);
3685 
3686 nfs3err:
3687  if (ret < 0) {
3689  cs ? cs->resolvedloc.path : NULL);
3690  nfs3_rmdir_reply(req, stat, NULL, NULL);
3692  /* Ret must be 0 after this so that the caller does not
3693  * also send an RPC reply.
3694  */
3695  ret = 0;
3696  }
3697 out:
3698  return ret;
3699 }
3700 
3701 int
3703 {
3704  char name[NFS_PATH_MAX];
3705  struct nfs3_fh fh = {
3706  {0},
3707  };
3708  rmdir3args args;
3709  int ret = RPCSVC_ACTOR_ERROR;
3710 
3711  if (!req)
3712  return ret;
3713  nfs3_prep_rmdir3args(&args, &fh, name);
3714  if (xdr_to_rmdir3args(req->msg[0], &args) <= 0) {
3716  "Error decoding args");
3717  rpcsvc_request_seterr(req, GARBAGE_ARGS);
3718  goto rpcerr;
3719  }
3720 
3721  ret = nfs3_rmdir(req, &fh, name);
3722  if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
3724  "RMDIR procedure failed");
3725  rpcsvc_request_seterr(req, SYSTEM_ERR);
3726  ret = RPCSVC_ACTOR_ERROR;
3727  }
3728 
3729 rpcerr:
3730  return ret;
3731 }
3732 
3733 int
3735  struct iatt *preoldparent, struct iatt *postoldparent,
3736  struct iatt *prenewparent, struct iatt *postnewparent)
3737 {
3738  rename3res res = {
3739  0,
3740  };
3741  uint64_t deviceid = 0;
3742 
3743  deviceid = nfs3_request_xlator_deviceid(req);
3744  nfs3_fill_rename3res(&res, stat, buf, preoldparent, postoldparent,
3745  prenewparent, postnewparent, deviceid);
3746 
3747  nfs3svc_submit_reply(req, (void *)&res,
3749 
3750  return 0;
3751 }
3752 
3753 int32_t
3754 nfs3svc_rename_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
3755  int32_t op_ret, int32_t op_errno, struct iatt *buf,
3756  struct iatt *preoldparent, struct iatt *postoldparent,
3757  struct iatt *prenewparent, struct iatt *postnewparent,
3758  dict_t *xdata)
3759 {
3760  int ret = -EFAULT;
3762  nfs3_call_state_t *cs = NULL;
3763 
3764  cs = frame->local;
3765  if (op_ret == -1) {
3766  stat = nfs3_cbk_errno_status(op_ret, op_errno);
3767  goto nfs3err;
3768  }
3769 
3770  stat = NFS3_OK;
3771 nfs3err:
3773  cs->resolvedloc.path);
3774  nfs3_rename_reply(cs->req, stat, buf, preoldparent, postoldparent,
3775  prenewparent, postnewparent);
3777  return 0;
3778 }
3779 
3780 int
3782 {
3784  int ret = -EFAULT;
3785  nfs3_call_state_t *cs = NULL;
3786  nfs_user_t nfu = {
3787  0,
3788  };
3789 
3790  if (!carg)
3791  return ret;
3792 
3793  cs = (nfs3_call_state_t *)carg;
3794  nfs3_check_new_fh_resolve_status(cs, stat, nfs3err);
3795  cs->parent = cs->resolvefh;
3796  nfs_request_user_init(&nfu, cs->req);
3797  ret = nfs_rename(cs->nfsx, cs->vol, &nfu, &cs->oploc, &cs->resolvedloc,
3798  nfs3svc_rename_cbk, cs);
3799  if (ret < 0)
3800  stat = nfs3_errno_to_nfsstat3(-ret);
3801 
3802 nfs3err:
3803  if (ret < 0) {
3805  -ret, cs->resolvedloc.path);
3806  nfs3_rename_reply(cs->req, stat, NULL, NULL, NULL, NULL, NULL);
3808  }
3809 
3810  return ret;
3811 }
3812 
3813 int
3815 {
3817  int ret = -EFAULT;
3818  nfs3_call_state_t *cs = NULL;
3819 
3820  if (!carg)
3821  return ret;
3822 
3823  cs = (nfs3_call_state_t *)carg;
3824  nfs3_check_fh_resolve_status(cs, stat, nfs3err);
3825  /* Copy the resolved loc for the source file into another loc
3826  * for safekeeping till we resolve the dest loc.
3827  */
3828  nfs_loc_copy(&cs->oploc, &cs->resolvedloc);
3829  nfs_loc_wipe(&cs->resolvedloc);
3830  GF_FREE(cs->resolventry);
3831 
3832  ret = nfs3_fh_resolve_and_resume(cs, &cs->fh, cs->pathname,
3834  if (ret < 0)
3835  stat = nfs3_errno_to_nfsstat3(-ret);
3836 
3837 nfs3err:
3838  if (ret < 0) {
3840  -ret, cs->resolvedloc.path);
3841  nfs3_rename_reply(cs->req, stat, NULL, NULL, NULL, NULL, NULL);
3843  }
3844 
3845  return ret;
3846 }
3847 
3848 int
3849 nfs3_rename(rpcsvc_request_t *req, struct nfs3_fh *olddirfh, char *oldname,
3850  struct nfs3_fh *newdirfh, char *newname)
3851 {
3852  xlator_t *vol = NULL;
3854  int ret = -EFAULT;
3855  struct nfs3_state *nfs3 = NULL;
3856  nfs3_call_state_t *cs = NULL;
3857 
3858  if ((!req) || (!olddirfh) || (!oldname) || (!newdirfh) || (!newname)) {
3860  "Bad arguments");
3861  return -1;
3862  }
3863 
3864  nfs3_log_rename_call(rpcsvc_request_xid(req), olddirfh, oldname, newdirfh,
3865  newname);
3866  nfs3_validate_gluster_fh(olddirfh, stat, nfs3err);
3867  nfs3_validate_gluster_fh(newdirfh, stat, nfs3err);
3868  nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
3869  nfs3_validate_strlen_or_goto(oldname, NFS_NAME_MAX, nfs3err, stat, ret);
3870  nfs3_validate_strlen_or_goto(newname, NFS_NAME_MAX, nfs3err, stat, ret);
3871  nfs3_map_fh_to_volume(nfs3, olddirfh, req, vol, stat, nfs3err);
3872  nfs3_volume_started_check(nfs3, vol, ret, out);
3873  nfs3_check_rw_volaccess(nfs3, olddirfh->exportid, stat, nfs3err);
3874  nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
3875 
3876  /* While we resolve the source (fh, name) pair, we need to keep a copy
3877  * of the dest (fh,name) pair.
3878  */
3879  cs->fh = *newdirfh;
3880  cs->pathname = gf_strdup(newname);
3881  if (!cs->pathname) {
3882  stat = NFS3ERR_SERVERFAULT;
3883  ret = -1;
3884  goto nfs3err;
3885  }
3886 
3887  ret = nfs3_fh_resolve_and_resume(cs, olddirfh, oldname,
3889  if (ret < 0)
3890  stat = nfs3_errno_to_nfsstat3(-ret);
3891 
3892 nfs3err:
3893  if (ret < 0) {
3895  cs ? cs->resolvedloc.path : NULL);
3896  nfs3_rename_reply(req, stat, NULL, NULL, NULL, NULL, NULL);
3898  /* Ret must be 0 after this so that the caller does not
3899  * also send an RPC reply.
3900  */
3901  ret = 0;
3902  }
3903 out:
3904  return ret;
3905 }
3906 
3907 int
3909 {
3910  char newname[NFS_PATH_MAX];
3911  char oldname[NFS_PATH_MAX];
3912  struct nfs3_fh olddirfh = {
3913  {0},
3914  };
3915  struct nfs3_fh newdirfh = {
3916  {0},
3917  };
3918  rename3args args;
3919  int ret = RPCSVC_ACTOR_ERROR;
3920 
3921  if (!req)
3922  return ret;
3923  nfs3_prep_rename3args(&args, &olddirfh, oldname, &newdirfh, newname);
3924  if (xdr_to_rename3args(req->msg[0], &args) <= 0) {
3926  "Error decoding args");
3927  rpcsvc_request_seterr(req, GARBAGE_ARGS);
3928  goto rpcerr;
3929  }
3930 
3931  ret = nfs3_rename(req, &olddirfh, oldname, &newdirfh, newname);
3932  if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
3934  "RENAME procedure failed");
3935  rpcsvc_request_seterr(req, SYSTEM_ERR);
3936  ret = RPCSVC_ACTOR_ERROR;
3937  }
3938 
3939 rpcerr:
3940  return ret;
3941 }
3942 
3943 int
3945  struct iatt *preparent, struct iatt *postparent)
3946 {
3947  link3res res = {
3948  0,
3949  };
3950  uint64_t deviceid = 0;
3951 
3952  deviceid = nfs3_request_xlator_deviceid(req);
3953  nfs3_fill_link3res(&res, stat, buf, preparent, postparent, deviceid);
3954  nfs3svc_submit_reply(req, (void *)&res,
3956 
3957  return 0;
3958 }
3959 
3960 int32_t
3961 nfs3svc_link_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
3962  int32_t op_ret, int32_t op_errno, inode_t *inode,
3963  struct iatt *buf, struct iatt *preparent,
3964  struct iatt *postparent, dict_t *xdata)
3965 {
3967  nfs3_call_state_t *cs = NULL;
3968 
3969  cs = frame->local;
3970  if (op_ret == -1) {
3971  stat = nfs3_cbk_errno_status(op_ret, op_errno);
3972  } else
3973  stat = NFS3_OK;
3974 
3975  nfs3_log_common_res(rpcsvc_request_xid(cs->req), NFS3_LINK, stat, op_errno,
3976  cs->resolvedloc.path);
3977  nfs3_link_reply(cs->req, stat, buf, preparent, postparent);
3979 
3980  return 0;
3981 }
3982 
3983 int
3985 {
3987  int ret = -EFAULT;
3988  nfs3_call_state_t *cs = NULL;
3989  nfs_user_t nfu = {
3990  0,
3991  };
3992 
3993  if (!carg)
3994  return ret;
3995 
3996  cs = (nfs3_call_state_t *)carg;
3997  nfs3_check_new_fh_resolve_status(cs, stat, nfs3err);
3998 
3999  nfs_request_user_init(&nfu, cs->req);
4000  ret = nfs_link(cs->nfsx, cs->vol, &nfu, &cs->oploc, &cs->resolvedloc,
4001  nfs3svc_link_cbk, cs);
4002  if (ret < 0)
4003  stat = nfs3_errno_to_nfsstat3(-ret);
4004 
4005 nfs3err:
4006  if (ret < 0) {
4008  cs->resolvedloc.path);
4009  nfs3_link_reply(cs->req, stat, NULL, NULL, NULL);
4011  }
4012  return ret;
4013 }
4014 
4015 int
4017 {
4019  int ret = -EFAULT;
4020  nfs3_call_state_t *cs = NULL;
4021 
4022  if (!carg)
4023  return ret;
4024 
4025  cs = (nfs3_call_state_t *)carg;
4026  nfs3_check_fh_resolve_status(cs, stat, nfs3err);
4027  nfs_loc_copy(&cs->oploc, &cs->resolvedloc);
4028  nfs_loc_wipe(&cs->resolvedloc);
4029 
4030  ret = nfs3_fh_resolve_and_resume(cs, &cs->fh, cs->pathname,
4032  if (ret < 0)
4033  stat = nfs3_errno_to_nfsstat3(-ret);
4034 
4035 nfs3err:
4036  if (ret < 0) {
4038  cs->resolvedloc.path);
4039  nfs3_link_reply(cs->req, stat, NULL, NULL, NULL);
4041  }
4042 
4043  return ret;
4044 }
4045 
4046 int
4047 nfs3_link(rpcsvc_request_t *req, struct nfs3_fh *targetfh,
4048  struct nfs3_fh *dirfh, char *newname)
4049 {
4050  xlator_t *vol = NULL;
4052  int ret = -EFAULT;
4053  struct nfs3_state *nfs3 = NULL;
4054  nfs3_call_state_t *cs = NULL;
4055 
4056  if ((!req) || (!targetfh) || (!dirfh) || (!newname)) {
4058  "Bad arguments");
4059  return -1;
4060  }
4061 
4062  nfs3_validate_gluster_fh(dirfh, stat, nfs3err);
4063  nfs3_validate_gluster_fh(targetfh, stat, nfs3err);
4064  nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
4065  nfs3_validate_strlen_or_goto(newname, NFS_NAME_MAX, nfs3err, stat, ret);
4066  nfs3_map_fh_to_volume(nfs3, dirfh, req, vol, stat, nfs3err);
4067  nfs3_volume_started_check(nfs3, vol, ret, out);
4068  nfs3_check_rw_volaccess(nfs3, dirfh->exportid, stat, nfs3err);
4069  nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
4070 
4071  cs->fh = *dirfh;
4072  cs->pathname = gf_strdup(newname);
4073  if (!cs->pathname) {
4074  stat = NFS3ERR_SERVERFAULT;
4075  ret = -1;
4076  goto nfs3err;
4077  }
4078 
4079  ret = nfs3_fh_resolve_and_resume(cs, targetfh, NULL, nfs3_link_resume_tgt);
4080  if (ret < 0)
4081  stat = nfs3_errno_to_nfsstat3(-ret);
4082 
4083 nfs3err:
4084  if (ret < 0) {
4086  cs ? cs->pathname : NULL);
4087  nfs3_link_reply(req, stat, NULL, NULL, NULL);
4089  /* Ret must be 0 after this so that the caller does not
4090  * also send an RPC reply.
4091  */
4092  ret = 0;
4093  }
4094 out:
4095  return ret;
4096 }
4097 
4098 int
4100 {
4101  char newpath[NFS_PATH_MAX];
4102  struct nfs3_fh dirfh = {
4103  {0},
4104  };
4105  struct nfs3_fh targetfh = {
4106  {0},
4107  };
4108  link3args args;
4109  int ret = RPCSVC_ACTOR_ERROR;
4110 
4111  if (!req)
4112  return ret;
4113  nfs3_prep_link3args(&args, &targetfh, &dirfh, newpath);
4114  if (xdr_to_link3args(req->msg[0], &args) <= 0) {
4116  "Error decoding args");
4117  rpcsvc_request_seterr(req, GARBAGE_ARGS);
4118  goto rpcerr;
4119  }
4120 
4121  ret = nfs3_link(req, &targetfh, &dirfh, newpath);
4122  if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
4124  "LINK procedure failed");
4125  rpcsvc_request_seterr(req, SYSTEM_ERR);
4126  ret = RPCSVC_ACTOR_ERROR;
4127  }
4128 
4129 rpcerr:
4130  return ret;
4131 }
4132 
4133 int
4135  uint64_t cverf, struct iatt *dirstat, gf_dirent_t *entries,
4136  count3 dircount, count3 maxcount, int is_eof)
4137 {
4138  readdirp3res res = {
4139  0,
4140  };
4141  uint64_t deviceid = 0;
4142 
4143  deviceid = nfs3_request_xlator_deviceid(req);
4144  nfs3_fill_readdirp3res(&res, stat, dirfh, cverf, dirstat, entries, dircount,
4145  maxcount, is_eof, deviceid);
4146  nfs3svc_submit_reply(req, (void *)&res,
4148  nfs3_free_readdirp3res(&res);
4149 
4150  return 0;
4151 }
4152 
4153 int
4155  uint64_t cverf, struct iatt *dirstat, gf_dirent_t *entries,
4156  count3 count, int is_eof)
4157 {
4158  readdir3res res = {
4159  0,
4160  };
4161  uint64_t deviceid = 0;
4162 
4163  deviceid = nfs3_request_xlator_deviceid(req);
4164  nfs3_fill_readdir3res(&res, stat, dirfh, cverf, dirstat, entries, count,
4165  is_eof, deviceid);
4166  nfs3svc_submit_reply(req, (void *)&res,
4168  nfs3_free_readdir3res(&res);
4169 
4170  return 0;
4171 }
4172 
4173 int32_t
4175  int32_t op_ret, int32_t op_errno, struct iatt *buf,
4176  dict_t *xdata)
4177 {
4179  int is_eof = 0;
4180  nfs3_call_state_t *cs = NULL;
4181 
4182  cs = frame->local;
4183  if (op_ret == -1) {
4184  stat = nfs3_cbk_errno_status(op_ret, op_errno);
4185  goto nfs3err;
4186  }
4187 
4188  /* Check whether we encountered a end of directory stream while
4189  * readdir'ing.
4190  */
4191  if (cs->operrno == ENOENT) {
4192  gf_msg_trace(GF_NFS3, 0, "Reached end-of-directory");
4193  is_eof = 1;
4194  }
4195 
4196  stat = NFS3_OK;
4197 
4198  /* do inode linking here */
4199  gf_link_inodes_from_dirent(this, cs->fd->inode, &cs->entries);
4200 
4201 nfs3err:
4202  if (cs->maxcount == 0) {
4203  nfs3_log_readdir_res(rpcsvc_request_xid(cs->req), stat, op_errno,
4204  (uintptr_t)cs->fd, cs->dircount, is_eof,
4205  cs->resolvedloc.path);
4206  nfs3_readdir_reply(cs->req, stat, &cs->parent, (uintptr_t)cs->fd, buf,
4207  &cs->entries, cs->dircount, is_eof);
4208  } else {
4209  nfs3_log_readdirp_res(rpcsvc_request_xid(cs->req), stat, op_errno,
4210  (uintptr_t)cs->fd, cs->dircount, cs->maxcount,
4211  is_eof, cs->resolvedloc.path);
4212  nfs3_readdirp_reply(cs->req, stat, &cs->parent, (uintptr_t)cs->fd, buf,
4213  &cs->entries, cs->dircount, cs->maxcount, is_eof);
4214  }
4215 
4216  if (is_eof) {
4217  /* do nothing */
4218  }
4219 
4221  return 0;
4222 }
4223 
4224 int32_t
4225 nfs3svc_readdir_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
4226  int32_t op_ret, int32_t op_errno, gf_dirent_t *entries,
4227  dict_t *xdata)
4228 {
4230  int ret = -EFAULT;
4231  nfs_user_t nfu = {
4232  0,
4233  };
4234  nfs3_call_state_t *cs = NULL;
4235 
4236  cs = frame->local;
4237  if (op_ret == -1) {
4238  stat = nfs3_cbk_errno_status(op_ret, op_errno);
4239  goto err;
4240  }
4241 
4242  cs->operrno = op_errno;
4243  list_splice_init(&entries->list, &cs->entries.list);
4244  nfs_request_user_init(&nfu, cs->req);
4245  ret = nfs_fstat(cs->nfsx, cs->vol, &nfu, cs->fd, nfs3svc_readdir_fstat_cbk,
4246  cs);
4247  if (ret < 0) {
4248  op_ret = -1;
4249  stat = nfs3_errno_to_nfsstat3(-ret);
4250  op_errno = -ret;
4251  }
4252 
4253 err:
4254  if (op_ret >= 0)
4255  goto ret;
4256 
4257  if (cs->maxcount == 0) {
4259  op_errno, cs->resolvedloc.path);
4260  nfs3_readdir_reply(cs->req, stat, NULL, 0, NULL, NULL, 0, 0);
4261  } else {
4263  op_errno, cs->resolvedloc.path);
4264  nfs3_readdirp_reply(cs->req, stat, NULL, 0, NULL, NULL, 0, 0, 0);
4265  }
4266 
4267  /* For directories, we force a purge from the fd cache on close
4268  * so that next time the dir is read, we'll get any changed directory
4269  * entries.
4270  */
4272 ret:
4273  return 0;
4274 }
4275 
4276 int
4278 {
4279  int ret = -EFAULT;
4280  nfs_user_t nfu = {
4281  0,
4282  };
4283 
4284  if (!cs)
4285  return ret;
4286 
4287  nfs_request_user_init(&nfu, cs->req);
4288  ret = nfs_readdirp(cs->nfsx, cs->vol, &nfu, cs->fd, cs->dircount,
4289  cs->cookie, nfs3svc_readdir_cbk, cs);
4290  return ret;
4291 }
4292 
4293 int
4295 {
4297  int ret = -EFAULT;
4298  nfs3_call_state_t *cs = NULL;
4299  struct nfs3_state *nfs3 = NULL;
4300 
4301  if (!carg)
4302  return ret;
4303 
4304  cs = (nfs3_call_state_t *)carg;
4305  nfs3_check_fh_resolve_status(cs, stat, nfs3err);
4306  nfs3 = rpcsvc_request_program_private(cs->req);
4307  ret = nfs3_verify_dircookie(nfs3, cs->fd, cs->cookie, cs->cookieverf,
4308  &stat);
4309  if (ret < 0) /* Stat already set by verifier function above. */
4310  goto nfs3err;
4311 
4312  ret = nfs3_readdir_process(cs);
4313  if (ret < 0)
4314  stat = nfs3_errno_to_nfsstat3(-ret);
4315 nfs3err:
4316  if (ret < 0) {
4317  if (cs->maxcount == 0) {
4319  -ret, cs->resolvedloc.path);
4320  nfs3_readdir_reply(cs->req, stat, NULL, 0, NULL, NULL, 0, 0);
4321  } else {
4323  stat, -ret, cs->resolvedloc.path);
4324  nfs3_readdirp_reply(cs->req, stat, NULL, 0, NULL, NULL, 0, 0, 0);
4325  }
4327  }
4328 
4329  return 0;
4330 }
4331 
4332 int32_t
4334  int32_t op_ret, int32_t op_errno, fd_t *fd,
4335  dict_t *xdata)
4336 {
4337  /*
4338  * We don't really need this, it's just an artifact of forcing the
4339  * opendir to happen.
4340  */
4341  if (fd) {
4342  fd_unref(fd);
4343  }
4344 
4345  return 0;
4346 }
4347 
4348 int
4350 {
4352  int ret = -EFAULT;
4353  nfs3_call_state_t *cs = NULL;
4354  nfs_user_t nfu = {
4355  0,
4356  };
4357 
4358  if (!carg)
4359  return ret;
4360 
4361  cs = (nfs3_call_state_t *)carg;
4362  nfs3_check_fh_resolve_status(cs, stat, nfs3err);
4363  cs->fd = fd_anonymous(cs->resolvedloc.inode);
4364  if (!cs->fd) {
4366  "Fail to create anonymous fd");
4367  goto nfs3err;
4368  }
4369 
4370  /*
4371  * NFS client will usually send us a readdirp without an opendir,
4372  * which would cause us to skip our usual self-heal checks which occur
4373  * in opendir for native protocol. To make sure those checks do happen,
4374  * our most reliable option is to do our own opendir for any readdirp
4375  * at the beginning of the directory.
4376  */
4377  if (cs->cookie == 0) {
4378  nfs_request_user_init(&nfu, cs->req);
4379  ret = nfs_opendir(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
4381  if (ret < 0) {
4383  "auto-opendir failed");
4384  }
4385  }
4386 
4387  ret = nfs3_readdir_read_resume(cs);
4388  if (ret < 0)
4389  stat = nfs3_errno_to_nfsstat3(-ret);
4390 
4391 nfs3err:
4392  if (ret < 0) {
4393  if (cs->maxcount == 0) {
4395  -ret, cs->resolvedloc.path);
4396  nfs3_readdir_reply(cs->req, stat, NULL, 0, NULL, NULL, 0, 0);
4397  } else {
4399  stat, -ret, cs->resolvedloc.path);
4400  nfs3_readdirp_reply(cs->req, stat, NULL, 0, NULL, NULL, 0, 0, 0);
4401  }
4403  }
4404 
4405  return ret;
4406 }
4407 
4408 int
4410  uint64_t cverf, count3 dircount, count3 maxcount)
4411 {
4412  xlator_t *vol = NULL;
4414  int ret = -EFAULT;
4415  struct nfs3_state *nfs3 = NULL;
4416  nfs3_call_state_t *cs = NULL;
4417  struct nfs_state *nfs = NULL;
4418  gf_boolean_t is_readdirp = !!maxcount;
4419 
4420  if ((!req) || (!fh)) {
4422  "Bad arguments");
4423  return -1;
4424  }
4425 
4426  nfs3_log_readdir_call(rpcsvc_request_xid(req), fh, dircount, maxcount);
4427  nfs3_validate_gluster_fh(fh, stat, nfs3err);
4428  nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
4429  nfs3_map_fh_to_volume(nfs3, fh, req, vol, stat, nfs3err);
4430  nfs3_volume_started_check(nfs3, vol, ret, out);
4431  nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
4432  nfs = nfs_state(nfs3->nfsx);
4433 
4434  if (is_readdirp && !nfs->rdirplus) {
4435  ret = -ENOTSUP;
4436  stat = nfs3_errno_to_nfsstat3(-ret);
4437  goto nfs3err;
4438  }
4439 
4440  cs->cookieverf = cverf;
4441  cs->dircount = dircount;
4442  cs->maxcount = maxcount;
4443  cs->cookie = cookie;
4444  cs->parent = *fh;
4446  if (ret < 0)
4447  stat = nfs3_errno_to_nfsstat3(-ret);
4448 
4449 nfs3err:
4450  if (ret < 0) {
4451  if (!is_readdirp) {
4453  -ret, cs ? cs->resolvedloc.path : NULL);
4454  nfs3_readdir_reply(req, stat, NULL, 0, NULL, NULL, 0, 0);
4455  } else {
4457  -ret, cs ? cs->resolvedloc.path : NULL);
4458  nfs3_readdirp_reply(req, stat, NULL, 0, NULL, NULL, 0, 0, 0);
4459  }
4460  /* Ret must be NULL after this so that the caller does not
4461  * also send an RPC reply.
4462  */
4463  ret = 0;
4465  }
4466 out:
4467  return ret;
4468 }
4469 
4470 int
4472 {
4473  readdir3args ra;
4474  struct nfs3_fh fh = {
4475  {0},
4476  };
4477  int ret = RPCSVC_ACTOR_ERROR;
4478  uint64_t verf = 0;
4479  uint64_t *cval;
4480 
4481  if (!req)
4482  return ret;
4483  nfs3_prep_readdir3args(&ra, &fh);
4484  if (xdr_to_readdir3args(req->msg[0], &ra) <= 0) {
4486  "Error decoding args");
4487  rpcsvc_request_seterr(req, GARBAGE_ARGS);
4488  goto rpcerr;
4489  }
4490  cval = (uint64_t *)ra.cookieverf;
4491  verf = *cval;
4492 
4493  ret = nfs3_readdir(req, &fh, ra.cookie, verf, ra.count, 0);
4494  if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
4496  "READDIR procedure failed");
4497  rpcsvc_request_seterr(req, SYSTEM_ERR);
4498  ret = RPCSVC_ACTOR_ERROR;
4499  }
4500 
4501 rpcerr:
4502  return ret;
4503 }
4504 
4505 int
4507 {
4508  readdirp3args ra;
4509  struct nfs3_fh fh = {
4510  {0},
4511  };
4512  int ret = RPCSVC_ACTOR_ERROR;
4513  uint64_t cverf = 0;
4514  uint64_t *cval;
4515 
4516  if (!req)
4517  return ret;
4518  nfs3_prep_readdirp3args(&ra, &fh);
4519  if (xdr_to_readdirp3args(req->msg[0], &ra) <= 0) {
4521  "Error decoding args");
4522  rpcsvc_request_seterr(req, GARBAGE_ARGS);
4523  goto rpcerr;
4524  }
4525  cval = (uint64_t *)ra.cookieverf;
4526  cverf = *cval;
4527 
4528  ret = nfs3_readdir(req, &fh, ra.cookie, cverf, ra.dircount, ra.maxcount);
4529  if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
4531  "READDIRP procedure failed");
4532  rpcsvc_request_seterr(req, SYSTEM_ERR);
4533  ret = RPCSVC_ACTOR_ERROR;
4534  }
4535 
4536 rpcerr:
4537  return ret;
4538 }
4539 
4540 int
4541 nfs3_fsstat_reply(rpcsvc_request_t *req, nfsstat3 stat, struct statvfs *fsbuf,
4542  struct iatt *postbuf)
4543 {
4544  fsstat3res res = {
4545  0,
4546  };
4547  uint64_t deviceid = 0;
4548 
4549  deviceid = nfs3_request_xlator_deviceid(req);
4550  nfs3_fill_fsstat3res(&res, stat, fsbuf, postbuf, deviceid);
4551  return nfs3svc_submit_reply(req, &res,
4553 }
4554 
4555 int32_t
4556 nfs3_fsstat_stat_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
4557  int32_t op_ret, int32_t op_errno, struct iatt *buf,
4558  dict_t *xdata)
4559 {
4561  nfs3_call_state_t *cs = NULL;
4562 
4563  cs = frame->local;
4564  if (op_ret == -1) {
4565  stat = nfs3_cbk_errno_status(op_ret, op_errno);
4566  } else
4567  stat = NFS3_OK;
4568 
4570  op_errno, cs->resolvedloc.path);
4571  nfs3_fsstat_reply(cs->req, stat, &cs->fsstat, buf);
4573  return 0;
4574 }
4575 
4576 int32_t
4577 nfs3_fsstat_statfs_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
4578  int32_t op_ret, int32_t op_errno, struct statvfs *buf,
4579  dict_t *xdata)
4580 {
4581  nfs_user_t nfu = {
4582  0,
4583  };
4584  int ret = -EFAULT;
4586  nfs3_call_state_t *cs = NULL;
4587 
4588  cs = frame->local;
4589  if (op_ret == -1) {
4590  ret = -op_errno;
4591  stat = nfs3_cbk_errno_status(op_ret, op_errno);
4592  goto err;
4593  }
4594 
4595  /* Then get the stat for the fs root in order to fill in the
4596  * post_op_attr.
4597  */
4598  cs->fsstat = *buf;
4599  nfs_request_user_init(&nfu, cs->req);
4600  ret = nfs_stat(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
4601  nfs3_fsstat_stat_cbk, cs);
4602  if (ret < 0)
4603  stat = nfs3_errno_to_nfsstat3(-ret);
4604 
4605 err:
4606  if (ret < 0) {
4608  -ret, cs->resolvedloc.path);
4609  nfs3_fsstat_reply(cs->req, stat, NULL, NULL);
4611  }
4612 
4613  return 0;
4614 }
4615 
4616 int
4618 {
4620  int ret = -EFAULT;
4621  nfs3_call_state_t *cs = NULL;
4622  nfs_user_t nfu = {
4623  0,
4624  };
4625 
4626  if (!carg)
4627  return ret;
4628 
4629  cs = (nfs3_call_state_t *)carg;
4630  nfs3_check_fh_resolve_status(cs, stat, nfs3err);
4631  nfs_request_user_init(&nfu, cs->req);
4632  /* First, we need to get the statvfs for the subvol */
4633  ret = nfs_statfs(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
4635  if (ret < 0)
4636  stat = nfs3_errno_to_nfsstat3(-ret);
4637 
4638 nfs3err:
4639  if (ret < 0) {
4641  -ret, cs->resolvedloc.path);
4642  nfs3_fsstat_reply(cs->req, stat, NULL, NULL);
4644  }
4645 
4646  return ret;
4647 }
4648 
4649 int
4651 {
4652  xlator_t *vol = NULL;
4654  int ret = -EFAULT;
4655  struct nfs3_state *nfs3 = NULL;
4656  nfs3_call_state_t *cs = NULL;
4657 
4658  if ((!req) || (!fh)) {
4660  "Bad arguments");
4661  return -1;
4662  }
4663 
4664  nfs3_log_common_call(rpcsvc_request_xid(req), "FSSTAT", fh);
4665  nfs3_validate_gluster_fh(fh, stat, nfs3err);
4666  nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
4667  nfs3_map_fh_to_volume(nfs3, fh, req, vol, stat, nfs3err);
4668  nfs3_volume_started_check(nfs3, vol, ret, out);
4669  nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
4670 
4671  ret = nfs3_fh_resolve_and_resume(cs, fh, NULL, nfs3_fsstat_resume);
4672  if (ret < 0)
4673  stat = nfs3_errno_to_nfsstat3(-ret);
4674 
4675 nfs3err:
4676  if (ret < 0) {
4678  cs ? cs->resolvedloc.path : NULL);
4679  nfs3_fsstat_reply(req, stat, NULL, NULL);
4681  /* Ret must be 0 after this so that the caller does not
4682  * also send an RPC reply.
4683  */
4684  ret = 0;
4685  }
4686 out:
4687  return ret;
4688 }
4689 
4690 int
4692 {
4693  struct nfs3_fh fh = {
4694  {0},
4695  };
4696  fsstat3args args;
4697  int ret = RPCSVC_ACTOR_ERROR;
4698 
4699  if (!req)
4700  return ret;
4701  nfs3_prep_fsstat3args(&args, &fh);
4702  if (xdr_to_fsstat3args(req->msg[0], &args) <= 0) {
4704  "Error decoding args");
4705  rpcsvc_request_seterr(req, GARBAGE_ARGS);
4706  goto rpcerr;
4707  }
4708 
4709  ret = nfs3_fsstat(req, &fh);
4710  if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
4712  "FSTAT procedure failed");
4713  rpcsvc_request_seterr(req, SYSTEM_ERR);
4714  ret = RPCSVC_ACTOR_ERROR;
4715  }
4716 
4717 rpcerr:
4718  return ret;
4719 }
4720 
4721 int
4722 nfs3_fsinfo_reply(rpcsvc_request_t *req, nfsstat3 status, struct iatt *fsroot)
4723 {
4724  fsinfo3res res;
4725  struct nfs3_state *nfs3 = NULL;
4726  uint64_t deviceid = 0;
4727 
4728  deviceid = nfs3_request_xlator_deviceid(req);
4729  nfs3 = rpcsvc_request_program_private(req);
4730  nfs3_fill_fsinfo3res(nfs3, &res, status, fsroot, deviceid);
4731 
4733  return 0;
4734 }
4735 
4736 int32_t
4737 nfs3svc_fsinfo_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
4738  int32_t op_ret, int32_t op_errno, struct iatt *buf,
4739  dict_t *xdata)
4740 {
4741  nfsstat3 status = NFS3ERR_SERVERFAULT;
4742  nfs3_call_state_t *cs = NULL;
4743 
4744  cs = frame->local;
4745 
4746  if (op_ret == -1) {
4747  status = nfs3_cbk_errno_status(op_ret, op_errno);
4748  } else
4749  status = NFS3_OK;
4750 
4752  op_errno, cs->resolvedloc.path);
4753 
4754  nfs3_fsinfo_reply(cs->req, status, buf);
4756 
4757  return 0;
4758 }
4759 
4760 int
4762 {
4764  int ret = -EFAULT;
4765  nfs_user_t nfu = {
4766  0,
4767  };
4768  nfs3_call_state_t *cs = NULL;
4769 
4770  if (!carg)
4771  return ret;
4772 
4773  cs = (nfs3_call_state_t *)carg;
4774  nfs3_check_fh_resolve_status(cs, stat, nfs3err);
4775  nfs_request_user_init(&nfu, cs->req);
4776 
4777  ret = nfs_stat(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
4778  nfs3svc_fsinfo_cbk, cs);
4779  if (ret < 0)
4780  stat = nfs3_errno_to_nfsstat3(-ret);
4781 
4782 nfs3err:
4783  if (ret < 0) {
4785  -ret, cs->resolvedloc.path);
4786  nfs3_fsinfo_reply(cs->req, stat, NULL);
4788  }
4789 
4790  return ret;
4791 }
4792 
4793 int
4795 {
4796  xlator_t *vol = NULL;
4798  int ret = -EFAULT;
4799  struct nfs3_state *nfs3 = NULL;
4800  nfs3_call_state_t *cs = NULL;
4801 
4802  if ((!req) || (!fh)) {
4804  "Bad arguments");
4805  return -1;
4806  }
4807 
4808  nfs3_log_common_call(rpcsvc_request_xid(req), "FSINFO", fh);
4809  nfs3_validate_gluster_fh(fh, stat, nfs3err);
4810  nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
4811  nfs3_map_fh_to_volume(nfs3, fh, req, vol, stat, nfs3err);
4812  nfs3_volume_started_check(nfs3, vol, ret, out);
4813  nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
4814 
4815  ret = nfs3_fh_resolve_and_resume(cs, fh, NULL, nfs3_fsinfo_resume);
4816  if (ret < 0)
4817  stat = nfs3_errno_to_nfsstat3(-ret);
4818 
4819 nfs3err:
4820  if (ret < 0) {
4822  cs ? cs->resolvedloc.path : NULL);
4823  nfs3_fsinfo_reply(req, stat, NULL);
4825  ret = 0;
4826  }
4827 out:
4828  return ret;
4829 }
4830 
4831 int
4833 {
4834  int ret = RPCSVC_ACTOR_ERROR;
4835  fsinfo3args args;
4836  struct nfs3_fh root = {
4837  {0},
4838  };
4839 
4840  if (!req)
4841  return ret;
4842 
4843  nfs3_prep_fsinfo3args(&args, &root);
4844  if (xdr_to_fsinfo3args(req->msg[0], &args) <= 0) {
4846  "Error decoding arguments");
4847  rpcsvc_request_seterr(req, GARBAGE_ARGS);
4848  goto rpcerr;
4849  }
4850 
4851  ret = nfs3_fsinfo(req, &root);
4852  if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
4854  "FSINFO procedure failed");
4855  rpcsvc_request_seterr(req, SYSTEM_ERR);
4856  ret = RPCSVC_ACTOR_ERROR;
4857  }
4858 
4859 rpcerr:
4860  return ret;
4861 }
4862 
4863 int
4865 {
4866  pathconf3res res = {
4867  0,
4868  };
4869  uint64_t deviceid = 0;
4870 
4871  deviceid = nfs3_request_xlator_deviceid(req);
4872  nfs3_fill_pathconf3res(&res, stat, buf, deviceid);
4873  nfs3svc_submit_reply(req, (void *)&res,
4875  return 0;
4876 }
4877 
4878 int32_t
4879 nfs3svc_pathconf_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
4880  int32_t op_ret, int32_t op_errno, struct iatt *buf,
4881  dict_t *xdata)
4882 {
4883  struct iatt *sbuf = NULL;
4884  nfs3_call_state_t *cs = NULL;
4886 
4887  cs = frame->local;
4888  if (op_ret == -1) {
4889  stat = nfs3_cbk_errno_status(op_ret, op_errno);
4890  } else {
4891  /* If stat fop failed, we can still send the other components
4892  * in a pathconf reply.
4893  */
4894  sbuf = buf;
4895  stat = NFS3_OK;
4896  }
4897 
4899  op_errno, cs->resolvedloc.path);
4900  nfs3_pathconf_reply(cs->req, stat, sbuf);
4902 
4903  return 0;
4904 }
4905 
4906 int
4908 {
4910  int ret = -EFAULT;
4911  nfs_user_t nfu = {
4912  0,
4913  };
4914  nfs3_call_state_t *cs = NULL;
4915 
4916  if (!carg)
4917  return ret;
4918 
4919  cs = (nfs3_call_state_t *)carg;
4920  nfs3_check_fh_resolve_status(cs, stat, nfs3err);
4921  nfs_request_user_init(&nfu, cs->req);
4922  ret = nfs_stat(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
4923  nfs3svc_pathconf_cbk, cs);
4924  if (ret < 0)
4925  stat = nfs3_errno_to_nfsstat3(-ret);
4926 nfs3err:
4927  if (ret < 0) {
4929  -ret, cs->resolvedloc.path);
4930  nfs3_pathconf_reply(cs->req, stat, NULL);
4932  }
4933 
4934  return ret;
4935 }
4936 
4937 int
4939 {
4940  xlator_t *vol = NULL;
4942  int ret = -EFAULT;
4943  struct nfs3_state *nfs3 = NULL;
4944  nfs3_call_state_t *cs = NULL;
4945 
4946  if ((!req) || (!fh)) {
4948  "Bad arguments");
4949  return -1;
4950  }
4951 
4952  nfs3_log_common_call(rpcsvc_request_xid(req), "PATHCONF", fh);
4953  nfs3_validate_gluster_fh(fh, stat, nfs3err);
4954  nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
4955  nfs3_map_fh_to_volume(nfs3, fh, req, vol, stat, nfs3err);
4956  nfs3_volume_started_check(nfs3, vol, ret, out);
4957  nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
4958 
4959  ret = nfs3_fh_resolve_and_resume(cs, fh, NULL, nfs3_pathconf_resume);
4960  if (ret < 0)
4961  stat = nfs3_errno_to_nfsstat3(-ret);
4962 
4963 nfs3err:
4964  if (ret < 0) {
4966  cs ? cs->resolvedloc.path : NULL);
4967  nfs3_pathconf_reply(req, stat, NULL);
4969  /* Ret must be 0 after this so that the caller does not
4970  * also send an RPC reply.
4971  */
4972  ret = 0;
4973  }
4974 out:
4975  return ret;
4976 }
4977 
4978 int
4980 {
4981  struct nfs3_fh fh = {
4982  {0},
4983  };
4985  int ret = RPCSVC_ACTOR_ERROR;
4986 
4987  if (!req)
4988  return ret;
4990  if (xdr_to_pathconf3args(req->msg[0], &args) <= 0) {
4992  "Error decoding args");
4993  rpcsvc_request_seterr(req, GARBAGE_ARGS);
4994  goto rpcerr;
4995  }
4996 
4997  ret = nfs3_pathconf(req, &fh);
4998  if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
5000  "PATHCONF procedure failed");
5001  rpcsvc_request_seterr(req, SYSTEM_ERR);
5002  ret = RPCSVC_ACTOR_ERROR;
5003  }
5004 
5005 rpcerr:
5006  return ret;
5007 }
5008 
5009 int
5010 nfs3_commit_reply(rpcsvc_request_t *req, nfsstat3 stat, uint64_t wverf,
5011  struct iatt *prestat, struct iatt *poststat)
5012 {
5013  commit3res res = {
5014  0,
5015  };
5016  uint64_t deviceid = 0;
5017 
5018  deviceid = nfs3_request_xlator_deviceid(req);
5019  nfs3_fill_commit3res(&res, stat, wverf, prestat, poststat, deviceid);
5020  nfs3svc_submit_reply(req, (void *)&res,
5022 
5023  return 0;
5024 }
5025 
5026 int32_t
5027 nfs3svc_commit_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
5028  int32_t op_ret, int32_t op_errno, dict_t *xdata)
5029 {
5031  nfs3_call_state_t *cs = NULL;
5032  struct nfs3_state *nfs3 = NULL;
5033 
5034  cs = frame->local;
5035  if (op_ret == -1) {
5036  stat = nfs3_cbk_errno_status(op_ret, op_errno);
5037  } else
5038  stat = NFS3_OK;
5039 
5040  nfs3 = rpcsvc_request_program_private(cs->req);
5041  nfs3_log_commit_res(rpcsvc_request_xid(cs->req), stat, op_errno,
5042  nfs3->serverstart, cs->resolvedloc.path);
5043  nfs3_commit_reply(cs->req, stat, nfs3->serverstart, NULL, NULL);
5045 
5046  return 0;
5047 }
5048 
5049 int
5051 {
5053  int ret = -EFAULT;
5054  nfs_user_t nfu = {
5055  0,
5056  };
5057  nfs3_call_state_t *cs = NULL;
5058 
5059  if (!carg)
5060  return ret;
5061 
5062  cs = (nfs3_call_state_t *)carg;
5063  nfs3_check_fh_resolve_status(cs, stat, nfs3err);
5064 
5066  ret = -1;
5067  stat = NFS3_OK;
5068  goto nfs3err;
5069  }
5070 
5071  nfs_request_user_init(&nfu, cs->req);
5072  ret = nfs_flush(cs->nfsx, cs->vol, &nfu, cs->fd, nfs3svc_commit_cbk, cs);
5073  if (ret < 0)
5074  stat = nfs3_errno_to_nfsstat3(-ret);
5075 
5076 nfs3err:
5077  if (ret < 0) {
5079  -ret, cs->resolvedloc.path);
5080  nfs3_commit_reply(cs->req, stat, cs->nfs3state->serverstart, NULL,
5081  NULL);
5083  ret = 0;
5084  }
5085 
5086  return 0;
5087 }
5088 
5089 int
5091 {
5093  int ret = -EFAULT;
5094  nfs3_call_state_t *cs = NULL;
5095 
5096  if (!carg)
5097  return ret;
5098 
5099  cs = (nfs3_call_state_t *)carg;
5100  nfs3_check_fh_resolve_status(cs, stat, nfs3err);
5101  cs->fd = fd_anonymous(cs->resolvedloc.inode);
5102  if (!cs->fd) {
5104  "Failed to create anonymous fd.");
5105  goto nfs3err;
5106  }
5107 
5108  ret = nfs3_commit_resume(cs);
5109  if (ret < 0)
5110  stat = nfs3_errno_to_nfsstat3(-ret);
5111 nfs3err:
5112  if (ret < 0) {
5114  -ret, cs->resolvedloc.path);
5115  nfs3_commit_reply(cs->req, stat, 0, NULL, NULL);
5117  }
5118 
5119  return ret;
5120 }
5121 
5122 int
5123 nfs3_commit(rpcsvc_request_t *req, struct nfs3_fh *fh, offset3 offset,
5124  count3 count)
5125 {
5126  xlator_t *vol = NULL;
5128  int ret = -EFAULT;
5129  struct nfs3_state *nfs3 = NULL;
5130  nfs3_call_state_t *cs = NULL;
5131 
5132  if ((!req) || (!fh)) {
5134  "Bad arguments");
5135  return -1;
5136  }
5137 
5138  nfs3_log_rw_call(rpcsvc_request_xid(req), "COMMIT", fh, offset, count, -1);
5139  nfs3_validate_gluster_fh(fh, stat, nfs3err);
5140  nfs3_validate_nfs3_state(req, nfs3, stat, nfs3err, ret);
5141  nfs3_map_fh_to_volume(nfs3, fh, req, vol, stat, nfs3err);
5142  nfs3_volume_started_check(nfs3, vol, ret, out);
5143  nfs3_check_rw_volaccess(nfs3, fh->exportid, stat, nfs3err);
5144  nfs3_handle_call_state_init(nfs3, cs, req, vol, stat, nfs3err);
5145 
5146  cs->datacount = count;
5147  cs->dataoffset = offset;
5149  if (ret < 0)
5150  stat = nfs3_errno_to_nfsstat3(-ret);
5151 
5152 nfs3err:
5153  if (ret < 0) {
5155  cs ? cs->resolvedloc.path : NULL);
5156  nfs3_commit_reply(req, stat, 0, NULL, NULL);
5158  ret = 0;
5159  }
5160 out:
5161  return ret;
5162 }
5163 
5164 int
5166 {
5167  struct nfs3_fh fh = {
5168  {0},
5169  };
5170  commit3args args;
5171  int ret = RPCSVC_ACTOR_ERROR;
5172 
5173  if (!req)
5174  return ret;
5175  nfs3_prep_commit3args(&args, &fh);
5176  if (xdr_to_commit3args(req->msg[0], &args) <= 0) {
5178  "Error decoding args");
5179  rpcsvc_request_seterr(req, GARBAGE_ARGS);
5180  goto rpcerr;
5181  }
5182 
5183  ret = nfs3_commit(req, &fh, args.offset, args.count);
5184  if ((ret < 0) && (ret != RPCSVC_ACTOR_IGNORE)) {
5186  "COMMIT procedure failed");
5187  rpcsvc_request_seterr(req, SYSTEM_ERR);
5188  ret = RPCSVC_ACTOR_ERROR;
5189  }
5190 
5191 rpcerr:
5192  return ret;
5193 }
5194 
5196  {"NULL", nfs3svc_null, NULL, NFS3_NULL, DRC_IDEMPOTENT, 0},
5197  {"GETATTR", nfs3svc_getattr, NULL, NFS3_GETATTR, DRC_IDEMPOTENT, 0},
5198  {"SETATTR", nfs3svc_setattr, NULL, NFS3_SETATTR, DRC_NON_IDEMPOTENT, 0},
5199  {"LOOKUP", nfs3svc_lookup, NULL, NFS3_LOOKUP, DRC_IDEMPOTENT, 0},
5200  {"ACCESS", nfs3svc_access, NULL, NFS3_ACCESS, DRC_IDEMPOTENT, 0},
5201  {"READLINK", nfs3svc_readlink, NULL, NFS3_READLINK, DRC_IDEMPOTENT, 0},
5202  {"READ", nfs3svc_read, NULL, NFS3_READ, DRC_IDEMPOTENT, 0},
5204  0},
5205  {"CREATE", nfs3svc_create, NULL, NFS3_CREATE, DRC_NON_IDEMPOTENT, 0},
5206  {"MKDIR", nfs3svc_mkdir, NULL, NFS3_MKDIR, DRC_NON_IDEMPOTENT, 0},
5207  {"SYMLINK", nfs3svc_symlink, NULL, NFS3_SYMLINK, DRC_NON_IDEMPOTENT, 0},
5208  {"MKNOD", nfs3svc_mknod, NULL, NFS3_MKNOD, DRC_NON_IDEMPOTENT, 0},
5209  {"REMOVE", nfs3svc_remove, NULL, NFS3_REMOVE, DRC_NON_IDEMPOTENT, 0},
5210  {"RMDIR", nfs3svc_rmdir, NULL, NFS3_RMDIR, DRC_NON_IDEMPOTENT, 0},
5211  {"RENAME", nfs3svc_rename, NULL, NFS3_RENAME, DRC_NON_IDEMPOTENT, 0},
5212  {"LINK", nfs3svc_link, NULL, NFS3_LINK, DRC_NON_IDEMPOTENT, 0},
5213  {"READDIR", nfs3svc_readdir, NULL, NFS3_READDIR, DRC_IDEMPOTENT, 0},
5214  {"READDIRPLUS", nfs3svc_readdirp, NULL, NFS3_READDIRP, DRC_IDEMPOTENT, 0},
5215  {"FSSTAT", nfs3svc_fsstat, NULL, NFS3_FSSTAT, DRC_IDEMPOTENT, 0},
5216  {"FSINFO", nfs3svc_fsinfo, NULL, NFS3_FSINFO, DRC_IDEMPOTENT, 0},
5217  {"PATHCONF", nfs3svc_pathconf, NULL, NFS3_PATHCONF, DRC_IDEMPOTENT, 0},
5218  {"COMMIT", nfs3svc_commit, NULL, NFS3_COMMIT, DRC_IDEMPOTENT, 0}};
5219 
5221  .progname = "NFS3",
5222  .prognum = NFS_PROGRAM,
5223  .progver = NFS_V3,
5224  .progport = GF_NFS3_PORT,
5225  .actors = nfs3svc_actors,
5226  .numactors = NFS3_PROC_COUNT,
5227 
5228  /* Requests like FSINFO are sent before an auth scheme
5229  * is inited by client. See RFC 2623, Section 2.3.2. */
5230  .min_auth = AUTH_NULL,
5231 };
5232 
5233 /*
5234  * This function rounds up the input value to multiple of 4096. Min and Max
5235  * supported I/O size limits are 4KB (GF_NFS3_FILE_IO_SIZE_MIN) and
5236  * 1MB (GF_NFS3_FILE_IO_SIZE_MAX).
5237  */
5238 void
5239 nfs3_iosize_roundup_4KB(uint64_t *ioszptr)
5240 {
5241  uint64_t iosize;
5242  uint64_t iopages;
5243 
5244  if (!ioszptr)
5245  return;
5246 
5247  iosize = *ioszptr;
5248  iopages = (iosize + GF_NFS3_IO_SIZE - 1) >> GF_NFS3_IO_SHIFT;
5249  iosize = (iopages * GF_NFS3_IO_SIZE);
5250 
5251  /* Double check - boundary conditions */
5252  if (iosize < GF_NFS3_FILE_IO_SIZE_MIN) {
5253  iosize = GF_NFS3_FILE_IO_SIZE_MIN;
5254  } else if (iosize > GF_NFS3_FILE_IO_SIZE_MAX) {
5255  iosize = GF_NFS3_FILE_IO_SIZE_MAX;
5256  }
5257 
5258  *ioszptr = iosize;
5259 }
5260 
5261 int
5263 {
5264  int ret = -1;
5265  char *optstr = NULL;
5266  uint64_t size64 = 0;
5267 
5268  if ((!nfs3) || (!options))
5269  return -1;
5270 
5271  /* nfs3.read-size */
5272  nfs3->readsize = GF_NFS3_RTPREF;
5273  if (dict_get(options, "nfs3.read-size")) {
5274  ret = dict_get_str(options, "nfs3.read-size", &optstr);
5275  if (ret < 0) {
5277  "Failed to read option: nfs3.read-size");
5278  ret = -1;
5279  goto err;
5280  }
5281 
5282  ret = gf_string2uint64(optstr, &size64);
5283  if (ret == -1) {
5285  "Failed to format option: nfs3.read-size");
5286  ret = -1;
5287  goto err;
5288  }
5289 
5290  nfs3_iosize_roundup_4KB(&size64);
5291  nfs3->readsize = size64;
5292  }
5293 
5294  /* nfs3.write-size */
5295  nfs3->writesize = GF_NFS3_WTPREF;
5296  if (dict_get(options, "nfs3.write-size")) {
5297  ret = dict_get_str(options, "nfs3.write-size", &optstr);
5298  if (ret < 0) {
5300  "Failed to read option: nfs3.write-size");
5301  ret = -1;
5302  goto err;
5303  }
5304 
5305  ret = gf_string2uint64(optstr, &size64);
5306  if (ret == -1) {
5308  "Failed to format option: nfs3.write-size");
5309  ret = -1;
5310  goto err;
5311  }
5312 
5313  nfs3_iosize_roundup_4KB(&size64);
5314  nfs3->writesize = size64;
5315  }
5316 
5317  /* nfs3.readdir.size */
5318  nfs3->readdirsize = GF_NFS3_DTPREF;
5319  if (dict_get(options, "nfs3.readdir-size")) {
5320  ret = dict_get_str(options, "nfs3.readdir-size", &optstr);
5321  if (ret < 0) {
5323  "Failed to read option: nfs3.readdir-size");
5324  ret = -1;
5325  goto err;
5326  }
5327 
5328  ret = gf_string2uint64(optstr, &size64);
5329  if (ret == -1) {
5331  "Failed to format option: nfs3.readdir-size");
5332  ret = -1;
5333  goto err;
5334  }
5335 
5336  nfs3_iosize_roundup_4KB(&size64);
5337  nfs3->readdirsize = size64;
5338  }
5339 
5340  /* We want to use the size of the biggest param for the io buffer size.
5341  */
5342  nfs3->iobsize = nfs3->readsize;
5343  if (nfs3->iobsize < nfs3->writesize)
5344  nfs3->iobsize = nfs3->writesize;
5345  if (nfs3->iobsize < nfs3->readdirsize)
5346  nfs3->iobsize = nfs3->readdirsize;
5347 
5348  /* But this is the true size of each iobuf. We need this size to
5349  * accommodate the NFS headers also in the same buffer. */
5350  nfs3->iobsize = nfs3->iobsize * 2;
5351 
5352  ret = 0;
5353 err:
5354  return ret;
5355 }
5356 
5357 int
5359  dict_t *options)
5360 {
5361  int ret = -1;
5362  char *optstr = NULL;
5363  char searchkey[1024];
5364  char *name = NULL;
5365  gf_boolean_t boolt = _gf_false;
5366  uuid_t volumeid = {
5367  0,
5368  };
5369 
5370  if ((!nfsx) || (!exp))
5371  return -1;
5372 
5373  /* For init, fetch options from xlator but for
5374  * reconfigure, take the parameter */
5375  if (!options)
5376  options = nfsx->options;
5377 
5378  if (!options)
5379  return (-1);
5380 
5381  gf_uuid_clear(volumeid);
5382  if (gf_nfs_dvm_off(nfs_state(nfsx)))
5383  goto no_dvm;
5384 
5385  ret = snprintf(searchkey, sizeof(searchkey), "nfs3.%s.volume-id",
5386  exp->subvol->name);
5387  if (ret < 0) {
5389  "snprintf failed");
5390  ret = -1;
5391  goto err;
5392  }
5393 
5394  if (dict_get(options, searchkey)) {
5395  ret = dict_get_str(options, searchkey, &optstr);
5396  if (ret < 0) {
5398  "Failed to read option: %s", searchkey);
5399  ret = -1;
5400  goto err;
5401  }
5402  } else {
5404  "DVM is"
5405  " on but volume-id not given for volume: %s",
5406  exp->subvol->name);
5407  ret = -1;
5408  goto err;
5409  }
5410 
5411  if (optstr) {
5412  ret = gf_uuid_parse(optstr, volumeid);
5413  if (ret < 0) {
5415  "Failed to parse volume UUID");
5416  ret = -1;
5417  goto err;
5418  }
5419  gf_uuid_copy(exp->volumeid, volumeid);
5420  }
5421 
5422 no_dvm:
5423  /* Volume Access */
5424  name = exp->subvol->name;
5425  ret = snprintf(searchkey, sizeof(searchkey), "nfs3.%s.volume-access", name);
5426  if (ret < 0) {
5428  "snprintf failed");
5429  ret = -1;
5430  goto err;
5431  }
5432 
5434  if (dict_get(options, searchkey)) {
5435  ret = dict_get_str(options, searchkey, &optstr);
5436  if (ret < 0) {
5438  "Failed to read option: %s", searchkey);
5439  ret = -1;
5440  goto err;
5441  }
5442 
5443  if (strcmp(optstr, "read-only") == 0)
5445  }
5446 
5447  ret = snprintf(searchkey, sizeof(searchkey), "rpc-auth.%s.unix", name);
5448  if (ret < 0) {
5450  "snprintf failed");
5451  ret = -1;
5452  goto err;
5453  }
5454 
5455  if (dict_get(options, searchkey)) {
5456  ret = dict_get_str(options, searchkey, &optstr);
5457  if (ret < 0) {
5459  "Failed to read option: %s", searchkey);
5460  ret = -1;
5461  goto err;
5462  }
5463  }
5464 
5465  exp->trusted_sync = 0;
5466  ret = snprintf(searchkey, sizeof(searchkey), "nfs3.%s.trusted-sync", name);
5467  if (ret < 0) {
5469  "snprintf failed");
5470  ret = -1;
5471  goto err;
5472  }
5473 
5474  if (dict_get(options, searchkey)) {
5475  ret = dict_get_str(options, searchkey, &optstr);
5476  if (ret < 0) {
5478  "Failed to read option: %s", searchkey);
5479  ret = -1;
5480  goto err;
5481  }
5482 
5483  ret = gf_string2boolean(optstr, &boolt);
5484  if (ret < 0) {
5486  "Failed to convert str "
5487  "to gf_boolean_t");
5488  ret = -1;
5489  goto err;
5490  }
5491 
5492  if (boolt == _gf_true)
5493  exp->trusted_sync = 1;
5494  }
5495 
5496  exp->trusted_write = 0;
5497  ret = snprintf(searchkey, sizeof(searchkey), "nfs3.%s.trusted-write", name);
5498  if (ret < 0) {
5500  "snprintf failed");
5501  ret = -1;
5502  goto err;
5503  }
5504 
5505  if (dict_get(options, searchkey)) {
5506  ret = dict_get_str(options, searchkey, &optstr);
5507  if (ret < 0) {
5509  "Failed to read option: %s", searchkey);
5510  ret = -1;
5511  goto err;
5512  }
5513 
5514  ret = gf_string2boolean(optstr, &boolt);
5515  if (ret < 0) {
5517  "Failed to convert str"
5518  " to gf_boolean_t");
5519  ret = -1;
5520  goto err;
5521  }
5522 
5523  if (boolt ==