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

Pull nfsd updates from Chuck Lever:
"This is a light release containing mostly optimizations, code clean-
ups, and minor bug fixes. This development cycle has focused on non-
upstream kernel work:

1. Continuing to build upstream CI for NFSD, based on kdevops

2. Backporting NFSD filecache-related fixes to selected LTS kernels

One notable new feature in v6.10 NFSD is the addition of a new netlink
protocol dedicated to configuring NFSD. A new user space tool,
nfsdctl, is to be added to nfs-utils. Lots more to come here.

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

* tag 'nfsd-6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux: (29 commits)
NFSD: Force all NFSv4.2 COPY requests to be synchronous
SUNRPC: Fix gss_free_in_token_pages()
NFS/knfsd: Remove the invalid NFS error 'NFSERR_OPNOTSUPP'
knfsd: LOOKUP can return an illegal error value
nfsd: set security label during create operations
NFSD: Add COPY status code to OFFLOAD_STATUS response
NFSD: Record status of async copy operation in struct nfsd4_copy
SUNRPC: Remove comment for sp_lock
NFSD: add listener-{set,get} netlink command
SUNRPC: add a new svc_find_listener helper
SUNRPC: introduce svc_xprt_create_from_sa utility routine
NFSD: add write_version to netlink command
NFSD: convert write_threads to netlink command
NFSD: allow callers to pass in scope string to nfsd_svc
NFSD: move nfsd_mutex handling into nfsd_svc callers
lockd: host: Remove unnecessary statements'host = NULL;'
nfsd: don't create nfsv4recoverydir in nfsdfs when not used.
nfsd: optimise recalculate_deny_mode() for a common case
nfsd: add tracepoint in mark_client_expired_locked
nfsd: new tracepoint for check_slot_seqid
...

