Skip to content

Commit 6b9785d

Browse files
jtlaytonTrond Myklebust
authored andcommitted
nfs: don't share pNFS DS connections between net namespaces
Currently, different NFS clients can share the same DS connections, even when they are in different net namespaces. If a containerized client creates a DS connection, another container can find and use it. When the first client exits, the connection will close which can lead to stalls in other clients. Add a net namespace pointer to struct nfs4_pnfs_ds, and compare those value to the caller's netns in _data_server_lookup_locked() when searching for a nfs4_pnfs_ds to match. Reported-by: Omar Sandoval <osandov@osandov.com> Reported-by: Sargun Dillon <sargun@sargun.me> Closes: https://lore.kernel.org/linux-nfs/Z_ArpQC_vREh_hEA@telecaster/ Tested-by: Sargun Dillon <sargun@sargun.me> Signed-off-by: Jeff Layton <jlayton@kernel.org> Reviewed-by: Benjamin Coddington <bcodding@redhat.com> Link: https://lore.kernel.org/r/20250410-nfs-ds-netns-v2-1-f80b7979ba80@kernel.org Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
1 parent c457dc1 commit 6b9785d

File tree

4 files changed

+14
-11
lines changed

4 files changed

+14
-11
lines changed

fs/nfs/filelayout/filelayoutdev.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ nfs4_fl_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev,
7676
struct page *scratch;
7777
struct list_head dsaddrs;
7878
struct nfs4_pnfs_ds_addr *da;
79+
struct net *net = server->nfs_client->cl_net;
7980

8081
/* set up xdr stream */
8182
scratch = alloc_page(gfp_flags);
@@ -159,8 +160,7 @@ nfs4_fl_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev,
159160

160161
mp_count = be32_to_cpup(p); /* multipath count */
161162
for (j = 0; j < mp_count; j++) {
162-
da = nfs4_decode_mp_ds_addr(server->nfs_client->cl_net,
163-
&stream, gfp_flags);
163+
da = nfs4_decode_mp_ds_addr(net, &stream, gfp_flags);
164164
if (da)
165165
list_add_tail(&da->da_node, &dsaddrs);
166166
}
@@ -170,7 +170,7 @@ nfs4_fl_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev,
170170
goto out_err_free_deviceid;
171171
}
172172

173-
dsaddr->ds_list[i] = nfs4_pnfs_ds_add(&dsaddrs, gfp_flags);
173+
dsaddr->ds_list[i] = nfs4_pnfs_ds_add(net, &dsaddrs, gfp_flags);
174174
if (!dsaddr->ds_list[i])
175175
goto out_err_drain_dsaddrs;
176176
trace_fl_getdevinfo(server, &pdev->dev_id, dsaddr->ds_list[i]->ds_remotestr);

fs/nfs/flexfilelayout/flexfilelayoutdev.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ nfs4_ff_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev,
4949
struct nfs4_pnfs_ds_addr *da;
5050
struct nfs4_ff_layout_ds *new_ds = NULL;
5151
struct nfs4_ff_ds_version *ds_versions = NULL;
52+
struct net *net = server->nfs_client->cl_net;
5253
u32 mp_count;
5354
u32 version_count;
5455
__be32 *p;
@@ -80,8 +81,7 @@ nfs4_ff_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev,
8081

8182
for (i = 0; i < mp_count; i++) {
8283
/* multipath ds */
83-
da = nfs4_decode_mp_ds_addr(server->nfs_client->cl_net,
84-
&stream, gfp_flags);
84+
da = nfs4_decode_mp_ds_addr(net, &stream, gfp_flags);
8585
if (da)
8686
list_add_tail(&da->da_node, &dsaddrs);
8787
}
@@ -149,7 +149,7 @@ nfs4_ff_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev,
149149
new_ds->ds_versions = ds_versions;
150150
new_ds->ds_versions_cnt = version_count;
151151

