Skip to content

Commit

Permalink
Merge tag 'nfs-for-6.5-1' of git://git.linux-nfs.org/projects/trondmy…
Browse files Browse the repository at this point in the history
…/linux-nfs

Pull NFS client updates from Trond Myklebust:
"Stable fixes and other bugfixes:

   - nfs: don't report STATX_BTIME in ->getattr

   - Revert 'NFSv4: Retry LOCK on OLD_STATEID during delegation return'
     since it breaks NFSv4 state recovery.

   - NFSv4.1: freeze the session table upon receiving NFS4ERR_BADSESSION

   - Fix the NFSv4.2 xattr cache shrinker_id

   - Force a ctime update after a NFSv4.2 SETXATTR call

  Features and cleanups:

   - NFS and RPC over TLS client code from Chuck Lever

   - Support for use of abstract unix socket addresses with the rpcbind
     daemon

   - Sysfs API to allow shutdown of the kernel RPC client and prevent
     umount() hangs if the server is known to be permanently down

   - XDR cleanups from Anna"

* tag 'nfs-for-6.5-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (33 commits)
  Revert "NFSv4: Retry LOCK on OLD_STATEID during delegation return"
  NFS: Don't cleanup sysfs superblock entry if uninitialized
  nfs: don't report STATX_BTIME in ->getattr
  NFSv4.1: freeze the session table upon receiving NFS4ERR_BADSESSION
  NFSv4.2: fix wrong shrinker_id
  NFSv4: Clean up some shutdown loops
  NFS: Cancel all existing RPC tasks when shutdown
  NFS: add sysfs shutdown knob
  NFS: add a sysfs link to the acl rpc_client
  NFS: add a sysfs link to the lockd rpc_client
  NFS: Add sysfs links to sunrpc clients for nfs_clients
  NFS: add superblock sysfs entries
  NFS: Make all of /sys/fs/nfs network-namespace unique
  NFS: Open-code the nfs_kset kset_create_and_add()
  NFS: rename nfs_client_kobj to nfs_net_kobj
  NFS: rename nfs_client_kset to nfs_kset
  NFS: Add an "xprtsec=" NFS mount option
  NFS: Have struct nfs_client carry a TLS policy field
  SUNRPC: Add a TCP-with-TLS RPC transport class
  SUNRPC: Capture CMSG metadata on client-side receive
  ...
  • Loading branch information
torvalds committed Jul 1, 2023
2 parents f8566aa + 5b4a82a commit dfab92f
Show file tree
Hide file tree
Showing 31 changed files with 1,566 additions and 435 deletions.
6 changes: 6 additions & 0 deletions fs/lockd/clntlock.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@ void nlmclnt_prepare_block(struct nlm_wait *block, struct nlm_host *host, struct
block->b_status = nlm_lck_blocked;
}

struct rpc_clnt *nlmclnt_rpc_clnt(struct nlm_host *host)
{
return host->h_rpcclnt;
}
EXPORT_SYMBOL_GPL(nlmclnt_rpc_clnt);

/*
* Queue up a lock for blocking so that the GRANTED request can see it
*/
Expand Down
32 changes: 32 additions & 0 deletions fs/nfs/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
clp->cl_net = get_net(cl_init->net);

clp->cl_principal = "*";
clp->cl_xprtsec = cl_init->xprtsec;
return clp;

error_cleanup:
Expand Down Expand Up @@ -326,6 +327,10 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat
sap))
continue;

/* Match the xprt security policy */
if (clp->cl_xprtsec.policy != data->xprtsec.policy)
continue;

