aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-01-15 15:49:44 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-01-15 15:49:44 -0500
commitcc80fe0eefbbbd7b4e32f631bb2fa639d76af075 (patch)
tree1fdc8a85aba221d638a760f58f1301153f3bebf0
parentc7b6c5fe67d1519759de2014a2c44f50fb1426f3 (diff)
parent6e8b50d16a757d53f8817acecba97c5d4aa1cf65 (diff)
Merge tag 'nfsd-4.5' of git://linux-nfs.org/~bfields/linux
Pull nfsd updates from Bruce Fields: "Smaller bugfixes and cleanup, including a fix for a failures of kerberized NFSv4.1 mounts, and Scott Mayhew's work addressing ACK storms that can affect some high-availability NFS setups" * tag 'nfsd-4.5' of git://linux-nfs.org/~bfields/linux: nfsd: add new io class tracepoint nfsd: give up on CB_LAYOUTRECALLs after two lease periods nfsd: Fix nfsd leaks sunrpc module references lockd: constify nlmsvc_binding structure lockd: use to_delayed_work nfsd: use to_delayed_work Revert "svcrdma: Do not send XDR roundup bytes for a write chunk" lockd: Register callbacks on the inetaddr_chain and inet6addr_chain nfsd: Register callbacks on the inetaddr_chain and inet6addr_chain sunrpc: Add a function to close temporary transports immediately nfsd: don't base cl_cb_status on stale information nfsd4: fix gss-proxy 4.1 mounts for some AD principals nfsd: fix unlikely NULL deref in mach_creds_match nfsd: minor consolidation of mach_cred handling code nfsd: helper for dup of possibly NULL string svcrpc: move some initialization to common code nfsd: fix a warning message nfsd: constify nfsd4_callback_ops structure nfsd: recover: constify nfsd4_client_tracking_ops structures svcrdma: Do not send XDR roundup bytes for a write chunk
-rw-r--r--fs/lockd/svc.c79
-rw-r--r--fs/nfsd/lockd.c2
-rw-r--r--fs/nfsd/netns.h2
-rw-r--r--fs/nfsd/nfs4callback.c6
-rw-r--r--fs/nfsd/nfs4layouts.c39
-rw-r--r--fs/nfsd/nfs4recover.c6
-rw-r--r--fs/nfsd/nfs4state.c65
-rw-r--r--fs/nfsd/nfsfh.h23
-rw-r--r--fs/nfsd/nfssvc.c75
-rw-r--r--fs/nfsd/state.h4
-rw-r--r--fs/nfsd/trace.h41
-rw-r--r--fs/nfsd/vfs.c15
-rw-r--r--include/linux/lockd/bind.h2
-rw-r--r--include/linux/sunrpc/svc_xprt.h1
-rw-r--r--include/linux/sunrpc/svcauth.h9
-rw-r--r--net/sunrpc/auth_gss/gss_rpc_upcall.c3
-rw-r--r--net/sunrpc/svc_xprt.c45
-rw-r--r--net/sunrpc/svcauth.c2
-rw-r--r--net/sunrpc/svcauth_unix.c8
19 files changed, 370 insertions, 57 deletions
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 5f31ebd96c06..154a107cd376 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -25,13 +25,17 @@
25#include <linux/mutex.h> 25#include <linux/mutex.h>
26#include <linux/kthread.h> 26#include <linux/kthread.h>
27#include <linux/freezer.h> 27#include <linux/freezer.h>
28#include <linux/inetdevice.h>
28 29
29#include <linux/sunrpc/types.h> 30#include <linux/sunrpc/types.h>
30#include <linux/sunrpc/stats.h> 31#include <linux/sunrpc/stats.h>
31#include <linux/sunrpc/clnt.h> 32#include <linux/sunrpc/clnt.h>
32#include <linux/sunrpc/svc.h> 33#include <linux/sunrpc/svc.h>
33#include <linux/sunrpc/svcsock.h> 34#include <linux/sunrpc/svcsock.h>
35#include <linux/sunrpc/svc_xprt.h>
34#include <net/ip.h> 36#include <net/ip.h>
37#include <net/addrconf.h>
38#include <net/ipv6.h>
35#include <linux/lockd/lockd.h> 39#include <linux/lockd/lockd.h>
36#include <linux/nfs.h> 40#include <linux/nfs.h>
37 41
@@ -44,7 +48,7 @@
44 48
45static struct svc_program nlmsvc_program; 49static struct svc_program nlmsvc_program;
46 50
47struct nlmsvc_binding * nlmsvc_ops; 51const struct nlmsvc_binding *nlmsvc_ops;
48EXPORT_SYMBOL_GPL(nlmsvc_ops); 52EXPORT_SYMBOL_GPL(nlmsvc_ops);
49 53
50static DEFINE_MUTEX(nlmsvc_mutex); 54static DEFINE_MUTEX(nlmsvc_mutex);
@@ -90,8 +94,7 @@ static unsigned long get_lockd_grace_period(void)
90 94
91static void grace_ender(struct work_struct *grace) 95static void grace_ender(struct work_struct *grace)
92{ 96{
93 struct delayed_work *dwork = container_of(grace, struct delayed_work, 97 struct delayed_work *dwork = to_delayed_work(grace);
94 work);
95 struct lockd_net *ln = container_of(dwork, struct lockd_net, 98 struct lockd_net *ln = container_of(dwork, struct lockd_net,
96 grace_period_end); 99 grace_period_end);
97 100
@@ -279,6 +282,68 @@ static void lockd_down_net(struct svc_serv *serv, struct net *net)
279 } 282 }
280} 283}
281 284
285static int lockd_inetaddr_event(struct notifier_block *this,
286 unsigned long event, void *ptr)
287{
288 struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
289 struct sockaddr_in sin;
290
291 if (event != NETDEV_DOWN)
292 goto out;
293
294 if (nlmsvc_rqst) {
295 dprintk("lockd_inetaddr_event: removed %pI4\n",
296 &ifa->ifa_local);
297 sin.sin_family = AF_INET;
298 sin.sin_addr.s_addr = ifa->ifa_local;
299 svc_age_temp_xprts_now(nlmsvc_rqst->rq_server,
300 (struct sockaddr *)&sin);
301 }
302
303out:
304 return NOTIFY_DONE;
305}
306
307static struct notifier_block lockd_inetaddr_notifier = {
308 .notifier_call = lockd_inetaddr_event,
309};
310
311#if IS_ENABLED(CONFIG_IPV6)
312static int lockd_inet6addr_event(struct notifier_block *this,
313 unsigned long event, void *ptr)
314{
315 struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
316 struct sockaddr_in6 sin6;
317
318 if (event != NETDEV_DOWN)
319 goto out;
320
321 if (nlmsvc_rqst) {
322 dprintk("lockd_inet6addr_event: removed %pI6\n", &ifa->addr);
323 sin6.sin6_family = AF_INET6;
324 sin6.sin6_addr = ifa->addr;
325 svc_age_temp_xprts_now(nlmsvc_rqst->rq_server,
326 (struct sockaddr *)&sin6);
327 }
328
329out:
330 return NOTIFY_DONE;
331}
332
333static struct notifier_block lockd_inet6addr_notifier = {
334 .notifier_call = lockd_inet6addr_event,
335};
336#endif
337
338static void lockd_svc_exit_thread(void)
339{
340 unregister_inetaddr_notifier(&lockd_inetaddr_notifier);
341#if IS_ENABLED(CONFIG_IPV6)
342 unregister_inet6addr_notifier(&lockd_inet6addr_notifier);
343#endif
344 svc_exit_thread(nlmsvc_rqst);
345}
346
282static int lockd_start_svc(struct svc_serv *serv) 347static int lockd_start_svc(struct svc_serv *serv)
283{ 348{
284 int error; 349 int error;
@@ -315,7 +380,7 @@ static int lockd_start_svc(struct svc_serv *serv)
315 return 0; 380 return 0;
316 381
317out_task: 382out_task:
318 svc_exit_thread(nlmsvc_rqst); 383 lockd_svc_exit_thread();
319 nlmsvc_task = NULL; 384 nlmsvc_task = NULL;
320out_rqst: 385out_rqst:
321 nlmsvc_rqst = NULL; 386 nlmsvc_rqst = NULL;
@@ -360,6 +425,10 @@ static struct svc_serv *lockd_create_svc(void)
360 printk(KERN_WARNING "lockd_up: create service failed\n"); 425 printk(KERN_WARNING "lockd_up: create service failed\n");
361 return ERR_PTR(-ENOMEM); 426 return ERR_PTR(-ENOMEM);
362 } 427 }
428 register_inetaddr_notifier(&lockd_inetaddr_notifier);
429#if IS_ENABLED(CONFIG_IPV6)
430 register_inet6addr_notifier(&lockd_inet6addr_notifier);
431#endif
363 dprintk("lockd_up: service created\n"); 432 dprintk("lockd_up: service created\n");
364 return serv; 433 return serv;
365} 434}
@@ -428,7 +497,7 @@ lockd_down(struct net *net)
428 } 497 }
429 kthread_stop(nlmsvc_task); 498 kthread_stop(nlmsvc_task);
430 dprintk("lockd_down: service stopped\n"); 499 dprintk("lockd_down: service stopped\n");
431 svc_exit_thread(nlmsvc_rqst); 500 lockd_svc_exit_thread();
432 dprintk("lockd_down: service destroyed\n"); 501 dprintk("lockd_down: service destroyed\n");
433 nlmsvc_task = NULL; 502 nlmsvc_task = NULL;
434 nlmsvc_rqst = NULL; 503 nlmsvc_rqst = NULL;
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
index 77e7a5cca888..1a03bc3059e8 100644
--- a/fs/nfsd/lockd.c
+++ b/fs/nfsd/lockd.c
@@ -58,7 +58,7 @@ nlm_fclose(struct file *filp)
58 fput(filp); 58 fput(filp);
59} 59}
60 60
61static struct nlmsvc_binding nfsd_nlm_ops = { 61static const struct nlmsvc_binding nfsd_nlm_ops = {
62 .fopen = nlm_fopen, /* open file for locking */ 62 .fopen = nlm_fopen, /* open file for locking */
63 .fclose = nlm_fclose, /* close file */ 63 .fclose = nlm_fclose, /* close file */
64}; 64};
diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
index d8b16c2568f3..5fbf3bbd00d0 100644
--- a/fs/nfsd/netns.h
+++ b/fs/nfsd/netns.h
@@ -92,7 +92,7 @@ struct nfsd_net {
92 92
93 struct file *rec_file; 93 struct file *rec_file;
94 bool in_grace; 94 bool in_grace;
95 struct nfsd4_client_tracking_ops *client_tracking_ops; 95 const struct nfsd4_client_tracking_ops *client_tracking_ops;
96 96
97 time_t nfsd4_lease; 97 time_t nfsd4_lease;
98 time_t nfsd4_grace; 98 time_t nfsd4_grace;
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index e7f50c4081d6..7389cb1d7409 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -792,12 +792,16 @@ static void warn_no_callback_path(struct nfs4_client *clp, int reason)
792 792
793static void nfsd4_mark_cb_down(struct nfs4_client *clp, int reason) 793static void nfsd4_mark_cb_down(struct nfs4_client *clp, int reason)
794{ 794{
795 if (test_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_flags))
796 return;
795 clp->cl_cb_state = NFSD4_CB_DOWN; 797 clp->cl_cb_state = NFSD4_CB_DOWN;
796 warn_no_callback_path(clp, reason); 798 warn_no_callback_path(clp, reason);
797} 799}
798 800
799static void nfsd4_mark_cb_fault(struct nfs4_client *clp, int reason) 801static void nfsd4_mark_cb_fault(struct nfs4_client *clp, int reason)
800{ 802{
803 if (test_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_flags))
804 return;
801 clp->cl_cb_state = NFSD4_CB_FAULT; 805 clp->cl_cb_state = NFSD4_CB_FAULT;
802 warn_no_callback_path(clp, reason); 806 warn_no_callback_path(clp, reason);
803} 807}
@@ -1143,7 +1147,7 @@ nfsd4_run_cb_work(struct work_struct *work)
1143} 1147}
1144 1148
1145void nfsd4_init_cb(struct nfsd4_callback *cb, struct nfs4_client *clp, 1149void nfsd4_init_cb(struct nfsd4_callback *cb, struct nfs4_client *clp,
1146 struct nfsd4_callback_ops *ops, enum nfsd4_cb_op op) 1150 const struct nfsd4_callback_ops *ops, enum nfsd4_cb_op op)
1147{ 1151{
1148 cb->cb_clp = clp; 1152 cb->cb_clp = clp;
1149 cb->cb_msg.rpc_proc = &nfs4_cb_procedures[op]; 1153 cb->cb_msg.rpc_proc = &nfs4_cb_procedures[op];
diff --git a/fs/nfsd/nfs4layouts.c b/fs/nfsd/nfs4layouts.c
index c9d6c715c0fb..ce2d010d3b17 100644
--- a/fs/nfsd/nfs4layouts.c
+++ b/fs/nfsd/nfs4layouts.c
@@ -22,7 +22,7 @@ struct nfs4_layout {
22static struct kmem_cache *nfs4_layout_cache; 22static struct kmem_cache *nfs4_layout_cache;
23static struct kmem_cache *nfs4_layout_stateid_cache; 23static struct kmem_cache *nfs4_layout_stateid_cache;
24 24
25static struct nfsd4_callback_ops nfsd4_cb_layout_ops; 25static const struct nfsd4_callback_ops nfsd4_cb_layout_ops;
26static const struct lock_manager_operations nfsd4_layouts_lm_ops; 26static const struct lock_manager_operations nfsd4_layouts_lm_ops;
27 27
28const struct nfsd4_layout_ops *nfsd4_layout_ops[LAYOUT_TYPE_MAX] = { 28const struct nfsd4_layout_ops *nfsd4_layout_ops[LAYOUT_TYPE_MAX] = {
@@ -624,24 +624,39 @@ nfsd4_cb_layout_done(struct nfsd4_callback *cb, struct rpc_task *task)
624{ 624{
625 struct nfs4_layout_stateid *ls = 625 struct nfs4_layout_stateid *ls =
626 container_of(cb, struct nfs4_layout_stateid, ls_recall); 626 container_of(cb, struct nfs4_layout_stateid, ls_recall);
627 struct nfsd_net *nn;
628 ktime_t now, cutoff;
627 LIST_HEAD(reaplist); 629 LIST_HEAD(reaplist);
628 630
631
629 switch (task->tk_status) { 632 switch (task->tk_status) {
630 case 0: 633 case 0:
631 return 1; 634 case -NFS4ERR_DELAY:
635 /*
636 * Anything left? If not, then call it done. Note that we don't
637 * take the spinlock since this is an optimization and nothing
638 * should get added until the cb counter goes to zero.
639 */
640 if (list_empty(&ls->ls_layouts))
641 return 1;
642
643 /* Poll the client until it's done with the layout */
644 now = ktime_get();
645 nn = net_generic(ls->ls_stid.sc_client->net, nfsd_net_id);
646
647 /* Client gets 2 lease periods to return it */
648 cutoff = ktime_add_ns(task->tk_start,
649 nn->nfsd4_lease * NSEC_PER_SEC * 2);
650
651 if (ktime_before(now, cutoff)) {
652 rpc_delay(task, HZ/100); /* 10 mili-seconds */
653 return 0;
654 }
655 /* Fallthrough */
632 case -NFS4ERR_NOMATCHING_LAYOUT: 656 case -NFS4ERR_NOMATCHING_LAYOUT:
633 trace_layout_recall_done(&ls->ls_stid.sc_stateid); 657 trace_layout_recall_done(&ls->ls_stid.sc_stateid);
634 task->tk_status = 0; 658 task->tk_status = 0;
635 return 1; 659 return 1;
636 case -NFS4ERR_DELAY:
637 /* Poll the client until it's done with the layout */
638 /* FIXME: cap number of retries.
639 * The pnfs standard states that we need to only expire
640 * the client after at-least "lease time" .eg lease-time * 2
641 * when failing to communicate a recall
642 */
643 rpc_delay(task, HZ/100); /* 10 mili-seconds */
644 return 0;
645 default: 660 default:
646 /* 661 /*
647 * Unknown error or non-responding client, we'll need to fence. 662 * Unknown error or non-responding client, we'll need to fence.
@@ -665,7 +680,7 @@ nfsd4_cb_layout_release(struct nfsd4_callback *cb)
665 nfs4_put_stid(&ls->ls_stid); 680 nfs4_put_stid(&ls->ls_stid);
666} 681}
667 682
668static struct nfsd4_callback_ops nfsd4_cb_layout_ops = { 683static const struct nfsd4_callback_ops nfsd4_cb_layout_ops = {
669 .prepare = nfsd4_cb_layout_prepare, 684 .prepare = nfsd4_cb_layout_prepare,
670 .done = nfsd4_cb_layout_done, 685 .done = nfsd4_cb_layout_done,
671 .release = nfsd4_cb_layout_release, 686 .release = nfsd4_cb_layout_release,
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index e3d47091b191..79f0307a5ec8 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -631,7 +631,7 @@ nfsd4_check_legacy_client(struct nfs4_client *clp)
631 return -ENOENT; 631 return -ENOENT;
632} 632}
633 633
634static struct nfsd4_client_tracking_ops nfsd4_legacy_tracking_ops = { 634static const struct nfsd4_client_tracking_ops nfsd4_legacy_tracking_ops = {
635 .init = nfsd4_legacy_tracking_init, 635 .init = nfsd4_legacy_tracking_init,
636 .exit = nfsd4_legacy_tracking_exit, 636 .exit = nfsd4_legacy_tracking_exit,
637 .create = nfsd4_create_clid_dir, 637 .create = nfsd4_create_clid_dir,
@@ -1050,7 +1050,7 @@ out_err:
1050 printk(KERN_ERR "NFSD: Unable to end grace period: %d\n", ret); 1050 printk(KERN_ERR "NFSD: Unable to end grace period: %d\n", ret);
1051} 1051}
1052 1052
1053static struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops = { 1053static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops = {
1054 .init = nfsd4_init_cld_pipe, 1054 .init = nfsd4_init_cld_pipe,
1055 .exit = nfsd4_remove_cld_pipe, 1055 .exit = nfsd4_remove_cld_pipe,
1056 .create = nfsd4_cld_create, 1056 .create = nfsd4_cld_create,
@@ -1394,7 +1394,7 @@ nfsd4_umh_cltrack_grace_done(struct nfsd_net *nn)
1394 kfree(legacy); 1394 kfree(legacy);
1395} 1395}
1396 1396
1397static struct nfsd4_client_tracking_ops nfsd4_umh_tracking_ops = { 1397static const struct nfsd4_client_tracking_ops nfsd4_umh_tracking_ops = {
1398 .init = nfsd4_umh_cltrack_init, 1398 .init = nfsd4_umh_cltrack_init,
1399 .exit = NULL, 1399 .exit = NULL,
1400 .create = nfsd4_umh_cltrack_create, 1400 .create = nfsd4_umh_cltrack_create,
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index df5dba687265..c484a2b6cd10 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -98,7 +98,7 @@ static struct kmem_cache *odstate_slab;
98 98
99static void free_session(struct nfsd4_session *); 99static void free_session(struct nfsd4_session *);
100 100
101static struct nfsd4_callback_ops nfsd4_cb_recall_ops; 101static const struct nfsd4_callback_ops nfsd4_cb_recall_ops;
102 102
103static bool is_session_dead(struct nfsd4_session *ses) 103static bool is_session_dead(struct nfsd4_session *ses)
104{ 104{
@@ -1857,15 +1857,28 @@ static void copy_clid(struct nfs4_client *target, struct nfs4_client *source)
1857 target->cl_clientid.cl_id = source->cl_clientid.cl_id; 1857 target->cl_clientid.cl_id = source->cl_clientid.cl_id;
1858} 1858}
1859 1859
1860static int copy_cred(struct svc_cred *target, struct svc_cred *source) 1860int strdup_if_nonnull(char **target, char *source)
1861{ 1861{
1862 if (source->cr_principal) { 1862 if (source) {
1863 target->cr_principal = 1863 *target = kstrdup(source, GFP_KERNEL);
1864 kstrdup(source->cr_principal, GFP_KERNEL); 1864 if (!*target)
1865 if (target->cr_principal == NULL)
1866 return -ENOMEM; 1865 return -ENOMEM;
1867 } else 1866 } else
1868 target->cr_principal = NULL; 1867 *target = NULL;
1868 return 0;
1869}
1870
1871static int copy_cred(struct svc_cred *target, struct svc_cred *source)
1872{
1873 int ret;
1874
1875 ret = strdup_if_nonnull(&target->cr_principal, source->cr_principal);
1876 if (ret)
1877 return ret;
1878 ret = strdup_if_nonnull(&target->cr_raw_principal,
1879 source->cr_raw_principal);
1880 if (ret)
1881 return ret;
1869 target->cr_flavor = source->cr_flavor; 1882 target->cr_flavor = source->cr_flavor;
1870 target->cr_uid = source->cr_uid; 1883 target->cr_uid = source->cr_uid;
1871 target->cr_gid = source->cr_gid; 1884 target->cr_gid = source->cr_gid;
@@ -1969,6 +1982,9 @@ static bool mach_creds_match(struct nfs4_client *cl, struct svc_rqst *rqstp)
1969 return false; 1982 return false;
1970 if (!svc_rqst_integrity_protected(rqstp)) 1983 if (!svc_rqst_integrity_protected(rqstp))
1971 return false; 1984 return false;
1985 if (cl->cl_cred.cr_raw_principal)
1986 return 0 == strcmp(cl->cl_cred.cr_raw_principal,
1987 cr->cr_raw_principal);
1972 if (!cr->cr_principal) 1988 if (!cr->cr_principal)
1973 return false; 1989 return false;
1974 return 0 == strcmp(cl->cl_cred.cr_principal, cr->cr_principal); 1990 return 0 == strcmp(cl->cl_cred.cr_principal, cr->cr_principal);
@@ -2240,7 +2256,8 @@ nfsd4_store_cache_entry(struct nfsd4_compoundres *resp)
2240 base = resp->cstate.data_offset; 2256 base = resp->cstate.data_offset;
2241 slot->sl_datalen = buf->len - base; 2257 slot->sl_datalen = buf->len - base;
2242 if (read_bytes_from_xdr_buf(buf, base, slot->sl_data, slot->sl_datalen)) 2258 if (read_bytes_from_xdr_buf(buf, base, slot->sl_data, slot->sl_datalen))
2243 WARN("%s: sessions DRC could not cache compound\n", __func__); 2259 WARN(1, "%s: sessions DRC could not cache compound\n",
2260 __func__);
2244 return; 2261 return;
2245} 2262}
2246 2263
@@ -2365,10 +2382,27 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
2365 if (exid->flags & ~EXCHGID4_FLAG_MASK_A) 2382 if (exid->flags & ~EXCHGID4_FLAG_MASK_A)
2366 return nfserr_inval; 2383 return nfserr_inval;
2367 2384
2385 new = create_client(exid->clname, rqstp, &verf);
2386 if (new == NULL)
2387 return nfserr_jukebox;
2388
2368 switch (exid->spa_how) { 2389 switch (exid->spa_how) {
2369 case SP4_MACH_CRED: 2390 case SP4_MACH_CRED:
2370 if (!svc_rqst_integrity_protected(rqstp)) 2391 if (!svc_rqst_integrity_protected(rqstp)) {
2371 return nfserr_inval; 2392 status = nfserr_inval;
2393 goto out_nolock;
2394 }
2395 /*
2396 * Sometimes userspace doesn't give us a principal.
2397 * Which is a bug, really. Anyway, we can't enforce
2398 * MACH_CRED in that case, better to give up now:
2399 */
2400 if (!new->cl_cred.cr_principal &&
2401 !new->cl_cred.cr_raw_principal) {
2402 status = nfserr_serverfault;
2403 goto out_nolock;
2404 }
2405 new->cl_mach_cred = true;
2372 case SP4_NONE: 2406 case SP4_NONE:
2373 break; 2407 break;
2374 default: /* checked by xdr code */ 2408 default: /* checked by xdr code */
@@ -2377,10 +2411,6 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
2377 return nfserr_encr_alg_unsupp; 2411 return nfserr_encr_alg_unsupp;
2378 } 2412 }
2379 2413
2380 new = create_client(exid->clname, rqstp, &verf);
2381 if (new == NULL)
2382 return nfserr_jukebox;
2383
2384 /* Cases below refer to rfc 5661 section 18.35.4: */ 2414 /* Cases below refer to rfc 5661 section 18.35.4: */
2385 spin_lock(&nn->client_lock); 2415 spin_lock(&nn->client_lock);
2386 conf = find_confirmed_client_by_name(&exid->clname, nn); 2416 conf = find_confirmed_client_by_name(&exid->clname, nn);
@@ -2442,7 +2472,6 @@ out_new:
2442 goto out; 2472 goto out;
2443 } 2473 }
2444 new->cl_minorversion = cstate->minorversion; 2474 new->cl_minorversion = cstate->minorversion;
2445 new->cl_mach_cred = (exid->spa_how == SP4_MACH_CRED);
2446 2475
2447 gen_clid(new, nn); 2476 gen_clid(new, nn);
2448 add_to_unconfirmed(new); 2477 add_to_unconfirmed(new);
@@ -2460,6 +2489,7 @@ out_copy:
2460 2489
2461out: 2490out:
2462 spin_unlock(&nn->client_lock); 2491 spin_unlock(&nn->client_lock);
2492out_nolock:
2463 if (new) 2493 if (new)
2464 expire_client(new); 2494 expire_client(new);
2465 if (unconf) 2495 if (unconf)
@@ -3648,7 +3678,7 @@ static void nfsd4_cb_recall_release(struct nfsd4_callback *cb)
3648 nfs4_put_stid(&dp->dl_stid); 3678 nfs4_put_stid(&dp->dl_stid);
3649} 3679}
3650 3680
3651static struct nfsd4_callback_ops nfsd4_cb_recall_ops = { 3681static const struct nfsd4_callback_ops nfsd4_cb_recall_ops = {
3652 .prepare = nfsd4_cb_recall_prepare, 3682 .prepare = nfsd4_cb_recall_prepare,
3653 .done = nfsd4_cb_recall_done, 3683 .done = nfsd4_cb_recall_done,
3654 .release = nfsd4_cb_recall_release, 3684 .release = nfsd4_cb_recall_release,
@@ -4541,8 +4571,7 @@ static void
4541laundromat_main(struct work_struct *laundry) 4571laundromat_main(struct work_struct *laundry)
4542{ 4572{
4543 time_t t; 4573 time_t t;
4544 struct delayed_work *dwork = container_of(laundry, struct delayed_work, 4574 struct delayed_work *dwork = to_delayed_work(laundry);
4545 work);
4546 struct nfsd_net *nn = container_of(dwork, struct nfsd_net, 4575 struct nfsd_net *nn = container_of(dwork, struct nfsd_net,
4547 laundromat_work); 4576 laundromat_work);
4548 4577
diff --git a/fs/nfsd/nfsfh.h b/fs/nfsd/nfsfh.h
index 2087bae17582..0770bcb543c8 100644
--- a/fs/nfsd/nfsfh.h
+++ b/fs/nfsd/nfsfh.h
@@ -7,6 +7,7 @@
7#ifndef _LINUX_NFSD_NFSFH_H 7#ifndef _LINUX_NFSD_NFSFH_H
8#define _LINUX_NFSD_NFSFH_H 8#define _LINUX_NFSD_NFSFH_H
9 9
10#include <linux/crc32.h>
10#include <linux/sunrpc/svc.h> 11#include <linux/sunrpc/svc.h>
11#include <uapi/linux/nfsd/nfsfh.h> 12#include <uapi/linux/nfsd/nfsfh.h>
12 13
@@ -205,6 +206,28 @@ static inline bool fh_fsid_match(struct knfsd_fh *fh1, struct knfsd_fh *fh2)
205 return true; 206 return true;
206} 207}
207 208
209#ifdef CONFIG_CRC32
210/**
211 * knfsd_fh_hash - calculate the crc32 hash for the filehandle
212 * @fh - pointer to filehandle
213 *
214 * returns a crc32 hash for the filehandle that is compatible with
215 * the one displayed by "wireshark".
216 */
217
218static inline u32
219knfsd_fh_hash(struct knfsd_fh *fh)
220{
221 return ~crc32_le(0xFFFFFFFF, (unsigned char *)&fh->fh_base, fh->fh_size);
222}
223#else
224static inline u32
225knfsd_fh_hash(struct knfsd_fh *fh)
226{
227 return 0;
228}
229#endif
230
208#ifdef CONFIG_NFSD_V3 231#ifdef CONFIG_NFSD_V3
209/* 232/*
210 * The wcc data stored in current_fh should be cleared 233 * The wcc data stored in current_fh should be cleared
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index ad4e2377dd63..45007acaf364 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -14,9 +14,13 @@
14 14
15#include <linux/sunrpc/stats.h> 15#include <linux/sunrpc/stats.h>
16#include <linux/sunrpc/svcsock.h> 16#include <linux/sunrpc/svcsock.h>
17#include <linux/sunrpc/svc_xprt.h>
17#include <linux/lockd/bind.h> 18#include <linux/lockd/bind.h>
18#include <linux/nfsacl.h> 19#include <linux/nfsacl.h>
19#include <linux/seq_file.h> 20#include <linux/seq_file.h>
21#include <linux/inetdevice.h>
22#include <net/addrconf.h>
23#include <net/ipv6.h>
20#include <net/net_namespace.h> 24#include <net/net_namespace.h>
21#include "nfsd.h" 25#include "nfsd.h"
22#include "cache.h" 26#include "cache.h"
@@ -306,22 +310,81 @@ static void nfsd_shutdown_net(struct net *net)
306 nfsd_shutdown_generic(); 310 nfsd_shutdown_generic();
307} 311}
308 312
313static int nfsd_inetaddr_event(struct notifier_block *this, unsigned long event,
314 void *ptr)
315{
316 struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
317 struct net_device *dev = ifa->ifa_dev->dev;
318 struct net *net = dev_net(dev);
319 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
320 struct sockaddr_in sin;
321
322 if (event != NETDEV_DOWN)
323 goto out;
324
325 if (nn->nfsd_serv) {
326 dprintk("nfsd_inetaddr_event: removed %pI4\n", &ifa->ifa_local);
327 sin.sin_family = AF_INET;
328 sin.sin_addr.s_addr = ifa->ifa_local;
329 svc_age_temp_xprts_now(nn->nfsd_serv, (struct sockaddr *)&sin);
330 }
331
332out:
333 return NOTIFY_DONE;
334}
335
336static struct notifier_block nfsd_inetaddr_notifier = {
337 .notifier_call = nfsd_inetaddr_event,
338};
339
340#if IS_ENABLED(CONFIG_IPV6)
341static int nfsd_inet6addr_event(struct notifier_block *this,
342 unsigned long event, void *ptr)
343{
344 struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
345 struct net_device *dev = ifa->idev->dev;
346 struct net *net = dev_net(dev);
347 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
348 struct sockaddr_in6 sin6;
349
350 if (event != NETDEV_DOWN)
351 goto out;
352
353 if (nn->nfsd_serv) {
354 dprintk("nfsd_inet6addr_event: removed %pI6\n", &ifa->addr);
355 sin6.sin6_family = AF_INET6;
356 sin6.sin6_addr = ifa->addr;
357 svc_age_temp_xprts_now(nn->nfsd_serv, (struct sockaddr *)&sin6);
358 }
359
360out:
361 return NOTIFY_DONE;
362}
363
364static struct notifier_block nfsd_inet6addr_notifier = {
365 .notifier_call = nfsd_inet6addr_event,
366};
367#endif
368
309static void nfsd_last_thread(struct svc_serv *serv, struct net *net) 369static void nfsd_last_thread(struct svc_serv *serv, struct net *net)
310{ 370{
311 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 371 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
312 372
373 unregister_inetaddr_notifier(&nfsd_inetaddr_notifier);
374#if IS_ENABLED(CONFIG_IPV6)
375 unregister_inet6addr_notifier(&nfsd_inet6addr_notifier);
376#endif
313 /* 377 /*
314 * write_ports can create the server without actually starting 378 * write_ports can create the server without actually starting
315 * any threads--if we get shut down before any threads are 379 * any threads--if we get shut down before any threads are
316 * started, then nfsd_last_thread will be run before any of this 380 * started, then nfsd_last_thread will be run before any of this
317 * other initialization has been done. 381 * other initialization has been done except the rpcb information.
318 */ 382 */
383 svc_rpcb_cleanup(serv, net);
319 if (!nn->nfsd_net_up) 384 if (!nn->nfsd_net_up)
320 return; 385 return;
321 nfsd_shutdown_net(net);
322
323 svc_rpcb_cleanup(serv, net);
324 386
387 nfsd_shutdown_net(net);
325 printk(KERN_WARNING "nfsd: last server has exited, flushing export " 388 printk(KERN_WARNING "nfsd: last server has exited, flushing export "
326 "cache\n"); 389 "cache\n");
327 nfsd_export_flush(net); 390 nfsd_export_flush(net);
@@ -425,6 +488,10 @@ int nfsd_create_serv(struct net *net)
425 } 488 }
426 489
427 set_max_drc(); 490 set_max_drc();
491 register_inetaddr_notifier(&nfsd_inetaddr_notifier);
492#if IS_ENABLED(CONFIG_IPV6)
493 register_inet6addr_notifier(&nfsd_inet6addr_notifier);
494#endif
428 do_gettimeofday(&nn->nfssvc_boot); /* record boot time */ 495 do_gettimeofday(&nn->nfssvc_boot); /* record boot time */
429 return 0; 496 return 0;
430} 497}
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 99432b7ecb9c..c050c53036a6 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -65,7 +65,7 @@ struct nfsd4_callback {
65 struct nfs4_client *cb_clp; 65 struct nfs4_client *cb_clp;
66 u32 cb_minorversion; 66 u32 cb_minorversion;
67 struct rpc_message cb_msg; 67 struct rpc_message cb_msg;
68 struct nfsd4_callback_ops *cb_ops; 68 const struct nfsd4_callback_ops *cb_ops;
69 struct work_struct cb_work; 69 struct work_struct cb_work;
70 int cb_seq_status; 70 int cb_seq_status;
71 int cb_status; 71 int cb_status;
@@ -599,7 +599,7 @@ extern void nfsd4_probe_callback(struct nfs4_client *clp);
599extern void nfsd4_probe_callback_sync(struct nfs4_client *clp); 599extern void nfsd4_probe_callback_sync(struct nfs4_client *clp);
600extern void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *); 600extern void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *);
601extern void nfsd4_init_cb(struct nfsd4_callback *cb, struct nfs4_client *clp, 601extern void nfsd4_init_cb(struct nfsd4_callback *cb, struct nfs4_client *clp,
602 struct nfsd4_callback_ops *ops, enum nfsd4_cb_op op); 602 const struct nfsd4_callback_ops *ops, enum nfsd4_cb_op op);
603extern void nfsd4_run_cb(struct nfsd4_callback *cb); 603extern void nfsd4_run_cb(struct nfsd4_callback *cb);
604extern int nfsd4_create_callback_queue(void); 604extern int nfsd4_create_callback_queue(void);
605extern void nfsd4_destroy_callback_queue(void); 605extern void nfsd4_destroy_callback_queue(void);
diff --git a/fs/nfsd/trace.h b/fs/nfsd/trace.h
index 0befe762762b..3287041905da 100644
--- a/fs/nfsd/trace.h
+++ b/fs/nfsd/trace.h
@@ -8,6 +8,47 @@
8#define _NFSD_TRACE_H 8#define _NFSD_TRACE_H
9 9
10#include <linux/tracepoint.h> 10#include <linux/tracepoint.h>
11#include "nfsfh.h"
12
13DECLARE_EVENT_CLASS(nfsd_io_class,
14 TP_PROTO(struct svc_rqst *rqstp,
15 struct svc_fh *fhp,
16 loff_t offset,
17 int len),
18 TP_ARGS(rqstp, fhp, offset, len),
19 TP_STRUCT__entry(
20 __field(__be32, xid)
21 __field_struct(struct knfsd_fh, fh)
22 __field(loff_t, offset)
23 __field(int, len)
24 ),
25 TP_fast_assign(
26 __entry->xid = rqstp->rq_xid,
27 fh_copy_shallow(&__entry->fh, &fhp->fh_handle);
28 __entry->offset = offset;
29 __entry->len = len;
30 ),
31 TP_printk("xid=0x%x fh=0x%x offset=%lld len=%d",
32 __be32_to_cpu(__entry->xid), knfsd_fh_hash(&__entry->fh),
33 __entry->offset, __entry->len)
34)
35
36#define DEFINE_NFSD_IO_EVENT(name) \
37DEFINE_EVENT(nfsd_io_class, name, \
38 TP_PROTO(struct svc_rqst *rqstp, \
39 struct svc_fh *fhp, \
40 loff_t offset, \
41 int len), \
42 TP_ARGS(rqstp, fhp, offset, len))
43
44DEFINE_NFSD_IO_EVENT(read_start);
45DEFINE_NFSD_IO_EVENT(read_opened);
46DEFINE_NFSD_IO_EVENT(read_io_done);
47DEFINE_NFSD_IO_EVENT(read_done);
48DEFINE_NFSD_IO_EVENT(write_start);
49DEFINE_NFSD_IO_EVENT(write_opened);
50DEFINE_NFSD_IO_EVENT(write_io_done);
51DEFINE_NFSD_IO_EVENT(write_done);
11 52
12#include "state.h" 53#include "state.h"
13 54
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index d41c149fae75..6739077f17fe 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -43,6 +43,7 @@
43 43
44#include "nfsd.h" 44#include "nfsd.h"
45#include "vfs.h" 45#include "vfs.h"
46#include "trace.h"
46 47
47#define NFSDDBG_FACILITY NFSDDBG_FILEOP 48#define NFSDDBG_FACILITY NFSDDBG_FILEOP
48 49
@@ -997,16 +998,23 @@ __be32 nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
997 struct raparms *ra; 998 struct raparms *ra;
998 __be32 err; 999 __be32 err;
999 1000
1001 trace_read_start(rqstp, fhp, offset, vlen);
1000 err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file); 1002 err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file);
1001 if (err) 1003 if (err)
1002 return err; 1004 return err;
1003 1005
1004 ra = nfsd_init_raparms(file); 1006 ra = nfsd_init_raparms(file);
1007
1008 trace_read_opened(rqstp, fhp, offset, vlen);
1005 err = nfsd_vfs_read(rqstp, file, offset, vec, vlen, count); 1009 err = nfsd_vfs_read(rqstp, file, offset, vec, vlen, count);
1010 trace_read_io_done(rqstp, fhp, offset, vlen);
1011
1006 if (ra) 1012 if (ra)
1007 nfsd_put_raparams(file, ra); 1013 nfsd_put_raparams(file, ra);
1008 fput(file); 1014 fput(file);
1009 1015
1016 trace_read_done(rqstp, fhp, offset, vlen);
1017
1010 return err; 1018 return err;
1011} 1019}
1012 1020
@@ -1022,24 +1030,31 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
1022{ 1030{
1023 __be32 err = 0; 1031 __be32 err = 0;
1024 1032
1033 trace_write_start(rqstp, fhp, offset, vlen);
1034
1025 if (file) { 1035 if (file) {
1026 err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry, 1036 err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry,
1027 NFSD_MAY_WRITE|NFSD_MAY_OWNER_OVERRIDE); 1037 NFSD_MAY_WRITE|NFSD_MAY_OWNER_OVERRIDE);
1028 if (err) 1038 if (err)
1029 goto out; 1039 goto out;
1040 trace_write_opened(rqstp, fhp, offset, vlen);
1030 err = nfsd_vfs_write(rqstp, fhp, file, offset, vec, vlen, cnt, 1041 err = nfsd_vfs_write(rqstp, fhp, file, offset, vec, vlen, cnt,
1031 stablep); 1042 stablep);
1043 trace_write_io_done(rqstp, fhp, offset, vlen);
1032 } else { 1044 } else {
1033 err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_WRITE, &file); 1045 err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_WRITE, &file);
1034 if (err) 1046 if (err)
1035 goto out; 1047 goto out;
1036 1048
1049 trace_write_opened(rqstp, fhp, offset, vlen);
1037 if (cnt) 1050 if (cnt)
1038 err = nfsd_vfs_write(rqstp, fhp, file, offset, vec, vlen, 1051 err = nfsd_vfs_write(rqstp, fhp, file, offset, vec, vlen,
1039 cnt, stablep); 1052 cnt, stablep);
1053 trace_write_io_done(rqstp, fhp, offset, vlen);
1040 fput(file); 1054 fput(file);
1041 } 1055 }
1042out: 1056out:
1057 trace_write_done(rqstp, fhp, offset, vlen);
1043 return err; 1058 return err;
1044} 1059}
1045 1060
diff --git a/include/linux/lockd/bind.h b/include/linux/lockd/bind.h
index 4d24d64578c4..140edab64446 100644
--- a/include/linux/lockd/bind.h
+++ b/include/linux/lockd/bind.h
@@ -29,7 +29,7 @@ struct nlmsvc_binding {
29 void (*fclose)(struct file *); 29 void (*fclose)(struct file *);
30}; 30};
31 31
32extern struct nlmsvc_binding * nlmsvc_ops; 32extern const struct nlmsvc_binding *nlmsvc_ops;
33 33
34/* 34/*
35 * Similar to nfs_client_initdata, but without the NFS-specific 35 * Similar to nfs_client_initdata, but without the NFS-specific
diff --git a/include/linux/sunrpc/svc_xprt.h b/include/linux/sunrpc/svc_xprt.h
index 78512cfe1fe6..b7dabc4baafd 100644
--- a/include/linux/sunrpc/svc_xprt.h
+++ b/include/linux/sunrpc/svc_xprt.h
@@ -128,6 +128,7 @@ struct svc_xprt *svc_find_xprt(struct svc_serv *serv, const char *xcl_name,
128 const unsigned short port); 128 const unsigned short port);
129int svc_xprt_names(struct svc_serv *serv, char *buf, const int buflen); 129int svc_xprt_names(struct svc_serv *serv, char *buf, const int buflen);
130void svc_add_new_perm_xprt(struct svc_serv *serv, struct svc_xprt *xprt); 130void svc_add_new_perm_xprt(struct svc_serv *serv, struct svc_xprt *xprt);
131void svc_age_temp_xprts_now(struct svc_serv *, struct sockaddr *);
131 132
132static inline void svc_xprt_get(struct svc_xprt *xprt) 133static inline void svc_xprt_get(struct svc_xprt *xprt)
133{ 134{
diff --git a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h
index 8d71d6577459..c00f53a4ccdd 100644
--- a/include/linux/sunrpc/svcauth.h
+++ b/include/linux/sunrpc/svcauth.h
@@ -23,13 +23,19 @@ struct svc_cred {
23 kgid_t cr_gid; 23 kgid_t cr_gid;
24 struct group_info *cr_group_info; 24 struct group_info *cr_group_info;
25 u32 cr_flavor; /* pseudoflavor */ 25 u32 cr_flavor; /* pseudoflavor */
26 char *cr_principal; /* for gss */ 26 /* name of form servicetype/hostname@REALM, passed down by
27 * gss-proxy: */
28 char *cr_raw_principal;
29 /* name of form servicetype@hostname, passed down by
30 * rpc.svcgssd, or computed from the above: */
31 char *cr_principal;
27 struct gss_api_mech *cr_gss_mech; 32 struct gss_api_mech *cr_gss_mech;
28}; 33};
29 34
30static inline void init_svc_cred(struct svc_cred *cred) 35static inline void init_svc_cred(struct svc_cred *cred)
31{ 36{
32 cred->cr_group_info = NULL; 37 cred->cr_group_info = NULL;
38 cred->cr_raw_principal = NULL;
33 cred->cr_principal = NULL; 39 cred->cr_principal = NULL;
34 cred->cr_gss_mech = NULL; 40 cred->cr_gss_mech = NULL;
35} 41}
@@ -38,6 +44,7 @@ static inline void free_svc_cred(struct svc_cred *cred)
38{ 44{
39 if (cred->cr_group_info) 45 if (cred->cr_group_info)
40 put_group_info(cred->cr_group_info); 46 put_group_info(cred->cr_group_info);
47 kfree(cred->cr_raw_principal);
41 kfree(cred->cr_principal); 48 kfree(cred->cr_principal);
42 gss_mech_put(cred->cr_gss_mech); 49 gss_mech_put(cred->cr_gss_mech);
43 init_svc_cred(cred); 50 init_svc_cred(cred);
diff --git a/net/sunrpc/auth_gss/gss_rpc_upcall.c b/net/sunrpc/auth_gss/gss_rpc_upcall.c
index 59eeed43eda2..f0c6a8c78a56 100644
--- a/net/sunrpc/auth_gss/gss_rpc_upcall.c
+++ b/net/sunrpc/auth_gss/gss_rpc_upcall.c
@@ -326,6 +326,9 @@ int gssp_accept_sec_context_upcall(struct net *net,
326 if (data->found_creds && client_name.data != NULL) { 326 if (data->found_creds && client_name.data != NULL) {
327 char *c; 327 char *c;
328 328
329 data->creds.cr_raw_principal = kstrndup(client_name.data,
330 client_name.len, GFP_KERNEL);
331
329 data->creds.cr_principal = kstrndup(client_name.data, 332 data->creds.cr_principal = kstrndup(client_name.data,
330 client_name.len, GFP_KERNEL); 333 client_name.len, GFP_KERNEL);
331 if (data->creds.cr_principal) { 334 if (data->creds.cr_principal) {
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index a6cbb2104667..7422f28818b2 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -10,11 +10,13 @@
10#include <linux/kthread.h> 10#include <linux/kthread.h>
11#include <linux/slab.h> 11#include <linux/slab.h>
12#include <net/sock.h> 12#include <net/sock.h>
13#include <linux/sunrpc/addr.h>
13#include <linux/sunrpc/stats.h> 14#include <linux/sunrpc/stats.h>
14#include <linux/sunrpc/svc_xprt.h> 15#include <linux/sunrpc/svc_xprt.h>
15#include <linux/sunrpc/svcsock.h> 16#include <linux/sunrpc/svcsock.h>
16#include <linux/sunrpc/xprt.h> 17#include <linux/sunrpc/xprt.h>
17#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/netdevice.h>
18#include <trace/events/sunrpc.h> 20#include <trace/events/sunrpc.h>
19 21
20#define RPCDBG_FACILITY RPCDBG_SVCXPRT 22#define RPCDBG_FACILITY RPCDBG_SVCXPRT
@@ -938,6 +940,49 @@ static void svc_age_temp_xprts(unsigned long closure)
938 mod_timer(&serv->sv_temptimer, jiffies + svc_conn_age_period * HZ); 940 mod_timer(&serv->sv_temptimer, jiffies + svc_conn_age_period * HZ);
939} 941}
940 942
943/* Close temporary transports whose xpt_local matches server_addr immediately
944 * instead of waiting for them to be picked up by the timer.
945 *
946 * This is meant to be called from a notifier_block that runs when an ip
947 * address is deleted.
948 */
949void svc_age_temp_xprts_now(struct svc_serv *serv, struct sockaddr *server_addr)
950{
951 struct svc_xprt *xprt;
952 struct svc_sock *svsk;
953 struct socket *sock;
954 struct list_head *le, *next;
955 LIST_HEAD(to_be_closed);
956 struct linger no_linger = {
957 .l_onoff = 1,
958 .l_linger = 0,
959 };
960
961 spin_lock_bh(&serv->sv_lock);
962 list_for_each_safe(le, next, &serv->sv_tempsocks) {
963 xprt = list_entry(le, struct svc_xprt, xpt_list);
964 if (rpc_cmp_addr(server_addr, (struct sockaddr *)
965 &xprt->xpt_local)) {
966 dprintk("svc_age_temp_xprts_now: found %p\n", xprt);
967 list_move(le, &to_be_closed);
968 }
969 }
970 spin_unlock_bh(&serv->sv_lock);
971
972 while (!list_empty(&to_be_closed)) {
973 le = to_be_closed.next;
974 list_del_init(le);
975 xprt = list_entry(le, struct svc_xprt, xpt_list);
976 dprintk("svc_age_temp_xprts_now: closing %p\n", xprt);
977 svsk = container_of(xprt, struct svc_sock, sk_xprt);
978 sock = svsk->sk_sock;
979 kernel_setsockopt(sock, SOL_SOCKET, SO_LINGER,
980 (char *)&no_linger, sizeof(no_linger));
981 svc_close_xprt(xprt);
982 }
983}
984EXPORT_SYMBOL_GPL(svc_age_temp_xprts_now);
985
941static void call_xpt_users(struct svc_xprt *xprt) 986static void call_xpt_users(struct svc_xprt *xprt)
942{ 987{
943 struct svc_xpt_user *u; 988 struct svc_xpt_user *u;
diff --git a/net/sunrpc/svcauth.c b/net/sunrpc/svcauth.c
index 79c0f3459b5c..69841db1f533 100644
--- a/net/sunrpc/svcauth.c
+++ b/net/sunrpc/svcauth.c
@@ -55,6 +55,7 @@ svc_authenticate(struct svc_rqst *rqstp, __be32 *authp)
55 spin_unlock(&authtab_lock); 55 spin_unlock(&authtab_lock);
56 56
57 rqstp->rq_auth_slack = 0; 57 rqstp->rq_auth_slack = 0;
58 init_svc_cred(&rqstp->rq_cred);
58 59
59 rqstp->rq_authop = aops; 60 rqstp->rq_authop = aops;
60 return aops->accept(rqstp, authp); 61 return aops->accept(rqstp, authp);
@@ -63,6 +64,7 @@ EXPORT_SYMBOL_GPL(svc_authenticate);
63 64
64int svc_set_client(struct svc_rqst *rqstp) 65int svc_set_client(struct svc_rqst *rqstp)
65{ 66{
67 rqstp->rq_client = NULL;
66 return rqstp->rq_authop->set_client(rqstp); 68 return rqstp->rq_authop->set_client(rqstp);
67} 69}
68EXPORT_SYMBOL_GPL(svc_set_client); 70EXPORT_SYMBOL_GPL(svc_set_client);
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 621ca7b4a155..dfacdc95b3f5 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -728,10 +728,6 @@ svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp)
728 struct kvec *resv = &rqstp->rq_res.head[0]; 728 struct kvec *resv = &rqstp->rq_res.head[0];
729 struct svc_cred *cred = &rqstp->rq_cred; 729 struct svc_cred *cred = &rqstp->rq_cred;
730 730
731 cred->cr_group_info = NULL;
732 cred->cr_principal = NULL;
733 rqstp->rq_client = NULL;
734
735 if (argv->iov_len < 3*4) 731 if (argv->iov_len < 3*4)
736 return SVC_GARBAGE; 732 return SVC_GARBAGE;
737 733
@@ -794,10 +790,6 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
794 u32 slen, i; 790 u32 slen, i;
795 int len = argv->iov_len; 791 int len = argv->iov_len;
796 792
797 cred->cr_group_info = NULL;
798 cred->cr_principal = NULL;
799 rqstp->rq_client = NULL;
800
801 if ((len -= 3*4) < 0) 793 if ((len -= 3*4) < 0)
802 return SVC_GARBAGE; 794 return SVC_GARBAGE;
803 795