nfs_common: add NFS LOCALIO auxiliary protocol enablement
fs/nfs_common/nfslocalio.c provides interfaces that enable an NFS
client to generate a nonce (single-use UUID) and associated nfs_uuid_t
struct, register it with nfs_common for subsequent lookup and
verification by the NFS server and if matched the NFS server populates
members in the nfs_uuid_t struct.
nfs_common's nfs_uuids list is the basis for localio enablement, as
such it has members that point to nfsd memory for direct use by the
client (e.g. 'net' is the server's network namespace, through it the
client can access nn->nfsd_serv).
This commit also provides the base nfs_uuid_t interfaces to allow
proper net namespace refcounting for the LOCALIO use case.
CONFIG_NFS_LOCALIO controls the nfs_common, NFS server and NFS client
enablement for LOCALIO. If both NFS_FS=m and NFSD=m then
NFS_COMMON_LOCALIO_SUPPORT=m and nfs_localio.ko is built (and provides
nfs_common's LOCALIO support).
# lsmod | grep nfs_localio
nfs_localio 12288 2 nfsd,nfs
sunrpc 745472 35 nfs_localio,nfsd,auth_rpcgss,lockd,nfsv3,nfs
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Co-developed-by: NeilBrown <neilb@suse.de>
Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2024-09-05 15:09:48 -04:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
|
|
|
/*
|
|
|
|
* Copyright (C) 2024 Mike Snitzer <snitzer@hammerspace.com>
|
|
|
|
* Copyright (C) 2024 NeilBrown <neilb@suse.de>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/module.h>
|
2024-10-23 16:34:42 -04:00
|
|
|
#include <linux/list.h>
|
nfs_common: add NFS LOCALIO auxiliary protocol enablement
fs/nfs_common/nfslocalio.c provides interfaces that enable an NFS
client to generate a nonce (single-use UUID) and associated nfs_uuid_t
struct, register it with nfs_common for subsequent lookup and
verification by the NFS server and if matched the NFS server populates
members in the nfs_uuid_t struct.
nfs_common's nfs_uuids list is the basis for localio enablement, as
such it has members that point to nfsd memory for direct use by the
client (e.g. 'net' is the server's network namespace, through it the
client can access nn->nfsd_serv).
This commit also provides the base nfs_uuid_t interfaces to allow
proper net namespace refcounting for the LOCALIO use case.
CONFIG_NFS_LOCALIO controls the nfs_common, NFS server and NFS client
enablement for LOCALIO. If both NFS_FS=m and NFSD=m then
NFS_COMMON_LOCALIO_SUPPORT=m and nfs_localio.ko is built (and provides
nfs_common's LOCALIO support).
# lsmod | grep nfs_localio
nfs_localio 12288 2 nfsd,nfs
sunrpc 745472 35 nfs_localio,nfsd,auth_rpcgss,lockd,nfsv3,nfs
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Co-developed-by: NeilBrown <neilb@suse.de>
Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2024-09-05 15:09:48 -04:00
|
|
|
#include <linux/nfslocalio.h>
|
2024-11-15 20:40:56 -05:00
|
|
|
#include <linux/nfs3.h>
|
|
|
|
#include <linux/nfs4.h>
|
2024-11-15 20:40:57 -05:00
|
|
|
#include <linux/nfs_fs.h>
|
nfs_common: add NFS LOCALIO auxiliary protocol enablement
fs/nfs_common/nfslocalio.c provides interfaces that enable an NFS
client to generate a nonce (single-use UUID) and associated nfs_uuid_t
struct, register it with nfs_common for subsequent lookup and
verification by the NFS server and if matched the NFS server populates
members in the nfs_uuid_t struct.
nfs_common's nfs_uuids list is the basis for localio enablement, as
such it has members that point to nfsd memory for direct use by the
client (e.g. 'net' is the server's network namespace, through it the
client can access nn->nfsd_serv).
This commit also provides the base nfs_uuid_t interfaces to allow
proper net namespace refcounting for the LOCALIO use case.
CONFIG_NFS_LOCALIO controls the nfs_common, NFS server and NFS client
enablement for LOCALIO. If both NFS_FS=m and NFSD=m then
NFS_COMMON_LOCALIO_SUPPORT=m and nfs_localio.ko is built (and provides
nfs_common's LOCALIO support).
# lsmod | grep nfs_localio
nfs_localio 12288 2 nfsd,nfs
sunrpc 745472 35 nfs_localio,nfsd,auth_rpcgss,lockd,nfsv3,nfs
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Co-developed-by: NeilBrown <neilb@suse.de>
Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2024-09-05 15:09:48 -04:00
|
|
|
#include <net/netns/generic.h>
|
|
|
|
|
2024-11-15 20:41:03 -05:00
|
|
|
#include "localio_trace.h"
|
|
|
|
|
nfs_common: add NFS LOCALIO auxiliary protocol enablement
fs/nfs_common/nfslocalio.c provides interfaces that enable an NFS
client to generate a nonce (single-use UUID) and associated nfs_uuid_t
struct, register it with nfs_common for subsequent lookup and
verification by the NFS server and if matched the NFS server populates
members in the nfs_uuid_t struct.
nfs_common's nfs_uuids list is the basis for localio enablement, as
such it has members that point to nfsd memory for direct use by the
client (e.g. 'net' is the server's network namespace, through it the
client can access nn->nfsd_serv).
This commit also provides the base nfs_uuid_t interfaces to allow
proper net namespace refcounting for the LOCALIO use case.
CONFIG_NFS_LOCALIO controls the nfs_common, NFS server and NFS client
enablement for LOCALIO. If both NFS_FS=m and NFSD=m then
NFS_COMMON_LOCALIO_SUPPORT=m and nfs_localio.ko is built (and provides
nfs_common's LOCALIO support).
# lsmod | grep nfs_localio
nfs_localio 12288 2 nfsd,nfs
sunrpc 745472 35 nfs_localio,nfsd,auth_rpcgss,lockd,nfsv3,nfs
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Co-developed-by: NeilBrown <neilb@suse.de>
Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2024-09-05 15:09:48 -04:00
|
|
|
MODULE_LICENSE("GPL");
|
|
|
|
MODULE_DESCRIPTION("NFS localio protocol bypass support");
|
|
|
|
|
2024-11-15 20:41:01 -05:00
|
|
|
static DEFINE_SPINLOCK(nfs_uuids_lock);
|
nfs_common: add NFS LOCALIO auxiliary protocol enablement
fs/nfs_common/nfslocalio.c provides interfaces that enable an NFS
client to generate a nonce (single-use UUID) and associated nfs_uuid_t
struct, register it with nfs_common for subsequent lookup and
verification by the NFS server and if matched the NFS server populates
members in the nfs_uuid_t struct.
nfs_common's nfs_uuids list is the basis for localio enablement, as
such it has members that point to nfsd memory for direct use by the
client (e.g. 'net' is the server's network namespace, through it the
client can access nn->nfsd_serv).
This commit also provides the base nfs_uuid_t interfaces to allow
proper net namespace refcounting for the LOCALIO use case.
CONFIG_NFS_LOCALIO controls the nfs_common, NFS server and NFS client
enablement for LOCALIO. If both NFS_FS=m and NFSD=m then
NFS_COMMON_LOCALIO_SUPPORT=m and nfs_localio.ko is built (and provides
nfs_common's LOCALIO support).
# lsmod | grep nfs_localio
nfs_localio 12288 2 nfsd,nfs
sunrpc 745472 35 nfs_localio,nfsd,auth_rpcgss,lockd,nfsv3,nfs
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Co-developed-by: NeilBrown <neilb@suse.de>
Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2024-09-05 15:09:48 -04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Global list of nfs_uuid_t instances
|
2024-11-15 20:41:01 -05:00
|
|
|
* that is protected by nfs_uuids_lock.
|
nfs_common: add NFS LOCALIO auxiliary protocol enablement
fs/nfs_common/nfslocalio.c provides interfaces that enable an NFS
client to generate a nonce (single-use UUID) and associated nfs_uuid_t
struct, register it with nfs_common for subsequent lookup and
verification by the NFS server and if matched the NFS server populates
members in the nfs_uuid_t struct.
nfs_common's nfs_uuids list is the basis for localio enablement, as
such it has members that point to nfsd memory for direct use by the
client (e.g. 'net' is the server's network namespace, through it the
client can access nn->nfsd_serv).
This commit also provides the base nfs_uuid_t interfaces to allow
proper net namespace refcounting for the LOCALIO use case.
CONFIG_NFS_LOCALIO controls the nfs_common, NFS server and NFS client
enablement for LOCALIO. If both NFS_FS=m and NFSD=m then
NFS_COMMON_LOCALIO_SUPPORT=m and nfs_localio.ko is built (and provides
nfs_common's LOCALIO support).
# lsmod | grep nfs_localio
nfs_localio 12288 2 nfsd,nfs
sunrpc 745472 35 nfs_localio,nfsd,auth_rpcgss,lockd,nfsv3,nfs
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Co-developed-by: NeilBrown <neilb@suse.de>
Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2024-09-05 15:09:48 -04:00
|
|
|
*/
|
|
|
|
static LIST_HEAD(nfs_uuids);
|
|
|
|
|
2024-11-15 20:41:02 -05:00
|
|
|
/*
|
|
|
|
* Lock ordering:
|
|
|
|
* 1: nfs_uuid->lock
|
|
|
|
* 2: nfs_uuids_lock
|
|
|
|
* 3: nfs_uuid->list_lock (aka nn->local_clients_lock)
|
|
|
|
*
|
|
|
|
* May skip locks in select cases, but never hold multiple
|
|
|
|
* locks out of order.
|
|
|
|
*/
|
|
|
|
|
2024-10-23 16:34:42 -04:00
|
|
|
void nfs_uuid_init(nfs_uuid_t *nfs_uuid)
|
nfs_common: add NFS LOCALIO auxiliary protocol enablement
fs/nfs_common/nfslocalio.c provides interfaces that enable an NFS
client to generate a nonce (single-use UUID) and associated nfs_uuid_t
struct, register it with nfs_common for subsequent lookup and
verification by the NFS server and if matched the NFS server populates
members in the nfs_uuid_t struct.
nfs_common's nfs_uuids list is the basis for localio enablement, as
such it has members that point to nfsd memory for direct use by the
client (e.g. 'net' is the server's network namespace, through it the
client can access nn->nfsd_serv).
This commit also provides the base nfs_uuid_t interfaces to allow
proper net namespace refcounting for the LOCALIO use case.
CONFIG_NFS_LOCALIO controls the nfs_common, NFS server and NFS client
enablement for LOCALIO. If both NFS_FS=m and NFSD=m then
NFS_COMMON_LOCALIO_SUPPORT=m and nfs_localio.ko is built (and provides
nfs_common's LOCALIO support).
# lsmod | grep nfs_localio
nfs_localio 12288 2 nfsd,nfs
sunrpc 745472 35 nfs_localio,nfsd,auth_rpcgss,lockd,nfsv3,nfs
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Co-developed-by: NeilBrown <neilb@suse.de>
Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2024-09-05 15:09:48 -04:00
|
|
|
{
|
2024-11-15 20:41:04 -05:00
|
|
|
RCU_INIT_POINTER(nfs_uuid->net, NULL);
|
nfs_common: add NFS LOCALIO auxiliary protocol enablement
fs/nfs_common/nfslocalio.c provides interfaces that enable an NFS
client to generate a nonce (single-use UUID) and associated nfs_uuid_t
struct, register it with nfs_common for subsequent lookup and
verification by the NFS server and if matched the NFS server populates
members in the nfs_uuid_t struct.
nfs_common's nfs_uuids list is the basis for localio enablement, as
such it has members that point to nfsd memory for direct use by the
client (e.g. 'net' is the server's network namespace, through it the
client can access nn->nfsd_serv).
This commit also provides the base nfs_uuid_t interfaces to allow
proper net namespace refcounting for the LOCALIO use case.
CONFIG_NFS_LOCALIO controls the nfs_common, NFS server and NFS client
enablement for LOCALIO. If both NFS_FS=m and NFSD=m then
NFS_COMMON_LOCALIO_SUPPORT=m and nfs_localio.ko is built (and provides
nfs_common's LOCALIO support).
# lsmod | grep nfs_localio
nfs_localio 12288 2 nfsd,nfs
sunrpc 745472 35 nfs_localio,nfsd,auth_rpcgss,lockd,nfsv3,nfs
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Co-developed-by: NeilBrown <neilb@suse.de>
Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2024-09-05 15:09:48 -04:00
|
|
|
nfs_uuid->dom = NULL;
|
2024-11-15 20:41:02 -05:00
|
|
|
nfs_uuid->list_lock = NULL;
|
2024-10-23 16:34:42 -04:00
|
|
|
INIT_LIST_HEAD(&nfs_uuid->list);
|
2024-11-15 20:41:02 -05:00
|
|
|
INIT_LIST_HEAD(&nfs_uuid->files);
|
2024-11-15 20:40:56 -05:00
|
|
|
spin_lock_init(&nfs_uuid->lock);
|
2024-11-15 20:41:06 -05:00
|
|
|
nfs_uuid->nfs3_localio_probe_count = 0;
|
2024-10-23 16:34:42 -04:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(nfs_uuid_init);
|
nfs_common: add NFS LOCALIO auxiliary protocol enablement
fs/nfs_common/nfslocalio.c provides interfaces that enable an NFS
client to generate a nonce (single-use UUID) and associated nfs_uuid_t
struct, register it with nfs_common for subsequent lookup and
verification by the NFS server and if matched the NFS server populates
members in the nfs_uuid_t struct.
nfs_common's nfs_uuids list is the basis for localio enablement, as
such it has members that point to nfsd memory for direct use by the
client (e.g. 'net' is the server's network namespace, through it the
client can access nn->nfsd_serv).
This commit also provides the base nfs_uuid_t interfaces to allow
proper net namespace refcounting for the LOCALIO use case.
CONFIG_NFS_LOCALIO controls the nfs_common, NFS server and NFS client
enablement for LOCALIO. If both NFS_FS=m and NFSD=m then
NFS_COMMON_LOCALIO_SUPPORT=m and nfs_localio.ko is built (and provides
nfs_common's LOCALIO support).
# lsmod | grep nfs_localio
nfs_localio 12288 2 nfsd,nfs
sunrpc 745472 35 nfs_localio,nfsd,auth_rpcgss,lockd,nfsv3,nfs
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Co-developed-by: NeilBrown <neilb@suse.de>
Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2024-09-05 15:09:48 -04:00
|
|
|
|
2024-10-23 16:34:42 -04:00
|
|
|
bool nfs_uuid_begin(nfs_uuid_t *nfs_uuid)
|
|
|
|
{
|
2024-11-15 20:41:02 -05:00
|
|
|
spin_lock(&nfs_uuid->lock);
|
2024-11-15 20:41:04 -05:00
|
|
|
if (rcu_access_pointer(nfs_uuid->net)) {
|
2024-11-15 20:41:02 -05:00
|
|
|
/* This nfs_uuid is already in use */
|
|
|
|
spin_unlock(&nfs_uuid->lock);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-11-15 20:41:01 -05:00
|
|
|
spin_lock(&nfs_uuids_lock);
|
2024-10-23 16:34:42 -04:00
|
|
|
if (!list_empty(&nfs_uuid->list)) {
|
2024-11-15 20:41:02 -05:00
|
|
|
/* This nfs_uuid is already in use */
|
2024-11-15 20:41:01 -05:00
|
|
|
spin_unlock(&nfs_uuids_lock);
|
2024-11-15 20:41:02 -05:00
|
|
|
spin_unlock(&nfs_uuid->lock);
|
2024-10-23 16:34:42 -04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
list_add_tail(&nfs_uuid->list, &nfs_uuids);
|
2024-11-15 20:41:01 -05:00
|
|
|
spin_unlock(&nfs_uuids_lock);
|
2024-10-23 16:34:42 -04:00
|
|
|
|
2024-11-15 20:41:02 -05:00
|
|
|
uuid_gen(&nfs_uuid->uuid);
|
|
|
|
spin_unlock(&nfs_uuid->lock);
|
|
|
|
|
2024-10-23 16:34:42 -04:00
|
|
|
return true;
|
nfs_common: add NFS LOCALIO auxiliary protocol enablement
fs/nfs_common/nfslocalio.c provides interfaces that enable an NFS
client to generate a nonce (single-use UUID) and associated nfs_uuid_t
struct, register it with nfs_common for subsequent lookup and
verification by the NFS server and if matched the NFS server populates
members in the nfs_uuid_t struct.
nfs_common's nfs_uuids list is the basis for localio enablement, as
such it has members that point to nfsd memory for direct use by the
client (e.g. 'net' is the server's network namespace, through it the
client can access nn->nfsd_serv).
This commit also provides the base nfs_uuid_t interfaces to allow
proper net namespace refcounting for the LOCALIO use case.
CONFIG_NFS_LOCALIO controls the nfs_common, NFS server and NFS client
enablement for LOCALIO. If both NFS_FS=m and NFSD=m then
NFS_COMMON_LOCALIO_SUPPORT=m and nfs_localio.ko is built (and provides
nfs_common's LOCALIO support).
# lsmod | grep nfs_localio
nfs_localio 12288 2 nfsd,nfs
sunrpc 745472 35 nfs_localio,nfsd,auth_rpcgss,lockd,nfsv3,nfs
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Co-developed-by: NeilBrown <neilb@suse.de>
Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2024-09-05 15:09:48 -04:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(nfs_uuid_begin);
|
|
|
|
|
|
|
|
void nfs_uuid_end(nfs_uuid_t *nfs_uuid)
|
|
|
|
{
|
2024-11-15 20:41:04 -05:00
|
|
|
if (!rcu_access_pointer(nfs_uuid->net)) {
|
2024-11-15 20:41:02 -05:00
|
|
|
spin_lock(&nfs_uuid->lock);
|
2024-11-15 20:41:04 -05:00
|
|
|
if (!rcu_access_pointer(nfs_uuid->net)) {
|
2024-11-15 20:41:02 -05:00
|
|
|
/* Not local, remove from nfs_uuids */
|
|
|
|
spin_lock(&nfs_uuids_lock);
|
2024-10-23 16:34:42 -04:00
|
|
|
list_del_init(&nfs_uuid->list);
|
2024-11-15 20:41:02 -05:00
|
|
|
spin_unlock(&nfs_uuids_lock);
|
|
|
|
}
|
|
|
|
spin_unlock(&nfs_uuid->lock);
|
|
|
|
}
|
nfs_common: add NFS LOCALIO auxiliary protocol enablement
fs/nfs_common/nfslocalio.c provides interfaces that enable an NFS
client to generate a nonce (single-use UUID) and associated nfs_uuid_t
struct, register it with nfs_common for subsequent lookup and
verification by the NFS server and if matched the NFS server populates
members in the nfs_uuid_t struct.
nfs_common's nfs_uuids list is the basis for localio enablement, as
such it has members that point to nfsd memory for direct use by the
client (e.g. 'net' is the server's network namespace, through it the
client can access nn->nfsd_serv).
This commit also provides the base nfs_uuid_t interfaces to allow
proper net namespace refcounting for the LOCALIO use case.
CONFIG_NFS_LOCALIO controls the nfs_common, NFS server and NFS client
enablement for LOCALIO. If both NFS_FS=m and NFSD=m then
NFS_COMMON_LOCALIO_SUPPORT=m and nfs_localio.ko is built (and provides
nfs_common's LOCALIO support).
# lsmod | grep nfs_localio
nfs_localio 12288 2 nfsd,nfs
sunrpc 745472 35 nfs_localio,nfsd,auth_rpcgss,lockd,nfsv3,nfs
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Co-developed-by: NeilBrown <neilb@suse.de>
Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2024-09-05 15:09:48 -04:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(nfs_uuid_end);
|
|
|
|
|
|
|
|
static nfs_uuid_t * nfs_uuid_lookup_locked(const uuid_t *uuid)
|
|
|
|
{
|
|
|
|
nfs_uuid_t *nfs_uuid;
|
|
|
|
|
|
|
|
list_for_each_entry(nfs_uuid, &nfs_uuids, list)
|
|
|
|
if (uuid_equal(&nfs_uuid->uuid, uuid))
|
|
|
|
return nfs_uuid;
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct module *nfsd_mod;
|
|
|
|
|
|
|
|
void nfs_uuid_is_local(const uuid_t *uuid, struct list_head *list,
|
2024-11-15 20:41:02 -05:00
|
|
|
spinlock_t *list_lock, struct net *net,
|
|
|
|
struct auth_domain *dom, struct module *mod)
|
nfs_common: add NFS LOCALIO auxiliary protocol enablement
fs/nfs_common/nfslocalio.c provides interfaces that enable an NFS
client to generate a nonce (single-use UUID) and associated nfs_uuid_t
struct, register it with nfs_common for subsequent lookup and
verification by the NFS server and if matched the NFS server populates
members in the nfs_uuid_t struct.
nfs_common's nfs_uuids list is the basis for localio enablement, as
such it has members that point to nfsd memory for direct use by the
client (e.g. 'net' is the server's network namespace, through it the
client can access nn->nfsd_serv).
This commit also provides the base nfs_uuid_t interfaces to allow
proper net namespace refcounting for the LOCALIO use case.
CONFIG_NFS_LOCALIO controls the nfs_common, NFS server and NFS client
enablement for LOCALIO. If both NFS_FS=m and NFSD=m then
NFS_COMMON_LOCALIO_SUPPORT=m and nfs_localio.ko is built (and provides
nfs_common's LOCALIO support).
# lsmod | grep nfs_localio
nfs_localio 12288 2 nfsd,nfs
sunrpc 745472 35 nfs_localio,nfsd,auth_rpcgss,lockd,nfsv3,nfs
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Co-developed-by: NeilBrown <neilb@suse.de>
Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2024-09-05 15:09:48 -04:00
|
|
|
{
|
|
|
|
nfs_uuid_t *nfs_uuid;
|
|
|
|
|
2024-11-15 20:41:01 -05:00
|
|
|
spin_lock(&nfs_uuids_lock);
|
nfs_common: add NFS LOCALIO auxiliary protocol enablement
fs/nfs_common/nfslocalio.c provides interfaces that enable an NFS
client to generate a nonce (single-use UUID) and associated nfs_uuid_t
struct, register it with nfs_common for subsequent lookup and
verification by the NFS server and if matched the NFS server populates
members in the nfs_uuid_t struct.
nfs_common's nfs_uuids list is the basis for localio enablement, as
such it has members that point to nfsd memory for direct use by the
client (e.g. 'net' is the server's network namespace, through it the
client can access nn->nfsd_serv).
This commit also provides the base nfs_uuid_t interfaces to allow
proper net namespace refcounting for the LOCALIO use case.
CONFIG_NFS_LOCALIO controls the nfs_common, NFS server and NFS client
enablement for LOCALIO. If both NFS_FS=m and NFSD=m then
NFS_COMMON_LOCALIO_SUPPORT=m and nfs_localio.ko is built (and provides
nfs_common's LOCALIO support).
# lsmod | grep nfs_localio
nfs_localio 12288 2 nfsd,nfs
sunrpc 745472 35 nfs_localio,nfsd,auth_rpcgss,lockd,nfsv3,nfs
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Co-developed-by: NeilBrown <neilb@suse.de>
Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2024-09-05 15:09:48 -04:00
|
|
|
nfs_uuid = nfs_uuid_lookup_locked(uuid);
|
2024-11-15 20:41:02 -05:00
|
|
|
if (!nfs_uuid) {
|
|
|
|
spin_unlock(&nfs_uuids_lock);
|
|
|
|
return;
|
nfs_common: add NFS LOCALIO auxiliary protocol enablement
fs/nfs_common/nfslocalio.c provides interfaces that enable an NFS
client to generate a nonce (single-use UUID) and associated nfs_uuid_t
struct, register it with nfs_common for subsequent lookup and
verification by the NFS server and if matched the NFS server populates
members in the nfs_uuid_t struct.
nfs_common's nfs_uuids list is the basis for localio enablement, as
such it has members that point to nfsd memory for direct use by the
client (e.g. 'net' is the server's network namespace, through it the
client can access nn->nfsd_serv).
This commit also provides the base nfs_uuid_t interfaces to allow
proper net namespace refcounting for the LOCALIO use case.
CONFIG_NFS_LOCALIO controls the nfs_common, NFS server and NFS client
enablement for LOCALIO. If both NFS_FS=m and NFSD=m then
NFS_COMMON_LOCALIO_SUPPORT=m and nfs_localio.ko is built (and provides
nfs_common's LOCALIO support).
# lsmod | grep nfs_localio
nfs_localio 12288 2 nfsd,nfs
sunrpc 745472 35 nfs_localio,nfsd,auth_rpcgss,lockd,nfsv3,nfs
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Co-developed-by: NeilBrown <neilb@suse.de>
Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2024-09-05 15:09:48 -04:00
|
|
|
}
|
2024-11-15 20:41:02 -05:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We don't hold a ref on the net, but instead put
|
|
|
|
* ourselves on @list (nn->local_clients) so the net
|
|
|
|
* pointer can be invalidated.
|
|
|
|
*/
|
|
|
|
spin_lock(list_lock); /* list_lock is nn->local_clients_lock */
|
|
|
|
list_move(&nfs_uuid->list, list);
|
|
|
|
spin_unlock(list_lock);
|
|
|
|
|
2024-11-15 20:41:01 -05:00
|
|
|
spin_unlock(&nfs_uuids_lock);
|
2024-11-15 20:41:02 -05:00
|
|
|
/* Once nfs_uuid is parented to @list, avoid global nfs_uuids_lock */
|
|
|
|
spin_lock(&nfs_uuid->lock);
|
|
|
|
|
|
|
|
__module_get(mod);
|
|
|
|
nfsd_mod = mod;
|
|
|
|
|
|
|
|
nfs_uuid->list_lock = list_lock;
|
|
|
|
kref_get(&dom->ref);
|
|
|
|
nfs_uuid->dom = dom;
|
|
|
|
rcu_assign_pointer(nfs_uuid->net, net);
|
|
|
|
spin_unlock(&nfs_uuid->lock);
|
nfs_common: add NFS LOCALIO auxiliary protocol enablement
fs/nfs_common/nfslocalio.c provides interfaces that enable an NFS
client to generate a nonce (single-use UUID) and associated nfs_uuid_t
struct, register it with nfs_common for subsequent lookup and
verification by the NFS server and if matched the NFS server populates
members in the nfs_uuid_t struct.
nfs_common's nfs_uuids list is the basis for localio enablement, as
such it has members that point to nfsd memory for direct use by the
client (e.g. 'net' is the server's network namespace, through it the
client can access nn->nfsd_serv).
This commit also provides the base nfs_uuid_t interfaces to allow
proper net namespace refcounting for the LOCALIO use case.
CONFIG_NFS_LOCALIO controls the nfs_common, NFS server and NFS client
enablement for LOCALIO. If both NFS_FS=m and NFSD=m then
NFS_COMMON_LOCALIO_SUPPORT=m and nfs_localio.ko is built (and provides
nfs_common's LOCALIO support).
# lsmod | grep nfs_localio
nfs_localio 12288 2 nfsd,nfs
sunrpc 745472 35 nfs_localio,nfsd,auth_rpcgss,lockd,nfsv3,nfs
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Co-developed-by: NeilBrown <neilb@suse.de>
Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2024-09-05 15:09:48 -04:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(nfs_uuid_is_local);
|
|
|
|
|
2024-11-15 20:40:56 -05:00
|
|
|
void nfs_localio_enable_client(struct nfs_client *clp)
|
|
|
|
{
|
2024-11-15 20:41:04 -05:00
|
|
|
/* nfs_uuid_is_local() does the actual enablement */
|
2024-11-15 20:41:03 -05:00
|
|
|
trace_nfs_localio_enable_client(clp);
|
2024-11-15 20:40:56 -05:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(nfs_localio_enable_client);
|
|
|
|
|
2024-11-15 20:41:02 -05:00
|
|
|
/*
|
|
|
|
* Cleanup the nfs_uuid_t embedded in an nfs_client.
|
|
|
|
* This is the long-form of nfs_uuid_init().
|
|
|
|
*/
|
2024-11-15 20:41:04 -05:00
|
|
|
static bool nfs_uuid_put(nfs_uuid_t *nfs_uuid)
|
nfs_common: add NFS LOCALIO auxiliary protocol enablement
fs/nfs_common/nfslocalio.c provides interfaces that enable an NFS
client to generate a nonce (single-use UUID) and associated nfs_uuid_t
struct, register it with nfs_common for subsequent lookup and
verification by the NFS server and if matched the NFS server populates
members in the nfs_uuid_t struct.
nfs_common's nfs_uuids list is the basis for localio enablement, as
such it has members that point to nfsd memory for direct use by the
client (e.g. 'net' is the server's network namespace, through it the
client can access nn->nfsd_serv).
This commit also provides the base nfs_uuid_t interfaces to allow
proper net namespace refcounting for the LOCALIO use case.
CONFIG_NFS_LOCALIO controls the nfs_common, NFS server and NFS client
enablement for LOCALIO. If both NFS_FS=m and NFSD=m then
NFS_COMMON_LOCALIO_SUPPORT=m and nfs_localio.ko is built (and provides
nfs_common's LOCALIO support).
# lsmod | grep nfs_localio
nfs_localio 12288 2 nfsd,nfs
sunrpc 745472 35 nfs_localio,nfsd,auth_rpcgss,lockd,nfsv3,nfs
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Co-developed-by: NeilBrown <neilb@suse.de>
Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2024-09-05 15:09:48 -04:00
|
|
|
{
|
2024-11-15 20:41:02 -05:00
|
|
|
LIST_HEAD(local_files);
|
|
|
|
struct nfs_file_localio *nfl, *tmp;
|
|
|
|
|
|
|
|
spin_lock(&nfs_uuid->lock);
|
2024-11-15 20:41:04 -05:00
|
|
|
if (unlikely(!rcu_access_pointer(nfs_uuid->net))) {
|
2024-11-15 20:41:02 -05:00
|
|
|
spin_unlock(&nfs_uuid->lock);
|
2024-11-15 20:41:04 -05:00
|
|
|
return false;
|
2024-11-15 20:41:02 -05:00
|
|
|
}
|
2024-11-15 20:40:56 -05:00
|
|
|
RCU_INIT_POINTER(nfs_uuid->net, NULL);
|
|
|
|
|
nfs_common: add NFS LOCALIO auxiliary protocol enablement
fs/nfs_common/nfslocalio.c provides interfaces that enable an NFS
client to generate a nonce (single-use UUID) and associated nfs_uuid_t
struct, register it with nfs_common for subsequent lookup and
verification by the NFS server and if matched the NFS server populates
members in the nfs_uuid_t struct.
nfs_common's nfs_uuids list is the basis for localio enablement, as
such it has members that point to nfsd memory for direct use by the
client (e.g. 'net' is the server's network namespace, through it the
client can access nn->nfsd_serv).
This commit also provides the base nfs_uuid_t interfaces to allow
proper net namespace refcounting for the LOCALIO use case.
CONFIG_NFS_LOCALIO controls the nfs_common, NFS server and NFS client
enablement for LOCALIO. If both NFS_FS=m and NFSD=m then
NFS_COMMON_LOCALIO_SUPPORT=m and nfs_localio.ko is built (and provides
nfs_common's LOCALIO support).
# lsmod | grep nfs_localio
nfs_localio 12288 2 nfsd,nfs
sunrpc 745472 35 nfs_localio,nfsd,auth_rpcgss,lockd,nfsv3,nfs
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Co-developed-by: NeilBrown <neilb@suse.de>
Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2024-09-05 15:09:48 -04:00
|
|
|
if (nfs_uuid->dom) {
|
|
|
|
auth_domain_put(nfs_uuid->dom);
|
|
|
|
nfs_uuid->dom = NULL;
|
|
|
|
}
|
2024-11-15 20:41:02 -05:00
|
|
|
|
|
|
|
list_splice_init(&nfs_uuid->files, &local_files);
|
|
|
|
spin_unlock(&nfs_uuid->lock);
|
|
|
|
|
|
|
|
/* Walk list of files and ensure their last references dropped */
|
|
|
|
list_for_each_entry_safe(nfl, tmp, &local_files, list) {
|
|
|
|
nfs_close_local_fh(nfl);
|
|
|
|
cond_resched();
|
|
|
|
}
|
|
|
|
|
|
|
|
spin_lock(&nfs_uuid->lock);
|
|
|
|
BUG_ON(!list_empty(&nfs_uuid->files));
|
|
|
|
|
|
|
|
/* Remove client from nn->local_clients */
|
|
|
|
if (nfs_uuid->list_lock) {
|
|
|
|
spin_lock(nfs_uuid->list_lock);
|
|
|
|
BUG_ON(list_empty(&nfs_uuid->list));
|
|
|
|
list_del_init(&nfs_uuid->list);
|
|
|
|
spin_unlock(nfs_uuid->list_lock);
|
|
|
|
nfs_uuid->list_lock = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
module_put(nfsd_mod);
|
|
|
|
spin_unlock(&nfs_uuid->lock);
|
2024-11-15 20:41:04 -05:00
|
|
|
|
|
|
|
return true;
|
nfs_common: add NFS LOCALIO auxiliary protocol enablement
fs/nfs_common/nfslocalio.c provides interfaces that enable an NFS
client to generate a nonce (single-use UUID) and associated nfs_uuid_t
struct, register it with nfs_common for subsequent lookup and
verification by the NFS server and if matched the NFS server populates
members in the nfs_uuid_t struct.
nfs_common's nfs_uuids list is the basis for localio enablement, as
such it has members that point to nfsd memory for direct use by the
client (e.g. 'net' is the server's network namespace, through it the
client can access nn->nfsd_serv).
This commit also provides the base nfs_uuid_t interfaces to allow
proper net namespace refcounting for the LOCALIO use case.
CONFIG_NFS_LOCALIO controls the nfs_common, NFS server and NFS client
enablement for LOCALIO. If both NFS_FS=m and NFSD=m then
NFS_COMMON_LOCALIO_SUPPORT=m and nfs_localio.ko is built (and provides
nfs_common's LOCALIO support).
# lsmod | grep nfs_localio
nfs_localio 12288 2 nfsd,nfs
sunrpc 745472 35 nfs_localio,nfsd,auth_rpcgss,lockd,nfsv3,nfs
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Co-developed-by: NeilBrown <neilb@suse.de>
Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2024-09-05 15:09:48 -04:00
|
|
|
}
|
|
|
|
|
2024-11-15 20:40:56 -05:00
|
|
|
void nfs_localio_disable_client(struct nfs_client *clp)
|
nfs_common: add NFS LOCALIO auxiliary protocol enablement
fs/nfs_common/nfslocalio.c provides interfaces that enable an NFS
client to generate a nonce (single-use UUID) and associated nfs_uuid_t
struct, register it with nfs_common for subsequent lookup and
verification by the NFS server and if matched the NFS server populates
members in the nfs_uuid_t struct.
nfs_common's nfs_uuids list is the basis for localio enablement, as
such it has members that point to nfsd memory for direct use by the
client (e.g. 'net' is the server's network namespace, through it the
client can access nn->nfsd_serv).
This commit also provides the base nfs_uuid_t interfaces to allow
proper net namespace refcounting for the LOCALIO use case.
CONFIG_NFS_LOCALIO controls the nfs_common, NFS server and NFS client
enablement for LOCALIO. If both NFS_FS=m and NFSD=m then
NFS_COMMON_LOCALIO_SUPPORT=m and nfs_localio.ko is built (and provides
nfs_common's LOCALIO support).
# lsmod | grep nfs_localio
nfs_localio 12288 2 nfsd,nfs
sunrpc 745472 35 nfs_localio,nfsd,auth_rpcgss,lockd,nfsv3,nfs
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Co-developed-by: NeilBrown <neilb@suse.de>
Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2024-09-05 15:09:48 -04:00
|
|
|
{
|
2024-11-15 20:41:04 -05:00
|
|
|
if (nfs_uuid_put(&clp->cl_uuid))
|
2024-11-15 20:41:03 -05:00
|
|
|
trace_nfs_localio_disable_client(clp);
|
nfs_common: add NFS LOCALIO auxiliary protocol enablement
fs/nfs_common/nfslocalio.c provides interfaces that enable an NFS
client to generate a nonce (single-use UUID) and associated nfs_uuid_t
struct, register it with nfs_common for subsequent lookup and
verification by the NFS server and if matched the NFS server populates
members in the nfs_uuid_t struct.
nfs_common's nfs_uuids list is the basis for localio enablement, as
such it has members that point to nfsd memory for direct use by the
client (e.g. 'net' is the server's network namespace, through it the
client can access nn->nfsd_serv).
This commit also provides the base nfs_uuid_t interfaces to allow
proper net namespace refcounting for the LOCALIO use case.
CONFIG_NFS_LOCALIO controls the nfs_common, NFS server and NFS client
enablement for LOCALIO. If both NFS_FS=m and NFSD=m then
NFS_COMMON_LOCALIO_SUPPORT=m and nfs_localio.ko is built (and provides
nfs_common's LOCALIO support).
# lsmod | grep nfs_localio
nfs_localio 12288 2 nfsd,nfs
sunrpc 745472 35 nfs_localio,nfsd,auth_rpcgss,lockd,nfsv3,nfs
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Co-developed-by: NeilBrown <neilb@suse.de>
Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
2024-09-05 15:09:48 -04:00
|
|
|
}
|
2024-11-15 20:40:55 -05:00
|
|
|
EXPORT_SYMBOL_GPL(nfs_localio_disable_client);
|
2024-09-05 15:09:49 -04:00
|
|
|
|
2024-11-15 20:41:02 -05:00
|
|
|
void nfs_localio_invalidate_clients(struct list_head *nn_local_clients,
|
|
|
|
spinlock_t *nn_local_clients_lock)
|
2024-11-15 20:40:56 -05:00
|
|
|
{
|
2024-11-15 20:41:02 -05:00
|
|
|
LIST_HEAD(local_clients);
|
2024-11-15 20:40:56 -05:00
|
|
|
nfs_uuid_t *nfs_uuid, *tmp;
|
2024-11-15 20:41:02 -05:00
|
|
|
struct nfs_client *clp;
|
|
|
|
|
|
|
|
spin_lock(nn_local_clients_lock);
|
|
|
|
list_splice_init(nn_local_clients, &local_clients);
|
|
|
|
spin_unlock(nn_local_clients_lock);
|
|
|
|
list_for_each_entry_safe(nfs_uuid, tmp, &local_clients, list) {
|
|
|
|
if (WARN_ON(nfs_uuid->list_lock != nn_local_clients_lock))
|
|
|
|
break;
|
|
|
|
clp = container_of(nfs_uuid, struct nfs_client, cl_uuid);
|
2024-11-15 20:40:56 -05:00
|
|
|
nfs_localio_disable_client(clp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(nfs_localio_invalidate_clients);
|
|
|
|
|
2024-11-15 20:40:57 -05:00
|
|
|
static void nfs_uuid_add_file(nfs_uuid_t *nfs_uuid, struct nfs_file_localio *nfl)
|
|
|
|
{
|
2024-11-15 20:41:02 -05:00
|
|
|
/* Add nfl to nfs_uuid->files if it isn't already */
|
|
|
|
spin_lock(&nfs_uuid->lock);
|
|
|
|
if (list_empty(&nfl->list)) {
|
2024-11-15 20:40:57 -05:00
|
|
|
rcu_assign_pointer(nfl->nfs_uuid, nfs_uuid);
|
2024-11-15 20:41:02 -05:00
|
|
|
list_add_tail(&nfl->list, &nfs_uuid->files);
|
|
|
|
}
|
|
|
|
spin_unlock(&nfs_uuid->lock);
|
2024-11-15 20:40:57 -05:00
|
|
|
}
|
|
|
|
|
2024-11-15 20:40:59 -05:00
|
|
|
/*
|
|
|
|
* Caller is responsible for calling nfsd_net_put and
|
|
|
|
* nfsd_file_put (via nfs_to_nfsd_file_put_local).
|
|
|
|
*/
|
2024-09-05 15:09:53 -04:00
|
|
|
struct nfsd_file *nfs_open_local_fh(nfs_uuid_t *uuid,
|
|
|
|
struct rpc_clnt *rpc_clnt, const struct cred *cred,
|
2024-11-15 20:40:57 -05:00
|
|
|
const struct nfs_fh *nfs_fh, struct nfs_file_localio *nfl,
|
|
|
|
const fmode_t fmode)
|
2024-09-05 15:09:53 -04:00
|
|
|
{
|
|
|
|
struct net *net;
|
|
|
|
struct nfsd_file *localio;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Not running in nfsd context, so must safely get reference on nfsd_serv.
|
|
|
|
* But the server may already be shutting down, if so disallow new localio.
|
|
|
|
* uuid->net is NOT a counted reference, but rcu_read_lock() ensures that
|
2024-11-15 20:40:59 -05:00
|
|
|
* if uuid->net is not NULL, then calling nfsd_net_try_get() is safe
|
2024-09-05 15:09:53 -04:00
|
|
|
* and if it succeeds we will have an implied reference to the net.
|
|
|
|
*
|
|
|
|
* Otherwise NFS may not have ref on NFSD and therefore cannot safely
|
|
|
|
* make 'nfs_to' calls.
|
|
|
|
*/
|
|
|
|
rcu_read_lock();
|
|
|
|
net = rcu_dereference(uuid->net);
|
2024-11-15 20:40:59 -05:00
|
|
|
if (!net || !nfs_to->nfsd_net_try_get(net)) {
|
2024-09-05 15:09:53 -04:00
|
|
|
rcu_read_unlock();
|
|
|
|
return ERR_PTR(-ENXIO);
|
|
|
|
}
|
|
|
|
rcu_read_unlock();
|
2024-11-15 20:40:59 -05:00
|
|
|
/* We have an implied reference to net thanks to nfsd_net_try_get */
|
2024-09-05 15:09:53 -04:00
|
|
|
localio = nfs_to->nfsd_open_local_fh(net, uuid->dom, rpc_clnt,
|
|
|
|
cred, nfs_fh, fmode);
|
2024-11-13 22:59:38 -05:00
|
|
|
if (IS_ERR(localio))
|
|
|
|
nfs_to_nfsd_net_put(net);
|
2024-11-15 20:40:57 -05:00
|
|
|
else
|
|
|
|
nfs_uuid_add_file(uuid, nfl);
|
2024-11-13 22:59:38 -05:00
|
|
|
|
2024-09-05 15:09:53 -04:00
|
|
|
return localio;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(nfs_open_local_fh);
|
|
|
|
|
2024-11-15 20:40:57 -05:00
|
|
|
void nfs_close_local_fh(struct nfs_file_localio *nfl)
|
|
|
|
{
|
|
|
|
struct nfsd_file *ro_nf = NULL;
|
|
|
|
struct nfsd_file *rw_nf = NULL;
|
|
|
|
nfs_uuid_t *nfs_uuid;
|
|
|
|
|
|
|
|
rcu_read_lock();
|
|
|
|
nfs_uuid = rcu_dereference(nfl->nfs_uuid);
|
|
|
|
if (!nfs_uuid) {
|
|
|
|
/* regular (non-LOCALIO) NFS will hammer this */
|
|
|
|
rcu_read_unlock();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ro_nf = rcu_access_pointer(nfl->ro_file);
|
|
|
|
rw_nf = rcu_access_pointer(nfl->rw_file);
|
|
|
|
if (ro_nf || rw_nf) {
|
2024-11-15 20:41:02 -05:00
|
|
|
spin_lock(&nfs_uuid->lock);
|
2024-11-15 20:40:57 -05:00
|
|
|
if (ro_nf)
|
|
|
|
ro_nf = rcu_dereference_protected(xchg(&nfl->ro_file, NULL), 1);
|
|
|
|
if (rw_nf)
|
|
|
|
rw_nf = rcu_dereference_protected(xchg(&nfl->rw_file, NULL), 1);
|
|
|
|
|
2024-11-15 20:41:02 -05:00
|
|
|
/* Remove nfl from nfs_uuid->files list */
|
|
|
|
RCU_INIT_POINTER(nfl->nfs_uuid, NULL);
|
|
|
|
list_del_init(&nfl->list);
|
|
|
|
spin_unlock(&nfs_uuid->lock);
|
2024-11-15 20:40:57 -05:00
|
|
|
rcu_read_unlock();
|
|
|
|
|
|
|
|
if (ro_nf)
|
|
|
|
nfs_to_nfsd_file_put_local(ro_nf);
|
|
|
|
if (rw_nf)
|
|
|
|
nfs_to_nfsd_file_put_local(rw_nf);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
rcu_read_unlock();
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(nfs_close_local_fh);
|
|
|
|
|
2024-09-05 15:09:49 -04:00
|
|
|
/*
|
|
|
|
* The NFS LOCALIO code needs to call into NFSD using various symbols,
|
|
|
|
* but cannot be statically linked, because that will make the NFS
|
|
|
|
* module always depend on the NFSD module.
|
|
|
|
*
|
|
|
|
* 'nfs_to' provides NFS access to NFSD functions needed for LOCALIO,
|
|
|
|
* its lifetime is tightly coupled to the NFSD module and will always
|
|
|
|
* be available to NFS LOCALIO because any successful client<->server
|
|
|
|
* LOCALIO handshake results in a reference on the NFSD module (above),
|
|
|
|
* so NFS implicitly holds a reference to the NFSD module and its
|
|
|
|
* functions in the 'nfs_to' nfsd_localio_operations cannot disappear.
|
|
|
|
*
|
|
|
|
* If the last NFS client using LOCALIO disconnects (and its reference
|
|
|
|
* on NFSD dropped) then NFSD could be unloaded, resulting in 'nfs_to'
|
|
|
|
* functions being invalid pointers. But if NFSD isn't loaded then NFS
|
|
|
|
* will not be able to handshake with NFSD and will have no cause to
|
|
|
|
* try to call 'nfs_to' function pointers. If/when NFSD is reloaded it
|
|
|
|
* will reinitialize the 'nfs_to' function pointers and make LOCALIO
|
|
|
|
* possible.
|
|
|
|
*/
|
|
|
|
const struct nfsd_localio_operations *nfs_to;
|
|
|
|
EXPORT_SYMBOL_GPL(nfs_to);
|