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.

Merge tag 'nfsd-6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux

Pull nfsd updates from Chuck Lever:
"This is a light release containing optimizations, code clean-ups, and
minor bug fixes.

This development cycle focused on work outside of upstream kernel
development:

- Continuing to build upstream CI for NFSD based on kdevops

- Continuing to focus on the quality of NFSD in LTS kernels

- Participation in IETF nfsv4 WG discussions about NFSv4 ACLs,
directory delegation, and NFSv4.2 COPY offload

Notable features for v6.11 that do not come through the NFSD tree
include NFS server-side support for the new pNFS NVMe layout type
[RFC9561]. Functional testing for pNFS block layouts like this one has
been introduced to our kdevops CI harness. Work on improving the
resolution of file attribute time stamps in local filesystems is also
ongoing tree-wide.

As always I am grateful to NFSD contributors, reviewers, testers, and
bug reporters who participated during this cycle"

* tag 'nfsd-6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux:
nfsd: nfsd_file_lease_notifier_call gets a file_lease as an argument
gss_krb5: Fix the error handling path for crypto_sync_skcipher_setkey
MAINTAINERS: Add a bugzilla link for NFSD
nfsd: new netlink ops to get/set server pool_mode
sunrpc: refactor pool_mode setting code
nfsd: allow passing in array of thread counts via netlink
nfsd: make nfsd_svc take an array of thread counts
sunrpc: fix up the special handling of sv_nrpools == 1
SUNRPC: Add a trace point in svc_xprt_deferred_close
NFSD: Support write delegations in LAYOUTGET
lockd: Use *-y instead of *-objs in Makefile
NFSD: Fix nfsdcld warning
svcrdma: Handle ADDR_CHANGE CM event properly
svcrdma: Refactor the creation of listener CMA ID
NFSD: remove unused structs 'nfsd3_voidargs'
NFSD: harden svcxdr_dupstr() and svcxdr_tmpalloc() against integer overflows

