diff options
Diffstat (limited to 'xlators/nfs/server/src/mount3.c')
-rw-r--r-- | xlators/nfs/server/src/mount3.c | 6426 |
1 files changed, 3190 insertions, 3236 deletions
diff --git a/xlators/nfs/server/src/mount3.c b/xlators/nfs/server/src/mount3.c index f3d7def64d0..f0d8aff999f 100644 --- a/xlators/nfs/server/src/mount3.c +++ b/xlators/nfs/server/src/mount3.c @@ -36,119 +36,121 @@ #include <sys/socket.h> #include <sys/uio.h> - /* This macro will assist in freeing up entire link list * of host_auth_spec structure. */ -#define FREE_HOSTSPEC(exp) do { \ - struct host_auth_spec *host= exp->hostspec; \ - while (NULL != host){ \ - struct host_auth_spec* temp = host; \ - host = host->next; \ - if (NULL != temp->host_addr) { \ - GF_FREE (temp->host_addr); \ - } \ - GF_FREE (temp); \ - } \ - exp->hostspec = NULL; \ - } while (0) +#define FREE_HOSTSPEC(exp) \ + do { \ + struct host_auth_spec *host = exp->hostspec; \ + while (NULL != host) { \ + struct host_auth_spec *temp = host; \ + host = host->next; \ + if (NULL != temp->host_addr) { \ + GF_FREE(temp->host_addr); \ + } \ + GF_FREE(temp); \ + } \ + exp->hostspec = NULL; \ + } while (0) /* Paths for export and netgroup files */ -const char *exports_file_path = GLUSTERD_DEFAULT_WORKDIR "/nfs/exports"; +const char *exports_file_path = GLUSTERD_DEFAULT_WORKDIR "/nfs/exports"; const char *netgroups_file_path = GLUSTERD_DEFAULT_WORKDIR "/nfs/netgroups"; -typedef ssize_t (*mnt3_serializer) (struct iovec outmsg, void *args); +typedef ssize_t (*mnt3_serializer)(struct iovec outmsg, void *args); extern void * -mount3udp_thread (void *argv); +mount3udp_thread(void *argv); static void -mnt3_export_free (struct mnt3_export *exp) +mnt3_export_free(struct mnt3_export *exp) { - if (!exp) - return; - - if (exp->exptype == MNT3_EXPTYPE_DIR) - FREE_HOSTSPEC (exp); - GF_FREE (exp->expname); - GF_FREE (exp->fullpath); - GF_FREE (exp); + if (!exp) + return; + + if (exp->exptype == MNT3_EXPTYPE_DIR) + FREE_HOSTSPEC(exp); + GF_FREE(exp->expname); + GF_FREE(exp->fullpath); + GF_FREE(exp); } /* Generic reply function for MOUNTv3 specific replies. */ int -mnt3svc_submit_reply (rpcsvc_request_t *req, void *arg, mnt3_serializer sfunc) +mnt3svc_submit_reply(rpcsvc_request_t *req, void *arg, mnt3_serializer sfunc) { - struct iovec outmsg = {0, }; - struct iobuf *iob = NULL; - struct mount3_state *ms = NULL; - int ret = -1; - ssize_t msglen = 0; - struct iobref *iobref = NULL; - - if (!req) - return -1; - - ms = (struct mount3_state *)rpcsvc_request_program_private (req); - if (!ms) { - gf_msg (GF_MNT, GF_LOG_ERROR, EINVAL, - NFS_MSG_MNT_STATE_NOT_FOUND, "mount state not found"); - goto ret; - } - - /* First, get the io buffer into which the reply in arg will - * be serialized. - */ - /* TODO: use 'xdrproc_t' instead of 'sfunc' to get the xdr-size */ - iob = iobuf_get (ms->iobpool); - if (!iob) { - gf_msg (GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, - "Failed to get iobuf"); - goto ret; - } - - iobuf_to_iovec (iob, &outmsg); - /* Use the given serializer to translate the give C structure in arg - * to XDR format which will be written into the buffer in outmsg. - */ - msglen = sfunc (outmsg, arg); - if (msglen < 0) { - gf_msg (GF_MNT, GF_LOG_ERROR, 0, NFS_MSG_ENCODE_MSG_FAIL, - "Failed to encode message"); - goto ret; - } - outmsg.iov_len = msglen; - - iobref = iobref_new (); - if (iobref == NULL) { - gf_msg (GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, - "Failed to get iobref"); - goto ret; - } - - ret = iobref_add (iobref, iob); - if (ret) { - gf_msg (GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, - "Failed to add iob to iobref"); - goto ret; - } - - /* Then, submit the message for transmission. */ - ret = rpcsvc_submit_message (req, &outmsg, 1, NULL, 0, iobref); - if (ret == -1) { - gf_msg (GF_MNT, GF_LOG_ERROR, errno, NFS_MSG_REP_SUBMIT_FAIL, - "Reply submission failed"); - goto ret; - } + struct iovec outmsg = { + 0, + }; + struct iobuf *iob = NULL; + struct mount3_state *ms = NULL; + int ret = -1; + ssize_t msglen = 0; + struct iobref *iobref = NULL; + + if (!req) + return -1; - ret = 0; + ms = (struct mount3_state *)rpcsvc_request_program_private(req); + if (!ms) { + gf_msg(GF_MNT, GF_LOG_ERROR, EINVAL, NFS_MSG_MNT_STATE_NOT_FOUND, + "mount state not found"); + goto ret; + } + + /* First, get the io buffer into which the reply in arg will + * be serialized. + */ + /* TODO: use 'xdrproc_t' instead of 'sfunc' to get the xdr-size */ + iob = iobuf_get(ms->iobpool); + if (!iob) { + gf_msg(GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, + "Failed to get iobuf"); + goto ret; + } + + iobuf_to_iovec(iob, &outmsg); + /* Use the given serializer to translate the give C structure in arg + * to XDR format which will be written into the buffer in outmsg. + */ + msglen = sfunc(outmsg, arg); + if (msglen < 0) { + gf_msg(GF_MNT, GF_LOG_ERROR, 0, NFS_MSG_ENCODE_MSG_FAIL, + "Failed to encode message"); + goto ret; + } + outmsg.iov_len = msglen; + + iobref = iobref_new(); + if (iobref == NULL) { + gf_msg(GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, + "Failed to get iobref"); + goto ret; + } + + ret = iobref_add(iobref, iob); + if (ret) { + gf_msg(GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, + "Failed to add iob to iobref"); + goto ret; + } + + /* Then, submit the message for transmission. */ + ret = rpcsvc_submit_message(req, &outmsg, 1, NULL, 0, iobref); + if (ret == -1) { + gf_msg(GF_MNT, GF_LOG_ERROR, errno, NFS_MSG_REP_SUBMIT_FAIL, + "Reply submission failed"); + goto ret; + } + + ret = 0; ret: - if (NULL != iob) - iobuf_unref (iob); - if (NULL != iobref) - iobref_unref (iobref); + if (NULL != iob) + iobuf_unref(iob); + if (NULL != iobref) + iobref_unref(iobref); - return ret; + return ret; } /** * __mountdict_insert -- Insert a mount entry into the mount state @@ -159,39 +161,38 @@ ret: * Not for external use. */ void -__mountdict_insert (struct mount3_state *ms, struct mountentry *me) +__mountdict_insert(struct mount3_state *ms, struct mountentry *me) { - char *exname = NULL; - char *fpath = NULL; - data_t *medata = NULL; - - GF_VALIDATE_OR_GOTO (GF_MNT, ms, out); - GF_VALIDATE_OR_GOTO (GF_MNT, me, out); - - /* We don't want export names with leading slashes */ - exname = me->exname; - while (exname[0] == '/') - exname++; - - /* Get the fullpath for the export */ - fpath = me->fullpath; - if (me->has_full_path) { - while (fpath[0] == '/') - fpath++; - - /* Export names can either be just volumes or paths inside that - * volume. */ - exname = fpath; - } - - snprintf (me->hashkey, sizeof (me->hashkey), "%s:%s", exname, - me->hostname); - - medata = bin_to_data (me, sizeof (*me)); - dict_set (ms->mountdict, me->hashkey, medata); - gf_msg_trace (GF_MNT, 0, "Inserted into mountdict: %s", me->hashkey); + char *exname = NULL; + char *fpath = NULL; + data_t *medata = NULL; + + GF_VALIDATE_OR_GOTO(GF_MNT, ms, out); + GF_VALIDATE_OR_GOTO(GF_MNT, me, out); + + /* We don't want export names with leading slashes */ + exname = me->exname; + while (exname[0] == '/') + exname++; + + /* Get the fullpath for the export */ + fpath = me->fullpath; + if (me->has_full_path) { + while (fpath[0] == '/') + fpath++; + + /* Export names can either be just volumes or paths inside that + * volume. */ + exname = fpath; + } + + snprintf(me->hashkey, sizeof(me->hashkey), "%s:%s", exname, me->hostname); + + medata = bin_to_data(me, sizeof(*me)); + dict_set(ms->mountdict, me->hashkey, medata); + gf_msg_trace(GF_MNT, 0, "Inserted into mountdict: %s", me->hashkey); out: - return; + return; } /** @@ -203,91 +204,90 @@ out: * Not for external use. */ void -__mountdict_remove (struct mount3_state *ms, struct mountentry *me) +__mountdict_remove(struct mount3_state *ms, struct mountentry *me) { - dict_del (ms->mountdict, me->hashkey); + dict_del(ms->mountdict, me->hashkey); } /* Generic error reply function, just pass the err status * and it will do the rest, including transmission. */ int -mnt3svc_mnt_error_reply (rpcsvc_request_t *req, int mntstat) +mnt3svc_mnt_error_reply(rpcsvc_request_t *req, int mntstat) { - mountres3 res; + mountres3 res; - if (!req) - return -1; + if (!req) + return -1; - res.fhs_status = mntstat; - mnt3svc_submit_reply (req, (void *)&res, - (mnt3_serializer)xdr_serialize_mountres3); + res.fhs_status = mntstat; + mnt3svc_submit_reply(req, (void *)&res, + (mnt3_serializer)xdr_serialize_mountres3); - return 0; + return 0; } - mountstat3 -mnt3svc_errno_to_mnterr (int32_t errnum) +mnt3svc_errno_to_mnterr(int32_t errnum) { - mountstat3 stat; - - switch (errnum) { - - case 0: - stat = MNT3_OK; - break; - case ENOENT: - stat = MNT3ERR_NOENT; - break; - case EPERM: - stat = MNT3ERR_PERM; - break; - case EIO: - stat = MNT3ERR_IO; - break; - case EACCES: - stat = MNT3ERR_ACCES; - break; - case ENOTDIR: - stat = MNT3ERR_NOTDIR; - break; - case EINVAL: - stat = MNT3ERR_INVAL; - break; - case ENOSYS: - stat = MNT3ERR_NOTSUPP; - break; - case ENOMEM: - stat = MNT3ERR_SERVERFAULT; - break; - default: - stat = MNT3ERR_SERVERFAULT; - break; - } + mountstat3 stat; + + switch (errnum) { + case 0: + stat = MNT3_OK; + break; + case ENOENT: + stat = MNT3ERR_NOENT; + break; + case EPERM: + stat = MNT3ERR_PERM; + break; + case EIO: + stat = MNT3ERR_IO; + break; + case EACCES: + stat = MNT3ERR_ACCES; + break; + case ENOTDIR: + stat = MNT3ERR_NOTDIR; + break; + case EINVAL: + stat = MNT3ERR_INVAL; + break; + case ENOSYS: + stat = MNT3ERR_NOTSUPP; + break; + case ENOMEM: + stat = MNT3ERR_SERVERFAULT; + break; + default: + stat = MNT3ERR_SERVERFAULT; + break; + } - return stat; + return stat; } - mountres3 -mnt3svc_set_mountres3 (mountstat3 stat, struct nfs3_fh *fh, int *authflavor, - u_int aflen) +mnt3svc_set_mountres3(mountstat3 stat, struct nfs3_fh *fh, int *authflavor, + u_int aflen) { - mountres3 res = {0, }; - uint32_t fhlen = 0; + mountres3 res = { + 0, + }; + uint32_t fhlen = 0; - res.fhs_status = stat; + res.fhs_status = stat; - if (fh) - fhlen = nfs3_fh_compute_size (); + if (fh) + fhlen = nfs3_fh_compute_size(); - res.mountres3_u.mountinfo.fhandle.fhandle3_len = fhlen; - res.mountres3_u.mountinfo.fhandle.fhandle3_val = (char *)fh; - res.mountres3_u.mountinfo.auth_flavors.auth_flavors_val = authflavor; - res.mountres3_u.mountinfo.auth_flavors.auth_flavors_len = aflen; + res.mountres3_u.mountinfo.fhandle.fhandle3_len = fhlen; + res.mountres3_u.mountinfo.fhandle.fhandle3_val = (char *)fh; + res.mountres3_u.mountinfo.auth_flavors.auth_flavors_val = authflavor; + res.mountres3_u.mountinfo.auth_flavors.auth_flavors_len = aflen; - return res; + return res; } /* Read the rmtab from the store_handle and append (or not) the entries to the @@ -296,81 +296,82 @@ mnt3svc_set_mountres3 (mountstat3 stat, struct nfs3_fh *fh, int *authflavor, * Requires the store_handle to be locked. */ static int -__mount_read_rmtab (gf_store_handle_t *sh, struct list_head *mountlist, - gf_boolean_t append) +__mount_read_rmtab(gf_store_handle_t *sh, struct list_head *mountlist, + gf_boolean_t append) { - int ret = 0; - unsigned int idx = 0; - struct mountentry *me = NULL, *tmp = NULL; - /* me->hostname is a char[MNTPATHLEN] */ - char key[MNTPATHLEN + 11]; - - GF_ASSERT (sh && mountlist); - - if (!gf_store_locked_local (sh)) { - gf_msg (GF_MNT, GF_LOG_WARNING, 0, NFS_MSG_READ_LOCKED, - "Not reading unlocked %s", sh->path); - return -1; - } + int ret = 0; + unsigned int idx = 0; + struct mountentry *me = NULL, *tmp = NULL; + /* me->hostname is a char[MNTPATHLEN] */ + char key[MNTPATHLEN + 11]; - if (!append) { - list_for_each_entry_safe (me, tmp, mountlist, mlist) { - list_del (&me->mlist); - GF_FREE (me); - } - me = NULL; - } + GF_ASSERT(sh && mountlist); - for (;;) { - char *value = NULL; - - if (me && append) { - /* do not add duplicates */ - list_for_each_entry (tmp, mountlist, mlist) { - if (!strcmp(tmp->hostname, me->hostname) && - !strcmp(tmp->exname, me->exname)) { - GF_FREE (me); - goto dont_add; - } - } - list_add_tail (&me->mlist, mountlist); - } else if (me) { - list_add_tail (&me->mlist, mountlist); - } + if (!gf_store_locked_local(sh)) { + gf_msg(GF_MNT, GF_LOG_WARNING, 0, NFS_MSG_READ_LOCKED, + "Not reading unlocked %s", sh->path); + return -1; + } -dont_add: - me = GF_CALLOC (1, sizeof (*me), gf_nfs_mt_mountentry); - if (!me) { - gf_msg (GF_MNT, GF_LOG_ERROR, ENOMEM, - NFS_MSG_NO_MEMORY, "Out of memory"); - ret = -1; - goto out; + if (!append) { + list_for_each_entry_safe(me, tmp, mountlist, mlist) + { + list_del(&me->mlist); + GF_FREE(me); + } + me = NULL; + } + + for (;;) { + char *value = NULL; + + if (me && append) { + /* do not add duplicates */ + list_for_each_entry(tmp, mountlist, mlist) + { + if (!strcmp(tmp->hostname, me->hostname) && + !strcmp(tmp->exname, me->exname)) { + GF_FREE(me); + goto dont_add; } - - INIT_LIST_HEAD (&me->mlist); - - snprintf (key, 9 + MNTPATHLEN, "hostname-%d", idx); - ret = gf_store_retrieve_value (sh, key, &value); - if (ret) - break; - snprintf (me->hostname, MNTPATHLEN, "%s", value); - GF_FREE (value); - - snprintf (key, 11 + MNTPATHLEN, "mountpoint-%d", idx); - ret = gf_store_retrieve_value (sh, key, &value); - if (ret) - break; - snprintf (me->exname, MNTPATHLEN, "%s", value); - GF_FREE (value); - - idx++; - gf_msg_trace (GF_MNT, 0, "Read entries %s:%s", - me->hostname, me->exname); - } - gf_msg_debug (GF_MNT, 0, "Read %d entries from '%s'", idx, sh->path); - GF_FREE (me); + } + list_add_tail(&me->mlist, mountlist); + } else if (me) { + list_add_tail(&me->mlist, mountlist); + } + + dont_add: + me = GF_CALLOC(1, sizeof(*me), gf_nfs_mt_mountentry); + if (!me) { + gf_msg(GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, + "Out of memory"); + ret = -1; + goto out; + } + + INIT_LIST_HEAD(&me->mlist); + + snprintf(key, 9 + MNTPATHLEN, "hostname-%d", idx); + ret = gf_store_retrieve_value(sh, key, &value); + if (ret) + break; + snprintf(me->hostname, MNTPATHLEN, "%s", value); + GF_FREE(value); + + snprintf(key, 11 + MNTPATHLEN, "mountpoint-%d", idx); + ret = gf_store_retrieve_value(sh, key, &value); + if (ret) + break; + snprintf(me->exname, MNTPATHLEN, "%s", value); + GF_FREE(value); + + idx++; + gf_msg_trace(GF_MNT, 0, "Read entries %s:%s", me->hostname, me->exname); + } + gf_msg_debug(GF_MNT, 0, "Read %d entries from '%s'", idx, sh->path); + GF_FREE(me); out: - return ret; + return ret; } /* Overwrite the contents of the rwtab with the in-memory client list. @@ -379,98 +380,97 @@ out: static void __mount_rewrite_rmtab(struct mount3_state *ms, gf_store_handle_t *sh) { - struct mountentry *me = NULL; - char key[16]; - int fd, ret; - unsigned int idx = 0; - - if (!gf_store_locked_local (sh)) { - gf_msg (GF_MNT, GF_LOG_WARNING, 0, NFS_MSG_MODIFY_LOCKED, - "Not modifying unlocked %s", sh->path); - return; - } + struct mountentry *me = NULL; + char key[16]; + int fd, ret; + unsigned int idx = 0; + + if (!gf_store_locked_local(sh)) { + gf_msg(GF_MNT, GF_LOG_WARNING, 0, NFS_MSG_MODIFY_LOCKED, + "Not modifying unlocked %s", sh->path); + return; + } - fd = gf_store_mkstemp (sh); - if (fd == -1) { - gf_msg (GF_MNT, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY, - "Failed to open %s", sh->path); - return; - } + fd = gf_store_mkstemp(sh); + if (fd == -1) { + gf_msg(GF_MNT, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY, + "Failed to open %s", sh->path); + return; + } - list_for_each_entry (me, &ms->mountlist, mlist) { - snprintf (key, 16, "hostname-%d", idx); - ret = gf_store_save_value (fd, key, me->hostname); - if (ret) - goto fail; + list_for_each_entry(me, &ms->mountlist, mlist) + { + snprintf(key, 16, "hostname-%d", idx); + ret = gf_store_save_value(fd, key, me->hostname); + if (ret) + goto fail; - snprintf (key, 16, "mountpoint-%d", idx); - ret = gf_store_save_value (fd, key, me->exname); - if (ret) - goto fail; + snprintf(key, 16, "mountpoint-%d", idx); + ret = gf_store_save_value(fd, key, me->exname); + if (ret) + goto fail; - idx++; - } + idx++; + } - gf_msg_debug (GF_MNT, 0, "Updated rmtab with %d entries", idx); + gf_msg_debug(GF_MNT, 0, "Updated rmtab with %d entries", idx); - if (gf_store_rename_tmppath (sh)) - gf_msg (GF_MNT, GF_LOG_ERROR, errno, - NFS_MSG_RWTAB_OVERWRITE_FAIL, - "Failed to overwrite rwtab %s", sh->path); + if (gf_store_rename_tmppath(sh)) + gf_msg(GF_MNT, GF_LOG_ERROR, errno, NFS_MSG_RWTAB_OVERWRITE_FAIL, + "Failed to overwrite rwtab %s", sh->path); - return; + return; fail: - gf_msg (GF_MNT, GF_LOG_ERROR, errno, NFS_MSG_UPDATE_FAIL, - "Failed to update %s", sh->path); - gf_store_unlink_tmppath (sh); + gf_msg(GF_MNT, GF_LOG_ERROR, errno, NFS_MSG_UPDATE_FAIL, + "Failed to update %s", sh->path); + gf_store_unlink_tmppath(sh); } static gf_boolean_t -mount_open_rmtab (const char *rmtab, gf_store_handle_t **sh) +mount_open_rmtab(const char *rmtab, gf_store_handle_t **sh) { - int ret = -1; + int ret = -1; - /* updating the rmtab is disabled, use in-memory only */ - if (!rmtab || rmtab[0] == '\0') - return _gf_false; + /* updating the rmtab is disabled, use in-memory only */ + if (!rmtab || rmtab[0] == '\0') + return _gf_false; - ret = gf_store_handle_new (rmtab, sh); - if (ret) { - gf_log (GF_MNT, GF_LOG_WARNING, "Failed to open '%s'", rmtab); - return _gf_false; - } + ret = gf_store_handle_new(rmtab, sh); + if (ret) { + gf_log(GF_MNT, GF_LOG_WARNING, "Failed to open '%s'", rmtab); + return _gf_false; + } - return _gf_true; + return _gf_true; } - /* Read the rmtab into a clean ms->mountlist. */ static void -mount_read_rmtab (struct mount3_state *ms) +mount_read_rmtab(struct mount3_state *ms) { - gf_store_handle_t *sh = NULL; - struct nfs_state *nfs = NULL; - gf_boolean_t read_rmtab = _gf_false; + gf_store_handle_t *sh = NULL; + struct nfs_state *nfs = NULL; + gf_boolean_t read_rmtab = _gf_false; - nfs = (struct nfs_state *)ms->nfsx->private; + nfs = (struct nfs_state *)ms->nfsx->private; - read_rmtab = mount_open_rmtab (nfs->rmtab, &sh); - if (!read_rmtab) - return; + read_rmtab = mount_open_rmtab(nfs->rmtab, &sh); + if (!read_rmtab) + return; - if (gf_store_lock (sh)) { - gf_msg (GF_MNT, GF_LOG_WARNING, 0, NFS_MSG_LOCK_FAIL, - "Failed to lock '%s'", nfs->rmtab); - goto out; - } + if (gf_store_lock(sh)) { + gf_msg(GF_MNT, GF_LOG_WARNING, 0, NFS_MSG_LOCK_FAIL, + "Failed to lock '%s'", nfs->rmtab); + goto out; + } - __mount_read_rmtab (sh, &ms->mountlist, _gf_false); - gf_store_unlock (sh); + __mount_read_rmtab(sh, &ms->mountlist, _gf_false); + gf_store_unlock(sh); out: - gf_store_handle_destroy (sh); + gf_store_handle_destroy(sh); } /* Write the ms->mountlist to the rmtab. @@ -491,77 +491,75 @@ out: * 9. releases the store_handle lock of the old rmtab */ void -mount_rewrite_rmtab (struct mount3_state *ms, char *new_rmtab) +mount_rewrite_rmtab(struct mount3_state *ms, char *new_rmtab) { - gf_store_handle_t *sh = NULL, *nsh = NULL; - struct nfs_state *nfs = NULL; - int ret; - char *rmtab = NULL; - gf_boolean_t got_old_rmtab = _gf_false; - - nfs = (struct nfs_state *)ms->nfsx->private; - - got_old_rmtab = mount_open_rmtab (nfs->rmtab, &sh); - if (!got_old_rmtab && !new_rmtab) - return; - - if (got_old_rmtab && gf_store_lock (sh)) { - gf_msg (GF_MNT, GF_LOG_WARNING, 0, NFS_MSG_REWRITE_ERROR, - "Not rewriting '%s'", nfs->rmtab); - goto free_sh; - } + gf_store_handle_t *sh = NULL, *nsh = NULL; + struct nfs_state *nfs = NULL; + int ret; + char *rmtab = NULL; + gf_boolean_t got_old_rmtab = _gf_false; - if (new_rmtab) { - ret = gf_store_handle_new (new_rmtab, &nsh); - if (ret) { - gf_msg (GF_MNT, GF_LOG_WARNING, 0, NFS_MSG_OPEN_FAIL, - "Failed to open '%s'", new_rmtab); - goto unlock_sh; - } + nfs = (struct nfs_state *)ms->nfsx->private; - if (gf_store_lock (nsh)) { - gf_msg (GF_MNT, GF_LOG_WARNING, 0, - NFS_MSG_REWRITE_ERROR, - "Not rewriting '%s'", new_rmtab); - goto free_nsh; - } + got_old_rmtab = mount_open_rmtab(nfs->rmtab, &sh); + if (!got_old_rmtab && !new_rmtab) + return; + + if (got_old_rmtab && gf_store_lock(sh)) { + gf_msg(GF_MNT, GF_LOG_WARNING, 0, NFS_MSG_REWRITE_ERROR, + "Not rewriting '%s'", nfs->rmtab); + goto free_sh; + } + + if (new_rmtab) { + ret = gf_store_handle_new(new_rmtab, &nsh); + if (ret) { + gf_msg(GF_MNT, GF_LOG_WARNING, 0, NFS_MSG_OPEN_FAIL, + "Failed to open '%s'", new_rmtab); + goto unlock_sh; } - /* always read the currently used rmtab */ - if (got_old_rmtab) - __mount_read_rmtab (sh, &ms->mountlist, _gf_true); - - if (new_rmtab) { - /* read the new rmtab and write changes to the new location */ - __mount_read_rmtab (nsh, &ms->mountlist, _gf_true); - __mount_rewrite_rmtab (ms, nsh); - - /* replace the nfs->rmtab reference to the new rmtab */ - rmtab = gf_strdup(new_rmtab); - if (rmtab == NULL) { - gf_msg (GF_MNT, GF_LOG_ERROR, errno, NFS_MSG_NO_MEMORY, - "Out of memory, keeping %s as rmtab", - nfs->rmtab); - } else { - GF_FREE (nfs->rmtab); - nfs->rmtab = rmtab; - } + if (gf_store_lock(nsh)) { + gf_msg(GF_MNT, GF_LOG_WARNING, 0, NFS_MSG_REWRITE_ERROR, + "Not rewriting '%s'", new_rmtab); + goto free_nsh; + } + } + + /* always read the currently used rmtab */ + if (got_old_rmtab) + __mount_read_rmtab(sh, &ms->mountlist, _gf_true); + + if (new_rmtab) { + /* read the new rmtab and write changes to the new location */ + __mount_read_rmtab(nsh, &ms->mountlist, _gf_true); + __mount_rewrite_rmtab(ms, nsh); - gf_store_unlock (nsh); + /* replace the nfs->rmtab reference to the new rmtab */ + rmtab = gf_strdup(new_rmtab); + if (rmtab == NULL) { + gf_msg(GF_MNT, GF_LOG_ERROR, errno, NFS_MSG_NO_MEMORY, + "Out of memory, keeping %s as rmtab", nfs->rmtab); } else { - /* rewrite the current (unchanged location) rmtab */ - __mount_rewrite_rmtab (ms, sh); + GF_FREE(nfs->rmtab); + nfs->rmtab = rmtab; } + gf_store_unlock(nsh); + } else { + /* rewrite the current (unchanged location) rmtab */ + __mount_rewrite_rmtab(ms, sh); + } + free_nsh: - if (new_rmtab) - gf_store_handle_destroy (nsh); + if (new_rmtab) + gf_store_handle_destroy(nsh); unlock_sh: - if (got_old_rmtab) - gf_store_unlock (sh); + if (got_old_rmtab) + gf_store_unlock(sh); free_sh: - if (got_old_rmtab) - gf_store_handle_destroy (sh); + if (got_old_rmtab) + gf_store_handle_destroy(sh); } /* Add a new NFS-client to the ms->mountlist and update the rmtab if we can. @@ -576,374 +574,375 @@ free_sh: * common issue for all(?) NFS-servers. */ int -mnt3svc_update_mountlist (struct mount3_state *ms, rpcsvc_request_t *req, - const char *expname, const char *fullpath) +mnt3svc_update_mountlist(struct mount3_state *ms, rpcsvc_request_t *req, + const char *expname, const char *fullpath) { - struct mountentry *me = NULL; - struct mountentry *cur = NULL; - int ret = -1; - char *colon = NULL; - struct nfs_state *nfs = NULL; - gf_store_handle_t *sh = NULL; - gf_boolean_t update_rmtab = _gf_false; - - if ((!ms) || (!req) || (!expname)) - return -1; - - me = (struct mountentry *)GF_CALLOC (1, sizeof (*me), - gf_nfs_mt_mountentry); - if (!me) - return -1; - - nfs = (struct nfs_state *)ms->nfsx->private; - - update_rmtab = mount_open_rmtab (nfs->rmtab, &sh); + struct mountentry *me = NULL; + struct mountentry *cur = NULL; + int ret = -1; + char *colon = NULL; + struct nfs_state *nfs = NULL; + gf_store_handle_t *sh = NULL; + gf_boolean_t update_rmtab = _gf_false; + + if ((!ms) || (!req) || (!expname)) + return -1; - snprintf (me->exname, MNTPATHLEN, "%s", expname); - /* Sometimes we don't care about the full path - * so a NULL value for fullpath is valid. - */ - if (fullpath) { - if (strlen (fullpath) < MNTPATHLEN) { - strcpy (me->fullpath, fullpath); - me->has_full_path = _gf_true; - } - } + me = (struct mountentry *)GF_CALLOC(1, sizeof(*me), gf_nfs_mt_mountentry); + if (!me) + return -1; + nfs = (struct nfs_state *)ms->nfsx->private; - INIT_LIST_HEAD (&me->mlist); - /* Must get the IP or hostname of the client so we - * can map it into the mount entry. - */ - ret = rpcsvc_transport_peername (req->trans, me->hostname, MNTPATHLEN); - if (ret == -1) - goto free_err; + update_rmtab = mount_open_rmtab(nfs->rmtab, &sh); - colon = strrchr (me->hostname, ':'); - if (colon) { - *colon = '\0'; + snprintf(me->exname, MNTPATHLEN, "%s", expname); + /* Sometimes we don't care about the full path + * so a NULL value for fullpath is valid. + */ + if (fullpath) { + if (strlen(fullpath) < MNTPATHLEN) { + strcpy(me->fullpath, fullpath); + me->has_full_path = _gf_true; } - LOCK (&ms->mountlock); - { - /* in case locking fails, we just don't write the rmtab */ - if (update_rmtab && gf_store_lock (sh)) { - gf_msg (GF_MNT, GF_LOG_WARNING, 0, NFS_MSG_LOCK_FAIL, - "Failed to lock '%s', changes will not be " - "written", nfs->rmtab); - } else if (update_rmtab) { - __mount_read_rmtab (sh, &ms->mountlist, _gf_false); - } + } - /* do not add duplicates */ - list_for_each_entry (cur, &ms->mountlist, mlist) { - if (!strcmp(cur->hostname, me->hostname) && - !strcmp(cur->exname, me->exname)) { - GF_FREE (me); - goto dont_add; - } - } - list_add_tail (&me->mlist, &ms->mountlist); - __mountdict_insert (ms, me); + INIT_LIST_HEAD(&me->mlist); + /* Must get the IP or hostname of the client so we + * can map it into the mount entry. + */ + ret = rpcsvc_transport_peername(req->trans, me->hostname, MNTPATHLEN); + if (ret == -1) + goto free_err; - /* only write the rmtab in case it was locked */ - if (update_rmtab && gf_store_locked_local (sh)) - __mount_rewrite_rmtab (ms, sh); - } + colon = strrchr(me->hostname, ':'); + if (colon) { + *colon = '\0'; + } + LOCK(&ms->mountlock); + { + /* in case locking fails, we just don't write the rmtab */ + if (update_rmtab && gf_store_lock(sh)) { + gf_msg(GF_MNT, GF_LOG_WARNING, 0, NFS_MSG_LOCK_FAIL, + "Failed to lock '%s', changes will not be " + "written", + nfs->rmtab); + } else if (update_rmtab) { + __mount_read_rmtab(sh, &ms->mountlist, _gf_false); + } + + /* do not add duplicates */ + list_for_each_entry(cur, &ms->mountlist, mlist) + { + if (!strcmp(cur->hostname, me->hostname) && + !strcmp(cur->exname, me->exname)) { + GF_FREE(me); + goto dont_add; + } + } + list_add_tail(&me->mlist, &ms->mountlist); + __mountdict_insert(ms, me); + + /* only write the rmtab in case it was locked */ + if (update_rmtab && gf_store_locked_local(sh)) + __mount_rewrite_rmtab(ms, sh); + } dont_add: - if (update_rmtab && gf_store_locked_local (sh)) - gf_store_unlock (sh); + if (update_rmtab && gf_store_locked_local(sh)) + gf_store_unlock(sh); - UNLOCK (&ms->mountlock); + UNLOCK(&ms->mountlock); free_err: - if (update_rmtab) - gf_store_handle_destroy (sh); + if (update_rmtab) + gf_store_handle_destroy(sh); - if (ret == -1) - GF_FREE (me); + if (ret == -1) + GF_FREE(me); - return ret; + return ret; } - int -__mnt3_get_volume_id (struct mount3_state *ms, xlator_t *mntxl, - uuid_t volumeid) +__mnt3_get_volume_id(struct mount3_state *ms, xlator_t *mntxl, uuid_t volumeid) { - int ret = -1; - struct mnt3_export *exp = NULL; - - if ((!ms) || (!mntxl)) - return ret; - - LOCK (&ms->mountlock); - list_for_each_entry (exp, &ms->exportlist, explist) { - if (exp->vol == mntxl) { - gf_uuid_copy (volumeid, exp->volumeid); - ret = 0; - goto out; - } + int ret = -1; + struct mnt3_export *exp = NULL; + + if ((!ms) || (!mntxl)) + return ret; + + LOCK(&ms->mountlock); + list_for_each_entry(exp, &ms->exportlist, explist) + { + if (exp->vol == mntxl) { + gf_uuid_copy(volumeid, exp->volumeid); + ret = 0; + goto out; } + } out: - UNLOCK (&ms->mountlock); - return ret; + UNLOCK(&ms->mountlock); + return ret; } int -__mnt3_build_mountid_from_path (const char *path, uuid_t mountid) +__mnt3_build_mountid_from_path(const char *path, uuid_t mountid) { - uint32_t hashed_path = 0; - int ret = -1; + uint32_t hashed_path = 0; + int ret = -1; - if (!path) - goto out; + if (!path) + goto out; - while (strlen (path) > 0 && path[0] == '/') - path++; + while (strlen(path) > 0 && path[0] == '/') + path++; - /* Clear the mountid */ - gf_uuid_clear (mountid); + /* Clear the mountid */ + gf_uuid_clear(mountid); - hashed_path = SuperFastHash (path, strlen (path)); - if (hashed_path == 1) { - gf_msg (GF_MNT, GF_LOG_WARNING, 0, NFS_MSG_HASH_PATH_FAIL, - "failed to hash path: %s", path); - goto out; - } + hashed_path = SuperFastHash(path, strlen(path)); + if (hashed_path == 1) { + gf_msg(GF_MNT, GF_LOG_WARNING, 0, NFS_MSG_HASH_PATH_FAIL, + "failed to hash path: %s", path); + goto out; + } - memcpy (mountid, &hashed_path, sizeof (hashed_path)); - ret = 0; + memcpy(mountid, &hashed_path, sizeof(hashed_path)); + ret = 0; out: - return ret; + return ret; } int -__mnt3_get_mount_id (xlator_t *mntxl, uuid_t mountid) +__mnt3_get_mount_id(xlator_t *mntxl, uuid_t mountid) { - int ret = -1; - uint32_t hashed_path = 0; + int ret = -1; + uint32_t hashed_path = 0; + /* first clear the mountid */ + gf_uuid_clear(mountid); - /* first clear the mountid */ - gf_uuid_clear (mountid); + hashed_path = SuperFastHash(mntxl->name, strlen(mntxl->name)); + if (hashed_path == 1) { + gf_msg(GF_MNT, GF_LOG_WARNING, 0, NFS_MSG_HASH_XLATOR_FAIL, + "failed to hash xlator name: %s", mntxl->name); + goto out; + } - hashed_path = SuperFastHash (mntxl->name, strlen (mntxl->name)); - if (hashed_path == 1) { - gf_msg (GF_MNT, GF_LOG_WARNING, 0, NFS_MSG_HASH_XLATOR_FAIL, - "failed to hash xlator name: %s", mntxl->name); - goto out; - } - - memcpy (mountid, &hashed_path, sizeof (hashed_path)); - ret = 0; + memcpy(mountid, &hashed_path, sizeof(hashed_path)); + ret = 0; out: - return ret; + return ret; } - 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) +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) { - mountres3 res = {0, }; - rpcsvc_request_t *req = NULL; - struct nfs3_fh fh = {{0}, }; - struct mount3_state *ms = NULL; - mountstat3 status = 0; - int autharr[10]; - int autharrlen = 0; - rpcsvc_t *svc = NULL; - xlator_t *mntxl = NULL; - uuid_t volumeid = {0, }; - char *path = NULL; - uuid_t mountid = {1, }; - char fhstr[1536]; - int alloclen = 0; - - req = (rpcsvc_request_t *)frame->local; - - if (!req) - return -1; - - mntxl = (xlator_t *)cookie; - ms = (struct mount3_state *)rpcsvc_request_program_private (req); - if (!ms) { - gf_msg (GF_MNT, GF_LOG_ERROR, EINVAL, - NFS_MSG_MNT_STATE_NOT_FOUND, - "mount state not found"); - op_ret = -1; - op_errno = EINVAL; - } - - if (op_ret == -1) { - gf_msg (GF_NFS, GF_LOG_ERROR, op_errno, - NFS_MSG_LOOKUP_MNT_ERROR, "error=%s", - strerror (op_errno)); - status = mnt3svc_errno_to_mnterr (op_errno); - } - if (status != MNT3_OK) - goto xmit_res; - - alloclen = strlen(mntxl->name) + 2; - path = GF_MALLOC (alloclen, gf_nfs_mt_char); - if (!path) { - gf_msg (GF_MNT, GF_LOG_ERROR, ENOMEM, - NFS_MSG_NO_MEMORY, - "Memory allocation failed."); - goto xmit_res; - } - - snprintf (path, alloclen, "/%s", mntxl->name); - mnt3svc_update_mountlist (ms, req, path, NULL); - GF_FREE (path); - if (gf_nfs_dvm_off (nfs_state (ms->nfsx))) { - fh = nfs3_fh_build_indexed_root_fh (ms->nfsx->children, mntxl); - goto xmit_res; - } + mountres3 res = { + 0, + }; + rpcsvc_request_t *req = NULL; + struct nfs3_fh fh = { + {0}, + }; + struct mount3_state *ms = NULL; + mountstat3 status = 0; + int autharr[10]; + int autharrlen = 0; + rpcsvc_t *svc = NULL; + xlator_t *mntxl = NULL; + uuid_t volumeid = { + 0, + }; + char *path = NULL; + uuid_t mountid = { + 1, + }; + char fhstr[1536]; + int alloclen = 0; + + req = (rpcsvc_request_t *)frame->local; + + if (!req) + return -1; - __mnt3_get_mount_id (mntxl, mountid); - __mnt3_get_volume_id (ms, mntxl, volumeid); - fh = nfs3_fh_build_uuid_root_fh (volumeid, mountid); + mntxl = (xlator_t *)cookie; + ms = (struct mount3_state *)rpcsvc_request_program_private(req); + if (!ms) { + gf_msg(GF_MNT, GF_LOG_ERROR, EINVAL, NFS_MSG_MNT_STATE_NOT_FOUND, + "mount state not found"); + op_ret = -1; + op_errno = EINVAL; + } + + if (op_ret == -1) { + gf_msg(GF_NFS, GF_LOG_ERROR, op_errno, NFS_MSG_LOOKUP_MNT_ERROR, + "error=%s", strerror(op_errno)); + status = mnt3svc_errno_to_mnterr(op_errno); + } + if (status != MNT3_OK) + goto xmit_res; + + alloclen = strlen(mntxl->name) + 2; + path = GF_MALLOC(alloclen, gf_nfs_mt_char); + if (!path) { + gf_msg(GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, + "Memory allocation failed."); + goto xmit_res; + } + + snprintf(path, alloclen, "/%s", mntxl->name); + mnt3svc_update_mountlist(ms, req, path, NULL); + GF_FREE(path); + if (gf_nfs_dvm_off(nfs_state(ms->nfsx))) { + fh = nfs3_fh_build_indexed_root_fh(ms->nfsx->children, mntxl); + goto xmit_res; + } + + __mnt3_get_mount_id(mntxl, mountid); + __mnt3_get_volume_id(ms, mntxl, volumeid); + fh = nfs3_fh_build_uuid_root_fh(volumeid, mountid); xmit_res: - nfs3_fh_to_str (&fh, fhstr, sizeof (fhstr)); - gf_msg_debug (GF_MNT, 0, "MNT reply: fh %s, status: %d", fhstr, - status); - if (op_ret == 0) { - svc = rpcsvc_request_service (req); - autharrlen = rpcsvc_auth_array (svc, mntxl->name, autharr, - 10); - } - - res = mnt3svc_set_mountres3 (status, &fh, autharr, autharrlen); - mnt3svc_submit_reply (req, (void *)&res, - (mnt3_serializer)xdr_serialize_mountres3); - - return 0; + nfs3_fh_to_str(&fh, fhstr, sizeof(fhstr)); + gf_msg_debug(GF_MNT, 0, "MNT reply: fh %s, status: %d", fhstr, status); + if (op_ret == 0) { + svc = rpcsvc_request_service(req); + autharrlen = rpcsvc_auth_array(svc, mntxl->name, autharr, 10); + } + + res = mnt3svc_set_mountres3(status, &fh, autharr, autharrlen); + mnt3svc_submit_reply(req, (void *)&res, + (mnt3_serializer)xdr_serialize_mountres3); + + return 0; } - int -mnt3_match_dirpath_export (const char *expname, const char *dirpath, - gf_boolean_t export_parsing_match) +mnt3_match_dirpath_export(const char *expname, const char *dirpath, + gf_boolean_t export_parsing_match) { - int ret = 0; - size_t dlen; - char *fullpath = NULL; - char *second_slash = NULL; - char *dirdup = NULL; + int ret = 0; + size_t dlen; + char *fullpath = NULL; + char *second_slash = NULL; + char *dirdup = NULL; - if ((!expname) || (!dirpath)) - return 0; + if ((!expname) || (!dirpath)) + return 0; - dirdup = strdupa (dirpath); + dirdup = strdupa(dirpath); - /* Some clients send a dirpath for mount that includes the slash at the - * end. String compare for searching the export will fail because our - * exports list does not include that slash. Remove the slash to - * compare. - */ - dlen = strlen (dirdup); - if (dlen && dirdup[dlen - 1] == '/') - dirdup[dlen - 1] = '\0'; + /* Some clients send a dirpath for mount that includes the slash at the + * end. String compare for searching the export will fail because our + * exports list does not include that slash. Remove the slash to + * compare. + */ + dlen = strlen(dirdup); + if (dlen && dirdup[dlen - 1] == '/') + dirdup[dlen - 1] = '\0'; - /* Here we try to match fullpaths with export names */ - fullpath = dirdup; + /* Here we try to match fullpaths with export names */ + fullpath = dirdup; - if (export_parsing_match) { - if (dirdup[0] == '/') - fullpath = dirdup + 1; + if (export_parsing_match) { + if (dirdup[0] == '/') + fullpath = dirdup + 1; - second_slash = strchr (fullpath, '/'); - if (second_slash) - *second_slash = '\0'; - } + second_slash = strchr(fullpath, '/'); + if (second_slash) + *second_slash = '\0'; + } - /* The export name begins with a slash so move it forward by one - * to ignore the slash when we want to compare the fullpath and - * export. - */ - if (fullpath[0] != '/') - expname++; + /* The export name begins with a slash so move it forward by one + * to ignore the slash when we want to compare the fullpath and + * export. + */ + if (fullpath[0] != '/') + expname++; - if (strcmp (expname, fullpath) == 0) - ret = 1; + if (strcmp(expname, fullpath) == 0) + ret = 1; - return ret; + return ret; } - int -mnt3svc_mount_inode (rpcsvc_request_t *req, struct mount3_state *ms, - xlator_t * xl, inode_t *exportinode) +mnt3svc_mount_inode(rpcsvc_request_t *req, struct mount3_state *ms, + xlator_t *xl, inode_t *exportinode) { - int ret = -EFAULT; - nfs_user_t nfu = {0, }; - loc_t exportloc = {0, }; - - if ((!req) || (!xl) || (!ms) || (!exportinode)) - return ret; - - ret = nfs_inode_loc_fill (exportinode, &exportloc, NFS_RESOLVE_EXIST); - if (ret < 0) { - gf_msg (GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_INODE_LOC_FILL_ERROR, - "Loc fill failed for export inode" - ": gfid %s, volume: %s", - uuid_utoa (exportinode->gfid), xl->name); - goto err; - } - - /* To service the mount request, all we need to do - * is to send a lookup fop that returns the stat - * for the root of the child volume. This is - * used to build the root fh sent to the client. - */ - nfs_request_user_init (&nfu, req); - ret = nfs_lookup (ms->nfsx, xl, &nfu, &exportloc, - mnt3svc_lookup_mount_cbk, (void *)req); + int ret = -EFAULT; + nfs_user_t nfu = { + 0, + }; + loc_t exportloc = { + 0, + }; + + if ((!req) || (!xl) || (!ms) || (!exportinode)) + return ret; - nfs_loc_wipe (&exportloc); + ret = nfs_inode_loc_fill(exportinode, &exportloc, NFS_RESOLVE_EXIST); + if (ret < 0) { + gf_msg(GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_INODE_LOC_FILL_ERROR, + "Loc fill failed for export inode" + ": gfid %s, volume: %s", + uuid_utoa(exportinode->gfid), xl->name); + goto err; + } + + /* To service the mount request, all we need to do + * is to send a lookup fop that returns the stat + * for the root of the child volume. This is + * used to build the root fh sent to the client. + */ + nfs_request_user_init(&nfu, req); + ret = nfs_lookup(ms->nfsx, xl, &nfu, &exportloc, mnt3svc_lookup_mount_cbk, + (void *)req); + + nfs_loc_wipe(&exportloc); err: - return ret; + return ret; } - /* For a volume mount request, we just have to create loc on the root inode, * and send a lookup. In the lookup callback the mount reply is send along with * the file handle. */ int -mnt3svc_volume_mount (rpcsvc_request_t *req, struct mount3_state *ms, - struct mnt3_export *exp) +mnt3svc_volume_mount(rpcsvc_request_t *req, struct mount3_state *ms, + struct mnt3_export *exp) { - inode_t *exportinode = NULL; - int ret = -EFAULT; - uuid_t rootgfid = {0, }; - - if ((!req) || (!exp) || (!ms)) - return ret; - - rootgfid[15] = 1; - exportinode = inode_find (exp->vol->itable, rootgfid); - if (!exportinode) { - gf_msg (GF_MNT, GF_LOG_ERROR, ENOENT, - NFS_MSG_GET_ROOT_INODE_FAIL, - "Failed to get root inode"); - ret = -ENOENT; - goto err; - } + inode_t *exportinode = NULL; + int ret = -EFAULT; + uuid_t rootgfid = { + 0, + }; + + if ((!req) || (!exp) || (!ms)) + return ret; + + rootgfid[15] = 1; + exportinode = inode_find(exp->vol->itable, rootgfid); + if (!exportinode) { + gf_msg(GF_MNT, GF_LOG_ERROR, ENOENT, NFS_MSG_GET_ROOT_INODE_FAIL, + "Failed to get root inode"); + ret = -ENOENT; + goto err; + } - ret = mnt3svc_mount_inode (req, ms, exp->vol, exportinode); - inode_unref (exportinode); + ret = mnt3svc_mount_inode(req, ms, exp->vol, exportinode); + inode_unref(exportinode); err: - return ret; + return ret; } - /* The catch with directory exports is that the first component of the export * name will be the name of the volume. * Any lookup that needs to be performed to build the directory's file handle @@ -951,280 +950,280 @@ err: * we need to strip out the volume name first. */ char * -mnt3_get_volume_subdir (char *dirpath, char **volname) +mnt3_get_volume_subdir(char *dirpath, char **volname) { - /* subdir points to the first / after the volume name while dirpath - * points to the first char of the volume name. - */ - char *subdir = NULL; - int volname_len = 0; - static char *root = "/"; - - /* all callers are expected to pass a valid *dirpath */ - GF_ASSERT (dirpath); - - if (dirpath[0] == '/') - dirpath++; - - subdir = index (dirpath, (int)'/'); - if (!subdir) { - subdir = root; - volname_len = strlen (dirpath); - } else { - volname_len = subdir - dirpath; - } - - if (!volname) - goto out; - - if (!*volname) - goto out; - - strncpy (*volname, dirpath, volname_len); - *(*volname + volname_len) = '\0'; + /* subdir points to the first / after the volume name while dirpath + * points to the first char of the volume name. + */ + char *subdir = NULL; + int volname_len = 0; + static char *root = "/"; + + /* all callers are expected to pass a valid *dirpath */ + GF_ASSERT(dirpath); + + if (dirpath[0] == '/') + dirpath++; + + subdir = index(dirpath, (int)'/'); + if (!subdir) { + subdir = root; + volname_len = strlen(dirpath); + } else { + volname_len = subdir - dirpath; + } + + if (!volname) + goto out; + + if (!*volname) + goto out; + + strncpy(*volname, dirpath, volname_len); + *(*volname + volname_len) = '\0'; out: - return subdir; + return subdir; } - void -mnt3_resolve_state_wipe (mnt3_resolve_t *mres) +mnt3_resolve_state_wipe(mnt3_resolve_t *mres) { - if (!mres) - return; - - nfs_loc_wipe (&mres->resolveloc); - GF_FREE (mres); + if (!mres) + return; + nfs_loc_wipe(&mres->resolveloc); + GF_FREE(mres); } - /* Sets up the component argument to contain the next component in the path and * sets up path as an absolute path starting from the next component. */ static char * -setup_next_component (char *path, size_t plen, char *component, size_t clen) +setup_next_component(char *path, size_t plen, char *component, size_t clen) { - char *comp = NULL; - char *nextcomp = NULL; - - if ((!path) || (!component)) - return NULL; - - strncpy (component, path, clen); - comp = index (component, (int)'/'); - if (!comp) - goto err; - - comp++; - nextcomp = index (comp, (int)'/'); - if (nextcomp) { - strncpy (path, nextcomp, plen); - *nextcomp = '\0'; - } else - path[0] = '\0'; + char *comp = NULL; + char *nextcomp = NULL; + + if ((!path) || (!component)) + return NULL; + + strncpy(component, path, clen); + comp = index(component, (int)'/'); + if (!comp) + goto err; + + comp++; + nextcomp = index(comp, (int)'/'); + if (nextcomp) { + strncpy(path, nextcomp, plen); + *nextcomp = '\0'; + } else + path[0] = '\0'; err: - return comp; + return comp; } int32_t -mnt3_resolve_subdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, inode_t *inode, - struct iatt *buf, dict_t *xattr, - struct iatt *postparent); +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); 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); +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); /* There are multiple components in the directory export path and each one * needs to be looked up one after the other. */ int -__mnt3_resolve_export_subdir_comp (mnt3_resolve_t *mres) +__mnt3_resolve_export_subdir_comp(mnt3_resolve_t *mres) { - char dupsubdir[MNTPATHLEN]; - char *nextcomp = NULL; - int ret = -EFAULT; - nfs_user_t nfu = {0, }; - uuid_t gfid = {0, }; - - if (!mres) - return ret; - - nextcomp = setup_next_component (mres->remainingdir, - sizeof (mres->remainingdir), - dupsubdir, sizeof (dupsubdir)); - if (!nextcomp) - goto err; - - /* Wipe the contents of the previous component */ - gf_uuid_copy (gfid, mres->resolveloc.inode->gfid); - nfs_loc_wipe (&mres->resolveloc); - ret = nfs_entry_loc_fill (mres->mstate->nfsx, mres->exp->vol->itable, - gfid, nextcomp, &mres->resolveloc, - NFS_RESOLVE_CREATE, NULL); - if ((ret < 0) && (ret != -2)) { - gf_msg (GF_MNT, GF_LOG_ERROR, EFAULT, - NFS_MSG_RESOLVE_INODE_FAIL, "Failed to resolve and " - "create inode: parent gfid %s, entry %s", - uuid_utoa (gfid), nextcomp); - ret = -EFAULT; - goto err; - } + char dupsubdir[MNTPATHLEN]; + char *nextcomp = NULL; + int ret = -EFAULT; + nfs_user_t nfu = { + 0, + }; + uuid_t gfid = { + 0, + }; + + if (!mres) + return ret; - nfs_request_user_init (&nfu, mres->req); - if (IA_ISLNK (mres->resolveloc.inode->ia_type)) { - ret = nfs_readlink (mres->mstate->nfsx, mres->exp->vol, &nfu, - &mres->resolveloc, mnt3_readlink_cbk, mres); - gf_msg_debug (GF_MNT, 0, "Symlink found , need to resolve" - " into directory handle"); - goto err; - } - ret = nfs_lookup (mres->mstate->nfsx, mres->exp->vol, &nfu, - &mres->resolveloc, mnt3_resolve_subdir_cbk, mres); + nextcomp = setup_next_component(mres->remainingdir, + sizeof(mres->remainingdir), dupsubdir, + sizeof(dupsubdir)); + if (!nextcomp) + goto err; + + /* Wipe the contents of the previous component */ + gf_uuid_copy(gfid, mres->resolveloc.inode->gfid); + nfs_loc_wipe(&mres->resolveloc); + ret = nfs_entry_loc_fill(mres->mstate->nfsx, mres->exp->vol->itable, gfid, + nextcomp, &mres->resolveloc, NFS_RESOLVE_CREATE, + NULL); + if ((ret < 0) && (ret != -2)) { + gf_msg(GF_MNT, GF_LOG_ERROR, EFAULT, NFS_MSG_RESOLVE_INODE_FAIL, + "Failed to resolve and " + "create inode: parent gfid %s, entry %s", + uuid_utoa(gfid), nextcomp); + ret = -EFAULT; + goto err; + } + + nfs_request_user_init(&nfu, mres->req); + if (IA_ISLNK(mres->resolveloc.inode->ia_type)) { + ret = nfs_readlink(mres->mstate->nfsx, mres->exp->vol, &nfu, + &mres->resolveloc, mnt3_readlink_cbk, mres); + gf_msg_debug(GF_MNT, 0, + "Symlink found , need to resolve" + " into directory handle"); + goto err; + } + ret = nfs_lookup(mres->mstate->nfsx, mres->exp->vol, &nfu, + &mres->resolveloc, mnt3_resolve_subdir_cbk, mres); err: - return ret; + return ret; } -int __mnt3_resolve_subdir (mnt3_resolve_t *mres); +int +__mnt3_resolve_subdir(mnt3_resolve_t *mres); /* * Per the AFR2 comments, this function performs the "fresh" lookup * by deleting the inode from cache and calling __mnt3_resolve_subdir * again. */ -int __mnt3_fresh_lookup (mnt3_resolve_t *mres) { - inode_unlink (mres->resolveloc.inode, - mres->resolveloc.parent, mres->resolveloc.name); - strncpy (mres->remainingdir, mres->resolveloc.path, - strlen(mres->resolveloc.path)); - nfs_loc_wipe (&mres->resolveloc); - return __mnt3_resolve_subdir (mres); +int +__mnt3_fresh_lookup(mnt3_resolve_t *mres) +{ + inode_unlink(mres->resolveloc.inode, mres->resolveloc.parent, + mres->resolveloc.name); + strncpy(mres->remainingdir, mres->resolveloc.path, + strlen(mres->resolveloc.path)); + nfs_loc_wipe(&mres->resolveloc); + return __mnt3_resolve_subdir(mres); } int32_t -mnt3_resolve_subdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, inode_t *inode, - struct iatt *buf, dict_t *xattr, - struct iatt *postparent) +mnt3_resolve_subdir_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, dict_t *xattr, + struct iatt *postparent) { - mnt3_resolve_t *mres = NULL; - mountstat3 mntstat = MNT3ERR_SERVERFAULT; - struct nfs3_fh fh = {{0}, }; - int autharr[10]; - int autharrlen = 0; - rpcsvc_t *svc = NULL; - mountres3 res = {0, }; - xlator_t *mntxl = NULL; - char *path = NULL; - struct mount3_state *ms = NULL; - int authcode = 0; - char *authorized_host = NULL; - char *authorized_path = NULL; - inode_t *linked_inode = NULL; - - mres = frame->local; - ms = mres->mstate; - mntxl = (xlator_t *)cookie; - if (op_ret == -1 && op_errno == ESTALE) { - /* Nuke inode from cache and try the LOOKUP - * request again. */ - return __mnt3_fresh_lookup (mres); - } else if (op_ret == -1) { - gf_msg (GF_NFS, GF_LOG_ERROR, op_errno, - NFS_MSG_RESOLVE_SUBDIR_FAIL, "path=%s (%s)", - mres->resolveloc.path, strerror (op_errno)); - mntstat = mnt3svc_errno_to_mnterr (op_errno); - goto err; + mnt3_resolve_t *mres = NULL; + mountstat3 mntstat = MNT3ERR_SERVERFAULT; + struct nfs3_fh fh = { + {0}, + }; + int autharr[10]; + int autharrlen = 0; + rpcsvc_t *svc = NULL; + mountres3 res = { + 0, + }; + xlator_t *mntxl = NULL; + char *path = NULL; + struct mount3_state *ms = NULL; + int authcode = 0; + char *authorized_host = NULL; + char *authorized_path = NULL; + inode_t *linked_inode = NULL; + + mres = frame->local; + ms = mres->mstate; + mntxl = (xlator_t *)cookie; + if (op_ret == -1 && op_errno == ESTALE) { + /* Nuke inode from cache and try the LOOKUP + * request again. */ + return __mnt3_fresh_lookup(mres); + } else if (op_ret == -1) { + gf_msg(GF_NFS, GF_LOG_ERROR, op_errno, NFS_MSG_RESOLVE_SUBDIR_FAIL, + "path=%s (%s)", mres->resolveloc.path, strerror(op_errno)); + mntstat = mnt3svc_errno_to_mnterr(op_errno); + goto err; + } + + linked_inode = inode_link(mres->resolveloc.inode, mres->resolveloc.parent, + mres->resolveloc.name, buf); + + if (linked_inode) + nfs_fix_generation(this, linked_inode); + + nfs3_fh_build_child_fh(&mres->parentfh, buf, &fh); + if (strlen(mres->remainingdir) <= 0) { + int alloclen; + op_ret = -1; + mntstat = MNT3_OK; + + /* Construct the full path */ + int resolveloc_path_len = strlen(mres->resolveloc.path); + alloclen = strlen(mres->exp->expname) + resolveloc_path_len + 1; + mres->exp->fullpath = GF_MALLOC(alloclen, gf_nfs_mt_char); + if (!mres->exp->fullpath) { + gf_msg(GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, + "Memory allocation failed."); + goto err; + } + snprintf(mres->exp->fullpath, alloclen, "%s%s", mres->exp->expname, + mres->resolveloc.path); + + /* Check if this path is authorized to be mounted */ + authcode = mnt3_authenticate_request( + ms, mres->req, NULL, NULL, mres->exp->fullpath, &authorized_path, + &authorized_host, FALSE); + if (authcode != 0) { + mntstat = MNT3ERR_ACCES; + gf_msg_debug(GF_MNT, 0, "Client mount not allowed"); + op_ret = -1; + goto err; } - linked_inode = inode_link (mres->resolveloc.inode, - mres->resolveloc.parent, - mres->resolveloc.name, buf); - - if (linked_inode) - nfs_fix_generation (this, linked_inode); - - nfs3_fh_build_child_fh (&mres->parentfh, buf, &fh); - if (strlen (mres->remainingdir) <= 0) { - int alloclen; - op_ret = -1; - mntstat = MNT3_OK; - - /* Construct the full path */ - int resolveloc_path_len = strlen(mres->resolveloc.path); - alloclen = strlen (mres->exp->expname) + - resolveloc_path_len + 1; - mres->exp->fullpath = GF_MALLOC (alloclen, gf_nfs_mt_char); - if (!mres->exp->fullpath) { - gf_msg (GF_MNT, GF_LOG_ERROR, ENOMEM, - NFS_MSG_NO_MEMORY, - "Memory allocation failed."); - goto err; - } - snprintf (mres->exp->fullpath, alloclen, "%s%s", - mres->exp->expname, mres->resolveloc.path); - - /* Check if this path is authorized to be mounted */ - authcode = mnt3_authenticate_request (ms, mres->req, NULL, NULL, - mres->exp->fullpath, - &authorized_path, - &authorized_host, - FALSE); - if (authcode != 0) { - mntstat = MNT3ERR_ACCES; - gf_msg_debug (GF_MNT, 0, "Client mount not allowed"); - op_ret = -1; - goto err; - } - - alloclen = strlen (mres->exp->vol->name) + - resolveloc_path_len + 2; - path = GF_MALLOC (alloclen, gf_nfs_mt_char); - if (!path) { - gf_msg (GF_MNT, GF_LOG_ERROR, ENOMEM, - NFS_MSG_NO_MEMORY, - "Memory allocation failed"); - goto err; - } - /* Build mountid from the authorized path and stick it in the - * filehandle that will get passed back to the client - */ - __mnt3_build_mountid_from_path (authorized_path, fh.mountid); - - snprintf (path, alloclen, "/%s%s", mres->exp->vol->name, - mres->resolveloc.path); - - mnt3svc_update_mountlist (mres->mstate, mres->req, - path, mres->exp->fullpath); - GF_FREE (path); - } else { - mres->parentfh = fh; - op_ret = __mnt3_resolve_export_subdir_comp (mres); - if (op_ret < 0) - mntstat = mnt3svc_errno_to_mnterr (-op_ret); + alloclen = strlen(mres->exp->vol->name) + resolveloc_path_len + 2; + path = GF_MALLOC(alloclen, gf_nfs_mt_char); + if (!path) { + gf_msg(GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, + "Memory allocation failed"); + goto err; } + /* Build mountid from the authorized path and stick it in the + * filehandle that will get passed back to the client + */ + __mnt3_build_mountid_from_path(authorized_path, fh.mountid); + + snprintf(path, alloclen, "/%s%s", mres->exp->vol->name, + mres->resolveloc.path); + + mnt3svc_update_mountlist(mres->mstate, mres->req, path, + mres->exp->fullpath); + GF_FREE(path); + } else { + mres->parentfh = fh; + op_ret = __mnt3_resolve_export_subdir_comp(mres); + if (op_ret < 0) + mntstat = mnt3svc_errno_to_mnterr(-op_ret); + } err: - if (op_ret == -1) { - gf_msg_debug (GF_MNT, 0, "Mount reply status: %d", mntstat); - svc = rpcsvc_request_service (mres->req); - autharrlen = rpcsvc_auth_array (svc, mntxl->name, autharr, - 10); - - res = mnt3svc_set_mountres3 (mntstat, &fh, autharr, autharrlen); - mnt3svc_submit_reply (mres->req, (void *)&res, - (mnt3_serializer)xdr_serialize_mountres3); - mnt3_resolve_state_wipe (mres); - } + if (op_ret == -1) { + gf_msg_debug(GF_MNT, 0, "Mount reply status: %d", mntstat); + svc = rpcsvc_request_service(mres->req); + autharrlen = rpcsvc_auth_array(svc, mntxl->name, autharr, 10); - GF_FREE (authorized_path); - GF_FREE (authorized_host); + res = mnt3svc_set_mountres3(mntstat, &fh, autharr, autharrlen); + mnt3svc_submit_reply(mres->req, (void *)&res, + (mnt3_serializer)xdr_serialize_mountres3); + mnt3_resolve_state_wipe(mres); + } - return 0; + GF_FREE(authorized_path); + GF_FREE(authorized_host); + + return 0; } /* This function resolves symbolic link into directory path from @@ -1251,105 +1250,106 @@ err: * similar to udp */ 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) +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) { - mnt3_resolve_t *mres = NULL; - int ret = -EFAULT; - char *real_loc = NULL; - size_t path_len = 0; - size_t parent_path_len = 0; - char *parent_path = NULL; - char *absolute_path = NULL; - char *relative_path = NULL; - int mntstat = 0; - - GF_ASSERT (frame); - - mres = frame->local; - if (!mres || !path || (path[0] == '/') || (op_ret < 0)) - goto mnterr; - - /* Finding current location of symlink */ - parent_path_len = strlen (mres->resolveloc.path) - strlen (mres->resolveloc.name); - parent_path = gf_strndup (mres->resolveloc.path, parent_path_len); - if (!parent_path) { - ret = -ENOMEM; - goto mnterr; - } - - relative_path = gf_strdup (path); - if (!relative_path) { - ret = -ENOMEM; - goto mnterr; - } - /* Resolving into absolute path */ - ret = gf_build_absolute_path (parent_path, relative_path, &absolute_path); - if (ret < 0) { - gf_msg (GF_MNT, GF_LOG_ERROR, ret, - NFS_MSG_RESOLVE_SYMLINK_ERROR, - "Cannot resolve symlink, path is out of boundary " - "from current location %s and with relative path " - "%s pointed by symlink", parent_path, relative_path); - - goto mnterr; - } - - /* Building the actual mount path to be mounted */ - path_len = strlen (mres->exp->vol->name) + strlen (absolute_path) - + strlen (mres->remainingdir) + 1; - real_loc = GF_MALLOC (path_len, gf_nfs_mt_char); - if (!real_loc) { - ret = -ENOMEM; - goto mnterr; - } - snprintf (real_loc, path_len, "%s%s", mres->exp->vol->name, absolute_path); - gf_path_strip_trailing_slashes (real_loc); - - /* There may entries after symlink in the mount path, - * we should include remaining entries too */ - if (strlen (mres->remainingdir) > 0) - strcat (real_loc, mres->remainingdir); - - gf_msg_debug (GF_MNT, 0, "Resolved path is : %s%s " - "and actual mount path is %s", - absolute_path, mres->remainingdir, real_loc); - - /* After the resolving the symlink , parsing should be done - * for the populated mount path - */ - ret = mnt3_parse_dir_exports (mres->req, mres->mstate, real_loc, - _gf_true); - - if (ret) { - gf_msg (GF_MNT, GF_LOG_ERROR, 0, NFS_MSG_RESOLVE_ERROR, - "Resolved into an unknown path %s%s " - "from the current location of symlink %s", - absolute_path, mres->remainingdir, parent_path); - } - - GF_FREE (real_loc); - GF_FREE (absolute_path); - GF_FREE (parent_path); - GF_FREE (relative_path); - - return ret; + mnt3_resolve_t *mres = NULL; + int ret = -EFAULT; + char *real_loc = NULL; + size_t path_len = 0; + size_t parent_path_len = 0; + char *parent_path = NULL; + char *absolute_path = NULL; + char *relative_path = NULL; + int mntstat = 0; + + GF_ASSERT(frame); + + mres = frame->local; + if (!mres || !path || (path[0] == '/') || (op_ret < 0)) + goto mnterr; + + /* Finding current location of symlink */ + parent_path_len = strlen(mres->resolveloc.path) - + strlen(mres->resolveloc.name); + parent_path = gf_strndup(mres->resolveloc.path, parent_path_len); + if (!parent_path) { + ret = -ENOMEM; + goto mnterr; + } + + relative_path = gf_strdup(path); + if (!relative_path) { + ret = -ENOMEM; + goto mnterr; + } + /* Resolving into absolute path */ + ret = gf_build_absolute_path(parent_path, relative_path, &absolute_path); + if (ret < 0) { + gf_msg(GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_RESOLVE_SYMLINK_ERROR, + "Cannot resolve symlink, path is out of boundary " + "from current location %s and with relative path " + "%s pointed by symlink", + parent_path, relative_path); + + goto mnterr; + } + + /* Building the actual mount path to be mounted */ + path_len = strlen(mres->exp->vol->name) + strlen(absolute_path) + + strlen(mres->remainingdir) + 1; + real_loc = GF_MALLOC(path_len, gf_nfs_mt_char); + if (!real_loc) { + ret = -ENOMEM; + goto mnterr; + } + snprintf(real_loc, path_len, "%s%s", mres->exp->vol->name, absolute_path); + gf_path_strip_trailing_slashes(real_loc); + + /* There may entries after symlink in the mount path, + * we should include remaining entries too */ + if (strlen(mres->remainingdir) > 0) + strcat(real_loc, mres->remainingdir); + + gf_msg_debug(GF_MNT, 0, + "Resolved path is : %s%s " + "and actual mount path is %s", + absolute_path, mres->remainingdir, real_loc); + + /* After the resolving the symlink , parsing should be done + * for the populated mount path + */ + ret = mnt3_parse_dir_exports(mres->req, mres->mstate, real_loc, _gf_true); + + if (ret) { + gf_msg(GF_MNT, GF_LOG_ERROR, 0, NFS_MSG_RESOLVE_ERROR, + "Resolved into an unknown path %s%s " + "from the current location of symlink %s", + absolute_path, mres->remainingdir, parent_path); + } + + GF_FREE(real_loc); + GF_FREE(absolute_path); + GF_FREE(parent_path); + GF_FREE(relative_path); + + return ret; mnterr: - if (mres) { - mntstat = mnt3svc_errno_to_mnterr (-ret); - mnt3svc_mnt_error_reply (mres->req, mntstat); - } else - gf_msg (GF_MNT, GF_LOG_CRITICAL, EINVAL, NFS_MSG_INVALID_ENTRY, - "mres == NULL, this should *never* happen"); - if (absolute_path) - GF_FREE (absolute_path); - if (parent_path) - GF_FREE (parent_path); - if (relative_path) - GF_FREE (relative_path); - return ret; + if (mres) { + mntstat = mnt3svc_errno_to_mnterr(-ret); + mnt3svc_mnt_error_reply(mres->req, mntstat); + } else + gf_msg(GF_MNT, GF_LOG_CRITICAL, EINVAL, NFS_MSG_INVALID_ENTRY, + "mres == NULL, this should *never* happen"); + if (absolute_path) + GF_FREE(absolute_path); + if (parent_path) + GF_FREE(parent_path); + if (relative_path) + GF_FREE(relative_path); + return ret; } /* We will always have to perform a hard lookup on all the components of a @@ -1364,69 +1364,72 @@ mnterr: * of the exported directory can be built. */ int -__mnt3_resolve_subdir (mnt3_resolve_t *mres) +__mnt3_resolve_subdir(mnt3_resolve_t *mres) { - char dupsubdir[MNTPATHLEN]; - char *firstcomp = NULL; - int ret = -EFAULT; - nfs_user_t nfu = {0, }; - uuid_t rootgfid = {0, }; - - if (!mres) - return ret; - - firstcomp = setup_next_component (mres->remainingdir, - sizeof (mres->remainingdir), - dupsubdir, sizeof (dupsubdir)); - if (!firstcomp) - goto err; - - rootgfid[15] = 1; - ret = nfs_entry_loc_fill (mres->mstate->nfsx, mres->exp->vol->itable, - rootgfid, firstcomp, &mres->resolveloc, - NFS_RESOLVE_CREATE, NULL); - if ((ret < 0) && (ret != -2)) { - gf_msg (GF_MNT, GF_LOG_ERROR, EFAULT, - NFS_MSG_RESOLVE_INODE_FAIL, "Failed to resolve and " - "create inode for volume root: %s", - mres->exp->vol->name); - ret = -EFAULT; - goto err; - } + char dupsubdir[MNTPATHLEN]; + char *firstcomp = NULL; + int ret = -EFAULT; + nfs_user_t nfu = { + 0, + }; + uuid_t rootgfid = { + 0, + }; + + if (!mres) + return ret; - nfs_request_user_init (&nfu, mres->req); - if (IA_ISLNK (mres->resolveloc.inode->ia_type)) { - ret = nfs_readlink (mres->mstate->nfsx, mres->exp->vol, &nfu, - &mres->resolveloc, mnt3_readlink_cbk, mres); - gf_msg_debug (GF_MNT, 0, "Symlink found , need to resolve " - "into directory handle"); - goto err; - } - ret = nfs_lookup (mres->mstate->nfsx, mres->exp->vol, &nfu, - &mres->resolveloc, mnt3_resolve_subdir_cbk, mres); + firstcomp = setup_next_component(mres->remainingdir, + sizeof(mres->remainingdir), dupsubdir, + sizeof(dupsubdir)); + if (!firstcomp) + goto err; + + rootgfid[15] = 1; + ret = nfs_entry_loc_fill(mres->mstate->nfsx, mres->exp->vol->itable, + rootgfid, firstcomp, &mres->resolveloc, + NFS_RESOLVE_CREATE, NULL); + if ((ret < 0) && (ret != -2)) { + gf_msg(GF_MNT, GF_LOG_ERROR, EFAULT, NFS_MSG_RESOLVE_INODE_FAIL, + "Failed to resolve and " + "create inode for volume root: %s", + mres->exp->vol->name); + ret = -EFAULT; + goto err; + } + + nfs_request_user_init(&nfu, mres->req); + if (IA_ISLNK(mres->resolveloc.inode->ia_type)) { + ret = nfs_readlink(mres->mstate->nfsx, mres->exp->vol, &nfu, + &mres->resolveloc, mnt3_readlink_cbk, mres); + gf_msg_debug(GF_MNT, 0, + "Symlink found , need to resolve " + "into directory handle"); + goto err; + } + ret = nfs_lookup(mres->mstate->nfsx, mres->exp->vol, &nfu, + &mres->resolveloc, mnt3_resolve_subdir_cbk, mres); err: - return ret; + return ret; } - static gf_boolean_t -mnt3_match_subnet_v4 (struct addrinfo *ai, uint32_t saddr, uint32_t mask) +mnt3_match_subnet_v4(struct addrinfo *ai, uint32_t saddr, uint32_t mask) { - for (; ai; ai = ai->ai_next) { - struct sockaddr_in *sin = (struct sockaddr_in *)ai->ai_addr; + for (; ai; ai = ai->ai_next) { + struct sockaddr_in *sin = (struct sockaddr_in *)ai->ai_addr; - if (sin->sin_family != AF_INET) - continue; + if (sin->sin_family != AF_INET) + continue; - if (mask_match (saddr, sin->sin_addr.s_addr, mask)) - return _gf_true; - } + if (mask_match(saddr, sin->sin_addr.s_addr, mask)) + return _gf_true; + } - return _gf_false; + return _gf_false; } - /** * This function will verify if the client is allowed to mount * the directory or not. Client's IP address will be compared with @@ -1440,446 +1443,448 @@ mnt3_match_subnet_v4 (struct addrinfo *ai, uint32_t saddr, uint32_t mask) * TODO: Support IPv6 subnetwork */ int -mnt3_verify_auth (struct sockaddr_in *client_addr, struct mnt3_export *export) +mnt3_verify_auth(struct sockaddr_in *client_addr, struct mnt3_export *export) { - int retvalue = -EACCES; - int ret = 0; - struct host_auth_spec *host = NULL; - struct sockaddr_in *allowed_addr = NULL; - struct addrinfo *allowed_addrinfo = NULL; - - struct addrinfo hint = { - .ai_family = AF_INET, - .ai_protocol = (int)IPPROTO_TCP, - .ai_flags = AI_CANONNAME, - }; - - /* Sanity check */ - if ((NULL == client_addr) || - (NULL == export) || - (NULL == export->hostspec)) { - gf_msg (GF_MNT, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY, - "Invalid argument"); - return retvalue; - } - - host = export->hostspec; - - /* - * Currently IPv4 subnetwork is supported i.e. AF_INET. - * TODO: IPv6 subnetwork i.e. AF_INET6. - */ - if (client_addr->sin_family != AF_INET) { - gf_msg (GF_MNT, GF_LOG_ERROR, EAFNOSUPPORT, - NFS_MSG_UNSUPPORTED_VERSION, - "Only IPv4 is supported for subdir-auth"); - return retvalue; - } + int retvalue = -EACCES; + int ret = 0; + struct host_auth_spec *host = NULL; + struct sockaddr_in *allowed_addr = NULL; + struct addrinfo *allowed_addrinfo = NULL; + + struct addrinfo hint = { + .ai_family = AF_INET, + .ai_protocol = (int)IPPROTO_TCP, + .ai_flags = AI_CANONNAME, + }; + + /* Sanity check */ + if ((NULL == client_addr) || (NULL == export) || + (NULL == export->hostspec)) { + gf_msg(GF_MNT, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY, + "Invalid argument"); + return retvalue; + } - /* Try to see if the client IP matches the allowed IP list.*/ - while (NULL != host){ - GF_ASSERT (host->host_addr); + host = export->hostspec; - if (NULL != allowed_addrinfo) { - freeaddrinfo (allowed_addrinfo); - allowed_addrinfo = NULL; - } + /* + * Currently IPv4 subnetwork is supported i.e. AF_INET. + * TODO: IPv6 subnetwork i.e. AF_INET6. + */ + if (client_addr->sin_family != AF_INET) { + gf_msg(GF_MNT, GF_LOG_ERROR, EAFNOSUPPORT, NFS_MSG_UNSUPPORTED_VERSION, + "Only IPv4 is supported for subdir-auth"); + return retvalue; + } - /* Get the addrinfo for the allowed host (host_addr). */ - ret = getaddrinfo (host->host_addr, NULL, - &hint, &allowed_addrinfo); - if (0 != ret){ - /* - * getaddrinfo() FAILED for the host IP addr. Continue - * to search other allowed hosts in the hostspec list. - */ - gf_msg_debug (GF_MNT, 0, "getaddrinfo: %s\n", - gai_strerror (ret)); - host = host->next; - continue; - } + /* Try to see if the client IP matches the allowed IP list.*/ + while (NULL != host) { + GF_ASSERT(host->host_addr); - allowed_addr = (struct sockaddr_in *)(allowed_addrinfo->ai_addr); - if (NULL == allowed_addr) { - gf_msg (GF_MNT, GF_LOG_ERROR, EINVAL, - NFS_MSG_INVALID_ENTRY, "Invalid structure"); - break; - } + if (NULL != allowed_addrinfo) { + freeaddrinfo(allowed_addrinfo); + allowed_addrinfo = NULL; + } - /* Check if the network addr of both IPv4 socket match */ - if (mnt3_match_subnet_v4 (allowed_addrinfo, - client_addr->sin_addr.s_addr, - host->netmask)) { - retvalue = 0; - break; - } + /* Get the addrinfo for the allowed host (host_addr). */ + ret = getaddrinfo(host->host_addr, NULL, &hint, &allowed_addrinfo); + if (0 != ret) { + /* + * getaddrinfo() FAILED for the host IP addr. Continue + * to search other allowed hosts in the hostspec list. + */ + gf_msg_debug(GF_MNT, 0, "getaddrinfo: %s\n", gai_strerror(ret)); + host = host->next; + continue; + } - /* No match yet, continue the search */ - host = host->next; + allowed_addr = (struct sockaddr_in *)(allowed_addrinfo->ai_addr); + if (NULL == allowed_addr) { + gf_msg(GF_MNT, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY, + "Invalid structure"); + break; } - /* FREE the dynamic memory allocated by getaddrinfo() */ - if (NULL != allowed_addrinfo) { - freeaddrinfo (allowed_addrinfo); + /* Check if the network addr of both IPv4 socket match */ + if (mnt3_match_subnet_v4(allowed_addrinfo, client_addr->sin_addr.s_addr, + host->netmask)) { + retvalue = 0; + break; } - return retvalue; + /* No match yet, continue the search */ + host = host->next; + } + + /* FREE the dynamic memory allocated by getaddrinfo() */ + if (NULL != allowed_addrinfo) { + freeaddrinfo(allowed_addrinfo); + } + + return retvalue; } int -mnt3_resolve_subdir (rpcsvc_request_t *req, struct mount3_state *ms, - struct mnt3_export *exp, char *subdir, - gf_boolean_t send_reply) +mnt3_resolve_subdir(rpcsvc_request_t *req, struct mount3_state *ms, + struct mnt3_export *exp, char *subdir, + gf_boolean_t send_reply) { - mnt3_resolve_t *mres = NULL; - int ret = -EFAULT; - struct nfs3_fh pfh = GF_NFS3FH_STATIC_INITIALIZER; - struct sockaddr_in *sin = NULL; - - if ((!req) || (!ms) || (!exp) || (!subdir)) - return ret; - - sin = (struct sockaddr_in *)(&(req->trans->peerinfo.sockaddr)); - - /* Need to check AUTH */ - if (NULL != exp->hostspec) { - ret = mnt3_verify_auth (sin, exp); - if (0 != ret) { - gf_msg (GF_MNT, GF_LOG_ERROR, EACCES, - NFS_MSG_AUTH_VERIFY_FAILED, - "AUTH verification failed"); - return ret; - } - } + mnt3_resolve_t *mres = NULL; + int ret = -EFAULT; + struct nfs3_fh pfh = GF_NFS3FH_STATIC_INITIALIZER; + struct sockaddr_in *sin = NULL; - /* no reply is needed (WebNFS permissions checking), just return */ - if (!send_reply) - return 0; /* no error, mnt3_verify_auth() allowed it */ + if ((!req) || (!ms) || (!exp) || (!subdir)) + return ret; - mres = GF_CALLOC (1, sizeof (mnt3_resolve_t), gf_nfs_mt_mnt3_resolve); - if (!mres) { - gf_msg (GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, - "Memory allocation failed"); - goto err; + sin = (struct sockaddr_in *)(&(req->trans->peerinfo.sockaddr)); + + /* Need to check AUTH */ + if (NULL != exp->hostspec) { + ret = mnt3_verify_auth(sin, exp); + if (0 != ret) { + gf_msg(GF_MNT, GF_LOG_ERROR, EACCES, NFS_MSG_AUTH_VERIFY_FAILED, + "AUTH verification failed"); + return ret; } + } + + /* no reply is needed (WebNFS permissions checking), just return */ + if (!send_reply) + return 0; /* no error, mnt3_verify_auth() allowed it */ - mres->exp = exp; - mres->mstate = ms; - mres->req = req; + mres = GF_CALLOC(1, sizeof(mnt3_resolve_t), gf_nfs_mt_mnt3_resolve); + if (!mres) { + gf_msg(GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, + "Memory allocation failed"); + goto err; + } - snprintf (mres->remainingdir, MNTPATHLEN, "%s", subdir); - gf_path_strip_trailing_slashes (mres->remainingdir); + mres->exp = exp; + mres->mstate = ms; + mres->req = req; - if (gf_nfs_dvm_off (nfs_state (ms->nfsx))) - pfh = nfs3_fh_build_indexed_root_fh ( - mres->mstate->nfsx->children, + snprintf(mres->remainingdir, MNTPATHLEN, "%s", subdir); + gf_path_strip_trailing_slashes(mres->remainingdir); + + if (gf_nfs_dvm_off(nfs_state(ms->nfsx))) + pfh = nfs3_fh_build_indexed_root_fh(mres->mstate->nfsx->children, mres->exp->vol); - else - pfh = nfs3_fh_build_uuid_root_fh (exp->volumeid, exp->mountid); + else + pfh = nfs3_fh_build_uuid_root_fh(exp->volumeid, exp->mountid); - mres->parentfh = pfh; - ret = __mnt3_resolve_subdir (mres); - if (ret < 0) { - gf_msg (GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_RESOLVE_SUBDIR_FAIL, - "Failed to resolve export dir: %s", mres->exp->expname); - GF_FREE (mres); - } + mres->parentfh = pfh; + ret = __mnt3_resolve_subdir(mres); + if (ret < 0) { + gf_msg(GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_RESOLVE_SUBDIR_FAIL, + "Failed to resolve export dir: %s", mres->exp->expname); + GF_FREE(mres); + } err: - return ret; + return ret; } - int -mnt3_resolve_export_subdir (rpcsvc_request_t *req, struct mount3_state *ms, - struct mnt3_export *exp) +mnt3_resolve_export_subdir(rpcsvc_request_t *req, struct mount3_state *ms, + struct mnt3_export *exp) { - char *volume_subdir = NULL; - int ret = -EFAULT; + char *volume_subdir = NULL; + int ret = -EFAULT; - if ((!req) || (!ms) || (!exp)) - return ret; + if ((!req) || (!ms) || (!exp)) + return ret; - volume_subdir = mnt3_get_volume_subdir (exp->expname, NULL); + volume_subdir = mnt3_get_volume_subdir(exp->expname, NULL); - ret = mnt3_resolve_subdir (req, ms, exp, volume_subdir, _gf_true); - if (ret < 0) { - gf_msg (GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_RESOLVE_SUBDIR_FAIL, - "Failed to resolve export dir: %s", exp->expname); - goto err; - } + ret = mnt3_resolve_subdir(req, ms, exp, volume_subdir, _gf_true); + if (ret < 0) { + gf_msg(GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_RESOLVE_SUBDIR_FAIL, + "Failed to resolve export dir: %s", exp->expname); + goto err; + } err: - return ret; + return ret; } - int -mnt3svc_mount (rpcsvc_request_t *req, struct mount3_state *ms, - struct mnt3_export *exp) +mnt3svc_mount(rpcsvc_request_t *req, struct mount3_state *ms, + struct mnt3_export *exp) { - int ret = -EFAULT; + int ret = -EFAULT; - if ((!req) || (!ms) || (!exp)) - return ret; + if ((!req) || (!ms) || (!exp)) + return ret; - if (exp->exptype == MNT3_EXPTYPE_VOLUME) - ret = mnt3svc_volume_mount (req, ms, exp); - else if (exp->exptype == MNT3_EXPTYPE_DIR) - ret = mnt3_resolve_export_subdir (req, ms, exp); + if (exp->exptype == MNT3_EXPTYPE_VOLUME) + ret = mnt3svc_volume_mount(req, ms, exp); + else if (exp->exptype == MNT3_EXPTYPE_DIR) + ret = mnt3_resolve_export_subdir(req, ms, exp); - return ret; + return ret; } - /* mnt3_mntpath_to_xlator sets this to 1 if the mount is for a full -* volume or 2 for a subdir in the volume. -* -* The parameter 'export_parsing_match' indicates whether this function -* is being called by an exports parser or whether it is being called -* during mount. The behavior is different since we don't have to resolve -* the path when doing the parse. -*/ + * volume or 2 for a subdir in the volume. + * + * The parameter 'export_parsing_match' indicates whether this function + * is being called by an exports parser or whether it is being called + * during mount. The behavior is different since we don't have to resolve + * the path when doing the parse. + */ struct mnt3_export * -mnt3_mntpath_to_export (struct mount3_state *ms, const char *dirpath, - gf_boolean_t export_parsing_match) +mnt3_mntpath_to_export(struct mount3_state *ms, const char *dirpath, + gf_boolean_t export_parsing_match) { - struct mnt3_export *exp = NULL; - struct mnt3_export *found = NULL; - - if ((!ms) || (!dirpath)) - return NULL; - - LOCK (&ms->mountlock); - list_for_each_entry (exp, &ms->exportlist, explist) { - - /* Search for the an exact match with the volume */ - if (mnt3_match_dirpath_export (exp->expname, dirpath, - export_parsing_match)) { - found = exp; - gf_msg_debug (GF_MNT, 0, "Found export volume: " - "%s", exp->vol->name); - goto foundexp; - } - } + struct mnt3_export *exp = NULL; + struct mnt3_export *found = NULL; - gf_msg_debug (GF_MNT, 0, "Export not found"); + if ((!ms) || (!dirpath)) + return NULL; + + LOCK(&ms->mountlock); + list_for_each_entry(exp, &ms->exportlist, explist) + { + /* Search for the an exact match with the volume */ + if (mnt3_match_dirpath_export(exp->expname, dirpath, + export_parsing_match)) { + found = exp; + gf_msg_debug(GF_MNT, 0, + "Found export volume: " + "%s", + exp->vol->name); + goto foundexp; + } + } + + gf_msg_debug(GF_MNT, 0, "Export not found"); foundexp: - UNLOCK (&ms->mountlock); - return found; + UNLOCK(&ms->mountlock); + return found; } - static int -mnt3_check_client_net_check (rpcsvc_t *svc, char *expvol, - char *ipaddr, uint16_t port) +mnt3_check_client_net_check(rpcsvc_t *svc, char *expvol, char *ipaddr, + uint16_t port) { - int ret = RPCSVC_AUTH_REJECT; - - if ((!svc) || (!expvol) || (!ipaddr)) - goto err; - - ret = rpcsvc_auth_check (svc, expvol, ipaddr); - if (ret == RPCSVC_AUTH_REJECT) { - gf_msg (GF_MNT, GF_LOG_INFO, 0, NFS_MSG_PEER_NOT_ALLOWED, - "Peer %s not allowed", ipaddr); - goto err; - } - - ret = rpcsvc_transport_privport_check (svc, expvol, port); - if (ret == RPCSVC_AUTH_REJECT) { - gf_msg (GF_MNT, GF_LOG_INFO, errno, NFS_MSG_PEER_NOT_ALLOWED, - "Peer %s rejected. Unprivileged " - "port %d not allowed", ipaddr, port); - goto err; - } - - ret = RPCSVC_AUTH_ACCEPT; + int ret = RPCSVC_AUTH_REJECT; + + if ((!svc) || (!expvol) || (!ipaddr)) + goto err; + + ret = rpcsvc_auth_check(svc, expvol, ipaddr); + if (ret == RPCSVC_AUTH_REJECT) { + gf_msg(GF_MNT, GF_LOG_INFO, 0, NFS_MSG_PEER_NOT_ALLOWED, + "Peer %s not allowed", ipaddr); + goto err; + } + + ret = rpcsvc_transport_privport_check(svc, expvol, port); + if (ret == RPCSVC_AUTH_REJECT) { + gf_msg(GF_MNT, GF_LOG_INFO, errno, NFS_MSG_PEER_NOT_ALLOWED, + "Peer %s rejected. Unprivileged " + "port %d not allowed", + ipaddr, port); + goto err; + } + + ret = RPCSVC_AUTH_ACCEPT; err: - return ret; + return ret; } int -mnt3_check_client_net_tcp (rpcsvc_request_t *req, char *volname) +mnt3_check_client_net_tcp(rpcsvc_request_t *req, char *volname) { - rpcsvc_t *svc = NULL; - rpc_transport_t *trans = NULL; - union gf_sock_union sock_union; - socklen_t socksize = sizeof (struct sockaddr_in); - char peer[RPCSVC_PEER_STRLEN] = {0,}; - char *ipaddr = NULL; - uint16_t port = 0; - int ret = RPCSVC_AUTH_REJECT; - - if ((!req) || (!volname)) - goto err; - - svc = rpcsvc_request_service (req); - trans = rpcsvc_request_transport (req); - if ((!svc) || (!trans)) - goto err; - - ret = rpcsvc_transport_peeraddr (trans, peer, RPCSVC_PEER_STRLEN, - &sock_union.storage, socksize); - if (ret != 0) { - gf_msg (GF_MNT, GF_LOG_WARNING, ENOENT, - NFS_MSG_GET_PEER_ADDR_FAIL, "Failed to get peer " - "addr: %s", gai_strerror (ret)); - ret = RPCSVC_AUTH_REJECT; - goto err; - } - - /* peer[] gets IP:PORT formar, slash the port out */ - if (!get_host_name ((char *)peer, &ipaddr)) - ipaddr = peer; - - port = ntohs (sock_union.sin.sin_port); - - ret = mnt3_check_client_net_check (svc, volname, ipaddr, port); + rpcsvc_t *svc = NULL; + rpc_transport_t *trans = NULL; + union gf_sock_union sock_union; + socklen_t socksize = sizeof(struct sockaddr_in); + char peer[RPCSVC_PEER_STRLEN] = { + 0, + }; + char *ipaddr = NULL; + uint16_t port = 0; + int ret = RPCSVC_AUTH_REJECT; + + if ((!req) || (!volname)) + goto err; + + svc = rpcsvc_request_service(req); + trans = rpcsvc_request_transport(req); + if ((!svc) || (!trans)) + goto err; + + ret = rpcsvc_transport_peeraddr(trans, peer, RPCSVC_PEER_STRLEN, + &sock_union.storage, socksize); + if (ret != 0) { + gf_msg(GF_MNT, GF_LOG_WARNING, ENOENT, NFS_MSG_GET_PEER_ADDR_FAIL, + "Failed to get peer " + "addr: %s", + gai_strerror(ret)); + ret = RPCSVC_AUTH_REJECT; + goto err; + } + + /* peer[] gets IP:PORT formar, slash the port out */ + if (!get_host_name((char *)peer, &ipaddr)) + ipaddr = peer; + + port = ntohs(sock_union.sin.sin_port); + + ret = mnt3_check_client_net_check(svc, volname, ipaddr, port); err: - return ret; + return ret; } static int -mnt3_check_client_net_udp (struct svc_req *req, char *volname, xlator_t *nfsx) +mnt3_check_client_net_udp(struct svc_req *req, char *volname, xlator_t *nfsx) { - rpcsvc_t *svc = NULL; - struct sockaddr_in *sin = NULL; - char ipaddr[INET_ADDRSTRLEN + 1] = {0, }; - uint16_t port = 0; - int ret = RPCSVC_AUTH_REJECT; - struct nfs_state *nfs = NULL; - - if ((!req) || (!volname) || (!nfsx)) - goto err; + rpcsvc_t *svc = NULL; + struct sockaddr_in *sin = NULL; + char ipaddr[INET_ADDRSTRLEN + 1] = { + 0, + }; + uint16_t port = 0; + int ret = RPCSVC_AUTH_REJECT; + struct nfs_state *nfs = NULL; + + if ((!req) || (!volname) || (!nfsx)) + goto err; #if !defined(_TIRPC_SVC_H) - sin = svc_getcaller (req->rq_xprt); + sin = svc_getcaller(req->rq_xprt); #else - sin = (struct sockaddr_in *)svc_getcaller (req->rq_xprt); - /* TIRPC's svc_getcaller() returns a pointer to a sockaddr_in6, even - * though it might actually be an IPv4 address. It ought return a - * struct sockaddr and make the caller upcast it to the proper - * address family. Sigh. - */ + sin = (struct sockaddr_in *)svc_getcaller(req->rq_xprt); + /* TIRPC's svc_getcaller() returns a pointer to a sockaddr_in6, even + * though it might actually be an IPv4 address. It ought return a + * struct sockaddr and make the caller upcast it to the proper + * address family. Sigh. + */ #endif - if (!sin) - goto err; - /* And let's make sure that it's actually an IPv4 address. */ + if (!sin) + goto err; + /* And let's make sure that it's actually an IPv4 address. */ - GF_ASSERT (sin->sin_family == AF_INET); + GF_ASSERT(sin->sin_family == AF_INET); - (void) inet_ntop (AF_INET, &sin->sin_addr, ipaddr, INET_ADDRSTRLEN); + (void)inet_ntop(AF_INET, &sin->sin_addr, ipaddr, INET_ADDRSTRLEN); - port = ntohs (sin->sin_port); + port = ntohs(sin->sin_port); - nfs = (struct nfs_state *)nfsx->private; - if (nfs != NULL) - svc = nfs->rpcsvc; + nfs = (struct nfs_state *)nfsx->private; + if (nfs != NULL) + svc = nfs->rpcsvc; - ret = mnt3_check_client_net_check (svc, volname, ipaddr, port); + ret = mnt3_check_client_net_check(svc, volname, ipaddr, port); err: - return ret; + return ret; } - int -mnt3_parse_dir_exports (rpcsvc_request_t *req, struct mount3_state *ms, - char *path, gf_boolean_t send_reply) +mnt3_parse_dir_exports(rpcsvc_request_t *req, struct mount3_state *ms, + char *path, gf_boolean_t send_reply) { - char volname[1024] = {0, }; - struct mnt3_export *exp = NULL; - char *volname_ptr = NULL; - char *subdir = NULL; - int ret = -ENOENT; - struct nfs_state *nfs = NULL; - - if ((!ms) || (!path)) - return -1; - - volname_ptr = volname; - subdir = mnt3_get_volume_subdir (path, &volname_ptr); + char volname[1024] = { + 0, + }; + struct mnt3_export *exp = NULL; + char *volname_ptr = NULL; + char *subdir = NULL; + int ret = -ENOENT; + struct nfs_state *nfs = NULL; + + if ((!ms) || (!path)) + return -1; - /* first try to match the full export/subdir */ - exp = mnt3_mntpath_to_export (ms, path, _gf_false); + volname_ptr = volname; + subdir = mnt3_get_volume_subdir(path, &volname_ptr); + + /* first try to match the full export/subdir */ + exp = mnt3_mntpath_to_export(ms, path, _gf_false); + if (!exp) { + gf_msg_trace(GF_MNT, 0, + "Could not find exact matching export " + "for path=%s", + path); + /* if no exact match is found, look for a fallback */ + exp = mnt3_mntpath_to_export(ms, volname, _gf_true); if (!exp) { - gf_msg_trace (GF_MNT, 0, "Could not find exact matching export " - "for path=%s", path); - /* if no exact match is found, look for a fallback */ - exp = mnt3_mntpath_to_export (ms, volname, _gf_true); - if (!exp) { - gf_msg_trace (GF_MNT, 0, "Could not find export for " - "volume %s", volname); - goto err; - } - } - gf_msg_trace (GF_MNT, 0, "volume %s and export %s will be used for " - "path %s", exp->vol->name, exp->expname, path); - - nfs = (struct nfs_state *)ms->nfsx->private; - if (!nfs) - goto err; - - if (!nfs_subvolume_started (nfs, exp->vol)) { - gf_msg_debug (GF_MNT, 0, "Volume %s not started", - exp->vol->name); - goto err; - } - - ret = mnt3_check_client_net_tcp (req, exp->vol->name); - if (ret == RPCSVC_AUTH_REJECT) { - gf_msg_debug (GF_MNT, 0, "Client mount not allowed"); - ret = -EACCES; - goto err; - } - - ret = mnt3_resolve_subdir (req, ms, exp, subdir, send_reply); - if (ret < 0) { - gf_msg (GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_RESOLVE_SUBDIR_FAIL, - "Failed to resolve export dir: %s", subdir); - goto err; - } + gf_msg_trace(GF_MNT, 0, + "Could not find export for " + "volume %s", + volname); + goto err; + } + } + gf_msg_trace(GF_MNT, 0, + "volume %s and export %s will be used for " + "path %s", + exp->vol->name, exp->expname, path); + + nfs = (struct nfs_state *)ms->nfsx->private; + if (!nfs) + goto err; + + if (!nfs_subvolume_started(nfs, exp->vol)) { + gf_msg_debug(GF_MNT, 0, "Volume %s not started", exp->vol->name); + goto err; + } + + ret = mnt3_check_client_net_tcp(req, exp->vol->name); + if (ret == RPCSVC_AUTH_REJECT) { + gf_msg_debug(GF_MNT, 0, "Client mount not allowed"); + ret = -EACCES; + goto err; + } + + ret = mnt3_resolve_subdir(req, ms, exp, subdir, send_reply); + if (ret < 0) { + gf_msg(GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_RESOLVE_SUBDIR_FAIL, + "Failed to resolve export dir: %s", subdir); + goto err; + } err: - return ret; + return ret; } - int -mnt3_find_export (rpcsvc_request_t *req, char *path, struct mnt3_export **e) +mnt3_find_export(rpcsvc_request_t *req, char *path, struct mnt3_export **e) { - int ret = -EFAULT; - struct mount3_state *ms = NULL; - struct mnt3_export *exp = NULL; - - if ((!req) || (!path) || (!e)) - return -1; - - ms = (struct mount3_state *) rpcsvc_request_program_private (req); - if (!ms) { - gf_msg (GF_MNT, GF_LOG_ERROR, EINVAL, - NFS_MSG_MNT_STATE_NOT_FOUND, "Mount state not present"); - rpcsvc_request_seterr (req, SYSTEM_ERR); - goto err; - } + int ret = -EFAULT; + struct mount3_state *ms = NULL; + struct mnt3_export *exp = NULL; - gf_msg_debug (GF_MNT, 0, "dirpath: %s", path); - exp = mnt3_mntpath_to_export (ms, path, _gf_false); - if (exp) { - ret = 0; - *e = exp; - goto err; - } + if ((!req) || (!path) || (!e)) + return -1; - if (!gf_mnt3_export_dirs(ms)) { - ret = -1; - goto err; - } + ms = (struct mount3_state *)rpcsvc_request_program_private(req); + if (!ms) { + gf_msg(GF_MNT, GF_LOG_ERROR, EINVAL, NFS_MSG_MNT_STATE_NOT_FOUND, + "Mount state not present"); + rpcsvc_request_seterr(req, SYSTEM_ERR); + goto err; + } + + gf_msg_debug(GF_MNT, 0, "dirpath: %s", path); + exp = mnt3_mntpath_to_export(ms, path, _gf_false); + if (exp) { + ret = 0; + *e = exp; + goto err; + } - ret = mnt3_parse_dir_exports (req, ms, path, _gf_true); + if (!gf_mnt3_export_dirs(ms)) { + ret = -1; + goto err; + } + + ret = mnt3_parse_dir_exports(req, ms, path, _gf_true); err: - return ret; + return ret; } /** @@ -1892,25 +1897,29 @@ err: * failure: NULL */ char * -_mnt3_get_peer_addr (const rpcsvc_request_t *req) +_mnt3_get_peer_addr(const rpcsvc_request_t *req) { - rpc_transport_t *trans = NULL; - struct sockaddr_storage sastorage = {0, }; - char peer[RPCSVC_PEER_STRLEN] = {0, }; - char *peerdup = NULL; - int ret = 0; - - GF_VALIDATE_OR_GOTO (GF_NFS, req, out); - - trans = rpcsvc_request_transport (req); - ret = rpcsvc_transport_peeraddr (trans, peer, RPCSVC_PEER_STRLEN, - &sastorage, sizeof (sastorage)); - if (ret != 0) - goto out; - - peerdup = gf_strdup (peer); + rpc_transport_t *trans = NULL; + struct sockaddr_storage sastorage = { + 0, + }; + char peer[RPCSVC_PEER_STRLEN] = { + 0, + }; + char *peerdup = NULL; + int ret = 0; + + GF_VALIDATE_OR_GOTO(GF_NFS, req, out); + + trans = rpcsvc_request_transport(req); + ret = rpcsvc_transport_peeraddr(trans, peer, RPCSVC_PEER_STRLEN, &sastorage, + sizeof(sastorage)); + if (ret != 0) + goto out; + + peerdup = gf_strdup(peer); out: - return peerdup; + return peerdup; } /** @@ -1925,27 +1934,27 @@ out: * */ char * -_mnt3_get_host_from_peer (const char *peer_addr) +_mnt3_get_host_from_peer(const char *peer_addr) { - char *part = NULL; - size_t host_len = 0; - char *colon = NULL; - - colon = strrchr (peer_addr, ':'); - if (!colon) { - gf_msg (GF_MNT, GF_LOG_ERROR, 0, NFS_MSG_BAD_PEER, - "Bad peer %s", peer_addr); - goto out; - } - - host_len = colon - peer_addr; - if (host_len < RPCSVC_PEER_STRLEN) - part = gf_strndup (peer_addr, host_len); - else - gf_msg (GF_MNT, GF_LOG_ERROR, 0, NFS_MSG_PEER_TOO_LONG, - "Peer too long %s", peer_addr); + char *part = NULL; + size_t host_len = 0; + char *colon = NULL; + + colon = strrchr(peer_addr, ':'); + if (!colon) { + gf_msg(GF_MNT, GF_LOG_ERROR, 0, NFS_MSG_BAD_PEER, "Bad peer %s", + peer_addr); + goto out; + } + + host_len = colon - peer_addr; + if (host_len < RPCSVC_PEER_STRLEN) + part = gf_strndup(peer_addr, host_len); + else + gf_msg(GF_MNT, GF_LOG_ERROR, 0, NFS_MSG_PEER_TOO_LONG, + "Peer too long %s", peer_addr); out: - return part; + return part; } /** @@ -1956,13 +1965,13 @@ out: * */ int -mnt3_check_cached_fh (struct mount3_state *ms, struct nfs3_fh *fh, - const char *host_addr, gf_boolean_t is_write_op) +mnt3_check_cached_fh(struct mount3_state *ms, struct nfs3_fh *fh, + const char *host_addr, gf_boolean_t is_write_op) { - if (!is_write_op) - return is_nfs_fh_cached (ms->authcache, fh, host_addr); + if (!is_write_op) + return is_nfs_fh_cached(ms->authcache, fh, host_addr); - return is_nfs_fh_cached_and_writeable (ms->authcache, fh, host_addr); + return is_nfs_fh_cached_and_writeable(ms->authcache, fh, host_addr); } /** @@ -1984,109 +1993,103 @@ mnt3_check_cached_fh (struct mount3_state *ms, struct nfs3_fh *fh, * -EROFS for unauthorized write operations (rm, mkdir, write) */ 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, - gf_boolean_t is_write_op) +_mnt3_authenticate_req(struct mount3_state *ms, rpcsvc_request_t *req, + struct nfs3_fh *fh, const char *path, + char **authorized_export, char **authorized_host, + gf_boolean_t is_write_op) { - char *peer_addr = NULL; - char *host_addr_ip = NULL; - char *host_addr_fqdn = NULL; - int auth_status_code = -EACCES; - char *pathdup = NULL; - size_t dlen = 0; - char *auth_host = NULL; - gf_boolean_t fh_cached = _gf_false; - struct export_item *expitem = NULL; - - GF_VALIDATE_OR_GOTO (GF_MNT, ms, out); - GF_VALIDATE_OR_GOTO (GF_MNT, req, out); - - peer_addr = _mnt3_get_peer_addr (req); - - if (!peer_addr) - goto free_and_out; - - host_addr_ip = _mnt3_get_host_from_peer (peer_addr); - - if (!host_addr_ip) - goto free_and_out; - - if (path) { - /* Need to strip out trailing '/' */ - pathdup = strdupa (path); - dlen = strlen (pathdup); - if (dlen > 0 && pathdup[dlen-1] == '/') - pathdup[dlen-1] = '\0'; - } - - /* Check if the filehandle is cached */ - fh_cached = mnt3_check_cached_fh (ms, fh, host_addr_ip, is_write_op); - if (fh_cached) { - gf_msg_trace (GF_MNT, 0, "Found cached FH for %s", - host_addr_ip); - auth_status_code = 0; - goto free_and_out; - } - - /* Check if the IP is authorized */ - auth_status_code = mnt3_auth_host (ms->auth_params, host_addr_ip, - fh, pathdup, is_write_op, &expitem); - - gf_msg_debug (GF_MNT, 0, "access from IP %s is %s", host_addr_ip, - auth_status_code ? "denied" : "allowed"); - - if (auth_status_code != 0) { - /* If not, check if the FQDN is authorized */ - host_addr_fqdn = gf_rev_dns_lookup (host_addr_ip); - auth_status_code = mnt3_auth_host (ms->auth_params, - host_addr_fqdn, - fh, pathdup, is_write_op, - &expitem); - - gf_msg_debug (GF_MNT, 0, "access from FQDN %s is %s", - host_addr_fqdn, auth_status_code ? "denied" : - "allowed"); - - if (auth_status_code == 0) - auth_host = host_addr_fqdn; - } else - auth_host = host_addr_ip; - - /* Skip the lines that set authorized export & - * host if they are null. - */ - if (!authorized_export || !authorized_host) { - /* Cache the file handle if it was authorized */ - if (fh && auth_status_code == 0) - cache_nfs_fh (ms->authcache, fh, host_addr_ip, expitem); - - goto free_and_out; - } - - if (!fh && auth_status_code == 0) { - *authorized_export = gf_strdup (pathdup); - if (!*authorized_export) - gf_msg (GF_MNT, GF_LOG_CRITICAL, ENOMEM, - NFS_MSG_NO_MEMORY, - "Allocation error when copying " - "authorized path"); - - *authorized_host = gf_strdup (auth_host); - if (!*authorized_host) - gf_msg (GF_MNT, GF_LOG_CRITICAL, ENOMEM, - NFS_MSG_NO_MEMORY, - "Allocation error when copying " - "authorized host"); - } + char *peer_addr = NULL; + char *host_addr_ip = NULL; + char *host_addr_fqdn = NULL; + int auth_status_code = -EACCES; + char *pathdup = NULL; + size_t dlen = 0; + char *auth_host = NULL; + gf_boolean_t fh_cached = _gf_false; + struct export_item *expitem = NULL; + + GF_VALIDATE_OR_GOTO(GF_MNT, ms, out); + GF_VALIDATE_OR_GOTO(GF_MNT, req, out); + + peer_addr = _mnt3_get_peer_addr(req); + + if (!peer_addr) + goto free_and_out; + + host_addr_ip = _mnt3_get_host_from_peer(peer_addr); + + if (!host_addr_ip) + goto free_and_out; + + if (path) { + /* Need to strip out trailing '/' */ + pathdup = strdupa(path); + dlen = strlen(pathdup); + if (dlen > 0 && pathdup[dlen - 1] == '/') + pathdup[dlen - 1] = '\0'; + } + + /* Check if the filehandle is cached */ + fh_cached = mnt3_check_cached_fh(ms, fh, host_addr_ip, is_write_op); + if (fh_cached) { + gf_msg_trace(GF_MNT, 0, "Found cached FH for %s", host_addr_ip); + auth_status_code = 0; + goto free_and_out; + } + + /* Check if the IP is authorized */ + auth_status_code = mnt3_auth_host(ms->auth_params, host_addr_ip, fh, + pathdup, is_write_op, &expitem); + + gf_msg_debug(GF_MNT, 0, "access from IP %s is %s", host_addr_ip, + auth_status_code ? "denied" : "allowed"); + + if (auth_status_code != 0) { + /* If not, check if the FQDN is authorized */ + host_addr_fqdn = gf_rev_dns_lookup(host_addr_ip); + auth_status_code = mnt3_auth_host(ms->auth_params, host_addr_fqdn, fh, + pathdup, is_write_op, &expitem); + + gf_msg_debug(GF_MNT, 0, "access from FQDN %s is %s", host_addr_fqdn, + auth_status_code ? "denied" : "allowed"); + + if (auth_status_code == 0) + auth_host = host_addr_fqdn; + } else + auth_host = host_addr_ip; + + /* Skip the lines that set authorized export & + * host if they are null. + */ + if (!authorized_export || !authorized_host) { + /* Cache the file handle if it was authorized */ + if (fh && auth_status_code == 0) + cache_nfs_fh(ms->authcache, fh, host_addr_ip, expitem); + + goto free_and_out; + } + + if (!fh && auth_status_code == 0) { + *authorized_export = gf_strdup(pathdup); + if (!*authorized_export) + gf_msg(GF_MNT, GF_LOG_CRITICAL, ENOMEM, NFS_MSG_NO_MEMORY, + "Allocation error when copying " + "authorized path"); + + *authorized_host = gf_strdup(auth_host); + if (!*authorized_host) + gf_msg(GF_MNT, GF_LOG_CRITICAL, ENOMEM, NFS_MSG_NO_MEMORY, + "Allocation error when copying " + "authorized host"); + } free_and_out: - /* Free allocated strings after doing the auth */ - GF_FREE (peer_addr); - GF_FREE (host_addr_fqdn); - GF_FREE (host_addr_ip); + /* Free allocated strings after doing the auth */ + GF_FREE(peer_addr); + GF_FREE(host_addr_fqdn); + GF_FREE(host_addr_ip); out: - return auth_status_code; + return auth_status_code; } /** @@ -2114,827 +2117,810 @@ out: * -EROFS for unauthorized write operations (rm, mkdir, write) */ 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, gf_boolean_t is_write_op) +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, gf_boolean_t is_write_op) { - int auth_status_code = -EACCES; - char *parent_path = NULL; - const char *parent_old = NULL; - - GF_VALIDATE_OR_GOTO (GF_MNT, ms, out); - GF_VALIDATE_OR_GOTO (GF_MNT, req, out); - - /* If this option is not set, just allow it through */ - if (!ms->nfs->exports_auth) { - /* This function is called in a variety of use-cases (mount - * + each fop) so path/authorized_path are not always present. - * For the cases which it _is_ present we need to populate the - * authorized_path. */ - if (path && authorized_path) - *authorized_path = gf_strdup (path); - - auth_status_code = 0; - goto out; - } - - /* First check if the path is allowed */ - auth_status_code = _mnt3_authenticate_req (ms, req, fh, path, - authorized_path, - authorized_host, - is_write_op); - - /* If the filehandle is set, just exit since we have to make only - * one call to the function above - */ - if (fh) - goto out; - - parent_old = path; - while (auth_status_code != 0) { - /* Get the path's parent */ - parent_path = gf_resolve_path_parent (parent_old); - if (!parent_path) /* Nothing left in the path to resolve */ - goto out; - - /* Authenticate it */ - auth_status_code = _mnt3_authenticate_req (ms, req, fh, - parent_path, - authorized_path, - authorized_host, - is_write_op); - - parent_old = strdupa (parent_path); /* Copy the parent onto the - * stack. - */ - - GF_FREE (parent_path); /* Free the allocated parent string */ - } + int auth_status_code = -EACCES; + char *parent_path = NULL; + const char *parent_old = NULL; + + GF_VALIDATE_OR_GOTO(GF_MNT, ms, out); + GF_VALIDATE_OR_GOTO(GF_MNT, req, out); + + /* If this option is not set, just allow it through */ + if (!ms->nfs->exports_auth) { + /* This function is called in a variety of use-cases (mount + * + each fop) so path/authorized_path are not always present. + * For the cases which it _is_ present we need to populate the + * authorized_path. */ + if (path && authorized_path) + *authorized_path = gf_strdup(path); + + auth_status_code = 0; + goto out; + } + + /* First check if the path is allowed */ + auth_status_code = _mnt3_authenticate_req( + ms, req, fh, path, authorized_path, authorized_host, is_write_op); + + /* If the filehandle is set, just exit since we have to make only + * one call to the function above + */ + if (fh) + goto out; + + parent_old = path; + while (auth_status_code != 0) { + /* Get the path's parent */ + parent_path = gf_resolve_path_parent(parent_old); + if (!parent_path) /* Nothing left in the path to resolve */ + goto out; + + /* Authenticate it */ + auth_status_code = _mnt3_authenticate_req(ms, req, fh, parent_path, + authorized_path, + authorized_host, is_write_op); + + parent_old = strdupa(parent_path); /* Copy the parent onto the + * stack. + */ + + GF_FREE(parent_path); /* Free the allocated parent string */ + } out: - return auth_status_code; + return auth_status_code; } int -mnt3svc_mnt (rpcsvc_request_t *req) +mnt3svc_mnt(rpcsvc_request_t *req) { - struct iovec pvec = {0, }; - char path[MNTPATHLEN]; - int ret = -1; - struct mount3_state *ms = NULL; - mountstat3 mntstat = MNT3ERR_SERVERFAULT; - struct mnt3_export *exp = NULL; - struct nfs_state *nfs = NULL; - int authcode = 0; - - if (!req) - return -1; - - pvec.iov_base = path; - pvec.iov_len = MNTPATHLEN; - ret = xdr_to_mountpath (pvec, req->msg[0]); - if (ret == -1) { - gf_msg (GF_MNT, GF_LOG_ERROR, 0, NFS_MSG_ARGS_DECODE_ERROR, - "Failed to decode args"); - rpcsvc_request_seterr (req, GARBAGE_ARGS); - goto rpcerr; - } - - ms = (struct mount3_state *)rpcsvc_request_program_private (req); - if (!ms) { - gf_msg (GF_MNT, GF_LOG_ERROR, EINVAL, - NFS_MSG_MNT_STATE_NOT_FOUND, - "Mount state not present"); - rpcsvc_request_seterr (req, SYSTEM_ERR); - ret = -1; - goto rpcerr; - } - - nfs = (struct nfs_state *)ms->nfsx->private; - gf_msg_debug (GF_MNT, 0, "dirpath: %s", path); - ret = mnt3_find_export (req, path, &exp); - if (ret < 0) { - mntstat = mnt3svc_errno_to_mnterr (-ret); - goto mnterr; - } else if (!exp) { - /* - * SPECIAL CASE: exp is NULL if "path" is subdir in - * call to mnt3_find_export(). - * - * This is subdir mount, we are already DONE! - * nfs_subvolume_started() and mnt3_check_client_net_tcp() - * validation are done in mnt3_parse_dir_exports() - * which is invoked through mnt3_find_export(). - * - * TODO: All mount should happen thorugh mnt3svc_mount() - * It needs more clean up. - */ - return (0); - } - - if (!nfs_subvolume_started (nfs, exp->vol)) { - gf_msg_debug (GF_MNT, 0, "Volume %s not started", - exp->vol->name); - ret = -1; - mntstat = MNT3ERR_NOENT; - goto mnterr; - } - - ret = mnt3_check_client_net_tcp (req, exp->vol->name); - if (ret == RPCSVC_AUTH_REJECT) { - mntstat = MNT3ERR_ACCES; - gf_msg_debug (GF_MNT, 0, "Client mount not allowed"); - ret = -1; - goto mnterr; - } + struct iovec pvec = { + 0, + }; + char path[MNTPATHLEN]; + int ret = -1; + struct mount3_state *ms = NULL; + mountstat3 mntstat = MNT3ERR_SERVERFAULT; + struct mnt3_export *exp = NULL; + struct nfs_state *nfs = NULL; + int authcode = 0; + + if (!req) + return -1; - /* The second authentication check is the exports/netgroups - * check. + pvec.iov_base = path; + pvec.iov_len = MNTPATHLEN; + ret = xdr_to_mountpath(pvec, req->msg[0]); + if (ret == -1) { + gf_msg(GF_MNT, GF_LOG_ERROR, 0, NFS_MSG_ARGS_DECODE_ERROR, + "Failed to decode args"); + rpcsvc_request_seterr(req, GARBAGE_ARGS); + goto rpcerr; + } + + ms = (struct mount3_state *)rpcsvc_request_program_private(req); + if (!ms) { + gf_msg(GF_MNT, GF_LOG_ERROR, EINVAL, NFS_MSG_MNT_STATE_NOT_FOUND, + "Mount state not present"); + rpcsvc_request_seterr(req, SYSTEM_ERR); + ret = -1; + goto rpcerr; + } + + nfs = (struct nfs_state *)ms->nfsx->private; + gf_msg_debug(GF_MNT, 0, "dirpath: %s", path); + ret = mnt3_find_export(req, path, &exp); + if (ret < 0) { + mntstat = mnt3svc_errno_to_mnterr(-ret); + goto mnterr; + } else if (!exp) { + /* + * SPECIAL CASE: exp is NULL if "path" is subdir in + * call to mnt3_find_export(). + * + * This is subdir mount, we are already DONE! + * nfs_subvolume_started() and mnt3_check_client_net_tcp() + * validation are done in mnt3_parse_dir_exports() + * which is invoked through mnt3_find_export(). + * + * TODO: All mount should happen thorugh mnt3svc_mount() + * It needs more clean up. */ - authcode = mnt3_authenticate_request (ms, req, NULL, NULL, path, NULL, - NULL, _gf_false); - if (authcode != 0) { - mntstat = MNT3ERR_ACCES; - gf_msg_debug (GF_MNT, 0, "Client mount not allowed"); - ret = -1; - goto mnterr; - } - - ret = mnt3svc_mount (req, ms, exp); - - if (ret < 0) - mntstat = mnt3svc_errno_to_mnterr (-ret); + return (0); + } + + if (!nfs_subvolume_started(nfs, exp->vol)) { + gf_msg_debug(GF_MNT, 0, "Volume %s not started", exp->vol->name); + ret = -1; + mntstat = MNT3ERR_NOENT; + goto mnterr; + } + + ret = mnt3_check_client_net_tcp(req, exp->vol->name); + if (ret == RPCSVC_AUTH_REJECT) { + mntstat = MNT3ERR_ACCES; + gf_msg_debug(GF_MNT, 0, "Client mount not allowed"); + ret = -1; + goto mnterr; + } + + /* The second authentication check is the exports/netgroups + * check. + */ + authcode = mnt3_authenticate_request(ms, req, NULL, NULL, path, NULL, NULL, + _gf_false); + if (authcode != 0) { + mntstat = MNT3ERR_ACCES; + gf_msg_debug(GF_MNT, 0, "Client mount not allowed"); + ret = -1; + goto mnterr; + } + + ret = mnt3svc_mount(req, ms, exp); + + if (ret < 0) + mntstat = mnt3svc_errno_to_mnterr(-ret); mnterr: - if (ret < 0) { - mnt3svc_mnt_error_reply (req, mntstat); - ret = 0; - } + if (ret < 0) { + mnt3svc_mnt_error_reply(req, mntstat); + ret = 0; + } rpcerr: - return ret; + return ret; } - int -mnt3svc_null (rpcsvc_request_t *req) +mnt3svc_null(rpcsvc_request_t *req) { - struct iovec dummyvec = {0, }; + struct iovec dummyvec = { + 0, + }; - if (!req) { - gf_msg (GF_MNT, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY, - "Got NULL request!"); - return 0; - } - rpcsvc_submit_generic (req, &dummyvec, 1, NULL, 0, NULL); + if (!req) { + gf_msg(GF_MNT, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY, + "Got NULL request!"); return 0; + } + rpcsvc_submit_generic(req, &dummyvec, 1, NULL, 0, NULL); + return 0; } - mountlist -__build_mountlist (struct mount3_state *ms, int *count) +__build_mountlist(struct mount3_state *ms, int *count) { - struct mountbody *mlist = NULL; - struct mountbody *prev = NULL; - struct mountbody *first = NULL; - size_t namelen = 0; - int ret = -1; - struct mountentry *me = NULL; - - if ((!ms) || (!count)) - return NULL; - - /* read rmtab, other peers might have updated it */ - mount_read_rmtab(ms); - - *count = 0; - gf_msg_debug (GF_MNT, 0, "Building mount list:"); - list_for_each_entry (me, &ms->mountlist, mlist) { - namelen = strlen (me->exname); - mlist = GF_CALLOC (1, sizeof (*mlist), gf_nfs_mt_mountbody); - if (!mlist) { - gf_msg (GF_MNT, GF_LOG_ERROR, ENOMEM, - NFS_MSG_NO_MEMORY, "Memory allocation failed"); - goto free_list; - } - if (!first) - first = mlist; - - mlist->ml_directory = GF_MALLOC (namelen + 2, - gf_nfs_mt_char); - if (!mlist->ml_directory) { - gf_msg (GF_MNT, GF_LOG_ERROR, ENOMEM, - NFS_MSG_NO_MEMORY, "Memory allocation failed"); - goto free_list; - } + struct mountbody *mlist = NULL; + struct mountbody *prev = NULL; + struct mountbody *first = NULL; + size_t namelen = 0; + int ret = -1; + struct mountentry *me = NULL; + + if ((!ms) || (!count)) + return NULL; - strcpy (mlist->ml_directory, me->exname); + /* read rmtab, other peers might have updated it */ + mount_read_rmtab(ms); - namelen = strlen (me->hostname); - mlist->ml_hostname = GF_MALLOC (namelen + 2, - gf_nfs_mt_char); - if (!mlist->ml_hostname) { - gf_msg (GF_MNT, GF_LOG_ERROR, ENOMEM, - NFS_MSG_NO_MEMORY, "Memory allocation failed"); - goto free_list; - } + *count = 0; + gf_msg_debug(GF_MNT, 0, "Building mount list:"); + list_for_each_entry(me, &ms->mountlist, mlist) + { + namelen = strlen(me->exname); + mlist = GF_CALLOC(1, sizeof(*mlist), gf_nfs_mt_mountbody); + if (!mlist) { + gf_msg(GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, + "Memory allocation failed"); + goto free_list; + } + if (!first) + first = mlist; - strcat (mlist->ml_hostname, me->hostname); + mlist->ml_directory = GF_MALLOC(namelen + 2, gf_nfs_mt_char); + if (!mlist->ml_directory) { + gf_msg(GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, + "Memory allocation failed"); + goto free_list; + } - gf_msg_debug (GF_MNT, 0, "mount entry: dir: %s, host: %s", - mlist->ml_directory, mlist->ml_hostname); - if (prev) { - prev->ml_next = mlist; - prev = mlist; - } else - prev = mlist; + strcpy(mlist->ml_directory, me->exname); - (*count)++; + namelen = strlen(me->hostname); + mlist->ml_hostname = GF_MALLOC(namelen + 2, gf_nfs_mt_char); + if (!mlist->ml_hostname) { + gf_msg(GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, + "Memory allocation failed"); + goto free_list; } - ret = 0; + strcat(mlist->ml_hostname, me->hostname); + + gf_msg_debug(GF_MNT, 0, "mount entry: dir: %s, host: %s", + mlist->ml_directory, mlist->ml_hostname); + if (prev) { + prev->ml_next = mlist; + prev = mlist; + } else + prev = mlist; + + (*count)++; + } + + ret = 0; free_list: - if (ret == -1) { - xdr_free_mountlist (first); - first = NULL; - } + if (ret == -1) { + xdr_free_mountlist(first); + first = NULL; + } - return first; + return first; } - mountlist -mnt3svc_build_mountlist (struct mount3_state *ms, int *count) +mnt3svc_build_mountlist(struct mount3_state *ms, int *count) { - struct mountbody *first = NULL; + struct mountbody *first = NULL; - LOCK (&ms->mountlock); - { - first = __build_mountlist (ms, count); - } - UNLOCK (&ms->mountlock); + LOCK(&ms->mountlock); + { + first = __build_mountlist(ms, count); + } + UNLOCK(&ms->mountlock); - return first; + return first; } - int -mnt3svc_dump (rpcsvc_request_t *req) +mnt3svc_dump(rpcsvc_request_t *req) { - int ret = -1; - struct mount3_state *ms = NULL; - mountlist mlist; - mountstat3 mstat = 0; - mnt3_serializer sfunc = NULL; - void *arg = NULL; - - - if (!req) - return -1; + int ret = -1; + struct mount3_state *ms = NULL; + mountlist mlist; + mountstat3 mstat = 0; + mnt3_serializer sfunc = NULL; + void *arg = NULL; + + if (!req) + return -1; - ms = (struct mount3_state *)rpcsvc_request_program_private (req); - if (!ms) { - rpcsvc_request_seterr (req, SYSTEM_ERR); - goto rpcerr; - } + ms = (struct mount3_state *)rpcsvc_request_program_private(req); + if (!ms) { + rpcsvc_request_seterr(req, SYSTEM_ERR); + goto rpcerr; + } - sfunc = (mnt3_serializer)xdr_serialize_mountlist; - mlist = mnt3svc_build_mountlist (ms, &ret); - arg = &mlist; + sfunc = (mnt3_serializer)xdr_serialize_mountlist; + mlist = mnt3svc_build_mountlist(ms, &ret); + arg = &mlist; - if (!mlist) { - if (ret != 0) { - rpcsvc_request_seterr (req, SYSTEM_ERR); - ret = -1; - goto rpcerr; - } else { - arg = &mstat; - sfunc = (mnt3_serializer)xdr_serialize_mountstat3; - } + if (!mlist) { + if (ret != 0) { + rpcsvc_request_seterr(req, SYSTEM_ERR); + ret = -1; + goto rpcerr; + } else { + arg = &mstat; + sfunc = (mnt3_serializer)xdr_serialize_mountstat3; } + } - mnt3svc_submit_reply (req, arg, sfunc); + mnt3svc_submit_reply(req, arg, sfunc); - xdr_free_mountlist (mlist); - ret = 0; + xdr_free_mountlist(mlist); + ret = 0; rpcerr: - return ret; + return ret; } - int -mnt3svc_umount (struct mount3_state *ms, char *dirpath, char *hostname) +mnt3svc_umount(struct mount3_state *ms, char *dirpath, char *hostname) { - struct mountentry *me = NULL; - int ret = -1; - gf_store_handle_t *sh = NULL; - struct nfs_state *nfs = NULL; - gf_boolean_t update_rmtab = _gf_false; - - if ((!ms) || (!dirpath) || (!hostname)) - return -1; - - nfs = (struct nfs_state *)ms->nfsx->private; - - update_rmtab = mount_open_rmtab (nfs->rmtab, &sh); - if (update_rmtab) { - ret = gf_store_lock (sh); - if (ret) - goto out_free; - } - - LOCK (&ms->mountlock); - { - if (update_rmtab) - __mount_read_rmtab (sh, &ms->mountlist, _gf_false); + struct mountentry *me = NULL; + int ret = -1; + gf_store_handle_t *sh = NULL; + struct nfs_state *nfs = NULL; + gf_boolean_t update_rmtab = _gf_false; - if (list_empty (&ms->mountlist)) { - ret = 0; - goto out_unlock; - } + if ((!ms) || (!dirpath) || (!hostname)) + return -1; - ret = -1; - list_for_each_entry (me, &ms->mountlist, mlist) { - if ((strcmp (me->exname, dirpath) == 0) && - (strcmp (me->hostname, hostname) == 0)) { - ret = 0; - break; - } - } + nfs = (struct nfs_state *)ms->nfsx->private; - /* Need this check here because at the end of the search me - * might still be pointing to the last entry, which may not be - * the one we're looking for. - */ - if (ret == -1) {/* Not found in list. */ - gf_msg_trace (GF_MNT, 0, "Export not found"); - goto out_unlock; - } + update_rmtab = mount_open_rmtab(nfs->rmtab, &sh); + if (update_rmtab) { + ret = gf_store_lock(sh); + if (ret) + goto out_free; + } - if (!me) - goto out_unlock; + LOCK(&ms->mountlock); + { + if (update_rmtab) + __mount_read_rmtab(sh, &ms->mountlist, _gf_false); - gf_msg_debug (GF_MNT, 0, "Unmounting: dir %s, host: %s", - me->exname, me->hostname); + if (list_empty(&ms->mountlist)) { + ret = 0; + goto out_unlock; + } - list_del (&me->mlist); - GF_FREE (me); + ret = -1; + list_for_each_entry(me, &ms->mountlist, mlist) + { + if ((strcmp(me->exname, dirpath) == 0) && + (strcmp(me->hostname, hostname) == 0)) { + ret = 0; + break; + } + } - if (update_rmtab) - __mount_rewrite_rmtab (ms, sh); + /* Need this check here because at the end of the search me + * might still be pointing to the last entry, which may not be + * the one we're looking for. + */ + if (ret == -1) { /* Not found in list. */ + gf_msg_trace(GF_MNT, 0, "Export not found"); + goto out_unlock; } -out_unlock: - UNLOCK (&ms->mountlock); + + if (!me) + goto out_unlock; + + gf_msg_debug(GF_MNT, 0, "Unmounting: dir %s, host: %s", me->exname, + me->hostname); + + list_del(&me->mlist); + GF_FREE(me); if (update_rmtab) - gf_store_unlock (sh); + __mount_rewrite_rmtab(ms, sh); + } +out_unlock: + UNLOCK(&ms->mountlock); + + if (update_rmtab) + gf_store_unlock(sh); out_free: - if (update_rmtab) - gf_store_handle_destroy (sh); + if (update_rmtab) + gf_store_handle_destroy(sh); - return ret; + return ret; } - int -mnt3svc_umnt (rpcsvc_request_t *req) +mnt3svc_umnt(rpcsvc_request_t *req) { - char hostname[MNTPATHLEN]; - char dirpath[MNTPATHLEN]; - struct iovec pvec = {0, }; - int ret = -1; - struct mount3_state *ms = NULL; - mountstat3 mstat = MNT3_OK; - char *colon = NULL; - - if (!req) - return -1; - - /* Remove the mount point from the exports list. */ - pvec.iov_base = dirpath; - pvec.iov_len = MNTPATHLEN; - ret = xdr_to_mountpath (pvec, req->msg[0]); - if (ret == -1) { - gf_msg (GF_MNT, GF_LOG_ERROR, 0, NFS_MSG_ARGS_DECODE_ERROR, - "Failed decode args"); - rpcsvc_request_seterr (req, GARBAGE_ARGS); - goto rpcerr; - } - - ms = (struct mount3_state *)rpcsvc_request_program_private (req); - if (!ms) { - gf_msg (GF_MNT, GF_LOG_ERROR, EINVAL, - NFS_MSG_MNT_STATE_NOT_FOUND, "Mount state not present"); - rpcsvc_request_seterr (req, SYSTEM_ERR); - ret = -1; - goto rpcerr; - } - - ret = rpcsvc_transport_peername (req->trans, hostname, MNTPATHLEN); - if (ret != 0) { - gf_msg (GF_MNT, GF_LOG_ERROR, ENOENT, - NFS_MSG_GET_REMOTE_NAME_FAIL, - "Failed to get remote name: %s", gai_strerror (ret)); - goto rpcerr; - } + char hostname[MNTPATHLEN]; + char dirpath[MNTPATHLEN]; + struct iovec pvec = { + 0, + }; + int ret = -1; + struct mount3_state *ms = NULL; + mountstat3 mstat = MNT3_OK; + char *colon = NULL; + + if (!req) + return -1; - colon = strrchr (hostname, ':'); - if (colon) { - *colon= '\0'; - } - gf_path_strip_trailing_slashes (dirpath); - gf_msg_debug (GF_MNT, 0, "dirpath: %s, hostname: %s", dirpath, - hostname); - ret = mnt3svc_umount (ms, dirpath, hostname); + /* Remove the mount point from the exports list. */ + pvec.iov_base = dirpath; + pvec.iov_len = MNTPATHLEN; + ret = xdr_to_mountpath(pvec, req->msg[0]); + if (ret == -1) { + gf_msg(GF_MNT, GF_LOG_ERROR, 0, NFS_MSG_ARGS_DECODE_ERROR, + "Failed decode args"); + rpcsvc_request_seterr(req, GARBAGE_ARGS); + goto rpcerr; + } + + ms = (struct mount3_state *)rpcsvc_request_program_private(req); + if (!ms) { + gf_msg(GF_MNT, GF_LOG_ERROR, EINVAL, NFS_MSG_MNT_STATE_NOT_FOUND, + "Mount state not present"); + rpcsvc_request_seterr(req, SYSTEM_ERR); + ret = -1; + goto rpcerr; + } + + ret = rpcsvc_transport_peername(req->trans, hostname, MNTPATHLEN); + if (ret != 0) { + gf_msg(GF_MNT, GF_LOG_ERROR, ENOENT, NFS_MSG_GET_REMOTE_NAME_FAIL, + "Failed to get remote name: %s", gai_strerror(ret)); + goto rpcerr; + } + + colon = strrchr(hostname, ':'); + if (colon) { + *colon = '\0'; + } + gf_path_strip_trailing_slashes(dirpath); + gf_msg_debug(GF_MNT, 0, "dirpath: %s, hostname: %s", dirpath, hostname); + ret = mnt3svc_umount(ms, dirpath, hostname); - if (ret == -1) { - ret = 0; - mstat = MNT3ERR_NOENT; - } - /* FIXME: also take care of the corner case where the - * client was resolvable at mount but not at the umount - vice-versa. - */ - mnt3svc_submit_reply (req, &mstat, - (mnt3_serializer)xdr_serialize_mountstat3); + if (ret == -1) { + ret = 0; + mstat = MNT3ERR_NOENT; + } + /* FIXME: also take care of the corner case where the + * client was resolvable at mount but not at the umount - vice-versa. + */ + mnt3svc_submit_reply(req, &mstat, + (mnt3_serializer)xdr_serialize_mountstat3); rpcerr: - return ret; + return ret; } - int -__mnt3svc_umountall (struct mount3_state *ms) +__mnt3svc_umountall(struct mount3_state *ms) { - struct mountentry *me = NULL; - struct mountentry *tmp = NULL; + struct mountentry *me = NULL; + struct mountentry *tmp = NULL; - if (!ms) - return -1; + if (!ms) + return -1; - if (list_empty (&ms->mountlist)) - return 0; + if (list_empty(&ms->mountlist)) + return 0; - list_for_each_entry_safe (me, tmp, &ms->mountlist, mlist) { - list_del (&me->mlist); /* Remove from the mount list */ - __mountdict_remove (ms, me); /* Remove from the mount dict */ - GF_FREE (me); - } + list_for_each_entry_safe(me, tmp, &ms->mountlist, mlist) + { + list_del(&me->mlist); /* Remove from the mount list */ + __mountdict_remove(ms, me); /* Remove from the mount dict */ + GF_FREE(me); + } - return 0; + return 0; } - int -mnt3svc_umountall (struct mount3_state *ms) +mnt3svc_umountall(struct mount3_state *ms) { - int ret = -1; - if (!ms) - return -1; + int ret = -1; + if (!ms) + return -1; - LOCK (&ms->mountlock); - { - ret = __mnt3svc_umountall (ms); - } - UNLOCK (&ms->mountlock); + LOCK(&ms->mountlock); + { + ret = __mnt3svc_umountall(ms); + } + UNLOCK(&ms->mountlock); - return ret; + return ret; } - int -mnt3svc_umntall (rpcsvc_request_t *req) +mnt3svc_umntall(rpcsvc_request_t *req) { - int ret = RPCSVC_ACTOR_ERROR; - struct mount3_state *ms = NULL; - mountstat3 mstat = MNT3_OK; - - if (!req) - return ret; - - ms = (struct mount3_state *)rpcsvc_request_program_private (req); - if (!ms) { - gf_msg (GF_MNT, GF_LOG_ERROR, EINVAL, - NFS_MSG_MNT_STATE_NOT_FOUND, "Mount state not present"); - rpcsvc_request_seterr (req, SYSTEM_ERR); - goto rpcerr; - } + int ret = RPCSVC_ACTOR_ERROR; + struct mount3_state *ms = NULL; + mountstat3 mstat = MNT3_OK; + + if (!req) + return ret; + + ms = (struct mount3_state *)rpcsvc_request_program_private(req); + if (!ms) { + gf_msg(GF_MNT, GF_LOG_ERROR, EINVAL, NFS_MSG_MNT_STATE_NOT_FOUND, + "Mount state not present"); + rpcsvc_request_seterr(req, SYSTEM_ERR); + goto rpcerr; + } - mnt3svc_umountall (ms); - mnt3svc_submit_reply (req, &mstat, - (mnt3_serializer)xdr_serialize_mountstat3); + mnt3svc_umountall(ms); + mnt3svc_submit_reply(req, &mstat, + (mnt3_serializer)xdr_serialize_mountstat3); - ret = RPCSVC_ACTOR_SUCCESS; + ret = RPCSVC_ACTOR_SUCCESS; rpcerr: - return ret; + return ret; } - exports -mnt3_xlchildren_to_exports (rpcsvc_t *svc, struct mount3_state *ms) +mnt3_xlchildren_to_exports(rpcsvc_t *svc, struct mount3_state *ms) { - struct exportnode *elist = NULL; - struct exportnode *prev = NULL; - struct exportnode *first = NULL; - size_t namelen = 0; - int ret = -1; - char *addrstr = NULL; - struct mnt3_export *ent = NULL; - struct nfs_state *nfs = NULL; - - if ((!ms) || (!svc)) - return NULL; - - nfs = (struct nfs_state *)ms->nfsx->private; - if (!nfs) - return NULL; - - LOCK (&ms->mountlock); - list_for_each_entry(ent, &ms->exportlist, explist) { - - /* If volume is not started yet, do not list it for tools like - * showmount. - */ - if (!nfs_subvolume_started (nfs, ent->vol)) - continue; - - elist = GF_CALLOC (1, sizeof (*elist), gf_nfs_mt_exportnode); - if (!elist) { - gf_msg (GF_MNT, GF_LOG_ERROR, ENOMEM, - NFS_MSG_NO_MEMORY, "Memory allocation failed"); - goto free_list; - } - if (!first) - first = elist; - namelen = strlen (ent->expname); - elist->ex_dir = GF_MALLOC (namelen + 2, - gf_nfs_mt_char); - if (!elist->ex_dir) { - gf_msg (GF_MNT, GF_LOG_ERROR, ENOMEM, - NFS_MSG_NO_MEMORY, "Memory allocation failed"); - goto free_list; + struct exportnode *elist = NULL; + struct exportnode *prev = NULL; + struct exportnode *first = NULL; + size_t namelen = 0; + int ret = -1; + char *addrstr = NULL; + struct mnt3_export *ent = NULL; + struct nfs_state *nfs = NULL; + + if ((!ms) || (!svc)) + return NULL; + + nfs = (struct nfs_state *)ms->nfsx->private; + if (!nfs) + return NULL; + + LOCK(&ms->mountlock); + list_for_each_entry(ent, &ms->exportlist, explist) + { + /* If volume is not started yet, do not list it for tools like + * showmount. + */ + if (!nfs_subvolume_started(nfs, ent->vol)) + continue; + + elist = GF_CALLOC(1, sizeof(*elist), gf_nfs_mt_exportnode); + if (!elist) { + gf_msg(GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, + "Memory allocation failed"); + goto free_list; + } + if (!first) + first = elist; + namelen = strlen(ent->expname); + elist->ex_dir = GF_MALLOC(namelen + 2, gf_nfs_mt_char); + if (!elist->ex_dir) { + gf_msg(GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, + "Memory allocation failed"); + goto free_list; + } + strcpy(elist->ex_dir, ent->expname); + + addrstr = rpcsvc_volume_allowed(svc->options, ent->vol->name); + if (addrstr) { + /* create a groupnode per allowed client */ + char *pos = NULL; + char *addr = NULL; + char *addrs = NULL; + struct groupnode *group = NULL; + struct groupnode *prev_group = NULL; + + /* strtok_r() modifies the string, dup it */ + addrs = gf_strdup(addrstr); + if (!addrs) + goto free_list; + + while (1) { + /* only pass addrs on the 1st call */ + addr = strtok_r(group ? NULL : addrs, ",", &pos); + if (addr == NULL) + /* no mode clients */ + break; + + group = GF_CALLOC(1, sizeof(struct groupnode), + gf_nfs_mt_groupnode); + if (!group) { + gf_msg(GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, + "Memory " + "allocation failed"); + GF_FREE(addrs); + goto free_list; } - strcpy (elist->ex_dir, ent->expname); - - addrstr = rpcsvc_volume_allowed (svc->options, ent->vol->name); - if (addrstr) { - /* create a groupnode per allowed client */ - char *pos = NULL; - char *addr = NULL; - char *addrs = NULL; - struct groupnode *group = NULL; - struct groupnode *prev_group = NULL; - - /* strtok_r() modifies the string, dup it */ - addrs = gf_strdup (addrstr); - if (!addrs) - goto free_list; - - while (1) { - /* only pass addrs on the 1st call */ - addr = strtok_r (group ? NULL : addrs, ",", - &pos); - if (addr == NULL) - /* no mode clients */ - break; - - group = GF_CALLOC (1, sizeof (struct groupnode), - gf_nfs_mt_groupnode); - if (!group) { - gf_msg (GF_MNT, GF_LOG_ERROR, ENOMEM, - NFS_MSG_NO_MEMORY, "Memory " - "allocation failed"); - GF_FREE (addrs); - goto free_list; - } - - group->gr_name = gf_strdup (addr); - if (!group->gr_name) { - gf_msg (GF_MNT, GF_LOG_ERROR, ENOMEM, - NFS_MSG_NO_MEMORY, "Memory " - "allocation failed"); - GF_FREE (group); - GF_FREE (addrs); - goto free_list; - } - - /* chain the groups together */ - if (!elist->ex_groups) - elist->ex_groups = group; - else if (!prev_group->gr_next) - prev_group->gr_next = group; - prev_group = group; - } - - GF_FREE (addrs); - } else { - elist->ex_groups = GF_CALLOC (1, - sizeof (struct groupnode), - gf_nfs_mt_groupnode); - if (!elist->ex_groups) { - gf_msg (GF_MNT, GF_LOG_ERROR, ENOMEM, - NFS_MSG_NO_MEMORY, "Memory allocation " - "failed"); - goto free_list; - } - - addrstr = gf_strdup ("No Access"); - if (!addrstr) - goto free_list; - - elist->ex_groups->gr_name = addrstr; + + group->gr_name = gf_strdup(addr); + if (!group->gr_name) { + gf_msg(GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, + "Memory " + "allocation failed"); + GF_FREE(group); + GF_FREE(addrs); + goto free_list; } - if (prev) { - prev->ex_next = elist; - prev = elist; - } else - prev = elist; + /* chain the groups together */ + if (!elist->ex_groups) + elist->ex_groups = group; + else if (!prev_group->gr_next) + prev_group->gr_next = group; + prev_group = group; + } + + GF_FREE(addrs); + } else { + elist->ex_groups = GF_CALLOC(1, sizeof(struct groupnode), + gf_nfs_mt_groupnode); + if (!elist->ex_groups) { + gf_msg(GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, + "Memory allocation " + "failed"); + goto free_list; + } + + addrstr = gf_strdup("No Access"); + if (!addrstr) + goto free_list; + + elist->ex_groups->gr_name = addrstr; } - ret = 0; + if (prev) { + prev->ex_next = elist; + prev = elist; + } else + prev = elist; + } + + ret = 0; free_list: - UNLOCK (&ms->mountlock); - if (ret == -1) { - xdr_free_exports_list (first); - first = NULL; - } + UNLOCK(&ms->mountlock); + if (ret == -1) { + xdr_free_exports_list(first); + first = NULL; + } - return first; + return first; } - int -mnt3svc_export (rpcsvc_request_t *req) +mnt3svc_export(rpcsvc_request_t *req) { - struct mount3_state *ms = NULL; - exports elist = NULL; - int ret = -1; - - if (!req) - return -1; - - ms = (struct mount3_state *)rpcsvc_request_program_private (req); - if (!ms) { - gf_msg (GF_MNT, GF_LOG_ERROR, EINVAL, - NFS_MSG_MNT_STATE_NOT_FOUND, "mount state not found"); - rpcsvc_request_seterr (req, SYSTEM_ERR); - goto err; - } + struct mount3_state *ms = NULL; + exports elist = NULL; + int ret = -1; - /* Using the children translator names, build the export list */ - elist = mnt3_xlchildren_to_exports (rpcsvc_request_service (req), - ms); - /* Do not return error when exports list is empty. An exports list can - * be empty when no subvolumes have come up. No point returning error - * and confusing the user. - if (!elist) { - gf_log (GF_MNT, GF_LOG_ERROR, "Failed to build exports list"); - nfs_rpcsvc_request_seterr (req, SYSTEM_ERR); - goto err; - } - */ - - /* Note how the serializer is passed to the generic reply function. */ - mnt3svc_submit_reply (req, &elist, - (mnt3_serializer)xdr_serialize_exports); + if (!req) + return -1; - xdr_free_exports_list (elist); - ret = 0; + ms = (struct mount3_state *)rpcsvc_request_program_private(req); + if (!ms) { + gf_msg(GF_MNT, GF_LOG_ERROR, EINVAL, NFS_MSG_MNT_STATE_NOT_FOUND, + "mount state not found"); + rpcsvc_request_seterr(req, SYSTEM_ERR); + goto err; + } + + /* Using the children translator names, build the export list */ + elist = mnt3_xlchildren_to_exports(rpcsvc_request_service(req), ms); + /* Do not return error when exports list is empty. An exports list can + * be empty when no subvolumes have come up. No point returning error + * and confusing the user. + if (!elist) { + gf_log (GF_MNT, GF_LOG_ERROR, "Failed to build exports list"); + nfs_rpcsvc_request_seterr (req, SYSTEM_ERR); + goto err; + } + */ + + /* Note how the serializer is passed to the generic reply function. */ + mnt3svc_submit_reply(req, &elist, (mnt3_serializer)xdr_serialize_exports); + + xdr_free_exports_list(elist); + ret = 0; err: - return ret; + return ret; } - /* * __mnt3udp_get_mstate() Fetches mount3_state from xlator * Linkage: Static * Usage: Used only for UDP MOUNT codepath */ static struct mount3_state * -__mnt3udp_get_mstate (xlator_t *nfsx) +__mnt3udp_get_mstate(xlator_t *nfsx) { - struct nfs_state *nfs = NULL; - struct mount3_state *ms = NULL; + struct nfs_state *nfs = NULL; + struct mount3_state *ms = NULL; - if (nfsx == NULL) - return NULL; + if (nfsx == NULL) + return NULL; - nfs = (struct nfs_state *)nfsx->private; - if (nfs == NULL) - return NULL; + nfs = (struct nfs_state *)nfsx->private; + if (nfs == NULL) + return NULL; - ms = (struct mount3_state *)nfs->mstate; - return ms; + ms = (struct mount3_state *)nfs->mstate; + return ms; } extern int -glfs_resolve_at (struct glfs *, xlator_t *, inode_t *, - const char *, loc_t *, struct iatt *, int, int); +glfs_resolve_at(struct glfs *, xlator_t *, inode_t *, const char *, loc_t *, + struct iatt *, int, int); extern struct glfs * -glfs_new_from_ctx (glusterfs_ctx_t *); +glfs_new_from_ctx(glusterfs_ctx_t *); extern void -glfs_free_from_ctx (struct glfs *); +glfs_free_from_ctx(struct glfs *); static inode_t * -__mnt3udp_get_export_subdir_inode (struct svc_req *req, char *subdir, - char *expname, /* OUT */ - struct mnt3_export *exp) +__mnt3udp_get_export_subdir_inode(struct svc_req *req, char *subdir, + char *expname, /* OUT */ + struct mnt3_export *exp) { - inode_t *inode = NULL; - loc_t loc = {0, }; - struct iatt buf = {0, }; - int ret = -1; - glfs_t *fs = NULL; - - if ((!req) || (!subdir) || (!expname) || (!exp)) - return NULL; + inode_t *inode = NULL; + loc_t loc = { + 0, + }; + struct iatt buf = { + 0, + }; + int ret = -1; + glfs_t *fs = NULL; + + if ((!req) || (!subdir) || (!expname) || (!exp)) + return NULL; - /* AUTH check for subdir i.e. nfs.export-dir */ - if (exp->hostspec) { - struct sockaddr_in *sin = NULL; + /* AUTH check for subdir i.e. nfs.export-dir */ + if (exp->hostspec) { + struct sockaddr_in *sin = NULL; #if !defined(_TIRPC_SVC_H) - sin = svc_getcaller (req->rq_xprt); + sin = svc_getcaller(req->rq_xprt); #else - sin = (struct sockaddr_in *)svc_getcaller (req->rq_xprt); - /* TIRPC's svc_getcaller() returns a pointer to a - * sockaddr_in6, even though it might actually be an - * IPv4 address. It ought return a struct sockaddr and - * make the caller upcast it to the proper address family. - */ + sin = (struct sockaddr_in *)svc_getcaller(req->rq_xprt); + /* TIRPC's svc_getcaller() returns a pointer to a + * sockaddr_in6, even though it might actually be an + * IPv4 address. It ought return a struct sockaddr and + * make the caller upcast it to the proper address family. + */ #endif - /* And let's make sure that it's actually an IPv4 address. */ - GF_ASSERT (sin->sin_family == AF_INET); - - ret = mnt3_verify_auth (sin, exp); - if (ret) { - gf_msg (GF_MNT, GF_LOG_ERROR, EACCES, - NFS_MSG_AUTH_VERIFY_FAILED, - "AUTH(nfs.export-dir) verification failed"); - errno = EACCES; - return NULL; - } - } + /* And let's make sure that it's actually an IPv4 address. */ + GF_ASSERT(sin->sin_family == AF_INET); - /* - * IMP: glfs_t fs object is not used by glfs_resolve_at (). The main - * purpose is to not change the ABI of glfs_resolve_at () and not to - * pass a NULL object. - * - * TODO: Instead of linking against libgfapi.so, just for one API - * i.e. glfs_resolve_at(), It would be cleaner if PATH name to - * inode resolution code can be moved to libglusterfs.so or so. - * refer bugzilla for more details : - * https://bugzilla.redhat.com/show_bug.cgi?id=1161573 - */ - fs = glfs_new_from_ctx (exp->vol->ctx); - if (!fs) - return NULL; + ret = mnt3_verify_auth(sin, exp); + if (ret) { + gf_msg(GF_MNT, GF_LOG_ERROR, EACCES, NFS_MSG_AUTH_VERIFY_FAILED, + "AUTH(nfs.export-dir) verification failed"); + errno = EACCES; + return NULL; + } + } + + /* + * IMP: glfs_t fs object is not used by glfs_resolve_at (). The main + * purpose is to not change the ABI of glfs_resolve_at () and not to + * pass a NULL object. + * + * TODO: Instead of linking against libgfapi.so, just for one API + * i.e. glfs_resolve_at(), It would be cleaner if PATH name to + * inode resolution code can be moved to libglusterfs.so or so. + * refer bugzilla for more details : + * https://bugzilla.redhat.com/show_bug.cgi?id=1161573 + */ + fs = glfs_new_from_ctx(exp->vol->ctx); + if (!fs) + return NULL; - ret = glfs_resolve_at (fs, exp->vol, NULL, subdir, - &loc, &buf, 1 /* Follow link */, - 0 /* Hard lookup */); + ret = glfs_resolve_at(fs, exp->vol, NULL, subdir, &loc, &buf, + 1 /* Follow link */, 0 /* Hard lookup */); - glfs_free_from_ctx (fs); + glfs_free_from_ctx(fs); - if (ret != 0) { - loc_wipe (&loc); - return NULL; - } + if (ret != 0) { + loc_wipe(&loc); + return NULL; + } - inode = inode_ref (loc.inode); - snprintf (expname, PATH_MAX, "/%s%s", exp->vol->name, loc.path); + inode = inode_ref(loc.inode); + snprintf(expname, PATH_MAX, "/%s%s", exp->vol->name, loc.path); - loc_wipe (&loc); + loc_wipe(&loc); - return inode; + return inode; } static inode_t * -__mnt3udp_get_export_volume_inode (struct svc_req *req, char *volpath, - char *expname, /* OUT */ - struct mnt3_export *exp) +__mnt3udp_get_export_volume_inode(struct svc_req *req, char *volpath, + char *expname, /* OUT */ + struct mnt3_export *exp) { - char *rpath = NULL; - inode_t *inode = NULL; + char *rpath = NULL; + inode_t *inode = NULL; - if ((!req) || (!volpath) || (!expname) || (!exp)) - return NULL; + if ((!req) || (!volpath) || (!expname) || (!exp)) + return NULL; - rpath = strchr (volpath, '/'); - if (rpath == NULL) - rpath = "/"; + rpath = strchr(volpath, '/'); + if (rpath == NULL) + rpath = "/"; - inode = inode_from_path (exp->vol->itable, rpath); - snprintf (expname, PATH_MAX, "/%s", exp->vol->name); + inode = inode_from_path(exp->vol->itable, rpath); + snprintf(expname, PATH_MAX, "/%s", exp->vol->name); - return inode; + return inode; } /* @@ -2943,162 +2929,161 @@ __mnt3udp_get_export_volume_inode (struct svc_req *req, char *volpath, * when nfs.mount-udp is ENABLED (set to TRUE/ON). */ struct nfs3_fh * -nfs3_rootfh (struct svc_req *req, xlator_t *nfsx, - char *path, char *expname /* OUT */) +nfs3_rootfh(struct svc_req *req, xlator_t *nfsx, char *path, + char *expname /* OUT */) { - struct nfs3_fh *fh = NULL; - inode_t *inode = NULL; - struct mnt3_export *exp = NULL; - struct mount3_state *ms = NULL; - struct nfs_state *nfs = NULL; - int mnt3type = MNT3_EXPTYPE_DIR; - int ret = RPCSVC_AUTH_REJECT; - - if ((!req) || (!nfsx) || (!path) || (!expname)) { - errno = EFAULT; - return NULL; - } - - /* - * 1. First check if the MOUNT is for whole volume. - * i.e. __mnt3udp_get_export_volume_inode () - * 2. If NOT, then TRY for SUBDIR MOUNT. - * i.e. __mnt3udp_get_export_subdir_inode () - * 3. If a subdir is exported using nfs.export-dir, - * then the mount type would be MNT3_EXPTYPE_DIR, - * so make sure to find the proper path to be - * resolved using mnt3_get_volume_subdir() - * 3. Make sure subdir export is allowed. - */ - ms = __mnt3udp_get_mstate(nfsx); - if (!ms) { - errno = EFAULT; - return NULL; - } - - exp = mnt3_mntpath_to_export (ms, path , _gf_false); - if (exp != NULL) - mnt3type = exp->exptype; + struct nfs3_fh *fh = NULL; + inode_t *inode = NULL; + struct mnt3_export *exp = NULL; + struct mount3_state *ms = NULL; + struct nfs_state *nfs = NULL; + int mnt3type = MNT3_EXPTYPE_DIR; + int ret = RPCSVC_AUTH_REJECT; + + if ((!req) || (!nfsx) || (!path) || (!expname)) { + errno = EFAULT; + return NULL; + } + + /* + * 1. First check if the MOUNT is for whole volume. + * i.e. __mnt3udp_get_export_volume_inode () + * 2. If NOT, then TRY for SUBDIR MOUNT. + * i.e. __mnt3udp_get_export_subdir_inode () + * 3. If a subdir is exported using nfs.export-dir, + * then the mount type would be MNT3_EXPTYPE_DIR, + * so make sure to find the proper path to be + * resolved using mnt3_get_volume_subdir() + * 3. Make sure subdir export is allowed. + */ + ms = __mnt3udp_get_mstate(nfsx); + if (!ms) { + errno = EFAULT; + return NULL; + } - if (mnt3type == MNT3_EXPTYPE_DIR) { - char volname [MNTPATHLEN] = {0, }; - char *volptr = volname; + exp = mnt3_mntpath_to_export(ms, path, _gf_false); + if (exp != NULL) + mnt3type = exp->exptype; - /* Subdir export (nfs3.export-dirs) check */ - if (!gf_mnt3_export_dirs(ms)) { - errno = EACCES; - return NULL; - } + if (mnt3type == MNT3_EXPTYPE_DIR) { + char volname[MNTPATHLEN] = { + 0, + }; + char *volptr = volname; - path = mnt3_get_volume_subdir (path, &volptr); - if (exp == NULL) - exp = mnt3_mntpath_to_export (ms, volname , _gf_false); + /* Subdir export (nfs3.export-dirs) check */ + if (!gf_mnt3_export_dirs(ms)) { + errno = EACCES; + return NULL; } - if (exp == NULL) { - errno = ENOENT; - return NULL; - } + path = mnt3_get_volume_subdir(path, &volptr); + if (exp == NULL) + exp = mnt3_mntpath_to_export(ms, volname, _gf_false); + } - nfs = (struct nfs_state *)nfsx->private; - if (!nfs_subvolume_started (nfs, exp->vol)) { - errno = ENOENT; - return NULL; - } + if (exp == NULL) { + errno = ENOENT; + return NULL; + } - /* AUTH check: respect nfs.rpc-auth-allow/reject */ - ret = mnt3_check_client_net_udp (req, exp->vol->name, nfsx); - if (ret == RPCSVC_AUTH_REJECT) { - errno = EACCES; - return NULL; - } + nfs = (struct nfs_state *)nfsx->private; + if (!nfs_subvolume_started(nfs, exp->vol)) { + errno = ENOENT; + return NULL; + } - switch (mnt3type) { + /* AUTH check: respect nfs.rpc-auth-allow/reject */ + ret = mnt3_check_client_net_udp(req, exp->vol->name, nfsx); + if (ret == RPCSVC_AUTH_REJECT) { + errno = EACCES; + return NULL; + } + switch (mnt3type) { case MNT3_EXPTYPE_VOLUME: - inode = __mnt3udp_get_export_volume_inode (req, path, - expname, exp); - break; + inode = __mnt3udp_get_export_volume_inode(req, path, expname, exp); + break; case MNT3_EXPTYPE_DIR: - inode = __mnt3udp_get_export_subdir_inode (req, path, - expname, exp); - break; + inode = __mnt3udp_get_export_subdir_inode(req, path, expname, exp); + break; default: - /* Never reachable */ - gf_msg (GF_MNT, GF_LOG_ERROR, EFAULT, NFS_MSG_UNKNOWN_MNT_TYPE, - "Unknown MOUNT3 type"); - errno = EFAULT; - goto err; - } - - if (inode == NULL) { - /* Don't over-write errno */ - if (!errno) - errno = ENOENT; - goto err; - } - - /* Build the inode from FH */ - fh = GF_CALLOC (1, sizeof(*fh), gf_nfs_mt_nfs3_fh); - if (fh == NULL) { - errno = ENOMEM; - goto err; - } - - (void) nfs3_build_fh (inode, exp->volumeid, fh); + /* Never reachable */ + gf_msg(GF_MNT, GF_LOG_ERROR, EFAULT, NFS_MSG_UNKNOWN_MNT_TYPE, + "Unknown MOUNT3 type"); + errno = EFAULT; + goto err; + } + + if (inode == NULL) { + /* Don't over-write errno */ + if (!errno) + errno = ENOENT; + goto err; + } + + /* Build the inode from FH */ + fh = GF_CALLOC(1, sizeof(*fh), gf_nfs_mt_nfs3_fh); + if (fh == NULL) { + errno = ENOMEM; + goto err; + } + + (void)nfs3_build_fh(inode, exp->volumeid, fh); err: - if (inode) - inode_unref (inode); + if (inode) + inode_unref(inode); - return fh; + return fh; } int -mount3udp_add_mountlist (xlator_t *nfsx, char *host, char *export) +mount3udp_add_mountlist(xlator_t *nfsx, char *host, char *export) { - struct mountentry *me = NULL; - struct mount3_state *ms = NULL; + struct mountentry *me = NULL; + struct mount3_state *ms = NULL; - if ((!host) || (!export) || (!nfsx)) - return -1; + if ((!host) || (!export) || (!nfsx)) + return -1; - ms = __mnt3udp_get_mstate (nfsx); - if (!ms) - return -1; + ms = __mnt3udp_get_mstate(nfsx); + if (!ms) + return -1; - me = GF_CALLOC (1, sizeof (*me), gf_nfs_mt_mountentry); - if (!me) - return -1; + me = GF_CALLOC(1, sizeof(*me), gf_nfs_mt_mountentry); + if (!me) + return -1; - snprintf (me->exname, MNTPATHLEN, "%s", export); - snprintf (me->hostname, MNTPATHLEN, "%s", host); - INIT_LIST_HEAD (&me->mlist); - LOCK (&ms->mountlock); - { - list_add_tail (&me->mlist, &ms->mountlist); - mount_rewrite_rmtab(ms, NULL); - } - UNLOCK (&ms->mountlock); - return 0; + snprintf(me->exname, MNTPATHLEN, "%s", export); + snprintf(me->hostname, MNTPATHLEN, "%s", host); + INIT_LIST_HEAD(&me->mlist); + LOCK(&ms->mountlock); + { + list_add_tail(&me->mlist, &ms->mountlist); + mount_rewrite_rmtab(ms, NULL); + } + UNLOCK(&ms->mountlock); + return 0; } int -mount3udp_delete_mountlist (xlator_t *nfsx, char *hostname, char *export) +mount3udp_delete_mountlist(xlator_t *nfsx, char *hostname, char *export) { - struct mount3_state *ms = NULL; + struct mount3_state *ms = NULL; - if ((!hostname) || (!export) || (!nfsx)) - return -1; + if ((!hostname) || (!export) || (!nfsx)) + return -1; - ms = __mnt3udp_get_mstate (nfsx); - if (!ms) - return -1; + ms = __mnt3udp_get_mstate(nfsx); + if (!ms) + return -1; - mnt3svc_umount (ms, export, hostname); - return 0; + mnt3svc_umount(ms, export, hostname); + return 0; } /** @@ -3113,90 +3098,88 @@ mount3udp_delete_mountlist (xlator_t *nfsx, char *hostname, char *export) * NB: This does not support IPv6 currently. */ int -mnt3_export_fill_hostspec (struct host_auth_spec* hostspec, const char* hostip) +mnt3_export_fill_hostspec(struct host_auth_spec *hostspec, const char *hostip) { - char *ipdupstr = NULL; - char *savptr = NULL; - char *endptr = NULL; - char *ip = NULL; - char *token = NULL; - int ret = -1; - long prefixlen = IPv4_ADDR_SIZE; /* default */ - uint32_t shiftbits = 0; - size_t length = 0; - - /* Create copy of the string so that the source won't change - */ - ipdupstr = gf_strdup (hostip); - if (NULL == ipdupstr) { - gf_msg (GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, - "Memory allocation failed"); - goto err; - } - - ip = strtok_r (ipdupstr, "/", &savptr); - /* Validate the Hostname or IPv4 address - * TODO: IPv6 support for subdir auth. - */ - length = strlen (ip); - if ((!valid_ipv4_address (ip, (int)length, _gf_false)) && - (!valid_host_name (ip, (int)length))) { - gf_msg (GF_MNT, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY, - "Invalid hostname or IPv4 address: %s", ip); - goto err; - } - - hostspec->host_addr = gf_strdup (ip); - if (NULL == hostspec->host_addr) { - gf_msg (GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, - "Memory allocation failed"); - goto err; - } - - /** - * User provided CIDR address (xx.xx.xx.xx/n format) is split - * into HOST (IP addr or hostname) and network prefix(n) from - * which netmask would be calculated. This CIDR address may - * denote a single, distinct interface address or the beginning - * address of an entire network. - * - * e.g. the IPv4 block 192.168.100.0/24 represents the 256 - * IPv4 addresses from 192.168.100.0 to 192.168.100.255. - * Therefore to check if an IP matches 192.168.100.0/24 - * we should mask the IP with FFFFFF00 and compare it with - * host address part of CIDR. - * - * Refer: mask_match() in common-utils.c. - */ - token = strtok_r (NULL, "/", &savptr); - if (token != NULL) { - prefixlen = strtol (token, &endptr, 10); - if ((errno != 0) || (*endptr != '\0') || - (prefixlen < 0) || (prefixlen > IPv4_ADDR_SIZE)) { - gf_msg (THIS->name, GF_LOG_WARNING, EINVAL, - NFS_MSG_INVALID_ENTRY, - "Invalid IPv4 subnetwork mask"); - goto err; - } - } - - /* - * 1. Calculate the network mask address. - * 2. Convert it into Big-Endian format. - * 3. Store it in hostspec netmask. - */ - shiftbits = IPv4_ADDR_SIZE - prefixlen; - hostspec->netmask = htonl ((uint32_t)~0 << shiftbits); - - ret = 0; /* SUCCESS */ + char *ipdupstr = NULL; + char *savptr = NULL; + char *endptr = NULL; + char *ip = NULL; + char *token = NULL; + int ret = -1; + long prefixlen = IPv4_ADDR_SIZE; /* default */ + uint32_t shiftbits = 0; + size_t length = 0; + + /* Create copy of the string so that the source won't change + */ + ipdupstr = gf_strdup(hostip); + if (NULL == ipdupstr) { + gf_msg(GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, + "Memory allocation failed"); + goto err; + } + + ip = strtok_r(ipdupstr, "/", &savptr); + /* Validate the Hostname or IPv4 address + * TODO: IPv6 support for subdir auth. + */ + length = strlen(ip); + if ((!valid_ipv4_address(ip, (int)length, _gf_false)) && + (!valid_host_name(ip, (int)length))) { + gf_msg(GF_MNT, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY, + "Invalid hostname or IPv4 address: %s", ip); + goto err; + } + + hostspec->host_addr = gf_strdup(ip); + if (NULL == hostspec->host_addr) { + gf_msg(GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, + "Memory allocation failed"); + goto err; + } + + /** + * User provided CIDR address (xx.xx.xx.xx/n format) is split + * into HOST (IP addr or hostname) and network prefix(n) from + * which netmask would be calculated. This CIDR address may + * denote a single, distinct interface address or the beginning + * address of an entire network. + * + * e.g. the IPv4 block 192.168.100.0/24 represents the 256 + * IPv4 addresses from 192.168.100.0 to 192.168.100.255. + * Therefore to check if an IP matches 192.168.100.0/24 + * we should mask the IP with FFFFFF00 and compare it with + * host address part of CIDR. + * + * Refer: mask_match() in common-utils.c. + */ + token = strtok_r(NULL, "/", &savptr); + if (token != NULL) { + prefixlen = strtol(token, &endptr, 10); + if ((errno != 0) || (*endptr != '\0') || (prefixlen < 0) || + (prefixlen > IPv4_ADDR_SIZE)) { + gf_msg(THIS->name, GF_LOG_WARNING, EINVAL, NFS_MSG_INVALID_ENTRY, + "Invalid IPv4 subnetwork mask"); + goto err; + } + } + + /* + * 1. Calculate the network mask address. + * 2. Convert it into Big-Endian format. + * 3. Store it in hostspec netmask. + */ + shiftbits = IPv4_ADDR_SIZE - prefixlen; + hostspec->netmask = htonl((uint32_t)~0 << shiftbits); + + ret = 0; /* SUCCESS */ err: - if (NULL != ipdupstr) { - GF_FREE (ipdupstr); - } - return ret; + if (NULL != ipdupstr) { + GF_FREE(ipdupstr); + } + return ret; } - /** * This function will parse the AUTH parameter passed along with * "export-dir" option. If AUTH parameter is present then it will be @@ -3210,80 +3193,75 @@ err: * @return This function will return 0 on success and -1 on failure. */ int -mnt3_export_parse_auth_param (struct mnt3_export* exp, char* exportpath) +mnt3_export_parse_auth_param(struct mnt3_export *exp, char *exportpath) { - char *token = NULL; - char *savPtr = NULL; - char *hostip = NULL; - struct host_auth_spec *host = NULL; - int ret = 0; - - /* Using exportpath directly in strtok_r because we want - * to strip off AUTH parameter from exportpath. */ - token = strtok_r (exportpath, "(", &savPtr); - - /* Get the next token, which will be the AUTH parameter. */ - token = strtok_r (NULL, ")", &savPtr); - - if (NULL == token) { - /* If AUTH is not present then we should return success. */ - return 0; - } + char *token = NULL; + char *savPtr = NULL; + char *hostip = NULL; + struct host_auth_spec *host = NULL; + int ret = 0; - /* Free any previously allocated hostspec structure. */ - if (NULL != exp->hostspec) { - GF_FREE (exp->hostspec); - exp->hostspec = NULL; - } + /* Using exportpath directly in strtok_r because we want + * to strip off AUTH parameter from exportpath. */ + token = strtok_r(exportpath, "(", &savPtr); - exp->hostspec = GF_CALLOC (1, - sizeof (*(exp->hostspec)), - gf_nfs_mt_auth_spec); - if (NULL == exp->hostspec){ - gf_msg (GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, - "Memory allocation failed"); - return -1; - } + /* Get the next token, which will be the AUTH parameter. */ + token = strtok_r(NULL, ")", &savPtr); - /* AUTH parameter can have multiple entries. For each entry - * a host_auth_spec structure is created. */ - host = exp->hostspec; + if (NULL == token) { + /* If AUTH is not present then we should return success. */ + return 0; + } + + /* Free any previously allocated hostspec structure. */ + if (NULL != exp->hostspec) { + GF_FREE(exp->hostspec); + exp->hostspec = NULL; + } + + exp->hostspec = GF_CALLOC(1, sizeof(*(exp->hostspec)), gf_nfs_mt_auth_spec); + if (NULL == exp->hostspec) { + gf_msg(GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, + "Memory allocation failed"); + return -1; + } - hostip = strtok_r (token, "|", &savPtr); + /* AUTH parameter can have multiple entries. For each entry + * a host_auth_spec structure is created. */ + host = exp->hostspec; - /* Parse all AUTH parameters separated by '|' */ - while (NULL != hostip){ - ret = mnt3_export_fill_hostspec (host, hostip); - if (0 != ret) { - gf_msg (GF_MNT, GF_LOG_WARNING, 0, - NFS_MSG_PARSE_HOSTSPEC_FAIL, - "Failed to parse hostspec: %s", hostip); - goto err; - } + hostip = strtok_r(token, "|", &savPtr); - hostip = strtok_r (NULL, "|", &savPtr); - if (NULL == hostip) { - break; - } + /* Parse all AUTH parameters separated by '|' */ + while (NULL != hostip) { + ret = mnt3_export_fill_hostspec(host, hostip); + if (0 != ret) { + gf_msg(GF_MNT, GF_LOG_WARNING, 0, NFS_MSG_PARSE_HOSTSPEC_FAIL, + "Failed to parse hostspec: %s", hostip); + goto err; + } - host->next = GF_CALLOC (1, sizeof (*(host)), - gf_nfs_mt_auth_spec); - if (NULL == host->next){ - gf_msg (GF_MNT, GF_LOG_ERROR, ENOMEM, - NFS_MSG_NO_MEMORY, - "Memory allocation failed"); - goto err; - } - host = host->next; + hostip = strtok_r(NULL, "|", &savPtr); + if (NULL == hostip) { + break; } - /* In case of success return from here */ - return 0; + host->next = GF_CALLOC(1, sizeof(*(host)), gf_nfs_mt_auth_spec); + if (NULL == host->next) { + gf_msg(GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, + "Memory allocation failed"); + goto err; + } + host = host->next; + } + + /* In case of success return from here */ + return 0; err: - /* In case of failure free up hostspec structure. */ - FREE_HOSTSPEC (exp); + /* In case of failure free up hostspec structure. */ + FREE_HOSTSPEC(exp); - return -1; + return -1; } /** @@ -3292,419 +3270,410 @@ err: * exportpath format: <abspath>[(hostdesc[|hostspec|...])] */ struct mnt3_export * -mnt3_init_export_ent (struct mount3_state *ms, xlator_t *xl, char *exportpath, - uuid_t volumeid) +mnt3_init_export_ent(struct mount3_state *ms, xlator_t *xl, char *exportpath, + uuid_t volumeid) { - struct mnt3_export *exp = NULL; - int alloclen = 0; - int ret = -1; - - if ((!ms) || (!xl)) - return NULL; - - exp = GF_CALLOC (1, sizeof (*exp), gf_nfs_mt_mnt3_export); - if (!exp) { - gf_msg (GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, - "Memory allocation failed"); - return NULL; - } - - if (NULL != exportpath) { - /* If exportpath is not NULL then we should check if AUTH - * parameter is present or not. If AUTH parameter is present - * then it will be stripped and stored in mnt3_export (exp) - * structure. - */ - if (0 != mnt3_export_parse_auth_param (exp, exportpath)){ - gf_msg (GF_MNT, GF_LOG_ERROR, 0, - NFS_MSG_PARSE_AUTH_PARAM_FAIL, - "Failed to parse auth param"); - goto err; - } - } - + struct mnt3_export *exp = NULL; + int alloclen = 0; + int ret = -1; - INIT_LIST_HEAD (&exp->explist); - if (exportpath) - alloclen = strlen (xl->name) + 2 + strlen (exportpath); - else - alloclen = strlen (xl->name) + 2; + if ((!ms) || (!xl)) + return NULL; - exp->expname = GF_MALLOC (alloclen, gf_nfs_mt_char); - if (!exp->expname) { - gf_msg (GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, - "Memory allocation failed"); - goto err; - } + exp = GF_CALLOC(1, sizeof(*exp), gf_nfs_mt_mnt3_export); + if (!exp) { + gf_msg(GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, + "Memory allocation failed"); + return NULL; + } - if (exportpath) { - gf_msg_trace (GF_MNT, 0, "Initing dir export: %s:%s", - xl->name, exportpath); - exp->exptype = MNT3_EXPTYPE_DIR; - ret = snprintf (exp->expname, alloclen, "/%s%s", xl->name, - exportpath); - } else { - gf_msg_trace (GF_MNT, 0, "Initing volume export: %s", - xl->name); - exp->exptype = MNT3_EXPTYPE_VOLUME; - ret = snprintf (exp->expname, alloclen, "/%s", xl->name); - } - if (ret < 0) { - gf_msg (xl->name, GF_LOG_ERROR, ret, NFS_MSG_SET_EXP_FAIL, - "Failed to set the export name"); - goto err; - } - /* Just copy without discrimination, we'll determine whether to - * actually use it when a mount request comes in and a file handle - * needs to be built. + if (NULL != exportpath) { + /* If exportpath is not NULL then we should check if AUTH + * parameter is present or not. If AUTH parameter is present + * then it will be stripped and stored in mnt3_export (exp) + * structure. */ - gf_uuid_copy (exp->volumeid, volumeid); - exp->vol = xl; - - /* On success we should return from here*/ - return exp; + if (0 != mnt3_export_parse_auth_param(exp, exportpath)) { + gf_msg(GF_MNT, GF_LOG_ERROR, 0, NFS_MSG_PARSE_AUTH_PARAM_FAIL, + "Failed to parse auth param"); + goto err; + } + } + + INIT_LIST_HEAD(&exp->explist); + if (exportpath) + alloclen = strlen(xl->name) + 2 + strlen(exportpath); + else + alloclen = strlen(xl->name) + 2; + + exp->expname = GF_MALLOC(alloclen, gf_nfs_mt_char); + if (!exp->expname) { + gf_msg(GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, + "Memory allocation failed"); + goto err; + } + + if (exportpath) { + gf_msg_trace(GF_MNT, 0, "Initing dir export: %s:%s", xl->name, + exportpath); + exp->exptype = MNT3_EXPTYPE_DIR; + ret = snprintf(exp->expname, alloclen, "/%s%s", xl->name, exportpath); + } else { + gf_msg_trace(GF_MNT, 0, "Initing volume export: %s", xl->name); + exp->exptype = MNT3_EXPTYPE_VOLUME; + ret = snprintf(exp->expname, alloclen, "/%s", xl->name); + } + if (ret < 0) { + gf_msg(xl->name, GF_LOG_ERROR, ret, NFS_MSG_SET_EXP_FAIL, + "Failed to set the export name"); + goto err; + } + /* Just copy without discrimination, we'll determine whether to + * actually use it when a mount request comes in and a file handle + * needs to be built. + */ + gf_uuid_copy(exp->volumeid, volumeid); + exp->vol = xl; + + /* On success we should return from here*/ + return exp; err: - /* On failure free exp and it's members.*/ - if (NULL != exp) { - mnt3_export_free (exp); - exp = NULL; - } + /* On failure free exp and it's members.*/ + if (NULL != exp) { + mnt3_export_free(exp); + exp = NULL; + } - return exp; + return exp; } - int -__mnt3_init_volume_direxports (struct mount3_state *ms, xlator_t *xlator, - char *optstr, uuid_t volumeid) +__mnt3_init_volume_direxports(struct mount3_state *ms, xlator_t *xlator, + char *optstr, uuid_t volumeid) { - struct mnt3_export *newexp = NULL; - int ret = -1; - char *savptr = NULL; - char *dupopt = NULL; - char *token = NULL; - - if ((!ms) || (!xlator) || (!optstr)) - return -1; - - dupopt = strdupa (optstr); - - token = strtok_r (dupopt, ",", &savptr); - while (token) { - newexp = mnt3_init_export_ent (ms, xlator, token, volumeid); - if (!newexp) { - gf_msg (GF_MNT, GF_LOG_ERROR, 0, - NFS_MSG_INIT_DIR_EXP_FAIL, "Failed to init dir " - "export: %s", token); - ret = -1; - goto err; - } + struct mnt3_export *newexp = NULL; + int ret = -1; + char *savptr = NULL; + char *dupopt = NULL; + char *token = NULL; - list_add_tail (&newexp->explist, &ms->exportlist); - token = strtok_r (NULL, ",", &savptr); + if ((!ms) || (!xlator) || (!optstr)) + return -1; + + dupopt = strdupa(optstr); + + token = strtok_r(dupopt, ",", &savptr); + while (token) { + newexp = mnt3_init_export_ent(ms, xlator, token, volumeid); + if (!newexp) { + gf_msg(GF_MNT, GF_LOG_ERROR, 0, NFS_MSG_INIT_DIR_EXP_FAIL, + "Failed to init dir " + "export: %s", + token); + ret = -1; + goto err; } - ret = 0; + list_add_tail(&newexp->explist, &ms->exportlist); + token = strtok_r(NULL, ",", &savptr); + } + + ret = 0; err: - return ret; + return ret; } - int -__mnt3_init_volume (struct mount3_state *ms, dict_t *opts, xlator_t *xlator) +__mnt3_init_volume(struct mount3_state *ms, dict_t *opts, xlator_t *xlator) { - struct mnt3_export *newexp = NULL; - int ret = -1; - char searchstr[1024]; - char *optstr = NULL; - uuid_t volumeid = {0, }; + struct mnt3_export *newexp = NULL; + int ret = -1; + char searchstr[1024]; + char *optstr = NULL; + uuid_t volumeid = { + 0, + }; + + if ((!ms) || (!xlator) || (!opts)) + return -1; - if ((!ms) || (!xlator) || (!opts)) - return -1; + gf_uuid_clear(volumeid); + if (gf_nfs_dvm_off(nfs_state(ms->nfsx))) + goto no_dvm; - gf_uuid_clear (volumeid); - if (gf_nfs_dvm_off (nfs_state (ms->nfsx))) - goto no_dvm; + ret = snprintf(searchstr, 1024, "nfs3.%s.volume-id", xlator->name); + if (ret < 0) { + gf_msg(GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_SNPRINTF_FAIL, + "snprintf failed"); + ret = -1; + goto err; + } - ret = snprintf (searchstr, 1024, "nfs3.%s.volume-id", xlator->name); + if (dict_get(opts, searchstr)) { + ret = dict_get_str(opts, searchstr, &optstr); if (ret < 0) { - gf_msg (GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_SNPRINTF_FAIL, - "snprintf failed"); - ret = -1; - goto err; - } - - if (dict_get (opts, searchstr)) { - ret = dict_get_str (opts, searchstr, &optstr); - if (ret < 0) { - gf_msg (GF_MNT, GF_LOG_ERROR, ret, - NFS_MSG_DICT_GET_FAILED, "Failed to read " - "option: %s", searchstr); - ret = -1; - goto err; - } - } else { - gf_msg (GF_MNT, GF_LOG_ERROR, 0, NFS_MSG_VOLID_MISSING, - "DVM is on but volume-id not " - "given for volume: %s", xlator->name); - ret = -1; - goto err; - } - - if (optstr) { - ret = gf_uuid_parse (optstr, volumeid); - if (ret < 0) { - gf_msg (GF_MNT, GF_LOG_ERROR, ret, - NFS_MSG_PARSE_VOL_UUID_FAIL, "Failed to parse " - "volume UUID"); - ret = -1; - goto err; - } + gf_msg(GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_DICT_GET_FAILED, + "Failed to read " + "option: %s", + searchstr); + ret = -1; + goto err; + } + } else { + gf_msg(GF_MNT, GF_LOG_ERROR, 0, NFS_MSG_VOLID_MISSING, + "DVM is on but volume-id not " + "given for volume: %s", + xlator->name); + ret = -1; + goto err; + } + + if (optstr) { + ret = gf_uuid_parse(optstr, volumeid); + if (ret < 0) { + gf_msg(GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_PARSE_VOL_UUID_FAIL, + "Failed to parse " + "volume UUID"); + ret = -1; + goto err; } + } no_dvm: - ret = snprintf (searchstr, 1024, "nfs3.%s.export-dir", xlator->name); + ret = snprintf(searchstr, 1024, "nfs3.%s.export-dir", xlator->name); + if (ret < 0) { + gf_msg(GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_SNPRINTF_FAIL, + "snprintf failed"); + ret = -1; + goto err; + } + + if (dict_get(opts, searchstr)) { + ret = dict_get_str(opts, searchstr, &optstr); if (ret < 0) { - gf_msg (GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_SNPRINTF_FAIL, - "snprintf failed"); - ret = -1; - goto err; + gf_msg(GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_DICT_GET_FAILED, + "Failed to read " + "option: %s", + searchstr); + ret = -1; + goto err; } - if (dict_get (opts, searchstr)) { - ret = dict_get_str (opts, searchstr, &optstr); - if (ret < 0) { - gf_msg (GF_MNT, GF_LOG_ERROR, ret, - NFS_MSG_DICT_GET_FAILED, "Failed to read " - "option: %s", searchstr); - ret = -1; - goto err; - } - - ret = __mnt3_init_volume_direxports (ms, xlator, optstr, - volumeid); - if (ret == -1) { - gf_msg (GF_MNT, GF_LOG_ERROR, 0, - NFS_MSG_DIR_EXP_SETUP_FAIL, "Dir export " - "setup failed for volume: %s", xlator->name); - goto err; - } + ret = __mnt3_init_volume_direxports(ms, xlator, optstr, volumeid); + if (ret == -1) { + gf_msg(GF_MNT, GF_LOG_ERROR, 0, NFS_MSG_DIR_EXP_SETUP_FAIL, + "Dir export " + "setup failed for volume: %s", + xlator->name); + goto err; } + } - if (ms->export_volumes) { - newexp = mnt3_init_export_ent (ms, xlator, NULL, volumeid); - if (!newexp) { - ret = -1; - goto err; - } - - list_add_tail (&newexp->explist, &ms->exportlist); + if (ms->export_volumes) { + newexp = mnt3_init_export_ent(ms, xlator, NULL, volumeid); + if (!newexp) { + ret = -1; + goto err; } - ret = 0; + list_add_tail(&newexp->explist, &ms->exportlist); + } + ret = 0; err: - return ret; + return ret; } - int -__mnt3_init_volume_export (struct mount3_state *ms, dict_t *opts) +__mnt3_init_volume_export(struct mount3_state *ms, dict_t *opts) { - int ret = -1; - char *optstr = NULL; - /* On by default. */ - gf_boolean_t boolt = _gf_true; - - if ((!ms) || (!opts)) - return -1; - - if (!dict_get (opts, "nfs3.export-volumes")) { - ret = 0; - goto err; - } + int ret = -1; + char *optstr = NULL; + /* On by default. */ + gf_boolean_t boolt = _gf_true; - ret = dict_get_str (opts, "nfs3.export-volumes", &optstr); - if (ret < 0) { - gf_msg (GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_DICT_GET_FAILED, - "Failed to read option: nfs3.export-volumes"); - ret = -1; - goto err; - } + if ((!ms) || (!opts)) + return -1; - ret = gf_string2boolean (optstr, &boolt); - if (ret < 0) { - gf_msg (GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_STR2BOOL_FAIL, - "Failed to convert string to boolean"); - } + if (!dict_get(opts, "nfs3.export-volumes")) { + ret = 0; + goto err; + } + + ret = dict_get_str(opts, "nfs3.export-volumes", &optstr); + if (ret < 0) { + gf_msg(GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_DICT_GET_FAILED, + "Failed to read option: nfs3.export-volumes"); + ret = -1; + goto err; + } + + ret = gf_string2boolean(optstr, &boolt); + if (ret < 0) { + gf_msg(GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_STR2BOOL_FAIL, + "Failed to convert string to boolean"); + } err: - if (boolt == _gf_false) { - gf_msg_trace (GF_MNT, 0, "Volume exports disabled"); - ms->export_volumes = 0; - } else { - gf_msg_trace (GF_MNT, 0, "Volume exports enabled"); - ms->export_volumes = 1; - } - - return ret; + if (boolt == _gf_false) { + gf_msg_trace(GF_MNT, 0, "Volume exports disabled"); + ms->export_volumes = 0; + } else { + gf_msg_trace(GF_MNT, 0, "Volume exports enabled"); + ms->export_volumes = 1; + } + + return ret; } - int -__mnt3_init_dir_export (struct mount3_state *ms, dict_t *opts) +__mnt3_init_dir_export(struct mount3_state *ms, dict_t *opts) { - int ret = -1; - char *optstr = NULL; - /* On by default. */ - gf_boolean_t boolt = _gf_true; - - if ((!ms) || (!opts)) - return -1; + int ret = -1; + char *optstr = NULL; + /* On by default. */ + gf_boolean_t boolt = _gf_true; - if (!dict_get (opts, "nfs3.export-dirs")) { - ret = 0; - goto err; - } - - ret = dict_get_str (opts, "nfs3.export-dirs", &optstr); - if (ret < 0) { - gf_msg (GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_DICT_GET_FAILED, - "Failed to read option: nfs3.export-dirs"); - ret = -1; - goto err; - } + if ((!ms) || (!opts)) + return -1; - ret = gf_string2boolean (optstr, &boolt); - if (ret < 0) { - gf_msg (GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_STR2BOOL_FAIL, - "Failed to convert string to boolean"); - } + if (!dict_get(opts, "nfs3.export-dirs")) { + ret = 0; + goto err; + } + + ret = dict_get_str(opts, "nfs3.export-dirs", &optstr); + if (ret < 0) { + gf_msg(GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_DICT_GET_FAILED, + "Failed to read option: nfs3.export-dirs"); + ret = -1; + goto err; + } + + ret = gf_string2boolean(optstr, &boolt); + if (ret < 0) { + gf_msg(GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_STR2BOOL_FAIL, + "Failed to convert string to boolean"); + } err: - if (boolt == _gf_false) { - gf_msg_trace (GF_MNT, 0, "Dir exports disabled"); - ms->export_dirs = 0; - } else { - gf_msg_trace (GF_MNT, 0, "Dir exports enabled"); - ms->export_dirs = 1; - } - - return ret; + if (boolt == _gf_false) { + gf_msg_trace(GF_MNT, 0, "Dir exports disabled"); + ms->export_dirs = 0; + } else { + gf_msg_trace(GF_MNT, 0, "Dir exports enabled"); + ms->export_dirs = 1; + } + + return ret; } - int -mnt3_init_options (struct mount3_state *ms, dict_t *options) +mnt3_init_options(struct mount3_state *ms, dict_t *options) { - xlator_list_t *volentry = NULL; - int ret = -1; - - if ((!ms) || (!options)) - return -1; - - __mnt3_init_volume_export (ms, options); - __mnt3_init_dir_export (ms, options); - volentry = ms->nfsx->children; - while (volentry) { - gf_msg_trace (GF_MNT, 0, "Initing options for: %s", - volentry->xlator->name); - ret = __mnt3_init_volume (ms, options, volentry->xlator); - if (ret < 0) { - gf_msg (GF_MNT, GF_LOG_ERROR, ret, - NFS_MSG_VOL_INIT_FAIL, - "Volume init failed"); - goto err; - } + xlator_list_t *volentry = NULL; + int ret = -1; - volentry = volentry->next; + if ((!ms) || (!options)) + return -1; + + __mnt3_init_volume_export(ms, options); + __mnt3_init_dir_export(ms, options); + volentry = ms->nfsx->children; + while (volentry) { + gf_msg_trace(GF_MNT, 0, "Initing options for: %s", + volentry->xlator->name); + ret = __mnt3_init_volume(ms, options, volentry->xlator); + if (ret < 0) { + gf_msg(GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_VOL_INIT_FAIL, + "Volume init failed"); + goto err; } + volentry = volentry->next; + } - ret = 0; + ret = 0; err: - return ret; + return ret; } struct mount3_state * -mnt3_init_state (xlator_t *nfsx) +mnt3_init_state(xlator_t *nfsx) { - struct mount3_state *ms = NULL; - int ret = -1; - - if (!nfsx) - return NULL; + struct mount3_state *ms = NULL; + int ret = -1; - ms = GF_CALLOC (1, sizeof (*ms), gf_nfs_mt_mount3_state); - if (!ms) { - gf_msg (GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, - "Memory allocation failed"); - return NULL; - } + if (!nfsx) + return NULL; - ms->iobpool = nfsx->ctx->iobuf_pool; - ms->nfsx = nfsx; - INIT_LIST_HEAD (&ms->exportlist); - ret = mnt3_init_options (ms, nfsx->options); - if (ret < 0) { - gf_msg (GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_OPT_INIT_FAIL, - "Options init failed"); - return NULL; - } + ms = GF_CALLOC(1, sizeof(*ms), gf_nfs_mt_mount3_state); + if (!ms) { + gf_msg(GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, + "Memory allocation failed"); + return NULL; + } + + ms->iobpool = nfsx->ctx->iobuf_pool; + ms->nfsx = nfsx; + INIT_LIST_HEAD(&ms->exportlist); + ret = mnt3_init_options(ms, nfsx->options); + if (ret < 0) { + gf_msg(GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_OPT_INIT_FAIL, + "Options init failed"); + return NULL; + } - INIT_LIST_HEAD (&ms->mountlist); - LOCK_INIT (&ms->mountlock); + INIT_LIST_HEAD(&ms->mountlist); + LOCK_INIT(&ms->mountlock); - return ms; + return ms; } int -mount_init_state (xlator_t *nfsx) +mount_init_state(xlator_t *nfsx) { - int ret = -1; - struct nfs_state *nfs = NULL; - - if (!nfsx) - goto out; - - nfs = (struct nfs_state *)nfs_state (nfsx); - /*Maintaining global state for MOUNT1 and MOUNT3*/ - nfs->mstate = mnt3_init_state (nfsx); - if (!nfs->mstate) { - gf_msg (GF_NFS, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, - "Failed to allocate mount state"); - goto out; - } - ret = 0; + int ret = -1; + struct nfs_state *nfs = NULL; + + if (!nfsx) + goto out; + + nfs = (struct nfs_state *)nfs_state(nfsx); + /*Maintaining global state for MOUNT1 and MOUNT3*/ + nfs->mstate = mnt3_init_state(nfsx); + if (!nfs->mstate) { + gf_msg(GF_NFS, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, + "Failed to allocate mount state"); + goto out; + } + ret = 0; out: - return ret; + return ret; } -rpcsvc_actor_t mnt3svc_actors[MOUNT3_PROC_COUNT] = { - {"NULL", MOUNT3_NULL, mnt3svc_null, NULL, 0, DRC_NA}, - {"MNT", MOUNT3_MNT, mnt3svc_mnt, NULL, 0, DRC_NA}, - {"DUMP", MOUNT3_DUMP, mnt3svc_dump, NULL, 0, DRC_NA}, - {"UMNT", MOUNT3_UMNT, mnt3svc_umnt, NULL, 0, DRC_NA}, - {"UMNTALL", MOUNT3_UMNTALL, mnt3svc_umntall, NULL, 0, DRC_NA}, - {"EXPORT", MOUNT3_EXPORT, mnt3svc_export, NULL, 0, DRC_NA} -}; - - +rpcsvc_actor_t mnt3svc_actors[MOUNT3_PROC_COUNT] = { + {"NULL", MOUNT3_NULL, mnt3svc_null, NULL, 0, DRC_NA}, + {"MNT", MOUNT3_MNT, mnt3svc_mnt, NULL, 0, DRC_NA}, + {"DUMP", MOUNT3_DUMP, mnt3svc_dump, NULL, 0, DRC_NA}, + {"UMNT", MOUNT3_UMNT, mnt3svc_umnt, NULL, 0, DRC_NA}, + {"UMNTALL", MOUNT3_UMNTALL, mnt3svc_umntall, NULL, 0, DRC_NA}, + {"EXPORT", MOUNT3_EXPORT, mnt3svc_export, NULL, 0, DRC_NA}}; /* Static init parts are assigned here, dynamic ones are done in * mnt3svc_init and mnt3_init_state. * Making MOUNT3 a synctask so that the blocking DNS calls during rpc auth * gets offloaded to syncenv, keeping the main/poll thread unblocked */ -rpcsvc_program_t mnt3prog = { - .progname = "MOUNT3", - .prognum = MOUNT_PROGRAM, - .progver = MOUNT_V3, - .progport = GF_MOUNTV3_PORT, - .actors = mnt3svc_actors, - .numactors = MOUNT3_PROC_COUNT, - .min_auth = AUTH_NULL, - .synctask = _gf_true, +rpcsvc_program_t mnt3prog = { + .progname = "MOUNT3", + .prognum = MOUNT_PROGRAM, + .progver = MOUNT_V3, + .progport = GF_MOUNTV3_PORT, + .actors = mnt3svc_actors, + .numactors = MOUNT3_PROC_COUNT, + .min_auth = AUTH_NULL, + .synctask = _gf_true, }; /** @@ -3718,79 +3687,82 @@ rpcsvc_program_t mnt3prog = { * */ int -__mnt3_mounted_exports_walk (dict_t *dict, char *key, data_t *val, void *tmp) +__mnt3_mounted_exports_walk(dict_t *dict, char *key, data_t *val, void *tmp) { - char *path = NULL; - char *host_addr_ip = NULL; - char *host_addr_fqdn = NULL; - char *keydup = NULL; - char *colon = NULL; - struct mnt3_auth_params *auth_params = NULL; - int ret = 0; - int auth_status_code = 0; - - gf_msg_trace (GF_MNT, 0, "Checking if key %s is authorized.", key); - - auth_params = (struct mnt3_auth_params *)tmp; - - /* Since we haven't obtained a lock around the mount dict - * here, we want to duplicate the key and then process it. - * Otherwise we would potentially have a race condition - * by modifying the key in the dict when other threads - * are accessing it. - */ - keydup = strdupa (key); - - colon = strchr (keydup, ':'); - if (!colon) - return 0; - - *colon = '\0'; - - path = alloca (strlen (keydup) + 2); - snprintf (path, strlen (keydup) + 2, "/%s", keydup); - - /* Host is one character after ':' */ - host_addr_ip = colon + 1; - - /* Check if the IP is authorized */ - auth_status_code = mnt3_auth_host (auth_params, host_addr_ip, - NULL, path, FALSE, NULL); - if (auth_status_code == 0) { - goto out; - } - - ret = gf_get_hostname_from_ip (host_addr_ip, &host_addr_fqdn); - if (ret != 0) { - gf_msg (GF_MNT, GF_LOG_DEBUG, 0, NFS_MSG_AUTH_ERROR , - "Authorization failed for IP [%s], but name " - "resolution also failed!", host_addr_ip); - goto unmount; - } + char *path = NULL; + char *host_addr_ip = NULL; + char *host_addr_fqdn = NULL; + char *keydup = NULL; + char *colon = NULL; + struct mnt3_auth_params *auth_params = NULL; + int ret = 0; + int auth_status_code = 0; + + gf_msg_trace(GF_MNT, 0, "Checking if key %s is authorized.", key); + + auth_params = (struct mnt3_auth_params *)tmp; + + /* Since we haven't obtained a lock around the mount dict + * here, we want to duplicate the key and then process it. + * Otherwise we would potentially have a race condition + * by modifying the key in the dict when other threads + * are accessing it. + */ + keydup = strdupa(key); + + colon = strchr(keydup, ':'); + if (!colon) + return 0; - /* If not, check if the FQDN is authorized */ - gf_msg (GF_MNT, GF_LOG_DEBUG, 0, NFS_MSG_AUTH_ERROR, - "Authorization failed for IP [%s], attempting to" - " auth hostname [%s]...", host_addr_ip, host_addr_fqdn); - - auth_status_code = mnt3_auth_host (auth_params, host_addr_fqdn, - NULL, path, FALSE, NULL); - if (auth_status_code == 0) { - gf_msg (GF_MNT, GF_LOG_DEBUG, 0, NFS_MSG_AUTH_ERROR, - "Authorization succeeded for " - "Client [IP=%s, Hostname=%s].", - host_addr_ip, host_addr_fqdn); - goto out; - } + *colon = '\0'; + + path = alloca(strlen(keydup) + 2); + snprintf(path, strlen(keydup) + 2, "/%s", keydup); + + /* Host is one character after ':' */ + host_addr_ip = colon + 1; + + /* Check if the IP is authorized */ + auth_status_code = mnt3_auth_host(auth_params, host_addr_ip, NULL, path, + FALSE, NULL); + if (auth_status_code == 0) { + goto out; + } + + ret = gf_get_hostname_from_ip(host_addr_ip, &host_addr_fqdn); + if (ret != 0) { + gf_msg(GF_MNT, GF_LOG_DEBUG, 0, NFS_MSG_AUTH_ERROR, + "Authorization failed for IP [%s], but name " + "resolution also failed!", + host_addr_ip); + goto unmount; + } + + /* If not, check if the FQDN is authorized */ + gf_msg(GF_MNT, GF_LOG_DEBUG, 0, NFS_MSG_AUTH_ERROR, + "Authorization failed for IP [%s], attempting to" + " auth hostname [%s]...", + host_addr_ip, host_addr_fqdn); + + auth_status_code = mnt3_auth_host(auth_params, host_addr_fqdn, NULL, path, + FALSE, NULL); + if (auth_status_code == 0) { + gf_msg(GF_MNT, GF_LOG_DEBUG, 0, NFS_MSG_AUTH_ERROR, + "Authorization succeeded for " + "Client [IP=%s, Hostname=%s].", + host_addr_ip, host_addr_fqdn); + goto out; + } unmount: - gf_msg (GF_MNT, GF_LOG_ERROR, 0, NFS_MSG_AUTH_ERROR, - "Client [IP=%s, Hostname=%s] not authorized for this mount. " - "Unmounting!", host_addr_ip, host_addr_fqdn); - mnt3svc_umount (auth_params->ms, path, host_addr_ip); + gf_msg(GF_MNT, GF_LOG_ERROR, 0, NFS_MSG_AUTH_ERROR, + "Client [IP=%s, Hostname=%s] not authorized for this mount. " + "Unmounting!", + host_addr_ip, host_addr_fqdn); + mnt3svc_umount(auth_params->ms, path, host_addr_ip); out: - GF_FREE (host_addr_fqdn); - return 0; + GF_FREE(host_addr_fqdn); + return 0; } /** @@ -3802,14 +3774,12 @@ out: * */ void -_mnt3_invalidate_old_mounts (struct mount3_state *ms) +_mnt3_invalidate_old_mounts(struct mount3_state *ms) { - gf_msg_debug (GF_MNT, 0, "Invalidating old mounts ..."); - dict_foreach (ms->mountdict, __mnt3_mounted_exports_walk, - ms->auth_params); + gf_msg_debug(GF_MNT, 0, "Invalidating old mounts ..."); + dict_foreach(ms->mountdict, __mnt3_mounted_exports_walk, ms->auth_params); } - /** * _mnt3_has_file_changed -- Checks if a file has changed on disk * @@ -3822,25 +3792,25 @@ _mnt3_invalidate_old_mounts (struct mount3_state *ms) * Uses get_file_mtime () in common-utils.c */ gf_boolean_t -_mnt3_has_file_changed (const char *path, time_t *oldmtime) +_mnt3_has_file_changed(const char *path, time_t *oldmtime) { - gf_boolean_t changed = _gf_false; - time_t mtime = {0}; - int ret = 0; + gf_boolean_t changed = _gf_false; + time_t mtime = {0}; + int ret = 0; - GF_VALIDATE_OR_GOTO (GF_MNT, path, out); - GF_VALIDATE_OR_GOTO (GF_MNT, oldmtime, out); + GF_VALIDATE_OR_GOTO(GF_MNT, path, out); + GF_VALIDATE_OR_GOTO(GF_MNT, oldmtime, out); - ret = get_file_mtime (path, &mtime); - if (ret < 0) - goto out; + ret = get_file_mtime(path, &mtime); + if (ret < 0) + goto out; - if (mtime != *oldmtime) { - changed = _gf_true; - *oldmtime = mtime; - } + if (mtime != *oldmtime) { + changed = _gf_true; + *oldmtime = mtime; + } out: - return changed; + return changed; } /** @@ -3853,84 +3823,82 @@ out: * @return: Always returns NULL */ void * -_mnt3_auth_param_refresh_thread (void *argv) +_mnt3_auth_param_refresh_thread(void *argv) { - struct mount3_state *mstate = (struct mount3_state *)argv; - char *exp_file_path = NULL; - char *ng_file_path = NULL; - size_t nbytes = 0; - time_t exp_time = 0; - time_t ng_time = 0; - gf_boolean_t any_file_changed = _gf_false; - int ret = 0; - - nbytes = strlen (exports_file_path) + 1; - exp_file_path = alloca (nbytes); - snprintf (exp_file_path, nbytes, "%s", exports_file_path); - - nbytes = strlen (netgroups_file_path) + 1; - ng_file_path = alloca (nbytes); - snprintf (ng_file_path, nbytes, "%s", netgroups_file_path); - - /* Set the initial timestamps to avoid reloading right after - * mnt3svc_init () spawns this thread */ - get_file_mtime (exp_file_path, &exp_time); - get_file_mtime (ng_file_path, &ng_time); - - while (_gf_true) { - if (mstate->stop_refresh) - break; - any_file_changed = _gf_false; - - /* Sleep before checking the file again */ - sleep (mstate->nfs->auth_refresh_time_secs); - - if (_mnt3_has_file_changed (exp_file_path, &exp_time)) { - gf_msg (GF_MNT, GF_LOG_INFO, 0, NFS_MSG_UPDATING_EXP, - "File %s changed, updating exports,", - exp_file_path); - - ret = mnt3_auth_set_exports_auth (mstate->auth_params, - exp_file_path); - if (ret) - gf_msg (GF_MNT, GF_LOG_ERROR, 0, - NFS_MSG_SET_EXP_AUTH_PARAM_FAIL, - "Failed to set export auth params."); - else - any_file_changed = _gf_true; - } - - if (_mnt3_has_file_changed (ng_file_path, &ng_time)) { - gf_msg (GF_MNT, GF_LOG_INFO, 0, - NFS_MSG_UPDATING_NET_GRP, "File %s changed," - "updating netgroups", ng_file_path); - - ret = mnt3_auth_set_netgroups_auth (mstate->auth_params, - ng_file_path); - if (ret) - gf_msg (GF_MNT, GF_LOG_ERROR, 0, - NFS_MSG_SET_NET_GRP_FAIL, - "Failed to set netgroup auth params."); - else - any_file_changed = _gf_true; - } - - /* If no files changed, go back to sleep */ - if (!any_file_changed) - continue; - - gf_msg (GF_MNT, GF_LOG_INFO, 0, NFS_MSG_PURGING_AUTH_CACHE, - "Purging auth cache."); - auth_cache_purge (mstate->authcache); - - /* Walk through mounts that are no longer authorized - * and unmount them on the server side. This will - * cause subsequent file ops to fail with access denied. - */ - _mnt3_invalidate_old_mounts (mstate); - } + struct mount3_state *mstate = (struct mount3_state *)argv; + char *exp_file_path = NULL; + char *ng_file_path = NULL; + size_t nbytes = 0; + time_t exp_time = 0; + time_t ng_time = 0; + gf_boolean_t any_file_changed = _gf_false; + int ret = 0; + + nbytes = strlen(exports_file_path) + 1; + exp_file_path = alloca(nbytes); + snprintf(exp_file_path, nbytes, "%s", exports_file_path); + + nbytes = strlen(netgroups_file_path) + 1; + ng_file_path = alloca(nbytes); + snprintf(ng_file_path, nbytes, "%s", netgroups_file_path); + + /* Set the initial timestamps to avoid reloading right after + * mnt3svc_init () spawns this thread */ + get_file_mtime(exp_file_path, &exp_time); + get_file_mtime(ng_file_path, &ng_time); + + while (_gf_true) { + if (mstate->stop_refresh) + break; + any_file_changed = _gf_false; + + /* Sleep before checking the file again */ + sleep(mstate->nfs->auth_refresh_time_secs); + + if (_mnt3_has_file_changed(exp_file_path, &exp_time)) { + gf_msg(GF_MNT, GF_LOG_INFO, 0, NFS_MSG_UPDATING_EXP, + "File %s changed, updating exports,", exp_file_path); + + ret = mnt3_auth_set_exports_auth(mstate->auth_params, + exp_file_path); + if (ret) + gf_msg(GF_MNT, GF_LOG_ERROR, 0, NFS_MSG_SET_EXP_AUTH_PARAM_FAIL, + "Failed to set export auth params."); + else + any_file_changed = _gf_true; + } + + if (_mnt3_has_file_changed(ng_file_path, &ng_time)) { + gf_msg(GF_MNT, GF_LOG_INFO, 0, NFS_MSG_UPDATING_NET_GRP, + "File %s changed," + "updating netgroups", + ng_file_path); + + ret = mnt3_auth_set_netgroups_auth(mstate->auth_params, + ng_file_path); + if (ret) + gf_msg(GF_MNT, GF_LOG_ERROR, 0, NFS_MSG_SET_NET_GRP_FAIL, + "Failed to set netgroup auth params."); + else + any_file_changed = _gf_true; + } + + /* If no files changed, go back to sleep */ + if (!any_file_changed) + continue; + + gf_msg(GF_MNT, GF_LOG_INFO, 0, NFS_MSG_PURGING_AUTH_CACHE, + "Purging auth cache."); + auth_cache_purge(mstate->authcache); + + /* Walk through mounts that are no longer authorized + * and unmount them on the server side. This will + * cause subsequent file ops to fail with access denied. + */ + _mnt3_invalidate_old_mounts(mstate); + } - return NULL; + return NULL; } /** @@ -3946,53 +3914,50 @@ _mnt3_auth_param_refresh_thread (void *argv) * bubbled up from the functions we call to set the params. */ int -_mnt3_init_auth_params (struct mount3_state *mstate) +_mnt3_init_auth_params(struct mount3_state *mstate) { - int ret = -EINVAL; - char *exp_file_path = NULL; - char *ng_file_path = NULL; - size_t nbytes = 0; - - GF_VALIDATE_OR_GOTO (GF_MNT, mstate, out); - - mstate->auth_params = mnt3_auth_params_init (mstate); - if (!mstate->auth_params) { - gf_msg (GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, - "Failed to init mount auth params."); - ret = -ENOMEM; - goto out; - } - - nbytes = strlen (exports_file_path) + 1; - exp_file_path = alloca (nbytes); - snprintf (exp_file_path, nbytes, "%s", exports_file_path); - - ret = mnt3_auth_set_exports_auth (mstate->auth_params, exp_file_path); - if (ret < 0) { - gf_msg (GF_MNT, GF_LOG_ERROR, ret, - NFS_MSG_SET_EXP_AUTH_PARAM_FAIL, - "Failed to set export auth params."); - goto out; - } - - nbytes = strlen (netgroups_file_path) + 1; - ng_file_path = alloca (nbytes); - snprintf (ng_file_path, nbytes, "%s", netgroups_file_path); - - ret = mnt3_auth_set_netgroups_auth (mstate->auth_params, ng_file_path); - if (ret < 0) { - gf_msg (GF_MNT, GF_LOG_ERROR, ret, - NFS_MSG_SET_EXP_AUTH_PARAM_FAIL, - "Failed to set netgroup auth params."); - goto out; - } - - ret = 0; + int ret = -EINVAL; + char *exp_file_path = NULL; + char *ng_file_path = NULL; + size_t nbytes = 0; + + GF_VALIDATE_OR_GOTO(GF_MNT, mstate, out); + + mstate->auth_params = mnt3_auth_params_init(mstate); + if (!mstate->auth_params) { + gf_msg(GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, + "Failed to init mount auth params."); + ret = -ENOMEM; + goto out; + } + + nbytes = strlen(exports_file_path) + 1; + exp_file_path = alloca(nbytes); + snprintf(exp_file_path, nbytes, "%s", exports_file_path); + + ret = mnt3_auth_set_exports_auth(mstate->auth_params, exp_file_path); + if (ret < 0) { + gf_msg(GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_SET_EXP_AUTH_PARAM_FAIL, + "Failed to set export auth params."); + goto out; + } + + nbytes = strlen(netgroups_file_path) + 1; + ng_file_path = alloca(nbytes); + snprintf(ng_file_path, nbytes, "%s", netgroups_file_path); + + ret = mnt3_auth_set_netgroups_auth(mstate->auth_params, ng_file_path); + if (ret < 0) { + gf_msg(GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_SET_EXP_AUTH_PARAM_FAIL, + "Failed to set netgroup auth params."); + goto out; + } + + ret = 0; out: - return ret; + return ret; } - /** * mnt3svc_deinit -- Function called by the nfs translator to cleanup all state * @@ -4001,289 +3966,278 @@ out: * as well as the threads that have been started. */ void -mnt3svc_deinit (xlator_t *nfsx) +mnt3svc_deinit(xlator_t *nfsx) { - struct mount3_state *mstate = NULL; - struct nfs_state *nfs = NULL; + struct mount3_state *mstate = NULL; + struct nfs_state *nfs = NULL; - if (!nfsx || !nfsx->private) - return; - - nfs = (struct nfs_state *)nfsx->private; - mstate = (struct mount3_state *)nfs->mstate; - - if (nfs->refresh_auth) { - /* Mark as true and wait for thread to exit */ - mstate->stop_refresh = _gf_true; - pthread_join (mstate->auth_refresh_thread, NULL); - } - - if (nfs->exports_auth) - mnt3_auth_params_deinit (mstate->auth_params); - - /* Unmount everything and clear mountdict */ - LOCK (&mstate->mountlock); - { - __mnt3svc_umountall (mstate); - dict_unref (mstate->mountdict); - } - UNLOCK (&mstate->mountlock); + if (!nfsx || !nfsx->private) + return; + nfs = (struct nfs_state *)nfsx->private; + mstate = (struct mount3_state *)nfs->mstate; + + if (nfs->refresh_auth) { + /* Mark as true and wait for thread to exit */ + mstate->stop_refresh = _gf_true; + pthread_join(mstate->auth_refresh_thread, NULL); + } + + if (nfs->exports_auth) + mnt3_auth_params_deinit(mstate->auth_params); + + /* Unmount everything and clear mountdict */ + LOCK(&mstate->mountlock); + { + __mnt3svc_umountall(mstate); + dict_unref(mstate->mountdict); + } + UNLOCK(&mstate->mountlock); } rpcsvc_program_t * -mnt3svc_init (xlator_t *nfsx) +mnt3svc_init(xlator_t *nfsx) { - struct mount3_state *mstate = NULL; - struct nfs_state *nfs = NULL; - dict_t *options = NULL; - char *portstr = NULL; - int ret = -1; - pthread_t udp_thread; - - if (!nfsx || !nfsx->private) - return NULL; - - nfs = (struct nfs_state *)nfsx->private; - - gf_msg_debug (GF_MNT, 0, "Initing Mount v3 state"); - mstate = (struct mount3_state *)nfs->mstate; - if (!mstate) { - gf_msg (GF_MNT, GF_LOG_ERROR, 0, NFS_MSG_MNT_STATE_INIT_FAIL, - "Mount v3 state init failed"); - goto err; - } + struct mount3_state *mstate = NULL; + struct nfs_state *nfs = NULL; + dict_t *options = NULL; + char *portstr = NULL; + int ret = -1; + pthread_t udp_thread; + + if (!nfsx || !nfsx->private) + return NULL; - mstate->nfs = nfs; + nfs = (struct nfs_state *)nfsx->private; - mstate->mountdict = dict_new (); - if (!mstate->mountdict) { - gf_msg (GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, - "Failed to setup mount dict. Allocation error."); - goto err; - } + gf_msg_debug(GF_MNT, 0, "Initing Mount v3 state"); + mstate = (struct mount3_state *)nfs->mstate; + if (!mstate) { + gf_msg(GF_MNT, GF_LOG_ERROR, 0, NFS_MSG_MNT_STATE_INIT_FAIL, + "Mount v3 state init failed"); + goto err; + } - if (nfs->exports_auth) { - ret = _mnt3_init_auth_params (mstate); - if (ret < 0) - goto err; + mstate->nfs = nfs; - mstate->authcache = auth_cache_init (nfs->auth_cache_ttl_sec); - if (!mstate->authcache) { - ret = -ENOMEM; - goto err; - } + mstate->mountdict = dict_new(); + if (!mstate->mountdict) { + gf_msg(GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY, + "Failed to setup mount dict. Allocation error."); + goto err; + } - mstate->stop_refresh = _gf_false; /* Allow thread to run */ - ret = gf_thread_create (&mstate->auth_refresh_thread, NULL, - _mnt3_auth_param_refresh_thread, - mstate, "nfsauth"); - if (ret) { - gf_msg_debug (GF_MNT, GF_LOG_DEBUG, - "Thread creation failed"); - } + if (nfs->exports_auth) { + ret = _mnt3_init_auth_params(mstate); + if (ret < 0) + goto err; - } else - gf_msg (GF_MNT, GF_LOG_INFO, 0, NFS_MSG_EXP_AUTH_DISABLED, - "Exports auth has been disabled!"); + mstate->authcache = auth_cache_init(nfs->auth_cache_ttl_sec); + if (!mstate->authcache) { + ret = -ENOMEM; + goto err; + } - mnt3prog.private = mstate; - options = dict_new (); + mstate->stop_refresh = _gf_false; /* Allow thread to run */ + ret = gf_thread_create(&mstate->auth_refresh_thread, NULL, + _mnt3_auth_param_refresh_thread, mstate, + "nfsauth"); + if (ret) { + gf_msg_debug(GF_MNT, GF_LOG_DEBUG, "Thread creation failed"); + } - ret = gf_asprintf (&portstr, "%d", GF_MOUNTV3_PORT); - if (ret == -1) - goto err; + } else + gf_msg(GF_MNT, GF_LOG_INFO, 0, NFS_MSG_EXP_AUTH_DISABLED, + "Exports auth has been disabled!"); - ret = dict_set_dynstr (options, "transport.socket.listen-port", - portstr); - if (ret == -1) - goto err; + mnt3prog.private = mstate; + options = dict_new(); - ret = dict_set_str (options, "transport-type", "socket"); - if (ret == -1) { - gf_msg (GF_NFS, GF_LOG_ERROR, errno, NFS_MSG_DICT_SET_FAILED, - "dict_set_str error"); - goto err; - } + ret = gf_asprintf(&portstr, "%d", GF_MOUNTV3_PORT); + if (ret == -1) + goto err; - if (nfs->allow_insecure) { - ret = dict_set_str (options, "rpc-auth-allow-insecure", "on"); - if (ret == -1) { - gf_msg (GF_NFS, GF_LOG_ERROR, errno, - NFS_MSG_DICT_SET_FAILED, "dict_set_str error"); - goto err; - } - ret = dict_set_str (options, "rpc-auth.ports.insecure", "on"); - if (ret == -1) { - gf_msg (GF_NFS, GF_LOG_ERROR, errno, - NFS_MSG_DICT_SET_FAILED, "dict_set_str error"); - goto err; - } - } + ret = dict_set_dynstr(options, "transport.socket.listen-port", portstr); + if (ret == -1) + goto err; - ret= rpcsvc_create_listeners (nfs->rpcsvc, options, nfsx->name); + ret = dict_set_str(options, "transport-type", "socket"); + if (ret == -1) { + gf_msg(GF_NFS, GF_LOG_ERROR, errno, NFS_MSG_DICT_SET_FAILED, + "dict_set_str error"); + goto err; + } + + if (nfs->allow_insecure) { + ret = dict_set_str(options, "rpc-auth-allow-insecure", "on"); if (ret == -1) { - gf_msg (GF_NFS, GF_LOG_ERROR, errno, - NFS_MSG_LISTENERS_CREATE_FAIL, - "Unable to create listeners"); - dict_unref (options); - goto err; + gf_msg(GF_NFS, GF_LOG_ERROR, errno, NFS_MSG_DICT_SET_FAILED, + "dict_set_str error"); + goto err; } - - if (nfs->mount_udp) { - ret = gf_thread_create (&udp_thread, NULL, mount3udp_thread, - nfsx, "nfsudp"); - if (ret) { - gf_msg_debug (GF_MNT, GF_LOG_DEBUG, - "Thread creation failed"); - } + ret = dict_set_str(options, "rpc-auth.ports.insecure", "on"); + if (ret == -1) { + gf_msg(GF_NFS, GF_LOG_ERROR, errno, NFS_MSG_DICT_SET_FAILED, + "dict_set_str error"); + goto err; + } + } + + ret = rpcsvc_create_listeners(nfs->rpcsvc, options, nfsx->name); + if (ret == -1) { + gf_msg(GF_NFS, GF_LOG_ERROR, errno, NFS_MSG_LISTENERS_CREATE_FAIL, + "Unable to create listeners"); + dict_unref(options); + goto err; + } + + if (nfs->mount_udp) { + ret = gf_thread_create(&udp_thread, NULL, mount3udp_thread, nfsx, + "nfsudp"); + if (ret) { + gf_msg_debug(GF_MNT, GF_LOG_DEBUG, "Thread creation failed"); } - return &mnt3prog; + } + return &mnt3prog; err: - return NULL; + return NULL; } - -rpcsvc_actor_t mnt1svc_actors[MOUNT1_PROC_COUNT] = { - {"NULL", MOUNT1_NULL, mnt3svc_null, NULL, 0, DRC_NA}, - {"MNT", MOUNT1_MNT, NULL, NULL, 0, DRC_NA }, - {"DUMP", MOUNT1_DUMP, mnt3svc_dump, NULL, 0, DRC_NA}, - {"UMNT", MOUNT1_UMNT, mnt3svc_umnt, NULL, 0, DRC_NA}, - {"UMNTALL", MOUNT1_UMNTALL, NULL, NULL, 0, DRC_NA}, - {"EXPORT", MOUNT1_EXPORT, mnt3svc_export, NULL, 0, DRC_NA} -}; - -rpcsvc_program_t mnt1prog = { - .progname = "MOUNT1", - .prognum = MOUNT_PROGRAM, - .progver = MOUNT_V1, - .progport = GF_MOUNTV1_PORT, - .actors = mnt1svc_actors, - .numactors = MOUNT1_PROC_COUNT, - .min_auth = AUTH_NULL, - .synctask = _gf_true, +rpcsvc_actor_t mnt1svc_actors[MOUNT1_PROC_COUNT] = { + {"NULL", MOUNT1_NULL, mnt3svc_null, NULL, 0, DRC_NA}, + {"MNT", MOUNT1_MNT, NULL, NULL, 0, DRC_NA}, + {"DUMP", MOUNT1_DUMP, mnt3svc_dump, NULL, 0, DRC_NA}, + {"UMNT", MOUNT1_UMNT, mnt3svc_umnt, NULL, 0, DRC_NA}, + {"UMNTALL", MOUNT1_UMNTALL, NULL, NULL, 0, DRC_NA}, + {"EXPORT", MOUNT1_EXPORT, mnt3svc_export, NULL, 0, DRC_NA}}; + +rpcsvc_program_t mnt1prog = { + .progname = "MOUNT1", + .prognum = MOUNT_PROGRAM, + .progver = MOUNT_V1, + .progport = GF_MOUNTV1_PORT, + .actors = mnt1svc_actors, + .numactors = MOUNT1_PROC_COUNT, + .min_auth = AUTH_NULL, + .synctask = _gf_true, }; - rpcsvc_program_t * -mnt1svc_init (xlator_t *nfsx) +mnt1svc_init(xlator_t *nfsx) { - struct mount3_state *mstate = NULL; - struct nfs_state *nfs = NULL; - dict_t *options = NULL; - char *portstr = NULL; - int ret = -1; - - if (!nfsx || !nfsx->private) - return NULL; - - nfs = (struct nfs_state *)nfsx->private; - - gf_msg_debug (GF_MNT, GF_LOG_DEBUG, "Initing Mount v1 state"); - mstate = (struct mount3_state *)nfs->mstate; - if (!mstate) { - gf_msg (GF_MNT, GF_LOG_ERROR, EINVAL, - NFS_MSG_MNT_STATE_INIT_FAIL, - "Mount v3 state init failed"); - goto err; - } + struct mount3_state *mstate = NULL; + struct nfs_state *nfs = NULL; + dict_t *options = NULL; + char *portstr = NULL; + int ret = -1; + + if (!nfsx || !nfsx->private) + return NULL; + + nfs = (struct nfs_state *)nfsx->private; - mnt1prog.private = mstate; + gf_msg_debug(GF_MNT, GF_LOG_DEBUG, "Initing Mount v1 state"); + mstate = (struct mount3_state *)nfs->mstate; + if (!mstate) { + gf_msg(GF_MNT, GF_LOG_ERROR, EINVAL, NFS_MSG_MNT_STATE_INIT_FAIL, + "Mount v3 state init failed"); + goto err; + } - options = dict_new (); + mnt1prog.private = mstate; - ret = gf_asprintf (&portstr, "%d", GF_MOUNTV1_PORT); - if (ret == -1) - goto err; + options = dict_new(); - ret = dict_set_dynstr (options, "transport.socket.listen-port", portstr); - if (ret == -1) - goto err; - ret = dict_set_str (options, "transport-type", "socket"); + ret = gf_asprintf(&portstr, "%d", GF_MOUNTV1_PORT); + if (ret == -1) + goto err; + + ret = dict_set_dynstr(options, "transport.socket.listen-port", portstr); + if (ret == -1) + goto err; + ret = dict_set_str(options, "transport-type", "socket"); + if (ret == -1) { + gf_msg(GF_NFS, GF_LOG_ERROR, errno, NFS_MSG_DICT_SET_FAILED, + "dict_set_str error"); + goto err; + } + + if (nfs->allow_insecure) { + ret = dict_set_str(options, "rpc-auth-allow-insecure", "on"); if (ret == -1) { - gf_msg (GF_NFS, GF_LOG_ERROR, errno, NFS_MSG_DICT_SET_FAILED, - "dict_set_str error"); - goto err; + gf_msg(GF_NFS, GF_LOG_ERROR, errno, NFS_MSG_DICT_SET_FAILED, + "dict_set_str error"); + goto err; } - - if (nfs->allow_insecure) { - ret = dict_set_str (options, "rpc-auth-allow-insecure", "on"); - if (ret == -1) { - gf_msg (GF_NFS, GF_LOG_ERROR, errno, - NFS_MSG_DICT_SET_FAILED, - "dict_set_str error"); - goto err; - } - ret = dict_set_str (options, "rpc-auth.ports.insecure", "on"); - if (ret == -1) { - gf_msg (GF_NFS, GF_LOG_ERROR, errno, - NFS_MSG_DICT_SET_FAILED, - "dict_set_str error"); - goto err; - } + ret = dict_set_str(options, "rpc-auth.ports.insecure", "on"); + if (ret == -1) { + gf_msg(GF_NFS, GF_LOG_ERROR, errno, NFS_MSG_DICT_SET_FAILED, + "dict_set_str error"); + goto err; } + } #ifdef IPV6_DEFAULT - ret = dict_set_str (options, "transport.address-family", "inet6"); - if (ret == -1) { - gf_log (GF_NFS, GF_LOG_ERROR, - "dict_set_str error when trying to enable ipv6"); - goto err; - } + ret = dict_set_str(options, "transport.address-family", "inet6"); + if (ret == -1) { + gf_log(GF_NFS, GF_LOG_ERROR, + "dict_set_str error when trying to enable ipv6"); + goto err; + } #endif - ret = rpcsvc_create_listeners (nfs->rpcsvc, options, nfsx->name); - if (ret == -1) { - gf_msg (GF_NFS, GF_LOG_ERROR, errno, - NFS_MSG_LISTENERS_CREATE_FAIL, - "Unable to create listeners"); - dict_unref (options); - goto err; - } + ret = rpcsvc_create_listeners(nfs->rpcsvc, options, nfsx->name); + if (ret == -1) { + gf_msg(GF_NFS, GF_LOG_ERROR, errno, NFS_MSG_LISTENERS_CREATE_FAIL, + "Unable to create listeners"); + dict_unref(options); + goto err; + } - return &mnt1prog; + return &mnt1prog; err: - return NULL; + return NULL; } int -mount_reconfigure_state (xlator_t *nfsx, dict_t *options) +mount_reconfigure_state(xlator_t *nfsx, dict_t *options) { - int ret = -1; - struct nfs_state *nfs = NULL; - struct mount3_state *ms = NULL; - struct mnt3_export *exp = NULL; - struct mnt3_export *texp = NULL; - - if ((!nfsx) || (!options)) - return (-1); - - nfs = (struct nfs_state *)nfs_state (nfsx); - if (!nfs) - return (-1); - - ms = nfs->mstate; - if (!ms) - return (-1); - - /* - * Free() up the old export list. mnt3_init_options() will - * rebuild the export list from scratch. Do it with locking - * to avoid unnecessary race conditions. - */ - LOCK (&ms->mountlock); - list_for_each_entry_safe (exp, texp, &ms->exportlist, explist) { - list_del (&exp->explist); - mnt3_export_free (exp); - } - ret = mnt3_init_options (ms, options); - UNLOCK (&ms->mountlock); - - if (ret < 0) { - gf_msg (GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_RECONF_FAIL, - "Options reconfigure failed"); - return (-1); - } - - return (0); + int ret = -1; + struct nfs_state *nfs = NULL; + struct mount3_state *ms = NULL; + struct mnt3_export *exp = NULL; + struct mnt3_export *texp = NULL; + + if ((!nfsx) || (!options)) + return (-1); + + nfs = (struct nfs_state *)nfs_state(nfsx); + if (!nfs) + return (-1); + + ms = nfs->mstate; + if (!ms) + return (-1); + + /* + * Free() up the old export list. mnt3_init_options() will + * rebuild the export list from scratch. Do it with locking + * to avoid unnecessary race conditions. + */ + LOCK(&ms->mountlock); + list_for_each_entry_safe(exp, texp, &ms->exportlist, explist) + { + list_del(&exp->explist); + mnt3_export_free(exp); + } + ret = mnt3_init_options(ms, options); + UNLOCK(&ms->mountlock); + + if (ret < 0) { + gf_msg(GF_MNT, GF_LOG_ERROR, ret, NFS_MSG_RECONF_FAIL, + "Options reconfigure failed"); + return (-1); + } + + return (0); } |