+1286 -271
+110
Documentation/netlink/specs/nfsd.yaml
··· 62 62 name: compound-ops 63 63 type: u32 64 64 multi-attr: true 65 + - 66 + name: server 67 + attributes: 68 + - 69 + name: threads 70 + type: u32 71 + multi-attr: true 72 + - 73 + name: gracetime 74 + type: u32 75 + - 76 + name: leasetime 77 + type: u32 78 + - 79 + name: scope 80 + type: string 81 + - 82 + name: version 83 + attributes: 84 + - 85 + name: major 86 + type: u32 87 + - 88 + name: minor 89 + type: u32 90 + - 91 + name: enabled 92 + type: flag 93 + - 94 + name: server-proto 95 + attributes: 96 + - 97 + name: version 98 + type: nest 99 + nested-attributes: version 100 + multi-attr: true 101 + - 102 + name: sock 103 + attributes: 104 + - 105 + name: addr 106 + type: binary 107 + - 108 + name: transport-name 109 + type: string 110 + - 111 + name: server-sock 112 + attributes: 113 + - 114 + name: addr 115 + type: nest 116 + nested-attributes: sock 117 + multi-attr: true 65 118 66 119 operations: 67 120 list: ··· 140 87 - sport 141 88 - dport 142 89 - compound-ops 90 + - 91 + name: threads-set 92 + doc: set the number of running threads 93 + attribute-set: server 94 + flags: [ admin-perm ] 95 + do: 96 + request: 97 + attributes: 98 + - threads 99 + - gracetime 100 + - leasetime 101 + - scope 102 + - 103 + name: threads-get 104 + doc: get the number of running threads 105 + attribute-set: server 106 + do: 107 + reply: 108 + attributes: 109 + - threads 110 + - gracetime 111 + - leasetime 112 + - scope 113 + - 114 + name: version-set 115 + doc: set nfs enabled versions 116 + attribute-set: server-proto 117 + flags: [ admin-perm ] 118 + do: 119 + request: 120 + attributes: 121 + - version 122 + - 123 + name: version-get 124 + doc: get nfs enabled versions 125 + attribute-set: server-proto 126 + do: 127 + reply: 128 + attributes: 129 + - version 130 + - 131 + name: listener-set 132 + doc: set nfs running sockets 133 + attribute-set: server-sock 134 + flags: [ admin-perm ] 135 + do: 136 + request: 137 + attributes: 138 + - addr 139 + - 140 + name: listener-get 141 + doc: get nfs running listeners 142 + attribute-set: server-sock 143 + do: 144 + reply: 145 + attributes: 146 + - addr
-1
fs/lockd/host.c
··· 117 117 if (nsm != NULL) 118 118 refcount_inc(&nsm->sm_count); 119 119 else { 120 - host = NULL; 121 120 nsm = nsm_get_handle(ni->net, ni->sap, ni->salen, 122 121 ni->hostname, ni->hostname_len); 123 122 if (unlikely(nsm == NULL)) {
+10 -6
fs/nfsd/export.c
··· 334 334 static int export_stats_init(struct export_stats *stats) 335 335 { 336 336 stats->start_time = ktime_get_seconds(); 337 - return nfsd_percpu_counters_init(stats->counter, EXP_STATS_COUNTERS_NUM); 337 + return percpu_counter_init_many(stats->counter, 0, GFP_KERNEL, 338 + EXP_STATS_COUNTERS_NUM); 338 339 } 339 340 340 341 static void export_stats_reset(struct export_stats *stats) 341 342 { 342 - if (stats) 343 - nfsd_percpu_counters_reset(stats->counter, 344 - EXP_STATS_COUNTERS_NUM); 343 + if (stats) { 344 + int i; 345 + 346 + for (i = 0; i < EXP_STATS_COUNTERS_NUM; i++) 347 + percpu_counter_set(&stats->counter[i], 0); 348 + } 345 349 } 346 350 347 351 static void export_stats_destroy(struct export_stats *stats) 348 352 { 349 353 if (stats) 350 - nfsd_percpu_counters_destroy(stats->counter, 351 - EXP_STATS_COUNTERS_NUM); 354 + percpu_counter_destroy_many(stats->counter, 355 + EXP_STATS_COUNTERS_NUM); 352 356 } 353 357 354 358 static void svc_export_put(struct kref *ref)
+66
fs/nfsd/netlink.c
··· 10 10 11 11 #include <uapi/linux/nfsd_netlink.h> 12 12 13 + /* Common nested types */ 14 + const struct nla_policy nfsd_sock_nl_policy[NFSD_A_SOCK_TRANSPORT_NAME + 1] = { 15 + [NFSD_A_SOCK_ADDR] = { .type = NLA_BINARY, }, 16 + [NFSD_A_SOCK_TRANSPORT_NAME] = { .type = NLA_NUL_STRING, }, 17 + }; 18 + 19 + const struct nla_policy nfsd_version_nl_policy[NFSD_A_VERSION_ENABLED + 1] = { 20 + [NFSD_A_VERSION_MAJOR] = { .type = NLA_U32, }, 21 + [NFSD_A_VERSION_MINOR] = { .type = NLA_U32, }, 22 + [NFSD_A_VERSION_ENABLED] = { .type = NLA_FLAG, }, 23 + }; 24 + 25 + /* NFSD_CMD_THREADS_SET - do */ 26 + static const struct nla_policy nfsd_threads_set_nl_policy[NFSD_A_SERVER_SCOPE + 1] = { 27 + [NFSD_A_SERVER_THREADS] = { .type = NLA_U32, }, 28 + [NFSD_A_SERVER_GRACETIME] = { .type = NLA_U32, }, 29 + [NFSD_A_SERVER_LEASETIME] = { .type = NLA_U32, }, 30 + [NFSD_A_SERVER_SCOPE] = { .type = NLA_NUL_STRING, }, 31 + }; 32 + 33 + /* NFSD_CMD_VERSION_SET - do */ 34 + static const struct nla_policy nfsd_version_set_nl_policy[NFSD_A_SERVER_PROTO_VERSION + 1] = { 35 + [NFSD_A_SERVER_PROTO_VERSION] = NLA_POLICY_NESTED(nfsd_version_nl_policy), 36 + }; 37 + 38 + /* NFSD_CMD_LISTENER_SET - do */ 39 + static const struct nla_policy nfsd_listener_set_nl_policy[NFSD_A_SERVER_SOCK_ADDR + 1] = { 40 + [NFSD_A_SERVER_SOCK_ADDR] = NLA_POLICY_NESTED(nfsd_sock_nl_policy), 41 + }; 42 + 13 43 /* Ops table for nfsd */ 14 44 static const struct genl_split_ops nfsd_nl_ops[] = { 15 45 { ··· 48 18 .dumpit = nfsd_nl_rpc_status_get_dumpit, 49 19 .done = nfsd_nl_rpc_status_get_done, 50 20 .flags = GENL_CMD_CAP_DUMP, 21 + }, 22 + { 23 + .cmd = NFSD_CMD_THREADS_SET, 24 + .doit = nfsd_nl_threads_set_doit, 25 + .policy = nfsd_threads_set_nl_policy, 26 + .maxattr = NFSD_A_SERVER_SCOPE, 27 + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, 28 + }, 29 + { 30 + .cmd = NFSD_CMD_THREADS_GET, 31 + .doit = nfsd_nl_threads_get_doit, 32 + .flags = GENL_CMD_CAP_DO, 33 + }, 34 + { 35 + .cmd = NFSD_CMD_VERSION_SET, 36 + .doit = nfsd_nl_version_set_doit, 37 + .policy = nfsd_version_set_nl_policy, 38 + .maxattr = NFSD_A_SERVER_PROTO_VERSION, 39 + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, 40 + }, 41 + { 42 + .cmd = NFSD_CMD_VERSION_GET, 43 + .doit = nfsd_nl_version_get_doit, 44 + .flags = GENL_CMD_CAP_DO, 45 + }, 46 + { 47 + .cmd = NFSD_CMD_LISTENER_SET, 48 + .doit = nfsd_nl_listener_set_doit, 49 + .policy = nfsd_listener_set_nl_policy, 50 + .maxattr = NFSD_A_SERVER_SOCK_ADDR, 51 + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, 52 + }, 53 + { 54 + .cmd = NFSD_CMD_LISTENER_GET, 55 + .doit = nfsd_nl_listener_get_doit, 56 + .flags = GENL_CMD_CAP_DO, 51 57 }, 52 58 }; 53 59
+10
fs/nfsd/netlink.h
··· 11 11 12 12 #include <uapi/linux/nfsd_netlink.h> 13 13 14 + /* Common nested types */ 15 + extern const struct nla_policy nfsd_sock_nl_policy[NFSD_A_SOCK_TRANSPORT_NAME + 1]; 16 + extern const struct nla_policy nfsd_version_nl_policy[NFSD_A_VERSION_ENABLED + 1]; 17 + 14 18 int nfsd_nl_rpc_status_get_start(struct netlink_callback *cb); 15 19 int nfsd_nl_rpc_status_get_done(struct netlink_callback *cb); 16 20 17 21 int nfsd_nl_rpc_status_get_dumpit(struct sk_buff *skb, 18 22 struct netlink_callback *cb); 23 + int nfsd_nl_threads_set_doit(struct sk_buff *skb, struct genl_info *info); 24 + int nfsd_nl_threads_get_doit(struct sk_buff *skb, struct genl_info *info); 25 + int nfsd_nl_version_set_doit(struct sk_buff *skb, struct genl_info *info); 26 + int nfsd_nl_version_get_doit(struct sk_buff *skb, struct genl_info *info); 27 + int nfsd_nl_listener_set_doit(struct sk_buff *skb, struct genl_info *info); 28 + int nfsd_nl_listener_get_doit(struct sk_buff *skb, struct genl_info *info); 19 29 20 30 extern struct genl_family nfsd_nl_family; 21 31
+1
fs/nfsd/netns.h
··· 218 218 /* Simple check to find out if a given net was properly initialized */ 219 219 #define nfsd_netns_ready(nn) ((nn)->sessionid_hashtbl) 220 220 221 + extern bool nfsd_support_version(int vers); 221 222 extern void nfsd_netns_free_versions(struct nfsd_net *nn); 222 223 223 224 extern unsigned int nfsd_net_id;
+9 -22
fs/nfsd/nfs4callback.c
··· 978 978 return max(((u32)nn->nfsd4_lease)/10, 1u) * HZ; 979 979 } 980 980 981 - static struct workqueue_struct *callback_wq; 982 - 983 981 static bool nfsd4_queue_cb(struct nfsd4_callback *cb) 984 982 { 985 - trace_nfsd_cb_queue(cb->cb_clp, cb); 986 - return queue_work(callback_wq, &cb->cb_work); 983 + struct nfs4_client *clp = cb->cb_clp; 984 + 985 + trace_nfsd_cb_queue(clp, cb); 986 + return queue_work(clp->cl_callback_wq, &cb->cb_work); 987 987 } 988 988 989 989 static void nfsd41_cb_inflight_begin(struct nfs4_client *clp) ··· 1153 1153 void nfsd4_probe_callback_sync(struct nfs4_client *clp) 1154 1154 { 1155 1155 nfsd4_probe_callback(clp); 1156 - flush_workqueue(callback_wq); 1156 + flush_workqueue(clp->cl_callback_wq); 1157 1157 } 1158 1158 1159 1159 void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *conn) ··· 1372 1372 .rpc_release = nfsd4_cb_release, 1373 1373 }; 1374 1374 1375 - int nfsd4_create_callback_queue(void) 1376 - { 1377 - callback_wq = alloc_ordered_workqueue("nfsd4_callbacks", 0); 1378 - if (!callback_wq) 1379 - return -ENOMEM; 1380 - return 0; 1381 - } 1382 - 1383 - void nfsd4_destroy_callback_queue(void) 1384 - { 1385 - destroy_workqueue(callback_wq); 1386 - } 1387 - 1388 1375 /* must be called under the state lock */ 1389 1376 void nfsd4_shutdown_callback(struct nfs4_client *clp) 1390 1377 { ··· 1385 1398 * client, destroy the rpc client, and stop: 1386 1399 */ 1387 1400 nfsd4_run_cb(&clp->cl_cb_null); 1388 - flush_workqueue(callback_wq); 1401 + flush_workqueue(clp->cl_callback_wq); 1389 1402 nfsd41_cb_inflight_wait_complete(clp); 1390 1403 } 1391 1404 ··· 1407 1420 1408 1421 /* 1409 1422 * Note there isn't a lot of locking in this code; instead we depend on 1410 - * the fact that it is run from the callback_wq, which won't run two 1411 - * work items at once. So, for example, callback_wq handles all access 1412 - * of cl_cb_client and all calls to rpc_create or rpc_shutdown_client. 1423 + * the fact that it is run from clp->cl_callback_wq, which won't run two 1424 + * work items at once. So, for example, clp->cl_callback_wq handles all 1425 + * access of cl_cb_client and all calls to rpc_create or rpc_shutdown_client. 1413 1426 */ 1414 1427 static void nfsd4_process_cb_update(struct nfsd4_callback *cb) 1415 1428 {
+66 -13
fs/nfsd/nfs4proc.c
··· 1737 1737 nfs4_put_copy(copy); 1738 1738 } 1739 1739 1740 - static void nfsd4_send_cb_offload(struct nfsd4_copy *copy, __be32 nfserr) 1740 + static void nfsd4_send_cb_offload(struct nfsd4_copy *copy) 1741 1741 { 1742 1742 struct nfsd4_cb_offload *cbo; 1743 1743 ··· 1747 1747 1748 1748 memcpy(&cbo->co_res, &copy->cp_res, sizeof(copy->cp_res)); 1749 1749 memcpy(&cbo->co_fh, &copy->fh, sizeof(copy->fh)); 1750 - cbo->co_nfserr = nfserr; 1750 + cbo->co_nfserr = copy->nfserr; 1751 1751 1752 1752 nfsd4_init_cb(&cbo->co_cb, copy->cp_clp, &nfsd4_cb_offload_ops, 1753 1753 NFSPROC4_CLNT_CB_OFFLOAD); 1754 1754 trace_nfsd_cb_offload(copy->cp_clp, &cbo->co_res.cb_stateid, 1755 - &cbo->co_fh, copy->cp_count, nfserr); 1755 + &cbo->co_fh, copy->cp_count, copy->nfserr); 1756 1756 nfsd4_run_cb(&cbo->co_cb); 1757 1757 } 1758 1758 ··· 1766 1766 static int nfsd4_do_async_copy(void *data) 1767 1767 { 1768 1768 struct nfsd4_copy *copy = (struct nfsd4_copy *)data; 1769 - __be32 nfserr; 1770 1769 1771 1770 trace_nfsd_copy_do_async(copy); 1772 1771 if (nfsd4_ssc_is_inter(copy)) { ··· 1776 1777 if (IS_ERR(filp)) { 1777 1778 switch (PTR_ERR(filp)) { 1778 1779 case -EBADF: 1779 - nfserr = nfserr_wrong_type; 1780 + copy->nfserr = nfserr_wrong_type; 1780 1781 break; 1781 1782 default: 1782 - nfserr = nfserr_offload_denied; 1783 + copy->nfserr = nfserr_offload_denied; 1783 1784 } 1784 1785 /* ss_mnt will be unmounted by the laundromat */ 1785 1786 goto do_callback; 1786 1787 } 1787 - nfserr = nfsd4_do_copy(copy, filp, copy->nf_dst->nf_file, 1788 - false); 1788 + copy->nfserr = nfsd4_do_copy(copy, filp, copy->nf_dst->nf_file, 1789 + false); 1789 1790 nfsd4_cleanup_inter_ssc(copy->ss_nsui, filp, copy->nf_dst); 1790 1791 } else { 1791 - nfserr = nfsd4_do_copy(copy, copy->nf_src->nf_file, 1792 - copy->nf_dst->nf_file, false); 1792 + copy->nfserr = nfsd4_do_copy(copy, copy->nf_src->nf_file, 1793 + copy->nf_dst->nf_file, false); 1793 1794 } 1794 1795 1795 1796 do_callback: 1796 - nfsd4_send_cb_offload(copy, nfserr); 1797 + set_bit(NFSD4_COPY_F_COMPLETED, &copy->cp_flags); 1798 + nfsd4_send_cb_offload(copy); 1797 1799 cleanup_async_copy(copy); 1798 1800 return 0; 1799 1801 } ··· 1806 1806 struct nfsd4_copy *copy = &u->copy; 1807 1807 __be32 status; 1808 1808 struct nfsd4_copy *async_copy = NULL; 1809 + 1810 + /* 1811 + * Currently, async COPY is not reliable. Force all COPY 1812 + * requests to be synchronous to avoid client application 1813 + * hangs waiting for COPY completion. 1814 + */ 1815 + nfsd4_copy_set_sync(copy, true); 1809 1816 1810 1817 copy->cp_clp = cstate->clp; 1811 1818 if (nfsd4_ssc_is_inter(copy)) { ··· 2010 2003 struct nfsd4_copy *copy; 2011 2004 struct nfs4_client *clp = cstate->clp; 2012 2005 2006 + os->completed = false; 2013 2007 spin_lock(&clp->async_lock); 2014 2008 copy = find_async_copy_locked(clp, &os->stateid); 2015 - if (copy) 2009 + if (copy) { 2016 2010 os->count = copy->cp_res.wr_bytes_written; 2017 - else 2011 + if (test_bit(NFSD4_COPY_F_COMPLETED, &copy->cp_flags)) { 2012 + os->completed = true; 2013 + os->status = copy->nfserr; 2014 + } 2015 + } else 2018 2016 status = nfserr_bad_stateid; 2019 2017 spin_unlock(&clp->async_lock); 2020 2018 ··· 2164 2152 2165 2153 status = _nfsd4_verify(rqstp, cstate, &u->nverify); 2166 2154 return status == nfserr_same ? nfs_ok : status; 2155 + } 2156 + 2157 + static __be32 2158 + nfsd4_get_dir_delegation(struct svc_rqst *rqstp, 2159 + struct nfsd4_compound_state *cstate, 2160 + union nfsd4_op_u *u) 2161 + { 2162 + struct nfsd4_get_dir_delegation *gdd = &u->get_dir_delegation; 2163 + 2164 + /* 2165 + * RFC 8881, section 18.39.3 says: 2166 + * 2167 + * "The server may refuse to grant the delegation. In that case, the 2168 + * server will return NFS4ERR_DIRDELEG_UNAVAIL." 2169 + * 2170 + * This is sub-optimal, since it means that the server would need to 2171 + * abort compound processing just because the delegation wasn't 2172 + * available. RFC8881bis should change this to allow the server to 2173 + * return NFS4_OK with a non-fatal status of GDD4_UNAVAIL in this 2174 + * situation. 2175 + */ 2176 + gdd->gddrnf_status = GDD4_UNAVAIL; 2177 + return nfs_ok; 2167 2178 } 2168 2179 2169 2180 #ifdef CONFIG_NFSD_PNFS ··· 3117 3082 * sizeof(__be32); 3118 3083 } 3119 3084 3085 + static u32 nfsd4_get_dir_delegation_rsize(const struct svc_rqst *rqstp, 3086 + const struct nfsd4_op *op) 3087 + { 3088 + return (op_encode_hdr_size + 3089 + 1 /* gddr_status */ + 3090 + op_encode_verifier_maxsz + 3091 + op_encode_stateid_maxsz + 3092 + 2 /* gddr_notification */ + 3093 + 2 /* gddr_child_attributes */ + 3094 + 2 /* gddr_dir_attributes */); 3095 + } 3096 + 3120 3097 #ifdef CONFIG_NFSD_PNFS 3121 3098 static u32 nfsd4_getdeviceinfo_rsize(const struct svc_rqst *rqstp, 3122 3099 const struct nfsd4_op *op) ··· 3516 3469 .op_name = "OP_FREE_STATEID", 3517 3470 .op_get_currentstateid = nfsd4_get_freestateid, 3518 3471 .op_rsize_bop = nfsd4_only_status_rsize, 3472 + }, 3473 + [OP_GET_DIR_DELEGATION] = { 3474 + .op_func = nfsd4_get_dir_delegation, 3475 + .op_flags = OP_MODIFIES_SOMETHING, 3476 + .op_name = "OP_GET_DIR_DELEGATION", 3477 + .op_rsize_bop = nfsd4_get_dir_delegation_rsize, 3519 3478 }, 3520 3479 #ifdef CONFIG_NFSD_PNFS 3521 3480 [OP_GETDEVICEINFO] = {
+104 -84
fs/nfsd/nfs4state.c
··· 541 541 } 542 542 543 543 static struct nfs4_openowner * 544 - find_openstateowner_str_locked(unsigned int hashval, struct nfsd4_open *open, 544 + find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open, 545 545 struct nfs4_client *clp) 546 546 { 547 547 struct nfs4_stateowner *so; ··· 556 556 return openowner(nfs4_get_stateowner(so)); 557 557 } 558 558 return NULL; 559 - } 560 - 561 - static struct nfs4_openowner * 562 - find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open, 563 - struct nfs4_client *clp) 564 - { 565 - struct nfs4_openowner *oo; 566 - 567 - spin_lock(&clp->cl_lock); 568 - oo = find_openstateowner_str_locked(hashval, open, clp); 569 - spin_unlock(&clp->cl_lock); 570 - return oo; 571 559 } 572 560 573 561 static inline u32 ··· 1397 1409 recalculate_deny_mode(struct nfs4_file *fp) 1398 1410 { 1399 1411 struct nfs4_ol_stateid *stp; 1412 + u32 old_deny; 1400 1413 1401 1414 spin_lock(&fp->fi_lock); 1415 + old_deny = fp->fi_share_deny; 1402 1416 fp->fi_share_deny = 0; 1403 - list_for_each_entry(stp, &fp->fi_stateids, st_perfile) 1417 + list_for_each_entry(stp, &fp->fi_stateids, st_perfile) { 1404 1418 fp->fi_share_deny |= bmap_to_share_mode(stp->st_deny_bmap); 1419 + if (fp->fi_share_deny == old_deny) 1420 + break; 1421 + } 1405 1422 spin_unlock(&fp->fi_lock); 1406 1423 } 1407 1424 ··· 2238 2245 GFP_KERNEL); 2239 2246 if (!clp->cl_ownerstr_hashtbl) 2240 2247 goto err_no_hashtbl; 2248 + clp->cl_callback_wq = alloc_ordered_workqueue("nfsd4_callbacks", 0); 2249 + if (!clp->cl_callback_wq) 2250 + goto err_no_callback_wq; 2251 + 2241 2252 for (i = 0; i < OWNER_HASH_SIZE; i++) 2242 2253 INIT_LIST_HEAD(&clp->cl_ownerstr_hashtbl[i]); 2243 2254 INIT_LIST_HEAD(&clp->cl_sessions); ··· 2264 2267 spin_lock_init(&clp->cl_lock); 2265 2268 rpc_init_wait_queue(&clp->cl_cb_waitq, "Backchannel slot table"); 2266 2269 return clp; 2270 + err_no_callback_wq: 2271 + kfree(clp->cl_ownerstr_hashtbl); 2267 2272 err_no_hashtbl: 2268 2273 kfree(clp->cl_name.data); 2269 2274 err_no_name: ··· 2279 2280 struct nfs4_client *clp = container_of(c, struct nfs4_client, cl_nfsdfs); 2280 2281 2281 2282 free_svc_cred(&clp->cl_cred); 2283 + destroy_workqueue(clp->cl_callback_wq); 2282 2284 kfree(clp->cl_ownerstr_hashtbl); 2283 2285 kfree(clp->cl_name.data); 2284 2286 kfree(clp->cl_nii_domain.data); ··· 2352 2352 2353 2353 static __be32 mark_client_expired_locked(struct nfs4_client *clp) 2354 2354 { 2355 - if (atomic_read(&clp->cl_rpc_users)) 2355 + int users = atomic_read(&clp->cl_rpc_users); 2356 + 2357 + trace_nfsd_mark_client_expired(clp, users); 2358 + 2359 + if (users) 2356 2360 return nfserr_jukebox; 2357 2361 unhash_client_locked(clp); 2358 2362 return nfs_ok; ··· 3645 3641 return status; 3646 3642 } 3647 3643 3648 - static __be32 3649 - check_slot_seqid(u32 seqid, u32 slot_seqid, int slot_inuse) 3644 + static __be32 check_slot_seqid(u32 seqid, u32 slot_seqid, bool slot_inuse) 3650 3645 { 3651 - dprintk("%s enter. seqid %d slot_seqid %d\n", __func__, seqid, 3652 - slot_seqid); 3653 - 3654 3646 /* The slot is in use, and no response has been sent. */ 3655 3647 if (slot_inuse) { 3656 3648 if (seqid == slot_seqid) ··· 3823 3823 } 3824 3824 3825 3825 /* RFC 8881 Section 18.36.4 Phase 2: Sequence ID processing. */ 3826 - if (conf) 3826 + if (conf) { 3827 3827 cs_slot = &conf->cl_cs_slot; 3828 - else 3828 + trace_nfsd_slot_seqid_conf(conf, cr_ses); 3829 + } else { 3829 3830 cs_slot = &unconf->cl_cs_slot; 3831 + trace_nfsd_slot_seqid_unconf(unconf, cr_ses); 3832 + } 3830 3833 status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0); 3831 3834 switch (status) { 3832 3835 case nfs_ok: ··· 4224 4221 * sr_highest_slotid and the sr_target_slot id to maxslots */ 4225 4222 seq->maxslots = session->se_fchannel.maxreqs; 4226 4223 4224 + trace_nfsd_slot_seqid_sequence(clp, seq, slot); 4227 4225 status = check_slot_seqid(seq->seqid, slot->sl_seqid, 4228 4226 slot->sl_flags & NFSD4_SLOT_INUSE); 4229 4227 if (status == nfserr_replay_cache) { ··· 4666 4662 atomic_set(&nn->nfsd_courtesy_clients, 0); 4667 4663 } 4668 4664 4665 + enum rp_lock { 4666 + RP_UNLOCKED, 4667 + RP_LOCKED, 4668 + RP_UNHASHED, 4669 + }; 4670 + 4669 4671 static void init_nfs4_replay(struct nfs4_replay *rp) 4670 4672 { 4671 4673 rp->rp_status = nfserr_serverfault; 4672 4674 rp->rp_buflen = 0; 4673 4675 rp->rp_buf = rp->rp_ibuf; 4674 - mutex_init(&rp->rp_mutex); 4676 + atomic_set(&rp->rp_locked, RP_UNLOCKED); 4675 4677 } 4676 4678 4677 - static void nfsd4_cstate_assign_replay(struct nfsd4_compound_state *cstate, 4678 - struct nfs4_stateowner *so) 4679 + static int nfsd4_cstate_assign_replay(struct nfsd4_compound_state *cstate, 4680 + struct nfs4_stateowner *so) 4679 4681 { 4680 4682 if (!nfsd4_has_session(cstate)) { 4681 - mutex_lock(&so->so_replay.rp_mutex); 4683 + wait_var_event(&so->so_replay.rp_locked, 4684 + atomic_cmpxchg(&so->so_replay.rp_locked, 4685 + RP_UNLOCKED, RP_LOCKED) != RP_LOCKED); 4686 + if (atomic_read(&so->so_replay.rp_locked) == RP_UNHASHED) 4687 + return -EAGAIN; 4682 4688 cstate->replay_owner = nfs4_get_stateowner(so); 4683 4689 } 4690 + return 0; 4684 4691 } 4685 4692 4686 4693 void nfsd4_cstate_clear_replay(struct nfsd4_compound_state *cstate) ··· 4700 4685 4701 4686 if (so != NULL) { 4702 4687 cstate->replay_owner = NULL; 4703 - mutex_unlock(&so->so_replay.rp_mutex); 4688 + atomic_set(&so->so_replay.rp_locked, RP_UNLOCKED); 4689 + wake_up_var(&so->so_replay.rp_locked); 4704 4690 nfs4_put_stateowner(so); 4705 4691 } 4706 4692 } ··· 4882 4866 } 4883 4867 4884 4868 static struct nfs4_openowner * 4885 - alloc_init_open_stateowner(unsigned int strhashval, struct nfsd4_open *open, 4886 - struct nfsd4_compound_state *cstate) 4869 + find_or_alloc_open_stateowner(unsigned int strhashval, struct nfsd4_open *open, 4870 + struct nfsd4_compound_state *cstate) 4887 4871 { 4888 4872 struct nfs4_client *clp = cstate->clp; 4889 - struct nfs4_openowner *oo, *ret; 4873 + struct nfs4_openowner *oo, *new = NULL; 4890 4874 4891 - oo = alloc_stateowner(openowner_slab, &open->op_owner, clp); 4892 - if (!oo) 4893 - return NULL; 4894 - oo->oo_owner.so_ops = &openowner_ops; 4895 - oo->oo_owner.so_is_open_owner = 1; 4896 - oo->oo_owner.so_seqid = open->op_seqid; 4897 - oo->oo_flags = 0; 4898 - if (nfsd4_has_session(cstate)) 4899 - oo->oo_flags |= NFS4_OO_CONFIRMED; 4900 - oo->oo_time = 0; 4901 - oo->oo_last_closed_stid = NULL; 4902 - INIT_LIST_HEAD(&oo->oo_close_lru); 4875 + retry: 4903 4876 spin_lock(&clp->cl_lock); 4904 - ret = find_openstateowner_str_locked(strhashval, open, clp); 4905 - if (ret == NULL) { 4906 - hash_openowner(oo, clp, strhashval); 4907 - ret = oo; 4908 - } else 4909 - nfs4_free_stateowner(&oo->oo_owner); 4910 - 4877 + oo = find_openstateowner_str(strhashval, open, clp); 4878 + if (!oo && new) { 4879 + hash_openowner(new, clp, strhashval); 4880 + spin_unlock(&clp->cl_lock); 4881 + return new; 4882 + } 4911 4883 spin_unlock(&clp->cl_lock); 4912 - return ret; 4884 + 4885 + if (oo && !(oo->oo_flags & NFS4_OO_CONFIRMED)) { 4886 + /* Replace unconfirmed owners without checking for replay. */ 4887 + release_openowner(oo); 4888 + oo = NULL; 4889 + } 4890 + if (oo) { 4891 + if (new) 4892 + nfs4_free_stateowner(&new->oo_owner); 4893 + return oo; 4894 + } 4895 + 4896 + new = alloc_stateowner(openowner_slab, &open->op_owner, clp); 4897 + if (!new) 4898 + return NULL; 4899 + new->oo_owner.so_ops = &openowner_ops; 4900 + new->oo_owner.so_is_open_owner = 1; 4901 + new->oo_owner.so_seqid = open->op_seqid; 4902 + new->oo_flags = 0; 4903 + if (nfsd4_has_session(cstate)) 4904 + new->oo_flags |= NFS4_OO_CONFIRMED; 4905 + new->oo_time = 0; 4906 + new->oo_last_closed_stid = NULL; 4907 + INIT_LIST_HEAD(&new->oo_close_lru); 4908 + goto retry; 4913 4909 } 4914 4910 4915 4911 static struct nfs4_ol_stateid * ··· 4997 4969 * Wait for the refcount to drop to 2. Since it has been unhashed, 4998 4970 * there should be no danger of the refcount going back up again at 4999 4971 * this point. 4972 + * Some threads with a reference might be waiting for rp_locked, 4973 + * so tell them to stop waiting. 5000 4974 */ 4975 + atomic_set(&oo->oo_owner.so_replay.rp_locked, RP_UNHASHED); 4976 + wake_up_var(&oo->oo_owner.so_replay.rp_locked); 5001 4977 wait_event(close_wq, refcount_read(&s->st_stid.sc_count) == 2); 5002 4978 5003 4979 release_all_access(s); ··· 5374 5342 clp = cstate->clp; 5375 5343 5376 5344 strhashval = ownerstr_hashval(&open->op_owner); 5377 - oo = find_openstateowner_str(strhashval, open, clp); 5345 + retry: 5346 + oo = find_or_alloc_open_stateowner(strhashval, open, cstate); 5378 5347 open->op_openowner = oo; 5379 - if (!oo) { 5380 - goto new_owner; 5381 - } 5382 - if (!(oo->oo_flags & NFS4_OO_CONFIRMED)) { 5383 - /* Replace unconfirmed owners without checking for replay. */ 5384 - release_openowner(oo); 5385 - open->op_openowner = NULL; 5386 - goto new_owner; 5348 + if (!oo) 5349 + return nfserr_jukebox; 5350 + if (nfsd4_cstate_assign_replay(cstate, &oo->oo_owner) == -EAGAIN) { 5351 + nfs4_put_stateowner(&oo->oo_owner); 5352 + goto retry; 5387 5353 } 5388 5354 status = nfsd4_check_seqid(cstate, &oo->oo_owner, open->op_seqid); 5389 5355 if (status) 5390 5356 return status; 5391 - goto alloc_stateid; 5392 - new_owner: 5393 - oo = alloc_init_open_stateowner(strhashval, open, cstate); 5394 - if (oo == NULL) 5395 - return nfserr_jukebox; 5396 - open->op_openowner = oo; 5397 - alloc_stateid: 5357 + 5398 5358 open->op_stp = nfs4_alloc_open_stateid(clp); 5399 5359 if (!open->op_stp) 5400 5360 return nfserr_jukebox; ··· 6157 6133 void nfsd4_cleanup_open_state(struct nfsd4_compound_state *cstate, 6158 6134 struct nfsd4_open *open) 6159 6135 { 6160 - if (open->op_openowner) { 6161 - struct nfs4_stateowner *so = &open->op_openowner->oo_owner; 6162 - 6163 - nfsd4_cstate_assign_replay(cstate, so); 6164 - nfs4_put_stateowner(so); 6165 - } 6136 + if (open->op_openowner) 6137 + nfs4_put_stateowner(&open->op_openowner->oo_owner); 6166 6138 if (open->op_file) 6167 6139 kmem_cache_free(file_slab, open->op_file); 6168 6140 if (open->op_stp) ··· 7222 7202 trace_nfsd_preprocess(seqid, stateid); 7223 7203 7224 7204 *stpp = NULL; 7205 + retry: 7225 7206 status = nfsd4_lookup_stateid(cstate, stateid, 7226 7207 typemask, statusmask, &s, nn); 7227 7208 if (status) 7228 7209 return status; 7229 7210 stp = openlockstateid(s); 7230 - nfsd4_cstate_assign_replay(cstate, stp->st_stateowner); 7211 + if (nfsd4_cstate_assign_replay(cstate, stp->st_stateowner) == -EAGAIN) { 7212 + nfs4_put_stateowner(stp->st_stateowner); 7213 + goto retry; 7214 + } 7231 7215 7232 7216 status = nfs4_seqid_op_checks(cstate, stateid, seqid, stp); 7233 7217 if (!status) ··· 7373 7349 return status; 7374 7350 } 7375 7351 7376 - static void nfsd4_close_open_stateid(struct nfs4_ol_stateid *s) 7352 + static bool nfsd4_close_open_stateid(struct nfs4_ol_stateid *s) 7377 7353 { 7378 7354 struct nfs4_client *clp = s->st_stid.sc_client; 7379 7355 bool unhashed; ··· 7390 7366 list_for_each_entry(stp, &reaplist, st_locks) 7391 7367 nfs4_free_cpntf_statelist(clp->net, &stp->st_stid); 7392 7368 free_ol_stateid_reaplist(&reaplist); 7369 + return false; 7393 7370 } else { 7394 7371 spin_unlock(&clp->cl_lock); 7395 7372 free_ol_stateid_reaplist(&reaplist); 7396 - if (unhashed) 7397 - move_to_close_lru(s, clp->net); 7373 + return unhashed; 7398 7374 } 7399 7375 } 7400 7376 ··· 7410 7386 struct nfs4_ol_stateid *stp; 7411 7387 struct net *net = SVC_NET(rqstp); 7412 7388 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 7389 + bool need_move_to_close_list; 7413 7390 7414 7391 dprintk("NFSD: nfsd4_close on file %pd\n", 7415 7392 cstate->current_fh.fh_dentry); ··· 7435 7410 */ 7436 7411 nfs4_inc_and_copy_stateid(&close->cl_stateid, &stp->st_stid); 7437 7412 7438 - nfsd4_close_open_stateid(stp); 7413 + need_move_to_close_list = nfsd4_close_open_stateid(stp); 7439 7414 mutex_unlock(&stp->st_mutex); 7415 + if (need_move_to_close_list) 7416 + move_to_close_lru(stp, net); 7440 7417 7441 7418 /* v4.1+ suggests that we send a special stateid in here, since the 7442 7419 * clients should just ignore this anyway. Since this is not useful ··· 8652 8625 if (ret) 8653 8626 return ret; 8654 8627 8655 - ret = nfsd4_create_callback_queue(); 8656 - if (ret) { 8657 - rhltable_destroy(&nfs4_file_rhltable); 8658 - return ret; 8659 - } 8660 - 8661 8628 set_max_delegations(); 8662 8629 return 0; 8663 8630 } ··· 8692 8671 void 8693 8672 nfs4_state_shutdown(void) 8694 8673 { 8695 - nfsd4_destroy_callback_queue(); 8696 8674 rhltable_destroy(&nfs4_file_rhltable); 8697 8675 } 8698 8676
+80 -3
fs/nfsd/nfs4xdr.c
··· 1732 1732 return nfsd4_decode_stateid4(argp, &free_stateid->fr_stateid); 1733 1733 } 1734 1734 1735 + static __be32 1736 + nfsd4_decode_get_dir_delegation(struct nfsd4_compoundargs *argp, 1737 + union nfsd4_op_u *u) 1738 + { 1739 + struct nfsd4_get_dir_delegation *gdd = &u->get_dir_delegation; 1740 + __be32 status; 1741 + 1742 + memset(gdd, 0, sizeof(*gdd)); 1743 + 1744 + if (xdr_stream_decode_bool(argp->xdr, &gdd->gdda_signal_deleg_avail) < 0) 1745 + return nfserr_bad_xdr; 1746 + status = nfsd4_decode_bitmap4(argp, gdd->gdda_notification_types, 1747 + ARRAY_SIZE(gdd->gdda_notification_types)); 1748 + if (status) 1749 + return status; 1750 + status = nfsd4_decode_nfstime4(argp, &gdd->gdda_child_attr_delay); 1751 + if (status) 1752 + return status; 1753 + status = nfsd4_decode_nfstime4(argp, &gdd->gdda_dir_attr_delay); 1754 + if (status) 1755 + return status; 1756 + status = nfsd4_decode_bitmap4(argp, gdd->gdda_child_attributes, 1757 + ARRAY_SIZE(gdd->gdda_child_attributes)); 1758 + if (status) 1759 + return status; 1760 + return nfsd4_decode_bitmap4(argp, gdd->gdda_dir_attributes, 1761 + ARRAY_SIZE(gdd->gdda_dir_attributes)); 1762 + } 1763 + 1735 1764 #ifdef CONFIG_NFSD_PNFS 1736 1765 static __be32 1737 1766 nfsd4_decode_getdeviceinfo(struct nfsd4_compoundargs *argp, ··· 2399 2370 [OP_CREATE_SESSION] = nfsd4_decode_create_session, 2400 2371 [OP_DESTROY_SESSION] = nfsd4_decode_destroy_session, 2401 2372 [OP_FREE_STATEID] = nfsd4_decode_free_stateid, 2402 - [OP_GET_DIR_DELEGATION] = nfsd4_decode_notsupp, 2373 + [OP_GET_DIR_DELEGATION] = nfsd4_decode_get_dir_delegation, 2403 2374 #ifdef CONFIG_NFSD_PNFS 2404 2375 [OP_GETDEVICEINFO] = nfsd4_decode_getdeviceinfo, 2405 2376 [OP_GETDEVICELIST] = nfsd4_decode_notsupp, ··· 4992 4963 return nfs_ok; 4993 4964 } 4994 4965 4966 + static __be32 4967 + nfsd4_encode_get_dir_delegation(struct nfsd4_compoundres *resp, __be32 nfserr, 4968 + union nfsd4_op_u *u) 4969 + { 4970 + struct nfsd4_get_dir_delegation *gdd = &u->get_dir_delegation; 4971 + struct xdr_stream *xdr = resp->xdr; 4972 + __be32 status = nfserr_resource; 4973 + 4974 + switch(gdd->gddrnf_status) { 4975 + case GDD4_OK: 4976 + if (xdr_stream_encode_u32(xdr, GDD4_OK) != XDR_UNIT) 4977 + break; 4978 + status = nfsd4_encode_verifier4(xdr, &gdd->gddr_cookieverf); 4979 + if (status) 4980 + break; 4981 + status = nfsd4_encode_stateid4(xdr, &gdd->gddr_stateid); 4982 + if (status) 4983 + break; 4984 + status = nfsd4_encode_bitmap4(xdr, gdd->gddr_notification[0], 0, 0); 4985 + if (status) 4986 + break; 4987 + status = nfsd4_encode_bitmap4(xdr, gdd->gddr_child_attributes[0], 4988 + gdd->gddr_child_attributes[1], 4989 + gdd->gddr_child_attributes[2]); 4990 + if (status) 4991 + break; 4992 + status = nfsd4_encode_bitmap4(xdr, gdd->gddr_dir_attributes[0], 4993 + gdd->gddr_dir_attributes[1], 4994 + gdd->gddr_dir_attributes[2]); 4995 + break; 4996 + default: 4997 + pr_warn("nfsd: bad gddrnf_status (%u)\n", gdd->gddrnf_status); 4998 + gdd->gddrnf_will_signal_deleg_avail = 0; 4999 + fallthrough; 5000 + case GDD4_UNAVAIL: 5001 + if (xdr_stream_encode_u32(xdr, GDD4_UNAVAIL) != XDR_UNIT) 5002 + break; 5003 + status = nfsd4_encode_bool(xdr, gdd->gddrnf_will_signal_deleg_avail); 5004 + break; 5005 + } 5006 + return status; 5007 + } 5008 + 4995 5009 #ifdef CONFIG_NFSD_PNFS 4996 5010 static __be32 4997 5011 nfsd4_encode_device_addr4(struct xdr_stream *xdr, ··· 5271 5199 if (nfserr != nfs_ok) 5272 5200 return nfserr; 5273 5201 /* osr_complete<1> */ 5274 - if (xdr_stream_encode_u32(xdr, 0) != XDR_UNIT) 5202 + if (os->completed) { 5203 + if (xdr_stream_encode_u32(xdr, 1) != XDR_UNIT) 5204 + return nfserr_resource; 5205 + if (xdr_stream_encode_be32(xdr, os->status) != XDR_UNIT) 5206 + return nfserr_resource; 5207 + } else if (xdr_stream_encode_u32(xdr, 0) != XDR_UNIT) 5275 5208 return nfserr_resource; 5276 5209 return nfs_ok; 5277 5210 } ··· 5656 5579 [OP_CREATE_SESSION] = nfsd4_encode_create_session, 5657 5580 [OP_DESTROY_SESSION] = nfsd4_encode_noop, 5658 5581 [OP_FREE_STATEID] = nfsd4_encode_noop, 5659 - [OP_GET_DIR_DELEGATION] = nfsd4_encode_noop, 5582 + [OP_GET_DIR_DELEGATION] = nfsd4_encode_get_dir_delegation, 5660 5583 #ifdef CONFIG_NFSD_PNFS 5661 5584 [OP_GETDEVICEINFO] = nfsd4_encode_getdeviceinfo, 5662 5585 [OP_GETDEVICELIST] = nfsd4_encode_noop,
+521 -5
fs/nfsd/nfsctl.c
··· 15 15 #include <linux/sunrpc/addr.h> 16 16 #include <linux/sunrpc/gss_api.h> 17 17 #include <linux/sunrpc/rpc_pipe_fs.h> 18 + #include <linux/sunrpc/svc.h> 18 19 #include <linux/module.h> 19 20 #include <linux/fsnotify.h> 20 21 ··· 49 48 NFSD_MaxBlkSize, 50 49 NFSD_MaxConnections, 51 50 NFSD_Filecache, 52 - #ifdef CONFIG_NFSD_V4 53 51 NFSD_Leasetime, 54 52 NFSD_Gracetime, 55 53 NFSD_RecoveryDir, 56 54 NFSD_V4EndGrace, 57 - #endif 58 55 NFSD_MaxReserved 59 56 }; 60 57 ··· 405 406 if (newthreads < 0) 406 407 return -EINVAL; 407 408 trace_nfsd_ctl_threads(net, newthreads); 408 - rv = nfsd_svc(newthreads, net, file->f_cred); 409 + mutex_lock(&nfsd_mutex); 410 + rv = nfsd_svc(newthreads, net, file->f_cred, NULL); 411 + mutex_unlock(&nfsd_mutex); 409 412 if (rv < 0) 410 413 return rv; 411 414 } else ··· 1361 1360 #ifdef CONFIG_NFSD_V4 1362 1361 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR}, 1363 1362 [NFSD_Gracetime] = {"nfsv4gracetime", &transaction_ops, S_IWUSR|S_IRUSR}, 1363 + #ifdef CONFIG_NFSD_LEGACY_CLIENT_TRACKING 1364 1364 [NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR}, 1365 + #endif 1365 1366 [NFSD_V4EndGrace] = {"v4_end_grace", &transaction_ops, S_IWUSR|S_IRUGO}, 1366 1367 #endif 1367 1368 /* last one */ {""} ··· 1655 1652 } 1656 1653 1657 1654 /** 1655 + * nfsd_nl_threads_set_doit - set the number of running threads 1656 + * @skb: reply buffer 1657 + * @info: netlink metadata and command arguments 1658 + * 1659 + * Return 0 on success or a negative errno. 1660 + */ 1661 + int nfsd_nl_threads_set_doit(struct sk_buff *skb, struct genl_info *info) 1662 + { 1663 + int nthreads = 0, count = 0, nrpools, ret = -EOPNOTSUPP, rem; 1664 + struct net *net = genl_info_net(info); 1665 + struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1666 + const struct nlattr *attr; 1667 + const char *scope = NULL; 1668 + 1669 + if (GENL_REQ_ATTR_CHECK(info, NFSD_A_SERVER_THREADS)) 1670 + return -EINVAL; 1671 + 1672 + /* count number of SERVER_THREADS values */ 1673 + nlmsg_for_each_attr(attr, info->nlhdr, GENL_HDRLEN, rem) { 1674 + if (nla_type(attr) == NFSD_A_SERVER_THREADS) 1675 + count++; 1676 + } 1677 + 1678 + mutex_lock(&nfsd_mutex); 1679 + 1680 + nrpools = nfsd_nrpools(net); 1681 + if (nrpools && count > nrpools) 1682 + count = nrpools; 1683 + 1684 + /* XXX: make this handle non-global pool-modes */ 1685 + if (count > 1) 1686 + goto out_unlock; 1687 + 1688 + nthreads = nla_get_u32(info->attrs[NFSD_A_SERVER_THREADS]); 1689 + if (info->attrs[NFSD_A_SERVER_GRACETIME] || 1690 + info->attrs[NFSD_A_SERVER_LEASETIME] || 1691 + info->attrs[NFSD_A_SERVER_SCOPE]) { 1692 + ret = -EBUSY; 1693 + if (nn->nfsd_serv && nn->nfsd_serv->sv_nrthreads) 1694 + goto out_unlock; 1695 + 1696 + ret = -EINVAL; 1697 + attr = info->attrs[NFSD_A_SERVER_GRACETIME]; 1698 + if (attr) { 1699 + u32 gracetime = nla_get_u32(attr); 1700 + 1701 + if (gracetime < 10 || gracetime > 3600) 1702 + goto out_unlock; 1703 + 1704 + nn->nfsd4_grace = gracetime; 1705 + } 1706 + 1707 + attr = info->attrs[NFSD_A_SERVER_LEASETIME]; 1708 + if (attr) { 1709 + u32 leasetime = nla_get_u32(attr); 1710 + 1711 + if (leasetime < 10 || leasetime > 3600) 1712 + goto out_unlock; 1713 + 1714 + nn->nfsd4_lease = leasetime; 1715 + } 1716 + 1717 + attr = info->attrs[NFSD_A_SERVER_SCOPE]; 1718 + if (attr) 1719 + scope = nla_data(attr); 1720 + } 1721 + 1722 + ret = nfsd_svc(nthreads, net, get_current_cred(), scope); 1723 + 1724 + out_unlock: 1725 + mutex_unlock(&nfsd_mutex); 1726 + 1727 + return ret == nthreads ? 0 : ret; 1728 + } 1729 + 1730 + /** 1731 + * nfsd_nl_threads_get_doit - get the number of running threads 1732 + * @skb: reply buffer 1733 + * @info: netlink metadata and command arguments 1734 + * 1735 + * Return 0 on success or a negative errno. 1736 + */ 1737 + int nfsd_nl_threads_get_doit(struct sk_buff *skb, struct genl_info *info) 1738 + { 1739 + struct net *net = genl_info_net(info); 1740 + struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1741 + void *hdr; 1742 + int err; 1743 + 1744 + skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); 1745 + if (!skb) 1746 + return -ENOMEM; 1747 + 1748 + hdr = genlmsg_iput(skb, info); 1749 + if (!hdr) { 1750 + err = -EMSGSIZE; 1751 + goto err_free_msg; 1752 + } 1753 + 1754 + mutex_lock(&nfsd_mutex); 1755 + 1756 + err = nla_put_u32(skb, NFSD_A_SERVER_GRACETIME, 1757 + nn->nfsd4_grace) || 1758 + nla_put_u32(skb, NFSD_A_SERVER_LEASETIME, 1759 + nn->nfsd4_lease) || 1760 + nla_put_string(skb, NFSD_A_SERVER_SCOPE, 1761 + nn->nfsd_name); 1762 + if (err) 1763 + goto err_unlock; 1764 + 1765 + if (nn->nfsd_serv) { 1766 + int i; 1767 + 1768 + for (i = 0; i < nfsd_nrpools(net); ++i) { 1769 + struct svc_pool *sp = &nn->nfsd_serv->sv_pools[i]; 1770 + 1771 + err = nla_put_u32(skb, NFSD_A_SERVER_THREADS, 1772 + atomic_read(&sp->sp_nrthreads)); 1773 + if (err) 1774 + goto err_unlock; 1775 + } 1776 + } else { 1777 + err = nla_put_u32(skb, NFSD_A_SERVER_THREADS, 0); 1778 + if (err) 1779 + goto err_unlock; 1780 + } 1781 + 1782 + mutex_unlock(&nfsd_mutex); 1783 + 1784 + genlmsg_end(skb, hdr); 1785 + 1786 + return genlmsg_reply(skb, info); 1787 + 1788 + err_unlock: 1789 + mutex_unlock(&nfsd_mutex); 1790 + err_free_msg: 1791 + nlmsg_free(skb); 1792 + 1793 + return err; 1794 + } 1795 + 1796 + /** 1797 + * nfsd_nl_version_set_doit - set the nfs enabled versions 1798 + * @skb: reply buffer 1799 + * @info: netlink metadata and command arguments 1800 + * 1801 + * Return 0 on success or a negative errno. 1802 + */ 1803 + int nfsd_nl_version_set_doit(struct sk_buff *skb, struct genl_info *info) 1804 + { 1805 + const struct nlattr *attr; 1806 + struct nfsd_net *nn; 1807 + int i, rem; 1808 + 1809 + if (GENL_REQ_ATTR_CHECK(info, NFSD_A_SERVER_PROTO_VERSION)) 1810 + return -EINVAL; 1811 + 1812 + mutex_lock(&nfsd_mutex); 1813 + 1814 + nn = net_generic(genl_info_net(info), nfsd_net_id); 1815 + if (nn->nfsd_serv) { 1816 + mutex_unlock(&nfsd_mutex); 1817 + return -EBUSY; 1818 + } 1819 + 1820 + /* clear current supported versions. */ 1821 + nfsd_vers(nn, 2, NFSD_CLEAR); 1822 + nfsd_vers(nn, 3, NFSD_CLEAR); 1823 + for (i = 0; i <= NFSD_SUPPORTED_MINOR_VERSION; i++) 1824 + nfsd_minorversion(nn, i, NFSD_CLEAR); 1825 + 1826 + nlmsg_for_each_attr(attr, info->nlhdr, GENL_HDRLEN, rem) { 1827 + struct nlattr *tb[NFSD_A_VERSION_MAX + 1]; 1828 + u32 major, minor = 0; 1829 + bool enabled; 1830 + 1831 + if (nla_type(attr) != NFSD_A_SERVER_PROTO_VERSION) 1832 + continue; 1833 + 1834 + if (nla_parse_nested(tb, NFSD_A_VERSION_MAX, attr, 1835 + nfsd_version_nl_policy, info->extack) < 0) 1836 + continue; 1837 + 1838 + if (!tb[NFSD_A_VERSION_MAJOR]) 1839 + continue; 1840 + 1841 + major = nla_get_u32(tb[NFSD_A_VERSION_MAJOR]); 1842 + if (tb[NFSD_A_VERSION_MINOR]) 1843 + minor = nla_get_u32(tb[NFSD_A_VERSION_MINOR]); 1844 + 1845 + enabled = nla_get_flag(tb[NFSD_A_VERSION_ENABLED]); 1846 + 1847 + switch (major) { 1848 + case 4: 1849 + nfsd_minorversion(nn, minor, enabled ? NFSD_SET : NFSD_CLEAR); 1850 + break; 1851 + case 3: 1852 + case 2: 1853 + if (!minor) 1854 + nfsd_vers(nn, major, enabled ? NFSD_SET : NFSD_CLEAR); 1855 + break; 1856 + default: 1857 + break; 1858 + } 1859 + } 1860 + 1861 + mutex_unlock(&nfsd_mutex); 1862 + 1863 + return 0; 1864 + } 1865 + 1866 + /** 1867 + * nfsd_nl_version_get_doit - get the enabled status for all supported nfs versions 1868 + * @skb: reply buffer 1869 + * @info: netlink metadata and command arguments 1870 + * 1871 + * Return 0 on success or a negative errno. 1872 + */ 1873 + int nfsd_nl_version_get_doit(struct sk_buff *skb, struct genl_info *info) 1874 + { 1875 + struct nfsd_net *nn; 1876 + int i, err; 1877 + void *hdr; 1878 + 1879 + skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); 1880 + if (!skb) 1881 + return -ENOMEM; 1882 + 1883 + hdr = genlmsg_iput(skb, info); 1884 + if (!hdr) { 1885 + err = -EMSGSIZE; 1886 + goto err_free_msg; 1887 + } 1888 + 1889 + mutex_lock(&nfsd_mutex); 1890 + nn = net_generic(genl_info_net(info), nfsd_net_id); 1891 + 1892 + for (i = 2; i <= 4; i++) { 1893 + int j; 1894 + 1895 + for (j = 0; j <= NFSD_SUPPORTED_MINOR_VERSION; j++) { 1896 + struct nlattr *attr; 1897 + 1898 + /* Don't record any versions the kernel doesn't have 1899 + * compiled in 1900 + */ 1901 + if (!nfsd_support_version(i)) 1902 + continue; 1903 + 1904 + /* NFSv{2,3} does not support minor numbers */ 1905 + if (i < 4 && j) 1906 + continue; 1907 + 1908 + attr = nla_nest_start(skb, 1909 + NFSD_A_SERVER_PROTO_VERSION); 1910 + if (!attr) { 1911 + err = -EINVAL; 1912 + goto err_nfsd_unlock; 1913 + } 1914 + 1915 + if (nla_put_u32(skb, NFSD_A_VERSION_MAJOR, i) || 1916 + nla_put_u32(skb, NFSD_A_VERSION_MINOR, j)) { 1917 + err = -EINVAL; 1918 + goto err_nfsd_unlock; 1919 + } 1920 + 1921 + /* Set the enabled flag if the version is enabled */ 1922 + if (nfsd_vers(nn, i, NFSD_TEST) && 1923 + (i < 4 || nfsd_minorversion(nn, j, NFSD_TEST)) && 1924 + nla_put_flag(skb, NFSD_A_VERSION_ENABLED)) { 1925 + err = -EINVAL; 1926 + goto err_nfsd_unlock; 1927 + } 1928 + 1929 + nla_nest_end(skb, attr); 1930 + } 1931 + } 1932 + 1933 + mutex_unlock(&nfsd_mutex); 1934 + genlmsg_end(skb, hdr); 1935 + 1936 + return genlmsg_reply(skb, info); 1937 + 1938 + err_nfsd_unlock: 1939 + mutex_unlock(&nfsd_mutex); 1940 + err_free_msg: 1941 + nlmsg_free(skb); 1942 + 1943 + return err; 1944 + } 1945 + 1946 + /** 1947 + * nfsd_nl_listener_set_doit - set the nfs running sockets 1948 + * @skb: reply buffer 1949 + * @info: netlink metadata and command arguments 1950 + * 1951 + * Return 0 on success or a negative errno. 1952 + */ 1953 + int nfsd_nl_listener_set_doit(struct sk_buff *skb, struct genl_info *info) 1954 + { 1955 + struct net *net = genl_info_net(info); 1956 + struct svc_xprt *xprt, *tmp; 1957 + const struct nlattr *attr; 1958 + struct svc_serv *serv; 1959 + LIST_HEAD(permsocks); 1960 + struct nfsd_net *nn; 1961 + int err, rem; 1962 + 1963 + mutex_lock(&nfsd_mutex); 1964 + 1965 + err = nfsd_create_serv(net); 1966 + if (err) { 1967 + mutex_unlock(&nfsd_mutex); 1968 + return err; 1969 + } 1970 + 1971 + nn = net_generic(net, nfsd_net_id); 1972 + serv = nn->nfsd_serv; 1973 + 1974 + spin_lock_bh(&serv->sv_lock); 1975 + 1976 + /* Move all of the old listener sockets to a temp list */ 1977 + list_splice_init(&serv->sv_permsocks, &permsocks); 1978 + 1979 + /* 1980 + * Walk the list of server_socks from userland and move any that match 1981 + * back to sv_permsocks 1982 + */ 1983 + nlmsg_for_each_attr(attr, info->nlhdr, GENL_HDRLEN, rem) { 1984 + struct nlattr *tb[NFSD_A_SOCK_MAX + 1]; 1985 + const char *xcl_name; 1986 + struct sockaddr *sa; 1987 + 1988 + if (nla_type(attr) != NFSD_A_SERVER_SOCK_ADDR) 1989 + continue; 1990 + 1991 + if (nla_parse_nested(tb, NFSD_A_SOCK_MAX, attr, 1992 + nfsd_sock_nl_policy, info->extack) < 0) 1993 + continue; 1994 + 1995 + if (!tb[NFSD_A_SOCK_ADDR] || !tb[NFSD_A_SOCK_TRANSPORT_NAME]) 1996 + continue; 1997 + 1998 + if (nla_len(tb[NFSD_A_SOCK_ADDR]) < sizeof(*sa)) 1999 + continue; 2000 + 2001 + xcl_name = nla_data(tb[NFSD_A_SOCK_TRANSPORT_NAME]); 2002 + sa = nla_data(tb[NFSD_A_SOCK_ADDR]); 2003 + 2004 + /* Put back any matching sockets */ 2005 + list_for_each_entry_safe(xprt, tmp, &permsocks, xpt_list) { 2006 + /* This shouldn't be possible */ 2007 + if (WARN_ON_ONCE(xprt->xpt_net != net)) { 2008 + list_move(&xprt->xpt_list, &serv->sv_permsocks); 2009 + continue; 2010 + } 2011 + 2012 + /* If everything matches, put it back */ 2013 + if (!strcmp(xprt->xpt_class->xcl_name, xcl_name) && 2014 + rpc_cmp_addr_port(sa, (struct sockaddr *)&xprt->xpt_local)) { 2015 + list_move(&xprt->xpt_list, &serv->sv_permsocks); 2016 + break; 2017 + } 2018 + } 2019 + } 2020 + 2021 + /* For now, no removing old sockets while server is running */ 2022 + if (serv->sv_nrthreads && !list_empty(&permsocks)) { 2023 + list_splice_init(&permsocks, &serv->sv_permsocks); 2024 + spin_unlock_bh(&serv->sv_lock); 2025 + err = -EBUSY; 2026 + goto out_unlock_mtx; 2027 + } 2028 + 2029 + /* Close the remaining sockets on the permsocks list */ 2030 + while (!list_empty(&permsocks)) { 2031 + xprt = list_first_entry(&permsocks, struct svc_xprt, xpt_list); 2032 + list_move(&xprt->xpt_list, &serv->sv_permsocks); 2033 + 2034 + /* 2035 + * Newly-created sockets are born with the BUSY bit set. Clear 2036 + * it if there are no threads, since nothing can pick it up 2037 + * in that case. 2038 + */ 2039 + if (!serv->sv_nrthreads) 2040 + clear_bit(XPT_BUSY, &xprt->xpt_flags); 2041 + 2042 + set_bit(XPT_CLOSE, &xprt->xpt_flags); 2043 + spin_unlock_bh(&serv->sv_lock); 2044 + svc_xprt_close(xprt); 2045 + spin_lock_bh(&serv->sv_lock); 2046 + } 2047 + 2048 + spin_unlock_bh(&serv->sv_lock); 2049 + 2050 + /* walk list of addrs again, open any that still don't exist */ 2051 + nlmsg_for_each_attr(attr, info->nlhdr, GENL_HDRLEN, rem) { 2052 + struct nlattr *tb[NFSD_A_SOCK_MAX + 1]; 2053 + const char *xcl_name; 2054 + struct sockaddr *sa; 2055 + int ret; 2056 + 2057 + if (nla_type(attr) != NFSD_A_SERVER_SOCK_ADDR) 2058 + continue; 2059 + 2060 + if (nla_parse_nested(tb, NFSD_A_SOCK_MAX, attr, 2061 + nfsd_sock_nl_policy, info->extack) < 0) 2062 + continue; 2063 + 2064 + if (!tb[NFSD_A_SOCK_ADDR] || !tb[NFSD_A_SOCK_TRANSPORT_NAME]) 2065 + continue; 2066 + 2067 + if (nla_len(tb[NFSD_A_SOCK_ADDR]) < sizeof(*sa)) 2068 + continue; 2069 + 2070 + xcl_name = nla_data(tb[NFSD_A_SOCK_TRANSPORT_NAME]); 2071 + sa = nla_data(tb[NFSD_A_SOCK_ADDR]); 2072 + 2073 + xprt = svc_find_listener(serv, xcl_name, net, sa); 2074 + if (xprt) { 2075 + svc_xprt_put(xprt); 2076 + continue; 2077 + } 2078 + 2079 + ret = svc_xprt_create_from_sa(serv, xcl_name, net, sa, 2080 + SVC_SOCK_ANONYMOUS, 2081 + get_current_cred()); 2082 + /* always save the latest error */ 2083 + if (ret < 0) 2084 + err = ret; 2085 + } 2086 + 2087 + if (!serv->sv_nrthreads && list_empty(&nn->nfsd_serv->sv_permsocks)) 2088 + nfsd_destroy_serv(net); 2089 + 2090 + out_unlock_mtx: 2091 + mutex_unlock(&nfsd_mutex); 2092 + 2093 + return err; 2094 + } 2095 + 2096 + /** 2097 + * nfsd_nl_listener_get_doit - get the nfs running listeners 2098 + * @skb: reply buffer 2099 + * @info: netlink metadata and command arguments 2100 + * 2101 + * Return 0 on success or a negative errno. 2102 + */ 2103 + int nfsd_nl_listener_get_doit(struct sk_buff *skb, struct genl_info *info) 2104 + { 2105 + struct svc_xprt *xprt; 2106 + struct svc_serv *serv; 2107 + struct nfsd_net *nn; 2108 + void *hdr; 2109 + int err; 2110 + 2111 + skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); 2112 + if (!skb) 2113 + return -ENOMEM; 2114 + 2115 + hdr = genlmsg_iput(skb, info); 2116 + if (!hdr) { 2117 + err = -EMSGSIZE; 2118 + goto err_free_msg; 2119 + } 2120 + 2121 + mutex_lock(&nfsd_mutex); 2122 + nn = net_generic(genl_info_net(info), nfsd_net_id); 2123 + 2124 + /* no nfs server? Just send empty socket list */ 2125 + if (!nn->nfsd_serv) 2126 + goto out_unlock_mtx; 2127 + 2128 + serv = nn->nfsd_serv; 2129 + spin_lock_bh(&serv->sv_lock); 2130 + list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list) { 2131 + struct nlattr *attr; 2132 + 2133 + attr = nla_nest_start(skb, NFSD_A_SERVER_SOCK_ADDR); 2134 + if (!attr) { 2135 + err = -EINVAL; 2136 + goto err_serv_unlock; 2137 + } 2138 + 2139 + if (nla_put_string(skb, NFSD_A_SOCK_TRANSPORT_NAME, 2140 + xprt->xpt_class->xcl_name) || 2141 + nla_put(skb, NFSD_A_SOCK_ADDR, 2142 + sizeof(struct sockaddr_storage), 2143 + &xprt->xpt_local)) { 2144 + err = -EINVAL; 2145 + goto err_serv_unlock; 2146 + } 2147 + 2148 + nla_nest_end(skb, attr); 2149 + } 2150 + spin_unlock_bh(&serv->sv_lock); 2151 + out_unlock_mtx: 2152 + mutex_unlock(&nfsd_mutex); 2153 + genlmsg_end(skb, hdr); 2154 + 2155 + return genlmsg_reply(skb, info); 2156 + 2157 + err_serv_unlock: 2158 + spin_unlock_bh(&serv->sv_lock); 2159 + mutex_unlock(&nfsd_mutex); 2160 + err_free_msg: 2161 + nlmsg_free(skb); 2162 + 2163 + return err; 2164 + } 2165 + 2166 + /** 1658 2167 * nfsd_net_init - Prepare the nfsd_net portion of a new net namespace 1659 2168 * @net: a freshly-created network namespace 1660 2169 * ··· 2187 1672 retval = nfsd_idmap_init(net); 2188 1673 if (retval) 2189 1674 goto out_idmap_error; 2190 - retval = nfsd_stat_counters_init(nn); 1675 + retval = percpu_counter_init_many(nn->counter, 0, GFP_KERNEL, 1676 + NFSD_STATS_COUNTERS_NUM); 2191 1677 if (retval) 2192 1678 goto out_repcache_error; 2193 1679 memset(&nn->nfsd_svcstats, 0, sizeof(nn->nfsd_svcstats)); ··· 2220 1704 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 2221 1705 2222 1706 nfsd_proc_stat_shutdown(net); 2223 - nfsd_stat_counters_destroy(nn); 1707 + percpu_counter_destroy_many(nn->counter, NFSD_STATS_COUNTERS_NUM); 2224 1708 nfsd_idmap_shutdown(net); 2225 1709 nfsd_export_shutdown(net); 2226 1710 nfsd_netns_free_versions(nn);
+1 -2
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); 106 + int nfsd_svc(int nrservs, struct net *net, const struct cred *cred, const char *scope); 107 107 int nfsd_dispatch(struct svc_rqst *rqstp); 108 108 109 109 int nfsd_nrthreads(struct net *); ··· 230 230 #define nfserr_nospc cpu_to_be32(NFSERR_NOSPC) 231 231 #define nfserr_rofs cpu_to_be32(NFSERR_ROFS) 232 232 #define nfserr_mlink cpu_to_be32(NFSERR_MLINK) 233 - #define nfserr_opnotsupp cpu_to_be32(NFSERR_OPNOTSUPP) 234 233 #define nfserr_nametoolong cpu_to_be32(NFSERR_NAMETOOLONG) 235 234 #define nfserr_notempty cpu_to_be32(NFSERR_NOTEMPTY) 236 235 #define nfserr_dquot cpu_to_be32(NFSERR_DQUOT)
+2 -2
fs/nfsd/nfsfh.c
··· 573 573 _fh_update(fhp, exp, dentry); 574 574 if (fhp->fh_handle.fh_fileid_type == FILEID_INVALID) { 575 575 fh_put(fhp); 576 - return nfserr_opnotsupp; 576 + return nfserr_stale; 577 577 } 578 578 579 579 return 0; ··· 599 599 600 600 _fh_update(fhp, fhp->fh_export, dentry); 601 601 if (fhp->fh_handle.fh_fileid_type == FILEID_INVALID) 602 - return nfserr_opnotsupp; 602 + return nfserr_stale; 603 603 return 0; 604 604 out_bad: 605 605 printk(KERN_ERR "fh_update: fh not verified!\n");
+5 -6
fs/nfsd/nfssvc.c
··· 133 133 .pg_rpcbind_set = nfsd_rpcbind_set, 134 134 }; 135 135 136 - static bool 137 - nfsd_support_version(int vers) 136 + bool nfsd_support_version(int vers) 138 137 { 139 138 if (vers >= NFSD_MINVERS && vers < NFSD_NRVERS) 140 139 return nfsd_version[vers] != NULL; ··· 768 769 * this is the first time nrservs is nonzero. 769 770 */ 770 771 int 771 - nfsd_svc(int nrservs, struct net *net, const struct cred *cred) 772 + nfsd_svc(int nrservs, struct net *net, const struct cred *cred, const char *scope) 772 773 { 773 774 int error; 774 775 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 775 776 struct svc_serv *serv; 776 777 777 - mutex_lock(&nfsd_mutex); 778 + lockdep_assert_held(&nfsd_mutex); 779 + 778 780 dprintk("nfsd: creating service\n"); 779 781 780 782 nrservs = max(nrservs, 0); ··· 785 785 if (nrservs == 0 && nn->nfsd_serv == NULL) 786 786 goto out; 787 787 788 - strscpy(nn->nfsd_name, utsname()->nodename, 788 + strscpy(nn->nfsd_name, scope ? scope : utsname()->nodename, 789 789 sizeof(nn->nfsd_name)); 790 790 791 791 error = nfsd_create_serv(net); ··· 804 804 if (serv->sv_nrthreads == 0) 805 805 nfsd_destroy_serv(net); 806 806 out: 807 - mutex_unlock(&nfsd_mutex); 808 807 return error; 809 808 } 810 809
+3 -3
fs/nfsd/state.h
··· 408 408 1 << NFSD4_CLIENT_CB_KILL) 409 409 #define NFSD4_CLIENT_CB_RECALL_ANY (6) 410 410 unsigned long cl_flags; 411 + 412 + struct workqueue_struct *cl_callback_wq; 411 413 const struct cred *cl_cb_cred; 412 414 struct rpc_clnt *cl_cb_client; 413 415 u32 cl_cb_ident; ··· 488 486 unsigned int rp_buflen; 489 487 char *rp_buf; 490 488 struct knfsd_fh rp_openfh; 491 - struct mutex rp_mutex; 489 + atomic_t rp_locked; 492 490 char rp_ibuf[NFSD4_REPLAY_ISIZE]; 493 491 }; 494 492 ··· 737 735 extern void nfsd4_init_cb(struct nfsd4_callback *cb, struct nfs4_client *clp, 738 736 const struct nfsd4_callback_ops *ops, enum nfsd4_cb_op op); 739 737 extern bool nfsd4_run_cb(struct nfsd4_callback *cb); 740 - extern int nfsd4_create_callback_queue(void); 741 - extern void nfsd4_destroy_callback_queue(void); 742 738 extern void nfsd4_shutdown_callback(struct nfs4_client *); 743 739 extern void nfsd4_shutdown_copy(struct nfs4_client *clp); 744 740 extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(struct xdr_netobj name,
-42
fs/nfsd/stats.c
··· 73 73 74 74 DEFINE_PROC_SHOW_ATTRIBUTE(nfsd); 75 75 76 - int nfsd_percpu_counters_init(struct percpu_counter *counters, int num) 77 - { 78 - int i, err = 0; 79 - 80 - for (i = 0; !err && i < num; i++) 81 - err = percpu_counter_init(&counters[i], 0, GFP_KERNEL); 82 - 83 - if (!err) 84 - return 0; 85 - 86 - for (; i > 0; i--) 87 - percpu_counter_destroy(&counters[i-1]); 88 - 89 - return err; 90 - } 91 - 92 - void nfsd_percpu_counters_reset(struct percpu_counter counters[], int num) 93 - { 94 - int i; 95 - 96 - for (i = 0; i < num; i++) 97 - percpu_counter_set(&counters[i], 0); 98 - } 99 - 100 - void nfsd_percpu_counters_destroy(struct percpu_counter counters[], int num) 101 - { 102 - int i; 103 - 104 - for (i = 0; i < num; i++) 105 - percpu_counter_destroy(&counters[i]); 106 - } 107 - 108 - int nfsd_stat_counters_init(struct nfsd_net *nn) 109 - { 110 - return nfsd_percpu_counters_init(nn->counter, NFSD_STATS_COUNTERS_NUM); 111 - } 112 - 113 - void nfsd_stat_counters_destroy(struct nfsd_net *nn) 114 - { 115 - nfsd_percpu_counters_destroy(nn->counter, NFSD_STATS_COUNTERS_NUM); 116 - } 117 - 118 76 void nfsd_proc_stat_init(struct net *net) 119 77 { 120 78 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
-5
fs/nfsd/stats.h
··· 10 10 #include <uapi/linux/nfsd/stats.h> 11 11 #include <linux/percpu_counter.h> 12 12 13 - int nfsd_percpu_counters_init(struct percpu_counter *counters, int num); 14 - void nfsd_percpu_counters_reset(struct percpu_counter *counters, int num); 15 - void nfsd_percpu_counters_destroy(struct percpu_counter *counters, int num); 16 - int nfsd_stat_counters_init(struct nfsd_net *nn); 17 - void nfsd_stat_counters_destroy(struct nfsd_net *nn); 18 13 void nfsd_proc_stat_init(struct net *net); 19 14 void nfsd_proc_stat_shutdown(struct net *net); 20 15
+97 -3
fs/nfsd/trace.h
··· 749 749 ) 750 750 ); 751 751 752 + DECLARE_EVENT_CLASS(nfsd_cs_slot_class, 753 + TP_PROTO( 754 + const struct nfs4_client *clp, 755 + const struct nfsd4_create_session *cs 756 + ), 757 + TP_ARGS(clp, cs), 758 + TP_STRUCT__entry( 759 + __field(u32, seqid) 760 + __field(u32, slot_seqid) 761 + __field(u32, cl_boot) 762 + __field(u32, cl_id) 763 + __sockaddr(addr, clp->cl_cb_conn.cb_addrlen) 764 + ), 765 + TP_fast_assign( 766 + const struct nfsd4_clid_slot *slot = &clp->cl_cs_slot; 767 + 768 + __entry->cl_boot = clp->cl_clientid.cl_boot; 769 + __entry->cl_id = clp->cl_clientid.cl_id; 770 + __assign_sockaddr(addr, &clp->cl_cb_conn.cb_addr, 771 + clp->cl_cb_conn.cb_addrlen); 772 + __entry->seqid = cs->seqid; 773 + __entry->slot_seqid = slot->sl_seqid; 774 + ), 775 + TP_printk("addr=%pISpc client %08x:%08x seqid=%u slot_seqid=%u", 776 + __get_sockaddr(addr), __entry->cl_boot, __entry->cl_id, 777 + __entry->seqid, __entry->slot_seqid 778 + ) 779 + ); 780 + 781 + #define DEFINE_CS_SLOT_EVENT(name) \ 782 + DEFINE_EVENT(nfsd_cs_slot_class, nfsd_##name, \ 783 + TP_PROTO( \ 784 + const struct nfs4_client *clp, \ 785 + const struct nfsd4_create_session *cs \ 786 + ), \ 787 + TP_ARGS(clp, cs)) 788 + 789 + DEFINE_CS_SLOT_EVENT(slot_seqid_conf); 790 + DEFINE_CS_SLOT_EVENT(slot_seqid_unconf); 791 + 792 + TRACE_EVENT(nfsd_slot_seqid_sequence, 793 + TP_PROTO( 794 + const struct nfs4_client *clp, 795 + const struct nfsd4_sequence *seq, 796 + const struct nfsd4_slot *slot 797 + ), 798 + TP_ARGS(clp, seq, slot), 799 + TP_STRUCT__entry( 800 + __field(u32, seqid) 801 + __field(u32, slot_seqid) 802 + __field(u32, cl_boot) 803 + __field(u32, cl_id) 804 + __sockaddr(addr, clp->cl_cb_conn.cb_addrlen) 805 + __field(bool, in_use) 806 + ), 807 + TP_fast_assign( 808 + __entry->cl_boot = clp->cl_clientid.cl_boot; 809 + __entry->cl_id = clp->cl_clientid.cl_id; 810 + __assign_sockaddr(addr, &clp->cl_cb_conn.cb_addr, 811 + clp->cl_cb_conn.cb_addrlen); 812 + __entry->seqid = seq->seqid; 813 + __entry->slot_seqid = slot->sl_seqid; 814 + ), 815 + TP_printk("addr=%pISpc client %08x:%08x seqid=%u slot_seqid=%u (%sin use)", 816 + __get_sockaddr(addr), __entry->cl_boot, __entry->cl_id, 817 + __entry->seqid, __entry->slot_seqid, 818 + __entry->in_use ? "" : "not " 819 + ) 820 + ); 821 + 752 822 DECLARE_EVENT_CLASS(nfsd_clientid_class, 753 823 TP_PROTO(const clientid_t *clid), 754 824 TP_ARGS(clid), ··· 847 777 DEFINE_CLIENTID_EVENT(purged); 848 778 DEFINE_CLIENTID_EVENT(renew); 849 779 DEFINE_CLIENTID_EVENT(stale); 780 + 781 + TRACE_EVENT(nfsd_mark_client_expired, 782 + TP_PROTO( 783 + const struct nfs4_client *clp, 784 + int cl_rpc_users 785 + ), 786 + TP_ARGS(clp, cl_rpc_users), 787 + TP_STRUCT__entry( 788 + __field(int, cl_rpc_users) 789 + __field(u32, cl_boot) 790 + __field(u32, cl_id) 791 + __sockaddr(addr, clp->cl_cb_conn.cb_addrlen) 792 + ), 793 + TP_fast_assign( 794 + __entry->cl_rpc_users = cl_rpc_users; 795 + __entry->cl_boot = clp->cl_clientid.cl_boot; 796 + __entry->cl_id = clp->cl_clientid.cl_id; 797 + __assign_sockaddr(addr, &clp->cl_cb_conn.cb_addr, 798 + clp->cl_cb_conn.cb_addrlen) 799 + ), 800 + TP_printk("addr=%pISpc client %08x:%08x cl_rpc_users=%d", 801 + __get_sockaddr(addr), __entry->cl_boot, __entry->cl_id, 802 + __entry->cl_rpc_users) 803 + ); 850 804 851 805 DECLARE_EVENT_CLASS(nfsd_net_class, 852 806 TP_PROTO(const struct nfsd_net *nn), ··· 1628 1534 __entry->seq_status = cb->cb_seq_status; 1629 1535 ), 1630 1536 TP_printk(SUNRPC_TRACE_TASK_SPECIFIER 1631 - " sessionid=%08x:%08x:%08x:%08x tk_status=%d seq_status=%d\n", 1537 + " sessionid=%08x:%08x:%08x:%08x tk_status=%d seq_status=%d", 1632 1538 __entry->task_id, __entry->client_id, 1633 1539 __entry->cl_boot, __entry->cl_id, 1634 1540 __entry->seqno, __entry->reserved, ··· 1667 1573 __entry->slot_seqno = session->se_cb_seq_nr; 1668 1574 ), 1669 1575 TP_printk(SUNRPC_TRACE_TASK_SPECIFIER 1670 - " sessionid=%08x:%08x:%08x:%08x new slot seqno=%u\n", 1576 + " sessionid=%08x:%08x:%08x:%08x new slot seqno=%u", 1671 1577 __entry->task_id, __entry->client_id, 1672 1578 __entry->cl_boot, __entry->cl_id, 1673 1579 __entry->seqno, __entry->reserved, ··· 2072 1978 __entry->time = time; 2073 1979 __assign_str(name, name); 2074 1980 ), 2075 - TP_printk("file=%s time=%d\n", 1981 + TP_printk("file=%s time=%d", 2076 1982 __get_str(name), __entry->time 2077 1983 ) 2078 1984 );
+1 -1
fs/nfsd/vfs.c
··· 1422 1422 * Callers expect new file metadata to be committed even 1423 1423 * if the attributes have not changed. 1424 1424 */ 1425 - if (iap->ia_valid) 1425 + if (nfsd_attrs_valid(attrs)) 1426 1426 status = nfsd_setattr(rqstp, resfhp, attrs, NULL); 1427 1427 else 1428 1428 status = nfserrno(commit_metadata(resfhp));
+8
fs/nfsd/vfs.h
··· 60 60 posix_acl_release(attrs->na_dpacl); 61 61 } 62 62 63 + static inline bool nfsd_attrs_valid(struct nfsd_attrs *attrs) 64 + { 65 + struct iattr *iap = attrs->na_iattr; 66 + 67 + return (iap->ia_valid || (attrs->na_seclabel && 68 + attrs->na_seclabel->len)); 69 + } 70 + 63 71 __be32 nfserrno (int errno); 64 72 int nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp, 65 73 struct svc_export **expp);
+23 -1
fs/nfsd/xdr4.h
··· 518 518 stateid_t fr_stateid; /* request */ 519 519 }; 520 520 521 + struct nfsd4_get_dir_delegation { 522 + /* request */ 523 + u32 gdda_signal_deleg_avail; 524 + u32 gdda_notification_types[1]; 525 + struct timespec64 gdda_child_attr_delay; 526 + struct timespec64 gdda_dir_attr_delay; 527 + u32 gdda_child_attributes[3]; 528 + u32 gdda_dir_attributes[3]; 529 + /* response */ 530 + u32 gddrnf_status; 531 + nfs4_verifier gddr_cookieverf; 532 + stateid_t gddr_stateid; 533 + u32 gddr_notification[1]; 534 + u32 gddr_child_attributes[3]; 535 + u32 gddr_dir_attributes[3]; 536 + bool gddrnf_will_signal_deleg_avail; 537 + }; 538 + 521 539 /* also used for NVERIFY */ 522 540 struct nfsd4_verify { 523 541 u32 ve_bmval[3]; /* request */ ··· 692 674 #define NFSD4_COPY_F_INTRA (1) 693 675 #define NFSD4_COPY_F_SYNCHRONOUS (2) 694 676 #define NFSD4_COPY_F_COMMITTED (3) 677 + #define NFSD4_COPY_F_COMPLETED (4) 695 678 696 679 /* response */ 680 + __be32 nfserr; 697 681 struct nfsd42_write_res cp_res; 698 682 struct knfsd_fh fh; 699 683 ··· 755 735 756 736 /* response */ 757 737 u64 count; 758 - u32 status; 738 + __be32 status; 739 + bool completed; 759 740 }; 760 741 761 742 struct nfsd4_copy_notify { ··· 818 797 struct nfsd4_reclaim_complete reclaim_complete; 819 798 struct nfsd4_test_stateid test_stateid; 820 799 struct nfsd4_free_stateid free_stateid; 800 + struct nfsd4_get_dir_delegation get_dir_delegation; 821 801 struct nfsd4_getdeviceinfo getdeviceinfo; 822 802 struct nfsd4_layoutget layoutget; 823 803 struct nfsd4_layoutcommit layoutcommit;
+6
include/linux/nfs4.h
··· 701 701 SP4_SSV = 2 702 702 }; 703 703 704 + /* GET_DIR_DELEGATION non-fatal status codes */ 705 + enum gddrnf4_status { 706 + GDD4_OK = 0, 707 + GDD4_UNAVAIL = 1 708 + }; 709 + 704 710 enum pnfs_layouttype { 705 711 LAYOUT_NFSV4_1_FILES = 1, 706 712 LAYOUT_OSD2_OBJECTS = 2,
+5
include/linux/sunrpc/svc_xprt.h
··· 135 135 void svc_unreg_xprt_class(struct svc_xprt_class *); 136 136 void svc_xprt_init(struct net *, struct svc_xprt_class *, struct svc_xprt *, 137 137 struct svc_serv *); 138 + int svc_xprt_create_from_sa(struct svc_serv *serv, const char *xprt_name, 139 + struct net *net, struct sockaddr *sap, 140 + int flags, const struct cred *cred); 138 141 int svc_xprt_create(struct svc_serv *serv, const char *xprt_name, 139 142 struct net *net, const int family, 140 143 const unsigned short port, int flags, ··· 150 147 void svc_xprt_close(struct svc_xprt *xprt); 151 148 int svc_port_is_privileged(struct sockaddr *sin); 152 149 int svc_print_xprts(char *buf, int maxlen); 150 + struct svc_xprt *svc_find_listener(struct svc_serv *serv, const char *xcl_name, 151 + struct net *net, const struct sockaddr *sa); 153 152 struct svc_xprt *svc_find_xprt(struct svc_serv *serv, const char *xcl_name, 154 153 struct net *net, const sa_family_t af, 155 154 const unsigned short port);
-2
include/trace/misc/nfs.h
··· 28 28 TRACE_DEFINE_ENUM(NFSERR_NOSPC); 29 29 TRACE_DEFINE_ENUM(NFSERR_ROFS); 30 30 TRACE_DEFINE_ENUM(NFSERR_MLINK); 31 - TRACE_DEFINE_ENUM(NFSERR_OPNOTSUPP); 32 31 TRACE_DEFINE_ENUM(NFSERR_NAMETOOLONG); 33 32 TRACE_DEFINE_ENUM(NFSERR_NOTEMPTY); 34 33 TRACE_DEFINE_ENUM(NFSERR_DQUOT); ··· 63 64 { NFSERR_NOSPC, "NOSPC" }, \ 64 65 { NFSERR_ROFS, "ROFS" }, \ 65 66 { NFSERR_MLINK, "MLINK" }, \ 66 - { NFSERR_OPNOTSUPP, "OPNOTSUPP" }, \ 67 67 { NFSERR_NAMETOOLONG, "NAMETOOLONG" }, \ 68 68 { NFSERR_NOTEMPTY, "NOTEMPTY" }, \ 69 69 { NFSERR_DQUOT, "DQUOT" }, \
-1
include/uapi/linux/nfs.h
··· 61 61 NFSERR_NOSPC = 28, /* v2 v3 v4 */ 62 62 NFSERR_ROFS = 30, /* v2 v3 v4 */ 63 63 NFSERR_MLINK = 31, /* v3 v4 */ 64 - NFSERR_OPNOTSUPP = 45, /* v2 v3 */ 65 64 NFSERR_NAMETOOLONG = 63, /* v2 v3 v4 */ 66 65 NFSERR_NOTEMPTY = 66, /* v2 v3 v4 */ 67 66 NFSERR_DQUOT = 69, /* v2 v3 v4 */
+47
include/uapi/linux/nfsd_netlink.h
··· 30 30 }; 31 31 32 32 enum { 33 + NFSD_A_SERVER_THREADS = 1, 34 + NFSD_A_SERVER_GRACETIME, 35 + NFSD_A_SERVER_LEASETIME, 36 + NFSD_A_SERVER_SCOPE, 37 + 38 + __NFSD_A_SERVER_MAX, 39 + NFSD_A_SERVER_MAX = (__NFSD_A_SERVER_MAX - 1) 40 + }; 41 + 42 + enum { 43 + NFSD_A_VERSION_MAJOR = 1, 44 + NFSD_A_VERSION_MINOR, 45 + NFSD_A_VERSION_ENABLED, 46 + 47 + __NFSD_A_VERSION_MAX, 48 + NFSD_A_VERSION_MAX = (__NFSD_A_VERSION_MAX - 1) 49 + }; 50 + 51 + enum { 52 + NFSD_A_SERVER_PROTO_VERSION = 1, 53 + 54 + __NFSD_A_SERVER_PROTO_MAX, 55 + NFSD_A_SERVER_PROTO_MAX = (__NFSD_A_SERVER_PROTO_MAX - 1) 56 + }; 57 + 58 + enum { 59 + NFSD_A_SOCK_ADDR = 1, 60 + NFSD_A_SOCK_TRANSPORT_NAME, 61 + 62 + __NFSD_A_SOCK_MAX, 63 + NFSD_A_SOCK_MAX = (__NFSD_A_SOCK_MAX - 1) 64 + }; 65 + 66 + enum { 67 + NFSD_A_SERVER_SOCK_ADDR = 1, 68 + 69 + __NFSD_A_SERVER_SOCK_MAX, 70 + NFSD_A_SERVER_SOCK_MAX = (__NFSD_A_SERVER_SOCK_MAX - 1) 71 + }; 72 + 73 + enum { 33 74 NFSD_CMD_RPC_STATUS_GET = 1, 75 + NFSD_CMD_THREADS_SET, 76 + NFSD_CMD_THREADS_GET, 77 + NFSD_CMD_VERSION_SET, 78 + NFSD_CMD_VERSION_GET, 79 + NFSD_CMD_LISTENER_SET, 80 + NFSD_CMD_LISTENER_GET, 34 81 35 82 __NFSD_CMD_MAX, 36 83 NFSD_CMD_MAX = (__NFSD_CMD_MAX - 1)
+2 -8
net/sunrpc/auth_gss/svcauth_gss.c
··· 1033 1033 1034 1034 static void gss_free_in_token_pages(struct gssp_in_token *in_token) 1035 1035 { 1036 - u32 inlen; 1037 1036 int i; 1038 1037 1039 1038 i = 0; 1040 - inlen = in_token->page_len; 1041 - while (inlen) { 1042 - if (in_token->pages[i]) 1043 - put_page(in_token->pages[i]); 1044 - inlen -= inlen > PAGE_SIZE ? PAGE_SIZE : inlen; 1045 - } 1046 - 1039 + while (in_token->pages[i]) 1040 + put_page(in_token->pages[i++]); 1047 1041 kfree(in_token->pages); 1048 1042 in_token->pages = NULL; 1049 1043 }
-2
net/sunrpc/svc.c
··· 1265 1265 if (rqstp->rq_proc >= versp->vs_nproc) 1266 1266 goto err_bad_proc; 1267 1267 rqstp->rq_procinfo = procp = &versp->vs_proc[rqstp->rq_proc]; 1268 - if (!procp) 1269 - goto err_bad_proc; 1270 1268 1271 1269 /* Initialize storage for argp and resp */ 1272 1270 memset(rqstp->rq_argp, 0, procp->pc_argzero);
+109 -59
net/sunrpc/svc_xprt.c
··· 46 46 47 47 /* SMP locking strategy: 48 48 * 49 - * svc_pool->sp_lock protects most of the fields of that pool. 50 49 * svc_serv->sv_lock protects sv_tempsocks, sv_permsocks, sv_tmpcnt. 51 50 * when both need to be taken (rare), svc_serv->sv_lock is first. 52 51 * The "service mutex" protects svc_serv->sv_nrthread. ··· 210 211 } 211 212 EXPORT_SYMBOL_GPL(svc_xprt_init); 212 213 213 - static struct svc_xprt *__svc_xpo_create(struct svc_xprt_class *xcl, 214 - struct svc_serv *serv, 215 - struct net *net, 216 - const int family, 217 - const unsigned short port, 218 - int flags) 219 - { 220 - struct sockaddr_in sin = { 221 - .sin_family = AF_INET, 222 - .sin_addr.s_addr = htonl(INADDR_ANY), 223 - .sin_port = htons(port), 224 - }; 225 - #if IS_ENABLED(CONFIG_IPV6) 226 - struct sockaddr_in6 sin6 = { 227 - .sin6_family = AF_INET6, 228 - .sin6_addr = IN6ADDR_ANY_INIT, 229 - .sin6_port = htons(port), 230 - }; 231 - #endif 232 - struct svc_xprt *xprt; 233 - struct sockaddr *sap; 234 - size_t len; 235 - 236 - switch (family) { 237 - case PF_INET: 238 - sap = (struct sockaddr *)&sin; 239 - len = sizeof(sin); 240 - break; 241 - #if IS_ENABLED(CONFIG_IPV6) 242 - case PF_INET6: 243 - sap = (struct sockaddr *)&sin6; 244 - len = sizeof(sin6); 245 - break; 246 - #endif 247 - default: 248 - return ERR_PTR(-EAFNOSUPPORT); 249 - } 250 - 251 - xprt = xcl->xcl_ops->xpo_create(serv, net, sap, len, flags); 252 - if (IS_ERR(xprt)) 253 - trace_svc_xprt_create_err(serv->sv_program->pg_name, 254 - xcl->xcl_name, sap, len, xprt); 255 - return xprt; 256 - } 257 - 258 214 /** 259 215 * svc_xprt_received - start next receiver thread 260 216 * @xprt: controlling transport ··· 248 294 } 249 295 250 296 static int _svc_xprt_create(struct svc_serv *serv, const char *xprt_name, 251 - struct net *net, const int family, 252 - const unsigned short port, int flags, 253 - const struct cred *cred) 297 + struct net *net, struct sockaddr *sap, 298 + size_t len, int flags, const struct cred *cred) 254 299 { 255 300 struct svc_xprt_class *xcl; 256 301 ··· 265 312 goto err; 266 313 267 314 spin_unlock(&svc_xprt_class_lock); 268 - newxprt = __svc_xpo_create(xcl, serv, net, family, port, flags); 315 + newxprt = xcl->xcl_ops->xpo_create(serv, net, sap, len, flags); 269 316 if (IS_ERR(newxprt)) { 317 + trace_svc_xprt_create_err(serv->sv_program->pg_name, 318 + xcl->xcl_name, sap, len, 319 + newxprt); 270 320 module_put(xcl->xcl_owner); 271 321 return PTR_ERR(newxprt); 272 322 } ··· 286 330 } 287 331 288 332 /** 333 + * svc_xprt_create_from_sa - Add a new listener to @serv from socket address 334 + * @serv: target RPC service 335 + * @xprt_name: transport class name 336 + * @net: network namespace 337 + * @sap: socket address pointer 338 + * @flags: SVC_SOCK flags 339 + * @cred: credential to bind to this transport 340 + * 341 + * Return local xprt port on success or %-EPROTONOSUPPORT on failure 342 + */ 343 + int svc_xprt_create_from_sa(struct svc_serv *serv, const char *xprt_name, 344 + struct net *net, struct sockaddr *sap, 345 + int flags, const struct cred *cred) 346 + { 347 + size_t len; 348 + int err; 349 + 350 + switch (sap->sa_family) { 351 + case AF_INET: 352 + len = sizeof(struct sockaddr_in); 353 + break; 354 + #if IS_ENABLED(CONFIG_IPV6) 355 + case AF_INET6: 356 + len = sizeof(struct sockaddr_in6); 357 + break; 358 + #endif 359 + default: 360 + return -EAFNOSUPPORT; 361 + } 362 + 363 + err = _svc_xprt_create(serv, xprt_name, net, sap, len, flags, cred); 364 + if (err == -EPROTONOSUPPORT) { 365 + request_module("svc%s", xprt_name); 366 + err = _svc_xprt_create(serv, xprt_name, net, sap, len, flags, 367 + cred); 368 + } 369 + 370 + return err; 371 + } 372 + EXPORT_SYMBOL_GPL(svc_xprt_create_from_sa); 373 + 374 + /** 289 375 * svc_xprt_create - Add a new listener to @serv 290 376 * @serv: target RPC service 291 377 * @xprt_name: transport class name ··· 337 339 * @flags: SVC_SOCK flags 338 340 * @cred: credential to bind to this transport 339 341 * 340 - * Return values: 341 - * %0: New listener added successfully 342 - * %-EPROTONOSUPPORT: Requested transport type not supported 342 + * Return local xprt port on success or %-EPROTONOSUPPORT on failure 343 343 */ 344 344 int svc_xprt_create(struct svc_serv *serv, const char *xprt_name, 345 345 struct net *net, const int family, 346 346 const unsigned short port, int flags, 347 347 const struct cred *cred) 348 348 { 349 - int err; 349 + struct sockaddr_in sin = { 350 + .sin_family = AF_INET, 351 + .sin_addr.s_addr = htonl(INADDR_ANY), 352 + .sin_port = htons(port), 353 + }; 354 + #if IS_ENABLED(CONFIG_IPV6) 355 + struct sockaddr_in6 sin6 = { 356 + .sin6_family = AF_INET6, 357 + .sin6_addr = IN6ADDR_ANY_INIT, 358 + .sin6_port = htons(port), 359 + }; 360 + #endif 361 + struct sockaddr *sap; 350 362 351 - err = _svc_xprt_create(serv, xprt_name, net, family, port, flags, cred); 352 - if (err == -EPROTONOSUPPORT) { 353 - request_module("svc%s", xprt_name); 354 - err = _svc_xprt_create(serv, xprt_name, net, family, port, flags, cred); 363 + switch (family) { 364 + case PF_INET: 365 + sap = (struct sockaddr *)&sin; 366 + break; 367 + #if IS_ENABLED(CONFIG_IPV6) 368 + case PF_INET6: 369 + sap = (struct sockaddr *)&sin6; 370 + break; 371 + #endif 372 + default: 373 + return -EAFNOSUPPORT; 355 374 } 356 - return err; 375 + 376 + return svc_xprt_create_from_sa(serv, xprt_name, net, sap, flags, cred); 357 377 } 358 378 EXPORT_SYMBOL_GPL(svc_xprt_create); 359 379 ··· 1274 1258 spin_unlock(&xprt->xpt_lock); 1275 1259 return dr; 1276 1260 } 1261 + 1262 + /** 1263 + * svc_find_listener - find an RPC transport instance 1264 + * @serv: pointer to svc_serv to search 1265 + * @xcl_name: C string containing transport's class name 1266 + * @net: owner net pointer 1267 + * @sa: sockaddr containing address 1268 + * 1269 + * Return the transport instance pointer for the endpoint accepting 1270 + * connections/peer traffic from the specified transport class, 1271 + * and matching sockaddr. 1272 + */ 1273 + struct svc_xprt *svc_find_listener(struct svc_serv *serv, const char *xcl_name, 1274 + struct net *net, const struct sockaddr *sa) 1275 + { 1276 + struct svc_xprt *xprt; 1277 + struct svc_xprt *found = NULL; 1278 + 1279 + spin_lock_bh(&serv->sv_lock); 1280 + list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list) { 1281 + if (xprt->xpt_net != net) 1282 + continue; 1283 + if (strcmp(xprt->xpt_class->xcl_name, xcl_name)) 1284 + continue; 1285 + if (!rpc_cmp_addr_port(sa, (struct sockaddr *)&xprt->xpt_local)) 1286 + continue; 1287 + found = xprt; 1288 + svc_xprt_get(xprt); 1289 + break; 1290 + } 1291 + spin_unlock_bh(&serv->sv_lock); 1292 + return found; 1293 + } 1294 + EXPORT_SYMBOL_GPL(svc_find_listener); 1277 1295 1278 1296 /** 1279 1297 * svc_find_xprt - find an RPC transport instance