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