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)  

mount3.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 "nfs-common.h"
19 #include "nfs3-fh.h"
20 #include "nfs-fops.h"
21 #include "nfs-inodes.h"
22 #include "nfs-generics.h"
23 #include <glusterfs/locking.h>
24 #include <glusterfs/iatt.h>
25 #include "nfs-mem-types.h"
26 #include "nfs.h"
27 #include <glusterfs/common-utils.h>
28 #include <glusterfs/store.h>
29 #include "glfs-internal.h"
30 #include "glfs.h"
31 #include "mount3-auth.h"
32 #include <glusterfs/hashfn.h>
33 #include "nfs-messages.h"
34 
35 #include <errno.h>
36 #include <sys/socket.h>
37 #include <sys/uio.h>
38 
39 /* This macro will assist in freeing up entire link list
40  * of host_auth_spec structure.
41  */
42 #define FREE_HOSTSPEC(exp) \
43  do { \
44  struct host_auth_spec *host = exp->hostspec; \
45  while (NULL != host) { \
46  struct host_auth_spec *temp = host; \
47  host = host->next; \
48  if (NULL != temp->host_addr) { \
49  GF_FREE(temp->host_addr); \
50  } \
51  GF_FREE(temp); \
52  } \
53  exp->hostspec = NULL; \
54  } while (0)
55 
56 /* Paths for export and netgroup files */
57 const char *exports_file_path = GLUSTERD_DEFAULT_WORKDIR "/nfs/exports";
58 const char *netgroups_file_path = GLUSTERD_DEFAULT_WORKDIR "/nfs/netgroups";
59 
60 typedef ssize_t (*mnt3_serializer)(struct iovec outmsg, void *args);
61 
62 extern void *
63 mount3udp_thread(void *argv);
64 
65 static void
67 {
68  if (!exp)
69  return;
70 
71  if (exp->exptype == MNT3_EXPTYPE_DIR)
72  FREE_HOSTSPEC(exp);
73  GF_FREE(exp->expname);
74  GF_FREE(exp->fullpath);
75  GF_FREE(exp);
76 }
77 
78 /* Generic reply function for MOUNTv3 specific replies. */
79 int
81 {
82  struct iovec outmsg = {
83  0,
84  };
85  struct iobuf *iob = NULL;
86  struct mount3_state *ms = NULL;
87  int ret = -1;
88  ssize_t msglen = 0;
89  struct iobref *iobref = NULL;
90 
91  if (!req)
92  return -1;
93 
94  ms = (struct mount3_state *)rpcsvc_request_program_private(req);
95  if (!ms) {
97  "mount state not found");
98  goto ret;
99  }
100 
101  /* First, get the io buffer into which the reply in arg will
102  * be serialized.
103  */
104  /* TODO: use 'xdrproc_t' instead of 'sfunc' to get the xdr-size */
105  iob = iobuf_get(ms->iobpool);
106  if (!iob) {
108  "Failed to get iobuf");
109  goto ret;
110  }
111 
112  iobuf_to_iovec(iob, &outmsg);
113  /* Use the given serializer to translate the give C structure in arg
114  * to XDR format which will be written into the buffer in outmsg.
115  */
116  msglen = sfunc(outmsg, arg);
117  if (msglen < 0) {
119  "Failed to encode message");
120  goto ret;
121  }
122  outmsg.iov_len = msglen;
123 
124  iobref = iobref_new();
125  if (iobref == NULL) {
127  "Failed to get iobref");
128  goto ret;
129  }
130 
131  ret = iobref_add(iobref, iob);
132  if (ret) {
134  "Failed to add iob to iobref");
135  goto ret;
136  }
137 
138  /* Then, submit the message for transmission. */
139  ret = rpcsvc_submit_message(req, &outmsg, 1, NULL, 0, iobref);
140  if (ret == -1) {
142  "Reply submission failed");
143  goto ret;
144  }
145 
146  ret = 0;
147 ret:
148  if (NULL != iob)
149  iobuf_unref(iob);
150  if (NULL != iobref)
152 
153  return ret;
154 }
163 void
165 {
166  char *exname = NULL;
167  char *fpath = NULL;
168  data_t *medata = NULL;
169 
172 
173  /* We don't want export names with leading slashes */
174  exname = me->exname;
175  while (exname[0] == '/')
176  exname++;
177 
178  /* Get the fullpath for the export */
179  fpath = me->fullpath;
180  if (me->has_full_path) {
181  while (fpath[0] == '/')
182  fpath++;
183 
184  /* Export names can either be just volumes or paths inside that
185  * volume. */
186  exname = fpath;
187  }
188 
189  snprintf(me->hashkey, sizeof(me->hashkey), "%s:%s", exname, me->hostname);
190 
191  medata = bin_to_data(me, sizeof(*me));
192  dict_set(ms->mountdict, me->hashkey, medata);
193  gf_msg_trace(GF_MNT, 0, "Inserted into mountdict: %s", me->hashkey);
194 out:
195  return;
196 }
197 
206 void
208 {
209  dict_del(ms->mountdict, me->hashkey);
210 }
211 
212 /* Generic error reply function, just pass the err status
213  * and it will do the rest, including transmission.
214  */
215 int
217 {
218  mountres3 res;
219 
220  if (!req)
221  return -1;
222 
223  res.fhs_status = mntstat;
224  mnt3svc_submit_reply(req, (void *)&res,
226 
227  return 0;
228 }
229 
231 mnt3svc_errno_to_mnterr(int32_t errnum)
232 {
233  mountstat3 stat;
234 
235  switch (errnum) {
236  case 0:
237  stat = MNT3_OK;
238  break;
239  case ENOENT:
240  stat = MNT3ERR_NOENT;
241  break;
242  case EPERM:
243  stat = MNT3ERR_PERM;
244  break;
245  case EIO:
246  stat = MNT3ERR_IO;
247  break;
248  case EACCES:
249  stat = MNT3ERR_ACCES;
250  break;
251  case ENOTDIR:
252  stat = MNT3ERR_NOTDIR;
253  break;
254  case EINVAL:
255  stat = MNT3ERR_INVAL;
256  break;
257  case ENOSYS:
258  stat = MNT3ERR_NOTSUPP;
259  break;
260  case ENOMEM:
261  stat = MNT3ERR_SERVERFAULT;
262  break;
263  default:
264  stat = MNT3ERR_SERVERFAULT;
265  break;
266  }
267 
268  return stat;
269 }
270 
271 mountres3
272 mnt3svc_set_mountres3(mountstat3 stat, struct nfs3_fh *fh, int *authflavor,
273  u_int aflen)
274 {
275  mountres3 res = {
276  0,
277  };
278  uint32_t fhlen = 0;
279 
280  res.fhs_status = stat;
281 
282  if (fh)
283  fhlen = nfs3_fh_compute_size();
284 
286  res.mountres3_u.mountinfo.fhandle.fhandle3_val = (char *)fh;
289 
290  return res;
291 }
292 
293 /* Read the rmtab from the store_handle and append (or not) the entries to the
294  * mountlist.
295  *
296  * Requires the store_handle to be locked.
297  */
298 static int
300  gf_boolean_t append)
301 {
302  int ret = 0;
303  unsigned int idx = 0;
304  struct mountentry *me = NULL, *tmp = NULL;
305  /* me->hostname is a char[MNTPATHLEN] */
306  char key[MNTPATHLEN + 11];
307 
308  GF_ASSERT(sh && mountlist);
309 
310  if (!gf_store_locked_local(sh)) {
312  "Not reading unlocked %s", sh->path);
313  return -1;
314  }
315 
316  if (!append) {
318  {
319  list_del(&me->mlist);
320  GF_FREE(me);
321  }
322  me = NULL;
323  }
324 
325  for (;;) {
326  char *value = NULL;
327 
328  if (me && append) {
329  /* do not add duplicates */
331  {
332  if (!strcmp(tmp->hostname, me->hostname) &&
333  !strcmp(tmp->exname, me->exname)) {
334  GF_FREE(me);
335  goto dont_add;
336  }
337  }
339  } else if (me) {
341  }
342 
343  dont_add:
344  me = GF_CALLOC(1, sizeof(*me), gf_nfs_mt_mountentry);
345  if (!me) {
347  "Out of memory");
348  ret = -1;
349  goto out;
350  }
351 
352  INIT_LIST_HEAD(&me->mlist);
353 
354  snprintf(key, 9 + MNTPATHLEN, "hostname-%d", idx);
355  ret = gf_store_retrieve_value(sh, key, &value);
356  if (ret)
357  break;
358  snprintf(me->hostname, MNTPATHLEN, "%s", value);
359  GF_FREE(value);
360 
361  snprintf(key, 11 + MNTPATHLEN, "mountpoint-%d", idx);
362  ret = gf_store_retrieve_value(sh, key, &value);
363  if (ret)
364  break;
365  snprintf(me->exname, MNTPATHLEN, "%s", value);
366  GF_FREE(value);
367 
368  idx++;
369  gf_msg_trace(GF_MNT, 0, "Read entries %s:%s", me->hostname, me->exname);
370  }
371  gf_msg_debug(GF_MNT, 0, "Read %d entries from '%s'", idx, sh->path);
372  GF_FREE(me);
373 out:
374  return ret;
375 }
376 
377 /* Overwrite the contents of the rwtab with the in-memory client list.
378  * Fail gracefully if the stora_handle is not locked.
379  */
380 static void
382 {
383  struct mountentry *me = NULL;
384  char key[16];
385  int fd, ret;
386  unsigned int idx = 0;
387 
388  if (!gf_store_locked_local(sh)) {
390  "Not modifying unlocked %s", sh->path);
391  return;
392  }
393 
394  fd = gf_store_mkstemp(sh);
395  if (fd == -1) {
397  "Failed to open %s", sh->path);
398  return;
399  }
400 
402  {
403  snprintf(key, 16, "hostname-%d", idx);
404  ret = gf_store_save_value(fd, key, me->hostname);
405  if (ret)
406  goto fail;
407 
408  snprintf(key, 16, "mountpoint-%d", idx);
409  ret = gf_store_save_value(fd, key, me->exname);
410  if (ret)
411  goto fail;
412 
413  idx++;
414  }
415 
416  gf_msg_debug(GF_MNT, 0, "Updated rmtab with %d entries", idx);
417 
418  if (gf_store_rename_tmppath(sh))
420  "Failed to overwrite rwtab %s", sh->path);
421 
422  return;
423 
424 fail:
426  "Failed to update %s", sh->path);
428 }
429 
430 static gf_boolean_t
431 mount_open_rmtab(const char *rmtab, gf_store_handle_t **sh)
432 {
433  int ret = -1;
434 
435  /* updating the rmtab is disabled, use in-memory only */
436  if (!rmtab || rmtab[0] == '\0')
437  return _gf_false;
438 
439  ret = gf_store_handle_new(rmtab, sh);
440  if (ret) {
441  gf_log(GF_MNT, GF_LOG_WARNING, "Failed to open '%s'", rmtab);
442  return _gf_false;
443  }
444 
445  return _gf_true;
446 }
447 
448 /* Read the rmtab into a clean ms->mountlist.
449  */
450 static void
452 {
453  gf_store_handle_t *sh = NULL;
454  struct nfs_state *nfs = NULL;
455  gf_boolean_t read_rmtab = _gf_false;
456 
457  nfs = (struct nfs_state *)ms->nfsx->private;
458 
459  read_rmtab = mount_open_rmtab(nfs->rmtab, &sh);
460  if (!read_rmtab)
461  return;
462 
463  if (gf_store_lock(sh)) {
465  "Failed to lock '%s'", nfs->rmtab);
466  goto out;
467  }
468 
470  gf_store_unlock(sh);
471 
472 out:
474 }
475 
476 /* Write the ms->mountlist to the rmtab.
477  *
478  * The rmtab could be empty, or it can exists and have been updated by a
479  * different storage server without our knowing.
480  *
481  * 0. if opening the nfs->rmtab fails, return gracefully
482  * 1. takes the store_handle lock on the current rmtab
483  * - blocks if an other storage server rewrites the rmtab at the same time
484  * 2. [if new_rmtab] takes the store_handle lock on the new rmtab
485  * 3. reads/merges the entries from the current rmtab
486  * 4. [if new_rmtab] reads/merges the entries from the new rmtab
487  * 5. [if new_rmtab] writes the new rmtab
488  * 6. [if not new_rmtab] writes the current rmtab
489  * 7 [if new_rmtab] replaces nfs->rmtab to point to the new location
490  * 8. [if new_rmtab] releases the store_handle lock of the new rmtab
491  * 9. releases the store_handle lock of the old rmtab
492  */
493 void
494 mount_rewrite_rmtab(struct mount3_state *ms, char *new_rmtab)
495 {
496  gf_store_handle_t *sh = NULL, *nsh = NULL;
497  struct nfs_state *nfs = NULL;
498  int ret;
499  char *rmtab = NULL;
500  gf_boolean_t got_old_rmtab = _gf_false;
501 
502  nfs = (struct nfs_state *)ms->nfsx->private;
503 
504  got_old_rmtab = mount_open_rmtab(nfs->rmtab, &sh);
505  if (!got_old_rmtab && !new_rmtab)
506  return;
507 
508  if (got_old_rmtab && gf_store_lock(sh)) {
510  "Not rewriting '%s'", nfs->rmtab);
511  goto free_sh;
512  }
513 
514  if (new_rmtab) {
515  ret = gf_store_handle_new(new_rmtab, &nsh);
516  if (ret) {
518  "Failed to open '%s'", new_rmtab);
519  goto unlock_sh;
520  }
521 
522  if (gf_store_lock(nsh)) {
524  "Not rewriting '%s'", new_rmtab);
525  goto free_nsh;
526  }
527  }
528 
529  /* always read the currently used rmtab */
530  if (got_old_rmtab)
532 
533  if (new_rmtab) {
534  /* read the new rmtab and write changes to the new location */
536  __mount_rewrite_rmtab(ms, nsh);
537 
538  /* replace the nfs->rmtab reference to the new rmtab */
539  rmtab = gf_strdup(new_rmtab);
540  if (rmtab == NULL) {
542  "Out of memory, keeping %s as rmtab", nfs->rmtab);
543  } else {
544  GF_FREE(nfs->rmtab);
545  nfs->rmtab = rmtab;
546  }
547 
548  gf_store_unlock(nsh);
549  } else {
550  /* rewrite the current (unchanged location) rmtab */
551  __mount_rewrite_rmtab(ms, sh);
552  }
553 
554 free_nsh:
555  if (new_rmtab)
557 unlock_sh:
558  if (got_old_rmtab)
559  gf_store_unlock(sh);
560 free_sh:
561  if (got_old_rmtab)
563 }
564 
565 /* Add a new NFS-client to the ms->mountlist and update the rmtab if we can.
566  *
567  * A NFS-client will only be removed from the ms->mountlist in case the
568  * NFS-client sends a unmount request. It is possible that a NFS-client
569  * crashed/rebooted had network loss or something else prevented the NFS-client
570  * to unmount cleanly. In this case, a duplicate entry would be added to the
571  * ms->mountlist, which is wrong and we should prevent.
572  *
573  * It is fully acceptable that the ms->mountlist is not 100% correct, this is a
574  * common issue for all(?) NFS-servers.
575  */
576 int
578  const char *expname, const char *fullpath)
579 {
580  struct mountentry *me = NULL;
581  struct mountentry *cur = NULL;
582  int ret = -1;
583  char *colon = NULL;
584  struct nfs_state *nfs = NULL;
585  gf_store_handle_t *sh = NULL;
586  gf_boolean_t update_rmtab = _gf_false;
587 
588  if ((!ms) || (!req) || (!expname))
589  return -1;
590 
591  me = (struct mountentry *)GF_CALLOC(1, sizeof(*me), gf_nfs_mt_mountentry);
592  if (!me)
593  return -1;
594 
595  nfs = (struct nfs_state *)ms->nfsx->private;
596 
597  update_rmtab = mount_open_rmtab(nfs->rmtab, &sh);
598 
599  snprintf(me->exname, MNTPATHLEN, "%s", expname);
600  /* Sometimes we don't care about the full path
601  * so a NULL value for fullpath is valid.
602  */
603  if (fullpath) {
604  if (strlen(fullpath) < MNTPATHLEN) {
605  strcpy(me->fullpath, fullpath);
606  me->has_full_path = _gf_true;
607  }
608  }
609 
610  INIT_LIST_HEAD(&me->mlist);
611  /* Must get the IP or hostname of the client so we
612  * can map it into the mount entry.
613  */
615  if (ret == -1)
616  goto free_err;
617 
618  colon = strrchr(me->hostname, ':');
619  if (colon) {
620  *colon = '\0';
621  }
622  LOCK(&ms->mountlock);
623  {
624  /* in case locking fails, we just don't write the rmtab */
625  if (update_rmtab && gf_store_lock(sh)) {
627  "Failed to lock '%s', changes will not be "
628  "written",
629  nfs->rmtab);
630  } else if (update_rmtab) {
632  }
633 
634  /* do not add duplicates */
635  list_for_each_entry(cur, &ms->mountlist, mlist)
636  {
637  if (!strcmp(cur->hostname, me->hostname) &&
638  !strcmp(cur->exname, me->exname)) {
639  GF_FREE(me);
640  goto dont_add;
641  }
642  }
643  list_add_tail(&me->mlist, &ms->mountlist);
644  __mountdict_insert(ms, me);
645 
646  /* only write the rmtab in case it was locked */
647  if (update_rmtab && gf_store_locked_local(sh))
648  __mount_rewrite_rmtab(ms, sh);
649  }
650 dont_add:
651  if (update_rmtab && gf_store_locked_local(sh))
652  gf_store_unlock(sh);
653 
654  UNLOCK(&ms->mountlock);
655 
656 free_err:
657  if (update_rmtab)
659 
660  if (ret == -1)
661  GF_FREE(me);
662 
663  return ret;
664 }
665 
666 int
667 __mnt3_get_volume_id(struct mount3_state *ms, xlator_t *mntxl, uuid_t volumeid)
668 {
669  int ret = -1;
670  struct mnt3_export *exp = NULL;
671 
672  if ((!ms) || (!mntxl))
673  return ret;
674 
675  LOCK(&ms->mountlock);
677  {
678  if (exp->vol == mntxl) {
680  ret = 0;
681  goto out;
682  }
683  }
684 
685 out:
686  UNLOCK(&ms->mountlock);
687  return ret;
688 }
689 
690 int
691 __mnt3_build_mountid_from_path(const char *path, uuid_t mountid)
692 {
693  uint32_t hashed_path = 0;
694  int ret = -1;
695 
696  if (!path)
697  goto out;
698 
699  while (strlen(path) > 0 && path[0] == '/')
700  path++;
701 
702  /* Clear the mountid */
704 
705  hashed_path = SuperFastHash(path, strlen(path));
706  if (hashed_path == 1) {
708  "failed to hash path: %s", path);
709  goto out;
710  }
711 
712  memcpy(mountid, &hashed_path, sizeof(hashed_path));
713  ret = 0;
714 out:
715  return ret;
716 }
717 
718 int
720 {
721  int ret = -1;
722  uint32_t hashed_path = 0;
723 
724  /* first clear the mountid */
726 
727  hashed_path = SuperFastHash(mntxl->name, strlen(mntxl->name));
728  if (hashed_path == 1) {
730  "failed to hash xlator name: %s", mntxl->name);
731  goto out;
732  }
733 
734  memcpy(mountid, &hashed_path, sizeof(hashed_path));
735  ret = 0;
736 out:
737  return ret;
738 }
739 
740 int32_t
741 mnt3svc_lookup_mount_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
742  int32_t op_ret, int32_t op_errno, inode_t *inode,
743  struct iatt *buf, dict_t *xattr,
744  struct iatt *postparent)
745 {
746  mountres3 res = {
747  0,
748  };
749  rpcsvc_request_t *req = NULL;
750  struct nfs3_fh fh = {
751  {0},
752  };
753  struct mount3_state *ms = NULL;
754  mountstat3 status = 0;
755  int autharr[10];
756  int autharrlen = 0;
757  rpcsvc_t *svc = NULL;
758  xlator_t *mntxl = NULL;
759  uuid_t volumeid = {
760  0,
761  };
762  char *path = NULL;
763  uuid_t mountid = {
764  1,
765  };
766  char fhstr[1536];
767  int alloclen = 0;
768 
769  req = (rpcsvc_request_t *)frame->local;
770 
771  if (!req)
772  return -1;
773 
774  mntxl = (xlator_t *)cookie;
775  ms = (struct mount3_state *)rpcsvc_request_program_private(req);
776  if (!ms) {
778  "mount state not found");
779  op_ret = -1;
780  op_errno = EINVAL;
781  }
782 
783  if (op_ret == -1) {
785  "error=%s", strerror(op_errno));
786  status = mnt3svc_errno_to_mnterr(op_errno);
787  }
788  if (status != MNT3_OK)
789  goto xmit_res;
790 
791  alloclen = strlen(mntxl->name) + 2;
792  path = GF_MALLOC(alloclen, gf_nfs_mt_char);
793  if (!path) {
795  "Memory allocation failed.");
796  goto xmit_res;
797  }
798 
799  snprintf(path, alloclen, "/%s", mntxl->name);
800  mnt3svc_update_mountlist(ms, req, path, NULL);
801  GF_FREE(path);
802  if (gf_nfs_dvm_off(nfs_state(ms->nfsx))) {
803  fh = nfs3_fh_build_indexed_root_fh(ms->nfsx->children, mntxl);
804  goto xmit_res;
805  }
806 
807  __mnt3_get_mount_id(mntxl, mountid);
808  __mnt3_get_volume_id(ms, mntxl, volumeid);
809  fh = nfs3_fh_build_uuid_root_fh(volumeid, mountid);
810 
811 xmit_res:
812  nfs3_fh_to_str(&fh, fhstr, sizeof(fhstr));
813  gf_msg_debug(GF_MNT, 0, "MNT reply: fh %s, status: %d", fhstr, status);
814  if (op_ret == 0) {
815  svc = rpcsvc_request_service(req);
816  autharrlen = rpcsvc_auth_array(svc, mntxl->name, autharr, 10);
817  }
818 
819  res = mnt3svc_set_mountres3(status, &fh, autharr, autharrlen);
820  mnt3svc_submit_reply(req, (void *)&res,
822 
823  return 0;
824 }
825 
826 int
827 mnt3_match_dirpath_export(const char *expname, const char *dirpath,
828  gf_boolean_t export_parsing_match)
829 {
830  int ret = 0;
831  size_t dlen;
832  char *fullpath = NULL;
833  char *second_slash = NULL;
834  char *dirdup = NULL;
835 
836  if ((!expname) || (!dirpath))
837  return 0;
838 
839  dirdup = strdupa(dirpath);
840 
841  /* Some clients send a dirpath for mount that includes the slash at the
842  * end. String compare for searching the export will fail because our
843  * exports list does not include that slash. Remove the slash to
844  * compare.
845  */
846  dlen = strlen(dirdup);
847  if (dlen && dirdup[dlen - 1] == '/')
848  dirdup[dlen - 1] = '\0';
849 
850  /* Here we try to match fullpaths with export names */
851  fullpath = dirdup;
852 
853  if (export_parsing_match) {
854  if (dirdup[0] == '/')
855  fullpath = dirdup + 1;
856 
857  second_slash = strchr(fullpath, '/');
858  if (second_slash)
859  *second_slash = '\0';
860  }
861 
862  /* The export name begins with a slash so move it forward by one
863  * to ignore the slash when we want to compare the fullpath and
864  * export.
865  */
866  if (fullpath[0] != '/')
867  expname++;
868 
869  if (strcmp(expname, fullpath) == 0)
870  ret = 1;
871 
872  return ret;
873 }
874 
875 int
877  xlator_t *xl, inode_t *exportinode)
878 {
879  int ret = -EFAULT;
880  nfs_user_t nfu = {
881  0,
882  };
883  loc_t exportloc = {
884  0,
885  };
886 
887  if ((!req) || (!xl) || (!ms) || (!exportinode))
888  return ret;
889 
890  ret = nfs_inode_loc_fill(exportinode, &exportloc, NFS_RESOLVE_EXIST);
891  if (ret < 0) {
893  "Loc fill failed for export inode"
894  ": gfid %s, volume: %s",
895  uuid_utoa(exportinode->gfid), xl->name);
896  goto err;
897  }
898 
899  /* To service the mount request, all we need to do
900  * is to send a lookup fop that returns the stat
901  * for the root of the child volume. This is
902  * used to build the root fh sent to the client.
903  */
904  nfs_request_user_init(&nfu, req);
905  ret = nfs_lookup(ms->nfsx, xl, &nfu, &exportloc, mnt3svc_lookup_mount_cbk,
906  (void *)req);
907 
908  nfs_loc_wipe(&exportloc);
909 err:
910  return ret;
911 }
912 
913 /* For a volume mount request, we just have to create loc on the root inode,
914  * and send a lookup. In the lookup callback the mount reply is send along with
915  * the file handle.
916  */
917 int
919  struct mnt3_export *exp)
920 {
921  inode_t *exportinode = NULL;
922  int ret = -EFAULT;
923  static uuid_t rootgfid = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
924 
925  if ((!req) || (!exp) || (!ms))
926  return ret;
927 
928  exportinode = inode_find(exp->vol->itable, rootgfid);
929  if (!exportinode) {
931  "Failed to get root inode");
932  ret = -ENOENT;
933  goto err;
934  }
935 
936  ret = mnt3svc_mount_inode(req, ms, exp->vol, exportinode);
937  inode_unref(exportinode);
938 
939 err:
940  return ret;
941 }
942 
943 /* The catch with directory exports is that the first component of the export
944  * name will be the name of the volume.
945  * Any lookup that needs to be performed to build the directory's file handle
946  * needs to start from the directory path from the root of the volume. For that
947  * we need to strip out the volume name first.
948  */
949 char *
950 mnt3_get_volume_subdir(char *dirpath, char **volname)
951 {
952  /* subdir points to the first / after the volume name while dirpath
953  * points to the first char of the volume name.
954  */
955  char *subdir = NULL;
956  int volname_len = 0;
957  static char *root = "/";
958 
959  /* all callers are expected to pass a valid *dirpath */
961 
962  if (dirpath[0] == '/')
963  dirpath++;
964 
965  subdir = index(dirpath, (int)'/');
966  if (!subdir) {
967  subdir = root;
968  volname_len = strlen(dirpath);
969  } else {
970  volname_len = subdir - dirpath;
971  }
972 
973  if (!volname)
974  goto out;
975 
976  if (!*volname)
977  goto out;
978 
979  strncpy(*volname, dirpath, volname_len);
980  *(*volname + volname_len) = '\0';
981 out:
982  return subdir;
983 }
984 
985 void
987 {
988  if (!mres)
989  return;
990 
991  nfs_loc_wipe(&mres->resolveloc);
992  GF_FREE(mres);
993 }
994 
995 /* Sets up the component argument to contain the next component in the path and
996  * sets up path as an absolute path starting from the next component.
997  */
998 static char *
999 setup_next_component(char *path, size_t plen, char *component, size_t clen)
1000 {
1001  char *comp = NULL;
1002  char *nextcomp = NULL;
1003 
1004  if ((!path) || (!component))
1005  return NULL;
1006 
1007  strncpy(component, path, clen);
1008  comp = index(component, (int)'/');
1009  if (!comp)
1010  goto err;
1011 
1012  comp++;
1013  nextcomp = index(comp, (int)'/');
1014  if (nextcomp) {
1015  strncpy(path, nextcomp, plen);
1016  *nextcomp = '\0';
1017  } else
1018  path[0] = '\0';
1019 
1020 err:
1021  return comp;
1022 }
1023 
1024 int32_t
1025 mnt3_resolve_subdir_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
1026  int32_t op_ret, int32_t op_errno, inode_t *inode,
1027  struct iatt *buf, dict_t *xattr,
1028  struct iatt *postparent);
1029 
1030 int32_t
1031 mnt3_readlink_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
1032  int32_t op_ret, int32_t op_errno, const char *path,
1033  struct iatt *buf, dict_t *xdata);
1034 
1035 /* There are multiple components in the directory export path and each one
1036  * needs to be looked up one after the other.
1037  */
1038 int
1040 {
1041  char dupsubdir[MNTPATHLEN];
1042  char *nextcomp = NULL;
1043  int ret = -EFAULT;
1044  nfs_user_t nfu = {
1045  0,
1046  };
1047  uuid_t gfid = {
1048  0,
1049  };
1050 
1051  if (!mres)
1052  return ret;
1053 
1054  nextcomp = setup_next_component(mres->remainingdir,
1055  sizeof(mres->remainingdir), dupsubdir,
1056  sizeof(dupsubdir));
1057  if (!nextcomp)
1058  goto err;
1059 
1060  /* Wipe the contents of the previous component */
1061  gf_uuid_copy(gfid, mres->resolveloc.inode->gfid);
1062  nfs_loc_wipe(&mres->resolveloc);
1063  ret = nfs_entry_loc_fill(mres->mstate->nfsx, mres->exp->vol->itable, gfid,
1064  nextcomp, &mres->resolveloc, NFS_RESOLVE_CREATE,
1065  NULL);
1066  if ((ret < 0) && (ret != -2)) {
1068  "Failed to resolve and "
1069  "create inode: parent gfid %s, entry %s",
1070  uuid_utoa(gfid), nextcomp);
1071  ret = -EFAULT;
1072  goto err;
1073  }
1074 
1075  nfs_request_user_init(&nfu, mres->req);
1076  if (IA_ISLNK(mres->resolveloc.inode->ia_type)) {
1077  ret = nfs_readlink(mres->mstate->nfsx, mres->exp->vol, &nfu,
1078  &mres->resolveloc, mnt3_readlink_cbk, mres);
1079  gf_msg_debug(GF_MNT, 0,
1080  "Symlink found , need to resolve"
1081  " into directory handle");
1082  goto err;
1083  }
1084  ret = nfs_lookup(mres->mstate->nfsx, mres->exp->vol, &nfu,
1085  &mres->resolveloc, mnt3_resolve_subdir_cbk, mres);
1086 
1087 err:
1088  return ret;
1089 }
1090 
1091 int
1093 
1094 /*
1095  * Per the AFR2 comments, this function performs the "fresh" lookup
1096  * by deleting the inode from cache and calling __mnt3_resolve_subdir
1097  * again.
1098  */
1099 int
1101 {
1103  mres->resolveloc.name);
1104  strncpy(mres->remainingdir, mres->resolveloc.path,
1105  strlen(mres->resolveloc.path));
1106  nfs_loc_wipe(&mres->resolveloc);
1107  return __mnt3_resolve_subdir(mres);
1108 }
1109 
1110 int32_t
1111 mnt3_resolve_subdir_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
1112  int32_t op_ret, int32_t op_errno, inode_t *inode,
1113  struct iatt *buf, dict_t *xattr,
1114  struct iatt *postparent)
1115 {
1116  mnt3_resolve_t *mres = NULL;
1117  mountstat3 mntstat = MNT3ERR_SERVERFAULT;
1118  struct nfs3_fh fh = {
1119  {0},
1120  };
1121  int autharr[10];
1122  int autharrlen = 0;
1123  rpcsvc_t *svc = NULL;
1124  mountres3 res = {
1125  0,
1126  };
1127  xlator_t *mntxl = NULL;
1128  char *path = NULL;
1129  struct mount3_state *ms = NULL;
1130  int authcode = 0;
1131  char *authorized_host = NULL;
1132  char *authorized_path = NULL;
1133  inode_t *linked_inode = NULL;
1134 
1135  mres = frame->local;
1136  ms = mres->mstate;
1137  mntxl = (xlator_t *)cookie;
1138  if (op_ret == -1 && op_errno == ESTALE) {
1139  /* Nuke inode from cache and try the LOOKUP
1140  * request again. */
1141  return __mnt3_fresh_lookup(mres);
1142  } else if (op_ret == -1) {
1144  "path=%s (%s)", mres->resolveloc.path, strerror(op_errno));
1145  mntstat = mnt3svc_errno_to_mnterr(op_errno);
1146  goto err;
1147  }
1148 
1149  linked_inode = inode_link(mres->resolveloc.inode, mres->resolveloc.parent,
1150  mres->resolveloc.name, buf);
1151 
1152  if (linked_inode)
1153  nfs_fix_generation(this, linked_inode);
1154 
1155  nfs3_fh_build_child_fh(&mres->parentfh, buf, &fh);
1156  if (strlen(mres->remainingdir) <= 0) {
1157  int alloclen;
1158  op_ret = -1;
1159  mntstat = MNT3_OK;
1160 
1161  /* Construct the full path */
1162  int resolveloc_path_len = strlen(mres->resolveloc.path);
1163  alloclen = strlen(mres->exp->expname) + resolveloc_path_len + 1;
1164  mres->exp->fullpath = GF_MALLOC(alloclen, gf_nfs_mt_char);
1165  if (!mres->exp->fullpath) {
1167  "Memory allocation failed.");
1168  goto err;
1169  }
1170  snprintf(mres->exp->fullpath, alloclen, "%s%s", mres->exp->expname,
1171  mres->resolveloc.path);
1172 
1173  /* Check if this path is authorized to be mounted */
1174  authcode = mnt3_authenticate_request(
1175  ms, mres->req, NULL, NULL, mres->exp->fullpath, &authorized_path,
1176  &authorized_host, FALSE);
1177  if (authcode != 0) {
1178  mntstat = MNT3ERR_ACCES;
1179  gf_msg_debug(GF_MNT, 0, "Client mount not allowed");
1180  op_ret = -1;
1181  goto err;
1182  }
1183 
1184  alloclen = strlen(mres->exp->vol->name) + resolveloc_path_len + 2;
1185  path = GF_MALLOC(alloclen, gf_nfs_mt_char);
1186  if (!path) {
1188  "Memory allocation failed");
1189  goto err;
1190  }
1191  /* Build mountid from the authorized path and stick it in the
1192  * filehandle that will get passed back to the client
1193  */
1194  __mnt3_build_mountid_from_path(authorized_path, fh.mountid);
1195 
1196  snprintf(path, alloclen, "/%s%s", mres->exp->vol->name,
1197  mres->resolveloc.path);
1198 
1199  mnt3svc_update_mountlist(mres->mstate, mres->req, path,
1200  mres->exp->fullpath);
1201  GF_FREE(path);
1202  } else {
1203  mres->parentfh = fh;
1204  op_ret = __mnt3_resolve_export_subdir_comp(mres);
1205  if (op_ret < 0)
1206  mntstat = mnt3svc_errno_to_mnterr(-op_ret);
1207  }
1208 err:
1209  if (op_ret == -1) {
1210  gf_msg_debug(GF_MNT, 0, "Mount reply status: %d", mntstat);
1211  svc = rpcsvc_request_service(mres->req);
1212  autharrlen = rpcsvc_auth_array(svc, mntxl->name, autharr, 10);
1213 
1214  res = mnt3svc_set_mountres3(mntstat, &fh, autharr, autharrlen);
1215  mnt3svc_submit_reply(mres->req, (void *)&res,
1218  }
1219 
1220  GF_FREE(authorized_path);
1221  GF_FREE(authorized_host);
1222 
1223  return 0;
1224 }
1225 
1226 /* This function resolves symbolic link into directory path from
1227  * the mount and restart the parsing process from the beginning
1228  *
1229  * Note : Path specified in the symlink should be relative to the
1230  * symlink, because that is the one which is consistent through
1231  * out the file system.
1232  * If the symlink resolves into another symlink ,then same process
1233  * will be repeated.
1234  * If symbolic links points outside the file system are not considered
1235  * here.
1236  *
1237  * TODO : 1.) This function cannot handle symlinks points to path which
1238  * goes out of the filesystem and comes backs again to same.
1239  * For example, consider vol is exported volume.It contains
1240  * dir,
1241  * symlink1 which points to ../vol/dir,
1242  * symlink2 which points to ../mnt/../vol/dir,
1243  * symlink1 and symlink2 are not handled right now.
1244  *
1245  * 2.) udp mount routine is much simpler from tcp routine and resolves
1246  * symlink directly.May be ,its better we change this routine
1247  * similar to udp
1248  */
1249 int32_t
1250 mnt3_readlink_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
1251  int32_t op_ret, int32_t op_errno, const char *path,
1252  struct iatt *buf, dict_t *xdata)
1253 {
1254  mnt3_resolve_t *mres = NULL;
1255  int ret = -EFAULT;
1256  char *real_loc = NULL;
1257  size_t path_len = 0;
1258  size_t parent_path_len = 0;
1259  char *parent_path = NULL;
1260  char *absolute_path = NULL;
1261  char *relative_path = NULL;
1262  int mntstat = 0;
1263 
1264  GF_ASSERT(frame);
1265 
1266  mres = frame->local;
1267  if (!mres || !path || (path[0] == '/') || (op_ret < 0))
1268  goto mnterr;
1269 
1270  /* Finding current location of symlink */
1271  parent_path_len = strlen(mres->resolveloc.path) -
1272  strlen(mres->resolveloc.name);
1273  parent_path = gf_strndup(mres->resolveloc.path, parent_path_len);
1274  if (!parent_path) {
1275  ret = -ENOMEM;
1276  goto mnterr;
1277  }
1278 
1279  relative_path = gf_strdup(path);
1280  if (!relative_path) {
1281  ret = -ENOMEM;
1282  goto mnterr;
1283  }
1284  /* Resolving into absolute path */
1285  ret = gf_build_absolute_path(parent_path, relative_path, &absolute_path);
1286  if (ret < 0) {
1288  "Cannot resolve symlink, path is out of boundary "
1289  "from current location %s and with relative path "
1290  "%s pointed by symlink",
1291  parent_path, relative_path);
1292 
1293  goto mnterr;
1294  }
1295 
1296  /* Building the actual mount path to be mounted */
1297  path_len = strlen(mres->exp->vol->name) + strlen(absolute_path) +
1298  strlen(mres->remainingdir) + 1;
1299  real_loc = GF_MALLOC(path_len, gf_nfs_mt_char);
1300  if (!real_loc) {
1301  ret = -ENOMEM;
1302  goto mnterr;
1303  }
1304  snprintf(real_loc, path_len, "%s%s", mres->exp->vol->name, absolute_path);
1306 
1307  /* There may entries after symlink in the mount path,
1308  * we should include remaining entries too */
1309  if (strlen(mres->remainingdir) > 0)
1310  strcat(real_loc, mres->remainingdir);
1311 
1312  gf_msg_debug(GF_MNT, 0,
1313  "Resolved path is : %s%s "
1314  "and actual mount path is %s",
1315  absolute_path, mres->remainingdir, real_loc);
1316 
1317  /* After the resolving the symlink , parsing should be done
1318  * for the populated mount path
1319  */
1320  ret = mnt3_parse_dir_exports(mres->req, mres->mstate, real_loc, _gf_true);
1321 
1322  if (ret) {
1324  "Resolved into an unknown path %s%s "
1325  "from the current location of symlink %s",
1326  absolute_path, mres->remainingdir, parent_path);
1327  }
1328 
1329  GF_FREE(real_loc);
1330  GF_FREE(absolute_path);
1331  GF_FREE(parent_path);
1332  GF_FREE(relative_path);
1333 
1334  return ret;
1335 
1336 mnterr:
1337  if (mres) {
1338  mntstat = mnt3svc_errno_to_mnterr(-ret);
1339  mnt3svc_mnt_error_reply(mres->req, mntstat);
1340  } else
1342  "mres == NULL, this should *never* happen");
1343  if (absolute_path)
1344  GF_FREE(absolute_path);
1345  if (parent_path)
1346  GF_FREE(parent_path);
1347  if (relative_path)
1348  GF_FREE(relative_path);
1349  return ret;
1350 }
1351 
1352 /* We will always have to perform a hard lookup on all the components of a
1353  * directory export for a mount request because in the mount reply we need the
1354  * file handle of the directory. Our file handle creation code is designed with
1355  * the assumption that to build a child file/dir fh, we'll always have the
1356  * parent dir's fh available so that we may copy the hash array of the previous
1357  * dir levels.
1358  *
1359  * Since we do not store the file handles anywhere, for every mount request we
1360  * must resolve the file handles of every component so that the parent dir file
1361  * of the exported directory can be built.
1362  */
1363 int
1365 {
1366  char dupsubdir[MNTPATHLEN];
1367  char *firstcomp = NULL;
1368  int ret = -EFAULT;
1369  nfs_user_t nfu = {
1370  0,
1371  };
1372  static uuid_t rootgfid = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
1373 
1374  if (!mres)
1375  return ret;
1376 
1377  firstcomp = setup_next_component(mres->remainingdir,
1378  sizeof(mres->remainingdir), dupsubdir,
1379  sizeof(dupsubdir));
1380  if (!firstcomp)
1381  goto err;
1382 
1383  ret = nfs_entry_loc_fill(mres->mstate->nfsx, mres->exp->vol->itable,
1384  rootgfid, firstcomp, &mres->resolveloc,
1385  NFS_RESOLVE_CREATE, NULL);
1386  if ((ret < 0) && (ret != -2)) {
1388  "Failed to resolve and "
1389  "create inode for volume root: %s",
1390  mres->exp->vol->name);
1391  ret = -EFAULT;
1392  goto err;
1393  }
1394 
1395  nfs_request_user_init(&nfu, mres->req);
1396  if (IA_ISLNK(mres->resolveloc.inode->ia_type)) {
1397  ret = nfs_readlink(mres->mstate->nfsx, mres->exp->vol, &nfu,
1398  &mres->resolveloc, mnt3_readlink_cbk, mres);
1399  gf_msg_debug(GF_MNT, 0,
1400  "Symlink found , need to resolve "
1401  "into directory handle");
1402  goto err;
1403  }
1404  ret = nfs_lookup(mres->mstate->nfsx, mres->exp->vol, &nfu,
1405  &mres->resolveloc, mnt3_resolve_subdir_cbk, mres);
1406 
1407 err:
1408  return ret;
1409 }
1410 
1411 static gf_boolean_t
1412 mnt3_match_subnet_v4(struct addrinfo *ai, uint32_t saddr, uint32_t mask)
1413 {
1414  for (; ai; ai = ai->ai_next) {
1415  struct sockaddr_in *sin = (struct sockaddr_in *)ai->ai_addr;
1416 
1417  if (sin->sin_family != AF_INET)
1418  continue;
1419 
1420  if (mask_match(saddr, sin->sin_addr.s_addr, mask))
1421  return _gf_true;
1422  }
1423 
1424  return _gf_false;
1425 }
1426 
1439 int
1440 mnt3_verify_auth(struct sockaddr_in *client_addr, struct mnt3_export *export)
1441 {
1442  int retvalue = -EACCES;
1443  int ret = 0;
1444  struct host_auth_spec *host = NULL;
1445  struct sockaddr_in *allowed_addr = NULL;
1446  struct addrinfo *allowed_addrinfo = NULL;
1447 
1448  struct addrinfo hint = {
1449  .ai_family = AF_INET,
1450  .ai_protocol = (int)IPPROTO_TCP,
1451  .ai_flags = AI_CANONNAME,
1452  };
1453 
1454  /* Sanity check */
1455  if ((NULL == client_addr) || (NULL == export) ||
1456  (NULL == export->hostspec)) {
1458  "Invalid argument");
1459  return retvalue;
1460  }
1461 
1462  host = export->hostspec;
1463 
1464  /*
1465  * Currently IPv4 subnetwork is supported i.e. AF_INET.
1466  * TODO: IPv6 subnetwork i.e. AF_INET6.
1467  */
1468  if (client_addr->sin_family != AF_INET) {
1470  "Only IPv4 is supported for subdir-auth");
1471  return retvalue;
1472  }
1473 
1474  /* Try to see if the client IP matches the allowed IP list.*/
1475  while (NULL != host) {
1476  GF_ASSERT(host->host_addr);
1477 
1478  if (NULL != allowed_addrinfo) {
1479  freeaddrinfo(allowed_addrinfo);
1480  allowed_addrinfo = NULL;
1481  }
1482 
1483  /* Get the addrinfo for the allowed host (host_addr). */
1484  ret = getaddrinfo(host->host_addr, NULL, &hint, &allowed_addrinfo);
1485  if (0 != ret) {
1486  /*
1487  * getaddrinfo() FAILED for the host IP addr. Continue
1488  * to search other allowed hosts in the hostspec list.
1489  */
1490  gf_msg_debug(GF_MNT, 0, "getaddrinfo: %s\n", gai_strerror(ret));
1491  host = host->next;
1492  continue;
1493  }
1494 
1495  allowed_addr = (struct sockaddr_in *)(allowed_addrinfo->ai_addr);
1496  if (NULL == allowed_addr) {
1498  "Invalid structure");
1499  break;
1500  }
1501 
1502  /* Check if the network addr of both IPv4 socket match */
1503  if (mnt3_match_subnet_v4(allowed_addrinfo, client_addr->sin_addr.s_addr,
1504  host->netmask)) {
1505  retvalue = 0;
1506  break;
1507  }
1508 
1509  /* No match yet, continue the search */
1510  host = host->next;
1511  }
1512 
1513  /* FREE the dynamic memory allocated by getaddrinfo() */
1514  if (NULL != allowed_addrinfo) {
1515  freeaddrinfo(allowed_addrinfo);
1516  }
1517 
1518  return retvalue;
1519 }
1520 
1521 int
1523  struct mnt3_export *exp, char *subdir,
1524  gf_boolean_t send_reply)
1525 {
1526  mnt3_resolve_t *mres = NULL;
1527  int ret = -EFAULT;
1529  struct sockaddr_in *sin = NULL;
1530 
1531  if ((!req) || (!ms) || (!exp) || (!subdir))
1532  return ret;
1533 
1534  sin = (struct sockaddr_in *)(&(req->trans->peerinfo.sockaddr));
1535 
1536  /* Need to check AUTH */
1537  if (NULL != exp->hostspec) {
1538  ret = mnt3_verify_auth(sin, exp);
1539  if (0 != ret) {
1541  "AUTH verification failed");
1542  return ret;
1543  }
1544  }
1545 
1546  /* no reply is needed (WebNFS permissions checking), just return */
1547  if (!send_reply)
1548  return 0; /* no error, mnt3_verify_auth() allowed it */
1549 
1550  mres = GF_CALLOC(1, sizeof(mnt3_resolve_t), gf_nfs_mt_mnt3_resolve);
1551  if (!mres) {
1553  "Memory allocation failed");
1554  goto err;
1555  }
1556 
1557  mres->exp = exp;
1558  mres->mstate = ms;
1559  mres->req = req;
1560 
1561  snprintf(mres->remainingdir, MNTPATHLEN, "%s", subdir);
1563 
1564  if (gf_nfs_dvm_off(nfs_state(ms->nfsx)))
1566  mres->exp->vol);
1567  else
1568  pfh = nfs3_fh_build_uuid_root_fh(exp->volumeid, exp->mountid);
1569 
1570  mres->parentfh = pfh;
1571  ret = __mnt3_resolve_subdir(mres);
1572  if (ret < 0) {
1574  "Failed to resolve export dir: %s", mres->exp->expname);
1575  GF_FREE(mres);
1576  }
1577 
1578 err:
1579  return ret;
1580 }
1581 
1582 int
1584  struct mnt3_export *exp)
1585 {
1586  char *volume_subdir = NULL;
1587  int ret = -EFAULT;
1588 
1589  if ((!req) || (!ms) || (!exp))
1590  return ret;
1591 
1592  volume_subdir = mnt3_get_volume_subdir(exp->expname, NULL);
1593 
1594  ret = mnt3_resolve_subdir(req, ms, exp, volume_subdir, _gf_true);
1595  if (ret < 0) {
1597  "Failed to resolve export dir: %s", exp->expname);
1598  goto err;
1599  }
1600 
1601 err:
1602  return ret;
1603 }
1604 
1605 int
1607  struct mnt3_export *exp)
1608 {
1609  int ret = -EFAULT;
1610 
1611  if ((!req) || (!ms) || (!exp))
1612  return ret;
1613 
1614  if (exp->exptype == MNT3_EXPTYPE_VOLUME)
1615  ret = mnt3svc_volume_mount(req, ms, exp);
1616  else if (exp->exptype == MNT3_EXPTYPE_DIR)
1617  ret = mnt3_resolve_export_subdir(req, ms, exp);
1618 
1619  return ret;
1620 }
1621 
1622 /* mnt3_mntpath_to_xlator sets this to 1 if the mount is for a full
1623  * volume or 2 for a subdir in the volume.
1624  *
1625  * The parameter 'export_parsing_match' indicates whether this function
1626  * is being called by an exports parser or whether it is being called
1627  * during mount. The behavior is different since we don't have to resolve
1628  * the path when doing the parse.
1629  */
1630 struct mnt3_export *
1632  gf_boolean_t export_parsing_match)
1633 {
1634  struct mnt3_export *exp = NULL;
1635  struct mnt3_export *found = NULL;
1636 
1637  if ((!ms) || (!dirpath))
1638  return NULL;
1639 
1640  LOCK(&ms->mountlock);
1642  {
1643  /* Search for the an exact match with the volume */
1645  export_parsing_match)) {
1646  found = exp;
1647  gf_msg_debug(GF_MNT, 0,
1648  "Found export volume: "
1649  "%s",
1650  exp->vol->name);
1651  goto foundexp;
1652  }
1653  }
1654 
1655  gf_msg_debug(GF_MNT, 0, "Export not found");
1656 foundexp:
1657  UNLOCK(&ms->mountlock);
1658  return found;
1659 }
1660 
1661 static int
1662 mnt3_check_client_net_check(rpcsvc_t *svc, char *expvol, char *ipaddr,
1663  uint16_t port)
1664 {
1665  int ret = RPCSVC_AUTH_REJECT;
1666 
1667  if ((!svc) || (!expvol) || (!ipaddr))
1668  goto err;
1669 
1670  ret = rpcsvc_auth_check(svc, expvol, ipaddr);
1671  if (ret == RPCSVC_AUTH_REJECT) {
1673  "Peer %s not allowed", ipaddr);
1674  goto err;
1675  }
1676 
1677  ret = rpcsvc_transport_privport_check(svc, expvol, port);
1678  if (ret == RPCSVC_AUTH_REJECT) {
1680  "Peer %s rejected. Unprivileged "
1681  "port %d not allowed",
1682  ipaddr, port);
1683  goto err;
1684  }
1685 
1686  ret = RPCSVC_AUTH_ACCEPT;
1687 err:
1688  return ret;
1689 }
1690 
1691 int
1693 {
1694  rpcsvc_t *svc = NULL;
1695  rpc_transport_t *trans = NULL;
1696  union gf_sock_union sock_union;
1697  socklen_t socksize = sizeof(struct sockaddr_in);
1698  char peer[RPCSVC_PEER_STRLEN] = {
1699  0,
1700  };
1701  char *ipaddr = NULL;
1702  uint16_t port = 0;
1703  int ret = RPCSVC_AUTH_REJECT;
1704 
1705  if ((!req) || (!volname))
1706  goto err;
1707 
1708  svc = rpcsvc_request_service(req);
1709  trans = rpcsvc_request_transport(req);
1710  if ((!svc) || (!trans))
1711  goto err;
1712 
1713  ret = rpcsvc_transport_peeraddr(trans, peer, RPCSVC_PEER_STRLEN,
1714  &sock_union.storage, socksize);
1715  if (ret != 0) {
1717  "Failed to get peer "
1718  "addr: %s",
1719  gai_strerror(ret));
1720  ret = RPCSVC_AUTH_REJECT;
1721  goto err;
1722  }
1723 
1724  /* peer[] gets IP:PORT formar, slash the port out */
1725  if (!get_host_name((char *)peer, &ipaddr))
1726  ipaddr = peer;
1727 
1728  port = ntohs(sock_union.sin.sin_port);
1729 
1730  ret = mnt3_check_client_net_check(svc, volname, ipaddr, port);
1731 err:
1732  return ret;
1733 }
1734 
1735 static int
1736 mnt3_check_client_net_udp(struct svc_req *req, char *volname, xlator_t *nfsx)
1737 {
1738  rpcsvc_t *svc = NULL;
1739  struct sockaddr_in *sin = NULL;
1740  char ipaddr[INET_ADDRSTRLEN + 1] = {
1741  0,
1742  };
1743  uint16_t port = 0;
1744  int ret = RPCSVC_AUTH_REJECT;
1745  struct nfs_state *nfs = NULL;
1746 
1747  if ((!req) || (!volname) || (!nfsx))
1748  goto err;
1749 
1750 #if !defined(_TIRPC_SVC_H)
1751  sin = svc_getcaller(req->rq_xprt);
1752 #else
1753  sin = (struct sockaddr_in *)svc_getcaller(req->rq_xprt);
1754  /* TIRPC's svc_getcaller() returns a pointer to a sockaddr_in6, even
1755  * though it might actually be an IPv4 address. It ought return a
1756  * struct sockaddr and make the caller upcast it to the proper
1757  * address family. Sigh.
1758  */
1759 #endif
1760  if (!sin)
1761  goto err;
1762  /* And let's make sure that it's actually an IPv4 address. */
1763 
1764  GF_ASSERT(sin->sin_family == AF_INET);
1765 
1766  (void)inet_ntop(AF_INET, &sin->sin_addr, ipaddr, INET_ADDRSTRLEN);
1767 
1768  port = ntohs(sin->sin_port);
1769 
1770  nfs = (struct nfs_state *)nfsx->private;
1771  if (nfs != NULL)
1772  svc = nfs->rpcsvc;
1773 
1774  ret = mnt3_check_client_net_check(svc, volname, ipaddr, port);
1775 err:
1776  return ret;
1777 }
1778 
1779 int
1781  char *path, gf_boolean_t send_reply)
1782 {
1783  char volname[1024] = {
1784  0,
1785  };
1786  struct mnt3_export *exp = NULL;
1787  char *volname_ptr = NULL;
1788  char *subdir = NULL;
1789  int ret = -ENOENT;
1790  struct nfs_state *nfs = NULL;
1791 
1792  if ((!ms) || (!path))
1793  return -1;
1794 
1795  volname_ptr = volname;
1796  subdir = mnt3_get_volume_subdir(path, &volname_ptr);
1797 
1798  /* first try to match the full export/subdir */
1799  exp = mnt3_mntpath_to_export(ms, path, _gf_false);
1800  if (!exp) {
1801  gf_msg_trace(GF_MNT, 0,
1802  "Could not find exact matching export "
1803  "for path=%s",
1804  path);
1805  /* if no exact match is found, look for a fallback */
1806  exp = mnt3_mntpath_to_export(ms, volname, _gf_true);
1807  if (!exp) {
1808  gf_msg_trace(GF_MNT, 0,
1809  "Could not find export for "
1810  "volume %s",
1811  volname);
1812  goto err;
1813  }
1814  }
1815  gf_msg_trace(GF_MNT, 0,
1816  "volume %s and export %s will be used for "
1817  "path %s",
1818  exp->vol->name, exp->expname, path);
1819 
1820  nfs = (struct nfs_state *)ms->nfsx->private;
1821  if (!nfs)
1822  goto err;
1823 
1824  if (!nfs_subvolume_started(nfs, exp->vol)) {
1825  gf_msg_debug(GF_MNT, 0, "Volume %s not started", exp->vol->name);
1826  goto err;
1827  }
1828 
1829  ret = mnt3_check_client_net_tcp(req, exp->vol->name);
1830  if (ret == RPCSVC_AUTH_REJECT) {
1831  gf_msg_debug(GF_MNT, 0, "Client mount not allowed");
1832  ret = -EACCES;
1833  goto err;
1834  }
1835 
1836  ret = mnt3_resolve_subdir(req, ms, exp, subdir, send_reply);
1837  if (ret < 0) {
1839  "Failed to resolve export dir: %s", subdir);
1840  goto err;
1841  }
1842 
1843 err:
1844  return ret;
1845 }
1846 
1847 int
1848 mnt3_find_export(rpcsvc_request_t *req, char *path, struct mnt3_export **e)
1849 {
1850  int ret = -EFAULT;
1851  struct mount3_state *ms = NULL;
1852  struct mnt3_export *exp = NULL;
1853 
1854  if ((!req) || (!path) || (!e))
1855  return -1;
1856 
1857  ms = (struct mount3_state *)rpcsvc_request_program_private(req);
1858  if (!ms) {
1860  "Mount state not present");
1861  rpcsvc_request_seterr(req, SYSTEM_ERR);
1862  goto err;
1863  }
1864 
1865  gf_msg_debug(GF_MNT, 0, "dirpath: %s", path);
1866  exp = mnt3_mntpath_to_export(ms, path, _gf_false);
1867  if (exp) {
1868  ret = 0;
1869  *e = exp;
1870  goto err;
1871  }
1872 
1873  if (!gf_mnt3_export_dirs(ms)) {
1874  ret = -1;
1875  goto err;
1876  }
1877 
1878  ret = mnt3_parse_dir_exports(req, ms, path, _gf_true);
1879 
1880 err:
1881  return ret;
1882 }
1883 
1893 char *
1895 {
1896  rpc_transport_t *trans = NULL;
1897  struct sockaddr_storage sastorage = {
1898  0,
1899  };
1900  char peer[RPCSVC_PEER_STRLEN] = {
1901  0,
1902  };
1903  char *peerdup = NULL;
1904  int ret = 0;
1905 
1907 
1908  trans = rpcsvc_request_transport(req);
1909  ret = rpcsvc_transport_peeraddr(trans, peer, RPCSVC_PEER_STRLEN, &sastorage,
1910  sizeof(sastorage));
1911  if (ret != 0)
1912  goto out;
1913 
1914  peerdup = gf_strdup(peer);
1915 out:
1916  return peerdup;
1917 }
1918 
1930 char *
1931 _mnt3_get_host_from_peer(const char *peer_addr)
1932 {
1933  char *part = NULL;
1934  size_t host_len = 0;
1935  char *colon = NULL;
1936 
1937  colon = strrchr(peer_addr, ':');
1938  if (!colon) {
1939  gf_msg(GF_MNT, GF_LOG_ERROR, 0, NFS_MSG_BAD_PEER, "Bad peer %s",
1940  peer_addr);
1941  goto out;
1942  }
1943 
1944  host_len = colon - peer_addr;
1945  if (host_len < RPCSVC_PEER_STRLEN)
1946  part = gf_strndup(peer_addr, host_len);
1947  else
1949  "Peer too long %s", peer_addr);
1950 out:
1951  return part;
1952 }
1953 
1961 int
1963  const char *host_addr, gf_boolean_t is_write_op)
1964 {
1965  if (!is_write_op)
1966  return is_nfs_fh_cached(ms->authcache, fh, host_addr);
1967 
1968  return is_nfs_fh_cached_and_writeable(ms->authcache, fh, host_addr);
1969 }
1970 
1989 int
1991  struct nfs3_fh *fh, const char *path,
1992  char **authorized_export, char **authorized_host,
1993  gf_boolean_t is_write_op)
1994 {
1995  char *peer_addr = NULL;
1996  char *host_addr_ip = NULL;
1997  char *host_addr_fqdn = NULL;
1998  int auth_status_code = -EACCES;
1999  char *pathdup = NULL;
2000  size_t dlen = 0;
2001  char *auth_host = NULL;
2002  gf_boolean_t fh_cached = _gf_false;
2003  struct export_item *expitem = NULL;
2004 
2007 
2008  peer_addr = _mnt3_get_peer_addr(req);
2009 
2010  if (!peer_addr)
2011  goto free_and_out;
2012 
2013  host_addr_ip = _mnt3_get_host_from_peer(peer_addr);
2014 
2015  if (!host_addr_ip)
2016  goto free_and_out;
2017 
2018  if (path) {
2019  /* Need to strip out trailing '/' */
2020  pathdup = strdupa(path);
2021  dlen = strlen(pathdup);
2022  if (dlen > 0 && pathdup[dlen - 1] == '/')
2023  pathdup[dlen - 1] = '\0';
2024  }
2025 
2026  /* Check if the filehandle is cached */
2027  fh_cached = mnt3_check_cached_fh(ms, fh, host_addr_ip, is_write_op);
2028  if (fh_cached) {
2029  gf_msg_trace(GF_MNT, 0, "Found cached FH for %s", host_addr_ip);
2030  auth_status_code = 0;
2031  goto free_and_out;
2032  }
2033 
2034  /* Check if the IP is authorized */
2035  auth_status_code = mnt3_auth_host(ms->auth_params, host_addr_ip, fh,
2036  pathdup, is_write_op, &expitem);
2037 
2038  gf_msg_debug(GF_MNT, 0, "access from IP %s is %s", host_addr_ip,
2039  auth_status_code ? "denied" : "allowed");
2040 
2041  if (auth_status_code != 0) {
2042  /* If not, check if the FQDN is authorized */
2043  host_addr_fqdn = gf_rev_dns_lookup(host_addr_ip);
2044  auth_status_code = mnt3_auth_host(ms->auth_params, host_addr_fqdn, fh,
2045  pathdup, is_write_op, &expitem);
2046 
2047  gf_msg_debug(GF_MNT, 0, "access from FQDN %s is %s", host_addr_fqdn,
2048  auth_status_code ? "denied" : "allowed");
2049 
2050  if (auth_status_code == 0)
2051  auth_host = host_addr_fqdn;
2052  } else
2053  auth_host = host_addr_ip;
2054 
2055  /* Skip the lines that set authorized export &
2056  * host if they are null.
2057  */
2058  if (!authorized_export || !authorized_host) {
2059  /* Cache the file handle if it was authorized */
2060  if (fh && auth_status_code == 0)
2061  cache_nfs_fh(ms->authcache, fh, host_addr_ip, expitem);
2062 
2063  goto free_and_out;
2064  }
2065 
2066  if (!fh && auth_status_code == 0) {
2067  *authorized_export = gf_strdup(pathdup);
2068  if (!*authorized_export)
2070  "Allocation error when copying "
2071  "authorized path");
2072 
2073  *authorized_host = gf_strdup(auth_host);
2074  if (!*authorized_host)
2076  "Allocation error when copying "
2077  "authorized host");
2078  }
2079 
2080 free_and_out:
2081  /* Free allocated strings after doing the auth */
2082  GF_FREE(peer_addr);
2083  GF_FREE(host_addr_fqdn);
2084  GF_FREE(host_addr_ip);
2085 out:
2086  return auth_status_code;
2087 }
2088 
2113 int
2115  struct nfs3_fh *fh, const char *volname,
2116  const char *path, char **authorized_path,
2117  char **authorized_host, gf_boolean_t is_write_op)
2118 {
2119  int auth_status_code = -EACCES;
2120  char *parent_path = NULL;
2121  const char *parent_old = NULL;
2122 
2125 
2126  /* If this option is not set, just allow it through */
2127  if (!ms->nfs->exports_auth) {
2128  /* This function is called in a variety of use-cases (mount
2129  * + each fop) so path/authorized_path are not always present.
2130  * For the cases which it _is_ present we need to populate the
2131  * authorized_path. */
2132  if (path && authorized_path)
2133  *authorized_path = gf_strdup(path);
2134 
2135  auth_status_code = 0;
2136  goto out;
2137  }
2138 
2139  /* First check if the path is allowed */
2140  auth_status_code = _mnt3_authenticate_req(
2141  ms, req, fh, path, authorized_path, authorized_host, is_write_op);
2142 
2143  /* If the filehandle is set, just exit since we have to make only
2144  * one call to the function above
2145  */
2146  if (fh)
2147  goto out;
2148 
2149  parent_old = path;
2150  while (auth_status_code != 0) {
2151  /* Get the path's parent */
2152  parent_path = gf_resolve_path_parent(parent_old);
2153  if (!parent_path) /* Nothing left in the path to resolve */
2154  goto out;
2155 
2156  /* Authenticate it */
2157  auth_status_code = _mnt3_authenticate_req(ms, req, fh, parent_path,
2158  authorized_path,
2159  authorized_host, is_write_op);
2160 
2161  parent_old = strdupa(parent_path); /* Copy the parent onto the
2162  * stack.
2163  */
2164 
2165  GF_FREE(parent_path); /* Free the allocated parent string */
2166  }
2167 
2168 out:
2169  return auth_status_code;
2170 }
2171 
2172 int
2174 {
2175  struct iovec pvec = {
2176  0,
2177  };
2178  char path[MNTPATHLEN];
2179  int ret = -1;
2180  struct mount3_state *ms = NULL;
2181  mountstat3 mntstat = MNT3ERR_SERVERFAULT;
2182  struct mnt3_export *exp = NULL;
2183  struct nfs_state *nfs = NULL;
2184  int authcode = 0;
2185 
2186  if (!req)
2187  return -1;
2188 
2189  pvec.iov_base = path;
2190  pvec.iov_len = MNTPATHLEN;
2191  ret = xdr_to_mountpath(pvec, req->msg[0]);
2192  if (ret == -1) {
2194  "Failed to decode args");
2195  rpcsvc_request_seterr(req, GARBAGE_ARGS);
2196  goto rpcerr;
2197  }
2198 
2199  ms = (struct mount3_state *)rpcsvc_request_program_private(req);
2200  if (!ms) {
2202  "Mount state not present");
2203  rpcsvc_request_seterr(req, SYSTEM_ERR);
2204  ret = -1;
2205  goto rpcerr;
2206  }
2207 
2208  nfs = (struct nfs_state *)ms->nfsx->private;
2209  gf_msg_debug(GF_MNT, 0, "dirpath: %s", path);
2210  ret = mnt3_find_export(req, path, &exp);
2211  if (ret < 0) {
2212  mntstat = mnt3svc_errno_to_mnterr(-ret);
2213  goto mnterr;
2214  } else if (!exp) {
2215  /*
2216  * SPECIAL CASE: exp is NULL if "path" is subdir in
2217  * call to mnt3_find_export().
2218  *
2219  * This is subdir mount, we are already DONE!
2220  * nfs_subvolume_started() and mnt3_check_client_net_tcp()
2221  * validation are done in mnt3_parse_dir_exports()
2222  * which is invoked through mnt3_find_export().
2223  *
2224  * TODO: All mount should happen thorugh mnt3svc_mount()
2225  * It needs more clean up.
2226  */
2227  return (0);
2228  }
2229 
2230  if (!nfs_subvolume_started(nfs, exp->vol)) {
2231  gf_msg_debug(GF_MNT, 0, "Volume %s not started", exp->vol->name);
2232  ret = -1;
2233  mntstat = MNT3ERR_NOENT;
2234  goto mnterr;
2235  }
2236 
2237  ret = mnt3_check_client_net_tcp(req, exp->vol->name);
2238  if (ret == RPCSVC_AUTH_REJECT) {
2239  mntstat = MNT3ERR_ACCES;
2240  gf_msg_debug(GF_MNT, 0, "Client mount not allowed");
2241  ret = -1;
2242  goto mnterr;
2243  }
2244 
2245  /* The second authentication check is the exports/netgroups
2246  * check.
2247  */
2248  authcode = mnt3_authenticate_request(ms, req, NULL, NULL, path, NULL, NULL,
2249  _gf_false);
2250  if (authcode != 0) {
2251  mntstat = MNT3ERR_ACCES;
2252  gf_msg_debug(GF_MNT, 0, "Client mount not allowed");
2253  ret = -1;
2254  goto mnterr;
2255  }
2256 
2257  ret = mnt3svc_mount(req, ms, exp);
2258 
2259  if (ret < 0)
2260  mntstat = mnt3svc_errno_to_mnterr(-ret);
2261 mnterr:
2262  if (ret < 0) {
2263  mnt3svc_mnt_error_reply(req, mntstat);
2264  ret = 0;
2265  }
2266 
2267 rpcerr:
2268  return ret;
2269 }
2270 
2271 int
2273 {
2274  struct iovec dummyvec = {
2275  0,
2276  };
2277 
2278  if (!req) {
2280  "Got NULL request!");
2281  return 0;
2282  }
2283  rpcsvc_submit_generic(req, &dummyvec, 1, NULL, 0, NULL);
2284  return 0;
2285 }
2286 
2287 mountlist
2288 __build_mountlist(struct mount3_state *ms, int *count)
2289 {
2290  struct mountbody *mlist = NULL;
2291  struct mountbody *prev = NULL;
2292  struct mountbody *first = NULL;
2293  size_t namelen = 0;
2294  int ret = -1;
2295  struct mountentry *me = NULL;
2296 
2297  if ((!ms) || (!count))
2298  return NULL;
2299 
2300  /* read rmtab, other peers might have updated it */
2301  mount_read_rmtab(ms);
2302 
2303  *count = 0;
2304  gf_msg_debug(GF_MNT, 0, "Building mount list:");
2306  {
2307  namelen = strlen(me->exname);
2308  mlist = GF_CALLOC(1, sizeof(*mlist), gf_nfs_mt_mountbody);
2309  if (!mlist) {
2311  "Memory allocation failed");
2312  goto free_list;
2313  }
2314  if (!first)
2315  first = mlist;
2316 
2317  mlist->ml_directory = GF_MALLOC(namelen + 2, gf_nfs_mt_char);
2318  if (!mlist->ml_directory) {
2320  "Memory allocation failed");
2321  goto free_list;
2322  }
2323 
2324  strcpy(mlist->ml_directory, me->exname);
2325 
2326  namelen = strlen(me->hostname);
2327  mlist->ml_hostname = GF_MALLOC(namelen + 2, gf_nfs_mt_char);
2328  if (!mlist->ml_hostname) {
2330  "Memory allocation failed");
2331  goto free_list;
2332  }
2333 
2334  strcpy(mlist->ml_hostname, me->hostname);
2335 
2336  gf_msg_debug(GF_MNT, 0, "mount entry: dir: %s, host: %s",
2337  mlist->ml_directory, mlist->ml_hostname);
2338  if (prev) {
2339  prev->ml_next = mlist;
2340  prev = mlist;
2341  } else
2342  prev = mlist;
2343 
2344  (*count)++;
2345  }
2346 
2347  ret = 0;
2348 
2349 free_list:
2350  if (ret == -1) {
2351  xdr_free_mountlist(first);
2352  first = NULL;
2353  }
2354 
2355  return first;
2356 }
2357 
2358 mountlist
2359 mnt3svc_build_mountlist(struct mount3_state *ms, int *count)
2360 {
2361  struct mountbody *first = NULL;
2362 
2363  LOCK(&ms->mountlock);
2364  {
2365  first = __build_mountlist(ms, count);
2366  }
2367  UNLOCK(&ms->mountlock);
2368 
2369  return first;
2370 }
2371 
2372 int
2374 {
2375  int ret = -1;
2376  struct mount3_state *ms = NULL;
2377  mountlist mlist;
2378  mountstat3 mstat = 0;
2379  mnt3_serializer sfunc = NULL;
2380  void *arg = NULL;
2381 
2382  if (!req)
2383  return -1;
2384 
2385  ms = (struct mount3_state *)rpcsvc_request_program_private(req);
2386  if (!ms) {
2387  rpcsvc_request_seterr(req, SYSTEM_ERR);
2388  goto rpcerr;
2389  }
2390 
2392  mlist = mnt3svc_build_mountlist(ms, &ret);
2393  arg = &mlist;
2394 
2395  if (!mlist) {
2396  if (ret != 0) {
2397  rpcsvc_request_seterr(req, SYSTEM_ERR);
2398  ret = -1;
2399  goto rpcerr;
2400  } else {
2401  arg = &mstat;
2403  }
2404  }
2405 
2406  mnt3svc_submit_reply(req, arg, sfunc);
2407 
2408  xdr_free_mountlist(mlist);
2409  ret = 0;
2410 
2411 rpcerr:
2412  return ret;
2413 }
2414 
2415 int
2416 mnt3svc_umount(struct mount3_state *ms, char *dirpath, char *hostname)
2417 {
2418  struct mountentry *me = NULL;
2419  int ret = -1;
2420  gf_store_handle_t *sh = NULL;
2421  struct nfs_state *nfs = NULL;
2422  gf_boolean_t update_rmtab = _gf_false;
2423 
2424  if ((!ms) || (!dirpath) || (!hostname))
2425  return -1;
2426 
2427  nfs = (struct nfs_state *)ms->nfsx->private;
2428 
2429  update_rmtab = mount_open_rmtab(nfs->rmtab, &sh);
2430  if (update_rmtab) {
2431  ret = gf_store_lock(sh);
2432  if (ret)
2433  goto out_free;
2434  }
2435 
2436  LOCK(&ms->mountlock);
2437  {
2438  if (update_rmtab)
2440 
2441  if (list_empty(&ms->mountlist)) {
2442  ret = 0;
2443  goto out_unlock;
2444  }
2445 
2446  ret = -1;
2447  list_for_each_entry(me, &ms->mountlist, mlist)
2448  {
2449  if ((strcmp(me->exname, dirpath) == 0) &&
2450  (strcmp(me->hostname, hostname) == 0)) {
2451  ret = 0;
2452  break;
2453  }
2454  }
2455 
2456  /* Need this check here because at the end of the search me
2457  * might still be pointing to the last entry, which may not be
2458  * the one we're looking for.
2459  */
2460  if (ret == -1) { /* Not found in list. */
2461  gf_msg_trace(GF_MNT, 0, "Export not found");
2462  goto out_unlock;
2463  }
2464 
2465  if (!me)
2466  goto out_unlock;
2467 
2468  gf_msg_debug(GF_MNT, 0, "Unmounting: dir %s, host: %s", me->exname,
2469  me->hostname);
2470 
2471  list_del(&me->mlist);
2472  GF_FREE(me);
2473 
2474  if (update_rmtab)
2475  __mount_rewrite_rmtab(ms, sh);
2476  }
2477 out_unlock:
2478  UNLOCK(&ms->mountlock);
2479 
2480  if (update_rmtab)
2481  gf_store_unlock(sh);
2482 
2483 out_free:
2484  if (update_rmtab)
2486 
2487  return ret;
2488 }
2489 
2490 int
2492 {
2493  char hostname[MNTPATHLEN];
2494  char dirpath[MNTPATHLEN];
2495  struct iovec pvec = {
2496  0,
2497  };
2498  int ret = -1;
2499  struct mount3_state *ms = NULL;
2500  mountstat3 mstat = MNT3_OK;
2501  char *colon = NULL;
2502 
2503  if (!req)
2504  return -1;
2505 
2506  /* Remove the mount point from the exports list. */
2507  pvec.iov_base = dirpath;
2508  pvec.iov_len = MNTPATHLEN;
2509  ret = xdr_to_mountpath(pvec, req->msg[0]);
2510  if (ret == -1) {
2512  "Failed decode args");
2513  rpcsvc_request_seterr(req, GARBAGE_ARGS);
2514  goto rpcerr;
2515  }
2516 
2517  ms = (struct mount3_state *)rpcsvc_request_program_private(req);
2518  if (!ms) {
2520  "Mount state not present");
2521  rpcsvc_request_seterr(req, SYSTEM_ERR);
2522  ret = -1;
2523  goto rpcerr;
2524  }
2525 
2526  ret = rpcsvc_transport_peername(req->trans, hostname, MNTPATHLEN);
2527  if (ret != 0) {
2529  "Failed to get remote name: %s", gai_strerror(ret));
2530  goto rpcerr;
2531  }
2532 
2533  colon = strrchr(hostname, ':');
2534  if (colon) {
2535  *colon = '\0';
2536  }
2538  gf_msg_debug(GF_MNT, 0, "dirpath: %s, hostname: %s", dirpath, hostname);
2539  ret = mnt3svc_umount(ms, dirpath, hostname);
2540 
2541  if (ret == -1) {
2542  ret = 0;
2543  mstat = MNT3ERR_NOENT;
2544  }
2545  /* FIXME: also take care of the corner case where the
2546  * client was resolvable at mount but not at the umount - vice-versa.
2547  */
2548  mnt3svc_submit_reply(req, &mstat,
2550 
2551 rpcerr:
2552  return ret;
2553 }
2554 
2555 int
2557 {
2558  struct mountentry *me = NULL;
2559  struct mountentry *tmp = NULL;
2560 
2561  if (!ms)
2562  return -1;
2563 
2564  if (list_empty(&ms->mountlist))
2565  return 0;
2566 
2567  list_for_each_entry_safe(me, tmp, &ms->mountlist, mlist)
2568  {
2569  list_del(&me->mlist); /* Remove from the mount list */
2570  __mountdict_remove(ms, me); /* Remove from the mount dict */
2571  GF_FREE(me);
2572  }
2573 
2574  return 0;
2575 }
2576 
2577 int
2579 {
2580  int ret = -1;
2581  if (!ms)
2582  return -1;
2583 
2584  LOCK(&ms->mountlock);
2585  {
2586  ret = __mnt3svc_umountall(ms);
2587  }
2588  UNLOCK(&ms->mountlock);
2589 
2590  return ret;
2591 }
2592 
2593 int
2595 {
2596  int ret = RPCSVC_ACTOR_ERROR;
2597  struct mount3_state *ms = NULL;
2598  mountstat3 mstat = MNT3_OK;
2599 
2600  if (!req)
2601  return ret;
2602 
2603  ms = (struct mount3_state *)rpcsvc_request_program_private(req);
2604  if (!ms) {
2606  "Mount state not present");
2607  rpcsvc_request_seterr(req, SYSTEM_ERR);
2608  goto rpcerr;
2609  }
2610 
2611  mnt3svc_umountall(ms);
2612  mnt3svc_submit_reply(req, &mstat,
2614 
2615  ret = RPCSVC_ACTOR_SUCCESS;
2616 rpcerr:
2617  return ret;
2618 }
2619 
2620 exports
2622 {
2623  struct exportnode *elist = NULL;
2624  struct exportnode *prev = NULL;
2625  struct exportnode *first = NULL;
2626  size_t namelen = 0;
2627  int ret = -1;
2628  char *addrstr = NULL;
2629  struct mnt3_export *ent = NULL;
2630  struct nfs_state *nfs = NULL;
2631 
2632  if ((!ms) || (!svc))
2633  return NULL;
2634 
2635  nfs = (struct nfs_state *)ms->nfsx->private;
2636  if (!nfs)
2637  return NULL;
2638 
2639  LOCK(&ms->mountlock);
2640  list_for_each_entry(ent, &ms->exportlist, explist)
2641  {
2642  /* If volume is not started yet, do not list it for tools like
2643  * showmount.
2644  */
2645  if (!nfs_subvolume_started(nfs, ent->vol))
2646  continue;
2647 
2648  elist = GF_CALLOC(1, sizeof(*elist), gf_nfs_mt_exportnode);
2649  if (!elist) {
2651  "Memory allocation failed");
2652  goto free_list;
2653  }
2654  if (!first)
2655  first = elist;
2656  namelen = strlen(ent->expname);
2657  elist->ex_dir = GF_MALLOC(namelen + 2, gf_nfs_mt_char);
2658  if (!elist->ex_dir) {
2660  "Memory allocation failed");
2661  if (first == elist)
2662  first = NULL;
2663  xdr_free_exports_list(elist);
2664  elist = NULL;
2665  goto free_list;
2666  }
2667  strcpy(elist->ex_dir, ent->expname);
2668 
2669  addrstr = rpcsvc_volume_allowed(svc->options, ent->vol->name);
2670  if (addrstr) {
2671  /* create a groupnode per allowed client */
2672  char *pos = NULL;
2673  char *addr = NULL;
2674  char *addrs = NULL;
2675  struct groupnode *group = NULL;
2676  struct groupnode *prev_group = NULL;
2677 
2678  /* strtok_r() modifies the string, dup it */
2679  addrs = gf_strdup(addrstr);
2680  if (!addrs)
2681  goto free_list;
2682 
2683  while (1) {
2684  /* only pass addrs on the 1st call */
2685  addr = strtok_r(group ? NULL : addrs, ",", &pos);
2686  if (addr == NULL)
2687  /* no mode clients */
2688  break;
2689 
2690  group = GF_CALLOC(1, sizeof(struct groupnode),
2692  if (!group) {
2694  "Memory "
2695  "allocation failed");
2696  GF_FREE(addrs);
2697  goto free_list;
2698  }
2699 
2700  group->gr_name = gf_strdup(addr);
2701  if (!group->gr_name) {
2703  "Memory "
2704  "allocation failed");
2705  GF_FREE(group);
2706  GF_FREE(addrs);
2707  goto free_list;
2708  }
2709 
2710  /* chain the groups together */
2711  if (!elist->ex_groups)
2712  elist->ex_groups = group;
2713  else if (prev_group && !prev_group->gr_next)
2714  prev_group->gr_next = group;
2715  prev_group = group;
2716  }
2717 
2718  GF_FREE(addrs);
2719  } else {
2720  elist->ex_groups = GF_CALLOC(1, sizeof(struct groupnode),
2722  if (!elist->ex_groups) {
2724  "Memory allocation "
2725  "failed");
2726  goto free_list;
2727  }
2728 
2729  addrstr = gf_strdup("No Access");
2730  if (!addrstr)
2731  goto free_list;
2732 
2733  elist->ex_groups->gr_name = addrstr;
2734  }
2735 
2736  if (prev) {
2737  prev->ex_next = elist;
2738  prev = elist;
2739  } else
2740  prev = elist;
2741  }
2742 
2743  ret = 0;
2744 
2745 free_list:
2746  UNLOCK(&ms->mountlock);
2747  if (ret == -1) {
2748  xdr_free_exports_list(first);
2749  first = NULL;
2750  }
2751 
2752  return first;
2753 }
2754 
2755 int
2757 {
2758  struct mount3_state *ms = NULL;
2759  exports elist = NULL;
2760  int ret = -1;
2761 
2762  if (!req)
2763  return -1;
2764 
2765  ms = (struct mount3_state *)rpcsvc_request_program_private(req);
2766  if (!ms) {
2768  "mount state not found");
2769  rpcsvc_request_seterr(req, SYSTEM_ERR);
2770  goto err;
2771  }
2772 
2773  /* Using the children translator names, build the export list */
2775  /* Do not return error when exports list is empty. An exports list can
2776  * be empty when no subvolumes have come up. No point returning error
2777  * and confusing the user.
2778  if (!elist) {
2779  gf_log (GF_MNT, GF_LOG_ERROR, "Failed to build exports list");
2780  nfs_rpcsvc_request_seterr (req, SYSTEM_ERR);
2781  goto err;
2782  }
2783  */
2784 
2785  /* Note how the serializer is passed to the generic reply function. */
2787 
2788  xdr_free_exports_list(elist);
2789  ret = 0;
2790 err:
2791  return ret;
2792 }
2793 
2794 /*
2795  * __mnt3udp_get_mstate() Fetches mount3_state from xlator
2796  * Linkage: Static
2797  * Usage: Used only for UDP MOUNT codepath
2798  */
2799 static struct mount3_state *
2801 {
2802  struct nfs_state *nfs = NULL;
2803  struct mount3_state *ms = NULL;
2804 
2805  if (nfsx == NULL)
2806  return NULL;
2807 
2808  nfs = (struct nfs_state *)nfsx->private;
2809  if (nfs == NULL)
2810  return NULL;
2811 
2812  ms = (struct mount3_state *)nfs->mstate;
2813  return ms;
2814 }
2815 
2816 extern int
2817 glfs_resolve_at(struct glfs *, xlator_t *, inode_t *, const char *, loc_t *,
2818  struct iatt *, int, int);
2819 
2820 extern struct glfs *
2822 
2823 extern void
2825 
2826 static inode_t *
2827 __mnt3udp_get_export_subdir_inode(struct svc_req *req, char *subdir,
2828  char *expname, /* OUT */
2829  struct mnt3_export *exp)
2830 {
2831  inode_t *inode = NULL;
2832  loc_t loc = {
2833  0,
2834  };
2835  struct iatt buf = {
2836  0,
2837  };
2838  int ret = -1;
2839  glfs_t *fs = NULL;
2840 
2841  if ((!req) || (!subdir) || (!expname) || (!exp))
2842  return NULL;
2843 
2844  /* AUTH check for subdir i.e. nfs.export-dir */
2845  if (exp->hostspec) {
2846  struct sockaddr_in *sin = NULL;
2847 
2848 #if !defined(_TIRPC_SVC_H)
2849  sin = svc_getcaller(req->rq_xprt);
2850 #else
2851  sin = (struct sockaddr_in *)svc_getcaller(req->rq_xprt);
2852  /* TIRPC's svc_getcaller() returns a pointer to a
2853  * sockaddr_in6, even though it might actually be an
2854  * IPv4 address. It ought return a struct sockaddr and
2855  * make the caller upcast it to the proper address family.
2856  */
2857 #endif
2858  /* And let's make sure that it's actually an IPv4 address. */
2859  GF_ASSERT(sin->sin_family == AF_INET);
2860 
2861  ret = mnt3_verify_auth(sin, exp);
2862  if (ret) {
2864  "AUTH(nfs.export-dir) verification failed");
2865  errno = EACCES;
2866  return NULL;
2867  }
2868  }
2869 
2870  /*
2871  * IMP: glfs_t fs object is not used by glfs_resolve_at (). The main
2872  * purpose is to not change the ABI of glfs_resolve_at () and not to
2873  * pass a NULL object.
2874  *
2875  * TODO: Instead of linking against libgfapi.so, just for one API
2876  * i.e. glfs_resolve_at(), It would be cleaner if PATH name to
2877  * inode resolution code can be moved to libglusterfs.so or so.
2878  * refer bugzilla for more details :
2879  * https://bugzilla.redhat.com/show_bug.cgi?id=1161573
2880  */
2881  fs = glfs_new_from_ctx(exp->vol->ctx);
2882  if (!fs)
2883  return NULL;
2884 
2885  ret = glfs_resolve_at(fs, exp->vol, NULL, subdir, &loc, &buf,
2886  1 /* Follow link */, 0 /* Hard lookup */);
2887 
2888  glfs_free_from_ctx(fs);
2889 
2890  if (ret != 0) {
2891  loc_wipe(&loc);
2892  return NULL;
2893  }
2894 
2895  inode = inode_ref(loc.inode);
2896  snprintf(expname, PATH_MAX, "/%s%s", exp->vol->name, loc.path);
2897 
2898  loc_wipe(&loc);
2899 
2900  return inode;
2901 }
2902 
2903 static inode_t *
2904 __mnt3udp_get_export_volume_inode(struct svc_req *req, char *volpath,
2905  char *expname, /* OUT */
2906  struct mnt3_export *exp)
2907 {
2908  char *rpath = NULL;
2909  inode_t *inode = NULL;
2910 
2911  if ((!req) || (!volpath) || (!expname) || (!exp))
2912  return NULL;
2913 
2914  rpath = strchr(volpath, '/');
2915  if (rpath == NULL)
2916  rpath = "/";
2917 
2918  inode = inode_from_path(exp->vol->itable, rpath);
2919  snprintf(expname, PATH_MAX, "/%s", exp->vol->name);
2920 
2921  return inode;
2922 }
2923 
2924 /*
2925  * nfs3_rootfh() is used for NFS MOUNT over UDP i.e. mountudpproc3_mnt_3_svc().
2926  * Especially in mount3udp_thread() THREAD. Gluster NFS starts this thread
2927  * when nfs.mount-udp is ENABLED (set to TRUE/ON).
2928  */
2929 struct nfs3_fh *
2930 nfs3_rootfh(struct svc_req *req, xlator_t *nfsx, char *path,
2931  char *expname /* OUT */)
2932 {
2933  struct nfs3_fh *fh = NULL;
2934  inode_t *inode = NULL;
2935  struct mnt3_export *exp = NULL;
2936  struct mount3_state *ms = NULL;
2937  struct nfs_state *nfs = NULL;
2938  int mnt3type = MNT3_EXPTYPE_DIR;
2939  int ret = RPCSVC_AUTH_REJECT;
2940 
2941  if ((!req) || (!nfsx) || (!path) || (!expname)) {
2942  errno = EFAULT;
2943  return NULL;
2944  }
2945 
2946  /*
2947  * 1. First check if the MOUNT is for whole volume.
2948  * i.e. __mnt3udp_get_export_volume_inode ()
2949  * 2. If NOT, then TRY for SUBDIR MOUNT.
2950  * i.e. __mnt3udp_get_export_subdir_inode ()
2951  * 3. If a subdir is exported using nfs.export-dir,
2952  * then the mount type would be MNT3_EXPTYPE_DIR,
2953  * so make sure to find the proper path to be
2954  * resolved using mnt3_get_volume_subdir()
2955  * 3. Make sure subdir export is allowed.
2956  */
2957  ms = __mnt3udp_get_mstate(nfsx);
2958  if (!ms) {
2959  errno = EFAULT;
2960  return NULL;
2961  }
2962 
2963  exp = mnt3_mntpath_to_export(ms, path, _gf_false);
2964  if (exp != NULL)
2965  mnt3type = exp->exptype;
2966 
2967  if (mnt3type == MNT3_EXPTYPE_DIR) {
2968  char volname[MNTPATHLEN] = {
2969  0,
2970  };
2971  char *volptr = volname;
2972 
2973  /* Subdir export (nfs3.export-dirs) check */
2974  if (!gf_mnt3_export_dirs(ms)) {
2975  errno = EACCES;
2976  return NULL;
2977  }
2978 
2979  path = mnt3_get_volume_subdir(path, &volptr);
2980  if (exp == NULL)
2981  exp = mnt3_mntpath_to_export(ms, volname, _gf_false);
2982  }
2983 
2984  if (exp == NULL) {
2985  errno = ENOENT;
2986  return NULL;
2987  }
2988 
2989  nfs = (struct nfs_state *)nfsx->private;
2990  if (!nfs_subvolume_started(nfs, exp->vol)) {
2991  errno = ENOENT;
2992  return NULL;
2993  }
2994 
2995  /* AUTH check: respect nfs.rpc-auth-allow/reject */
2996  ret = mnt3_check_client_net_udp(req, exp->vol->name, nfsx);
2997  if (ret == RPCSVC_AUTH_REJECT) {
2998  errno = EACCES;
2999  return NULL;
3000  }
3001 
3002  switch (mnt3type) {
3003  case MNT3_EXPTYPE_VOLUME:
3004  inode = __mnt3udp_get_export_volume_inode(req, path, expname, exp);
3005  break;
3006 
3007  case MNT3_EXPTYPE_DIR:
3008  inode = __mnt3udp_get_export_subdir_inode(req, path, expname, exp);
3009  break;
3010 
3011  default:
3012  /* Never reachable */
3014  "Unknown MOUNT3 type");
3015  errno = EFAULT;
3016  goto err;
3017  }
3018 
3019  if (inode == NULL) {
3020  /* Don't over-write errno */
3021  if (!errno)
3022  errno = ENOENT;
3023  goto err;
3024  }
3025 
3026  /* Build the inode from FH */
3027  fh = GF_CALLOC(1, sizeof(*fh), gf_nfs_mt_nfs3_fh);
3028  if (fh == NULL) {
3029  errno = ENOMEM;
3030  goto err;
3031  }
3032 
3033  (void)nfs3_build_fh(inode, exp->volumeid, fh);
3034 
3035 err:
3036  if (inode)
3037  inode_unref(inode);
3038 
3039  return fh;
3040 }
3041 
3042 int
3043 mount3udp_add_mountlist(xlator_t *nfsx, char *host, char *export)
3044 {
3045  struct mountentry *me = NULL;
3046  struct mount3_state *ms = NULL;
3047 
3048  if ((!host) || (!export) || (!nfsx))
3049  return -1;
3050 
3051  ms = __mnt3udp_get_mstate(nfsx);
3052  if (!ms)
3053  return -1;
3054 
3055  me = GF_CALLOC(1, sizeof(*me), gf_nfs_mt_mountentry);
3056  if (!me)
3057  return -1;
3058 
3059  snprintf(me->exname, MNTPATHLEN, "%s", export);
3060  snprintf(me->hostname, MNTPATHLEN, "%s", host);
3061  INIT_LIST_HEAD(&me->mlist);
3062  LOCK(&ms->mountlock);
3063  {
3064  list_add_tail(&me->mlist, &ms->mountlist);
3065  mount_rewrite_rmtab(ms, NULL);
3066  }
3067  UNLOCK(&ms->mountlock);
3068  return 0;
3069 }
3070 
3071 int
3072 mount3udp_delete_mountlist(xlator_t *nfsx, char *hostname, char *export)
3073 {
3074  struct mount3_state *ms = NULL;
3075 
3076  if ((!hostname) || (!export) || (!nfsx))
3077  return -1;
3078 
3079  ms = __mnt3udp_get_mstate(nfsx);
3080  if (!ms)
3081  return -1;
3082 
3083  mnt3svc_umount(ms, export, hostname);
3084  return 0;
3085 }
3086 
3098 int
3099 mnt3_export_fill_hostspec(struct host_auth_spec *hostspec, const char *hostip)
3100 {
3101  char *ipdupstr = NULL;
3102  char *savptr = NULL;
3103  char *endptr = NULL;
3104  char *ip = NULL;
3105  char *token = NULL;
3106  int ret = -1;
3107  long prefixlen = IPv4_ADDR_SIZE; /* default */
3108  uint32_t shiftbits = 0;
3109  size_t length = 0;
3110 
3111  /* Create copy of the string so that the source won't change
3112  */
3113  ipdupstr = gf_strdup(hostip);
3114  if (NULL == ipdupstr) {
3116  "Memory allocation failed");
3117  goto err;
3118  }
3119 
3120  ip = strtok_r(ipdupstr, "/", &savptr);
3121  /* Validate the Hostname or IPv4 address
3122  * TODO: IPv6 support for subdir auth.
3123  */
3124  length = strlen(ip);
3125  if ((!valid_ipv4_address(ip, (int)length, _gf_false)) &&
3126  (!valid_host_name(ip, (int)length))) {
3128  "Invalid hostname or IPv4 address: %s", ip);
3129  goto err;
3130  }
3131 
3132  hostspec->host_addr = gf_strdup(ip);
3133  if (NULL == hostspec->host_addr) {
3135  "Memory allocation failed");
3136  goto err;
3137  }
3138 
3154  token = strtok_r(NULL, "/", &savptr);
3155  if (token != NULL) {
3156  prefixlen = strtol(token, &endptr, 10);
3157  if ((errno != 0) || (*endptr != '\0') || (prefixlen < 0) ||
3158  (prefixlen > IPv4_ADDR_SIZE)) {
3160  "Invalid IPv4 subnetwork mask");
3161  goto err;
3162  }
3163  }
3164 
3165  /*
3166  * 1. Calculate the network mask address.
3167  * 2. Convert it into Big-Endian format.
3168  * 3. Store it in hostspec netmask.
3169  */
3170  shiftbits = IPv4_ADDR_SIZE - prefixlen;
3171  hostspec->netmask = htonl((uint32_t)~0 << shiftbits);
3172 
3173  ret = 0; /* SUCCESS */
3174 err:
3175  if (NULL != ipdupstr) {
3176  GF_FREE(ipdupstr);
3177  }
3178  return ret;
3179 }
3180 
3193 int
3194 mnt3_export_parse_auth_param(struct mnt3_export *exp, char *exportpath)
3195 {
3196  char *token = NULL;
3197  char *savPtr = NULL;
3198  char *hostip = NULL;
3199  struct host_auth_spec *host = NULL;
3200  int ret = 0;
3201 
3202  if (exportpath == NULL) {
3204  "Export path is NULL");
3205  return -1;
3206  }
3207 
3208  /* Using exportpath directly in strtok_r because we want
3209  * to strip off AUTH parameter from exportpath. */
3210  token = strtok_r(exportpath, "(", &savPtr);
3211 
3212  /* Get the next token, which will be the AUTH parameter. */
3213  token = strtok_r(NULL, ")", &savPtr);
3214 
3215  if (NULL == token) {
3216  /* If AUTH is not present then we should return success. */
3217  return 0;
3218  }
3219 
3220  /* Free any previously allocated hostspec structure. */
3221  if (NULL != exp->hostspec) {
3222  GF_FREE(exp->hostspec);
3223  exp->hostspec = NULL;
3224  }
3225 
3226  exp->hostspec = GF_CALLOC(1, sizeof(*(exp->hostspec)), gf_nfs_mt_auth_spec);
3227  if (NULL == exp->hostspec) {
3229  "Memory allocation failed");
3230  return -1;
3231  }
3232 
3233  /* AUTH parameter can have multiple entries. For each entry
3234  * a host_auth_spec structure is created. */
3235  host = exp->hostspec;
3236 
3237  hostip = strtok_r(token, "|", &savPtr);
3238 
3239  /* Parse all AUTH parameters separated by '|' */
3240  while (NULL != hostip) {
3241  ret = mnt3_export_fill_hostspec(host, hostip);
3242  if (0 != ret) {
3244  "Failed to parse hostspec: %s", hostip);
3245  goto err;
3246  }
3247 
3248  hostip = strtok_r(NULL, "|", &savPtr);
3249  if (NULL == hostip) {
3250  break;
3251  }
3252 
3253  host->next = GF_CALLOC(1, sizeof(*(host)), gf_nfs_mt_auth_spec);
3254  if (NULL == host->next) {
3256  "Memory allocation failed");
3257  goto err;
3258  }
3259  host = host->next;
3260  }
3261 
3262  /* In case of success return from here */
3263  return 0;
3264 err:
3265  /* In case of failure free up hostspec structure. */
3266  FREE_HOSTSPEC(exp);
3267 
3268  return -1;
3269 }
3270 
3276 struct mnt3_export *
3277 mnt3_init_export_ent(struct mount3_state *ms, xlator_t *xl, char *exportpath,
3278  uuid_t volumeid)
3279 {
3280  struct mnt3_export *exp = NULL;
3281  int alloclen = 0;
3282  int ret = -1;
3283 
3284  if ((!ms) || (!xl))
3285  return NULL;
3286 
3287  exp = GF_CALLOC(1, sizeof(*exp), gf_nfs_mt_mnt3_export);
3288  if (!exp) {
3290  "Memory allocation failed");
3291  return NULL;
3292  }
3293 
3294  if (NULL != exportpath) {
3295  /* If exportpath is not NULL then we should check if AUTH
3296  * parameter is present or not. If AUTH parameter is present
3297  * then it will be stripped and stored in mnt3_export (exp)
3298  * structure.
3299  */
3300  if (0 != mnt3_export_parse_auth_param(exp, exportpath)) {
3302  "Failed to parse auth param");
3303  goto err;
3304  }
3305  }
3306 
3307  INIT_LIST_HEAD(&exp->explist);
3308  if (exportpath)
3309  alloclen = strlen(xl->name) + 2 + strlen(exportpath);
3310  else
3311  alloclen = strlen(xl->name) + 2;
3312 
3313  exp->expname = GF_MALLOC(alloclen, gf_nfs_mt_char);
3314  if (!exp->expname) {
3316  "Memory allocation failed");
3317  goto err;
3318  }
3319 
3320  if (exportpath) {
3321  gf_msg_trace(GF_MNT, 0, "Initing dir export: %s:%s", xl->name,
3322  exportpath);
3323  exp->exptype = MNT3_EXPTYPE_DIR;
3324  ret = snprintf(exp->expname, alloclen, "/%s%s", xl->name, exportpath);
3325  } else {
3326  gf_msg_trace(GF_MNT, 0, "Initing volume export: %s", xl->name);
3328  ret = snprintf(exp->expname, alloclen, "/%s", xl->name);
3329  }
3330  if (ret < 0) {
3332  "Failed to set the export name");
3333  goto err;
3334  }
3335  /* Just copy without discrimination, we'll determine whether to
3336  * actually use it when a mount request comes in and a file handle
3337  * needs to be built.
3338  */
3340  exp->vol = xl;
3341 
3342  /* On success we should return from here*/
3343  return exp;
3344 err:
3345  /* On failure free exp and it's members.*/
3346  if (NULL != exp) {
3347  mnt3_export_free(exp);
3348  exp = NULL;
3349  }
3350 
3351  return exp;
3352 }
3353 
3354 int
3356  char *optstr, uuid_t volumeid)
3357 {
3358  struct mnt3_export *newexp = NULL;
3359  int ret = -1;
3360  char *savptr = NULL;
3361  char *dupopt = NULL;
3362  char *token = NULL;
3363 
3364  if ((!ms) || (!xlator) || (!optstr))
3365  return -1;
3366 
3367  dupopt = strdupa(optstr);
3368 
3369  token = strtok_r(dupopt, ",", &savptr);
3370  while (token) {
3371  newexp = mnt3_init_export_ent(ms, xlator, token, volumeid);
3372  if (!newexp) {
3374  "Failed to init dir "
3375  "export: %s",
3376  token);
3377  ret = -1;
3378  goto err;
3379  }
3380 
3381  list_add_tail(&newexp->explist, &ms->exportlist);
3382  token = strtok_r(NULL, ",", &savptr);
3383  }
3384 
3385  ret = 0;
3386 err:
3387  return ret;
3388 }
3389 
3390 int
3392 {
3393  struct mnt3_export *newexp = NULL;
3394  int ret = -1;
3395  char searchstr[1024];
3396  char *optstr = NULL;
3397  uuid_t volumeid = {
3398  0,
3399  };
3400 
3401  if ((!ms) || (!xlator) || (!opts))
3402  return -1;
3403 
3405  if (gf_nfs_dvm_off(nfs_state(ms->nfsx)))
3406  goto no_dvm;
3407 
3408  ret = snprintf(searchstr, 1024, "nfs3.%s.volume-id", xlator->name);
3409  if (ret < 0) {
3411  "snprintf failed");
3412  ret = -1;
3413  goto err;
3414  }
3415 
3416  if (dict_get(opts, searchstr)) {
3417  ret = dict_get_str(opts, searchstr, &optstr);
3418  if (ret < 0) {
3420  "Failed to read "
3421  "option: %s",
3422  searchstr);
3423  ret = -1;
3424  goto err;
3425  }
3426  } else {
3428  "DVM is on but volume-id not "
3429  "given for volume: %s",
3430  xlator->name);
3431  ret = -1;
3432  goto err;
3433  }
3434 
3435  if (optstr) {
3436  ret = gf_uuid_parse(optstr, volumeid);
3437  if (ret < 0) {
3439  "Failed to parse "
3440  "volume UUID");
3441  ret = -1;
3442  goto err;
3443  }
3444  }
3445 
3446 no_dvm:
3447  ret = snprintf(searchstr, 1024, "nfs3.%s.export-dir", xlator->name);
3448  if (ret < 0) {
3450  "snprintf failed");
3451  ret = -1;
3452  goto err;
3453  }
3454 
3455  if (dict_get(opts, searchstr)) {
3456  ret = dict_get_str(opts, searchstr, &optstr);
3457  if (ret < 0) {
3459  "Failed to read "
3460  "option: %s",
3461  searchstr);
3462  ret = -1;
3463  goto err;
3464  }
3465 
3466  ret = __mnt3_init_volume_direxports(ms, xlator, optstr, volumeid);
3467  if (ret == -1) {
3469  "Dir export "
3470  "setup failed for volume: %s",
3471  xlator->name);
3472  goto err;
3473  }
3474  }
3475 
3476  if (ms->export_volumes) {
3477  newexp = mnt3_init_export_ent(ms, xlator, NULL, volumeid);
3478  if (!newexp) {
3479  ret = -1;
3480  goto err;
3481  }
3482 
3483  list_add_tail(&newexp->explist, &ms->exportlist);
3484  }
3485  ret = 0;
3486 
3487 err:
3488  return ret;
3489 }
3490 
3491 int
3493 {
3494  int ret = -1;
3495  char *optstr = NULL;
3496  /* On by default. */
3497  gf_boolean_t boolt = _gf_true;
3498 
3499  if ((!ms) || (!opts))
3500  return -1;
3501 
3502  if (!dict_get(opts, "nfs3.export-volumes")) {
3503  ret = 0;
3504  goto err;
3505  }
3506 
3507  ret = dict_get_str(opts, "nfs3.export-volumes", &optstr);
3508  if (ret < 0) {
3510  "Failed to read option: nfs3.export-volumes");
3511  ret = -1;
3512  goto err;
3513  }
3514 
3515  ret = gf_string2boolean(optstr, &boolt);
3516  if (ret < 0) {
3518  "Failed to convert string to boolean");
3519  }
3520 
3521 err:
3522  if (boolt == _gf_false) {
3523  gf_msg_trace(GF_MNT, 0, "Volume exports disabled");
3524  ms->export_volumes = 0;
3525  } else {
3526  gf_msg_trace(GF_MNT, 0, "Volume exports enabled");
3527  ms->export_volumes = 1;
3528  }
3529 
3530  return ret;
3531 }
3532 
3533 int
3535 {
3536  int ret = -1;
3537  char *optstr = NULL;
3538  /* On by default. */
3539  gf_boolean_t boolt = _gf_true;
3540 
3541  if ((!ms) || (!opts))
3542  return -1;
3543 
3544  if (!dict_get(opts, "nfs3.export-dirs")) {
3545  ret = 0;
3546  goto err;
3547  }
3548 
3549  ret = dict_get_str(opts, "nfs3.export-dirs", &optstr);
3550  if (ret < 0) {
3552  "Failed to read option: nfs3.export-dirs");
3553  ret = -1;
3554  goto err;
3555  }
3556 
3557  ret = gf_string2boolean(optstr, &boolt);
3558  if (ret < 0) {
3560  "Failed to convert string to boolean");
3561  }
3562 
3563 err:
3564  if (boolt == _gf_false) {
3565  gf_msg_trace(GF_MNT, 0, "Dir exports disabled");
3566  ms->export_dirs = 0;
3567  } else {
3568  gf_msg_trace(GF_MNT, 0, "Dir exports enabled");
3569  ms->export_dirs = 1;
3570  }
3571 
3572  return ret;
3573 }
3574 
3575 int
3577 {
3578  xlator_list_t *volentry = NULL;
3579  int ret = -1;
3580 
3581  if ((!ms) || (!options))
3582  return -1;
3583 
3586  volentry = ms->nfsx->children;
3587  while (volentry) {
3588  gf_msg_trace(GF_MNT, 0, "Initing options for: %s",
3589  volentry->xlator->name);
3590  ret = __mnt3_init_volume(ms, options, volentry->xlator);
3591  if (ret < 0) {
3593  "Volume init failed");
3594  goto err;
3595  }
3596 
3597  volentry = volentry->next;
3598  }
3599 
3600  ret = 0;
3601 err:
3602  return ret;
3603 }
3604 
3605 struct mount3_state *
3607 {
3608  struct mount3_state *ms = NULL;
3609  int ret = -1;
3610 
3611  if (!nfsx)
3612  return NULL;
3613 
3614  ms = GF_CALLOC(1, sizeof(*ms), gf_nfs_mt_mount3_state);
3615  if (!ms) {
3617  "Memory allocation failed");
3618  return NULL;
3619  }
3620 
3621  ms->iobpool = nfsx->ctx->iobuf_pool;
3622  ms->nfsx = nfsx;
3623  INIT_LIST_HEAD(&ms->exportlist);
3624  ret = mnt3_init_options(ms, nfsx->options);
3625  if (ret < 0) {
3627  "Options init failed");
3628  return NULL;
3629  }
3630 
3631  INIT_LIST_HEAD(&ms->mountlist);
3632  LOCK_INIT(&ms->mountlock);
3633 
3634  return ms;
3635 }
3636 
3637 int
3639 {
3640  int ret = -1;
3641  struct nfs_state *nfs = NULL;
3642 
3643  if (!nfsx)
3644  goto out;
3645 
3646  nfs = (struct nfs_state *)nfs_state(nfsx);
3647  /*Maintaining global state for MOUNT1 and MOUNT3*/
3648  nfs->mstate = mnt3_init_state(nfsx);
3649  if (!nfs->mstate) {
3651  "Failed to allocate mount state");
3652  goto out;
3653  }
3654  ret = 0;
3655 out:
3656  return ret;
3657 }
3658 
3660  {
3661  "NULL",
3662  mnt3svc_null,
3663  NULL,
3664  MOUNT3_NULL,
3665  DRC_NA,
3666  },
3667  {"MNT", mnt3svc_mnt, NULL, MOUNT3_MNT, DRC_NA, 0},
3668  {"DUMP", mnt3svc_dump, NULL, MOUNT3_DUMP, DRC_NA, 0},
3669  {"UMNT", mnt3svc_umnt, NULL, MOUNT3_UMNT, DRC_NA, 0},
3670  {"UMNTALL", mnt3svc_umntall, NULL, MOUNT3_UMNTALL, DRC_NA, 0},
3671  {"EXPORT", mnt3svc_export, NULL, MOUNT3_EXPORT, DRC_NA, 0}};
3672 
3673 /* Static init parts are assigned here, dynamic ones are done in
3674  * mnt3svc_init and mnt3_init_state.
3675  * Making MOUNT3 a synctask so that the blocking DNS calls during rpc auth
3676  * gets offloaded to syncenv, keeping the main/poll thread unblocked
3677  */
3679  .progname = "MOUNT3",
3680  .prognum = MOUNT_PROGRAM,
3681  .progver = MOUNT_V3,
3682  .progport = GF_MOUNTV3_PORT,
3683  .actors = mnt3svc_actors,
3684  .numactors = MOUNT3_PROC_COUNT,
3685  .min_auth = AUTH_NULL,
3686  .synctask = _gf_true,
3687 };
3688 
3699 int
3700 __mnt3_mounted_exports_walk(dict_t *dict, char *key, data_t *val, void *tmp)
3701 {
3702  char *path = NULL;
3703  char *host_addr_ip = NULL;
3704  char *host_addr_fqdn = NULL;
3705  char *keydup = NULL;
3706  char *colon = NULL;
3707  struct mnt3_auth_params *auth_params = NULL;
3708  int ret = 0;
3709  int auth_status_code = 0;
3710 
3711  gf_msg_trace(GF_MNT, 0, "Checking if key %s is authorized.", key);
3712 
3713  auth_params = (struct mnt3_auth_params *)tmp;
3714 
3715  /* Since we haven't obtained a lock around the mount dict
3716  * here, we want to duplicate the key and then process it.
3717  * Otherwise we would potentially have a race condition
3718  * by modifying the key in the dict when other threads
3719  * are accessing it.
3720  */
3721  keydup = strdupa(key);
3722 
3723  colon = strchr(keydup, ':');
3724  if (!colon)
3725  return 0;
3726 
3727  *colon = '\0';
3728 
3729  path = alloca(strlen(keydup) + 2);
3730  snprintf(path, strlen(keydup) + 2, "/%s", keydup);
3731 
3732  /* Host is one character after ':' */
3733  host_addr_ip = colon + 1;
3734 
3735  /* Check if the IP is authorized */
3736  auth_status_code = mnt3_auth_host(auth_params, host_addr_ip, NULL, path,
3737  FALSE, NULL);
3738  if (auth_status_code == 0) {
3739  goto out;
3740  }
3741 
3742  ret = gf_get_hostname_from_ip(host_addr_ip, &host_addr_fqdn);
3743  if (ret != 0) {
3745  "Authorization failed for IP [%s], but name "
3746  "resolution also failed!",
3747  host_addr_ip);
3748  goto unmount;
3749  }
3750 
3751  /* If not, check if the FQDN is authorized */
3753  "Authorization failed for IP [%s], attempting to"
3754  " auth hostname [%s]...",
3755  host_addr_ip, host_addr_fqdn);
3756 
3757  auth_status_code = mnt3_auth_host(auth_params, host_addr_fqdn, NULL, path,
3758  FALSE, NULL);
3759  if (auth_status_code == 0) {
3761  "Authorization succeeded for "
3762  "Client [IP=%s, Hostname=%s].",
3763  host_addr_ip, host_addr_fqdn);
3764  goto out;
3765  }
3766 
3767 unmount:
3769  "Client [IP=%s, Hostname=%s] not authorized for this mount. "
3770  "Unmounting!",
3771  host_addr_ip, host_addr_fqdn);
3772  mnt3svc_umount(auth_params->ms, path, host_addr_ip);
3773 out:
3774  GF_FREE(host_addr_fqdn);
3775  return 0;
3776 }
3777 
3786 void
3788 {
3789  gf_msg_debug(GF_MNT, 0, "Invalidating old mounts ...");
3791 }
3792 
3805 _mnt3_has_file_changed(const char *path, time_t *oldmtime)
3806 {
3807  gf_boolean_t changed = _gf_false;
3808  time_t mtime = {0};
3809  int ret = 0;
3810 
3811  GF_VALIDATE_OR_GOTO(GF_MNT, path, out);
3812  GF_VALIDATE_OR_GOTO(GF_MNT, oldmtime, out);
3813 
3814  ret = get_file_mtime(path, &mtime);
3815  if (ret < 0)
3816  goto out;
3817 
3818  if (mtime != *oldmtime) {
3819  changed = _gf_true;
3820  *oldmtime = mtime;
3821  }
3822 out:
3823  return changed;
3824 }
3825 
3835 void *
3837 {
3838  struct mount3_state *mstate = (struct mount3_state *)argv;
3839  char *exp_file_path = NULL;
3840  char *ng_file_path = NULL;
3841  size_t nbytes = 0;
3842  time_t exp_time = 0;
3843  time_t ng_time = 0;
3844  gf_boolean_t any_file_changed = _gf_false;
3845  int ret = 0;
3846 
3847  nbytes = strlen(exports_file_path) + 1;
3848  exp_file_path = alloca(nbytes);
3849  snprintf(exp_file_path, nbytes, "%s", exports_file_path);
3850 
3851  nbytes = strlen(netgroups_file_path) + 1;
3852  ng_file_path = alloca(nbytes);
3853  snprintf(ng_file_path, nbytes, "%s", netgroups_file_path);
3854 
3855  /* Set the initial timestamps to avoid reloading right after
3856  * mnt3svc_init () spawns this thread */
3857  get_file_mtime(exp_file_path, &exp_time);
3858  get_file_mtime(ng_file_path, &ng_time);
3859 
3860  while (_gf_true) {
3861  if (mstate->stop_refresh)
3862  break;
3863  any_file_changed = _gf_false;
3864 
3865  /* Sleep before checking the file again */
3866  sleep(mstate->nfs->auth_refresh_time_secs);
3867 
3868  if (_mnt3_has_file_changed(exp_file_path, &exp_time)) {
3870  "File %s changed, updating exports,", exp_file_path);
3871 
3873  exp_file_path);
3874  if (ret)
3876  "Failed to set export auth params.");
3877  else
3878  any_file_changed = _gf_true;
3879  }
3880 
3881  if (_mnt3_has_file_changed(ng_file_path, &ng_time)) {
3883  "File %s changed,"
3884  "updating netgroups",
3885  ng_file_path);
3886 
3888  ng_file_path);
3889  if (ret)
3891  "Failed to set netgroup auth params.");
3892  else
3893  any_file_changed = _gf_true;
3894  }
3895 
3896  /* If no files changed, go back to sleep */
3897  if (!any_file_changed)
3898  continue;
3899 
3901  "Purging auth cache.");
3902  auth_cache_purge(mstate->authcache);
3903 
3904  /* Walk through mounts that are no longer authorized
3905  * and unmount them on the server side. This will
3906  * cause subsequent file ops to fail with access denied.
3907  */
3909  }
3910 
3911  return NULL;
3912 }
3913 
3926 int
3928 {
3929  int ret = -EINVAL;
3930  char *exp_file_path = NULL;
3931  char *ng_file_path = NULL;
3932  size_t nbytes = 0;
3933 
3934  GF_VALIDATE_OR_GOTO(GF_MNT, mstate, out);
3935 
3936  mstate->auth_params = mnt3_auth_params_init(mstate);
3937  if (!mstate->auth_params) {
3939  "Failed to init mount auth params.");
3940  ret = -ENOMEM;
3941  goto out;
3942  }
3943 
3944  nbytes = strlen(exports_file_path) + 1;
3945  exp_file_path = alloca(nbytes);
3946  snprintf(exp_file_path, nbytes, "%s", exports_file_path);
3947 
3948  ret = mnt3_auth_set_exports_auth(mstate->auth_params, exp_file_path);
3949  if (ret < 0) {
3951  "Failed to set export auth params.");
3952  goto out;
3953  }
3954 
3955  nbytes = strlen(netgroups_file_path) + 1;
3956  ng_file_path = alloca(nbytes);
3957  snprintf(ng_file_path, nbytes, "%s", netgroups_file_path);
3958 
3959  ret = mnt3_auth_set_netgroups_auth(mstate->auth_params, ng_file_path);
3960  if (ret < 0) {
3962  "Failed to set netgroup auth params.");
3963  goto out;
3964  }
3965 
3966  ret = 0;
3967 out:
3968  return ret;
3969 }
3970 
3978 void
3980 {
3981  struct mount3_state *mstate = NULL;
3982  struct nfs_state *nfs = NULL;
3983 
3984  if (!nfsx || !nfsx->private)
3985  return;
3986 
3987  nfs = (struct nfs_state *)nfsx->private;
3988  mstate = (struct mount3_state *)nfs->mstate;
3989 
3990  if (nfs->refresh_auth) {
3991  /* Mark as true and wait for thread to exit */
3993  pthread_join(mstate->auth_refresh_thread, NULL);
3994  }
3995 
3996  if (nfs->exports_auth)
3998 
3999  /* Unmount everything and clear mountdict */
4000  LOCK(&mstate->mountlock);
4001  {
4004  }
4005  UNLOCK(&mstate->mountlock);
4006 }
4007 
4010 {
4011  struct mount3_state *mstate = NULL;
4012  struct nfs_state *nfs = NULL;
4013  dict_t *options = NULL;
4014  char *portstr = NULL;
4015  int ret = -1;
4016  pthread_t udp_thread;
4017 
4018  if (!nfsx || !nfsx->private)
4019  return NULL;
4020 
4021  nfs = (struct nfs_state *)nfsx->private;
4022 
4023  gf_msg_debug(GF_MNT, 0, "Initing Mount v3 state");
4024  mstate = (struct mount3_state *)nfs->mstate;
4025  if (!mstate) {
4027  "Mount v3 state init failed");
4028  goto err;
4029  }
4030 
4031  mstate->nfs = nfs;
4032 
4033  mstate->mountdict = dict_new();
4034  if (!mstate->mountdict) {
4036  "Failed to setup mount dict. Allocation error.");
4037  goto err;
4038  }
4039 
4040  if (nfs->exports_auth) {
4041  ret = _mnt3_init_auth_params(mstate);
4042  if (ret < 0)
4043  goto err;
4044 
4046  if (!mstate->authcache) {
4047  ret = -ENOMEM;
4048  goto err;
4049  }
4050 
4051  mstate->stop_refresh = _gf_false; /* Allow thread to run */
4052  ret = gf_thread_create(&mstate->auth_refresh_thread, NULL,
4054  "nfsauth");
4055  if (ret) {
4056  gf_msg_debug(GF_MNT, GF_LOG_DEBUG, "Thread creation failed");
4057  }
4058 
4059  } else
4061  "Exports auth has been disabled!");
4062 
4063  mnt3prog.private = mstate;
4064  options = dict_new();
4065 
4066  ret = gf_asprintf(&portstr, "%d", GF_MOUNTV3_PORT);
4067  if (ret == -1)
4068  goto err;
4069 
4070  ret = dict_set_dynstr(options, "transport.socket.listen-port", portstr);
4071  if (ret == -1)
4072  goto err;
4073 
4074  ret = dict_set_str(options, "transport-type", "socket");
4075  if (ret == -1) {
4077  "dict_set_str error");
4078  goto err;
4079  }
4080 
4081  if (nfs->allow_insecure) {
4082  ret = dict_set_str(options, "rpc-auth-allow-insecure", "on");
4083  if (ret == -1) {
4085  "dict_set_str error");
4086  goto err;
4087  }
4088  ret = dict_set_str(options, "rpc-auth.ports.insecure", "on");
4089  if (ret == -1) {
4091  "dict_set_str error");
4092  goto err;
4093  }
4094  }
4095 
4097  if (ret == -1) {
4099  "Unable to create listeners");
4101  goto err;
4102  }
4103 
4104  if (nfs->mount_udp) {
4105  ret = gf_thread_create(&udp_thread, NULL, mount3udp_thread, nfsx,
4106  "nfsudp");
4107  if (ret) {
4108  gf_msg_debug(GF_MNT, GF_LOG_DEBUG, "Thread creation failed");
4109  }
4110  }
4111  if (options)
4113 
4114  return &mnt3prog;
4115 err:
4116  if (options)
4118  return NULL;
4119 }
4120 
4122  {"NULL", mnt3svc_null, NULL, MOUNT1_NULL, DRC_NA, 0},
4123  {"MNT", NULL, NULL, MOUNT1_MNT, DRC_NA, 0},
4124  {"DUMP", mnt3svc_dump, NULL, MOUNT1_DUMP, DRC_NA, 0},
4125  {"UMNT", mnt3svc_umnt, NULL, MOUNT1_UMNT, DRC_NA, 0},
4126  {"UMNTALL", NULL, NULL, MOUNT1_UMNTALL, DRC_NA, 0},
4127  {"EXPORT", mnt3svc_export, NULL, MOUNT1_EXPORT, DRC_NA, 0}};
4128 
4130  .progname = "MOUNT1",
4131  .prognum = MOUNT_PROGRAM,
4132  .progver = MOUNT_V1,
4133  .progport = GF_MOUNTV1_PORT,
4134  .actors = mnt1svc_actors,
4135  .numactors = MOUNT1_PROC_COUNT,
4136  .min_auth = AUTH_NULL,
4137  .synctask = _gf_true,
4138 };
4139 
4142 {
4143  struct mount3_state *mstate = NULL;
4144  struct nfs_state *nfs = NULL;
4145  dict_t *options = NULL;
4146  char *portstr = NULL;
4147  int ret = -1;
4148 
4149  if (!nfsx || !nfsx->private)
4150  return NULL;
4151 
4152  nfs = (struct nfs_state *)nfsx->private;
4153 
4154  gf_msg_debug(GF_MNT, GF_LOG_DEBUG, "Initing Mount v1 state");
4155  mstate = (struct mount3_state *)nfs->mstate;
4156  if (!mstate) {
4158  "Mount v3 state init failed");
4159  goto err;
4160  }
4161 
4162  mnt1prog.private = mstate;
4163 
4164  options = dict_new();
4165 
4166  ret = gf_asprintf(&portstr, "%d", GF_MOUNTV1_PORT);
4167  if (ret == -1)
4168  goto err;
4169 
4170  ret = dict_set_dynstr(options, "transport.socket.listen-port", portstr);
4171  if (ret == -1)
4172  goto err;
4173  ret = dict_set_str(options, "transport-type", "socket");
4174  if (ret == -1) {
4176  "dict_set_str error");
4177  goto err;
4178  }
4179 
4180  if (nfs->allow_insecure) {
4181  ret = dict_set_str(options, "rpc-auth-allow-insecure", "on");
4182  if (ret == -1) {
4184  "dict_set_str error");
4185  goto err;
4186  }
4187  ret = dict_set_str(options, "rpc-auth.ports.insecure", "on");
4188  if (ret == -1) {
4190  "dict_set_str error");
4191  goto err;
4192  }
4193  }
4194 
4195 #ifdef IPV6_DEFAULT
4196  ret = dict_set_str(options, "transport.address-family", "inet6");
4197  if (ret == -1) {
4199  "dict_set_str error when trying to enable ipv6");
4200  goto err;
4201  }
4202 #endif
4203 
4205  if (ret == -1) {
4207  "Unable to create listeners");
4209  goto err;
4210  }
4211 
4212  return &mnt1prog;
4213 err:
4214  return NULL;
4215 }
4216 
4217 int
4219 {
4220  int ret = -1;
4221  struct nfs_state *nfs = NULL;
4222  struct mount3_state *ms = NULL;
4223  struct mnt3_export *exp = NULL;
4224  struct mnt3_export *texp = NULL;
4225 
4226  if ((!nfsx) || (!options))
4227  return (-1);
4228 
4229  nfs = (struct nfs_state *)nfs_state(nfsx);
4230  if (!nfs)
4231  return (-1);
4232 
4233  ms = nfs->mstate;
4234  if (!ms)
4235  return (-1);
4236 
4237  /*
4238  * Free() up the old export list. mnt3_init_options() will
4239  * rebuild the export list from scratch. Do it with locking
4240  * to avoid unnecessary race conditions.
4241  */
4242  LOCK(&ms->mountlock);
4243  list_for_each_entry_safe(exp, texp, &ms->exportlist, explist)
4244  {
4245  list_del(&exp->explist);
4246  mnt3_export_free(exp);
4247  }
4248  ret = mnt3_init_options(ms, options);
4249  UNLOCK(&ms->mountlock);
4250 
4251  if (ret < 0) {
4253  "Options reconfigure failed");
4254  return (-1);
4255  }
4256 
4257  return (0);
4258 }
xdr_serialize_mountres3
ssize_t xdr_serialize_mountres3(struct iovec outmsg, mountres3 *res)
Definition: msg-nfs3.c:56
nfs3_fh_build_uuid_root_fh
struct nfs3_fh nfs3_fh_build_uuid_root_fh(uuid_t volumeid, uuid_t mountid)
Definition: nfs3-fh.c:80
NFS_MSG_MODIFY_LOCKED
@ NFS_MSG_MODIFY_LOCKED
Definition: nfs-messages.h:100
xlator.h
groupnode::gr_next
groups gr_next
Definition: xdr-nfs3.h:994
iobuf_to_iovec
void iobuf_to_iovec(struct iobuf *iob, struct iovec *iov)
Definition: iobuf.c:1093
NFS_MSG_GET_PEER_ADDR_FAIL
@ NFS_MSG_GET_PEER_ADDR_FAIL
Definition: nfs-messages.h:100
_gf_false
#define _gf_false
Definition: glusterfs.h:369
mount3_resolve_state::remainingdir
char remainingdir[1024]
Definition: mount3.h:174
is_nfs_fh_cached
bool is_nfs_fh_cached(struct auth_cache *cache, struct nfs3_fh *fh, const char *host_addr)
Definition: auth-cache.c:380
rpcsvc_request_service
#define rpcsvc_request_service(req)
Definition: rpcsvc.h:278
iobref
Definition: iobuf.h:154
out
#define out(x...)
Definition: gcrawler.c:35
list_del
static void list_del(struct list_head *old)
Definition: list.h:70
mnt3svc_mount_inode
int mnt3svc_mount_inode(rpcsvc_request_t *req, struct mount3_state *ms, xlator_t *xl, inode_t *exportinode)
Definition: mount3.c:876
DRC_NA
@ DRC_NA
Definition: rpcsvc-common.h:83
mnt3_export
Definition: mount3.h:99
is_nfs_fh_cached_and_writeable
bool is_nfs_fh_cached_and_writeable(struct auth_cache *cache, struct nfs3_fh *fh, const char *host_addr)
Definition: auth-cache.c:410
NFS_MSG_RESOLVE_SYMLINK_ERROR
@ NFS_MSG_RESOLVE_SYMLINK_ERROR
Definition: nfs-messages.h:100
mnt3_auth_params_deinit
void mnt3_auth_params_deinit(struct mnt3_auth_params *auth_params)
Definition: mount3-auth.c:79
nfs_state::allow_insecure
int allow_insecure
Definition: nfs.h:80
mount3-auth.h
MOUNT1_PROC_COUNT
#define MOUNT1_PROC_COUNT
Definition: xdr-nfs3.h:1052
__mnt3_mounted_exports_walk
int __mnt3_mounted_exports_walk(dict_t *dict, char *key, data_t *val, void *tmp)
Definition: mount3.c:3700
auth_cache_init
struct auth_cache * auth_cache_init(time_t ttl_sec)
Definition: auth-cache.c:69
mount3_state::stop_refresh
bool stop_refresh
Definition: mount3.h:162
bin_to_data
data_t * bin_to_data(void *value, int32_t len)
Definition: dict.c:1070
_glusterfs_ctx
Definition: glusterfs.h:618
mountentry::fullpath
char fullpath[1024]
Definition: mount3.h:78
mnt3svc_dump
int mnt3svc_dump(rpcsvc_request_t *req)
Definition: mount3.c:2373
list_add_tail
static void list_add_tail(struct list_head *new, struct list_head *head)
Definition: list.h:35
host_auth_spec::next
struct host_auth_spec * next
Definition: mount3.h:96
NFS_MSG_DICT_SET_FAILED
@ NFS_MSG_DICT_SET_FAILED
Definition: nfs-messages.h:100
NFS_MSG_SET_NET_GRP_FAIL
@ NFS_MSG_SET_NET_GRP_FAIL
Definition: nfs-messages.h:100
setup_next_component
static char * setup_next_component(char *path, size_t plen, char *component, size_t clen)
Definition: mount3.c:999
nfs_state::mstate
struct mount3_state * mstate
Definition: nfs.h:65
RPCSVC_AUTH_REJECT
#define RPCSVC_AUTH_REJECT
Definition: rpcsvc.h:549
GF_MOUNTV1_PORT
#define GF_MOUNTV1_PORT
Definition: mount3.h:33
glfs_resolve_at
int glfs_resolve_at(struct glfs *, xlator_t *, inode_t *, const char *, loc_t *, struct iatt *, int, int)
mount3udp_thread
void * mount3udp_thread(void *argv)
Definition: mount3udp_svc.c:212
mnt3_xlchildren_to_exports
exports mnt3_xlchildren_to_exports(rpcsvc_t *svc, struct mount3_state *ms)
Definition: mount3.c:2621
iatt.h
rpcsvc_request::trans
rpc_transport_t * trans
Definition: rpcsvc.h:157
iobuf.h
IPv4_ADDR_SIZE
#define IPv4_ADDR_SIZE
Definition: common-utils.h:62
mnt3svc_set_mountres3
mountres3 mnt3svc_set_mountres3(mountstat3 stat, struct nfs3_fh *fh, int *authflavor, u_int aflen)
Definition: mount3.c:272
mnt3svc_lookup_mount_cbk
int32_t mnt3svc_lookup_mount_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, inode_t *inode, struct iatt *buf, dict_t *xattr, struct iatt *postparent)
Definition: mount3.c:741
__mnt3udp_get_export_volume_inode
static inode_t * __mnt3udp_get_export_volume_inode(struct svc_req *req, char *volpath, char *expname, struct mnt3_export *exp)
Definition: mount3.c:2904
mnt3_resolve_export_subdir
int mnt3_resolve_export_subdir(rpcsvc_request_t *req, struct mount3_state *ms, struct mnt3_export *exp)
Definition: mount3.c:1583
mnt3prog
static rpcsvc_program_t mnt3prog
Definition: mount3.c:3678
mnt3svc_umnt
int mnt3svc_umnt(rpcsvc_request_t *req)
Definition: mount3.c:2491
MOUNT_PROGRAM
#define MOUNT_PROGRAM
Definition: xdr-nfs3.h:1034
iobuf_unref
void iobuf_unref(struct iobuf *iobuf)
Definition: iobuf.c:720
NFS_MSG_VOLID_MISSING
@ NFS_MSG_VOLID_MISSING
Definition: nfs-messages.h:100
_xlator::ctx
glusterfs_ctx_t * ctx
Definition: xlator.h:818
NFS_MSG_OPEN_FAIL
@ NFS_MSG_OPEN_FAIL
Definition: nfs-messages.h:100
iatt
Definition: iatt.h:46
mnt3svc_submit_reply
int mnt3svc_submit_reply(rpcsvc_request_t *req, void *arg, mnt3_serializer sfunc)
Definition: mount3.c:80
nfs_state
#define nfs_state(nfsxl)
Definition: nfs-fops.h:101
__mnt3_resolve_export_subdir_comp
int __mnt3_resolve_export_subdir_comp(mnt3_resolve_t *mres)
Definition: mount3.c:1039
mnt3svc_null
int mnt3svc_null(rpcsvc_request_t *req)
Definition: mount3.c:2272
GF_VALIDATE_OR_GOTO
#define GF_VALIDATE_OR_GOTO(name, arg, label)
Definition: common-utils.h:319
rpcsvc_transport_peername
int rpcsvc_transport_peername(rpc_transport_t *trans, char *hostname, int hostlen)
Definition: rpcsvc.c:1926
gf_nfs_mt_exportnode
@ gf_nfs_mt_exportnode
Definition: nfs-mem-types.h:21
xlator_list::next
struct xlator_list * next
Definition: xlator.h:762
MOUNT3_DUMP
#define MOUNT3_DUMP
Definition: xdr-nfs3.h:1040
NFS_MSG_PARSE_HOSTSPEC_FAIL
@ NFS_MSG_PARSE_HOSTSPEC_FAIL
Definition: nfs-messages.h:100
exports_file_path
const char * exports_file_path
Definition: mount3.c:57
mount3_resolve_state::exp
struct mnt3_export * exp
Definition: mount3.h:170
THIS
#define THIS
Definition: globals.h:126
mnt3svc_actors
static rpcsvc_actor_t mnt3svc_actors[6]
Definition: mount3.c:3659
mnt3_export::hostspec
struct host_auth_spec * hostspec
Definition: mount3.h:110
nfs3_fh::mountid
uuid_t mountid
Definition: nfs3-fh.h:53
rpcsvc_transport_privport_check
int rpcsvc_transport_privport_check(rpcsvc_t *svc, char *volname, uint16_t port)
Definition: rpcsvc.c:3079
valid_host_name
char valid_host_name(char *address, int length)
Definition: common-utils.c:2426
NFS_MSG_UPDATE_FAIL
@ NFS_MSG_UPDATE_FAIL
Definition: nfs-messages.h:100
_mnt3_authenticate_req
int _mnt3_authenticate_req(struct mount3_state *ms, rpcsvc_request_t *req, struct nfs3_fh *fh, const char *path, char **authorized_export, char **authorized_host, bool is_write_op)
Definition: mount3.c:1990
host_auth_spec::netmask
uint32_t netmask
Definition: mount3.h:95
rpcsvc_program
Definition: rpcsvc.h:393
mnt3svc_umntall
int mnt3svc_umntall(rpcsvc_request_t *req)
Definition: mount3.c:2594
nfs-inodes.h
gf_nfs_dvm_off
#define gf_nfs_dvm_off(nfsstt)
Definition: nfs.h:113
inode_ref
inode_t * inode_ref(inode_t *inode)
Definition: inode.c:609
gf_nfs_mt_nfs3_fh
@ gf_nfs_mt_nfs3_fh
Definition: nfs-mem-types.h:28
mount3_resolve_state::mstate
struct mount3_state * mstate
Definition: mount3.h:171
NFS_MSG_RWTAB_OVERWRITE_FAIL
@ NFS_MSG_RWTAB_OVERWRITE_FAIL
Definition: nfs-messages.h:100
mountbody
Definition: xdr-nfs3.h:983
rpcsvc_program::private
void * private
Definition: rpcsvc.h:421
rpcsvc_request_seterr
#define rpcsvc_request_seterr(req, err)
Definition: rpcsvc.h:565
NFS_MSG_PARSE_AUTH_PARAM_FAIL
@ NFS_MSG_PARSE_AUTH_PARAM_FAIL
Definition: nfs-messages.h:100
GF_FREE
#define GF_FREE(free_ptr)
Definition: mem-pool.h:159
__mnt3udp_get_export_subdir_inode
static inode_t * __mnt3udp_get_export_subdir_inode(struct svc_req *req, char *subdir, char *expname, struct mnt3_export *exp)
Definition: mount3.c:2827
args
union args_ args
MNT3_EXPTYPE_VOLUME
#define MNT3_EXPTYPE_VOLUME
Definition: mount3.h:89
nfs_state::exports_auth
int exports_auth
Definition: nfs.h:86
_mnt3_auth_param_refresh_thread
void * _mnt3_auth_param_refresh_thread(void *argv)
Definition: mount3.c:3836
NFS_MSG_LISTENERS_CREATE_FAIL
@ NFS_MSG_LISTENERS_CREATE_FAIL
Definition: nfs-messages.h:100
gf_nfs_mt_auth_spec
@ gf_nfs_mt_auth_spec
Definition: nfs-mem-types.h:41
MNT3ERR_ACCES
@ MNT3ERR_ACCES
Definition: xdr-nfs3.h:955
dict_get
data_t * dict_get(dict_t *this, char *key)
Definition: dict.c:544
NFS_MSG_VOL_INIT_FAIL
@ NFS_MSG_VOL_INIT_FAIL
Definition: nfs-messages.h:100
mount3_state::export_dirs
bool export_dirs
Definition: mount3.h:159
mnt3_check_client_net_udp
static int mnt3_check_client_net_udp(struct svc_req *req, char *volname, xlator_t *nfsx)
Definition: mount3.c:1736
nfs-generics.h
gf_nfs_mt_char
@ gf_nfs_mt_char
Definition: nfs-mem-types.h:20
NFS_MSG_PURGING_AUTH_CACHE
@ NFS_MSG_PURGING_AUTH_CACHE
Definition: nfs-messages.h:100
mountentry::exname
char exname[1024]
Definition: mount3.h:76
xlator_list
Definition: xlator.h:760
mountentry::has_full_path
bool has_full_path
Definition: mount3.h:80
mnt3_mntpath_to_export
struct mnt3_export * mnt3_mntpath_to_export(struct mount3_state *ms, const char *dirpath, bool export_parsing_match)
Definition: mount3.c:1631
mnt3_export::explist
struct list_head explist
Definition: mount3.h:100
NFS_MSG_SET_EXP_AUTH_PARAM_FAIL
@ NFS_MSG_SET_EXP_AUTH_PARAM_FAIL
Definition: nfs-messages.h:100
mnt3_auth_host
int mnt3_auth_host(const struct mnt3_auth_params *auth_params, const char *host, struct nfs3_fh *fh, const char *dir, bool is_write_op, struct export_item **save_item)
Definition: mount3-auth.c:614
_call_frame
Definition: stack.h:63
IA_ISLNK
#define IA_ISLNK(t)
Definition: iatt.h:136
NFS_RESOLVE_CREATE
#define NFS_RESOLVE_CREATE
Definition: nfs-common.h:50
rpcsvc.h
mount3udp_delete_mountlist
int mount3udp_delete_mountlist(xlator_t *nfsx, char *hostname, char *export)
Definition: mount3.c:3072
NFS_MSG_READ_LOCKED
@ NFS_MSG_READ_LOCKED
Definition: nfs-messages.h:100
__mnt3_fresh_lookup
int __mnt3_fresh_lookup(mnt3_resolve_t *mres)
Definition: mount3.c:1100
rpcsvc_transport_peeraddr
int rpcsvc_transport_peeraddr(rpc_transport_t *trans, char *addrstr, int addrlen, struct sockaddr_storage *sa, socklen_t sasize)
Definition: rpcsvc.c:1936
_inode::ia_type
ia_type_t ia_type
Definition: inode.h:107
rpcsvc_submit_message
int rpcsvc_submit_message(rpcsvc_request_t *req, struct iovec *proghdr, int hdrcount, struct iovec *payload, int payloadcount, struct iobref *iobref)
Definition: rpcsvc.c:1838
xdr_serialize_exports
ssize_t xdr_serialize_exports(struct iovec outmsg, exports *elist)
Definition: msg-nfs3.c:362
MNT3ERR_INVAL
@ MNT3ERR_INVAL
Definition: xdr-nfs3.h:957
NFS_MSG_REP_SUBMIT_FAIL
@ NFS_MSG_REP_SUBMIT_FAIL
Definition: nfs-messages.h:100
mnt3_export::mountid
uuid_t mountid
Definition: mount3.h:122
gf_sock_union::sin
struct sockaddr_in sin
Definition: common-utils.h:463
xdr-nfs3.h
gf_rev_dns_lookup
char * gf_rev_dns_lookup(const char *ip)
Definition: common-utils.c:396
nfs3_rootfh
struct nfs3_fh * nfs3_rootfh(struct svc_req *req, xlator_t *nfsx, char *path, char *expname)
Definition: mount3.c:2930
_inode
Definition: inode.h:99
NFS_MSG_UNSUPPORTED_VERSION
@ NFS_MSG_UNSUPPORTED_VERSION
Definition: nfs-messages.h:100
mnt3_authenticate_request
int mnt3_authenticate_request(struct mount3_state *ms, rpcsvc_request_t *req, struct nfs3_fh *fh, const char *volname, const char *path, char **authorized_path, char **authorized_host, bool is_write_op)
Definition: mount3.c:2114
export_item
Definition: exports.h:55
MNT3_EXPTYPE_DIR
#define MNT3_EXPTYPE_DIR
Definition: mount3.h:90
_glusterfs_ctx::iobuf_pool
void * iobuf_pool
Definition: glusterfs.h:627
mount_read_rmtab
static void mount_read_rmtab(struct mount3_state *ms)
Definition: mount3.c:451
nfs_fix_generation
void nfs_fix_generation(xlator_t *this, inode_t *inode)
Definition: nfs-common.c:419
_mnt3_get_host_from_peer
char * _mnt3_get_host_from_peer(const char *peer_addr)
Definition: mount3.c:1931
MOUNT3_MNT
#define MOUNT3_MNT
Definition: xdr-nfs3.h:1039
mnt3_export_fill_hostspec
int mnt3_export_fill_hostspec(struct host_auth_spec *hostspec, const char *hostip)
Definition: mount3.c:3099
NFS_MSG_INIT_DIR_EXP_FAIL
@ NFS_MSG_INIT_DIR_EXP_FAIL
Definition: nfs-messages.h:100
_loc::parent
inode_t * parent
Definition: xlator.h:70
NFS_MSG_LOCK_FAIL
@ NFS_MSG_LOCK_FAIL
Definition: nfs-messages.h:100
NFS_RESOLVE_EXIST
#define NFS_RESOLVE_EXIST
Definition: nfs-common.h:49
gf_thread_create
int gf_thread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg, const char *name,...)
Definition: common-utils.c:4084
_xlator::options
dict_t * options
Definition: xlator.h:779
nfs_readlink
int nfs_readlink(xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *linkloc, fop_readlink_cbk_t cbk, void *local)
Definition: nfs-generics.c:253
mount_reconfigure_state
int mount_reconfigure_state(xlator_t *nfsx, dict_t *options)
Definition: mount3.c:4218
SuperFastHash
uint32_t SuperFastHash(const char *data, int32_t len)
Definition: hashfn.c:28
hashfn.h
nfs_loc_wipe
void nfs_loc_wipe(loc_t *loc)
Definition: nfs-common.c:117
iobref_new
struct iobref * iobref_new(void)
Definition: iobuf.c:746
xdr_free_mountlist
void xdr_free_mountlist(mountlist ml)
Definition: xdr-nfs3.c:1879
mnt3svc_errno_to_mnterr
mountstat3 mnt3svc_errno_to_mnterr(int32_t errnum)
Definition: mount3.c:231
gf_asprintf
int gf_asprintf(char **string_ptr, const char *format,...)
Definition: mem-pool.c:237
gf_build_absolute_path
int32_t gf_build_absolute_path(char *current_path, char *relative_path, char **path)
Definition: common-utils.c:4570
MNT3ERR_IO
@ MNT3ERR_IO
Definition: xdr-nfs3.h:954
mnt3_init_state
struct mount3_state * mnt3_init_state(xlator_t *nfsx)
Definition: mount3.c:3606
mnt3_auth_params
Definition: mount3-auth.h:26
dict_foreach
int dict_foreach(dict_t *dict, int(*fn)(dict_t *this, char *key, data_t *value, void *data), void *data)
Definition: dict.c:1286
NFS_MSG_REWRITE_ERROR
@ NFS_MSG_REWRITE_ERROR
Definition: nfs-messages.h:100
MOUNT1_DUMP
#define MOUNT1_DUMP
Definition: xdr-nfs3.h:1048
GF_LOG_WARNING
@ GF_LOG_WARNING
Definition: logging.h:74
nfs3-fh.h
dict_set_dynstr
int dict_set_dynstr(dict_t *this, char *key, char *str)
Definition: dict.c:2487
mnt3_match_dirpath_export
int mnt3_match_dirpath_export(const char *expname, const char *dirpath, bool export_parsing_match)
Definition: mount3.c:827
iobuf_get
struct iobuf * iobuf_get(struct iobuf_pool *iobuf_pool)
Definition: iobuf.c:608
rpcsvc_create_listeners
int32_t rpcsvc_create_listeners(rpcsvc_t *svc, dict_t *options, char *name)
Definition: rpcsvc.c:2018
mount3_state::iobpool
struct iobuf_pool * iobpool
Definition: mount3.h:132
_mnt3_has_file_changed
bool _mnt3_has_file_changed(const char *path, time_t *oldmtime)
Definition: mount3.c:3805
mountres3::fhs_status
mountstat3 fhs_status
Definition: xdr-nfs3.h:974
INIT_LIST_HEAD
#define INIT_LIST_HEAD(head)
Definition: list.h:19
MOUNT_V3
#define MOUNT_V3
Definition: xdr-nfs3.h:1035
_data
Definition: dict.h:97
rpc_transport
Definition: rpc-transport.h:162
_mnt3_invalidate_old_mounts
void _mnt3_invalidate_old_mounts(struct mount3_state *ms)
Definition: mount3.c:3787
mnt3_readlink_cbk
int32_t mnt3_readlink_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, const char *path, struct iatt *buf, dict_t *xdata)
Definition: mount3.c:1250
gf_boolean_t
#define gf_boolean_t
Definition: glusterfs.h:368
MOUNT1_UMNT
#define MOUNT1_UMNT
Definition: xdr-nfs3.h:1049
NFS_MSG_RESOLVE_ERROR
@ NFS_MSG_RESOLVE_ERROR
Definition: nfs-messages.h:100
gf_resolve_path_parent
char * gf_resolve_path_parent(const char *path)
Definition: common-utils.c:420
GF_LOG_DEBUG
@ GF_LOG_DEBUG
Definition: logging.h:77
nfs_entry_loc_fill
int nfs_entry_loc_fill(xlator_t *this, inode_table_t *itable, uuid_t pargfid, char *entry, loc_t *loc, int how, bool *freshlookup)
Definition: nfs-common.c:310
gf_uuid_clear
static void gf_uuid_clear(uuid_t uuid)
Definition: compat-uuid.h:17
mnt3_resolve_state_wipe
void mnt3_resolve_state_wipe(mnt3_resolve_t *mres)
Definition: mount3.c:986
src.utils.fail
def fail(msg, code=1, logger=None)
Definition: utils.py:154
MNT3ERR_NOENT
@ MNT3ERR_NOENT
Definition: xdr-nfs3.h:953
mnt3_parse_dir_exports
int mnt3_parse_dir_exports(rpcsvc_request_t *req, struct mount3_state *ms, char *path, bool send_reply)
Definition: mount3.c:1780
glfs_new_from_ctx
struct glfs * glfs_new_from_ctx(glusterfs_ctx_t *)
NFS_MSG_GET_REMOTE_NAME_FAIL
@ NFS_MSG_GET_REMOTE_NAME_FAIL
Definition: nfs-messages.h:100
MOUNT1_EXPORT
#define MOUNT1_EXPORT
Definition: xdr-nfs3.h:1051
NFS_MSG_OPT_INIT_FAIL
@ NFS_MSG_OPT_INIT_FAIL
Definition: nfs-messages.h:100
mnt3svc_umount
int mnt3svc_umount(struct mount3_state *ms, char *dirpath, char *hostname)
Definition: mount3.c:2416
nfs3_build_fh
int nfs3_build_fh(inode_t *inode, uuid_t exportid, struct nfs3_fh *newfh)
Definition: nfs3-fh.c:154
mnt3_auth_set_netgroups_auth
int mnt3_auth_set_netgroups_auth(struct mnt3_auth_params *auth_params, const char *filename)
Definition: mount3-auth.c:151
UNLOCK
#define UNLOCK(x)
Definition: locking.h:79
_xlator::name
char * name
Definition: xlator.h:772
MOUNT1_UMNTALL
#define MOUNT1_UMNTALL
Definition: xdr-nfs3.h:1050
gf_nfs_mt_mnt3_export
@ gf_nfs_mt_mnt3_export
Definition: nfs-mem-types.h:32
mnt3svc_init
rpcsvc_program_t * mnt3svc_init(xlator_t *nfsx)
Definition: mount3.c:4009
store.h
rpcsvc_volume_allowed
char * rpcsvc_volume_allowed(dict_t *options, char *volname)
Definition: rpcsvc.c:3139
exportnode::ex_next
exports ex_next
Definition: xdr-nfs3.h:1003
mountres3::mountinfo
mountres3_ok mountinfo
Definition: xdr-nfs3.h:976
mount3_state::mountlock
gf_lock_t mountlock
Definition: mount3.h:152
NFS_MSG_NO_MEMORY
@ NFS_MSG_NO_MEMORY
Definition: nfs-messages.h:100
gf_msg
#define gf_msg(dom, level, errnum, msgid, fmt...)
Definition: logging.h:229
_call_frame::local
void * local
Definition: stack.h:67
rpcsvc_request::msg
struct iovec msg[16]
Definition: rpcsvc.h:194
NFS_MSG_PEER_TOO_LONG
@ NFS_MSG_PEER_TOO_LONG
Definition: nfs-messages.h:100
mount3_state::auth_refresh_thread
pthread_t auth_refresh_thread
Definition: mount3.h:161
gf_store_handle_new
int32_t gf_store_handle_new(const char *path, gf_store_handle_t **handle)
Definition: store.c:407
exportnode::ex_groups
groups ex_groups
Definition: xdr-nfs3.h:1002
__mount_rewrite_rmtab
static void __mount_rewrite_rmtab(struct mount3_state *ms, gf_store_handle_t *sh)
Definition: mount3.c:381
gf_string2boolean
int gf_string2boolean(const char *str, bool *b)
Definition: common-utils.c:1922
GF_MNT
#define GF_MNT
Definition: mount3.h:34
mount3_state::nfs
struct nfs_state * nfs
Definition: mount3.h:129
mnt3_verify_auth
int mnt3_verify_auth(struct sockaddr_in *client_addr, struct mnt3_export *export)
Definition: mount3.c:1440
NFS_MSG_BAD_PEER
@ NFS_MSG_BAD_PEER
Definition: nfs-messages.h:100
mount3_state::auth_params
struct mnt3_auth_params * auth_params
Definition: mount3.h:155
gf_msg_debug
#define gf_msg_debug(dom, errnum, fmt...)
Definition: logging.h:270
mount3_state::mountlist
struct list_head mountlist
Definition: mount3.h:140
gf_sock_union::storage
struct sockaddr_storage storage
Definition: common-utils.h:461
NFS_MSG_MNT_STATE_NOT_FOUND
@ NFS_MSG_MNT_STATE_NOT_FOUND
Definition: nfs-messages.h:100
list_head
Definition: list.h:14
NFS_MSG_DICT_GET_FAILED
@ NFS_MSG_DICT_GET_FAILED
Definition: nfs-messages.h:100
NFS_MSG_DIR_EXP_SETUP_FAIL
@ NFS_MSG_DIR_EXP_SETUP_FAIL
Definition: nfs-messages.h:100
__mnt3_init_volume
int __mnt3_init_volume(struct mount3_state *ms, dict_t *opts, xlator_t *xlator)
Definition: mount3.c:3391
dict_new
dict_t * dict_new(void)
Definition: dict.c:107
dict_unref
void dict_unref(dict_t *this)
Definition: dict.c:734
mnt3_check_cached_fh
int mnt3_check_cached_fh(struct mount3_state *ms, struct nfs3_fh *fh, const char *host_addr, bool is_write_op)
Definition: mount3.c:1962
gf_store_handle_destroy
int32_t gf_store_handle_destroy(gf_store_handle_t *handle)
Definition: store.c:473
GF_NFS
#define GF_NFS
Definition: nfs.h:20
nfs_state::rmtab
char * rmtab
Definition: nfs.h:93
inode_unref
inode_t * inode_unref(inode_t *inode)
Definition: inode.c:588
exportnode
Definition: xdr-nfs3.h:1000
MOUNT3_EXPORT
#define MOUNT3_EXPORT
Definition: xdr-nfs3.h:1043
GLUSTERD_DEFAULT_WORKDIR
#define GLUSTERD_DEFAULT_WORKDIR
Definition: glusterfs.h:271
fhandle3::fhandle3_val
char * fhandle3_val
Definition: xdr-nfs3.h:943
groupnode
Definition: xdr-nfs3.h:992
__mnt3_build_mountid_from_path
int __mnt3_build_mountid_from_path(const char *path, uuid_t mountid)
Definition: mount3.c:691
gf_nfs_mt_groupnode
@ gf_nfs_mt_groupnode
Definition: nfs-mem-types.h:22
MOUNT1_MNT
#define MOUNT1_MNT
Definition: xdr-nfs3.h:1047
gf_uuid_parse
static int gf_uuid_parse(const char *in, uuid_t uuid)
Definition: compat-uuid.h:47
mnt3svc_mnt_error_reply
int mnt3svc_mnt_error_reply(rpcsvc_request_t *req, int mntstat)
Definition: mount3.c:216
nfs3_fh_to_str
void nfs3_fh_to_str(struct nfs3_fh *fh, char *str, size_t len)
Definition: nfs3-fh.c:113
dict_get_str
int dict_get_str(dict_t *this, char *key, char **str)
Definition: dict.c:2385
NFS_MSG_INVALID_ENTRY
@ NFS_MSG_INVALID_ENTRY
Definition: nfs-messages.h:100
gf_store_unlink_tmppath
int32_t gf_store_unlink_tmppath(gf_store_handle_t *shandle)
Definition: store.c:159
GF_MOUNTV3_PORT
#define GF_MOUNTV3_PORT
Definition: mount3.h:29
gf_store_save_value
int32_t gf_store_save_value(int fd, char *key, char *value)
Definition: store.c:312
list_empty
static int list_empty(struct list_head *head)
Definition: list.h:104
NFS_MSG_RESOLVE_SUBDIR_FAIL
@ NFS_MSG_RESOLVE_SUBDIR_FAIL
Definition: nfs-messages.h:100
gf_store_retrieve_value
int32_t gf_store_retrieve_value(gf_store_handle_t *handle, char *key, char **value)
Definition: store.c:240
_mnt3_get_peer_addr
char * _mnt3_get_peer_addr(const rpcsvc_request_t *req)
Definition: mount3.c:1894
host_auth_spec
Definition: mount3.h:93
strdupa
#define strdupa(s)
Definition: compat.h:434
dirpath
char * dirpath
Definition: xdr-nfs3.h:946
netgroups_file_path
const char * netgroups_file_path
Definition: mount3.c:58
glfs_free_from_ctx
void glfs_free_from_ctx(struct glfs *)
mnt3_resolve_subdir_cbk
int32_t mnt3_resolve_subdir_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, inode_t *inode, struct iatt *buf, dict_t *xattr, struct iatt *postparent)
Definition: mount3.c:1111
rpcsvc_request_program_private
#define rpcsvc_request_program_private(req)
Definition: rpcsvc.h:271
mnt3_auth_set_exports_auth
int mnt3_auth_set_exports_auth(struct mnt3_auth_params *auth_params, const char *filename)
Definition: mount3-auth.c:110
mnt1prog
static rpcsvc_program_t mnt1prog
Definition: mount3.c:4129
gf_store_locked_local
int gf_store_locked_local(gf_store_handle_t *sh)
Definition: store.c:737
mnt3_match_subnet_v4
static bool mnt3_match_subnet_v4(struct addrinfo *ai, uint32_t saddr, uint32_t mask)
Definition: mount3.c:1412
mount3_state
Definition: mount3.h:125
NFS_MSG_PARSE_VOL_UUID_FAIL
@ NFS_MSG_PARSE_VOL_UUID_FAIL
Definition: nfs-messages.h:100
mnt3_get_volume_subdir
char * mnt3_get_volume_subdir(char *dirpath, char **volname)
Definition: mount3.c:950
_xlator::private
void * private
Definition: xlator.h:822
__mnt3udp_get_mstate
static struct mount3_state * __mnt3udp_get_mstate(xlator_t *nfsx)
Definition: mount3.c:2800
rpcsvc_request
Definition: rpcsvc.h:155
mountentry
Definition: mount3.h:71
inode_from_path
inode_t * inode_from_path(inode_table_t *table, const char *path)
Definition: inode.c:1945
mnt3_export::volumeid
uuid_t volumeid
Definition: mount3.h:121
MOUNT3_UMNT
#define MOUNT3_UMNT
Definition: xdr-nfs3.h:1041
rpcsvc_state::options
dict_t * options
Definition: rpcsvc-common.h:46
mnt3_export::exptype
int exptype
Definition: mount3.h:112
nfs3_fh_build_child_fh
int nfs3_fh_build_child_fh(struct nfs3_fh *parent, struct iatt *newstat, struct nfs3_fh *newfh)
Definition: nfs3-fh.c:170
GF_LOG_CRITICAL
@ GF_LOG_CRITICAL
Definition: logging.h:72
uuid_utoa
char * uuid_utoa(uuid_t uuid)
Definition: common-utils.c:2841
_xlator
Definition: xlator.h:770
mnt3_init_options
int mnt3_init_options(struct mount3_state *ms, dict_t *options)
Definition: mount3.c:3576
nfs_inode_loc_fill
int nfs_inode_loc_fill(inode_t *inode, loc_t *loc, int how)
Definition: nfs-common.c:170
NFS_MSG_EXP_AUTH_DISABLED
@ NFS_MSG_EXP_AUTH_DISABLED
Definition: nfs-messages.h:100
nfs-mem-types.h
nfs.h
nfs_request_user_init
void nfs_request_user_init(nfs_user_t *nfu, rpcsvc_request_t *req)
Definition: nfs.c:672
xdr_free_exports_list
void xdr_free_exports_list(struct exportnode *first)
Definition: xdr-nfs3.c:1860
MOUNT3_PROC_COUNT
#define MOUNT3_PROC_COUNT
Definition: xdr-nfs3.h:1044
MNT3ERR_NOTSUPP
@ MNT3ERR_NOTSUPP
Definition: xdr-nfs3.h:959
mount3_resolve_state::parentfh
struct nfs3_fh parentfh
Definition: mount3.h:176
_loc::inode
inode_t * inode
Definition: xlator.h:69
peer_info::sockaddr
struct sockaddr_storage sockaddr
Definition: rpc-transport.h:68
rpcsvc_actor_desc
Definition: rpcsvc.h:358
xlator_list::xlator
xlator_t * xlator
Definition: xlator.h:761
msg-nfs3.h
gf_log
#define gf_log(dom, level, fmt...)
Definition: logging.h:282
mount3udp_add_mountlist
int mount3udp_add_mountlist(xlator_t *nfsx, char *host, char *export)
Definition: mount3.c:3043
gf_store_handle_
Definition: store.h:16
iobref_add
int iobref_add(struct iobref *iobref, struct iobuf *iobuf)
Definition: iobuf.c:889
xdr_serialize_mountlist
ssize_t xdr_serialize_mountlist(struct iovec outmsg, mountlist *ml)
Definition: msg-nfs3.c:68
gf_store_rename_tmppath
int32_t gf_store_rename_tmppath(gf_store_handle_t *shandle)
Definition: store.c:125
nfs_subvolume_started
int nfs_subvolume_started(struct nfs_state *nfs, xlator_t *xl)
Definition: nfs.c:414
NFS_MSG_RECONF_FAIL
@ NFS_MSG_RECONF_FAIL
Definition: nfs-messages.h:100
NFS_MSG_MNT_STATE_INIT_FAIL
@ NFS_MSG_MNT_STATE_INIT_FAIL
Definition: nfs-messages.h:100
gf_mnt3_export_dirs
#define gf_mnt3_export_dirs(mst)
Definition: mount3.h:167
nfs3_fh
Definition: nfs3-fh.h:33
nfs_lookup
int nfs_lookup(xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc, fop_lookup_cbk_t cbk, void *local)
Definition: nfs-generics.c:71
_loc
Definition: xlator.h:66
auth_cache_purge
void auth_cache_purge(struct auth_cache *cache)
Definition: auth-cache.c:346
mnt3svc_build_mountlist
mountlist mnt3svc_build_mountlist(struct mount3_state *ms, int *count)
Definition: mount3.c:2359
NFS_MSG_PEER_NOT_ALLOWED
@ NFS_MSG_PEER_NOT_ALLOWED
Definition: nfs-messages.h:100
rpcsvc_request_transport
#define rpcsvc_request_transport(req)
Definition: rpcsvc.h:290
mnt3svc_mount
int mnt3svc_mount(rpcsvc_request_t *req, struct mount3_state *ms, struct mnt3_export *exp)
Definition: mount3.c:1606
mnt3svc_deinit
void mnt3svc_deinit(xlator_t *nfsx)
Definition: mount3.c:3979
dict_set
int32_t dict_set(dict_t *this, char *key, data_t *value)
Definition: dict.c:474
mountres3_ok::auth_flavors
struct mountres3_ok::@96 auth_flavors
gf_path_strip_trailing_slashes
void gf_path_strip_trailing_slashes(char *path)
Definition: common-utils.c:3094
get_host_name
char * get_host_name(char *word, char **host)
Definition: common-utils.c:3070
gf_store_unlock
void gf_store_unlock(gf_store_handle_t *sh)
Definition: store.c:721
GF_NFS3FH_STATIC_INITIALIZER
#define GF_NFS3FH_STATIC_INITIALIZER
Definition: nfs3-fh.h:61
gf_nfs_mt_mnt3_resolve
@ gf_nfs_mt_mnt3_resolve
Definition: nfs-mem-types.h:31
NFS_MSG_HASH_PATH_FAIL
@ NFS_MSG_HASH_PATH_FAIL
Definition: nfs-messages.h:100
mnt3_resolve_subdir
int mnt3_resolve_subdir(rpcsvc_request_t *req, struct mount3_state *ms, struct mnt3_export *exp, char *subdir, bool send_reply)
Definition: mount3.c:1522
nfs_state
Definition: nfs.h:62
mnt3_find_export
int mnt3_find_export(rpcsvc_request_t *req, char *path, struct mnt3_export **e)
Definition: mount3.c:1848
MOUNT1_NULL
#define MOUNT1_NULL
Definition: xdr-nfs3.h:1046
nfs_state::mount_udp
int mount_udp
Definition: nfs.h:83
mount3_state::authcache
struct auth_cache * authcache
Definition: mount3.h:164
__mountdict_remove
void __mountdict_remove(struct mount3_state *ms, struct mountentry *me)
Definition: mount3.c:207
mount_init_state
int mount_init_state(xlator_t *nfsx)
Definition: mount3.c:3638
_xlator::children
xlator_list_t * children
Definition: xlator.h:778
S40ufo-stop.opts
opts
Definition: S40ufo-stop.py:17
gf_nfs_mt_mountentry
@ gf_nfs_mt_mountentry
Definition: nfs-mem-types.h:17
mnt3svc_volume_mount
int mnt3svc_volume_mount(rpcsvc_request_t *req, struct mount3_state *ms, struct mnt3_export *exp)
Definition: mount3.c:918
__mount_read_rmtab
static int __mount_read_rmtab(gf_store_handle_t *sh, struct list_head *mountlist, bool append)
Definition: mount3.c:299
glfs
Definition: glfs-internal.h:174
gf_nfs_mt_mountbody
@ gf_nfs_mt_mountbody
Definition: nfs-mem-types.h:18
MOUNT_V1
#define MOUNT_V1
Definition: xdr-nfs3.h:1036
mnt1svc_actors
static rpcsvc_actor_t mnt1svc_actors[6]
Definition: mount3.c:4121
__mnt3_resolve_subdir
int __mnt3_resolve_subdir(mnt3_resolve_t *mres)
Definition: mount3.c:1364
exportnode::ex_dir
dirpath ex_dir
Definition: xdr-nfs3.h:1001
groupnode::gr_name
name gr_name
Definition: xdr-nfs3.h:993
nfs_state::auth_refresh_time_secs
unsigned int auth_refresh_time_secs
Definition: nfs.h:90
MNT3ERR_PERM
@ MNT3ERR_PERM
Definition: xdr-nfs3.h:952
__mnt3_get_volume_id
int __mnt3_get_volume_id(struct mount3_state *ms, xlator_t *mntxl, uuid_t volumeid)
Definition: mount3.c:667
mnt3_export_parse_auth_param
int mnt3_export_parse_auth_param(struct mnt3_export *exp, char *exportpath)
Definition: mount3.c:3194
NFS_MSG_STR2BOOL_FAIL
@ NFS_MSG_STR2BOOL_FAIL
Definition: nfs-messages.h:100
__mnt3_init_dir_export
int __mnt3_init_dir_export(struct mount3_state *ms, dict_t *opts)
Definition: mount3.c:3534
mountres3_ok::auth_flavors_len
u_int auth_flavors_len
Definition: xdr-nfs3.h:967
NFS_MSG_AUTH_VERIFY_FAILED
@ NFS_MSG_AUTH_VERIFY_FAILED
Definition: nfs-messages.h:100
valid_ipv4_address
char valid_ipv4_address(char *address, int length, bool wildcard_acc)
Definition: common-utils.c:2484
mountentry::hashkey
char hashkey[1024 *2+2]
Definition: mount3.h:86
mnt3_export::expname
char * expname
Definition: mount3.h:105
nfs_user_info
Definition: nfs.h:128
mount3_state::exportlist
struct list_head exportlist
Definition: mount3.h:135
mnt3svc_mnt
int mnt3svc_mnt(rpcsvc_request_t *req)
Definition: mount3.c:2173
GF_LOG_ERROR
@ GF_LOG_ERROR
Definition: logging.h:73
mnt3_export_free
static void mnt3_export_free(struct mnt3_export *exp)
Definition: mount3.c:66
NFS_MSG_SNPRINTF_FAIL
@ NFS_MSG_SNPRINTF_FAIL
Definition: nfs-messages.h:100
list_for_each_entry
#define list_for_each_entry(pos, head, member)
Definition: list.h:235
fhandle3::fhandle3_len
u_int fhandle3_len
Definition: xdr-nfs3.h:942
MNT3_OK
@ MNT3_OK
Definition: xdr-nfs3.h:951
NFS_MSG_RESOLVE_INODE_FAIL
@ NFS_MSG_RESOLVE_INODE_FAIL
Definition: nfs-messages.h:100
gf_sock_union
Definition: common-utils.h:460
RPCSVC_ACTOR_ERROR
#define RPCSVC_ACTOR_ERROR
Definition: rpcsvc.h:323
locking.h
loc_wipe
void loc_wipe(loc_t *loc)
Definition: xlator.c:997
LOCK_INIT
#define LOCK_INIT(x)
Definition: locking.h:76
mnt3_check_client_net_check
static int mnt3_check_client_net_check(rpcsvc_t *svc, char *expvol, char *ipaddr, uint16_t port)
Definition: mount3.c:1662
mnt3_export::vol
xlator_t * vol
Definition: mount3.h:111
__mnt3svc_umountall
int __mnt3svc_umountall(struct mount3_state *ms)
Definition: mount3.c:2556
xdr_serialize_mountstat3
ssize_t xdr_serialize_mountstat3(struct iovec outmsg, mountstat3 *m)
Definition: msg-nfs3.c:74
gf_store_lock
int gf_store_lock(gf_store_handle_t *sh)
Definition: store.c:694
MNTPATHLEN
#define MNTPATHLEN
Definition: xdr-nfs3.h:937
mountentry::mlist
struct list_head mlist
Definition: mount3.h:73
options
static struct argp_option options[]
Definition: glfs-bm.c:322
NFS_MSG_INODE_LOC_FILL_ERROR
@ NFS_MSG_INODE_LOC_FILL_ERROR
Definition: nfs-messages.h:100
mount3_resolve_state::req
rpcsvc_request_t * req
Definition: mount3.h:172
MNT3ERR_NOTDIR
@ MNT3ERR_NOTDIR
Definition: xdr-nfs3.h:956
iobref_unref
void iobref_unref(struct iobref *iobref)
Definition: iobuf.c:804
__mnt3_get_mount_id
int __mnt3_get_mount_id(xlator_t *mntxl, uuid_t mountid)
Definition: mount3.c:719
rpc_transport::peerinfo
peer_info_t peerinfo
Definition: rpc-transport.h:187
nfs3_fh_compute_size
uint32_t nfs3_fh_compute_size()
Definition: nfs3-fh.c:183
mount3_state::export_volumes
bool export_volumes
Definition: mount3.h:158
_xlator::itable
inode_table_t * itable
Definition: xlator.h:820
nfs-common.h
gf_get_hostname_from_ip
int gf_get_hostname_from_ip(char *client_ip, char **hostname)
Definition: common-utils.c:3405
dict.h
mnt3svc_update_mountlist
int mnt3svc_update_mountlist(struct mount3_state *ms, rpcsvc_request_t *req, const char *expname, const char *fullpath)
Definition: mount3.c:577
__mnt3_init_volume_export
int __mnt3_init_volume_export(struct mount3_state *ms, dict_t *opts)
Definition: mount3.c:3492
NFS_MSG_AUTH_ERROR
@ NFS_MSG_AUTH_ERROR
Definition: nfs-messages.h:100
dict_del
void dict_del(dict_t *this, char *key)
Definition: dict.c:602
dict_set_str
int dict_set_str(dict_t *this, char *key, char *str)
Definition: dict.c:2410
get_file_mtime
int get_file_mtime(const char *path, time_t *stamp)
Definition: common-utils.c:2134
RPCSVC_ACTOR_SUCCESS
#define RPCSVC_ACTOR_SUCCESS
Definition: rpcsvc.h:322
NFS_MSG_UPDATING_EXP
@ NFS_MSG_UPDATING_EXP
Definition: nfs-messages.h:100
gf_nfs_mt_mount3_state
@ gf_nfs_mt_mount3_state
Definition: nfs-mem-types.h:23
NFS_MSG_ARGS_DECODE_ERROR
@ NFS_MSG_ARGS_DECODE_ERROR
Definition: nfs-messages.h:100
NFS_MSG_SET_EXP_FAIL
@ NFS_MSG_SET_EXP_FAIL
Definition: nfs-messages.h:100
inode_unlink
void inode_unlink(inode_t *inode, inode_t *parent, const char *name)
Definition: inode.c:1253
LOCK
#define LOCK(x)
Definition: locking.h:77
mountres3
Definition: xdr-nfs3.h:973
mask_match
bool mask_match(const uint32_t a, const uint32_t b, const uint32_t m)
Definition: common-utils.c:2834
inode_link
inode_t * inode_link(inode_t *inode, inode_t *parent, const char *name, struct iatt *stbuf)
Definition: inode.c:1062
__mnt3_init_volume_direxports
int __mnt3_init_volume_direxports(struct mount3_state *ms, xlator_t *xlator, char *optstr, uuid_t volumeid)
Definition: mount3.c:3355
_inode::gfid
uuid_t gfid
Definition: inode.h:101
NFS_MSG_LOOKUP_MNT_ERROR
@ NFS_MSG_LOOKUP_MNT_ERROR
Definition: nfs-messages.h:100
MOUNT3_UMNTALL
#define MOUNT3_UMNTALL
Definition: xdr-nfs3.h:1042
nfs_state::refresh_auth
int refresh_auth
Definition: nfs.h:88
mountres3_ok::fhandle
fhandle3 fhandle
Definition: xdr-nfs3.h:965
nfs_state::auth_cache_ttl_sec
unsigned int auth_cache_ttl_sec
Definition: nfs.h:91
nfs3_fh_build_indexed_root_fh
struct nfs3_fh nfs3_fh_build_indexed_root_fh(xlator_list_t *cl, xlator_t *xl)
Definition: nfs3-fh.c:59
glfs-internal.h
FREE_HOSTSPEC
#define FREE_HOSTSPEC(exp)
Definition: mount3.c:42
__build_mountlist
mountlist __build_mountlist(struct mount3_state *ms, int *count)
Definition: mount3.c:2288
mountbody::ml_next
mountlist ml_next
Definition: xdr-nfs3.h:986
glfs.h
RPCSVC_PEER_STRLEN
#define RPCSVC_PEER_STRLEN
Definition: rpcsvc.h:547
rpcsvc_submit_generic
int rpcsvc_submit_generic(rpcsvc_request_t *req, struct iovec *proghdr, int hdrcount, struct iovec *payload, int payloadcount, struct iobref *iobref)
Definition: rpcsvc.c:1501
rpcsvc_state
Definition: rpcsvc-common.h:35
mnt3_auth_params::ms
struct mount3_state * ms
Definition: mount3-auth.h:29
list_for_each_entry_safe
#define list_for_each_entry_safe(pos, n, head, member)
Definition: list.h:240
mount3_resolve_state
Definition: mount3.h:169
xdr_to_mountpath
ssize_t xdr_to_mountpath(struct iovec outpath, struct iovec inmsg)
Definition: msg-nfs3.c:27
NFS_MSG_HASH_XLATOR_FAIL
@ NFS_MSG_HASH_XLATOR_FAIL
Definition: nfs-messages.h:100
NFS_MSG_GET_ROOT_INODE_FAIL
@ NFS_MSG_GET_ROOT_INODE_FAIL
Definition: nfs-messages.h:100
_dict
Definition: dict.h:114
_loc::path
const char * path
Definition: xlator.h:67
GF_CALLOC
#define GF_CALLOC(nmemb, size, type)
Definition: mem-pool.h:153
mnt3svc_umountall
int mnt3svc_umountall(struct mount3_state *ms)
Definition: mount3.c:2578
common-utils.h
GF_ASSERT
#define GF_ASSERT(x)
Definition: common-utils.h:434
inode_find
inode_t * inode_find(inode_table_t *table, uuid_t gfid)
Definition: inode.c:923
MOUNT3_NULL
#define MOUNT3_NULL
Definition: xdr-nfs3.h:1038
NFS_MSG_ENCODE_MSG_FAIL
@ NFS_MSG_ENCODE_MSG_FAIL
Definition: nfs-messages.h:100
gf_uuid_copy
static void gf_uuid_copy(uuid_t dst, const uuid_t src)
Definition: compat-uuid.h:29
MNT3ERR_SERVERFAULT
@ MNT3ERR_SERVERFAULT
Definition: xdr-nfs3.h:960
nfs_state::rpcsvc
rpcsvc_t * rpcsvc
Definition: nfs.h:63
GF_LOG_INFO
@ GF_LOG_INFO
Definition: logging.h:76
__mountdict_insert
void __mountdict_insert(struct mount3_state *ms, struct mountentry *me)
Definition: mount3.c:164
mountres3_ok::auth_flavors_val
int * auth_flavors_val
Definition: xdr-nfs3.h:968
_gf_true
#define _gf_true
Definition: glusterfs.h:370
nfs-fops.h
gf_store_mkstemp
int32_t gf_store_mkstemp(gf_store_handle_t *shandle)
Definition: store.c:59
mnt3_auth_params_init
struct mnt3_auth_params * mnt3_auth_params_init(struct mount3_state *ms)
Definition: mount3-auth.c:57
NFS_MSG_UNKNOWN_MNT_TYPE
@ NFS_MSG_UNKNOWN_MNT_TYPE
Definition: nfs-messages.h:100
gf_strdup
static char * gf_strdup(const char *src)
Definition: mem-pool.h:182
err
#define err(x...)
Definition: gcrawler.c:34
rpcsvc_program::progname
char progname[32]
Definition: rpcsvc.h:394
iobuf
Definition: iobuf.h:58
mnt3_export::fullpath
char * fullpath
Definition: mount3.h:117
mount_open_rmtab
static bool mount_open_rmtab(const char *rmtab, gf_store_handle_t **sh)
Definition: mount3.c:431
mount3_resolve_state::resolveloc
loc_t resolveloc
Definition: mount3.h:175
rpcsvc_auth_check
int rpcsvc_auth_check(rpcsvc_t *svc, char *volname, char *ipaddr)
Definition: rpcsvc.c:2994
NFS_MSG_UPDATING_NET_GRP
@ NFS_MSG_UPDATING_NET_GRP
Definition: nfs-messages.h:100
nfs-messages.h
RPCSVC_AUTH_ACCEPT
#define RPCSVC_AUTH_ACCEPT
Definition: rpcsvc.h:548
host_auth_spec::host_addr
char * host_addr
Definition: mount3.h:94
gf_msg_trace
#define gf_msg_trace(dom, errnum, fmt...)
Definition: logging.h:276
GF_MALLOC
#define GF_MALLOC(size, type)
Definition: mem-pool.h:155
mount3_state::nfsx
xlator_t * nfsx
Definition: mount3.h:126
_mnt3_init_auth_params
int _mnt3_init_auth_params(struct mount3_state *mstate)
Definition: mount3.c:3927
mount_rewrite_rmtab
void mount_rewrite_rmtab(struct mount3_state *ms, char *new_rmtab)
Definition: mount3.c:494
mountstat3
mountstat3
Definition: xdr-nfs3.h:950
mountres3::mountres3_u
union mountres3::@97 mountres3_u
gf_strndup
static char * gf_strndup(const char *src, size_t len)
Definition: mem-pool.h:162
_loc::name
const char * name
Definition: xlator.h:68
mount3_state::mountdict
dict_t * mountdict
Definition: mount3.h:149
mnt3svc_export
int mnt3svc_export(rpcsvc_request_t *req)
Definition: mount3.c:2756
cache_nfs_fh
int cache_nfs_fh(struct auth_cache *cache, struct nfs3_fh *fh, const char *host_addr, struct export_item *export_item)
Definition: auth-cache.c:442
mnt3_serializer
ssize_t(* mnt3_serializer)(struct iovec outmsg, void *args)
Definition: mount3.c:60
mnt3_init_export_ent
struct mnt3_export * mnt3_init_export_ent(struct mount3_state *ms, xlator_t *xl, char *exportpath, uuid_t volumeid)
Definition: mount3.c:3277
rpcsvc_auth_array
int rpcsvc_auth_array(rpcsvc_t *svc, char *volname, int *autharr, int arrlen)
Definition: rpcsvc-auth.c:489
gf_store_handle_::path
char * path
Definition: store.h:17
mnt3_check_client_net_tcp
int mnt3_check_client_net_tcp(rpcsvc_request_t *req, char *volname)
Definition: mount3.c:1692
mnt1svc_init
rpcsvc_program_t * mnt1svc_init(xlator_t *nfsx)
Definition: mount3.c:4141
mountentry::hostname
char hostname[1024]
Definition: mount3.h:77
mount3.h