diff options
author | Bipin Kunal <bkunal@redhat.com> | 2016-06-07 18:30:16 +0530 |
---|---|---|
committer | Niels de Vos <ndevos@redhat.com> | 2016-06-09 11:40:25 -0700 |
commit | 3bd4b1529817d4ce40c2b9654044e6230cbf7233 (patch) | |
tree | b095f2ed5e5f14992cec6f977d9ca39d672f88e7 | |
parent | ab88bad8fe40bd9a9106b02857abfdc51a3284cd (diff) |
nfs: build exportlist with multiple groupnodes
The EXPORT procedure of the MOUNT protocol does not correctly create
structures for the 'groupnodes' in the reply. Each 'groupnode' should be
a single entry in the 'nfs.rpc-auth-allow' volume option. Because the
value is handled as a single string, the encoding of the
groupnode->gr_name fails when the value of the volume option is longer
than 255 characters.
In the error case, encoding the EXPORTS reply fails, and the waiting
'showmount' command will not receive a reply and times out.
Splitting the allowed entries and creating a groupnode for each one
prevents the too long ->gr_name. This is following the structures for
the EXPORTS reply in the MOUNT protocol more correctly as well. Note
that the contents of ->gr_name is expected to be server dependent.
Change-Id: Ibbabad581cc9aa00feb80fbbc851a1b10b28383d
BUG: 1343286
Signed-off-by: Niels de Vos <ndevos@redhat.com>
Reviewed-on: http://review.gluster.org/14667
Smoke: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: bipin kunal <kunalbipin@gmail.com>
NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
Reviewed-by: jiffin tony Thottan <jthottan@redhat.com>
CentOS-regression: Gluster Build System <jenkins@build.gluster.com>
-rw-r--r-- | tests/bugs/nfs/showmount-many-clients.t | 41 | ||||
-rw-r--r-- | xlators/nfs/server/src/mount3.c | 84 |
2 files changed, 107 insertions, 18 deletions
diff --git a/tests/bugs/nfs/showmount-many-clients.t b/tests/bugs/nfs/showmount-many-clients.t new file mode 100644 index 00000000000..f1b6859d528 --- /dev/null +++ b/tests/bugs/nfs/showmount-many-clients.t @@ -0,0 +1,41 @@ +#!/bin/bash +# +# The nfs.rpc-auth-allow volume option is used to generate the list of clients +# that are displayed as able to mount the export. The "group" in the export +# should be a list of all clients, identified by "name". In previous versions, +# the "name" was the copied string from nfs.rpc-auth-allow. This is not +# correct, as the volume option should be parsed and split into different +# groups. +# +# When the single string is passed, this testcase fails when the +# nfs.rpc-auth-allow volume option is longer than 256 characters. By splitting +# the groups into their own structures, this testcase passes. +# + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../nfs.rc +. $(dirname $0)/../../volume.rc + +cleanup + +TEST glusterd +TEST pidof glusterd + +TEST $CLI volume create $V0 $H0:$B0/brick1 +EXPECT 'Created' volinfo_field $V0 'Status' +TEST $CLI volume set $V0 nfs.disable false + +CLIENTS=$(echo 127.0.0.{1..128} | tr ' ' ,) +TEST $CLI volume set $V0 nfs.rpc-auth-allow ${CLIENTS} +TEST $CLI volume set $V0 nfs.rpc-auth-reject all + +TEST $CLI volume start $V0; +EXPECT 'Started' volinfo_field $V0 'Status' + +# glusterfs/nfs needs some time to start up in the background +EXPECT_WITHIN $NFS_EXPORT_TIMEOUT 1 is_nfs_export_available + +# showmount should not timeout (no reply is sent on error) +TEST showmount -e $H0 + +cleanup diff --git a/xlators/nfs/server/src/mount3.c b/xlators/nfs/server/src/mount3.c index cb8b9a1af2f..580f92af4b7 100644 --- a/xlators/nfs/server/src/mount3.c +++ b/xlators/nfs/server/src/mount3.c @@ -2632,27 +2632,75 @@ mnt3_xlchildren_to_exports (rpcsvc_t *svc, struct mount3_state *ms) } strcpy (elist->ex_dir, ent->expname); - addrstr = rpcsvc_volume_allowed (svc->options, - ent->vol->name); - 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; - } - /*This check has to be done after checking - * elist->ex_groups allocation check to avoid resource leak; - */ - if (addrstr) - addrstr = gf_strdup (addrstr); - else + 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 + 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; - if (!addrstr) { - goto free_list; + elist->ex_groups->gr_name = addrstr; } - elist->ex_groups->gr_name = addrstr; + if (prev) { prev->ex_next = elist; prev = elist; |