summaryrefslogtreecommitdiffstats
path: root/xlators/nfs/server/src/nfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/nfs/server/src/nfs.c')
-rw-r--r--xlators/nfs/server/src/nfs.c781
1 files changed, 707 insertions, 74 deletions
diff --git a/xlators/nfs/server/src/nfs.c b/xlators/nfs/server/src/nfs.c
index a48e11499..75c8fe44e 100644
--- a/xlators/nfs/server/src/nfs.c
+++ b/xlators/nfs/server/src/nfs.c
@@ -2,19 +2,10 @@
Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.com>
This file is part of GlusterFS.
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
*/
/* This is the primary translator source for NFS.
@@ -41,6 +32,207 @@
#include "nfs-mem-types.h"
#include "nfs3-helpers.h"
#include "nlm4.h"
+#include "options.h"
+#include "acl3.h"
+#include "rpc-drc.h"
+
+#define STRINGIFY(val) #val
+#define TOSTRING(val) STRINGIFY(val)
+
+#define OPT_SERVER_AUX_GIDS "nfs.server-aux-gids"
+#define OPT_SERVER_GID_CACHE_TIMEOUT "nfs.server.aux-gid-timeout"
+
+/* TODO: DATADIR should be based on configure's $(localstatedir) */
+#define DATADIR "/var/lib/glusterd"
+#define NFS_DATADIR DATADIR "/nfs"
+
+/* Forward declaration */
+int nfs_add_initer (struct list_head *list, nfs_version_initer_t init);
+
+static int
+nfs_init_version (xlator_t *this, nfs_version_initer_t init)
+{
+ int ret = -1;
+ struct nfs_initer_list *version = NULL;
+ struct nfs_initer_list *tmp = NULL;
+ rpcsvc_program_t *prog = NULL;
+ struct list_head *versions = NULL;
+ struct nfs_state *nfs = NULL;
+ gf_boolean_t found = _gf_false;
+
+ if ((!this) || (!this->private) || (!init))
+ return (-1);
+
+ nfs = (struct nfs_state *)this->private;
+
+ ret = nfs_add_initer (&nfs->versions, init);
+ if (ret == -1) {
+ gf_log (GF_NFS, GF_LOG_ERROR,
+ "Failed to add protocol initializer");
+ goto err;
+ }
+
+ versions = &nfs->versions;
+ list_for_each_entry_safe (version, tmp, versions, list) {
+ prog = version->program;
+ if (version->init == init) {
+ prog = init(this);
+ if (!prog) {
+ ret = -1;
+ goto err;
+ }
+ version->program = prog;
+ found = _gf_true;
+ break;
+ }
+ }
+
+ /* program not added */
+ if (!found) {
+ gf_log (GF_NFS, GF_LOG_ERROR,
+ "Program: %s NOT found", prog->progname);
+ goto err;
+ }
+
+ /* Check if nfs.port is configured */
+ if (nfs->override_portnum)
+ prog->progport = nfs->override_portnum;
+
+ gf_log (GF_NFS, GF_LOG_DEBUG, "Starting program: %s", prog->progname);
+
+ ret = rpcsvc_program_register (nfs->rpcsvc, prog);
+ if (ret == -1) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Program: %s init failed",
+ prog->progname);
+ goto err;
+ }
+
+ /* Registration with portmapper is disabled, Nothing to do */
+ if (!nfs->register_portmap)
+ goto err;
+
+ ret = rpcsvc_program_register_portmap (prog, prog->progport);
+ if (ret == -1) {
+ gf_log (GF_NFS, GF_LOG_ERROR,
+ "Program %s registration failed",
+ prog->progname);
+ goto err;
+ }
+ ret = 0; /* All well */
+err:
+ return ret;
+}
+
+static int
+nfs_deinit_version (struct nfs_state *nfs, nfs_version_initer_t init)
+{
+ int ret = -1;
+ struct nfs_initer_list *version = NULL;
+ struct nfs_initer_list *tmp = NULL;
+ rpcsvc_program_t *prog = NULL;
+ struct list_head *versions = NULL;
+
+ if ((!nfs) || (!init))
+ return (-1);
+
+ versions = &nfs->versions;
+ list_for_each_entry_safe (version, tmp, versions, list) {
+ prog = version->program;
+ if (version->init == init) {
+ prog = version->program;
+ ret = rpcsvc_program_unregister (nfs->rpcsvc, prog);
+ if (ret != 0)
+ return (-1);
+ list_del (&version->list);
+ GF_FREE (version);
+ return (0);
+ }
+ }
+
+ return (-1);
+}
+
+static int
+nfs_reconfigure_acl3 (xlator_t *this)
+{
+ struct nfs_state *nfs = NULL;
+
+ if ((!this) || (!this->private))
+ return (-1);
+
+ nfs = (struct nfs_state *)this->private;
+
+ /* ACL is enabled */
+ if (nfs->enable_acl)
+ return nfs_init_version (this, acl3svc_init);
+
+ /* ACL is disabled */
+ return nfs_deinit_version (nfs, acl3svc_init);
+}
+
+static int
+nfs_reconfigure_nlm4 (xlator_t *this)
+{
+ struct nfs_state *nfs = NULL;
+
+ if ((!this) || (!this->private))
+ return (-1);
+
+ nfs = (struct nfs_state *)this->private;
+
+ /* NLM is enabled */
+ if (nfs->enable_nlm)
+ return nfs_init_version (this, nlm4svc_init);
+
+ /* NLM is disabled */
+ return nfs_deinit_version (nfs, nlm4svc_init);
+}
+
+static int
+nfs_program_register_portmap_all (struct nfs_state *nfs)
+{
+ struct list_head *versions = NULL;
+ struct nfs_initer_list *version = NULL;
+ struct nfs_initer_list *tmp = NULL;
+ rpcsvc_program_t *prog = NULL;
+
+ if (nfs == NULL)
+ return (-1);
+
+ versions = &nfs->versions;
+ list_for_each_entry_safe (version, tmp, versions, list) {
+ prog = version->program;
+ if (prog == NULL)
+ continue;
+ if (nfs->override_portnum)
+ prog->progport = nfs->override_portnum;
+ (void) rpcsvc_program_register_portmap (prog, prog->progport);
+ }
+
+ return (0);
+}
+
+static int
+nfs_program_unregister_portmap_all (struct nfs_state *nfs)
+{
+ struct list_head *versions = NULL;
+ struct nfs_initer_list *version = NULL;
+ struct nfs_initer_list *tmp = NULL;
+ rpcsvc_program_t *prog = NULL;
+
+ if (nfs == NULL)
+ return (-1);
+
+ versions = &nfs->versions;
+ list_for_each_entry_safe (version, tmp, versions, list) {
+ prog = version->program;
+ if (prog == NULL)
+ continue;
+ (void) rpcsvc_program_unregister_portmap (prog);
+ }
+
+ return (0);
+}
/* Every NFS version must call this function with the init function
* for its particular version.
@@ -118,7 +310,7 @@ nfs_init_versions (struct nfs_state *nfs, xlator_t *this)
ret = -1;
goto err;
}
-// prog->actorxl = this;
+
version->program = prog;
if (nfs->override_portnum)
prog->progport = nfs->override_portnum;
@@ -127,17 +319,21 @@ nfs_init_versions (struct nfs_state *nfs, xlator_t *this)
ret = rpcsvc_program_register (nfs->rpcsvc, prog);
if (ret == -1) {
- gf_log (GF_NFS, GF_LOG_ERROR, "Program init failed");
+ gf_log (GF_NFS, GF_LOG_ERROR, "Program: %s init failed",
+ prog->progname);
goto err;
}
- if (rpcsvc_register_portmap_enabled(nfs->rpcsvc)) {
+ if (nfs->register_portmap) {
ret = rpcsvc_program_register_portmap (prog,
prog->progport);
if (ret == -1) {
- gf_log (GF_NFS, GF_LOG_ERROR, "Program registration failed");
+ gf_log (GF_NFS, GF_LOG_ERROR,
+ "Program %s registration failed",
+ prog->progname);
goto err;
}
}
+
}
ret = 0;
@@ -154,22 +350,22 @@ nfs_add_all_initiators (struct nfs_state *nfs)
/* Add the initializers for all versions. */
ret = nfs_add_initer (&nfs->versions, mnt3svc_init);
if (ret == -1) {
- gf_log (GF_NFS, GF_LOG_ERROR, "Failed to add protocol"
- " initializer");
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to add "
+ "MOUNT3 protocol initializer");
goto ret;
}
ret = nfs_add_initer (&nfs->versions, mnt1svc_init);
if (ret == -1) {
- gf_log (GF_NFS, GF_LOG_ERROR, "Failed to add protocol"
- " initializer");
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to add "
+ "MOUNT1 protocol initializer");
goto ret;
}
ret = nfs_add_initer (&nfs->versions, nfs3svc_init);
if (ret == -1) {
- gf_log (GF_NFS, GF_LOG_ERROR, "Failed to add protocol"
- " initializer");
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to add "
+ "NFS3 protocol initializer");
goto ret;
}
@@ -182,6 +378,15 @@ nfs_add_all_initiators (struct nfs_state *nfs)
}
}
+ if (nfs->enable_acl == _gf_true) {
+ ret = nfs_add_initer (&nfs->versions, acl3svc_init);
+ if (ret == -1) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to add "
+ "ACL protocol initializer");
+ goto ret;
+ }
+ }
+
ret = 0;
ret:
return ret;
@@ -515,10 +720,11 @@ nfs_init_state (xlator_t *this)
if (!this)
return NULL;
- if ((!this->children) || (!this->children->xlator)) {
- gf_log (GF_NFS, GF_LOG_ERROR, "nfs must have at least one"
- " child subvolume");
- return NULL;
+ if (!this->children) {
+ gf_log (GF_NFS, GF_LOG_INFO,
+ "NFS is manually disabled: Exiting");
+ /* Nothing for nfs process to do, exit cleanly */
+ kill (getpid (), SIGTERM);
}
nfs = GF_CALLOC (1, sizeof (*nfs), gf_nfs_mt_nfs_state);
@@ -574,19 +780,17 @@ nfs_init_state (xlator_t *this)
}
nfs->enable_nlm = _gf_true;
- if (!dict_get_str (this->options, "nfs.nlm", &optstr)) {
-
- ret = gf_string2boolean (optstr, &boolt);
- if (ret < 0) {
- gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse"
- " bool string");
- goto free_foppool;
- }
+ ret = dict_get_str_boolean (this->options, "nfs.nlm", _gf_true);
+ if (ret == _gf_false) {
+ gf_log (GF_NFS, GF_LOG_INFO, "NLM is manually disabled");
+ nfs->enable_nlm = _gf_false;
+ }
- if (boolt == _gf_false) {
- gf_log (GF_NFS, GF_LOG_INFO, "NLM is manually disabled");
- nfs->enable_nlm = _gf_false;
- }
+ nfs->enable_acl = _gf_true;
+ ret = dict_get_str_boolean (this->options, "nfs.acl", _gf_true);
+ if (ret == _gf_false) {
+ gf_log (GF_NFS, GF_LOG_INFO, "ACL is manually disabled");
+ nfs->enable_acl = _gf_false;
}
nfs->enable_ino32 = 0;
@@ -651,6 +855,34 @@ nfs_init_state (xlator_t *this)
}
}
+ nfs->mount_udp = 0;
+ if (dict_get(this->options, "nfs.mount-udp")) {
+ ret = dict_get_str (this->options, "nfs.mount-udp", &optstr);
+ if (ret == -1) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse dict");
+ goto free_foppool;
+ }
+
+ ret = gf_string2boolean (optstr, &boolt);
+ if (ret < 0) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse bool "
+ "string");
+ goto free_foppool;
+ }
+
+ if (boolt == _gf_true)
+ nfs->mount_udp = 1;
+ }
+
+ nfs->rmtab = gf_strdup (NFS_DATADIR "/rmtab");
+ if (dict_get(this->options, "nfs.mount-rmtab")) {
+ ret = dict_get_str (this->options, "nfs.mount-rmtab", &nfs->rmtab);
+ if (ret == -1) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse dict");
+ goto free_foppool;
+ }
+ }
+
/* support both options rpc-auth.ports.insecure and
* rpc-auth-allow-insecure for backward compatibility
*/
@@ -711,6 +943,16 @@ nfs_init_state (xlator_t *this)
}
}
+ GF_OPTION_INIT (OPT_SERVER_AUX_GIDS, nfs->server_aux_gids,
+ bool, free_foppool);
+ GF_OPTION_INIT (OPT_SERVER_GID_CACHE_TIMEOUT, nfs->server_aux_gids_max_age,
+ uint32, free_foppool);
+
+ if (gid_cache_init(&nfs->gid_cache, nfs->server_aux_gids_max_age) < 0) {
+ gf_log(GF_NFS, GF_LOG_ERROR, "Failed to initialize group cache.");
+ goto free_foppool;
+ }
+
if (stat("/sbin/rpc.statd", &stbuf) == -1) {
gf_log (GF_NFS, GF_LOG_WARNING, "/sbin/rpc.statd not found. "
"Disabling NLM");
@@ -724,8 +966,11 @@ nfs_init_state (xlator_t *this)
goto free_foppool;
}
+ nfs->register_portmap = rpcsvc_register_portmap_enabled (nfs->rpcsvc);
+
this->private = (void *)nfs;
INIT_LIST_HEAD (&nfs->versions);
+ nfs->generation = 1965;
ret = 0;
@@ -744,6 +989,243 @@ free_rpcsvc:
return nfs;
}
+int
+nfs_drc_init (xlator_t *this)
+{
+ int ret = -1;
+ rpcsvc_t *svc = NULL;
+
+ svc = ((struct nfs_state *)(this->private))->rpcsvc;
+ if (!svc)
+ goto out;
+
+ ret = rpcsvc_drc_init (svc, this->options);
+
+ out:
+ return ret;
+}
+
+int
+nfs_reconfigure_state (xlator_t *this, dict_t *options)
+{
+ int ret = 0;
+ int keyindx = 0;
+ char *optstr = NULL;
+ gf_boolean_t optbool;
+ uint32_t optuint32;
+ struct nfs_state *nfs = NULL;
+ char *blacklist_keys[] = {
+ "nfs.port",
+ "nfs.transport-type",
+ "nfs.mem-factor",
+ NULL};
+
+ GF_VALIDATE_OR_GOTO (GF_NFS, this, out);
+ GF_VALIDATE_OR_GOTO (GF_NFS, this->private, out);
+ GF_VALIDATE_OR_GOTO (GF_NFS, options, out);
+
+ nfs = (struct nfs_state *)this->private;
+
+ /* Black listed options can't be reconfigured, they need
+ * NFS to be restarted. There are two cases 1. SET 2. UNSET.
+ * 1. SET */
+ while (blacklist_keys[keyindx]) {
+ if (dict_get (options, blacklist_keys[keyindx])) {
+ gf_log (GF_NFS, GF_LOG_ERROR,
+ "Reconfiguring %s needs NFS restart",
+ blacklist_keys[keyindx]);
+ goto out;
+ }
+ keyindx ++;
+ }
+
+ /* UNSET for nfs.mem-factor */
+ if ((!dict_get (options, "nfs.mem-factor")) &&
+ (nfs->memfactor != GF_NFS_DEFAULT_MEMFACTOR)) {
+ gf_log (GF_NFS, GF_LOG_INFO,
+ "Reconfiguring nfs.mem-factor needs NFS restart");
+ goto out;
+ }
+
+ /* UNSET for nfs.port */
+ if ((!dict_get (options, "nfs.port")) &&
+ (nfs->override_portnum)) {
+ gf_log (GF_NFS, GF_LOG_ERROR,
+ "Reconfiguring nfs.port needs NFS restart");
+ goto out;
+ }
+
+ /* reconfig nfs.mount-rmtab */
+ optstr = NFS_DATADIR "/rmtab";
+ if (dict_get (options, "nfs.mount-rmtab")) {
+ ret = dict_get_str (options, "nfs.mount-rmtab", &optstr);
+ if (ret < 0) {
+ gf_log (GF_NFS, GF_LOG_ERROR, "Failed to read "
+ "reconfigured option: nfs.mount-rmtab");
+ goto out;
+ }
+ gf_path_strip_trailing_slashes (optstr);
+ }
+ if (strcmp (nfs->rmtab, optstr) != 0) {
+ mount_rewrite_rmtab (nfs->mstate, optstr);
+ gf_log (GF_NFS, GF_LOG_INFO,
+ "Reconfigured nfs.mount-rmtab path: %s",
+ nfs->rmtab);
+ }
+
+ GF_OPTION_RECONF (OPT_SERVER_AUX_GIDS, optbool,
+ options, bool, out);
+ if (nfs->server_aux_gids != optbool) {
+ nfs->server_aux_gids = optbool;
+ gf_log(GF_NFS, GF_LOG_INFO, "Reconfigured %s with value %d",
+ OPT_SERVER_AUX_GIDS, optbool);
+ }
+
+ GF_OPTION_RECONF (OPT_SERVER_GID_CACHE_TIMEOUT, optuint32,
+ options, uint32, out);
+ if (nfs->server_aux_gids_max_age != optuint32) {
+ nfs->server_aux_gids_max_age = optuint32;
+ gid_cache_reconf (&nfs->gid_cache, optuint32);
+ gf_log(GF_NFS, GF_LOG_INFO, "Reconfigured %s with value %d",
+ OPT_SERVER_GID_CACHE_TIMEOUT, optuint32);
+ }
+
+ /* reconfig nfs.dynamic-volumes */
+ ret = dict_get_str_boolean (options, "nfs.dynamic-volumes",
+ GF_NFS_DVM_OFF);
+ switch (ret) {
+ case GF_NFS_DVM_ON:
+ case GF_NFS_DVM_OFF:
+ optbool = ret;
+ break;
+ default:
+ optbool = GF_NFS_DVM_OFF;
+ break;
+ }
+ if (nfs->dynamicvolumes != optbool) {
+ nfs->dynamicvolumes = optbool;
+ gf_log(GF_NFS, GF_LOG_INFO, "Reconfigured nfs.dynamic-volumes"
+ " with value %d", optbool);
+ }
+
+ optbool = _gf_false;
+ if (dict_get (options, "nfs.enable-ino32")) {
+ ret = dict_get_str_boolean (options, "nfs.enable-ino32",
+ _gf_false);
+ if (ret < 0) {
+ gf_log (GF_NFS, GF_LOG_ERROR,
+ "Failed to read reconfigured option: "
+ "nfs.enable-ino32");
+ goto out;
+ }
+ optbool = ret;
+ }
+ if (nfs->enable_ino32 != optbool) {
+ nfs->enable_ino32 = optbool;
+ gf_log(GF_NFS, GF_LOG_INFO, "Reconfigured nfs.enable-ino32"
+ " with value %d", optbool);
+ }
+
+ /* nfs.nlm is enabled by default */
+ ret = dict_get_str_boolean (options, "nfs.nlm", _gf_true);
+ if (ret < 0) {
+ optbool = _gf_true;
+ } else {
+ optbool = ret;
+ }
+ if (nfs->enable_nlm != optbool) {
+ gf_log (GF_NFS, GF_LOG_INFO, "NLM is manually %s",
+ (optbool ? "enabled":"disabled"));
+ nfs->enable_nlm = optbool;
+ nfs_reconfigure_nlm4 (this);
+ }
+
+ /* nfs.acl is enabled by default */
+ ret = dict_get_str_boolean (options, "nfs.acl", _gf_true);
+ if (ret < 0) {
+ optbool = _gf_true;
+ } else {
+ optbool = ret;
+ }
+ if (nfs->enable_acl != optbool) {
+ gf_log (GF_NFS, GF_LOG_INFO, "ACL is manually %s",
+ (optbool ? "enabled":"disabled"));
+ nfs->enable_acl = optbool;
+ nfs_reconfigure_acl3 (this);
+ }
+
+ ret = 0;
+out:
+ return ret;
+}
+
+
+/*
+ * reconfigure() for NFS server xlator.
+ */
+int
+reconfigure (xlator_t *this, dict_t *options)
+{
+ int ret = 0;
+ struct nfs_state *nfs = NULL;
+ gf_boolean_t regpmap = _gf_true;
+
+ if ((!this) || (!this->private) || (!options))
+ return (-1);
+
+ nfs = (struct nfs_state *)this->private;
+
+ /* Reconfigure nfs options */
+ ret = nfs_reconfigure_state(this, options);
+ if (ret) {
+ gf_log (GF_NFS, GF_LOG_ERROR,
+ "nfs reconfigure state failed");
+ return (-1);
+ }
+
+ /* Reconfigure nfs3 options */
+ ret = nfs3_reconfigure_state(this, options);
+ if (ret) {
+ gf_log (GF_NFS, GF_LOG_ERROR,
+ "nfs3 reconfigure state failed");
+ return (-1);
+ }
+
+ /* Reconfigure mount options */
+ ret = mount_reconfigure_state(this, options);
+ if (ret) {
+ gf_log (GF_NFS, GF_LOG_ERROR,
+ "mount reconfigure state failed");
+ return (-1);
+ }
+
+ /* Reconfigure rpc layer */
+ ret = rpcsvc_reconfigure_options (nfs->rpcsvc, options);
+ if (ret) {
+ gf_log (GF_NFS, GF_LOG_ERROR,
+ "rpcsvc reconfigure options failed");
+ return (-1);
+ }
+ regpmap = rpcsvc_register_portmap_enabled(nfs->rpcsvc);
+ if (nfs->register_portmap != regpmap) {
+ nfs->register_portmap = regpmap;
+ if (regpmap) {
+ (void) nfs_program_register_portmap_all (nfs);
+ } else {
+ (void) nfs_program_unregister_portmap_all (nfs);
+ }
+ }
+
+ /* Reconfigure drc */
+ ret = rpcsvc_drc_reconfigure (nfs->rpcsvc, options);
+ if (ret) {
+ gf_log (GF_NFS, GF_LOG_ERROR,
+ "rpcsvc DRC reconfigure failed");
+ return (-1);
+ }
+
+ return (0);
+}
int
init (xlator_t *this) {
@@ -799,7 +1281,9 @@ init (xlator_t *this) {
goto err;
}
- gf_log (GF_NFS, GF_LOG_INFO, "NFS service started");
+ ret = nfs_drc_init (this);
+ if (ret == 0)
+ gf_log (GF_NFS, GF_LOG_INFO, "NFS service started");
err:
return ret;
@@ -810,24 +1294,26 @@ int
notify (xlator_t *this, int32_t event, void *data, ...)
{
xlator_t *subvol = NULL;
+ struct nfs_state *priv = NULL;
subvol = (xlator_t *)data;
gf_log (GF_NFS, GF_LOG_TRACE, "Notification received: %d",
event);
- switch (event)
- {
- case GF_EVENT_CHILD_UP:
- {
- nfs_startup_subvolume (this, subvol);
- break;
- }
- case GF_EVENT_PARENT_UP:
- {
- default_notify (this, GF_EVENT_PARENT_UP, data);
- break;
- }
+ switch (event) {
+ case GF_EVENT_CHILD_UP:
+ nfs_startup_subvolume (this, subvol);
+ break;
+
+ case GF_EVENT_CHILD_MODIFIED:
+ priv = this->private;
+ ++(priv->generation);
+ break;
+
+ case GF_EVENT_PARENT_UP:
+ default_notify (this, GF_EVENT_PARENT_UP, data);
+ break;
}
return 0;
@@ -849,14 +1335,14 @@ fini (xlator_t *this)
int32_t
nfs_forget (xlator_t *this, inode_t *inode)
{
- uint64_t ctx = 0;
- struct list_head *head = NULL;
+ uint64_t ctx = 0;
+ struct nfs_inode_ctx *ictx = NULL;
if (inode_ctx_del (inode, this, &ctx))
return -1;
- head = (struct list_head *)ctx;
- GF_FREE (head);
+ ictx = (struct nfs_inode_ctx *)ctx;
+ GF_FREE (ictx);
return 0;
}
@@ -946,13 +1432,39 @@ out:
return ret;
}
+extern int32_t
+nlm_priv (xlator_t *this);
+
+int32_t
+nfs_priv (xlator_t *this)
+{
+ int32_t ret = -1;
+
+ /* DRC needs the global drc structure, xl is of no use to it. */
+ ret = rpcsvc_drc_priv (((struct nfs_state *)(this->private))->rpcsvc->drc);
+ if (ret) {
+ gf_log (this->name, GF_LOG_DEBUG, "Statedump of DRC failed");
+ goto out;
+ }
+
+ ret = nlm_priv (this);
+ if (ret) {
+ gf_log (this->name, GF_LOG_DEBUG, "Statedump of NLM failed");
+ goto out;
+ }
+ out:
+ return ret;
+}
+
+
struct xlator_cbks cbks = {
.forget = nfs_forget,
};
-struct xlator_fops fops = { };
+struct xlator_fops fops;
struct xlator_dumpops dumpops = {
+ .priv = nfs_priv,
.priv_to_dict = nfs_priv_to_dict,
};
@@ -964,29 +1476,53 @@ struct xlator_dumpops dumpops = {
struct volume_options options[] = {
{ .key = {"nfs3.read-size"},
.type = GF_OPTION_TYPE_SIZET,
- .description = "Size in which the client should issue read requests"
- " to the Gluster NFSv3 server. Must be a multiple of"
- " 4KB."
+ .min = GF_NFS3_RTMIN,
+ .max = GF_NFS3_RTMAX,
+ .default_value = TOSTRING(GF_NFS3_RTPREF),
+ .description = "Size in which the client should issue read requests "
+ "to the Gluster NFSv3 server. Must be a multiple of "
+ "4KB (4096). Min and Max supported values are 4KB "
+ "(4096) and 1MB (1048576) respectively. If the "
+ "specified value is within the supported range but "
+ "not a multiple of 4096, it is rounded up to the "
+ "nearest multiple of 4096."
},
{ .key = {"nfs3.write-size"},
.type = GF_OPTION_TYPE_SIZET,
- .description = "Size in which the client should issue write requests"
- " to the Gluster NFSv3 server. Must be a multiple of"
- " 4KB."
+ .min = GF_NFS3_WTMIN,
+ .max = GF_NFS3_WTMAX,
+ .default_value = TOSTRING(GF_NFS3_WTPREF),
+ .description = "Size in which the client should issue write requests "
+ "to the Gluster NFSv3 server. Must be a multiple of "
+ "1KB (1024). Min and Max supported values are "
+ "4KB (4096) and 1MB(1048576) respectively. If the "
+ "specified value is within the supported range but "
+ "not a multiple of 4096, it is rounded up to the "
+ "nearest multiple of 4096."
},
{ .key = {"nfs3.readdir-size"},
.type = GF_OPTION_TYPE_SIZET,
+ .min = GF_NFS3_DTMIN,
+ .max = GF_NFS3_DTMAX,
+ .default_value = TOSTRING(GF_NFS3_DTPREF),
.description = "Size in which the client should issue directory "
- " reading requests."
+ "reading requests to the Gluster NFSv3 server. Must "
+ "be a multiple of 1KB (1024). Min and Max supported "
+ "values are 4KB (4096) and 1MB (1048576) respectively."
+ "If the specified value is within the supported range "
+ "but not a multiple of 4096, it is rounded up to the "
+ "nearest multiple of 4096."
},
{ .key = {"nfs3.*.volume-access"},
.type = GF_OPTION_TYPE_STR,
.value = {"read-only", "read-write"},
+ .default_value = "read-write",
.description = "Type of access desired for this subvolume: "
" read-only, read-write(default)"
},
{ .key = {"nfs3.*.trusted-write"},
.type = GF_OPTION_TYPE_BOOL,
+ .default_value = "off",
.description = "On an UNSTABLE write from client, return STABLE flag"
" to force client to not send a COMMIT request. In "
"some environments, combined with a replicated "
@@ -1001,6 +1537,7 @@ struct volume_options options[] = {
},
{ .key = {"nfs3.*.trusted-sync"},
.type = GF_OPTION_TYPE_BOOL,
+ .default_value = "off",
.description = "All writes and COMMIT requests are treated as async."
" This implies that no write requests are guaranteed"
" to be on server disks when the write reply is "
@@ -1010,25 +1547,40 @@ struct volume_options options[] = {
},
{ .key = {"nfs3.*.export-dir"},
.type = GF_OPTION_TYPE_PATH,
+ .default_value = "",
.description = "By default, all subvolumes of nfs are exported as "
"individual exports. There are cases where a "
"subdirectory or subdirectories in the volume need to "
"be exported separately. This option can also be used "
"in conjunction with nfs3.export-volumes option to "
"restrict exports only to the subdirectories specified"
- " through this option. Must be an absolute path."
+ " through this option. Must be an absolute path. Along"
+ " with path allowed list of IPs/hostname can be "
+ "associated with each subdirectory. If provided "
+ "connection will allowed only from these IPs. By "
+ "default connections from all IPs are allowed. "
+ "Format: <dir>[(hostspec[|hostspec|...])][,...]. Where"
+ " hostspec can be an IP address, hostname or an IP "
+ "range in CIDR notation. "
+ "e.g. /foo(192.168.1.0/24|host1|10.1.1.8),/host2."
+ " NOTE: Care must be taken while configuring this "
+ "option as invalid entries and/or unreachable DNS "
+ "servers can introduce unwanted delay in all the mount"
+ " calls."
},
{ .key = {"nfs3.export-dirs"},
.type = GF_OPTION_TYPE_BOOL,
+ .default_value = "on",
.description = "By default, all subvolumes of nfs are exported as "
"individual exports. There are cases where a "
"subdirectory or subdirectories in the volume need to "
"be exported separately. Enabling this option allows "
"any directory on a volumes to be exported separately."
- " Directory exports are enabled by default."
+ "Directory exports are enabled by default."
},
{ .key = {"nfs3.export-volumes"},
.type = GF_OPTION_TYPE_BOOL,
+ .default_value = "on",
.description = "Enable or disable exporting whole volumes, instead "
"if used in conjunction with nfs3.export-dir, can "
"allow setting up only subdirectories as exports. On "
@@ -1036,6 +1588,7 @@ struct volume_options options[] = {
},
{ .key = {"rpc-auth.auth-unix"},
.type = GF_OPTION_TYPE_BOOL,
+ .default_value = "on",
.description = "Disable or enable the AUTH_UNIX authentication type."
"Must always be enabled for better interoperability."
"However, can be disabled if needed. Enabled by"
@@ -1043,12 +1596,14 @@ struct volume_options options[] = {
},
{ .key = {"rpc-auth.auth-null"},
.type = GF_OPTION_TYPE_BOOL,
+ .default_value = "on",
.description = "Disable or enable the AUTH_NULL authentication type."
"Must always be enabled. This option is here only to"
" avoid unrecognized option warnings"
},
{ .key = {"rpc-auth.auth-unix.*"},
.type = GF_OPTION_TYPE_BOOL,
+ .default_value = "on",
.description = "Disable or enable the AUTH_UNIX authentication type "
"for a particular exported volume overriding defaults"
" and general setting for AUTH_UNIX scheme. Must "
@@ -1058,6 +1613,7 @@ struct volume_options options[] = {
},
{ .key = {"rpc-auth.auth-unix.*.allow"},
.type = GF_OPTION_TYPE_STR,
+ .default_value = "on",
.description = "Disable or enable the AUTH_UNIX authentication type "
"for a particular exported volume overriding defaults"
" and general setting for AUTH_UNIX scheme. Must "
@@ -1067,6 +1623,7 @@ struct volume_options options[] = {
},
{ .key = {"rpc-auth.auth-null.*"},
.type = GF_OPTION_TYPE_BOOL,
+ .default_value = "on",
.description = "Disable or enable the AUTH_NULL authentication type "
"for a particular exported volume overriding defaults"
" and general setting for AUTH_NULL. Must always be "
@@ -1075,6 +1632,7 @@ struct volume_options options[] = {
},
{ .key = {"rpc-auth.addr.allow"},
.type = GF_OPTION_TYPE_INTERNET_ADDRESS_LIST,
+ .default_value = "all",
.description = "Allow a comma separated list of addresses and/or"
" hostnames to connect to the server. By default, all"
" connections are allowed. This allows users to "
@@ -1082,6 +1640,7 @@ struct volume_options options[] = {
},
{ .key = {"rpc-auth.addr.reject"},
.type = GF_OPTION_TYPE_INTERNET_ADDRESS_LIST,
+ .default_value = "none",
.description = "Reject a comma separated list of addresses and/or"
" hostnames from connecting to the server. By default,"
" all connections are allowed. This allows users to"
@@ -1089,6 +1648,7 @@ struct volume_options options[] = {
},
{ .key = {"rpc-auth.addr.*.allow"},
.type = GF_OPTION_TYPE_INTERNET_ADDRESS_LIST,
+ .default_value = "all",
.description = "Allow a comma separated list of addresses and/or"
" hostnames to connect to the server. By default, all"
" connections are allowed. This allows users to "
@@ -1096,6 +1656,7 @@ struct volume_options options[] = {
},
{ .key = {"rpc-auth.addr.*.reject"},
.type = GF_OPTION_TYPE_INTERNET_ADDRESS_LIST,
+ .default_value = "none",
.description = "Reject a comma separated list of addresses and/or"
" hostnames from connecting to the server. By default,"
" all connections are allowed. This allows users to"
@@ -1103,6 +1664,7 @@ struct volume_options options[] = {
},
{ .key = {"rpc-auth.ports.insecure"},
.type = GF_OPTION_TYPE_BOOL,
+ .default_value = "off",
.description = "Allow client connections from unprivileged ports. By "
"default only privileged ports are allowed. This is a"
"global setting in case insecure ports are to be "
@@ -1110,31 +1672,35 @@ struct volume_options options[] = {
},
{ .key = {"rpc-auth.ports.*.insecure"},
.type = GF_OPTION_TYPE_BOOL,
+ .default_value = "off",
.description = "Allow client connections from unprivileged ports. By "
"default only privileged ports are allowed. Use this"
" option to enable or disable insecure ports for "
- "a specific subvolume and to override the global setting "
- " set by the previous option."
+ "a specific subvolume and to override the global "
+ "setting set by the previous option."
},
{ .key = {"rpc-auth.addr.namelookup"},
.type = GF_OPTION_TYPE_BOOL,
+ .default_value = "off",
.description = "Users have the option of turning on name lookup for"
" incoming client connections using this option. Use this "
"option to turn on name lookups during address-based "
"authentication. Turning this on will enable you to"
- " use hostnames in rpc-auth.addr.* filters. In some "
+ " use hostnames in nfs.rpc-auth-* filters. In some "
"setups, the name server can take too long to reply to DNS "
- "queries resulting in timeouts of mount requests. By default, "
- " name lookup is off"
+ "queries resulting in timeouts of mount requests. By "
+ "default, name lookup is off"
},
{ .key = {"nfs.dynamic-volumes"},
.type = GF_OPTION_TYPE_BOOL,
+ .default_value = "off",
.description = "Internal option set to tell gnfs to use a different"
" scheme for encoding file handles when DVM is being"
" used."
},
{ .key = {"nfs3.*.volume-id"},
.type = GF_OPTION_TYPE_STR,
+ .default_value = "",
.description = "When nfs.dynamic-volumes is set, gnfs expects every "
"subvolume to have this option set for it, so that "
"gnfs can use this option to identify the volume. "
@@ -1143,22 +1709,34 @@ struct volume_options options[] = {
},
{ .key = {"nfs.enable-ino32"},
.type = GF_OPTION_TYPE_BOOL,
+ .default_value = "no",
.description = "For nfs clients or apps that do not support 64-bit "
"inode numbers, use this option to make NFS return "
- "32-bit inode numbers instead. Disabled by default, so "
- "NFS returns 64-bit inode numbers."
+ "32-bit inode numbers instead. Disabled by default, so"
+ " NFS returns 64-bit inode numbers."
},
{ .key = {"rpc.register-with-portmap"},
.type = GF_OPTION_TYPE_BOOL,
+ .default_value = "on",
.description = "For systems that need to run multiple nfs servers, "
"only one registration is possible with "
"portmap service. Use this option to turn off portmap "
"registration for Gluster NFS. On by default"
},
+ { .key = {"rpc.outstanding-rpc-limit"},
+ .type = GF_OPTION_TYPE_INT,
+ .min = RPCSVC_MIN_OUTSTANDING_RPC_LIMIT,
+ .max = RPCSVC_MAX_OUTSTANDING_RPC_LIMIT,
+ .default_value = TOSTRING(RPCSVC_DEFAULT_OUTSTANDING_RPC_LIMIT),
+ .description = "Parameter to throttle the number of incoming RPC "
+ "requests from a client. 0 means no limit (can "
+ "potentially run out of memory)"
+ },
{ .key = {"nfs.port"},
.type = GF_OPTION_TYPE_INT,
.min = 1,
.max = 0xffff,
+ .default_value = TOSTRING(GF_NFS3_PORT),
.description = "Use this option on systems that need Gluster NFS to "
"be associated with a non-default port number."
},
@@ -1166,6 +1744,7 @@ struct volume_options options[] = {
.type = GF_OPTION_TYPE_INT,
.min = 1,
.max = 1024,
+ .default_value = TOSTRING(GF_NFS_DEFAULT_MEMFACTOR),
.description = "Use this option to make NFS be faster on systems by "
"using more memory. This option specifies a multiple "
"that determines the total amount of memory used. "
@@ -1176,17 +1755,71 @@ struct volume_options options[] = {
},
{ .key = {"nfs.*.disable"},
.type = GF_OPTION_TYPE_BOOL,
+ .default_value = "false",
.description = "This option is used to start or stop NFS server"
"for individual volume."
},
{ .key = {"nfs.nlm"},
.type = GF_OPTION_TYPE_BOOL,
+ .default_value = "on",
.description = "This option, if set to 'off', disables NLM server "
"by not registering the service with the portmapper."
" Set it to 'on' to re-enable it. Default value: 'on'"
},
+ { .key = {"nfs.mount-udp"},
+ .type = GF_OPTION_TYPE_BOOL,
+ .default_value = "off",
+ .description = "set the option to 'on' to enable mountd on UDP. "
+ "Required for some Solaris and AIX NFS clients. "
+ "The need for enabling this option often depends "
+ "on the usage of NLM."
+ },
+ { .key = {"nfs.mount-rmtab"},
+ .type = GF_OPTION_TYPE_PATH,
+ .default_value = DATADIR "/rmtab",
+ .description = "Set the location of the cache file that is used to "
+ "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."
+ },
+ { .key = {OPT_SERVER_AUX_GIDS},
+ .type = GF_OPTION_TYPE_BOOL,
+ .default_value = "off",
+ .description = "Let the server look up which groups a user belongs "
+ "to, overwriting the list passed from the client. "
+ "This enables support for group lists longer than "
+ "can be passed through the NFS protocol, but is not "
+ "secure unless users and groups are well synchronized "
+ "between clients and servers."
+ },
+ { .key = {OPT_SERVER_GID_CACHE_TIMEOUT},
+ .type = GF_OPTION_TYPE_INT,
+ .min = 0,
+ .max = 3600,
+ .default_value = "5",
+ .description = "Number of seconds to cache auxiliary-GID data, when "
+ OPT_SERVER_AUX_GIDS " is set."
+ },
+ { .key = {"nfs.acl"},
+ .type = GF_OPTION_TYPE_BOOL,
+ .default_value = "on",
+ .description = "This option is used to control ACL support for NFS."
+ },
+ { .key = {"nfs.drc"},
+ .type = GF_OPTION_TYPE_STR,
+ .default_value = "on",
+ .description = "Enable Duplicate Request Cache in gNFS server to "
+ "improve correctness of non-idempotent operations like "
+ "write, delete, link, et al"
+ },
+ { .key = {"nfs.drc-size"},
+ .type = GF_OPTION_TYPE_INT,
+ .default_value = "0x20000",
+ .description = "Sets the number of non-idempotent "
+ "requests to cache in drc"
+ },
{ .key = {NULL} },
};
-