Mercurial > illumos > illumos-gate
changeset 13931:3f18ae9d8c98
3502 panic in smb_server_shutdown (sl_count assertion)
Reviewed by: Gordon Ross <gwr@nexenta.com>
Reviewed by: Dan McDonald <danmcd@nexenta.com>
Approved by: Richard Lowe <richlowe@richlowe.net>
author | Kevin Crowe <kevin.crowe@nexenta.com> |
---|---|
date | Tue, 17 Jul 2012 12:40:19 -0400 |
parents | f2303e5259ca |
children | b74723e0c05f |
files | usr/src/uts/common/fs/smbsrv/smb_kshare.c usr/src/uts/common/fs/smbsrv/smb_server.c |
diffstat | 2 files changed, 39 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/fs/smbsrv/smb_kshare.c Tue Feb 15 21:27:02 2011 -0500 +++ b/usr/src/uts/common/fs/smbsrv/smb_kshare.c Tue Jul 17 12:40:19 2012 -0400 @@ -21,6 +21,7 @@ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012 Nexenta Systems, Inc. All rights reserved. */ #include <smbsrv/smb_door.h> @@ -60,6 +61,9 @@ smb_kshare_destroy }; +extern int smb_server_lookup(smb_server_t **); +extern void smb_server_release(smb_server_t *); + /* * This function is not MultiThread safe. The caller has to make sure only one * thread calls this function. @@ -347,22 +351,35 @@ int smb_kshare_export_list(smb_ioc_share_t *ioc) { - nvlist_t *shrlist; + nvlist_t *shrlist = NULL; nvlist_t *share; nvpair_t *nvp; smb_kshare_t *shr; char *shrname; - int rc; + int rc = 0; + smb_server_t *sv = NULL; if (!smb_export_isready()) return (ENOTACTIVE); + if ((rc = smb_server_lookup(&sv)) != 0) + return (rc); + if ((rc = nvlist_unpack(ioc->shr, ioc->shrlen, &shrlist, KM_SLEEP)) != 0) - return (rc); + goto out; for (nvp = nvlist_next_nvpair(shrlist, NULL); nvp != NULL; nvp = nvlist_next_nvpair(shrlist, nvp)) { + + /* + * Since this loop can run for a while we want to exit + * as soon as the server state is anything but RUNNING + * to allow shutdown to proceed. + */ + if (sv->sv_state != SMB_SERVER_STATE_RUNNING) + goto out; + if (nvpair_type(nvp) != DATA_TYPE_NVLIST) continue; @@ -381,14 +398,19 @@ continue; } + /* smb_kshare_export consumes shr so it's not leaked */ if ((rc = smb_kshare_export(shr)) != 0) { smb_kshare_destroy(shr); continue; } } + rc = 0; - nvlist_free(shrlist); - return (0); +out: + if (shrlist != NULL) + nvlist_free(shrlist); + smb_server_release(sv); + return (rc); } /*
--- a/usr/src/uts/common/fs/smbsrv/smb_server.c Tue Feb 15 21:27:02 2011 -0500 +++ b/usr/src/uts/common/fs/smbsrv/smb_server.c Tue Jul 17 12:40:19 2012 -0400 @@ -230,8 +230,8 @@ static void smb_server_kstat_init(smb_server_t *); static void smb_server_kstat_fini(smb_server_t *); static void smb_server_timers(smb_thread_t *, void *); -static int smb_server_lookup(smb_server_t **); -static void smb_server_release(smb_server_t *); +int smb_server_lookup(smb_server_t **); +void smb_server_release(smb_server_t *); static void smb_server_store_cfg(smb_server_t *, smb_ioc_cfg_t *); static void smb_server_shutdown(smb_server_t *); static int smb_server_fsop_start(smb_server_t *); @@ -1408,6 +1408,14 @@ smb_server_listener_stop(&sv->sv_tcp_daemon); if (sv->sv_session != NULL) { + /* + * smb_kshare_export may have a request on here. + * Normal sessions do this in smb_session_cancel() + * but this is a "fake" session used only for the + * requests used by the kshare thread(s). + */ + smb_slist_wait_for_empty(&sv->sv_session->s_req_list); + smb_session_delete(sv->sv_session); sv->sv_session = NULL; } @@ -1637,7 +1645,7 @@ * This function tries to find the server associated with the zone of the * caller. */ -static int +int smb_server_lookup(smb_server_t **psv) { zoneid_t zid; @@ -1673,7 +1681,7 @@ * This function decrements the reference count of the server and signals its * condition variable if the state of the server is SMB_SERVER_STATE_DELETING. */ -static void +void smb_server_release(smb_server_t *sv) { SMB_SERVER_VALID(sv);