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
Unified · Split
| @@ -25,13 +25,17 @@ · 24 unmodified lines | ||
| 25 | 25 | #include <linux/mutex.h> |
| 26 | 26 | #include <linux/kthread.h> |
| 27 | 27 | #include <linux/freezer.h> |
| 28 | +#include <linux/inetdevice.h> | |
| 28 | 29 | |
| 29 | 30 | #include <linux/sunrpc/types.h> |
| 30 | 31 | #include <linux/sunrpc/stats.h> |
| 31 | 32 | #include <linux/sunrpc/clnt.h> |
| 32 | 33 | #include <linux/sunrpc/svc.h> |
| 33 | 34 | #include <linux/sunrpc/svcsock.h> |
| 35 | +#include <linux/sunrpc/svc_xprt.h> | |
| 34 | 36 | #include <net/ip.h> |
| 37 | +#include <net/addrconf.h> | |
| 38 | +#include <net/ipv6.h> | |
| 35 | 39 | #include <linux/lockd/lockd.h> |
| 36 | 40 | #include <linux/nfs.h> |
| 37 | 41 | |
| @@ -44,7 +48,7 @@ · 6 unmodified lines | ||
| 44 | 48 | |
| 45 | 49 | static struct svc_program nlmsvc_program; |
| 46 | 50 | |
| 47 | −struct nlmsvc_binding * nlmsvc_ops; | |
| 51 | +const struct nlmsvc_binding *nlmsvc_ops; | |
| 48 | 52 | EXPORT_SYMBOL_GPL(nlmsvc_ops); |
| 49 | 53 | |
| 50 | 54 | static DEFINE_MUTEX(nlmsvc_mutex); |
| @@ -90,8 +94,7 @@ static unsigned long get_lockd_grace_period(void) · 39 unmodified lines | ||
| 90 | 94 | |
| 91 | 95 | static void grace_ender(struct work_struct *grace) |
| 92 | 96 | { |
| 93 | − struct delayed_work *dwork = container_of(grace, struct delayed_work, | |
| 94 | − work); | |
| 97 | + struct delayed_work *dwork = to_delayed_work(grace); | |
| 95 | 98 | struct lockd_net *ln = container_of(dwork, struct lockd_net, |
| 96 | 99 | grace_period_end); |
| 97 | 100 | |
| @@ -279,6 +282,68 @@ static void lockd_down_net(struct svc_serv *serv, struct net *net) · 181 unmodified lines | ||
| 279 | 282 | } |
| 280 | 283 | } |
| 281 | 284 | |
| 285 | +static 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 | + | |
| 303 | +out: | |
| 304 | + return NOTIFY_DONE; | |
| 305 | +} | |
| 306 | + | |
| 307 | +static struct notifier_block lockd_inetaddr_notifier = { | |
| 308 | + .notifier_call = lockd_inetaddr_event, | |
| 309 | +}; | |
| 310 | + | |
| 311 | +#if IS_ENABLED(CONFIG_IPV6) | |
| 312 | +static 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 | + | |
| 329 | +out: | |
| 330 | + return NOTIFY_DONE; | |
| 331 | +} | |
| 332 | + | |
| 333 | +static struct notifier_block lockd_inet6addr_notifier = { | |
| 334 | + .notifier_call = lockd_inet6addr_event, | |
| 335 | +}; | |
| 336 | +#endif | |
| 337 | + | |
| 338 | +static 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 | + | |
| 282 | 347 | static int lockd_start_svc(struct svc_serv *serv) |
| 283 | 348 | { |
| 284 | 349 | int error; |
| @@ -315,7 +380,7 @@ static int lockd_start_svc(struct svc_serv *serv) · 30 unmodified lines | ||
| 315 | 380 | return 0; |
| 316 | 381 | |
| 317 | 382 | out_task: |
| 318 | − svc_exit_thread(nlmsvc_rqst); | |
| 383 | + lockd_svc_exit_thread(); | |
| 319 | 384 | nlmsvc_task = NULL; |
| 320 | 385 | out_rqst: |
| 321 | 386 | nlmsvc_rqst = NULL; |
| @@ -360,6 +425,10 @@ static struct svc_serv *lockd_create_svc(void) · 38 unmodified lines | ||
| 360 | 425 | printk(KERN_WARNING "lockd_up: create service failed\n"); |
| 361 | 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 | 432 | dprintk("lockd_up: service created\n"); |
| 364 | 433 | return serv; |
| 365 | 434 | } |
| @@ -428,7 +497,7 @@ lockd_down(struct net *net) · 62 unmodified lines | ||
| 428 | 497 | } |
| 429 | 498 | kthread_stop(nlmsvc_task); |
| 430 | 499 | dprintk("lockd_down: service stopped\n"); |
| 431 | − svc_exit_thread(nlmsvc_rqst); | |
| 500 | + lockd_svc_exit_thread(); | |
| 432 | 501 | dprintk("lockd_down: service destroyed\n"); |
| 433 | 502 | nlmsvc_task = NULL; |
| 434 | 503 | nlmsvc_rqst = NULL; |
| @@ -58,7 +58,7 @@ nlm_fclose(struct file *filp) · 57 unmodified lines | ||
| 58 | 58 | fput(filp); |
| 59 | 59 | } |
| 60 | 60 | |
| 61 | −static struct nlmsvc_binding nfsd_nlm_ops = { | |
| 61 | +static const struct nlmsvc_binding nfsd_nlm_ops = { | |
| 62 | 62 | .fopen = nlm_fopen, /* open file for locking */ |
| 63 | 63 | .fclose = nlm_fclose, /* close file */ |
| 64 | 64 | }; |
| @@ -92,7 +92,7 @@ struct nfsd_net { · 91 unmodified lines | ||
| 92 | 92 | |
| 93 | 93 | struct file *rec_file; |
| 94 | 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 | 97 | time_t nfsd4_lease; |
| 98 | 98 | time_t nfsd4_grace; |
| @@ -792,12 +792,16 @@ static void warn_no_callback_path(struct nfs4_client *clp, int reason) · 791 unmodified lines | ||
| 792 | 792 | |
| 793 | 793 | static 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 | 797 | clp->cl_cb_state = NFSD4_CB_DOWN; |
| 796 | 798 | warn_no_callback_path(clp, reason); |
| 797 | 799 | } |
| 798 | 800 | |
| 799 | 801 | static 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 | 805 | clp->cl_cb_state = NFSD4_CB_FAULT; |
| 802 | 806 | warn_no_callback_path(clp, reason); |
| 803 | 807 | } |
| @@ -1143,7 +1147,7 @@ nfsd4_run_cb_work(struct work_struct *work) · 339 unmodified lines | ||
| 1143 | 1147 | } |
| 1144 | 1148 | |
| 1145 | 1149 | void 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 | 1152 | cb->cb_clp = clp; |
| 1149 | 1153 | cb->cb_msg.rpc_proc = &nfs4_cb_procedures[op]; |
| @@ -22,7 +22,7 @@ struct nfs4_layout { · 21 unmodified lines | ||
| 22 | 22 | static struct kmem_cache *nfs4_layout_cache; |
| 23 | 23 | static struct kmem_cache *nfs4_layout_stateid_cache; |
| 24 | 24 | |
| 25 | −static struct nfsd4_callback_ops nfsd4_cb_layout_ops; | |
| 25 | +static const struct nfsd4_callback_ops nfsd4_cb_layout_ops; | |
| 26 | 26 | static const struct lock_manager_operations nfsd4_layouts_lm_ops; |
| 27 | 27 | |
| 28 | 28 | const 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) · 595 unmodified lines | ||
| 624 | 624 | { |
| 625 | 625 | struct nfs4_layout_stateid *ls = |
| 626 | 626 | container_of(cb, struct nfs4_layout_stateid, ls_recall); |
| 627 | + struct nfsd_net *nn; | |
| 628 | + ktime_t now, cutoff; | |
| 627 | 629 | LIST_HEAD(reaplist); |
| 628 | 630 | |
| 631 | + | |
| 629 | 632 | switch (task->tk_status) { |
| 630 | 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 | 656 | case -NFS4ERR_NOMATCHING_LAYOUT: |
| 633 | 657 | trace_layout_recall_done(&ls->ls_stid.sc_stateid); |
| 634 | 658 | task->tk_status = 0; |
| 635 | 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 | 660 | default: |
| 646 | 661 | /* |
| 647 | 662 | * Unknown error or non-responding client, we'll need to fence. |
| @@ -665,7 +680,7 @@ nfsd4_cb_layout_release(struct nfsd4_callback *cb) · 17 unmodified lines | ||
| 665 | 680 | nfs4_put_stid(&ls->ls_stid); |
| 666 | 681 | } |
| 667 | 682 | |
| 668 | −static struct nfsd4_callback_ops nfsd4_cb_layout_ops = { | |
| 683 | +static const struct nfsd4_callback_ops nfsd4_cb_layout_ops = { | |
| 669 | 684 | .prepare = nfsd4_cb_layout_prepare, |
| 670 | 685 | .done = nfsd4_cb_layout_done, |
| 671 | 686 | .release = nfsd4_cb_layout_release, |
| @@ -631,7 +631,7 @@ nfsd4_check_legacy_client(struct nfs4_client *clp) · 630 unmodified lines | ||
| 631 | 631 | return -ENOENT; |
| 632 | 632 | } |
| 633 | 633 | |
| 634 | −static struct nfsd4_client_tracking_ops nfsd4_legacy_tracking_ops = { | |
| 634 | +static const struct nfsd4_client_tracking_ops nfsd4_legacy_tracking_ops = { | |
| 635 | 635 | .init = nfsd4_legacy_tracking_init, |
| 636 | 636 | .exit = nfsd4_legacy_tracking_exit, |
| 637 | 637 | .create = nfsd4_create_clid_dir, |
| @@ -1050,7 +1050,7 @@ out_err: · 412 unmodified lines | ||
| 1050 | 1050 | printk(KERN_ERR "NFSD: Unable to end grace period: %d\n", ret); |
| 1051 | 1051 | } |
| 1052 | 1052 | |
| 1053 | −static struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops = { | |
| 1053 | +static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops = { | |
| 1054 | 1054 | .init = nfsd4_init_cld_pipe, |
| 1055 | 1055 | .exit = nfsd4_remove_cld_pipe, |
| 1056 | 1056 | .create = nfsd4_cld_create, |
| @@ -1394,7 +1394,7 @@ nfsd4_umh_cltrack_grace_done(struct nfsd_net *nn) · 337 unmodified lines | ||
| 1394 | 1394 | kfree(legacy); |
| 1395 | 1395 | } |
| 1396 | 1396 | |
| 1397 | −static struct nfsd4_client_tracking_ops nfsd4_umh_tracking_ops = { | |
| 1397 | +static const struct nfsd4_client_tracking_ops nfsd4_umh_tracking_ops = { | |
| 1398 | 1398 | .init = nfsd4_umh_cltrack_init, |
| 1399 | 1399 | .exit = NULL, |
| 1400 | 1400 | .create = nfsd4_umh_cltrack_create, |
| @@ -98,7 +98,7 @@ static struct kmem_cache *odstate_slab; · 97 unmodified lines | ||
| 98 | 98 | |
| 99 | 99 | static void free_session(struct nfsd4_session *); |
| 100 | 100 | |
| 101 | −static struct nfsd4_callback_ops nfsd4_cb_recall_ops; | |
| 101 | +static const struct nfsd4_callback_ops nfsd4_cb_recall_ops; | |
| 102 | 102 | |
| 103 | 103 | static 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) · 1752 unmodified lines | ||
| 1857 | 1857 | target->cl_clientid.cl_id = source->cl_clientid.cl_id; |
| 1858 | 1858 | } |
| 1859 | 1859 | |
| 1860 | −static int copy_cred(struct svc_cred *target, struct svc_cred *source) | |
| 1860 | +int strdup_if_nonnull(char **target, char *source) | |
| 1861 | 1861 | { |
| 1862 | − if (source->cr_principal) { | |
| 1863 | − target->cr_principal = | |
| 1864 | − kstrdup(source->cr_principal, GFP_KERNEL); | |
| 1865 | − if (target->cr_principal == NULL) | |
| 1862 | + if (source) { | |
| 1863 | + *target = kstrdup(source, GFP_KERNEL); | |
| 1864 | + if (!*target) | |
| 1866 | 1865 | return -ENOMEM; |
| 1867 | 1866 | } else |
| 1868 | − target->cr_principal = NULL; | |
| 1867 | + *target = NULL; | |
| 1868 | + return 0; | |
| 1869 | +} | |
| 1870 | + | |
| 1871 | +static 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 | 1882 | target->cr_flavor = source->cr_flavor; |
| 1870 | 1883 | target->cr_uid = source->cr_uid; |
| 1871 | 1884 | target->cr_gid = source->cr_gid; |
| @@ -1969,6 +1982,9 @@ static bool mach_creds_match(struct nfs4_client *cl, struct svc_rqst *rqstp) · 97 unmodified lines | ||
| 1969 | 1982 | return false; |
| 1970 | 1983 | if (!svc_rqst_integrity_protected(rqstp)) |
| 1971 | 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 | 1988 | if (!cr->cr_principal) |
| 1973 | 1989 | return false; |
| 1974 | 1990 | return 0 == strcmp(cl->cl_cred.cr_principal, cr->cr_principal); |
| @@ -2240,7 +2256,8 @@ nfsd4_store_cache_entry(struct nfsd4_compoundres *resp) · 265 unmodified lines | ||
| 2240 | 2256 | base = resp->cstate.data_offset; |
| 2241 | 2257 | slot->sl_datalen = buf->len - base; |
| 2242 | 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 | 2261 | return; |
| 2245 | 2262 | } |
| 2246 | 2263 | |
| @@ -2365,10 +2382,27 @@ nfsd4_exchange_id(struct svc_rqst *rqstp, · 118 unmodified lines | ||
| 2365 | 2382 | if (exid->flags & ~EXCHGID4_FLAG_MASK_A) |
| 2366 | 2383 | return nfserr_inval; |
| 2367 | 2384 | |
| 2385 | + new = create_client(exid->clname, rqstp, &verf); | |
| 2386 | + if (new == NULL) | |
| 2387 | + return nfserr_jukebox; | |
| 2388 | + | |
| 2368 | 2389 | switch (exid->spa_how) { |
| 2369 | 2390 | case SP4_MACH_CRED: |
| 2370 | − if (!svc_rqst_integrity_protected(rqstp)) | |
| 2371 | − return nfserr_inval; | |
| 2391 | + if (!svc_rqst_integrity_protected(rqstp)) { | |
| 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 | 2406 | case SP4_NONE: |
| 2373 | 2407 | break; |
| 2374 | 2408 | default: /* checked by xdr code */ |
| @@ -2377,10 +2411,6 @@ nfsd4_exchange_id(struct svc_rqst *rqstp, · 2 unmodified lines | ||
| 2377 | 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 | 2414 | /* Cases below refer to rfc 5661 section 18.35.4: */ |
| 2385 | 2415 | spin_lock(&nn->client_lock); |
| 2386 | 2416 | conf = find_confirmed_client_by_name(&exid->clname, nn); |
| @@ -2442,7 +2472,6 @@ out_new: · 55 unmodified lines | ||
| 2442 | 2472 | goto out; |
| 2443 | 2473 | } |
| 2444 | 2474 | new->cl_minorversion = cstate->minorversion; |
| 2445 | − new->cl_mach_cred = (exid->spa_how == SP4_MACH_CRED); | |
| 2446 | 2475 | |
| 2447 | 2476 | gen_clid(new, nn); |
| 2448 | 2477 | add_to_unconfirmed(new); |
| @@ -2460,6 +2489,7 @@ out_copy: · 11 unmodified lines | ||
| 2460 | 2489 | |
| 2461 | 2490 | out: |
| 2462 | 2491 | spin_unlock(&nn->client_lock); |
| 2492 | +out_nolock: | |
| 2463 | 2493 | if (new) |
| 2464 | 2494 | expire_client(new); |
| 2465 | 2495 | if (unconf) |
| @@ -3648,7 +3678,7 @@ static void nfsd4_cb_recall_release(struct nfsd4_callback *cb) · 1182 unmodified lines | ||
| 3648 | 3678 | nfs4_put_stid(&dp->dl_stid); |
| 3649 | 3679 | } |
| 3650 | 3680 | |
| 3651 | −static struct nfsd4_callback_ops nfsd4_cb_recall_ops = { | |
| 3681 | +static const struct nfsd4_callback_ops nfsd4_cb_recall_ops = { | |
| 3652 | 3682 | .prepare = nfsd4_cb_recall_prepare, |
| 3653 | 3683 | .done = nfsd4_cb_recall_done, |
| 3654 | 3684 | .release = nfsd4_cb_recall_release, |
| @@ -4541,8 +4571,7 @@ static void · 886 unmodified lines | ||
| 4541 | 4571 | laundromat_main(struct work_struct *laundry) |
| 4542 | 4572 | { |
| 4543 | 4573 | time_t t; |
| 4544 | − struct delayed_work *dwork = container_of(laundry, struct delayed_work, | |
| 4545 | − work); | |
| 4574 | + struct delayed_work *dwork = to_delayed_work(laundry); | |
| 4546 | 4575 | struct nfsd_net *nn = container_of(dwork, struct nfsd_net, |
| 4547 | 4576 | laundromat_work); |
| 4548 | 4577 | |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | #ifndef _LINUX_NFSD_NFSFH_H |
| 8 | 8 | #define _LINUX_NFSD_NFSFH_H |
| 9 | 9 | |
| 10 | +#include <linux/crc32.h> | |
| 10 | 11 | #include <linux/sunrpc/svc.h> |
| 11 | 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) · 192 unmodified lines | ||
| 205 | 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 | + | |
| 218 | +static inline u32 | |
| 219 | +knfsd_fh_hash(struct knfsd_fh *fh) | |
| 220 | +{ | |
| 221 | + return ~crc32_le(0xFFFFFFFF, (unsigned char *)&fh->fh_base, fh->fh_size); | |
| 222 | +} | |
| 223 | +#else | |
| 224 | +static inline u32 | |
| 225 | +knfsd_fh_hash(struct knfsd_fh *fh) | |
| 226 | +{ | |
| 227 | + return 0; | |
| 228 | +} | |
| 229 | +#endif | |
| 230 | + | |
| 208 | 231 | #ifdef CONFIG_NFSD_V3 |
| 209 | 232 | /* |
| 210 | 233 | * The wcc data stored in current_fh should be cleared |
| @@ -14,9 +14,13 @@ · 13 unmodified lines | ||
| 14 | 14 | |
| 15 | 15 | #include <linux/sunrpc/stats.h> |
| 16 | 16 | #include <linux/sunrpc/svcsock.h> |
| 17 | +#include <linux/sunrpc/svc_xprt.h> | |
| 17 | 18 | #include <linux/lockd/bind.h> |
| 18 | 19 | #include <linux/nfsacl.h> |
| 19 | 20 | #include <linux/seq_file.h> |
| 21 | +#include <linux/inetdevice.h> | |
| 22 | +#include <net/addrconf.h> | |
| 23 | +#include <net/ipv6.h> | |
| 20 | 24 | #include <net/net_namespace.h> |
| 21 | 25 | #include "nfsd.h" |
| 22 | 26 | #include "cache.h" |
| @@ -306,22 +310,81 @@ static void nfsd_shutdown_net(struct net *net) · 283 unmodified lines | ||
| 306 | 310 | nfsd_shutdown_generic(); |
| 307 | 311 | } |
| 308 | 312 | |
| 313 | +static 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 | + | |
| 332 | +out: | |
| 333 | + return NOTIFY_DONE; | |
| 334 | +} | |
| 335 | + | |
| 336 | +static struct notifier_block nfsd_inetaddr_notifier = { | |
| 337 | + .notifier_call = nfsd_inetaddr_event, | |
| 338 | +}; | |
| 339 | + | |
| 340 | +#if IS_ENABLED(CONFIG_IPV6) | |
| 341 | +static 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 | + | |
| 360 | +out: | |
| 361 | + return NOTIFY_DONE; | |
| 362 | +} | |
| 363 | + | |
| 364 | +static struct notifier_block nfsd_inet6addr_notifier = { | |
| 365 | + .notifier_call = nfsd_inet6addr_event, | |
| 366 | +}; | |
| 367 | +#endif | |
| 368 | + | |
| 309 | 369 | static void nfsd_last_thread(struct svc_serv *serv, struct net *net) |
| 310 | 370 | { |
| 311 | 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 | 378 | * write_ports can create the server without actually starting |
| 315 | 379 | * any threads--if we get shut down before any threads are |
| 316 | 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 | 384 | if (!nn->nfsd_net_up) |
| 320 | 385 | return; |
| 321 | − nfsd_shutdown_net(net); | |
| 322 | − | |
| 323 | − svc_rpcb_cleanup(serv, net); | |
| 324 | 386 | |
| 387 | + nfsd_shutdown_net(net); | |
| 325 | 388 | printk(KERN_WARNING "nfsd: last server has exited, flushing export " |
| 326 | 389 | "cache\n"); |
| 327 | 390 | nfsd_export_flush(net); |
| @@ -425,6 +488,10 @@ int nfsd_create_serv(struct net *net) · 97 unmodified lines | ||
| 425 | 488 | } |
| 426 | 489 | |
| 427 | 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 | 495 | do_gettimeofday(&nn->nfssvc_boot); /* record boot time */ |
| 429 | 496 | return 0; |
| 430 | 497 | } |
| @@ -65,7 +65,7 @@ struct nfsd4_callback { · 64 unmodified lines | ||
| 65 | 65 | struct nfs4_client *cb_clp; |
| 66 | 66 | u32 cb_minorversion; |
| 67 | 67 | struct rpc_message cb_msg; |
| 68 | − struct nfsd4_callback_ops *cb_ops; | |
| 68 | + const struct nfsd4_callback_ops *cb_ops; | |
| 69 | 69 | struct work_struct cb_work; |
| 70 | 70 | int cb_seq_status; |
| 71 | 71 | int cb_status; |
| @@ -599,7 +599,7 @@ extern void nfsd4_probe_callback(struct nfs4_client *clp); · 527 unmodified lines | ||
| 599 | 599 | extern void nfsd4_probe_callback_sync(struct nfs4_client *clp); |
| 600 | 600 | extern void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *); |
| 601 | 601 | extern 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); | |
| 603 | 603 | extern void nfsd4_run_cb(struct nfsd4_callback *cb); |
| 604 | 604 | extern int nfsd4_create_callback_queue(void); |
| 605 | 605 | extern void nfsd4_destroy_callback_queue(void); |
| @@ -8,6 +8,47 @@ · 7 unmodified lines | ||
| 8 | 8 | #define _NFSD_TRACE_H |
| 9 | 9 | |
| 10 | 10 | #include <linux/tracepoint.h> |
| 11 | +#include "nfsfh.h" | |
| 12 | + | |
| 13 | +DECLARE_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) \ | |
| 37 | +DEFINE_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 | + | |
| 44 | +DEFINE_NFSD_IO_EVENT(read_start); | |
| 45 | +DEFINE_NFSD_IO_EVENT(read_opened); | |
| 46 | +DEFINE_NFSD_IO_EVENT(read_io_done); | |
| 47 | +DEFINE_NFSD_IO_EVENT(read_done); | |
| 48 | +DEFINE_NFSD_IO_EVENT(write_start); | |
| 49 | +DEFINE_NFSD_IO_EVENT(write_opened); | |
| 50 | +DEFINE_NFSD_IO_EVENT(write_io_done); | |
| 51 | +DEFINE_NFSD_IO_EVENT(write_done); | |
| 11 | 52 | |
| 12 | 53 | #include "state.h" |
| 13 | 54 | |
| @@ -43,6 +43,7 @@ · 42 unmodified lines | ||
| 43 | 43 | |
| 44 | 44 | #include "nfsd.h" |
| 45 | 45 | #include "vfs.h" |
| 46 | +#include "trace.h" | |
| 46 | 47 | |
| 47 | 48 | #define NFSDDBG_FACILITY NFSDDBG_FILEOP |
| 48 | 49 | |
| @@ -997,16 +998,23 @@ __be32 nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, · 948 unmodified lines | ||
| 997 | 998 | struct raparms *ra; |
| 998 | 999 | __be32 err; |
| 999 | 1000 | |
| 1001 | + trace_read_start(rqstp, fhp, offset, vlen); | |
| 1000 | 1002 | err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file); |
| 1001 | 1003 | if (err) |
| 1002 | 1004 | return err; |
| 1003 | 1005 | |
| 1004 | 1006 | ra = nfsd_init_raparms(file); |
| 1007 | + | |
| 1008 | + trace_read_opened(rqstp, fhp, offset, vlen); | |
| 1005 | 1009 | err = nfsd_vfs_read(rqstp, file, offset, vec, vlen, count); |
| 1010 | + trace_read_io_done(rqstp, fhp, offset, vlen); | |
| 1011 | + | |
| 1006 | 1012 | if (ra) |
| 1007 | 1013 | nfsd_put_raparams(file, ra); |
| 1008 | 1014 | fput(file); |
| 1009 | 1015 | |
| 1016 | + trace_read_done(rqstp, fhp, offset, vlen); | |
| 1017 | + | |
| 1010 | 1018 | return err; |
| 1011 | 1019 | } |
| 1012 | 1020 | |
| @@ -1022,24 +1030,31 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, · 9 unmodified lines | ||
| 1022 | 1030 | { |
| 1023 | 1031 | __be32 err = 0; |
| 1024 | 1032 | |
| 1033 | + trace_write_start(rqstp, fhp, offset, vlen); | |
| 1034 | + | |
| 1025 | 1035 | if (file) { |
| 1026 | 1036 | err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry, |
| 1027 | 1037 | NFSD_MAY_WRITE|NFSD_MAY_OWNER_OVERRIDE); |
| 1028 | 1038 | if (err) |
| 1029 | 1039 | goto out; |
| 1040 | + trace_write_opened(rqstp, fhp, offset, vlen); | |
| 1030 | 1041 | err = nfsd_vfs_write(rqstp, fhp, file, offset, vec, vlen, cnt, |
| 1031 | 1042 | stablep); |
| 1043 | + trace_write_io_done(rqstp, fhp, offset, vlen); | |
| 1032 | 1044 | } else { |
| 1033 | 1045 | err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_WRITE, &file); |
| 1034 | 1046 | if (err) |
| 1035 | 1047 | goto out; |
| 1036 | 1048 | |
| 1049 | + trace_write_opened(rqstp, fhp, offset, vlen); | |
| 1037 | 1050 | if (cnt) |
| 1038 | 1051 | err = nfsd_vfs_write(rqstp, fhp, file, offset, vec, vlen, |
| 1039 | 1052 | cnt, stablep); |
| 1053 | + trace_write_io_done(rqstp, fhp, offset, vlen); | |
| 1040 | 1054 | fput(file); |
| 1041 | 1055 | } |
| 1042 | 1056 | out: |
| 1057 | + trace_write_done(rqstp, fhp, offset, vlen); | |
| 1043 | 1058 | return err; |
| 1044 | 1059 | } |
| 1045 | 1060 | |
| @@ -29,7 +29,7 @@ struct nlmsvc_binding { · 28 unmodified lines | ||
| 29 | 29 | void (*fclose)(struct file *); |
| 30 | 30 | }; |
| 31 | 31 | |
| 32 | −extern struct nlmsvc_binding * nlmsvc_ops; | |
| 32 | +extern const struct nlmsvc_binding *nlmsvc_ops; | |
| 33 | 33 | |
| 34 | 34 | /* |
| 35 | 35 | * Similar to nfs_client_initdata, but without the NFS-specific |
| @@ -128,6 +128,7 @@ struct svc_xprt *svc_find_xprt(struct svc_serv *serv, const char *xcl_name, · 127 unmodified lines | ||
| 128 | 128 | const unsigned short port); |
| 129 | 129 | int svc_xprt_names(struct svc_serv *serv, char *buf, const int buflen); |
| 130 | 130 | void svc_add_new_perm_xprt(struct svc_serv *serv, struct svc_xprt *xprt); |
| 131 | +void svc_age_temp_xprts_now(struct svc_serv *, struct sockaddr *); | |
| 131 | 132 | |
| 132 | 133 | static inline void svc_xprt_get(struct svc_xprt *xprt) |
| 133 | 134 | { |
| @@ -23,13 +23,19 @@ struct svc_cred { · 22 unmodified lines | ||
| 23 | 23 | kgid_t cr_gid; |
| 24 | 24 | struct group_info *cr_group_info; |
| 25 | 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 | 32 | struct gss_api_mech *cr_gss_mech; |
| 28 | 33 | }; |
| 29 | 34 | |
| 30 | 35 | static inline void init_svc_cred(struct svc_cred *cred) |
| 31 | 36 | { |
| 32 | 37 | cred->cr_group_info = NULL; |
| 38 | + cred->cr_raw_principal = NULL; | |
| 33 | 39 | cred->cr_principal = NULL; |
| 34 | 40 | cred->cr_gss_mech = NULL; |
| 35 | 41 | } |
| @@ -38,6 +44,7 @@ static inline void free_svc_cred(struct svc_cred *cred) · 2 unmodified lines | ||
| 38 | 44 | { |
| 39 | 45 | if (cred->cr_group_info) |
| 40 | 46 | put_group_info(cred->cr_group_info); |
| 47 | + kfree(cred->cr_raw_principal); | |
| 41 | 48 | kfree(cred->cr_principal); |
| 42 | 49 | gss_mech_put(cred->cr_gss_mech); |
| 43 | 50 | init_svc_cred(cred); |
| @@ -326,6 +326,9 @@ int gssp_accept_sec_context_upcall(struct net *net, · 325 unmodified lines | ||
| 326 | 326 | if (data->found_creds && client_name.data != NULL) { |
| 327 | 327 | char *c; |
| 328 | 328 | |
| 329 | + data->creds.cr_raw_principal = kstrndup(client_name.data, | |
| 330 | + client_name.len, GFP_KERNEL); | |
| 331 | + | |
| 329 | 332 | data->creds.cr_principal = kstrndup(client_name.data, |
| 330 | 333 | client_name.len, GFP_KERNEL); |
| 331 | 334 | if (data->creds.cr_principal) { |
| @@ -10,11 +10,13 @@ · 9 unmodified lines | ||
| 10 | 10 | #include <linux/kthread.h> |
| 11 | 11 | #include <linux/slab.h> |
| 12 | 12 | #include <net/sock.h> |
| 13 | +#include <linux/sunrpc/addr.h> | |
| 13 | 14 | #include <linux/sunrpc/stats.h> |
| 14 | 15 | #include <linux/sunrpc/svc_xprt.h> |
| 15 | 16 | #include <linux/sunrpc/svcsock.h> |
| 16 | 17 | #include <linux/sunrpc/xprt.h> |
| 17 | 18 | #include <linux/module.h> |
| 19 | +#include <linux/netdevice.h> | |
| 18 | 20 | #include <trace/events/sunrpc.h> |
| 19 | 21 | |
| 20 | 22 | #define RPCDBG_FACILITY RPCDBG_SVCXPRT |
| @@ -938,6 +940,49 @@ static void svc_age_temp_xprts(unsigned long closure) · 917 unmodified lines | ||
| 938 | 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 | + */ | |
| 949 | +void 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 | +} | |
| 984 | +EXPORT_SYMBOL_GPL(svc_age_temp_xprts_now); | |
| 985 | + | |
| 941 | 986 | static void call_xpt_users(struct svc_xprt *xprt) |
| 942 | 987 | { |
| 943 | 988 | struct svc_xpt_user *u; |
| @@ -55,6 +55,7 @@ svc_authenticate(struct svc_rqst *rqstp, __be32 *authp) · 54 unmodified lines | ||
| 55 | 55 | spin_unlock(&authtab_lock); |
| 56 | 56 | |
| 57 | 57 | rqstp->rq_auth_slack = 0; |
| 58 | + init_svc_cred(&rqstp->rq_cred); | |
| 58 | 59 | |
| 59 | 60 | rqstp->rq_authop = aops; |
| 60 | 61 | return aops->accept(rqstp, authp); |
| @@ -63,6 +64,7 @@ EXPORT_SYMBOL_GPL(svc_authenticate); · 2 unmodified lines | ||
| 63 | 64 | |
| 64 | 65 | int svc_set_client(struct svc_rqst *rqstp) |
| 65 | 66 | { |
| 67 | + rqstp->rq_client = NULL; | |
| 66 | 68 | return rqstp->rq_authop->set_client(rqstp); |
| 67 | 69 | } |
| 68 | 70 | EXPORT_SYMBOL_GPL(svc_set_client); |
| @@ -728,10 +728,6 @@ svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp) · 727 unmodified lines | ||
| 728 | 728 | struct kvec *resv = &rqstp->rq_res.head[0]; |
| 729 | 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 | 731 | if (argv->iov_len < 3*4) |
| 736 | 732 | return SVC_GARBAGE; |
| 737 | 733 | |
| @@ -794,10 +790,6 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp) · 56 unmodified lines | ||
| 794 | 790 | u32 slen, i; |
| 795 | 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 | 793 | if ((len -= 3*4) < 0) |
| 802 | 794 | return SVC_GARBAGE; |
| 803 | 795 | |