nfs: make it possible to disable nfs.mount-rmtab

When there are many NFS-clients doing very often mount/unmount actions,
the updating of the 'rmtab' can become a bottleneck and cause delays. In
these situations, the output of 'showmount' may be less important than
the responsiveness of the (un)mounting.

By setting 'nfs.mount-rmtab' to the value "/-", the cache file is not
updated anymore, and the entries are only kept in memory.

BUG: 1169317
Change-Id: I40c4d8d754932f86fb2b1b2588843390464c773d
Reported-by: Cyril Peponnet <cyril@peponnet.fr>
Signed-off-by: Niels de Vos <ndevos@redhat.com>
Reviewed-on: http://review.gluster.org/9223
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: soumya k <skoduri@redhat.com>
Reviewed-by: jiffin tony Thottan <jthottan@redhat.com>
Reviewed-by: Kaleb KEITHLEY <kkeithle@redhat.com>
This commit is contained in:
Niels de Vos 2014-12-02 10:54:53 +01:00
parent a675ab96b9
commit 331ef6e1a8
5 changed files with 145 additions and 47 deletions

View File

@ -374,7 +374,7 @@ out:
}
int32_t
gf_store_handle_new (char *path, gf_store_handle_t **handle)
gf_store_handle_new (const char *path, gf_store_handle_t **handle)
{
int32_t ret = -1;
gf_store_handle_t *shandle = NULL;

View File

@ -74,7 +74,7 @@ int32_t
gf_store_save_value (int fd, char *key, char *value);
int32_t
gf_store_handle_new (char *path, gf_store_handle_t **handle);
gf_store_handle_new (const char *path, gf_store_handle_t **handle);
int
gf_store_handle_retrieve (char *path, gf_store_handle_t **handle);

66
tests/bugs/bug-1166862.t Executable file
View File

@ -0,0 +1,66 @@
#!/bin/bash
#
# When nfs.mount-rmtab is disabled, it should not get updated.
#
# Based on: bug-904065.t
#
# count the lines of a file, return 0 if the file does not exist
function count_lines()
{
if [ -e "$1" ]
then
wc -l < $1
else
echo 0
fi
}
. $(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 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
# disable the rmtab by settting it to the magic "/-" value
TEST $CLI volume set $V0 nfs.mount-rmtab /-
# before mounting the rmtab should be empty
EXPECT '0' count_lines $GLUSTERD_WORKDIR/nfs/rmtab
TEST mount_nfs $H0:/$V0 $N0 nolock
EXPECT '0' count_lines $GLUSTERD_WORKDIR/nfs/rmtab
# showmount should list one client
EXPECT '1' showmount --no-headers $H0
# unmount
EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $N0
# after resetting the option, the rmtab should get updated again
TEST $CLI volume reset $V0 nfs.mount-rmtab
# before mounting the rmtab should be empty
EXPECT '0' count_lines $GLUSTERD_WORKDIR/nfs/rmtab
TEST mount_nfs $H0:/$V0 $N0 nolock
EXPECT '2' count_lines $GLUSTERD_WORKDIR/nfs/rmtab
# removing a mount
EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $N0
EXPECT '0' count_lines $GLUSTERD_WORKDIR/nfs/rmtab
cleanup

View File

@ -420,6 +420,25 @@ fail:
gf_store_unlink_tmppath (sh);
}
static gf_boolean_t
mount_open_rmtab (const char *rmtab, gf_store_handle_t **sh)
{
int ret = -1;
/* 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;
}
return _gf_true;
}
/* Read the rmtab into a clean ms->mountlist.
*/
static void
@ -427,16 +446,13 @@ mount_read_rmtab (struct mount3_state *ms)
{
gf_store_handle_t *sh = NULL;
struct nfs_state *nfs = NULL;
int ret;
gf_boolean_t read_rmtab = _gf_false;
nfs = (struct nfs_state *)ms->nfsx->private;
ret = gf_store_handle_new (nfs->rmtab, &sh);
if (ret) {
gf_log (GF_MNT, GF_LOG_WARNING, "Failed to open '%s'",
nfs->rmtab);
read_rmtab = mount_open_rmtab (nfs->rmtab, &sh);
if (!read_rmtab)
return;
}
if (gf_store_lock (sh)) {
gf_log (GF_MNT, GF_LOG_WARNING, "Failed to lock '%s'",
@ -456,6 +472,7 @@ out:
* The rmtab could be empty, or it can exists and have been updated by a
* different storage server without our knowing.
*
* 0. if opening the nfs->rmtab fails, return gracefully
* 1. takes the store_handle lock on the current rmtab
* - blocks if an other storage server rewrites the rmtab at the same time
* 2. [if new_rmtab] takes the store_handle lock on the new rmtab
@ -474,17 +491,15 @@ mount_rewrite_rmtab (struct mount3_state *ms, char *new_rmtab)
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;
ret = gf_store_handle_new (nfs->rmtab, &sh);
if (ret) {
gf_log (GF_MNT, GF_LOG_WARNING, "Failed to open '%s'",
nfs->rmtab);
got_old_rmtab = mount_open_rmtab (nfs->rmtab, &sh);
if (!got_old_rmtab && !new_rmtab)
return;
}
if (gf_store_lock (sh)) {
if (got_old_rmtab && gf_store_lock (sh)) {
gf_log (GF_MNT, GF_LOG_WARNING, "Not rewriting '%s'",
nfs->rmtab);
goto free_sh;
@ -506,7 +521,8 @@ mount_rewrite_rmtab (struct mount3_state *ms, char *new_rmtab)
}
/* always read the currently used rmtab */
__mount_read_rmtab (sh, &ms->mountlist, _gf_true);
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 */
@ -533,9 +549,11 @@ free_nsh:
if (new_rmtab)
gf_store_handle_destroy (nsh);
unlock_sh:
gf_store_unlock (sh);
if (got_old_rmtab)
gf_store_unlock (sh);
free_sh:
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.
@ -559,6 +577,7 @@ mnt3svc_update_mountlist (struct mount3_state *ms, rpcsvc_request_t *req,
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;
@ -570,12 +589,7 @@ mnt3svc_update_mountlist (struct mount3_state *ms, rpcsvc_request_t *req,
nfs = (struct nfs_state *)ms->nfsx->private;
ret = gf_store_handle_new (nfs->rmtab, &sh);
if (ret) {
gf_log (GF_MNT, GF_LOG_WARNING, "Failed to open '%s'",
nfs->rmtab);
goto free_err;
}
update_rmtab = mount_open_rmtab (nfs->rmtab, &sh);
strncpy (me->exname, expname, MNTPATHLEN);
/* Sometimes we don't care about the full path
@ -595,7 +609,7 @@ mnt3svc_update_mountlist (struct mount3_state *ms, rpcsvc_request_t *req,
*/
ret = rpcsvc_transport_peername (req->trans, me->hostname, MNTPATHLEN);
if (ret == -1)
goto free_err2;
goto free_err;
colon = strrchr (me->hostname, ':');
if (colon) {
@ -604,10 +618,10 @@ mnt3svc_update_mountlist (struct mount3_state *ms, rpcsvc_request_t *req,
LOCK (&ms->mountlock);
{
/* in case locking fails, we just don't write the rmtab */
if (gf_store_lock (sh)) {
if (update_rmtab && gf_store_lock (sh)) {
gf_log (GF_MNT, GF_LOG_WARNING, "Failed to lock '%s'"
", changes will not be written", nfs->rmtab);
} else {
} else if (update_rmtab) {
__mount_read_rmtab (sh, &ms->mountlist, _gf_false);
}
@ -623,19 +637,19 @@ mnt3svc_update_mountlist (struct mount3_state *ms, rpcsvc_request_t *req,
__mountdict_insert (ms, me);
/* only write the rmtab in case it was locked */
if (gf_store_locked_local (sh))
if (update_rmtab && gf_store_locked_local (sh))
__mount_rewrite_rmtab (ms, sh);
}
dont_add:
if (gf_store_locked_local (sh))
if (update_rmtab && gf_store_locked_local (sh))
gf_store_unlock (sh);
UNLOCK (&ms->mountlock);
free_err2:
gf_store_handle_destroy (sh);
free_err:
if (update_rmtab)
gf_store_handle_destroy (sh);
if (ret == -1)
GF_FREE (me);
@ -2305,27 +2319,25 @@ mnt3svc_umount (struct mount3_state *ms, char *dirpath, char *hostname)
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;
ret = gf_store_handle_new (nfs->rmtab, &sh);
if (ret) {
gf_log (GF_MNT, GF_LOG_WARNING, "Failed to open '%s'",
nfs->rmtab);
return 0;
}
ret = gf_store_lock (sh);
if (ret) {
goto out_free;
update_rmtab = mount_open_rmtab (nfs->rmtab, &sh);
if (update_rmtab) {
ret = gf_store_lock (sh);
if (ret)
goto out_free;
}
LOCK (&ms->mountlock);
{
__mount_read_rmtab (sh, &ms->mountlist, _gf_false);
if (update_rmtab)
__mount_read_rmtab (sh, &ms->mountlist, _gf_false);
if (list_empty (&ms->mountlist)) {
ret = 0;
goto out_unlock;
@ -2357,13 +2369,20 @@ mnt3svc_umount (struct mount3_state *ms, char *dirpath, char *hostname)
list_del (&me->mlist);
GF_FREE (me);
__mount_rewrite_rmtab (ms, sh);
if (update_rmtab)
__mount_rewrite_rmtab (ms, sh);
}
out_unlock:
UNLOCK (&ms->mountlock);
gf_store_unlock (sh);
if (update_rmtab)
gf_store_unlock (sh);
out_free:
gf_store_handle_destroy (sh);
if (update_rmtab)
gf_store_handle_destroy (sh);
return ret;
}

View File

@ -948,6 +948,12 @@ nfs_init_state (xlator_t *this)
gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse dict");
goto free_foppool;
}
/* check if writing the rmtab is disabled*/
if (nfs->rmtab && strcmp ("/-", nfs->rmtab) == 0) {
GF_FREE (nfs->rmtab);
nfs->rmtab = NULL;
}
}
/* support both options rpc-auth.ports.insecure and
@ -1176,7 +1182,13 @@ nfs_reconfigure_state (xlator_t *this, dict_t *options)
}
gf_path_strip_trailing_slashes (rmtab);
}
if (strcmp (nfs->rmtab, rmtab) != 0) {
/* check if writing the rmtab is disabled*/
if (strcmp ("/-", rmtab) == 0) {
GF_FREE (nfs->rmtab);
nfs->rmtab = NULL;
gf_log (GF_NFS, GF_LOG_INFO,
"Disabled writing of nfs.mount-rmtab");
} else if (!nfs->rmtab || strcmp (nfs->rmtab, rmtab) != 0) {
mount_rewrite_rmtab (nfs->mstate, rmtab);
gf_log (GF_NFS, GF_LOG_INFO,
"Reconfigured nfs.mount-rmtab path: %s",
@ -1914,7 +1926,8 @@ struct volume_options options[] = {
"list all the NFS-clients that have connected "
"through the MOUNT protocol. If this is on shared "
"storage, all GlusterFS servers will update and "
"output (with 'showmount') the same list."
"output (with 'showmount') the same list. Set to "
"\"/-\" to disable."
},
{ .key = {OPT_SERVER_RPC_STATD},
.type = GF_OPTION_TYPE_PATH,