Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Dai Ngo and committed by
Chuck Lever
42cc1399 39bd1bfe

+94 -34
+3
fs/nfsd/netns.h
··· 25 25 #define SESSION_HASH_SIZE 512 26 26 27 27 struct cld_net; 28 + struct nfsd_net_cb; 28 29 struct nfsd4_client_tracking_ops; 29 30 30 31 enum { ··· 229 228 struct list_head local_clients; 230 229 #endif 231 230 siphash_key_t *fh_key; 231 + 232 + struct nfsd_net_cb *nfsd_cb; 232 233 }; 233 234 234 235 /* Simple check to find out if a given net was properly initialized */
+77 -34
fs/nfsd/nfs4callback.c
··· 1032 1032 PROC(CB_GETATTR, COMPOUND, cb_getattr, cb_getattr), 1033 1033 }; 1034 1034 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 - }; 1035 + #define NFS4_CB_PROGRAM 0x40000000 1036 + #define NFS4_CB_VERSION 1 1049 1037 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", 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; 1068 1043 }; 1069 1044 1070 1045 static int max_cb_time(struct net *net) ··· 1115 1140 1116 1141 static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses) 1117 1142 { 1143 + struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 1118 1144 int maxtime = max_cb_time(clp->net); 1119 1145 struct rpc_timeout timeparms = { 1120 1146 .to_initval = maxtime, ··· 1128 1152 .addrsize = conn->cb_addrlen, 1129 1153 .saddress = (struct sockaddr *) &conn->cb_saddr, 1130 1154 .timeout = &timeparms, 1131 - .program = &cb_program, 1132 - .version = 1, 1155 + .version = NFS4_CB_VERSION, 1133 1156 .flags = (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET), 1134 1157 .cred = current_cred(), 1135 1158 }; 1136 1159 struct rpc_clnt *client; 1137 1160 const struct cred *cred; 1138 1161 1162 + args.program = &nn->nfsd_cb->program; 1139 1163 if (clp->cl_minorversion == 0) { 1140 1164 if (!clp->cl_cred.cr_principal && 1141 1165 (clp->cl_cred.cr_flavor >= RPC_AUTH_GSS_KRB5)) { ··· 1761 1785 if (!queued) 1762 1786 nfsd41_cb_inflight_end(clp); 1763 1787 return queued; 1788 + } 1789 + 1790 + /** 1791 + * nfsd_net_cb_shutdown - release per-netns callback RPC program resources 1792 + * @nn: NFS server network namespace 1793 + * 1794 + * Frees resources allocated by nfsd_net_cb_init(). 1795 + */ 1796 + void nfsd_net_cb_shutdown(struct nfsd_net *nn) 1797 + { 1798 + struct nfsd_net_cb *cb = nn->nfsd_cb; 1799 + 1800 + if (cb) { 1801 + kfree(cb->version4.counts); 1802 + kfree(cb); 1803 + nn->nfsd_cb = NULL; 1804 + } 1805 + } 1806 + 1807 + /** 1808 + * nfsd_net_cb_init - initialize per-netns callback RPC program 1809 + * @nn: NFS server network namespace 1810 + * 1811 + * Sets up the callback RPC program, version table, procedure 1812 + * counts, and statistics structure for @nn. Caller must release 1813 + * these resources using nfsd_net_cb_shutdown(). 1814 + * 1815 + * Return: 0 on success, or -ENOMEM if allocation fails. 1816 + */ 1817 + int nfsd_net_cb_init(struct nfsd_net *nn) 1818 + { 1819 + struct nfsd_net_cb *cb; 1820 + 1821 + cb = kzalloc(sizeof(*cb), GFP_KERNEL); 1822 + if (!cb) 1823 + return -ENOMEM; 1824 + 1825 + cb->version4.counts = kzalloc_objs(unsigned int, 1826 + ARRAY_SIZE(nfs4_cb_procedures), GFP_KERNEL); 1827 + if (!cb->version4.counts) { 1828 + kfree(cb); 1829 + return -ENOMEM; 1830 + } 1831 + /* 1832 + * Note on the callback rpc program version number: despite language 1833 + * in rfc 5661 section 18.36.3 requiring servers to use 4 in this 1834 + * field, the official xdr descriptions for both 4.0 and 4.1 specify 1835 + * version 1, and in practice that appears to be what implementations 1836 + * use. The section 18.36.3 language is expected to be fixed in an 1837 + * erratum. 1838 + */ 1839 + cb->version4.number = NFS4_CB_VERSION; 1840 + cb->version4.nrprocs = ARRAY_SIZE(nfs4_cb_procedures); 1841 + cb->version4.procs = nfs4_cb_procedures; 1842 + cb->versions[NFS4_CB_VERSION] = &cb->version4; 1843 + 1844 + cb->program.name = "nfs4_cb"; 1845 + cb->program.number = NFS4_CB_PROGRAM; 1846 + cb->program.nrvers = ARRAY_SIZE(cb->versions); 1847 + cb->program.version = &cb->versions[0]; 1848 + cb->program.pipe_dir_name = "nfsd4_cb"; 1849 + cb->program.stats = &cb->stat; 1850 + cb->stat.program = &cb->program; 1851 + 1852 + nn->nfsd_cb = cb; 1853 + 1854 + return 0; 1764 1855 }
+5
fs/nfsd/nfsctl.c
··· 2203 2203 int retval; 2204 2204 int i; 2205 2205 2206 + retval = nfsd_net_cb_init(nn); 2207 + if (retval) 2208 + return retval; 2206 2209 retval = nfsd_export_init(net); 2207 2210 if (retval) 2208 2211 goto out_export_error; ··· 2246 2243 out_idmap_error: 2247 2244 nfsd_export_shutdown(net); 2248 2245 out_export_error: 2246 + nfsd_net_cb_shutdown(nn); 2249 2247 return retval; 2250 2248 } 2251 2249 ··· 2277 2273 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 2278 2274 2279 2275 kfree_sensitive(nn->fh_key); 2276 + nfsd_net_cb_shutdown(nn); 2280 2277 nfsd_proc_stat_shutdown(net); 2281 2278 percpu_counter_destroy_many(nn->counter, NFSD_STATS_COUNTERS_NUM); 2282 2279 nfsd_idmap_shutdown(net);
+9
fs/nfsd/state.h
··· 862 862 #ifdef CONFIG_NFSD_V4 863 863 void nfsd4_revoke_states(struct nfsd_net *nn, struct super_block *sb); 864 864 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); 865 867 #else 866 868 static inline void nfsd4_revoke_states(struct nfsd_net *nn, struct super_block *sb) 867 869 { 868 870 } 869 871 static inline void nfsd4_cancel_copy_by_sb(struct net *net, struct super_block *sb) 872 + { 873 + } 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) 870 879 { 871 880 } 872 881 #endif