refcount_inc(&clp->cl_count);
return clp;
}
Expand Down Expand Up @@ -458,6 +463,7 @@ void nfs_init_timeout_values(struct rpc_timeout *to, int proto,

switch (proto) {
case XPRT_TRANSPORT_TCP:
case XPRT_TRANSPORT_TCP_TLS:
case XPRT_TRANSPORT_RDMA:
if (retrans == NFS_UNSPEC_RETRANS)
to->to_retries = NFS_DEF_TCP_RETRANS;
Expand Down Expand Up @@ -510,6 +516,7 @@ int nfs_create_rpc_client(struct nfs_client *clp,
.version = clp->rpc_ops->version,
.authflavor = flavor,
.cred = cl_init->cred,
.xprtsec = cl_init->xprtsec,
};

if (test_bit(NFS_CS_DISCRTRY, &clp->cl_flags))
Expand Down Expand Up @@ -592,6 +599,7 @@ static int nfs_start_lockd(struct nfs_server *server)

server->nlm_host = host;
server->destroy = nfs_destroy_server;
nfs_sysfs_link_rpc_client(server, nlmclnt_rpc_clnt(host), NULL);
return 0;
}

Expand Down Expand Up @@ -621,6 +629,7 @@ int nfs_init_server_rpcclient(struct nfs_server *server,
if (server->flags & NFS_MOUNT_SOFT)
server->client->cl_softrtry = 1;

nfs_sysfs_link_rpc_client(server, server->client, NULL);
return 0;
}
EXPORT_SYMBOL_GPL(nfs_init_server_rpcclient);
Expand Down Expand Up @@ -675,6 +684,7 @@ static int nfs_init_server(struct nfs_server *server,
.cred = server->cred,
.nconnect = ctx->nfs_server.nconnect,
.init_flags = (1UL << NFS_CS_REUSEPORT),
.xprtsec = ctx->xprtsec,
};
struct nfs_client *clp;
int error;
Expand All @@ -690,6 +700,8 @@ static int nfs_init_server(struct nfs_server *server,
return PTR_ERR(clp);

server->nfs_client = clp;
nfs_sysfs_add_server(server);
nfs_sysfs_link_rpc_client(server, clp->cl_rpcclient, "_state");

/* Initialise the client representation from the mount data */
server->flags = ctx->flags;
Expand Down Expand Up @@ -944,6 +956,8 @@ void nfs_server_remove_lists(struct nfs_server *server)
}
EXPORT_SYMBOL_GPL(nfs_server_remove_lists);

static DEFINE_IDA(s_sysfs_ids);

/*
* Allocate and initialise a server record
*/
Expand All @@ -955,6 +969,12 @@ struct nfs_server *nfs_alloc_server(void)
if (!server)
return NULL;

server->s_sysfs_id = ida_alloc(&s_sysfs_ids, GFP_KERNEL);
if (server->s_sysfs_id < 0) {
kfree(server);
return NULL;
}

server->client = server->client_acl = ERR_PTR(-EINVAL);

/* Zero out the NFS state stuff */
Expand Down Expand Up @@ -1001,6 +1021,12 @@ void nfs_free_server(struct nfs_server *server)

nfs_put_client(server->nfs_client);

if (server->kobj.state_initialized) {
nfs_sysfs_remove_server(server);
kobject_put(&server->kobj);
}
ida_free(&s_sysfs_ids, server->s_sysfs_id);

ida_destroy(&server->lockowner_id);
ida_destroy(&server->openowner_id);
nfs_free_iostats(server->io_stats);
Expand Down Expand Up @@ -1102,6 +1128,11 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source,

server->fsid = fattr->fsid;

nfs_sysfs_add_server(server);

nfs_sysfs_link_rpc_client(server,
server->nfs_client->cl_rpcclient, "_state");

error = nfs_init_server_rpcclient(server,
source->client->cl_timeout,
flavor);
Expand Down Expand Up @@ -1385,6 +1416,7 @@ int __init nfs_fs_proc_init(void)
void nfs_fs_proc_exit(void)
{
remove_proc_subtree("fs/nfsfs", NULL);
ida_destroy(&s_sysfs_ids);
}

#endif /* CONFIG_PROC_FS */
67 changes: 67 additions & 0 deletions fs/nfs/fs_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
#include <linux/nfs_fs.h>
#include <linux/nfs_mount.h>
#include <linux/nfs4_mount.h>

#include <net/handshake.h>

#include "nfs.h"
#include "internal.h"

Expand Down Expand Up @@ -88,6 +91,7 @@ enum nfs_param {
Opt_vers,
Opt_wsize,
Opt_write,
Opt_xprtsec,
};

enum {
Expand Down Expand Up @@ -194,6 +198,7 @@ static const struct fs_parameter_spec nfs_fs_parameters[] = {
fsparam_string("vers", Opt_vers),
fsparam_enum ("write", Opt_write, nfs_param_enums_write),
fsparam_u32 ("wsize", Opt_wsize),
fsparam_string("xprtsec", Opt_xprtsec),
{}
};

Expand Down Expand Up @@ -267,6 +272,20 @@ static const struct constant_table nfs_secflavor_tokens[] = {
{}
};

enum {
Opt_xprtsec_none,
Opt_xprtsec_tls,
Opt_xprtsec_mtls,
nr__Opt_xprtsec
};

static const struct constant_table nfs_xprtsec_policies[] = {
{ "none", Opt_xprtsec_none },
{ "tls", Opt_xprtsec_tls },
{ "mtls", Opt_xprtsec_mtls },
{}
};

/*
* Sanity-check a server address provided by the mount command.
*
Expand Down Expand Up @@ -320,9 +339,21 @@ static int nfs_validate_transport_protocol(struct fs_context *fc,
default:
ctx->nfs_server.protocol = XPRT_TRANSPORT_TCP;
}

if (ctx->xprtsec.policy != RPC_XPRTSEC_NONE)
switch (ctx->nfs_server.protocol) {
case XPRT_TRANSPORT_TCP:
ctx->nfs_server.protocol = XPRT_TRANSPORT_TCP_TLS;
break;
default:
goto out_invalid_xprtsec_policy;
}

return 0;
out_invalid_transport_udp:
return nfs_invalf(fc, "NFS: Unsupported transport protocol udp");
out_invalid_xprtsec_policy:
return nfs_invalf(fc, "NFS: Transport does not support xprtsec");
}

/*
Expand Down Expand Up @@ -430,6 +461,29 @@ static int nfs_parse_security_flavors(struct fs_context *fc,
return 0;
}

static int nfs_parse_xprtsec_policy(struct fs_context *fc,
struct fs_parameter *param)
{
struct nfs_fs_context *ctx = nfs_fc2context(fc);

trace_nfs_mount_assign(param->key, param->string);

switch (lookup_constant(nfs_xprtsec_policies, param->string, -1)) {
case Opt_xprtsec_none:
ctx->xprtsec.policy = RPC_XPRTSEC_NONE;
break;
case Opt_xprtsec_tls:
ctx->xprtsec.policy = RPC_XPRTSEC_TLS_ANON;
break;
case Opt_xprtsec_mtls:
ctx->xprtsec.policy = RPC_XPRTSEC_TLS_X509;
break;
default:
return nfs_invalf(fc, "NFS: Unrecognized transport security policy");
}
return 0;
}

static int nfs_parse_version_string(struct fs_context *fc,
const char *string)
{
Expand Down Expand Up @@ -696,6 +750,11 @@ static int nfs_fs_context_parse_param(struct fs_context *fc,
if (ret < 0)
return ret;
break;
case Opt_xprtsec:
ret = nfs_parse_xprtsec_policy(fc, param);
if (ret < 0)
return ret;
break;

case Opt_proto:
if (!param->string)
Expand Down Expand Up @@ -791,16 +850,19 @@ static int nfs_fs_context_parse_param(struct fs_context *fc,
ctx->mount_server.addrlen = len;
break;
case Opt_nconnect:
trace_nfs_mount_assign(param->key, param->string);
if (result.uint_32 < 1 || result.uint_32 > NFS_MAX_CONNECTIONS)
goto out_of_bounds;
ctx->nfs_server.nconnect = result.uint_32;
break;
case Opt_max_connect:
trace_nfs_mount_assign(param->key, param->string);
if (result.uint_32 < 1 || result.uint_32 > NFS_MAX_TRANSPORTS)
goto out_of_bounds;
ctx->nfs_server.max_connect = result.uint_32;
break;
case Opt_lookupcache:
trace_nfs_mount_assign(param->key, param->string);
switch (result.uint_32) {
case Opt_lookupcache_all:
ctx->flags &= ~(NFS_MOUNT_LOOKUP_CACHE_NONEG|NFS_MOUNT_LOOKUP_CACHE_NONE);
Expand All @@ -817,6 +879,7 @@ static int nfs_fs_context_parse_param(struct fs_context *fc,
}
break;
case Opt_local_lock:
trace_nfs_mount_assign(param->key, param->string);
switch (result.uint_32) {
case Opt_local_lock_all:
ctx->flags |= (NFS_MOUNT_LOCAL_FLOCK |
Expand All @@ -837,6 +900,7 @@ static int nfs_fs_context_parse_param(struct fs_context *fc,
}
break;
case Opt_write:
trace_nfs_mount_assign(param->key, param->string);
switch (result.uint_32) {
case Opt_write_lazy:
ctx->flags &=
Expand Down Expand Up @@ -1569,6 +1633,9 @@ static int nfs_init_fs_context(struct fs_context *fc)
ctx->selected_flavor = RPC_AUTH_MAXFLAVOR;
ctx->minorversion = 0;
ctx->need_mount = true;
ctx->xprtsec.policy = RPC_XPRTSEC_NONE;
ctx->xprtsec.cert_serial = TLS_NO_CERT;
ctx->xprtsec.privkey_serial = TLS_NO_PRIVKEY;

fc->s_iflags |= SB_I_STABLE_WRITES;
}
Expand Down
2 changes: 1 addition & 1 deletion fs/nfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -845,7 +845,7 @@ int nfs_getattr(struct mnt_idmap *idmap, const struct path *path,

request_mask &= STATX_TYPE | STATX_MODE | STATX_NLINK | STATX_UID |
STATX_GID | STATX_ATIME | STATX_MTIME | STATX_CTIME |
STATX_INO | STATX_SIZE | STATX_BLOCKS | STATX_BTIME |
STATX_INO | STATX_SIZE | STATX_BLOCKS |
STATX_CHANGE_COOKIE;

if ((query_flags & AT_STATX_DONT_SYNC) && !force_sync) {
Expand Down
2 changes: 2 additions & 0 deletions fs/nfs/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ struct nfs_client_initdata {
struct net *net;
const struct rpc_timeout *timeparms;
const struct cred *cred;
struct xprtsec_parms xprtsec;
};

/*
Expand All @@ -101,6 +102,7 @@ struct nfs_fs_context {
unsigned int bsize;
struct nfs_auth_info auth_info;
rpc_authflavor_t selected_flavor;
struct xprtsec_parms xprtsec;
char *client_address;
unsigned int version;
unsigned int minorversion;
Expand Down
13 changes: 11 additions & 2 deletions fs/nfs/nfs3client.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include <linux/sunrpc/addr.h>
#include "internal.h"
#include "nfs3_fs.h"
#include "netns.h"
#include "sysfs.h"

#ifdef CONFIG_NFS_V3_ACL
static struct rpc_stat nfsacl_rpcstat = { &nfsacl_program };
Expand Down Expand Up @@ -31,6 +33,8 @@ static void nfs_init_server_aclclient(struct nfs_server *server)
if (IS_ERR(server->client_acl))
goto out_noacl;

nfs_sysfs_link_rpc_client(server, server->client_acl, NULL);

/* No errors! Assume that Sun nfsacls are supported */
server->caps |= NFS_CAP_ACLS;
return;
Expand Down Expand Up @@ -93,6 +97,7 @@ struct nfs_client *nfs3_set_ds_client(struct nfs_server *mds_srv,
.net = mds_clp->cl_net,
.timeparms = &ds_timeout,
.cred = mds_srv->cred,
.xprtsec = mds_clp->cl_xprtsec,
};
struct nfs_client *clp;
char buf[INET6_ADDRSTRLEN + 1];
Expand All @@ -102,8 +107,12 @@ struct nfs_client *nfs3_set_ds_client(struct nfs_server *mds_srv,
return ERR_PTR(-EINVAL);
cl_init.hostname = buf;

if (mds_clp->cl_nconnect > 1 && ds_proto == XPRT_TRANSPORT_TCP)
cl_init.nconnect = mds_clp->cl_nconnect;
switch (ds_proto) {
case XPRT_TRANSPORT_TCP:
case XPRT_TRANSPORT_TCP_TLS:
if (mds_clp->cl_nconnect > 1)
cl_init.nconnect = mds_clp->cl_nconnect;
}

if (mds_srv->flags & NFS_MOUNT_NORESVPORT)
__set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags);
Expand Down
Loading

0 comments on commit dfab92f

Please sign in to comment.