Skip to content

Commit 42cc139

Browse files
daimngochucklever
authored andcommitted
NFSD: convert callback RPC program to per-net namespace
The callback channel's rpc_program, rpc_version, rpc_stat, and per-procedure counts are declared as file-scope statics in nfs4callback.c, shared across all network namespaces. Forechannel RPC statistics are already maintained per-netns (via nfsd_svcstats in struct nfsd_net); the backchannel has no such separation. When backchannel statistics are eventually surfaced to userspace, the global counters would expose cross-namespace data. Allocate per-netns copies of these structures through a new opaque struct nfsd_net_cb, managed by nfsd_net_cb_init() and nfsd_net_cb_shutdown(). The struct definition is private to nfs4callback.c; struct nfsd_net holds only a pointer. Signed-off-by: Dai Ngo <dai.ngo@oracle.com> Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
1 parent 39bd1bf commit 42cc139

4 files changed

Lines changed: 95 additions & 35 deletions

File tree

fs/nfsd/netns.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#define SESSION_HASH_SIZE 512
2626

2727
struct cld_net;
28+
struct nfsd_net_cb;
2829
struct nfsd4_client_tracking_ops;
2930

3031
enum {
@@ -228,6 +229,8 @@ struct nfsd_net {
228229
struct list_head local_clients;
229230
#endif
230231
siphash_key_t *fh_key;
232+
233+
struct nfsd_net_cb *nfsd_cb;
231234
};
232235

233236
/* Simple check to find out if a given net was properly initialized */

fs/nfsd/nfs4callback.c

Lines changed: 78 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,39 +1032,14 @@ static const struct rpc_procinfo nfs4_cb_procedures[] = {
10321032
PROC(CB_GETATTR, COMPOUND, cb_getattr, cb_getattr),
10331033
};
10341034

1035-
static unsigned int nfs4_cb_counts[ARRAY_SIZE(nfs4_cb_procedures)];
1036-
static const struct rpc_version nfs_cb_version4 = {
1037-
/*
1038-
* Note on the callback rpc program version number: despite language in rfc
1039-
* 5661 section 18.36.3 requiring servers to use 4 in this field, the
1040-
* official xdr descriptions for both 4.0 and 4.1 specify version 1, and
1041-
* in practice that appears to be what implementations use. The section
1042-
* 18.36.3 language is expected to be fixed in an erratum.
1043-
*/
1044-
.number = 1,
1045-
.nrprocs = ARRAY_SIZE(nfs4_cb_procedures),
1046-
.procs = nfs4_cb_procedures,
1047-
.counts = nfs4_cb_counts,
1048-
};
1049-
1050-
static const struct rpc_version *nfs_cb_version[2] = {
1051-
[1] = &nfs_cb_version4,
1052-
};
1053-
1054-
static const struct rpc_program cb_program;
1055-
1056-
static struct rpc_stat cb_stats = {
1057-
.program = &cb_program
1058-
};
1059-
1060-
#define NFS4_CALLBACK 0x40000000
1061-
static const struct rpc_program cb_program = {
1062-
.name = "nfs4_cb",
1063-
.number = NFS4_CALLBACK,
1064-
.nrvers = ARRAY_SIZE(nfs_cb_version),
1065-
.version = nfs_cb_version,
1066-
.stats = &cb_stats,
1067-
.pipe_dir_name = "nfsd4_cb",
1035+
#define NFS4_CB_PROGRAM 0x40000000
1036+
#define NFS4_CB_VERSION 1
1037+
1038+
struct nfsd_net_cb {
1039+
struct rpc_version version4;
1040+
const struct rpc_version *versions[NFS4_CB_VERSION + 1];
1041+
struct rpc_program program;
1042+
struct rpc_stat stat;
10681043
};
10691044

10701045
static int max_cb_time(struct net *net)
@@ -1140,6 +1115,7 @@ static const struct cred *get_backchannel_cred(struct nfs4_client *clp, struct r
11401115

11411116
static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses)
11421117
{
1118+
struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
11431119
int maxtime = max_cb_time(clp->net);
11441120
struct rpc_timeout timeparms = {
11451121
.to_initval = maxtime,
@@ -1152,14 +1128,14 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c
11521128
.addrsize = conn->cb_addrlen,
11531129
.saddress = (struct sockaddr *) &conn->cb_saddr,
11541130
.timeout = &timeparms,
1155-
.program = &cb_program,
1156-
.version = 1,
1131+
.version = NFS4_CB_VERSION,
11571132
.flags = (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET),
11581133
.cred = current_cred(),
11591134
};
11601135
struct rpc_clnt *client;
11611136
const struct cred *cred;
11621137

1138+
args.program = &nn->nfsd_cb->program;
11631139
if (clp->cl_minorversion == 0) {
11641140
if (!clp->cl_cred.cr_principal &&
11651141
(clp->cl_cred.cr_flavor >= RPC_AUTH_GSS_KRB5)) {
@@ -1786,3 +1762,70 @@ bool nfsd4_run_cb(struct nfsd4_callback *cb)
17861762
nfsd41_cb_inflight_end(clp);
17871763
return queued;
17881764
}
1765+
1766+
/**
1767+
* nfsd_net_cb_shutdown - release per-netns callback RPC program resources
1768+
* @nn: NFS server network namespace
1769+
*
1770+
* Frees resources allocated by nfsd_net_cb_init().
1771+
*/
1772+
void nfsd_net_cb_shutdown(struct nfsd_net *nn)
1773+
{
1774+
struct nfsd_net_cb *cb = nn->nfsd_cb;
1775+
1776+
if (cb) {
1777+
kfree(cb->version4.counts);
1778+
kfree(cb);
1779+
nn->nfsd_cb = NULL;
1780+
}
1781+
}
1782+
1783+
/**
1784+
* nfsd_net_cb_init - initialize per-netns callback RPC program
1785+
* @nn: NFS server network namespace
1786+
*
1787+
* Sets up the callback RPC program, version table, procedure
1788+
* counts, and statistics structure for @nn. Caller must release
1789+
* these resources using nfsd_net_cb_shutdown().
1790+
*
1791+
* Return: 0 on success, or -ENOMEM if allocation fails.
1792+
*/
1793+
int nfsd_net_cb_init(struct nfsd_net *nn)
1794+
{
1795+
struct nfsd_net_cb *cb;
1796+
1797+
cb = kzalloc(sizeof(*cb), GFP_KERNEL);
1798+
if (!cb)
1799+
return -ENOMEM;
1800+
1801+
cb->version4.counts = kzalloc_objs(unsigned int,
1802+
ARRAY_SIZE(nfs4_cb_procedures), GFP_KERNEL);
1803+
if (!cb->version4.counts) {
1804+
kfree(cb);
1805+
return -ENOMEM;
1806+
}
1807+
/*
1808+
* Note on the callback rpc program version number: despite language
1809+
* in rfc 5661 section 18.36.3 requiring servers to use 4 in this
1810+
* field, the official xdr descriptions for both 4.0 and 4.1 specify
1811+
* version 1, and in practice that appears to be what implementations
1812+
* use. The section 18.36.3 language is expected to be fixed in an
1813+
* erratum.
1814+
*/
1815+
cb->version4.number = NFS4_CB_VERSION;
1816+
cb->version4.nrprocs = ARRAY_SIZE(nfs4_cb_procedures);
1817+
cb->version4.procs = nfs4_cb_procedures;
1818+
cb->versions[NFS4_CB_VERSION] = &cb->version4;
1819+
1820+
cb->program.name = "nfs4_cb";
1821+
cb->program.number = NFS4_CB_PROGRAM;
1822+
cb->program.nrvers = ARRAY_SIZE(cb->versions);
1823+
cb->program.version = &cb->versions[0];
1824+
cb->program.pipe_dir_name = "nfsd4_cb";
1825+
cb->program.stats = &cb->stat;
1826+
cb->stat.program = &cb->program;
1827+
1828+
nn->nfsd_cb = cb;
1829+
1830+
return 0;
1831+
}

fs/nfsd/nfsctl.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2203,6 +2203,9 @@ static __net_init int nfsd_net_init(struct net *net)
22032203
int retval;
22042204
int i;
22052205

2206+
retval = nfsd_net_cb_init(nn);
2207+
if (retval)
2208+
return retval;
22062209
retval = nfsd_export_init(net);
22072210
if (retval)
22082211
goto out_export_error;
@@ -2243,6 +2246,7 @@ static __net_init int nfsd_net_init(struct net *net)
22432246
out_idmap_error:
22442247
nfsd_export_shutdown(net);
22452248
out_export_error:
2249+
nfsd_net_cb_shutdown(nn);
22462250
return retval;
22472251
}
22482252

@@ -2273,6 +2277,7 @@ static __net_exit void nfsd_net_exit(struct net *net)
22732277
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
22742278

22752279
kfree_sensitive(nn->fh_key);
2280+
nfsd_net_cb_shutdown(nn);
22762281
nfsd_proc_stat_shutdown(net);
22772282
percpu_counter_destroy_many(nn->counter, NFSD_STATS_COUNTERS_NUM);
22782283
nfsd_idmap_shutdown(net);

fs/nfsd/state.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -862,13 +862,22 @@ struct nfsd_file *find_any_file(struct nfs4_file *f);
862862
#ifdef CONFIG_NFSD_V4
863863
void nfsd4_revoke_states(struct nfsd_net *nn, struct super_block *sb);
864864
void nfsd4_cancel_copy_by_sb(struct net *net, struct super_block *sb);
865+
int nfsd_net_cb_init(struct nfsd_net *nn);
866+
void nfsd_net_cb_shutdown(struct nfsd_net *nn);
865867
#else
866868
static inline void nfsd4_revoke_states(struct nfsd_net *nn, struct super_block *sb)
867869
{
868870
}
869871
static inline void nfsd4_cancel_copy_by_sb(struct net *net, struct super_block *sb)
870872
{
871873
}
874+
static inline int nfsd_net_cb_init(struct nfsd_net *nn)
875+
{
876+
return 0;
877+
}
878+
static inline void nfsd_net_cb_shutdown(struct nfsd_net *nn)
879+
{
880+
}
872881
#endif
873882

874883
/* grace period management */

0 commit comments

Comments
 (0)