+337 -127
+27
Documentation/netlink/specs/nfsd.yaml
··· 115 115 type: nest 116 116 nested-attributes: sock 117 117 multi-attr: true 118 + - 119 + name: pool-mode 120 + attributes: 121 + - 122 + name: mode 123 + type: string 124 + - 125 + name: npools 126 + type: u32 118 127 119 128 operations: 120 129 list: ··· 204 195 reply: 205 196 attributes: 206 197 - addr 198 + - 199 + name: pool-mode-set 200 + doc: set the current server pool-mode 201 + attribute-set: pool-mode 202 + flags: [ admin-perm ] 203 + do: 204 + request: 205 + attributes: 206 + - mode 207 + - 208 + name: pool-mode-get 209 + doc: get info about server pool-mode 210 + attribute-set: pool-mode 211 + do: 212 + reply: 213 + attributes: 214 + - mode 215 + - npools
+1 -1
MAINTAINERS
··· 12065 12065 R: Tom Talpey <tom@talpey.com> 12066 12066 L: linux-nfs@vger.kernel.org 12067 12067 S: Supported 12068 - W: http://nfs.sourceforge.net/ 12068 + B: https://bugzilla.kernel.org 12069 12069 T: git git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux.git 12070 12070 F: Documentation/filesystems/nfs/ 12071 12071 F: fs/lockd/
+4 -5
fs/lockd/Makefile
··· 7 7 8 8 obj-$(CONFIG_LOCKD) += lockd.o 9 9 10 - lockd-objs-y += clntlock.o clntproc.o clntxdr.o host.o svc.o svclock.o \ 11 - svcshare.o svcproc.o svcsubs.o mon.o trace.o xdr.o 12 - lockd-objs-$(CONFIG_LOCKD_V4) += clnt4xdr.o xdr4.o svc4proc.o 13 - lockd-objs-$(CONFIG_PROC_FS) += procfs.o 14 - lockd-objs := $(lockd-objs-y) 10 + lockd-y := clntlock.o clntproc.o clntxdr.o host.o svc.o svclock.o \ 11 + svcshare.o svcproc.o svcsubs.o mon.o trace.o xdr.o 12 + lockd-$(CONFIG_LOCKD_V4) += clnt4xdr.o xdr4.o svc4proc.o 13 + lockd-$(CONFIG_PROC_FS) += procfs.o
+1 -1
fs/nfsd/Kconfig
··· 162 162 config NFSD_LEGACY_CLIENT_TRACKING 163 163 bool "Support legacy NFSv4 client tracking methods (DEPRECATED)" 164 164 depends on NFSD_V4 165 - default n 165 + default y 166 166 help 167 167 The NFSv4 server needs to store a small amount of information on 168 168 stable storage in order to handle state recovery after reboot. Most
+1 -1
fs/nfsd/filecache.c
··· 664 664 nfsd_file_lease_notifier_call(struct notifier_block *nb, unsigned long arg, 665 665 void *data) 666 666 { 667 - struct file_lock *fl = data; 667 + struct file_lease *fl = data; 668 668 669 669 /* Only close files for F_SETLEASE leases */ 670 670 if (fl->c.flc_flags & FL_LEASE)
+17
fs/nfsd/netlink.c
··· 40 40 [NFSD_A_SERVER_SOCK_ADDR] = NLA_POLICY_NESTED(nfsd_sock_nl_policy), 41 41 }; 42 42 43 + /* NFSD_CMD_POOL_MODE_SET - do */ 44 + static const struct nla_policy nfsd_pool_mode_set_nl_policy[NFSD_A_POOL_MODE_MODE + 1] = { 45 + [NFSD_A_POOL_MODE_MODE] = { .type = NLA_NUL_STRING, }, 46 + }; 47 + 43 48 /* Ops table for nfsd */ 44 49 static const struct genl_split_ops nfsd_nl_ops[] = { 45 50 { ··· 86 81 { 87 82 .cmd = NFSD_CMD_LISTENER_GET, 88 83 .doit = nfsd_nl_listener_get_doit, 84 + .flags = GENL_CMD_CAP_DO, 85 + }, 86 + { 87 + .cmd = NFSD_CMD_POOL_MODE_SET, 88 + .doit = nfsd_nl_pool_mode_set_doit, 89 + .policy = nfsd_pool_mode_set_nl_policy, 90 + .maxattr = NFSD_A_POOL_MODE_MODE, 91 + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, 92 + }, 93 + { 94 + .cmd = NFSD_CMD_POOL_MODE_GET, 95 + .doit = nfsd_nl_pool_mode_get_doit, 89 96 .flags = GENL_CMD_CAP_DO, 90 97 }, 91 98 };
+2
fs/nfsd/netlink.h
··· 23 23 int nfsd_nl_version_get_doit(struct sk_buff *skb, struct genl_info *info); 24 24 int nfsd_nl_listener_set_doit(struct sk_buff *skb, struct genl_info *info); 25 25 int nfsd_nl_listener_get_doit(struct sk_buff *skb, struct genl_info *info); 26 + int nfsd_nl_pool_mode_set_doit(struct sk_buff *skb, struct genl_info *info); 27 + int nfsd_nl_pool_mode_get_doit(struct sk_buff *skb, struct genl_info *info); 26 28 27 29 extern struct genl_family nfsd_nl_family; 28 30
-2
fs/nfsd/nfs2acl.c
··· 308 308 fh_put(&resp->fh); 309 309 } 310 310 311 - struct nfsd3_voidargs { int dummy; }; 312 - 313 311 #define ST 1 /* status*/ 314 312 #define AT 21 /* attributes */ 315 313 #define pAT (1+AT) /* post attributes - conditional */
-2
fs/nfsd/nfs3acl.c
··· 221 221 posix_acl_release(resp->acl_default); 222 222 } 223 223 224 - struct nfsd3_voidargs { int dummy; }; 225 - 226 224 #define ST 1 /* status*/ 227 225 #define AT 21 /* attributes */ 228 226 #define pAT (1+AT) /* post attributes - conditional */
+3 -2
fs/nfsd/nfs4proc.c
··· 2269 2269 const struct nfsd4_layout_ops *ops; 2270 2270 struct nfs4_layout_stateid *ls; 2271 2271 __be32 nfserr; 2272 - int accmode = NFSD_MAY_READ_IF_EXEC; 2272 + int accmode = NFSD_MAY_READ_IF_EXEC | NFSD_MAY_OWNER_OVERRIDE; 2273 2273 2274 2274 switch (lgp->lg_seg.iomode) { 2275 2275 case IOMODE_READ: ··· 2359 2359 struct nfs4_layout_stateid *ls; 2360 2360 __be32 nfserr; 2361 2361 2362 - nfserr = fh_verify(rqstp, current_fh, 0, NFSD_MAY_WRITE); 2362 + nfserr = fh_verify(rqstp, current_fh, 0, 2363 + NFSD_MAY_WRITE | NFSD_MAY_OWNER_OVERRIDE); 2363 2364 if (nfserr) 2364 2365 goto out; 2365 2366
+2 -2
fs/nfsd/nfs4recover.c
··· 2086 2086 status = nn->client_tracking_ops->init(net); 2087 2087 out: 2088 2088 if (status) { 2089 - printk(KERN_WARNING "NFSD: Unable to initialize client " 2090 - "recovery tracking! (%d)\n", status); 2089 + pr_warn("NFSD: Unable to initialize client recovery tracking! (%d)\n", status); 2090 + pr_warn("NFSD: Is nfsdcld running? If not, enable CONFIG_NFSD_LEGACY_CLIENT_TRACKING.\n"); 2091 2091 nn->client_tracking_ops = NULL; 2092 2092 } 2093 2093 return status;
+6 -6
fs/nfsd/nfs4xdr.c
··· 118 118 * operation described in @argp finishes. 119 119 */ 120 120 static void * 121 - svcxdr_tmpalloc(struct nfsd4_compoundargs *argp, u32 len) 121 + svcxdr_tmpalloc(struct nfsd4_compoundargs *argp, size_t len) 122 122 { 123 123 struct svcxdr_tmpbuf *tb; 124 124 125 - tb = kmalloc(sizeof(*tb) + len, GFP_KERNEL); 125 + tb = kmalloc(struct_size(tb, buf, len), GFP_KERNEL); 126 126 if (!tb) 127 127 return NULL; 128 128 tb->next = argp->to_free; ··· 138 138 * buffer might end on a page boundary. 139 139 */ 140 140 static char * 141 - svcxdr_dupstr(struct nfsd4_compoundargs *argp, void *buf, u32 len) 141 + svcxdr_dupstr(struct nfsd4_compoundargs *argp, void *buf, size_t len) 142 142 { 143 - char *p = svcxdr_tmpalloc(argp, len + 1); 143 + char *p = svcxdr_tmpalloc(argp, size_add(len, 1)); 144 144 145 145 if (!p) 146 146 return NULL; ··· 150 150 } 151 151 152 152 static void * 153 - svcxdr_savemem(struct nfsd4_compoundargs *argp, __be32 *p, u32 len) 153 + svcxdr_savemem(struct nfsd4_compoundargs *argp, __be32 *p, size_t len) 154 154 { 155 155 __be32 *tmp; 156 156 ··· 2146 2146 */ 2147 2147 static __be32 2148 2148 nfsd4_vbuf_from_vector(struct nfsd4_compoundargs *argp, struct xdr_buf *xdr, 2149 - char **bufp, u32 buflen) 2149 + char **bufp, size_t buflen) 2150 2150 { 2151 2151 struct page **pages = xdr->pages; 2152 2152 struct kvec *head = xdr->head;
+86 -13
fs/nfsd/nfsctl.c
··· 406 406 return -EINVAL; 407 407 trace_nfsd_ctl_threads(net, newthreads); 408 408 mutex_lock(&nfsd_mutex); 409 - rv = nfsd_svc(newthreads, net, file->f_cred, NULL); 409 + rv = nfsd_svc(1, &newthreads, net, file->f_cred, NULL); 410 410 mutex_unlock(&nfsd_mutex); 411 411 if (rv < 0) 412 412 return rv; ··· 481 481 goto out_free; 482 482 trace_nfsd_ctl_pool_threads(net, i, nthreads[i]); 483 483 } 484 + 485 + /* 486 + * There must always be a thread in pool 0; the admin 487 + * can't shut down NFS completely using pool_threads. 488 + */ 489 + if (nthreads[0] == 0) 490 + nthreads[0] = 1; 491 + 484 492 rv = nfsd_set_nrthreads(i, nthreads, net); 485 493 if (rv) 486 494 goto out_free; ··· 1645 1637 */ 1646 1638 int nfsd_nl_threads_set_doit(struct sk_buff *skb, struct genl_info *info) 1647 1639 { 1648 - int nthreads = 0, count = 0, nrpools, ret = -EOPNOTSUPP, rem; 1640 + int *nthreads, count = 0, nrpools, i, ret = -EOPNOTSUPP, rem; 1649 1641 struct net *net = genl_info_net(info); 1650 1642 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1651 1643 const struct nlattr *attr; ··· 1662 1654 1663 1655 mutex_lock(&nfsd_mutex); 1664 1656 1665 - nrpools = nfsd_nrpools(net); 1666 - if (nrpools && count > nrpools) 1667 - count = nrpools; 1668 - 1669 - /* XXX: make this handle non-global pool-modes */ 1670 - if (count > 1) 1657 + nrpools = max(count, nfsd_nrpools(net)); 1658 + nthreads = kcalloc(nrpools, sizeof(int), GFP_KERNEL); 1659 + if (!nthreads) { 1660 + ret = -ENOMEM; 1671 1661 goto out_unlock; 1662 + } 1672 1663 1673 - nthreads = nla_get_u32(info->attrs[NFSD_A_SERVER_THREADS]); 1664 + i = 0; 1665 + nlmsg_for_each_attr(attr, info->nlhdr, GENL_HDRLEN, rem) { 1666 + if (nla_type(attr) == NFSD_A_SERVER_THREADS) { 1667 + nthreads[i++] = nla_get_u32(attr); 1668 + if (i >= nrpools) 1669 + break; 1670 + } 1671 + } 1672 + 1674 1673 if (info->attrs[NFSD_A_SERVER_GRACETIME] || 1675 1674 info->attrs[NFSD_A_SERVER_LEASETIME] || 1676 1675 info->attrs[NFSD_A_SERVER_SCOPE]) { ··· 1711 1696 scope = nla_data(attr); 1712 1697 } 1713 1698 1714 - ret = nfsd_svc(nthreads, net, get_current_cred(), scope); 1715 - 1699 + ret = nfsd_svc(nrpools, nthreads, net, get_current_cred(), scope); 1700 + if (ret > 0) 1701 + ret = 0; 1716 1702 out_unlock: 1717 1703 mutex_unlock(&nfsd_mutex); 1718 - 1719 - return ret == nthreads ? 0 : ret; 1704 + kfree(nthreads); 1705 + return ret; 1720 1706 } 1721 1707 1722 1708 /** ··· 2153 2137 err_free_msg: 2154 2138 nlmsg_free(skb); 2155 2139 2140 + return err; 2141 + } 2142 + 2143 + /** 2144 + * nfsd_nl_pool_mode_set_doit - set the number of running threads 2145 + * @skb: reply buffer 2146 + * @info: netlink metadata and command arguments 2147 + * 2148 + * Return 0 on success or a negative errno. 2149 + */ 2150 + int nfsd_nl_pool_mode_set_doit(struct sk_buff *skb, struct genl_info *info) 2151 + { 2152 + const struct nlattr *attr; 2153 + 2154 + if (GENL_REQ_ATTR_CHECK(info, NFSD_A_POOL_MODE_MODE)) 2155 + return -EINVAL; 2156 + 2157 + attr = info->attrs[NFSD_A_POOL_MODE_MODE]; 2158 + return sunrpc_set_pool_mode(nla_data(attr)); 2159 + } 2160 + 2161 + /** 2162 + * nfsd_nl_pool_mode_get_doit - get info about pool_mode 2163 + * @skb: reply buffer 2164 + * @info: netlink metadata and command arguments 2165 + * 2166 + * Return 0 on success or a negative errno. 2167 + */ 2168 + int nfsd_nl_pool_mode_get_doit(struct sk_buff *skb, struct genl_info *info) 2169 + { 2170 + struct net *net = genl_info_net(info); 2171 + char buf[16]; 2172 + void *hdr; 2173 + int err; 2174 + 2175 + if (sunrpc_get_pool_mode(buf, ARRAY_SIZE(buf)) >= ARRAY_SIZE(buf)) 2176 + return -ERANGE; 2177 + 2178 + skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); 2179 + if (!skb) 2180 + return -ENOMEM; 2181 + 2182 + err = -EMSGSIZE; 2183 + hdr = genlmsg_iput(skb, info); 2184 + if (!hdr) 2185 + goto err_free_msg; 2186 + 2187 + err = nla_put_string(skb, NFSD_A_POOL_MODE_MODE, buf) | 2188 + nla_put_u32(skb, NFSD_A_POOL_MODE_NPOOLS, nfsd_nrpools(net)); 2189 + if (err) 2190 + goto err_free_msg; 2191 + 2192 + genlmsg_end(skb, hdr); 2193 + return genlmsg_reply(skb, info); 2194 + 2195 + err_free_msg: 2196 + nlmsg_free(skb); 2156 2197 return err; 2157 2198 } 2158 2199
+2 -1
fs/nfsd/nfsd.h
··· 103 103 /* 104 104 * Function prototypes. 105 105 */ 106 - int nfsd_svc(int nrservs, struct net *net, const struct cred *cred, const char *scope); 106 + int nfsd_svc(int n, int *nservers, struct net *net, 107 + const struct cred *cred, const char *scope); 107 108 int nfsd_dispatch(struct svc_rqst *rqstp); 108 109 109 110 int nfsd_nrthreads(struct net *);
+44 -22
fs/nfsd/nfssvc.c
··· 709 709 return 0; 710 710 } 711 711 712 + /** 713 + * nfsd_set_nrthreads - set the number of running threads in the net's service 714 + * @n: number of array members in @nthreads 715 + * @nthreads: array of thread counts for each pool 716 + * @net: network namespace to operate within 717 + * 718 + * This function alters the number of running threads for the given network 719 + * namespace in each pool. If passed an array longer then the number of pools 720 + * the extra pool settings are ignored. If passed an array shorter than the 721 + * number of pools, the missing values are interpreted as 0's. 722 + * 723 + * Returns 0 on success or a negative errno on error. 724 + */ 712 725 int nfsd_set_nrthreads(int n, int *nthreads, struct net *net) 713 726 { 714 727 int i = 0; ··· 729 716 int err = 0; 730 717 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 731 718 732 - WARN_ON(!mutex_is_locked(&nfsd_mutex)); 719 + lockdep_assert_held(&nfsd_mutex); 733 720 734 721 if (nn->nfsd_serv == NULL || n <= 0) 735 722 return 0; 723 + 724 + /* 725 + * Special case: When n == 1, pass in NULL for the pool, so that the 726 + * change is distributed equally among them. 727 + */ 728 + if (n == 1) 729 + return svc_set_num_threads(nn->nfsd_serv, NULL, nthreads[0]); 736 730 737 731 if (n > nn->nfsd_serv->sv_nrpools) 738 732 n = nn->nfsd_serv->sv_nrpools; ··· 763 743 } 764 744 } 765 745 766 - /* 767 - * There must always be a thread in pool 0; the admin 768 - * can't shut down NFS completely using pool_threads. 769 - */ 770 - if (nthreads[0] == 0) 771 - nthreads[0] = 1; 772 - 773 746 /* apply the new numbers */ 774 747 for (i = 0; i < n; i++) { 775 748 err = svc_set_num_threads(nn->nfsd_serv, 776 749 &nn->nfsd_serv->sv_pools[i], 777 750 nthreads[i]); 778 751 if (err) 779 - break; 752 + goto out; 780 753 } 754 + 755 + /* Anything undefined in array is considered to be 0 */ 756 + for (i = n; i < nn->nfsd_serv->sv_nrpools; ++i) { 757 + err = svc_set_num_threads(nn->nfsd_serv, 758 + &nn->nfsd_serv->sv_pools[i], 759 + 0); 760 + if (err) 761 + goto out; 762 + } 763 + out: 781 764 return err; 782 765 } 783 766 784 - /* 785 - * Adjust the number of threads and return the new number of threads. 786 - * This is also the function that starts the server if necessary, if 787 - * this is the first time nrservs is nonzero. 767 + /** 768 + * nfsd_svc: start up or shut down the nfsd server 769 + * @n: number of array members in @nthreads 770 + * @nthreads: array of thread counts for each pool 771 + * @net: network namespace to operate within 772 + * @cred: credentials to use for xprt creation 773 + * @scope: server scope value (defaults to nodename) 774 + * 775 + * Adjust the number of threads in each pool and return the new 776 + * total number of threads in the service. 788 777 */ 789 778 int 790 - nfsd_svc(int nrservs, struct net *net, const struct cred *cred, const char *scope) 779 + nfsd_svc(int n, int *nthreads, struct net *net, const struct cred *cred, const char *scope) 791 780 { 792 781 int error; 793 782 struct nfsd_net *nn = net_generic(net, nfsd_net_id); ··· 805 776 lockdep_assert_held(&nfsd_mutex); 806 777 807 778 dprintk("nfsd: creating service\n"); 808 - 809 - nrservs = max(nrservs, 0); 810 - nrservs = min(nrservs, NFSD_MAXSERVS); 811 - error = 0; 812 - 813 - if (nrservs == 0 && nn->nfsd_serv == NULL) 814 - goto out; 815 779 816 780 strscpy(nn->nfsd_name, scope ? scope : utsname()->nodename, 817 781 sizeof(nn->nfsd_name)); ··· 817 795 error = nfsd_startup_net(net, cred); 818 796 if (error) 819 797 goto out_put; 820 - error = svc_set_num_threads(serv, NULL, nrservs); 798 + error = nfsd_set_nrthreads(n, nthreads, net); 821 799 if (error) 822 800 goto out_put; 823 801 error = serv->sv_nrthreads;
+3
include/linux/sunrpc/svc.h
··· 85 85 char * sv_name; /* service name */ 86 86 87 87 unsigned int sv_nrpools; /* number of thread pools */ 88 + bool sv_is_pooled; /* is this a pooled service? */ 88 89 struct svc_pool * sv_pools; /* array of thread pools */ 89 90 int (*sv_threadfn)(void *data); 90 91 ··· 399 398 /* 400 399 * Function prototypes. 401 400 */ 401 + int sunrpc_set_pool_mode(const char *val); 402 + int sunrpc_get_pool_mode(char *val, size_t size); 402 403 int svc_rpcb_setup(struct svc_serv *serv, struct net *net); 403 404 void svc_rpcb_cleanup(struct svc_serv *serv, struct net *net); 404 405 int svc_bind(struct svc_serv *serv, struct net *net);
+10
include/uapi/linux/nfsd_netlink.h
··· 71 71 }; 72 72 73 73 enum { 74 + NFSD_A_POOL_MODE_MODE = 1, 75 + NFSD_A_POOL_MODE_NPOOLS, 76 + 77 + __NFSD_A_POOL_MODE_MAX, 78 + NFSD_A_POOL_MODE_MAX = (__NFSD_A_POOL_MODE_MAX - 1) 79 + }; 80 + 81 + enum { 74 82 NFSD_CMD_RPC_STATUS_GET = 1, 75 83 NFSD_CMD_THREADS_SET, 76 84 NFSD_CMD_THREADS_GET, ··· 86 78 NFSD_CMD_VERSION_GET, 87 79 NFSD_CMD_LISTENER_SET, 88 80 NFSD_CMD_LISTENER_GET, 81 + NFSD_CMD_POOL_MODE_SET, 82 + NFSD_CMD_POOL_MODE_GET, 89 83 90 84 __NFSD_CMD_MAX, 91 85 NFSD_CMD_MAX = (__NFSD_CMD_MAX - 1)
+1 -1
net/sunrpc/auth_gss/gss_krb5_keys.c
··· 168 168 goto err_return; 169 169 blocksize = crypto_sync_skcipher_blocksize(cipher); 170 170 if (crypto_sync_skcipher_setkey(cipher, inkey->data, inkey->len)) 171 - goto err_return; 171 + goto err_free_cipher; 172 172 173 173 ret = -ENOMEM; 174 174 inblockdata = kmalloc(blocksize, gfp_mask);
+71 -40
net/sunrpc/svc.c
··· 72 72 static DEFINE_MUTEX(svc_pool_map_mutex);/* protects svc_pool_map.count only */ 73 73 74 74 static int 75 - param_set_pool_mode(const char *val, const struct kernel_param *kp) 75 + __param_set_pool_mode(const char *val, struct svc_pool_map *m) 76 76 { 77 - int *ip = (int *)kp->arg; 78 - struct svc_pool_map *m = &svc_pool_map; 79 - int err; 77 + int err, mode; 80 78 81 79 mutex_lock(&svc_pool_map_mutex); 82 80 83 - err = -EBUSY; 84 - if (m->count) 85 - goto out; 86 - 87 81 err = 0; 88 82 if (!strncmp(val, "auto", 4)) 89 - *ip = SVC_POOL_AUTO; 83 + mode = SVC_POOL_AUTO; 90 84 else if (!strncmp(val, "global", 6)) 91 - *ip = SVC_POOL_GLOBAL; 85 + mode = SVC_POOL_GLOBAL; 92 86 else if (!strncmp(val, "percpu", 6)) 93 - *ip = SVC_POOL_PERCPU; 87 + mode = SVC_POOL_PERCPU; 94 88 else if (!strncmp(val, "pernode", 7)) 95 - *ip = SVC_POOL_PERNODE; 89 + mode = SVC_POOL_PERNODE; 96 90 else 97 91 err = -EINVAL; 98 92 93 + if (err) 94 + goto out; 95 + 96 + if (m->count == 0) 97 + m->mode = mode; 98 + else if (mode != m->mode) 99 + err = -EBUSY; 99 100 out: 100 101 mutex_unlock(&svc_pool_map_mutex); 101 102 return err; 102 103 } 103 104 104 105 static int 105 - param_get_pool_mode(char *buf, const struct kernel_param *kp) 106 + param_set_pool_mode(const char *val, const struct kernel_param *kp) 106 107 { 107 - int *ip = (int *)kp->arg; 108 + struct svc_pool_map *m = kp->arg; 108 109 109 - switch (*ip) 110 + return __param_set_pool_mode(val, m); 111 + } 112 + 113 + int sunrpc_set_pool_mode(const char *val) 114 + { 115 + return __param_set_pool_mode(val, &svc_pool_map); 116 + } 117 + EXPORT_SYMBOL(sunrpc_set_pool_mode); 118 + 119 + /** 120 + * sunrpc_get_pool_mode - get the current pool_mode for the host 121 + * @buf: where to write the current pool_mode 122 + * @size: size of @buf 123 + * 124 + * Grab the current pool_mode from the svc_pool_map and write 125 + * the resulting string to @buf. Returns the number of characters 126 + * written to @buf (a'la snprintf()). 127 + */ 128 + int 129 + sunrpc_get_pool_mode(char *buf, size_t size) 130 + { 131 + struct svc_pool_map *m = &svc_pool_map; 132 + 133 + switch (m->mode) 110 134 { 111 135 case SVC_POOL_AUTO: 112 - return sysfs_emit(buf, "auto\n"); 136 + return snprintf(buf, size, "auto"); 113 137 case SVC_POOL_GLOBAL: 114 - return sysfs_emit(buf, "global\n"); 138 + return snprintf(buf, size, "global"); 115 139 case SVC_POOL_PERCPU: 116 - return sysfs_emit(buf, "percpu\n"); 140 + return snprintf(buf, size, "percpu"); 117 141 case SVC_POOL_PERNODE: 118 - return sysfs_emit(buf, "pernode\n"); 142 + return snprintf(buf, size, "pernode"); 119 143 default: 120 - return sysfs_emit(buf, "%d\n", *ip); 144 + return snprintf(buf, size, "%d", m->mode); 121 145 } 146 + } 147 + EXPORT_SYMBOL(sunrpc_get_pool_mode); 148 + 149 + static int 150 + param_get_pool_mode(char *buf, const struct kernel_param *kp) 151 + { 152 + char str[16]; 153 + int len; 154 + 155 + len = sunrpc_get_pool_mode(str, ARRAY_SIZE(str)); 156 + 157 + /* Ensure we have room for newline and NUL */ 158 + len = min_t(int, len, ARRAY_SIZE(str) - 2); 159 + 160 + /* tack on the newline */ 161 + str[len] = '\n'; 162 + str[len + 1] = '\0'; 163 + 164 + return sysfs_emit(buf, str); 122 165 } 123 166 124 167 module_param_call(pool_mode, param_set_pool_mode, param_get_pool_mode, 125 - &svc_pool_map.mode, 0644); 168 + &svc_pool_map, 0644); 126 169 127 170 /* 128 171 * Detect best pool mapping mode heuristically, ··· 293 250 int npools = -1; 294 251 295 252 mutex_lock(&svc_pool_map_mutex); 296 - 297 253 if (m->count++) { 298 254 mutex_unlock(&svc_pool_map_mutex); 299 - WARN_ON_ONCE(m->npools <= 1); 300 255 return m->npools; 301 256 } 302 257 ··· 316 275 m->mode = SVC_POOL_GLOBAL; 317 276 } 318 277 m->npools = npools; 319 - 320 - if (npools == 1) 321 - /* service is unpooled, so doesn't hold a reference */ 322 - m->count--; 323 - 324 278 mutex_unlock(&svc_pool_map_mutex); 325 279 return npools; 326 280 } 327 281 328 282 /* 329 - * Drop a reference to the global map of cpus to pools, if 330 - * pools were in use, i.e. if npools > 1. 283 + * Drop a reference to the global map of cpus to pools. 331 284 * When the last reference is dropped, the map data is 332 - * freed; this allows the sysadmin to change the pool 333 - * mode using the pool_mode module option without 334 - * rebooting or re-loading sunrpc.ko. 285 + * freed; this allows the sysadmin to change the pool. 335 286 */ 336 287 static void 337 - svc_pool_map_put(int npools) 288 + svc_pool_map_put(void) 338 289 { 339 290 struct svc_pool_map *m = &svc_pool_map; 340 291 341 - if (npools <= 1) 342 - return; 343 292 mutex_lock(&svc_pool_map_mutex); 344 - 345 293 if (!--m->count) { 346 294 kfree(m->to_pool); 347 295 m->to_pool = NULL; ··· 338 308 m->pool_to = NULL; 339 309 m->npools = 0; 340 310 } 341 - 342 311 mutex_unlock(&svc_pool_map_mutex); 343 312 } 344 313 ··· 582 553 serv = __svc_create(prog, stats, bufsize, npools, threadfn); 583 554 if (!serv) 584 555 goto out_err; 556 + serv->sv_is_pooled = true; 585 557 return serv; 586 558 out_err: 587 - svc_pool_map_put(npools); 559 + svc_pool_map_put(); 588 560 return NULL; 589 561 } 590 562 EXPORT_SYMBOL_GPL(svc_create_pooled); ··· 615 585 616 586 cache_clean_deferred(serv); 617 587 618 - svc_pool_map_put(serv->sv_nrpools); 588 + if (serv->sv_is_pooled) 589 + svc_pool_map_put(); 619 590 620 591 for (i = 0; i < serv->sv_nrpools; i++) { 621 592 struct svc_pool *pool = &serv->sv_pools[i];
+1
net/sunrpc/svc_xprt.c
··· 157 157 */ 158 158 void svc_xprt_deferred_close(struct svc_xprt *xprt) 159 159 { 160 + trace_svc_xprt_close(xprt); 160 161 if (!test_and_set_bit(XPT_CLOSE, &xprt->xpt_flags)) 161 162 svc_xprt_enqueue(xprt); 162 163 }
+55 -28
net/sunrpc/xprtrdma/svc_rdma_transport.c
··· 65 65 66 66 static struct svcxprt_rdma *svc_rdma_create_xprt(struct svc_serv *serv, 67 67 struct net *net, int node); 68 + static int svc_rdma_listen_handler(struct rdma_cm_id *cma_id, 69 + struct rdma_cm_event *event); 68 70 static struct svc_xprt *svc_rdma_create(struct svc_serv *serv, 69 71 struct net *net, 70 72 struct sockaddr *sa, int salen, ··· 122 120 svc_xprt_deferred_close(xprt); 123 121 break; 124 122 } 123 + } 124 + 125 + static struct rdma_cm_id * 126 + svc_rdma_create_listen_id(struct net *net, struct sockaddr *sap, 127 + void *context) 128 + { 129 + struct rdma_cm_id *listen_id; 130 + int ret; 131 + 132 + listen_id = rdma_create_id(net, svc_rdma_listen_handler, context, 133 + RDMA_PS_TCP, IB_QPT_RC); 134 + if (IS_ERR(listen_id)) 135 + return listen_id; 136 + 137 + /* Allow both IPv4 and IPv6 sockets to bind a single port 138 + * at the same time. 139 + */ 140 + #if IS_ENABLED(CONFIG_IPV6) 141 + ret = rdma_set_afonly(listen_id, 1); 142 + if (ret) 143 + goto out_destroy; 144 + #endif 145 + ret = rdma_bind_addr(listen_id, sap); 146 + if (ret) 147 + goto out_destroy; 148 + 149 + ret = rdma_listen(listen_id, RPCRDMA_LISTEN_BACKLOG); 150 + if (ret) 151 + goto out_destroy; 152 + 153 + return listen_id; 154 + 155 + out_destroy: 156 + rdma_destroy_id(listen_id); 157 + return ERR_PTR(ret); 125 158 } 126 159 127 160 static struct svcxprt_rdma *svc_rdma_create_xprt(struct svc_serv *serv, ··· 284 247 * 285 248 * Return values: 286 249 * %0: Do not destroy @cma_id 287 - * %1: Destroy @cma_id (never returned here) 250 + * %1: Destroy @cma_id 288 251 * 289 252 * NB: There is never a DEVICE_REMOVAL event for INADDR_ANY listeners. 290 253 */ 291 254 static int svc_rdma_listen_handler(struct rdma_cm_id *cma_id, 292 255 struct rdma_cm_event *event) 293 256 { 257 + struct sockaddr *sap = (struct sockaddr *)&cma_id->route.addr.src_addr; 258 + struct svcxprt_rdma *cma_xprt = cma_id->context; 259 + struct svc_xprt *cma_rdma = &cma_xprt->sc_xprt; 260 + struct rdma_cm_id *listen_id; 261 + 294 262 switch (event->event) { 295 263 case RDMA_CM_EVENT_CONNECT_REQUEST: 296 264 handle_connect_req(cma_id, &event->param.conn); 297 265 break; 266 + case RDMA_CM_EVENT_ADDR_CHANGE: 267 + listen_id = svc_rdma_create_listen_id(cma_rdma->xpt_net, 268 + sap, cma_xprt); 269 + if (IS_ERR(listen_id)) { 270 + pr_err("Listener dead, address change failed for device %s\n", 271 + cma_id->device->name); 272 + } else 273 + cma_xprt->sc_cm_id = listen_id; 274 + return 1; 298 275 default: 299 276 break; 300 277 } ··· 358 307 { 359 308 struct rdma_cm_id *listen_id; 360 309 struct svcxprt_rdma *cma_xprt; 361 - int ret; 362 310 363 311 if (sa->sa_family != AF_INET && sa->sa_family != AF_INET6) 364 312 return ERR_PTR(-EAFNOSUPPORT); ··· 367 317 set_bit(XPT_LISTENER, &cma_xprt->sc_xprt.xpt_flags); 368 318 strcpy(cma_xprt->sc_xprt.xpt_remotebuf, "listener"); 369 319 370 - listen_id = rdma_create_id(net, svc_rdma_listen_handler, cma_xprt, 371 - RDMA_PS_TCP, IB_QPT_RC); 320 + listen_id = svc_rdma_create_listen_id(net, sa, cma_xprt); 372 321 if (IS_ERR(listen_id)) { 373 - ret = PTR_ERR(listen_id); 374 - goto err0; 322 + kfree(cma_xprt); 323 + return (struct svc_xprt *)listen_id; 375 324 } 376 - 377 - /* Allow both IPv4 and IPv6 sockets to bind a single port 378 - * at the same time. 379 - */ 380 - #if IS_ENABLED(CONFIG_IPV6) 381 - ret = rdma_set_afonly(listen_id, 1); 382 - if (ret) 383 - goto err1; 384 - #endif 385 - ret = rdma_bind_addr(listen_id, sa); 386 - if (ret) 387 - goto err1; 388 325 cma_xprt->sc_cm_id = listen_id; 389 - 390 - ret = rdma_listen(listen_id, RPCRDMA_LISTEN_BACKLOG); 391 - if (ret) 392 - goto err1; 393 326 394 327 /* 395 328 * We need to use the address from the cm_id in case the ··· 382 349 svc_xprt_set_local(&cma_xprt->sc_xprt, sa, salen); 383 350 384 351 return &cma_xprt->sc_xprt; 385 - 386 - err1: 387 - rdma_destroy_id(listen_id); 388 - err0: 389 - kfree(cma_xprt); 390 - return ERR_PTR(ret); 391 352 } 392 353 393 354 /*