From owner-svn-src-head@FreeBSD.ORG Fri Dec 5 21:19:25 2008 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 50945106568A; Fri, 5 Dec 2008 21:19:25 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 400058FC23; Fri, 5 Dec 2008 21:19:25 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id mB5LJP6M073492; Fri, 5 Dec 2008 21:19:25 GMT (envelope-from jhb@svn.freebsd.org) Received: (from jhb@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id mB5LJPJp073491; Fri, 5 Dec 2008 21:19:25 GMT (envelope-from jhb@svn.freebsd.org) Message-Id: <200812052119.mB5LJPJp073491@svn.freebsd.org> From: John Baldwin Date: Fri, 5 Dec 2008 21:19:25 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r185652 - head/sys/libkern X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 05 Dec 2008 21:19:25 -0000 Author: jhb Date: Fri Dec 5 21:19:24 2008 New Revision: 185652 URL: http://svn.freebsd.org/changeset/base/185652 Log: Add simple locking for the in-kernel iconv code. Translation operations do not need any locking. Opening and closing translators is serialized using an sx lock. Note: This depends on the earlier fix to kern_module.c to properly order MOD_UNLOAD events. MFC after: 2 months Modified: head/sys/libkern/iconv.c Modified: head/sys/libkern/iconv.c ============================================================================== --- head/sys/libkern/iconv.c Fri Dec 5 21:17:54 2008 (r185651) +++ head/sys/libkern/iconv.c Fri Dec 5 21:19:24 2008 (r185652) @@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include "iconv_converter_if.h" @@ -52,6 +53,8 @@ MALLOC_DEFINE(M_ICONVDATA, "iconv_data", MODULE_VERSION(libiconv, 2); +static struct sx iconv_lock; + #ifdef notnow /* * iconv converter instance @@ -86,11 +89,16 @@ iconv_mod_unload(void) { struct iconv_cspair *csp; + sx_xlock(&iconv_lock); while ((csp = TAILQ_FIRST(&iconv_cslist)) != NULL) { if (csp->cp_refcount) return EBUSY; - iconv_unregister_cspair(csp); } + + while ((csp = TAILQ_FIRST(&iconv_cslist)) != NULL) + iconv_unregister_cspair(csp); + sx_xunlock(&iconv_lock); + sx_destroy(&iconv_lock); return 0; } @@ -102,6 +110,7 @@ iconv_mod_handler(module_t mod, int type switch (type) { case MOD_LOAD: error = 0; + sx_init(&iconv_lock, "iconv"); break; case MOD_UNLOAD: error = iconv_mod_unload(); @@ -311,7 +320,7 @@ iconv_sysctl_drvlist(SYSCTL_HANDLER_ARGS int error; error = 0; - + sx_slock(&iconv_lock); TAILQ_FOREACH(dcp, &iconv_converters, cc_link) { name = ICONV_CONVERTER_NAME(dcp); if (name == NULL) @@ -320,6 +329,7 @@ iconv_sysctl_drvlist(SYSCTL_HANDLER_ARGS if (error) break; } + sx_sunlock(&iconv_lock); if (error) return error; spc = 0; @@ -343,7 +353,7 @@ iconv_sysctl_cslist(SYSCTL_HANDLER_ARGS) error = 0; bzero(&csi, sizeof(csi)); csi.cs_version = ICONV_CSPAIR_INFO_VER; - + sx_slock(&iconv_lock); TAILQ_FOREACH(csp, &iconv_cslist, cp_link) { csi.cs_id = csp->cp_id; csi.cs_refcount = csp->cp_refcount; @@ -354,6 +364,7 @@ iconv_sysctl_cslist(SYSCTL_HANDLER_ARGS) if (error) break; } + sx_sunlock(&iconv_lock); return error; } @@ -387,9 +398,12 @@ iconv_sysctl_add(SYSCTL_HANDLER_ARGS) return EINVAL; if (iconv_lookupconv(din.ia_converter, &dcp) != 0) return EINVAL; + sx_xlock(&iconv_lock); error = iconv_register_cspair(din.ia_to, din.ia_from, dcp, NULL, &csp); - if (error) + if (error) { + sx_xunlock(&iconv_lock); return error; + } if (din.ia_datalen) { csp->cp_data = malloc(din.ia_datalen, M_ICONVDATA, M_WAITOK); error = copyin(din.ia_data, csp->cp_data, din.ia_datalen); @@ -400,10 +414,12 @@ iconv_sysctl_add(SYSCTL_HANDLER_ARGS) error = SYSCTL_OUT(req, &dout, sizeof(dout)); if (error) goto bad; + sx_xunlock(&iconv_lock); ICDEBUG("%s => %s, %d bytes\n",din.ia_from, din.ia_to, din.ia_datalen); return 0; bad: iconv_unregister_cspair(csp); + sx_xunlock(&iconv_lock); return error; } @@ -433,16 +449,22 @@ iconv_converter_handler(module_t mod, in switch (type) { case MOD_LOAD: + sx_xlock(&iconv_lock); error = iconv_register_converter(dcp); - if (error) + if (error) { + sx_xunlock(&iconv_lock); break; + } error = ICONV_CONVERTER_INIT(dcp); if (error) iconv_unregister_converter(dcp); + sx_xunlock(&iconv_lock); break; case MOD_UNLOAD: + sx_xlock(&iconv_lock); ICONV_CONVERTER_DONE(dcp); error = iconv_unregister_converter(dcp); + sx_xunlock(&iconv_lock); break; default: error = EINVAL;