diff options
Diffstat (limited to 'xlators/nfs')
| -rw-r--r-- | xlators/nfs/server/src/exports.h | 2 | ||||
| -rw-r--r-- | xlators/nfs/server/src/mount3.c | 11 | ||||
| -rw-r--r-- | xlators/nfs/server/src/mount3udp_svc.c | 10 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs-common.c | 6 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs.c | 26 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs3.c | 49 |
6 files changed, 99 insertions, 5 deletions
diff --git a/xlators/nfs/server/src/exports.h b/xlators/nfs/server/src/exports.h index bc9af2f0b8b..0079b9a3deb 100644 --- a/xlators/nfs/server/src/exports.h +++ b/xlators/nfs/server/src/exports.h @@ -22,7 +22,7 @@ #define GF_EXP GF_NFS"-exports" #define NETGROUP_REGEX_PATTERN "(@([a-zA-Z0-9\\(=, .])+)())" -#define HOSTNAME_REGEX_PATTERN "[[:space:]]([a-zA-Z0-9.\\(=,*/)-]+)" +#define HOSTNAME_REGEX_PATTERN "[[:space:]]([a-zA-Z0-9.\\(=,*/:)-]+)" #define OPTIONS_REGEX_PATTERN "([a-zA-Z0-9=\\.]+)" #define NETGROUP_MAX_LEN 128 diff --git a/xlators/nfs/server/src/mount3.c b/xlators/nfs/server/src/mount3.c index b7350385c32..57d1874c79a 100644 --- a/xlators/nfs/server/src/mount3.c +++ b/xlators/nfs/server/src/mount3.c @@ -1896,7 +1896,7 @@ _mnt3_get_host_from_peer (const char *peer_addr) size_t host_len = 0; char *colon = NULL; - colon = strchr (peer_addr, ':'); + colon = strrchr (peer_addr, ':'); if (!colon) { gf_msg (GF_MNT, GF_LOG_ERROR, 0, NFS_MSG_BAD_PEER, "Bad peer %s", peer_addr); @@ -4127,6 +4127,15 @@ mnt1svc_init (xlator_t *nfsx) } } +#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; + } +#endif + ret = rpcsvc_create_listeners (nfs->rpcsvc, options, nfsx->name); if (ret == -1) { gf_msg (GF_NFS, GF_LOG_ERROR, errno, diff --git a/xlators/nfs/server/src/mount3udp_svc.c b/xlators/nfs/server/src/mount3udp_svc.c index e8e226e953e..536a45ede3d 100644 --- a/xlators/nfs/server/src/mount3udp_svc.c +++ b/xlators/nfs/server/src/mount3udp_svc.c @@ -133,7 +133,15 @@ mountudp_program_3(struct svc_req *rqstp, register SVCXPRT *transp) mountres3 *res = NULL; struct sockaddr_in *sin = NULL; - sin = svc_getcaller (transp); + sin = (struct sockaddr_in *)svc_getcaller (transp); + /* 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. + * + * Let's make sure that it's actually an IPv4 address. + */ + GF_ASSERT (sin->sin_family == AF_INET); + inet_ntop (AF_INET, &sin->sin_addr, mnthost, INET_ADDRSTRLEN+1); switch (rqstp->rq_proc) { diff --git a/xlators/nfs/server/src/nfs-common.c b/xlators/nfs/server/src/nfs-common.c index af37f6b264c..a39a0e6ee3a 100644 --- a/xlators/nfs/server/src/nfs-common.c +++ b/xlators/nfs/server/src/nfs-common.c @@ -138,8 +138,12 @@ nfs_loc_fill (loc_t *loc, inode_t *inode, inode_t *parent, char *path) gf_uuid_copy (loc->gfid, inode->gfid); } - if (parent) + if (parent) { loc->parent = inode_ref (parent); + if (!gf_uuid_is_null (parent->gfid)) { + gf_uuid_copy (loc->pargfid, parent->gfid); + } + } if (path) { loc->path = gf_strdup (path); diff --git a/xlators/nfs/server/src/nfs.c b/xlators/nfs/server/src/nfs.c index ddfa89dab11..d5087f195ca 100644 --- a/xlators/nfs/server/src/nfs.c +++ b/xlators/nfs/server/src/nfs.c @@ -204,6 +204,9 @@ nfs_program_register_portmap_all (struct nfs_state *nfs) if (nfs->override_portnum) prog->progport = nfs->override_portnum; (void) rpcsvc_program_register_portmap (prog, prog->progport); +#ifdef IPV6_DEFAULT + (void) rpcsvc_program_register_rpcbind6 (prog, prog->progport); +#endif } return (0); @@ -339,6 +342,17 @@ nfs_init_versions (struct nfs_state *nfs, xlator_t *this) if (version->required) goto err; } +#ifdef IPV6_DEFAULT + ret = rpcsvc_program_register_rpcbind6 (prog, + prog->progport); + if (ret == -1) { + gf_msg (GF_NFS, GF_LOG_ERROR, 0, + NFS_MSG_PGM_REG_FAIL, + "Program (ipv6) %s registration failed", + prog->progname); + goto err; + } +#endif } } @@ -901,6 +915,16 @@ nfs_init_state (xlator_t *this) } } +#ifdef IPV6_DEFAULT + ret = dict_set_str (this->options, "transport.address-family", + "inet6"); + if (ret == -1) { + gf_log (GF_NFS, GF_LOG_ERROR, "dict_set_str error"); + goto free_foppool; + } +#endif + + /* Right only socket support exists between nfs client and * gluster nfs, so we can set default value as socket */ @@ -2019,7 +2043,7 @@ struct volume_options options[] = { }, { .key = {"nfs.mount-rmtab"}, .type = GF_OPTION_TYPE_PATH, - .default_value = NFS_DATADIR "/rmtab", + .default_value = "/-", .description = "Set the location of the cache file that is used to " "list all the NFS-clients that have connected " "through the MOUNT protocol. If this is on shared " diff --git a/xlators/nfs/server/src/nfs3.c b/xlators/nfs/server/src/nfs3.c index 64287c5b1bd..5aa9ea4e76e 100644 --- a/xlators/nfs/server/src/nfs3.c +++ b/xlators/nfs/server/src/nfs3.c @@ -372,6 +372,28 @@ out: } while (0) \ +/* + * This macro checks if the volume is started or not. + * If it is not started, it closes the client connection & logs it. + * + * Why do we do this? + * + * There is a "race condition" where gNFSd may start listening for RPC requests + * prior to the volume being started. Presumably, that is why this macro exists + * in the first place. In the NFS kernel client (specifically Linux's NFS + * kernel client), they establish a TCP connection to our endpoint and + * (re-)send requests. If we ignore the request, and return nothing back, + * the NFS kernel client waits forever for our response. If for some reason, + * the TCP connection were to die, and re-establish, the requests are + * retransmitted and everything begins working as expected + * + * Now, this is clearly bad behavior on the client side, + * but in order to make every user's life easier, + * gNFSd should simply disconnect the TCP connection if it sees requests + * before it is ready to accept them. + * + */ + #define nfs3_volume_started_check(nf3stt, vlm, rtval, erlbl) \ do { \ if ((!nfs_subvolume_started (nfs_state (nf3stt->nfsx), vlm))){\ @@ -379,11 +401,32 @@ out: NFS_MSG_VOL_DISABLE, \ "Volume is disabled: %s", \ vlm->name); \ + nfs3_disconnect_transport (req->trans); \ rtval = RPCSVC_ACTOR_IGNORE; \ goto erlbl; \ } \ } while (0) \ +void +nfs3_disconnect_transport (rpc_transport_t *transport) +{ + int ret = 0; + + GF_VALIDATE_OR_GOTO (GF_NFS3, transport, out); + + ret = rpc_transport_disconnect (transport); + if (ret != 0) { + gf_log (GF_NFS3, GF_LOG_WARNING, + "Unable to close client connection to %s.", + transport->peerinfo.identifier); + } else { + gf_log (GF_NFS3, GF_LOG_WARNING, + "Closed client connection to %s.", + transport->peerinfo.identifier); + } +out: + return; +} int nfs3_export_sync_trusted (struct nfs3_state *nfs3, uuid_t exportid) @@ -778,6 +821,12 @@ nfs3svc_getattr_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, cs = frame->local; if (op_ret == -1) { + /* Prevent crashes for the case where this call fails + * and buf is left in a NULL state, yet the op_errno == 0. + */ + if (!buf && op_errno == 0) { + op_errno = EIO; + } status = nfs3_cbk_errno_status (op_ret, op_errno); } |