152-
new_ds->ds = nfs4_pnfs_ds_add(&dsaddrs, gfp_flags);
152+
new_ds->ds = nfs4_pnfs_ds_add(net, &dsaddrs, gfp_flags);
153153
if (!new_ds->ds)
154154
goto out_err_drain_dsaddrs;
155155

fs/nfs/pnfs.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ struct nfs4_pnfs_ds {
6060
struct list_head ds_node; /* nfs4_pnfs_dev_hlist dev_dslist */
6161
char *ds_remotestr; /* comma sep list of addrs */
6262
struct list_head ds_addrs;
63+
const struct net *ds_net;
6364
struct nfs_client *ds_clp;
6465
refcount_t ds_count;
6566
unsigned long ds_state;
@@ -415,7 +416,8 @@ int pnfs_generic_commit_pagelist(struct inode *inode,
415416
int pnfs_generic_scan_commit_lists(struct nfs_commit_info *cinfo, int max);
416417
void pnfs_generic_write_commit_done(struct rpc_task *task, void *data);
417418
void nfs4_pnfs_ds_put(struct nfs4_pnfs_ds *ds);
418-
struct nfs4_pnfs_ds *nfs4_pnfs_ds_add(struct list_head *dsaddrs,
419+
struct nfs4_pnfs_ds *nfs4_pnfs_ds_add(const struct net *net,
420+
struct list_head *dsaddrs,
419421
gfp_t gfp_flags);
420422
void nfs4_pnfs_v3_ds_connect_unload(void);
421423
int nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds,

fs/nfs/pnfs_nfs.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -604,12 +604,12 @@ _same_data_server_addrs_locked(const struct list_head *dsaddrs1,
604604
* Lookup DS by addresses. nfs4_ds_cache_lock is held
605605
*/
606606
static struct nfs4_pnfs_ds *
607-
_data_server_lookup_locked(const struct list_head *dsaddrs)
607+
_data_server_lookup_locked(const struct net *net, const struct list_head *dsaddrs)
608608
{
609609
struct nfs4_pnfs_ds *ds;
610610

611611
list_for_each_entry(ds, &nfs4_data_server_cache, ds_node)
612-
if (_same_data_server_addrs_locked(&ds->ds_addrs, dsaddrs))
612+
if (ds->ds_net == net && _same_data_server_addrs_locked(&ds->ds_addrs, dsaddrs))
613613
return ds;
614614
return NULL;
615615
}
@@ -716,7 +716,7 @@ nfs4_pnfs_remotestr(struct list_head *dsaddrs, gfp_t gfp_flags)
716716
* uncached and return cached struct nfs4_pnfs_ds.
717717
*/
718718
struct nfs4_pnfs_ds *
719-
nfs4_pnfs_ds_add(struct list_head *dsaddrs, gfp_t gfp_flags)
719+
nfs4_pnfs_ds_add(const struct net *net, struct list_head *dsaddrs, gfp_t gfp_flags)
720720
{
721721
struct nfs4_pnfs_ds *tmp_ds, *ds = NULL;
722722
char *remotestr;
@@ -734,13 +734,14 @@ nfs4_pnfs_ds_add(struct list_head *dsaddrs, gfp_t gfp_flags)
734734
remotestr = nfs4_pnfs_remotestr(dsaddrs, gfp_flags);
735735

736736
spin_lock(&nfs4_ds_cache_lock);
737-
tmp_ds = _data_server_lookup_locked(dsaddrs);
737+
tmp_ds = _data_server_lookup_locked(net, dsaddrs);
738738
if (tmp_ds == NULL) {
739739
INIT_LIST_HEAD(&ds->ds_addrs);
740740
list_splice_init(dsaddrs, &ds->ds_addrs);
741741
ds->ds_remotestr = remotestr;
742742
refcount_set(&ds->ds_count, 1);
743743
INIT_LIST_HEAD(&ds->ds_node);
744+
ds->ds_net = net;
744745
ds->ds_clp = NULL;
745746
list_add(&ds->ds_node, &nfs4_data_server_cache);
746747
dprintk("%s add new data server %s\n", __func__,

0 commit comments

Comments
 (0)