summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xtests/bugs/nfs/bug-1302948.t13
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-volume-set.c8
-rw-r--r--xlators/nfs/server/src/nfs.c17
-rw-r--r--xlators/nfs/server/src/nfs.h1
-rw-r--r--xlators/nfs/server/src/nfs3-helpers.c1
-rw-r--r--xlators/nfs/server/src/nfs3.c11
6 files changed, 50 insertions, 1 deletions
diff --git a/tests/bugs/nfs/bug-1302948.t b/tests/bugs/nfs/bug-1302948.t
new file mode 100755
index 00000000000..a2fb0e68ff0
--- /dev/null
+++ b/tests/bugs/nfs/bug-1302948.t
@@ -0,0 +1,13 @@
+#!/bin/bash
+# TEST the nfs.rdirplus option
+. $(dirname $0)/../../include.rc
+
+cleanup
+TEST glusterd
+TEST pidof glusterd
+
+TEST $CLI volume create $V0 $H0:$B0/$V0
+TEST $CLI volume start $V0
+TEST $CLI volume set $V0 nfs.rdirplus off
+TEST $CLI volume set $V0 nfs.rdirplus on
+cleanup
diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-set.c b/xlators/mgmt/glusterd/src/glusterd-volume-set.c
index eac64008c9a..d15ee835a4e 100644
--- a/xlators/mgmt/glusterd/src/glusterd-volume-set.c
+++ b/xlators/mgmt/glusterd/src/glusterd-volume-set.c
@@ -2208,6 +2208,14 @@ struct volopt_map_entry glusterd_volopt_map[] = {
.type = GLOBAL_DOC,
.op_version = 3
},
+ { .key = "nfs.rdirplus",
+ .voltype = "nfs/server",
+ .option = "nfs.rdirplus",
+ .type = GLOBAL_DOC,
+ .op_version = GD_OP_VERSION_3_7_12,
+ .description = "When this option is set to off NFS falls back to "
+ "standard readdir instead of readdirp"
+ },
/* Cli options for Export authentication on nfs mount */
{ .key = "nfs.exports-auth-enable",
diff --git a/xlators/nfs/server/src/nfs.c b/xlators/nfs/server/src/nfs.c
index 8b4bc75ea00..47b9309db43 100644
--- a/xlators/nfs/server/src/nfs.c
+++ b/xlators/nfs/server/src/nfs.c
@@ -1054,6 +1054,9 @@ nfs_init_state (xlator_t *this)
goto free_foppool;
}
}
+
+ GF_OPTION_INIT ("nfs.rdirplus", nfs->rdirplus, bool, free_foppool);
+
GF_OPTION_INIT (OPT_SERVER_RPC_STATD, nfs->rpc_statd, path, free_foppool);
GF_OPTION_INIT (OPT_SERVER_RPC_STATD_PIDFILE, nfs->rpc_statd_pid_file, path, free_foppool);
@@ -1266,6 +1269,14 @@ nfs_reconfigure_state (xlator_t *this, dict_t *options)
OPT_SERVER_GID_CACHE_TIMEOUT, optuint32);
}
+ GF_OPTION_RECONF ("nfs.rdirplus", optbool,
+ options, bool, out);
+ if (nfs->rdirplus != optbool) {
+ nfs->rdirplus = optbool;
+ gf_msg (GF_NFS, GF_LOG_INFO, 0, NFS_MSG_RECONFIG_VALUE,
+ "Reconfigured nfs.rdirplus with value %d", optbool);
+ }
+
/* reconfig nfs.dynamic-volumes */
ret = dict_get_str_boolean (options, "nfs.dynamic-volumes",
GF_NFS_DVM_OFF);
@@ -2061,6 +2072,12 @@ struct volume_options options[] = {
.description = "Sets the TTL of an entry in the auth cache. Value is "
"in seconds."
},
+ { .key = {"nfs.rdirplus"},
+ .type = GF_OPTION_TYPE_BOOL,
+ .default_value = "on",
+ .description = "When this option is set to off NFS falls back to "
+ "standard readdir instead of readdirp"
+ },
{ .key = {NULL} },
};
diff --git a/xlators/nfs/server/src/nfs.h b/xlators/nfs/server/src/nfs.h
index 15aec5d7da9..85ad24ad07d 100644
--- a/xlators/nfs/server/src/nfs.h
+++ b/xlators/nfs/server/src/nfs.h
@@ -104,6 +104,7 @@ struct nfs_state {
gf_boolean_t register_portmap;
char *rpc_statd;
char *rpc_statd_pid_file;
+ gf_boolean_t rdirplus;
};
struct nfs_inode_ctx {
diff --git a/xlators/nfs/server/src/nfs3-helpers.c b/xlators/nfs/server/src/nfs3-helpers.c
index ed673a12489..bf2594f261d 100644
--- a/xlators/nfs/server/src/nfs3-helpers.c
+++ b/xlators/nfs/server/src/nfs3-helpers.c
@@ -230,6 +230,7 @@ nfs3_errno_to_nfsstat3 (int errnum)
stat = NFS3ERR_SERVERFAULT;
break;
+ case ENOTSUP:
case ENOSYS:
stat = NFS3ERR_NOTSUPP;
break;
diff --git a/xlators/nfs/server/src/nfs3.c b/xlators/nfs/server/src/nfs3.c
index 267795b92c9..4035491359f 100644
--- a/xlators/nfs/server/src/nfs3.c
+++ b/xlators/nfs/server/src/nfs3.c
@@ -4449,6 +4449,8 @@ nfs3_readdir (rpcsvc_request_t *req, struct nfs3_fh *fh, cookie3 cookie,
int ret = -EFAULT;
struct nfs3_state *nfs3 = NULL;
nfs3_call_state_t *cs = NULL;
+ struct nfs_state *nfs = NULL;
+ gf_boolean_t is_readdirp = !!maxcount;
if ((!req) || (!fh)) {
gf_msg (GF_NFS3, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY,
@@ -4463,6 +4465,13 @@ nfs3_readdir (rpcsvc_request_t *req, struct nfs3_fh *fh, cookie3 cookie,
nfs3_map_fh_to_volume (nfs3, fh, req, vol, stat, nfs3err);
nfs3_volume_started_check (nfs3, vol, ret, out);
nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);
+ nfs = nfs_state (nfs3->nfsx);
+
+ if (is_readdirp && !nfs->rdirplus) {
+ ret = -ENOTSUP;
+ stat = nfs3_errno_to_nfsstat3 (-ret);
+ goto nfs3err;
+ }
cs->cookieverf = cverf;
cs->dircount = dircount;
@@ -4476,7 +4485,7 @@ nfs3_readdir (rpcsvc_request_t *req, struct nfs3_fh *fh, cookie3 cookie,
nfs3err:
if (ret < 0) {
- if (maxcount == 0) {
+ if (!is_readdirp) {
nfs3_log_common_res (rpcsvc_request_xid (req),
NFS3_READDIR, stat, -ret,
cs ? cs->resolvedloc.path : NULL);