diff options
| author | Jerry Jelinek <jerry.jelinek@joyent.com> | 2017-04-05 16:29:48 +0000 |
|---|---|---|
| committer | Jerry Jelinek <jerry.jelinek@joyent.com> | 2017-04-05 16:38:00 +0000 |
| commit | 59d73dcf2d9b389641c1b420dc1dc2db59257220 (patch) | |
| tree | 81b0d23ca5ab332d86f49435a5af9eb58797c4d0 | |
| parent | 84091937dcd347b6d3f6be0b707e956fe77a2a52 (diff) | |
| download | illumos-joyent-59d73dcf2d9b389641c1b420dc1dc2db59257220.tar.gz | |
OS-6018 NFSv3 interaction with Linux statd fails
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Approved by: Patrick Mooney <patrick.mooney@joyent.com>
| -rw-r--r-- | usr/src/uts/common/brand/lx/os/lx_brand.c | 4 | ||||
| -rw-r--r-- | usr/src/uts/common/brand/lx/os/lx_lockd.c (renamed from usr/src/uts/common/brand/lx/os/lx_start_lockd.c) | 107 | ||||
| -rw-r--r-- | usr/src/uts/common/brand/sn1/sn1_brand.c | 3 | ||||
| -rw-r--r-- | usr/src/uts/common/brand/solaris10/s10_brand.c | 3 | ||||
| -rw-r--r-- | usr/src/uts/common/klm/mapfile-mod | 6 | ||||
| -rw-r--r-- | usr/src/uts/common/klm/nlm_dispatch.c | 11 | ||||
| -rw-r--r-- | usr/src/uts/common/klm/nlm_impl.c | 25 | ||||
| -rw-r--r-- | usr/src/uts/common/sys/brand.h | 2 | ||||
| -rw-r--r-- | usr/src/uts/intel/Makefile.files | 2 | ||||
| -rw-r--r-- | usr/src/uts/intel/lx_brand/Makefile | 5 |
10 files changed, 151 insertions, 17 deletions
diff --git a/usr/src/uts/common/brand/lx/os/lx_brand.c b/usr/src/uts/common/brand/lx/os/lx_brand.c index 4dfa0bc69e..b6ecc856e7 100644 --- a/usr/src/uts/common/brand/lx/os/lx_brand.c +++ b/usr/src/uts/common/brand/lx/os/lx_brand.c @@ -210,6 +210,7 @@ extern void lx_socket_init(); extern void lx_socket_fini(); extern int lx_start_nfs_lockd(); +extern void lx_upcall_statd(); lx_systrace_f *lx_systrace_entry_ptr; lx_systrace_f *lx_systrace_return_ptr; @@ -305,7 +306,8 @@ struct brand_ops lx_brops = { NULL, #endif B_FALSE, /* b_intp_parse_arg */ - lx_clearbrand /* b_clearbrand */ + lx_clearbrand, /* b_clearbrand */ + lx_upcall_statd /* b_rpc_statd */ }; struct brand_mach_ops lx_mops = { diff --git a/usr/src/uts/common/brand/lx/os/lx_start_lockd.c b/usr/src/uts/common/brand/lx/os/lx_lockd.c index 727f715cfb..234e815d3f 100644 --- a/usr/src/uts/common/brand/lx/os/lx_start_lockd.c +++ b/usr/src/uts/common/brand/lx/os/lx_lockd.c @@ -14,8 +14,18 @@ */ /* - * Start an NFS lockd (lx_lockd) process inside the zone. This uses the same - * technique as used in our lx cgroupfs to launch a release agent process. + * lx_start_nfs_lockd() starts an NFS lockd (lx_lockd) process inside the zone. + * This uses the same technique as used in our lx cgroupfs to launch a release + * agent process. This is called implicitly when an NFS mount syscall occurs + * within the zone. See the user-level lx_lockd source for the "big theory" + * comment behind this. + * + * lx_upcall_statd() is a brand hook that interposes on the rpc.statd RPC + * handling so that we can interface to a Linux rpc.statd that must run + * when NFSv3 locking is in use. The rpc.statd handles server or client reboots + * and interacts with the lockd to reclaim locks after the server reboots. The + * rcp.statd also informs the server when we reboot, so the server can release + * the locks we held. */ #include <sys/types.h> @@ -35,9 +45,19 @@ #include <sys/brand.h> #include <sys/lx_brand.h> #include <sys/pathname.h> +#include <rpcsvc/nlm_prot.h> +#include <rpcsvc/sm_inter.h> +#include <klm/nlm_impl.h> #define LX_LOCKD_PATH "/native/usr/lib/brand/lx/lx_lockd" +/* Linux lockd RPC called by statd when it detects an NFS server reboot */ +#define LX_NLMPROC_NSM_NOTIFY 16 + +/* From uts/common/klm/nlm_impl.c */ +extern void nlm_netbuf_to_netobj(struct netbuf *, int *, netobj *); +extern void nlm_nsm_clnt_init(CLIENT *, struct nlm_nsm *); + /* * Check if the current lockd is still running. */ @@ -228,3 +248,86 @@ lx_start_nfs_lockd() */ return (newproc(lx_run_lockd, NULL, cid, minclsyspri - 1, NULL, -1)); } + +void +lx_upcall_statd(int op, struct nlm_globals *g, struct nlm_host *host) +{ + struct nlm_nsm *nsm; + struct mon args; + struct mon_id *mip = &args.mon_id; + int family; + netobj obj; + enum clnt_stat stat; + + /* + * For Linux rpc.statd monitor registration, the Linux NSMPROC_MON and + * NSMPROC_UNMON RPC upcalls correspond almost directly to the native + * SM_MON and SM_UNMON RPC upcalls. The key differences with the native + * registration is that in our nlm_host_monitor function we make two + * RPC calls: + * - the first RPC (nsmaddrproc1_reg_1) uses our private 'nsm_addr' + * RPC protocol to register the lockd RPC information that statd + * should call when it detects that the remote server rebooted + * - the second RPC (sm_mon_1) tells statd the information about the + * remote server to be monitored + * For Linux, there is only a single RPC from the kernel to the local + * statd. This RPC is equivalent to our sm_mon_1 code, but it uses the + * Linux-private NLMPROC_NSM_NOTIFY lockd procedure in the 'my_proc' + * RPC parameter. This corresponds to our private 'nsm_addr' code, and + * tells statd which lockd RPC to call when it detects a server reboot. + * + * Because our sm_mon_1 RPC is so similar to the Linux RPC, we can use + * that directly and simply set the expected value in the 'my_proc' + * argument. + * + * Within the kernel lockd RPC handling, the nlm_prog_3_dtable dispatch + * table has an entry for each lockd RPC function. Thus, this table also + * contains an entry for the Linux NLMPROC_NSM_NOTIFY procedure. That + * procedure number is unused by the native lockd code, so there is no + * conflict with dispatching that procedure. The implementation of the + * procedure corresponds to the native, private NLM_SM_NOTIFY1 + * procedure which is called by the native rpc.statd. + * + * The Linux RPC call to "unmonitor" a host expects the same arguments + * as we pass to monitor, so that is also handled here by this same + * brand hook. + */ + nlm_netbuf_to_netobj(&host->nh_addr, &family, &obj); + nsm = &g->nlm_nsm; + + bzero(&args, sizeof (args)); + + mip->mon_name = host->nh_name; + mip->my_id.my_name = uts_nodename(); + mip->my_id.my_prog = NLM_PROG; + mip->my_id.my_vers = NLM_SM; + mip->my_id.my_proc = LX_NLMPROC_NSM_NOTIFY; + if (op == SM_MON) { + bcopy(&host->nh_sysid, args.priv, sizeof (uint16_t)); + } + + sema_p(&nsm->ns_sem); + nlm_nsm_clnt_init(nsm->ns_handle, nsm); + if (op == SM_MON) { + struct sm_stat_res mres; + + bzero(&mres, sizeof (mres)); + stat = sm_mon_1(&args, &mres, nsm->ns_handle); + } else { + struct sm_stat ures; + + ASSERT(op == SM_UNMON); + bzero(&ures, sizeof (ures)); + stat = sm_unmon_1(mip, &ures, nsm->ns_handle); + } + sema_v(&nsm->ns_sem); + + if (stat != RPC_SUCCESS) { + NLM_WARN("Failed to contact local statd, stat=%d", stat); + if (op == SM_MON) { + mutex_enter(&g->lock); + host->nh_flags &= ~NLM_NH_MONITORED; + mutex_exit(&g->lock); + } + } +} diff --git a/usr/src/uts/common/brand/sn1/sn1_brand.c b/usr/src/uts/common/brand/sn1/sn1_brand.c index 5726beffa2..92c0aec1e0 100644 --- a/usr/src/uts/common/brand/sn1/sn1_brand.c +++ b/usr/src/uts/common/brand/sn1/sn1_brand.c @@ -103,7 +103,8 @@ struct brand_ops sn1_brops = { NULL, /* b_setid_clear */ NULL, /* b_pagefault */ B_TRUE, /* b_intp_parse_arg */ - NULL /* b_clearbrand */ + NULL, /* b_clearbrand */ + NULL /* b_rpc_statd */ }; #ifdef sparc diff --git a/usr/src/uts/common/brand/solaris10/s10_brand.c b/usr/src/uts/common/brand/solaris10/s10_brand.c index 6fb2ffd80d..c02fcdaef6 100644 --- a/usr/src/uts/common/brand/solaris10/s10_brand.c +++ b/usr/src/uts/common/brand/solaris10/s10_brand.c @@ -108,7 +108,8 @@ struct brand_ops s10_brops = { NULL, /* b_setid_clear */ NULL, /* b_pagefault */ B_TRUE, /* b_intp_parse_arg */ - NULL /* b_clearbrand */ + NULL, /* b_clearbrand */ + NULL /* b_rpc_statd */ }; #ifdef sparc diff --git a/usr/src/uts/common/klm/mapfile-mod b/usr/src/uts/common/klm/mapfile-mod index 0debe6d986..b7789d81fd 100644 --- a/usr/src/uts/common/klm/mapfile-mod +++ b/usr/src/uts/common/klm/mapfile-mod @@ -11,6 +11,7 @@ # # Copyright 2011 Nexenta Systems, Inc. All rights reserved. +# Copyright 2017 Joyent, Inc. # @@ -49,6 +50,11 @@ SYMBOL_SCOPE { nlm_frlock; nlm_register_lock_locally; nlm_shrlock; +# These four functions are available for use within a branded zone. + nlm_nsm_clnt_init; + nlm_netbuf_to_netobj; + sm_mon_1; + sm_unmon_1; local: *; diff --git a/usr/src/uts/common/klm/nlm_dispatch.c b/usr/src/uts/common/klm/nlm_dispatch.c index a0ca2a56c4..8fa9940eae 100644 --- a/usr/src/uts/common/klm/nlm_dispatch.c +++ b/usr/src/uts/common/klm/nlm_dispatch.c @@ -11,6 +11,7 @@ /* * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Joyent, Inc. All rights reserved. */ /* @@ -412,13 +413,13 @@ nlm_prog_3_dtable[] = { 0, 0 }, - { /* 16: not used */ - NLM_SVC_FUNC(0), - (xdrproc_t)0, - (xdrproc_t)0, + { /* 16: Linux NLMPROC_NSM_NOTIFY (same handling as NLM_SM_NOTIFY1) */ + NLM_SVC_FUNC(nlm_sm_notify1_2_svc), + (xdrproc_t)xdr_nlm_sm_status, + (xdrproc_t)xdr_void, NULL, 0, - 0 }, + NLM_DISP_NOREMOTE }, { /* 17: NLM_SM_NOTIFY1 */ NLM_SVC_FUNC(nlm_sm_notify1_2_svc), diff --git a/usr/src/uts/common/klm/nlm_impl.c b/usr/src/uts/common/klm/nlm_impl.c index 1e9033a17c..f283828013 100644 --- a/usr/src/uts/common/klm/nlm_impl.c +++ b/usr/src/uts/common/klm/nlm_impl.c @@ -28,6 +28,7 @@ /* * Copyright 2015 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2012 by Delphix. All rights reserved. + * Copyright 2017 Joyent, Inc. All rights reserved. */ /* @@ -57,6 +58,7 @@ #include <sys/queue.h> #include <sys/bitmap.h> #include <sys/sdt.h> +#include <sys/brand.h> #include <netinet/in.h> #include <rpc/rpc.h> @@ -202,6 +204,12 @@ static struct nlm_knc nlm_netconfigs[] = { /* (g) */ }; /* + * NLM functions which can be called by a brand hook. + */ +void nlm_netbuf_to_netobj(struct netbuf *, int *, netobj *); +void nlm_nsm_clnt_init(CLIENT *, struct nlm_nsm *); + +/* * NLM misc. function */ static void nlm_copy_netbuf(struct netbuf *, struct netbuf *); @@ -210,8 +218,6 @@ static void nlm_kmem_reclaim(void *); static void nlm_pool_shutdown(void); static void nlm_suspend_zone(struct nlm_globals *); static void nlm_resume_zone(struct nlm_globals *); -static void nlm_nsm_clnt_init(CLIENT *, struct nlm_nsm *); -static void nlm_netbuf_to_netobj(struct netbuf *, int *, netobj *); /* * NLM thread functions @@ -1839,6 +1845,12 @@ nlm_host_unmonitor(struct nlm_globals *g, struct nlm_host *host) return; host->nh_flags &= ~NLM_NH_MONITORED; + + if (ZONE_IS_BRANDED(curzone) && ZBROP(curzone)->b_rpc_statd != NULL) { + ZBROP(curzone)->b_rpc_statd(SM_UNMON, g, host); + return; + } + stat = nlm_nsm_unmon(&g->nlm_nsm, host->nh_name); if (stat != RPC_SUCCESS) { NLM_WARN("NLM: Failed to contact statd, stat=%d\n", stat); @@ -1877,6 +1889,11 @@ nlm_host_monitor(struct nlm_globals *g, struct nlm_host *host, int state) host->nh_flags |= NLM_NH_MONITORED; mutex_exit(&host->nh_lock); + if (ZONE_IS_BRANDED(curzone) && ZBROP(curzone)->b_rpc_statd != NULL) { + ZBROP(curzone)->b_rpc_statd(SM_MON, g, host); + return; + } + /* * Before we begin monitoring the host register the network address * associated with this hostname. @@ -2781,14 +2798,14 @@ nlm_cprresume(void) rw_exit(&lm_lck); } -static void +void nlm_nsm_clnt_init(CLIENT *clnt, struct nlm_nsm *nsm) { (void) clnt_tli_kinit(clnt, &nsm->ns_knc, &nsm->ns_addr, 0, NLM_RPC_RETRIES, kcred); } -static void +void nlm_netbuf_to_netobj(struct netbuf *addr, int *family, netobj *obj) { /* LINTED pointer alignment */ diff --git a/usr/src/uts/common/sys/brand.h b/usr/src/uts/common/sys/brand.h index cf22a0f509..e7d4fb894e 100644 --- a/usr/src/uts/common/sys/brand.h +++ b/usr/src/uts/common/sys/brand.h @@ -150,6 +150,7 @@ struct execa; * b_pagefault - Trap pagefault events * b_intp_parse_arg - Controls interpreter argument handling (allow 1 or all) * b_clearbrand - Perform any actions necessary when clearing the brand. + * b_rpc_statd - Upcall to rpc.statd running within the zone */ struct brand_ops { void (*b_init_brand_data)(zone_t *, kmutex_t *); @@ -200,6 +201,7 @@ struct brand_ops { enum seg_rw); boolean_t b_intp_parse_arg; void (*b_clearbrand)(proc_t *, boolean_t); + void (*b_rpc_statd)(int, void *, void *); }; /* diff --git a/usr/src/uts/intel/Makefile.files b/usr/src/uts/intel/Makefile.files index b45d1a1539..a1bca02510 100644 --- a/usr/src/uts/intel/Makefile.files +++ b/usr/src/uts/intel/Makefile.files @@ -334,7 +334,7 @@ LX_BRAND_OBJS = \ lx_mkdir.o \ lx_modify_ldt.o \ lx_mount.o \ - lx_start_lockd.o \ + lx_lockd.o \ lx_open.o \ lx_personality.o \ lx_pgrp.o \ diff --git a/usr/src/uts/intel/lx_brand/Makefile b/usr/src/uts/intel/lx_brand/Makefile index b0a4e96412..819c22566c 100644 --- a/usr/src/uts/intel/lx_brand/Makefile +++ b/usr/src/uts/intel/lx_brand/Makefile @@ -21,7 +21,7 @@ # # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. -# Copyright 2016 Joyent, Inc. +# Copyright 2017 Joyent, Inc. # # This makefile drives the production of the kernel component of # the lx brand @@ -68,7 +68,8 @@ AS_INC_PATH += -I$(UTSBASE)/i86pc/genassym/$(OBJS_DIR) # CFLAGS += $(CCVERBOSE) -LDFLAGS += -dy -Nexec/elfexec -Nfs/fifofs -Nfs/sockfs -Ndrv/ip -Nfs/zfs +LDFLAGS += -dy -Nexec/elfexec -Nfs/fifofs -Nfs/sockfs -Ndrv/ip \ + -Nfs/zfs -Nmisc/klmmod # # For now, disable these lint checks; maintainers should endeavor |
