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:
parent
a675ab96b9
commit
331ef6e1a8
@ -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;
|
||||
|
@ -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
66
tests/bugs/bug-1166862.t
Executable 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
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user