diff options
-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; |