CVS commit: src/sys/dev/pci
Module Name:src Committed By: yamaguchi Date: Tue Mar 29 01:57:51 UTC 2022 Modified Files: src/sys/dev/pci: if_vioif.c Log Message: vioif(4): Added a comment about stopping packet processing To generate a diff of this commit: cvs rdiff -u -r1.75 -r1.76 src/sys/dev/pci/if_vioif.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/dev/pci/if_vioif.c diff -u src/sys/dev/pci/if_vioif.c:1.75 src/sys/dev/pci/if_vioif.c:1.76 --- src/sys/dev/pci/if_vioif.c:1.75 Thu Mar 24 08:02:21 2022 +++ src/sys/dev/pci/if_vioif.c Tue Mar 29 01:57:51 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: if_vioif.c,v 1.75 2022/03/24 08:02:21 yamaguchi Exp $ */ +/* $NetBSD: if_vioif.c,v 1.76 2022/03/29 01:57:51 yamaguchi Exp $ */ /* * Copyright (c) 2020 The NetBSD Foundation, Inc. @@ -27,7 +27,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: if_vioif.c,v 1.75 2022/03/24 08:02:21 yamaguchi Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_vioif.c,v 1.76 2022/03/29 01:57:51 yamaguchi Exp $"); #ifdef _KERNEL_OPT #include "opt_net_mpsafe.h" @@ -1211,6 +1211,34 @@ vioif_init(struct ifnet *ifp) } static void +vioif_stop_rendezvous(struct vioif_softc *sc) +{ + struct vioif_txqueue *txq; + struct vioif_rxqueue *rxq; + int i; + + /* + * stop all packet processing: + * 1. acquire a lock for queue to wait + *for finish of interrupt handler + * 2. stop workqueue for packet processing + */ + + for (i =0; i < sc->sc_act_nvq_pairs; i++) { + txq = >sc_txq[i]; + rxq = >sc_rxq[i]; + + mutex_enter(rxq->rxq_lock); + mutex_exit(rxq->rxq_lock); + vioif_work_wait(sc->sc_txrx_workqueue, >rxq_work); + + mutex_enter(txq->txq_lock); + mutex_exit(txq->txq_lock); + vioif_work_wait(sc->sc_txrx_workqueue, >txq_work); + } +} + +static void vioif_stop(struct ifnet *ifp, int disable) { struct vioif_softc *sc = ifp->if_softc; @@ -1243,19 +1271,7 @@ vioif_stop(struct ifnet *ifp, int disabl /* only way to stop I/O and DMA is resetting... */ virtio_reset(vsc); - /* rendezvous for finish of handlers */ - for (i = 0; i < sc->sc_act_nvq_pairs; i++) { - txq = >sc_txq[i]; - rxq = >sc_rxq[i]; - - mutex_enter(rxq->rxq_lock); - mutex_exit(rxq->rxq_lock); - vioif_work_wait(sc->sc_txrx_workqueue, >rxq_work); - - mutex_enter(txq->txq_lock); - mutex_exit(txq->txq_lock); - vioif_work_wait(sc->sc_txrx_workqueue, >txq_work); - } + vioif_stop_rendezvous(sc); for (i = 0; i < sc->sc_act_nvq_pairs; i++) { vioif_rx_queue_clear(>sc_rxq[i]);
CVS commit: src/sys/dev/pci
Module Name:src Committed By: yamaguchi Date: Tue Mar 29 01:57:51 UTC 2022 Modified Files: src/sys/dev/pci: if_vioif.c Log Message: vioif(4): Added a comment about stopping packet processing To generate a diff of this commit: cvs rdiff -u -r1.75 -r1.76 src/sys/dev/pci/if_vioif.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Re: null-terminated vs. nul-terminated
On 2022-03-26 11:57, Roland Illig wrote: The term "null-terminated string" is quite common when talking about C. In contrast, the word "nul" in "nul-terminated" always reminds me of the character abbreviation in ASCII, which has a narrower scope than C. I prefer to keep "null-terminated" here. Hi all, While I don't really want to prolong this debate, as the committer who triggered this discussion, I felt I should respond, in part to explain why I made my choice (which I reverted, though I don't agree "null- terminated" is more correct). TL;DR: there is no consistency here in NetBSD's code base in man pages or comments in source code, and no applicable style guide I know of, but "NUL-terminated" is the most common form found. It seems there was also an attempt at standardization in man pages made in 2005-2006, settling on "nul-terminated". I was taught (several decades ago) that the short form for the null byte or null character was NUL in ANSI C parlance (not just ASCII), and that "null-terminated" was incorrect as it's ambiguous. If someone were to say "null-byte-terminated", "null-character-terminated", or for the other context "null-pointer-terminated", that would be fine. "NUL-terminated" was the unambiguous contraction. (As others have pointed out, a cleverer way to avoid this debate would be to use entirely different terms.) The most common form found in man pages at present installed in NetBSD -current is actually "NUL-terminated", by a significant margin. That's in part because many of those are from third-party projects, e.g., OpenBSD and OpenSSL, which standardized on that form. The next most common is "null-terminated", then (following slightly behind) "nul- terminated", then (much less commonly) "NULL-terminated" (which seems quite incorrect to me). I didn't look as closely at comments, but a similar pattern emerged, with "NUL-terminated" the most common under /usr/include, for example (in part due to the origins of some upstream code). (It's not my intent here to quote or debate exact statistics, so I haven't provided any. I'm sharing my perception of practice, rightly or wrongly.) "nul-terminated" and "null-terminated" seemed more common in man pages that originated from historical BSD sources, so, lacking any style guide, I inferred the lowercase "nul" was more "correct" as "BSD style" (excepting modern OpenBSD), even though that looks a bit odd to me. I then examined where "nul-terminated" came from, and found these bulk commits, which imply a standard. date: 2005-01-02 18:38:04 +; author: wiz; Mark up NULL, and replace null by nul where appropriate. date: 2006-10-16 08:48:45 +; author: wiz; nul/null/NULL cleanup: when talking about characters/bytes, use "nul" and "nul-terminate" when talking about pointers, use "null pointer" or ".Dv NULL" So that seemed to me the established style. Regards, Dave
CVS commit: src/distrib/sets/lists
Module Name:src Committed By: christos Date: Mon Mar 28 20:52:17 UTC 2022 Modified Files: src/distrib/sets/lists/debug: mi src/distrib/sets/lists/tests: mi Log Message: Add t_link To generate a diff of this commit: cvs rdiff -u -r1.373 -r1.374 src/distrib/sets/lists/debug/mi cvs rdiff -u -r1.1188 -r1.1189 src/distrib/sets/lists/tests/mi Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/distrib/sets/lists/debug/mi diff -u src/distrib/sets/lists/debug/mi:1.373 src/distrib/sets/lists/debug/mi:1.374 --- src/distrib/sets/lists/debug/mi:1.373 Wed Feb 23 22:35:33 2022 +++ src/distrib/sets/lists/debug/mi Mon Mar 28 16:52:17 2022 @@ -1,4 +1,4 @@ -# $NetBSD: mi,v 1.373 2022/02/24 03:35:33 mrg Exp $ +# $NetBSD: mi,v 1.374 2022/03/28 20:52:17 christos Exp $ ./etc/mtree/set.debug comp-sys-root ./usr/lib comp-sys-usr compatdir ./usr/lib/i18n/libBIG5_g.a comp-c-debuglib debuglib,compatfile @@ -1712,6 +1712,7 @@ ./usr/libdata/debug/usr/tests/fs/union/t_pr.debug tests-fs-debug debug,atf,rump ./usr/libdata/debug/usr/tests/fs/vfs/t_full.debug tests-fs-debug debug,atf,rump ./usr/libdata/debug/usr/tests/fs/vfs/t_io.debug tests-fs-debug debug,atf,rump +./usr/libdata/debug/usr/tests/fs/vfs/t_link.debug tests-fs-debug debug,atf,rump ./usr/libdata/debug/usr/tests/fs/vfs/t_mtime_otrunc.debug tests-fs-debug debug,atf,rump ./usr/libdata/debug/usr/tests/fs/vfs/t_mtime_write.debug tests-fs-debug debug,atf,rump ./usr/libdata/debug/usr/tests/fs/vfs/t_renamerace.debug tests-fs-debug debug,atf,rump Index: src/distrib/sets/lists/tests/mi diff -u src/distrib/sets/lists/tests/mi:1.1188 src/distrib/sets/lists/tests/mi:1.1189 --- src/distrib/sets/lists/tests/mi:1.1188 Sat Feb 12 08:17:57 2022 +++ src/distrib/sets/lists/tests/mi Mon Mar 28 16:52:17 2022 @@ -1,4 +1,4 @@ -# $NetBSD: mi,v 1.1188 2022/02/12 13:17:57 rillig Exp $ +# $NetBSD: mi,v 1.1189 2022/03/28 20:52:17 christos Exp $ # # Note: don't delete entries from here - mark them as "obsolete" instead. # @@ -1598,6 +1598,7 @@ ./usr/tests/fs/vfs/Kyuafiletests-fs-tests atf,rump,kyua ./usr/tests/fs/vfs/t_fulltests-fs-tests atf,rump ./usr/tests/fs/vfs/t_io tests-fs-tests atf,rump +./usr/tests/fs/vfs/t_linktests-fs-tests atf,rump ./usr/tests/fs/vfs/t_mtime_otrunc tests-fs-tests atf,rump ./usr/tests/fs/vfs/t_mtime_write tests-fs-tests atf,rump ./usr/tests/fs/vfs/t_renameracetests-fs-tests atf,rump
CVS commit: src/distrib/sets/lists
Module Name:src Committed By: christos Date: Mon Mar 28 20:52:17 UTC 2022 Modified Files: src/distrib/sets/lists/debug: mi src/distrib/sets/lists/tests: mi Log Message: Add t_link To generate a diff of this commit: cvs rdiff -u -r1.373 -r1.374 src/distrib/sets/lists/debug/mi cvs rdiff -u -r1.1188 -r1.1189 src/distrib/sets/lists/tests/mi Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/tests/fs/vfs
Module Name:src Committed By: christos Date: Mon Mar 28 20:51:04 UTC 2022 Modified Files: src/tests/fs/vfs: Makefile Added Files: src/tests/fs/vfs: t_link.c Log Message: Add a test for hardlink sysctl limiting. To generate a diff of this commit: cvs rdiff -u -r1.27 -r1.28 src/tests/fs/vfs/Makefile cvs rdiff -u -r0 -r1.1 src/tests/fs/vfs/t_link.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/tests/fs/vfs/Makefile diff -u src/tests/fs/vfs/Makefile:1.27 src/tests/fs/vfs/Makefile:1.28 --- src/tests/fs/vfs/Makefile:1.27 Mon Mar 2 06:09:13 2020 +++ src/tests/fs/vfs/Makefile Mon Mar 28 16:51:04 2022 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.27 2020/03/02 11:09:13 christos Exp $ +# $NetBSD: Makefile,v 1.28 2022/03/28 20:51:04 christos Exp $ # .include @@ -6,6 +6,7 @@ TESTSDIR= ${TESTSBASE}/fs/vfs WARNS= 4 +TESTS_C+= t_link TESTS_C+= t_full TESTS_C+= t_io TESTS_C+= t_renamerace @@ -19,6 +20,12 @@ TESTS_C+= t_mtime_write TESTS_C+= t_vfsops TESTS_C+= t_vnops + +.PATH: ${NETBSDSRCDIR}/lib/libc/gen +CPPFLAGS.sysctlbyname.c += -DRUMP_ACTION +CPPFLAGS.sysctlgetmibinfo.c += -DRUMP_ACTION +SRCS.t_link+= sysctlbyname.c sysctlgetmibinfo.c t_link.c + LDADD+=-lrumpnet_shmif -lrumpnet -lrumpnet_net -lrumpnet_netinet# TCP/IP LDADD+=-lrumpfs_nfs # NFS LDADD+=-lrumpfs_ext2fs # ext2fs Added files: Index: src/tests/fs/vfs/t_link.c diff -u /dev/null src/tests/fs/vfs/t_link.c:1.1 --- /dev/null Mon Mar 28 16:51:05 2022 +++ src/tests/fs/vfs/t_link.c Mon Mar 28 16:51:04 2022 @@ -0,0 +1,150 @@ +/* $NetBSD: t_link.c,v 1.1 2022/03/28 20:51:04 christos Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *notice, this list of conditions and the following disclaimer in the + *documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "../common/h_fsmacros.h" +#include "h_macros.h" + +#define USES_OWNER \ + if (FSTYPE_MSDOS(tc)) \ + atf_tc_skip("owner not supported by file system") + + +static void +hardlink(const atf_tc_t *tc, const char *mp, uid_t u1, uid_t u2, +bool sysctl, bool allowed) +{ + const char name[] = "foo"; + const char link[] = "bar"; + int one = 1, fd; + + USES_OWNER; + + FSTEST_ENTER(); + + if (sysctl) { + if (sysctlbyname( + "security.models.extensions.hardlink_check_uid", + NULL, 0, , sizeof(one)) == -1) + atf_tc_fail_errno("sysctlbyname"); + } + + rump_pub_lwproc_rfork(RUMP_RFCFDG); + if (rump_sys_chmod(".", 0777) == -1) + atf_tc_fail_errno("chmod"); + if (rump_sys_setuid(u1) == -1) + atf_tc_fail_errno("setuid"); +if ((fd = rump_sys_open(name, O_RDWR|O_CREAT, 0666)) == -1) + atf_tc_fail_errno("open"); + if (rump_sys_close(fd) == -1) + atf_tc_fail_errno("close"); + rump_pub_lwproc_releaselwp(); + + rump_pub_lwproc_rfork(RUMP_RFCFDG); + if (rump_sys_setuid(u2) == -1) + atf_tc_fail_errno("setuid"); +if (rump_sys_link(name, link) == -1) { + if (allowed) + atf_tc_fail_errno("link"); + } else { + if (!allowed) + atf_tc_fail("failed to disallow hard link"); + } + rump_pub_lwproc_releaselwp(); + + FSTEST_EXIT(); +} + + +static void +hardlink_sameuser(const atf_tc_t *tc, const char *mp) +{ + hardlink(tc, mp, 1, 1, false, true); +} + +static void +hardlink_sameuser_sysctl(const atf_tc_t *tc, const char *mp) +{ + hardlink(tc, mp, 1, 1, true, true); +} + +static void +hardlink_otheruser(const atf_tc_t *tc, const char *mp) +{ + hardlink(tc, mp, 1, 2, false, true); +} + +static void +hardlink_otheruser_sysctl(const atf_tc_t *tc, const char *mp) +{ + hardlink(tc,
CVS commit: src/tests/fs/vfs
Module Name:src Committed By: christos Date: Mon Mar 28 20:51:04 UTC 2022 Modified Files: src/tests/fs/vfs: Makefile Added Files: src/tests/fs/vfs: t_link.c Log Message: Add a test for hardlink sysctl limiting. To generate a diff of this commit: cvs rdiff -u -r1.27 -r1.28 src/tests/fs/vfs/Makefile cvs rdiff -u -r0 -r1.1 src/tests/fs/vfs/t_link.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/rump/librump/rumpkern
Module Name:src Committed By: christos Date: Mon Mar 28 20:49:52 UTC 2022 Modified Files: src/sys/rump/librump/rumpkern: Makefile.rumpkern Log Message: include the extensions secmodel To generate a diff of this commit: cvs rdiff -u -r1.187 -r1.188 src/sys/rump/librump/rumpkern/Makefile.rumpkern Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/rump/librump/rumpkern
Module Name:src Committed By: christos Date: Mon Mar 28 20:49:52 UTC 2022 Modified Files: src/sys/rump/librump/rumpkern: Makefile.rumpkern Log Message: include the extensions secmodel To generate a diff of this commit: cvs rdiff -u -r1.187 -r1.188 src/sys/rump/librump/rumpkern/Makefile.rumpkern Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/rump/librump/rumpkern/Makefile.rumpkern diff -u src/sys/rump/librump/rumpkern/Makefile.rumpkern:1.187 src/sys/rump/librump/rumpkern/Makefile.rumpkern:1.188 --- src/sys/rump/librump/rumpkern/Makefile.rumpkern:1.187 Thu Aug 27 10:11:57 2020 +++ src/sys/rump/librump/rumpkern/Makefile.rumpkern Mon Mar 28 16:49:52 2022 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile.rumpkern,v 1.187 2020/08/27 14:11:57 riastradh Exp $ +# $NetBSD: Makefile.rumpkern,v 1.188 2022/03/28 20:49:52 christos Exp $ # IOCONFDIR:= ${.PARSEDIR} @@ -20,6 +20,7 @@ MAN= rump.3 rump_lwproc.3 ${RUMPTOP}/../crypto/cprng_fast\ ${RUMPTOP}/../crypto/nist_hash_drbg \ ${RUMPTOP}/../secmodel \ + ${RUMPTOP}/../secmodel/extensions \ ${RUMPTOP}/../secmodel/suser\ ${RUMPTOP}/../compat/common @@ -145,6 +146,7 @@ SRCS+= uvm_page_array.c uvm_page_status. # 4.4BSD secmodel. selection is hardcoded for now SRCS+= secmodel.c SRCS+= secmodel_suser.c +SRCS+= secmodel_extensions.c # the funny bit. this doesn't really belong here, but helps with the # needs of kern_descrip.c. And since it's a fully dynamic interface,
CVS commit: src/sys/rump/librump/rumpkern
Module Name:src Committed By: christos Date: Mon Mar 28 20:49:32 UTC 2022 Modified Files: src/sys/rump/librump/rumpkern: rump.c Log Message: no need to include suser; it gets autoloaded as a module. To generate a diff of this commit: cvs rdiff -u -r1.354 -r1.355 src/sys/rump/librump/rumpkern/rump.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/rump/librump/rumpkern
Module Name:src Committed By: christos Date: Mon Mar 28 20:49:32 UTC 2022 Modified Files: src/sys/rump/librump/rumpkern: rump.c Log Message: no need to include suser; it gets autoloaded as a module. To generate a diff of this commit: cvs rdiff -u -r1.354 -r1.355 src/sys/rump/librump/rumpkern/rump.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/rump/librump/rumpkern/rump.c diff -u src/sys/rump/librump/rumpkern/rump.c:1.354 src/sys/rump/librump/rumpkern/rump.c:1.355 --- src/sys/rump/librump/rumpkern/rump.c:1.354 Mon Mar 28 08:38:59 2022 +++ src/sys/rump/librump/rumpkern/rump.c Mon Mar 28 16:49:32 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: rump.c,v 1.354 2022/03/28 12:38:59 riastradh Exp $ */ +/* $NetBSD: rump.c,v 1.355 2022/03/28 20:49:32 christos Exp $ */ /* * Copyright (c) 2007-2011 Antti Kantee. All Rights Reserved. @@ -26,7 +26,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: rump.c,v 1.354 2022/03/28 12:38:59 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rump.c,v 1.355 2022/03/28 20:49:32 christos Exp $"); #include #define ELFSIZE ARCH_ELFSIZE @@ -85,8 +85,6 @@ __KERNEL_RCSID(0, "$NetBSD: rump.c,v 1.3 #include -#include - #include #include
CVS commit: src/games/cgram
Module Name:src Committed By: rillig Date: Mon Mar 28 20:00:29 UTC 2022 Modified Files: src/games/cgram: cgram.c Log Message: cgram: define a word as a sequence of letters, not non-whitespace Pressing Tab or Shift+Tab now advances to the next letter that could be substituted, it no longer stops at punctuation or digits. Since only letters are scrambled, these are most interesting to be edited. To generate a diff of this commit: cvs rdiff -u -r1.26 -r1.27 src/games/cgram/cgram.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/games/cgram/cgram.c diff -u src/games/cgram/cgram.c:1.26 src/games/cgram/cgram.c:1.27 --- src/games/cgram/cgram.c:1.26 Fri Oct 29 11:45:39 2021 +++ src/games/cgram/cgram.c Mon Mar 28 20:00:29 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: cgram.c,v 1.26 2021/10/29 11:45:39 nia Exp $ */ +/* $NetBSD: cgram.c,v 1.27 2022/03/28 20:00:29 rillig Exp $ */ /*- * Copyright (c) 2013, 2021 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include #if defined(__RCSID) && !defined(lint) -__RCSID("$NetBSD: cgram.c,v 1.26 2021/10/29 11:45:39 nia Exp $"); +__RCSID("$NetBSD: cgram.c,v 1.27 2022/03/28 20:00:29 rillig Exp $"); #endif #include @@ -48,12 +48,6 @@ __RCSID("$NetBSD: cgram.c,v 1.26 2021/10 static bool -ch_isspace(char ch) -{ - return isspace((unsigned char)ch) != 0; -} - -static bool ch_islower(char ch) { return ch >= 'a' && ch <= 'z'; @@ -451,20 +445,20 @@ go_right(void) static void go_to_prev_word(void) { - while (can_go_left() && ch_isspace(char_left_of_cursor())) + while (can_go_left() && !ch_isalpha(char_left_of_cursor())) go_left(); - while (can_go_left() && !ch_isspace(char_left_of_cursor())) + while (can_go_left() && ch_isalpha(char_left_of_cursor())) go_left(); } static void go_to_next_word(void) { - while (can_go_right() && !ch_isspace(char_at_cursor())) + while (can_go_right() && ch_isalpha(char_at_cursor())) go_right(); - while (can_go_right() && ch_isspace(char_at_cursor())) + while (can_go_right() && !ch_isalpha(char_at_cursor())) go_right(); }
CVS commit: src/games/cgram
Module Name:src Committed By: rillig Date: Mon Mar 28 20:00:29 UTC 2022 Modified Files: src/games/cgram: cgram.c Log Message: cgram: define a word as a sequence of letters, not non-whitespace Pressing Tab or Shift+Tab now advances to the next letter that could be substituted, it no longer stops at punctuation or digits. Since only letters are scrambled, these are most interesting to be edited. To generate a diff of this commit: cvs rdiff -u -r1.26 -r1.27 src/games/cgram/cgram.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/arch/arm/cortex
Module Name:src Committed By: riastradh Date: Mon Mar 28 19:59:36 UTC 2022 Modified Files: src/sys/arch/arm/cortex: gicv3.c Log Message: arm/cortex: Use container_of, not bespoke offsetof arithmetic. To generate a diff of this commit: cvs rdiff -u -r1.49 -r1.50 src/sys/arch/arm/cortex/gicv3.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/arch/arm/cortex/gicv3.c diff -u src/sys/arch/arm/cortex/gicv3.c:1.49 src/sys/arch/arm/cortex/gicv3.c:1.50 --- src/sys/arch/arm/cortex/gicv3.c:1.49 Sat Oct 2 20:52:09 2021 +++ src/sys/arch/arm/cortex/gicv3.c Mon Mar 28 19:59:35 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: gicv3.c,v 1.49 2021/10/02 20:52:09 skrll Exp $ */ +/* $NetBSD: gicv3.c,v 1.50 2022/03/28 19:59:35 riastradh Exp $ */ /*- * Copyright (c) 2018 Jared McNeill @@ -32,7 +32,7 @@ #define _INTR_PRIVATE #include -__KERNEL_RCSID(0, "$NetBSD: gicv3.c,v 1.49 2021/10/02 20:52:09 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: gicv3.c,v 1.50 2022/03/28 19:59:35 riastradh Exp $"); #include #include @@ -58,9 +58,9 @@ __KERNEL_RCSID(0, "$NetBSD: gicv3.c,v 1. #endif #define PICTOSOFTC(pic) \ - ((void *)((uintptr_t)(pic) - offsetof(struct gicv3_softc, sc_pic))) + container_of(pic, struct gicv3_softc, sc_pic) #define LPITOSOFTC(lpi) \ - ((void *)((uintptr_t)(lpi) - offsetof(struct gicv3_softc, sc_lpi))) + container_of(lpi, struct gicv3_softc, sc_lpi) #define IPL_TO_PRIORITY(sc, ipl) (((0xff - (ipl)) << (sc)->sc_priority_shift) & 0xff) #define IPL_TO_PMR(sc, ipl) (((0xff - (ipl)) << (sc)->sc_pmr_shift) & 0xff)
CVS commit: src/sys/arch/arm/cortex
Module Name:src Committed By: riastradh Date: Mon Mar 28 19:59:36 UTC 2022 Modified Files: src/sys/arch/arm/cortex: gicv3.c Log Message: arm/cortex: Use container_of, not bespoke offsetof arithmetic. To generate a diff of this commit: cvs rdiff -u -r1.49 -r1.50 src/sys/arch/arm/cortex/gicv3.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/arch/arm/apple
Module Name:src Committed By: riastradh Date: Mon Mar 28 19:59:26 UTC 2022 Modified Files: src/sys/arch/arm/apple: apple_intc.c Log Message: arm/apple: Use container_of, not bespoke offsetof arithmetic. Better type-safety this way. To generate a diff of this commit: cvs rdiff -u -r1.6 -r1.7 src/sys/arch/arm/apple/apple_intc.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/arch/arm/apple
Module Name:src Committed By: riastradh Date: Mon Mar 28 19:59:26 UTC 2022 Modified Files: src/sys/arch/arm/apple: apple_intc.c Log Message: arm/apple: Use container_of, not bespoke offsetof arithmetic. Better type-safety this way. To generate a diff of this commit: cvs rdiff -u -r1.6 -r1.7 src/sys/arch/arm/apple/apple_intc.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/arch/arm/apple/apple_intc.c diff -u src/sys/arch/arm/apple/apple_intc.c:1.6 src/sys/arch/arm/apple/apple_intc.c:1.7 --- src/sys/arch/arm/apple/apple_intc.c:1.6 Fri Nov 26 19:39:58 2021 +++ src/sys/arch/arm/apple/apple_intc.c Mon Mar 28 19:59:26 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: apple_intc.c,v 1.6 2021/11/26 19:39:58 skrll Exp $ */ +/* $NetBSD: apple_intc.c,v 1.7 2022/03/28 19:59:26 riastradh Exp $ */ /*- * Copyright (c) 2021 Jared McNeill @@ -32,7 +32,7 @@ #define _INTR_PRIVATE #include -__KERNEL_RCSID(0, "$NetBSD: apple_intc.c,v 1.6 2021/11/26 19:39:58 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: apple_intc.c,v 1.7 2022/03/28 19:59:26 riastradh Exp $"); #include #include @@ -112,10 +112,8 @@ struct apple_intc_softc { static struct apple_intc_softc *intc_softc; -#define PICTOSOFTC(pic) \ - ((void *)((uintptr_t)(pic) - offsetof(struct apple_intc_softc, sc_pic))) -#define PICTOPERCPU(pic) \ - ((void *)((uintptr_t)(pic) - offsetof(struct apple_intc_percpu, pc_pic))) +#define PICTOSOFTC(pic) container_of(pic, struct apple_intc_softc, sc_pic) +#define PICTOPERCPU(pic) container_of(pic, struct apple_intc_percpu, pc_pic) #define AIC_READ(sc, reg) \ bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
CVS commit: src/sys/secmodel/extensions
Module Name:src Committed By: rillig Date: Mon Mar 28 19:08:43 UTC 2022 Modified Files: src/sys/secmodel/extensions: secmodel_extensions.c Log Message: secmodel: fix grammar in description of hardlink_check_gid To generate a diff of this commit: cvs rdiff -u -r1.13 -r1.14 src/sys/secmodel/extensions/secmodel_extensions.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/secmodel/extensions/secmodel_extensions.c diff -u src/sys/secmodel/extensions/secmodel_extensions.c:1.13 src/sys/secmodel/extensions/secmodel_extensions.c:1.14 --- src/sys/secmodel/extensions/secmodel_extensions.c:1.13 Sun Mar 27 16:28:35 2022 +++ src/sys/secmodel/extensions/secmodel_extensions.c Mon Mar 28 19:08:43 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: secmodel_extensions.c,v 1.13 2022/03/27 16:28:35 christos Exp $ */ +/* $NetBSD: secmodel_extensions.c,v 1.14 2022/03/28 19:08:43 rillig Exp $ */ /*- * Copyright (c) 2011 Elad Efrat * All rights reserved. @@ -27,7 +27,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: secmodel_extensions.c,v 1.13 2022/03/27 16:28:35 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: secmodel_extensions.c,v 1.14 2022/03/28 19:08:43 rillig Exp $"); #include #include @@ -167,7 +167,7 @@ SYSCTL_SETUP(sysctl_security_extensions_ CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, "hardlink_check_gid", SYSCTL_DESCR("Whether unprivileged users can hardlink "\ - "to files they that they are not in their " \ + "to files that are not in their " \ "group membership"), sysctl_extensions_user_handler, 0, _check_gid, 0,
CVS commit: src/sys/secmodel/extensions
Module Name:src Committed By: rillig Date: Mon Mar 28 19:08:43 UTC 2022 Modified Files: src/sys/secmodel/extensions: secmodel_extensions.c Log Message: secmodel: fix grammar in description of hardlink_check_gid To generate a diff of this commit: cvs rdiff -u -r1.13 -r1.14 src/sys/secmodel/extensions/secmodel_extensions.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/dev/raidframe
Module Name:src Committed By: wiz Date: Mon Mar 28 13:07:14 UTC 2022 Modified Files: src/sys/dev/raidframe: rf_netbsdkintf.c Log Message: Restore another historic RCS Id. To generate a diff of this commit: cvs rdiff -u -r1.404 -r1.405 src/sys/dev/raidframe/rf_netbsdkintf.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/dev/raidframe/rf_netbsdkintf.c diff -u src/sys/dev/raidframe/rf_netbsdkintf.c:1.404 src/sys/dev/raidframe/rf_netbsdkintf.c:1.405 --- src/sys/dev/raidframe/rf_netbsdkintf.c:1.404 Mon Mar 28 12:33:21 2022 +++ src/sys/dev/raidframe/rf_netbsdkintf.c Mon Mar 28 13:07:14 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: rf_netbsdkintf.c,v 1.404 2022/03/28 12:33:21 riastradh Exp $ */ +/* $NetBSD: rf_netbsdkintf.c,v 1.405 2022/03/28 13:07:14 wiz Exp $ */ /*- * Copyright (c) 1996, 1997, 1998, 2008-2011 The NetBSD Foundation, Inc. @@ -62,7 +62,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * from: Utah $Hdr$ + * from: Utah $Hdr: cd.c 1.6 90/11/28$ * * @(#)cd.c8.2 (Berkeley) 11/16/93 */ @@ -101,7 +101,7 @@ ***/ #include -__KERNEL_RCSID(0, "$NetBSD: rf_netbsdkintf.c,v 1.404 2022/03/28 12:33:21 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rf_netbsdkintf.c,v 1.405 2022/03/28 13:07:14 wiz Exp $"); #ifdef _KERNEL_OPT #include "opt_raid_autoconfig.h"
CVS commit: src/sys/dev/raidframe
Module Name:src Committed By: wiz Date: Mon Mar 28 13:07:14 UTC 2022 Modified Files: src/sys/dev/raidframe: rf_netbsdkintf.c Log Message: Restore another historic RCS Id. To generate a diff of this commit: cvs rdiff -u -r1.404 -r1.405 src/sys/dev/raidframe/rf_netbsdkintf.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/arch/sandpoint/conf
Module Name:src Committed By: martin Date: Mon Mar 28 12:48:44 UTC 2022 Modified Files: src/sys/arch/sandpoint/conf: INSTALL Log Message: Provide a bit more space for the ramdisk image (which recently did grow) To generate a diff of this commit: cvs rdiff -u -r1.9 -r1.10 src/sys/arch/sandpoint/conf/INSTALL Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/arch/sandpoint/conf/INSTALL diff -u src/sys/arch/sandpoint/conf/INSTALL:1.9 src/sys/arch/sandpoint/conf/INSTALL:1.10 --- src/sys/arch/sandpoint/conf/INSTALL:1.9 Sun Aug 10 17:58:51 2014 +++ src/sys/arch/sandpoint/conf/INSTALL Mon Mar 28 12:48:44 2022 @@ -1,4 +1,4 @@ -# $NetBSD: INSTALL,v 1.9 2014/08/10 17:58:51 joerg Exp $ +# $NetBSD: INSTALL,v 1.10 2022/03/28 12:48:44 martin Exp $ # # GENERIC install kernel for SandPoint NAS # @@ -7,7 +7,7 @@ include "arch/sandpoint/conf/GENERIC" options MEMORY_DISK_HOOKS options MEMORY_DISK_IS_ROOT # Force root on RAM disk -options MEMORY_DISK_ROOT_SIZE=4600 # 2300KB +options MEMORY_DISK_ROOT_SIZE=4800 # 2400KB options MEMORY_DISK_RBFLAGS=RB_SINGLE # boot in single-user mode pseudo-device md
CVS commit: src/sys/arch/sandpoint/conf
Module Name:src Committed By: martin Date: Mon Mar 28 12:48:44 UTC 2022 Modified Files: src/sys/arch/sandpoint/conf: INSTALL Log Message: Provide a bit more space for the ramdisk image (which recently did grow) To generate a diff of this commit: cvs rdiff -u -r1.9 -r1.10 src/sys/arch/sandpoint/conf/INSTALL Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/dev
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:48:35 UTC 2022 Modified Files: src/sys/dev: ccd.c Log Message: sys/dev/ccd.c: Restore historic RCS id. This got munged accidentally by `git cvsexportcommit -k' -- taking that option out of my commitbomb script! To generate a diff of this commit: cvs rdiff -u -r1.188 -r1.189 src/sys/dev/ccd.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/dev/ccd.c diff -u src/sys/dev/ccd.c:1.188 src/sys/dev/ccd.c:1.189 --- src/sys/dev/ccd.c:1.188 Mon Mar 28 12:33:20 2022 +++ src/sys/dev/ccd.c Mon Mar 28 12:48:35 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: ccd.c,v 1.188 2022/03/28 12:33:20 riastradh Exp $ */ +/* $NetBSD: ccd.c,v 1.189 2022/03/28 12:48:35 riastradh Exp $ */ /*- * Copyright (c) 1996, 1997, 1998, 1999, 2007, 2009 The NetBSD Foundation, Inc. @@ -62,7 +62,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * from: Utah $Hdr$ + * from: Utah $Hdr: cd.c 1.6 90/11/28$ * * @(#)cd.c 8.2 (Berkeley) 11/16/93 */ @@ -88,7 +88,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ccd.c,v 1.188 2022/03/28 12:33:20 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ccd.c,v 1.189 2022/03/28 12:48:35 riastradh Exp $"); #include #include
CVS commit: src/sys/dev
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:48:35 UTC 2022 Modified Files: src/sys/dev: ccd.c Log Message: sys/dev/ccd.c: Restore historic RCS id. This got munged accidentally by `git cvsexportcommit -k' -- taking that option out of my commitbomb script! To generate a diff of this commit: cvs rdiff -u -r1.188 -r1.189 src/sys/dev/ccd.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:45:04 UTC 2022 Modified Files: src/sys/dev/usb: uatp.c Log Message: uatp(4): Use usbd_get/set_report for Geyser 3/4 reset. To generate a diff of this commit: cvs rdiff -u -r1.30 -r1.31 src/sys/dev/usb/uatp.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/dev/usb/uatp.c diff -u src/sys/dev/usb/uatp.c:1.30 src/sys/dev/usb/uatp.c:1.31 --- src/sys/dev/usb/uatp.c:1.30 Mon Mar 28 12:44:54 2022 +++ src/sys/dev/usb/uatp.c Mon Mar 28 12:45:04 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: uatp.c,v 1.30 2022/03/28 12:44:54 riastradh Exp $ */ +/* $NetBSD: uatp.c,v 1.31 2022/03/28 12:45:04 riastradh Exp $ */ /*- * Copyright (c) 2011-2014 The NetBSD Foundation, Inc. @@ -146,7 +146,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: uatp.c,v 1.30 2022/03/28 12:44:54 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uatp.c,v 1.31 2022/03/28 12:45:04 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -489,6 +489,7 @@ struct uatp_softc { device_t sc_dev; struct uhidev *sc_hdev; /* uhidev(9) parent. */ struct usbd_device *sc_udev; /* USB device. */ + struct usbd_interface *sc_iface0; /* Geyser 3/4 reset interface. */ device_t sc_wsmousedev; /* Attached wsmouse device. */ const struct uatp_parameters *sc_parameters; struct uatp_knobs sc_knobs; @@ -1295,19 +1296,12 @@ uatp_ioctl(void *v, unsigned long cmd, v static void geyser34_enable_raw_mode(struct uatp_softc *sc) { - struct usbd_device *udev = sc->sc_udev; - usb_device_request_t req; - usbd_status status; uint8_t report[GEYSER34_MODE_PACKET_SIZE]; - - req.bmRequestType = UT_READ_CLASS_INTERFACE; - req.bRequest = UR_GET_REPORT; - USETW2(req.wValue, UHID_FEATURE_REPORT, GEYSER34_MODE_REPORT_ID); - USETW(req.wIndex, GEYSER34_MODE_INTERFACE); - USETW(req.wLength, GEYSER34_MODE_PACKET_SIZE); + usbd_status status; DPRINTF(sc, UATP_DEBUG_RESET, ("get feature report\n")); - status = usbd_do_request(udev, , report); + status = usbd_get_report(sc->sc_iface0, UHID_FEATURE_REPORT, + GEYSER34_MODE_REPORT_ID, report, sizeof(report)); if (status != USBD_NORMAL_COMPLETION) { aprint_error_dev(uatp_dev(sc), "error reading feature report: %s\n", usbd_errstr(status)); @@ -1333,14 +1327,9 @@ geyser34_enable_raw_mode(struct uatp_sof report[0] = GEYSER34_RAW_MODE; - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UR_SET_REPORT; - USETW2(req.wValue, UHID_FEATURE_REPORT, GEYSER34_MODE_REPORT_ID); - USETW(req.wIndex, GEYSER34_MODE_INTERFACE); - USETW(req.wLength, GEYSER34_MODE_PACKET_SIZE); - DPRINTF(sc, UATP_DEBUG_RESET, ("set feature report\n")); - status = usbd_do_request(udev, , report); + status = usbd_set_report(sc->sc_iface0, UHID_FEATURE_REPORT, + GEYSER34_MODE_REPORT_ID, report, sizeof(report)); if (status != USBD_NORMAL_COMPLETION) { aprint_error_dev(uatp_dev(sc), "error writing feature report: %s\n", usbd_errstr(status)); @@ -1356,8 +1345,11 @@ geyser34_enable_raw_mode(struct uatp_sof static void geyser34_initialize(struct uatp_softc *sc) { + usbd_status err __diagused; DPRINTF(sc, UATP_DEBUG_MISC, ("initializing\n")); + err = usbd_device2interface_handle(sc->sc_udev, 0, >sc_iface0); + KASSERT(err == 0); /* always an interface 0 if attached */ geyser34_enable_raw_mode(sc); usb_init_task(>sc_reset_task, _reset_task, sc, 0); }
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:45:04 UTC 2022 Modified Files: src/sys/dev/usb: uatp.c Log Message: uatp(4): Use usbd_get/set_report for Geyser 3/4 reset. To generate a diff of this commit: cvs rdiff -u -r1.30 -r1.31 src/sys/dev/usb/uatp.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:44:55 UTC 2022 Modified Files: src/sys/dev/usb: uatp.c Log Message: uatp(4): Fix detach logic. Let wsmouse child decide whether it's in use or close if mandatory. If config_detach_children succeeds, this must no longer be open and we can commit to freeing everything. To generate a diff of this commit: cvs rdiff -u -r1.29 -r1.30 src/sys/dev/usb/uatp.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/dev/usb/uatp.c diff -u src/sys/dev/usb/uatp.c:1.29 src/sys/dev/usb/uatp.c:1.30 --- src/sys/dev/usb/uatp.c:1.29 Mon Mar 28 12:44:17 2022 +++ src/sys/dev/usb/uatp.c Mon Mar 28 12:44:54 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: uatp.c,v 1.29 2022/03/28 12:44:17 riastradh Exp $ */ +/* $NetBSD: uatp.c,v 1.30 2022/03/28 12:44:54 riastradh Exp $ */ /*- * Copyright (c) 2011-2014 The NetBSD Foundation, Inc. @@ -146,7 +146,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: uatp.c,v 1.29 2022/03/28 12:44:17 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uatp.c,v 1.30 2022/03/28 12:44:54 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -298,7 +298,7 @@ static void uatp_disable(void *); static int uatp_ioctl(void *, unsigned long, void *, int, struct lwp *); static void geyser34_enable_raw_mode(struct uatp_softc *); static void geyser34_initialize(struct uatp_softc *); -static int geyser34_finalize(struct uatp_softc *); +static void geyser34_finalize(struct uatp_softc *); static void geyser34_deferred_reset(struct uatp_softc *); static void geyser34_reset_task(void *); static void uatp_intr(void *, void *, unsigned int); @@ -553,8 +553,8 @@ struct uatp_parameters { /* Device-specific initialization routine. May be null. */ void (*initialize)(struct uatp_softc *); - /* Device-specific finalization routine. May be null. May fail. */ - int (*finalize)(struct uatp_softc *); + /* Device-specific finalization routine. May be null. */ + void (*finalize)(struct uatp_softc *); /* Tests whether this is a base sample. Second argument is * input_size bytes long. */ @@ -1182,19 +1182,18 @@ static int uatp_detach(device_t self, int flags) { struct uatp_softc *sc = device_private(self); + int error; DPRINTF(sc, UATP_DEBUG_MISC, ("detaching with flags %d\n", flags)); -if (sc->sc_status & UATP_ENABLED) { - aprint_error_dev(uatp_dev(sc), "can't detach while enabled\n"); - return EBUSY; -} + error = config_detach_children(self, flags); + if (error) + return error; - if (sc->sc_parameters->finalize) { - int error = sc->sc_parameters->finalize(sc); - if (error != 0) - return error; - } + KASSERT((sc->sc_status & UATP_ENABLED) == 0); + + if (sc->sc_parameters->finalize) + sc->sc_parameters->finalize(sc); pmf_device_deregister(self); @@ -1203,7 +1202,7 @@ uatp_detach(device_t self, int flags) tap_finalize(sc); - return config_detach_children(self, flags); + return 0; } static int @@ -1363,15 +1362,13 @@ geyser34_initialize(struct uatp_softc *s usb_init_task(>sc_reset_task, _reset_task, sc, 0); } -static int +static void geyser34_finalize(struct uatp_softc *sc) { DPRINTF(sc, UATP_DEBUG_MISC, ("finalizing\n")); usb_rem_task_wait(sc->sc_udev, >sc_reset_task, USB_TASKQ_DRIVER, NULL); - - return 0; } static void
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:44:55 UTC 2022 Modified Files: src/sys/dev/usb: uatp.c Log Message: uatp(4): Fix detach logic. Let wsmouse child decide whether it's in use or close if mandatory. If config_detach_children succeeds, this must no longer be open and we can commit to freeing everything. To generate a diff of this commit: cvs rdiff -u -r1.29 -r1.30 src/sys/dev/usb/uatp.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:44:45 UTC 2022 Modified Files: src/sys/dev/usb: uhidev.c Log Message: uhidev(9): Assert uhidev is open when writing. (Maybe we could have uhidevs that are output-only, in which case a driver could, in principle, want to issue writes without getting any input report interrupts. But we can cross that bridge when we come to it.) To generate a diff of this commit: cvs rdiff -u -r1.92 -r1.93 src/sys/dev/usb/uhidev.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/dev/usb/uhidev.c diff -u src/sys/dev/usb/uhidev.c:1.92 src/sys/dev/usb/uhidev.c:1.93 --- src/sys/dev/usb/uhidev.c:1.92 Mon Mar 28 12:44:37 2022 +++ src/sys/dev/usb/uhidev.c Mon Mar 28 12:44:45 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: uhidev.c,v 1.92 2022/03/28 12:44:37 riastradh Exp $ */ +/* $NetBSD: uhidev.c,v 1.93 2022/03/28 12:44:45 riastradh Exp $ */ /* * Copyright (c) 2001, 2012 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.92 2022/03/28 12:44:37 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.93 2022/03/28 12:44:45 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -1083,6 +1083,7 @@ uhidev_write(struct uhidev *scd, void *d mutex_enter(>sc_lock); KASSERT(sc->sc_refcnt); + KASSERT(scd->sc_state & UHIDEV_OPEN); for (;;) { if (scd->sc_state & UHIDEV_STOPPED) { err = USBD_CANCELLED; @@ -1116,6 +1117,7 @@ uhidev_write(struct uhidev *scd, void *d mutex_enter(>sc_lock); KASSERT(sc->sc_refcnt); + KASSERT(scd->sc_state & UHIDEV_OPEN); KASSERTMSG(sc->sc_writelock == curlwp, "%s: migrated from %p to %p", device_xname(sc->sc_dev), curlwp, sc->sc_writelock); KASSERTMSG(sc->sc_writereportid == scd->sc_report_id, @@ -1168,6 +1170,7 @@ uhidev_write_async(struct uhidev *scd, v mutex_enter(>sc_lock); KASSERT(sc->sc_refcnt); + KASSERT(scd->sc_state & UHIDEV_OPEN); if (scd->sc_state & UHIDEV_STOPPED) { err = USBD_CANCELLED; goto out;
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:44:45 UTC 2022 Modified Files: src/sys/dev/usb: uhidev.c Log Message: uhidev(9): Assert uhidev is open when writing. (Maybe we could have uhidevs that are output-only, in which case a driver could, in principle, want to issue writes without getting any input report interrupts. But we can cross that bridge when we come to it.) To generate a diff of this commit: cvs rdiff -u -r1.92 -r1.93 src/sys/dev/usb/uhidev.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:44:37 UTC 2022 Modified Files: src/sys/dev/usb: uhidev.c uhidev.h Log Message: uhidev(9): Define UHIDEV_MAXREPID = 255. Report ids are limited by the HID spec to a single byte. - Clamp max report id in report descriptor to this. - Prune dead refcnt-overflow error branches. Assert instead. To generate a diff of this commit: cvs rdiff -u -r1.91 -r1.92 src/sys/dev/usb/uhidev.c cvs rdiff -u -r1.26 -r1.27 src/sys/dev/usb/uhidev.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/dev/usb/uhidev.c diff -u src/sys/dev/usb/uhidev.c:1.91 src/sys/dev/usb/uhidev.c:1.92 --- src/sys/dev/usb/uhidev.c:1.91 Mon Mar 28 12:44:28 2022 +++ src/sys/dev/usb/uhidev.c Mon Mar 28 12:44:37 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: uhidev.c,v 1.91 2022/03/28 12:44:28 riastradh Exp $ */ +/* $NetBSD: uhidev.c,v 1.92 2022/03/28 12:44:37 riastradh Exp $ */ /* * Copyright (c) 2001, 2012 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.91 2022/03/28 12:44:28 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.92 2022/03/28 12:44:37 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -458,7 +458,7 @@ uhidev_maxrepid(void *buf, int len) if ((int)h.report_ID > maxid) maxid = h.report_ID; hid_end_parse(d); - return maxid; + return MIN(maxid, UHIDEV_MAXREPID); } static int @@ -671,11 +671,11 @@ uhidev_open_pipes(struct uhidev_softc *s /* * If the pipes are already open, just increment the reference - * count, or fail if it would overflow. + * count. The reference count is limited by the number of + * report ids, so this can't overflow. */ if (sc->sc_refcnt) { - if (sc->sc_refcnt == INT_MAX) - return EBUSY; + KASSERT(sc->sc_refcnt < UHIDEV_MAXREPID); sc->sc_refcnt++; return 0; } @@ -700,12 +700,9 @@ uhidev_open_pipes(struct uhidev_softc *s if (error) goto out; if (sc->sc_refcnt) { - if (sc->sc_refcnt == INT_MAX) { - error = EBUSY; - } else { - sc->sc_refcnt++; - error = 0; - } + KASSERT(sc->sc_refcnt < UHIDEV_MAXREPID); + sc->sc_refcnt++; + error = 0; goto out0; } mutex_exit(>sc_lock); Index: src/sys/dev/usb/uhidev.h diff -u src/sys/dev/usb/uhidev.h:1.26 src/sys/dev/usb/uhidev.h:1.27 --- src/sys/dev/usb/uhidev.h:1.26 Mon Mar 28 12:44:17 2022 +++ src/sys/dev/usb/uhidev.h Mon Mar 28 12:44:37 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: uhidev.h,v 1.26 2022/03/28 12:44:17 riastradh Exp $ */ +/* $NetBSD: uhidev.h,v 1.27 2022/03/28 12:44:37 riastradh Exp $ */ /* * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -54,5 +54,6 @@ usbd_status uhidev_write_async(struct uh usbd_callback, void *); #define UHIDEV_OSIZE 64 +#define UHIDEV_MAXREPID 255 #endif /* _DEV_USB_UHIDEV_H_ */
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:44:37 UTC 2022 Modified Files: src/sys/dev/usb: uhidev.c uhidev.h Log Message: uhidev(9): Define UHIDEV_MAXREPID = 255. Report ids are limited by the HID spec to a single byte. - Clamp max report id in report descriptor to this. - Prune dead refcnt-overflow error branches. Assert instead. To generate a diff of this commit: cvs rdiff -u -r1.91 -r1.92 src/sys/dev/usb/uhidev.c cvs rdiff -u -r1.26 -r1.27 src/sys/dev/usb/uhidev.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:44:28 UTC 2022 Modified Files: src/sys/dev/usb: uhidev.c Log Message: uhidev(9): Omit needless sc_dying. To generate a diff of this commit: cvs rdiff -u -r1.90 -r1.91 src/sys/dev/usb/uhidev.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/dev/usb/uhidev.c diff -u src/sys/dev/usb/uhidev.c:1.90 src/sys/dev/usb/uhidev.c:1.91 --- src/sys/dev/usb/uhidev.c:1.90 Mon Mar 28 12:44:17 2022 +++ src/sys/dev/usb/uhidev.c Mon Mar 28 12:44:28 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: uhidev.c,v 1.90 2022/03/28 12:44:17 riastradh Exp $ */ +/* $NetBSD: uhidev.c,v 1.91 2022/03/28 12:44:28 riastradh Exp $ */ /* * Copyright (c) 2001, 2012 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.90 2022/03/28 12:44:17 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.91 2022/03/28 12:44:28 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -110,7 +110,6 @@ struct uhidev_softc { int sc_refcnt; int sc_writereportid; int sc_stopreportid; - u_char sc_dying; /* * - Read under sc_lock, provided sc_refcnt > 0. @@ -146,10 +145,9 @@ static int uhidev_match(device_t, cfdata static void uhidev_attach(device_t, device_t, void *); static void uhidev_childdet(device_t, device_t); static int uhidev_detach(device_t, int); -static int uhidev_activate(device_t, enum devact); CFATTACH_DECL2_NEW(uhidev, sizeof(struct uhidev_softc), uhidev_match, -uhidev_attach, uhidev_detach, uhidev_activate, NULL, uhidev_childdet); +uhidev_attach, uhidev_detach, NULL, NULL, uhidev_childdet); static int uhidev_match(device_t parent, cfdata_t match, void *aux) @@ -203,7 +201,6 @@ uhidev_attach(device_t parent, device_t sc->sc_refcnt = 0; sc->sc_writereportid = -1; sc->sc_stopreportid = -1; - sc->sc_dying = false; id = usbd_get_interface_descriptor(iface); @@ -244,7 +241,6 @@ uhidev_attach(device_t parent, device_t if (ed == NULL) { aprint_error_dev(self, "could not read endpoint descriptor\n"); - sc->sc_dying = 1; return; } @@ -275,7 +271,6 @@ uhidev_attach(device_t parent, device_t */ if (sc->sc_iep_addr == -1) { aprint_error_dev(self, "no input interrupt endpoint\n"); - sc->sc_dying = 1; return; } @@ -336,7 +331,6 @@ uhidev_attach(device_t parent, device_t } if (err) { aprint_error_dev(self, "no report descriptor\n"); - sc->sc_dying = 1; return; } @@ -479,20 +473,6 @@ uhidevprint(void *aux, const char *pnp) return UNCONF; } -static int -uhidev_activate(device_t self, enum devact act) -{ - struct uhidev_softc *sc = device_private(self); - - switch (act) { - case DVACT_DEACTIVATE: - sc->sc_dying = 1; - return 0; - default: - return EOPNOTSUPP; - } -} - static void uhidev_childdet(device_t self, device_t child) { @@ -523,26 +503,17 @@ uhidev_detach(device_t self, int flags) DPRINTF(("uhidev_detach: sc=%p flags=%d\n", sc, flags)); - /* Notify that we are going away. */ - mutex_enter(>sc_lock); - sc->sc_dying = 1; - cv_broadcast(>sc_cv); - mutex_exit(>sc_lock); - /* * Try to detach all our children. If anything fails, bail. * Failure can happen if this is from drvctl -d; of course, if * this is a USB device being yanked, flags will have * DETACH_FORCE and the children will not have the option of - * refusing detachment. + * refusing detachment. If they do detach, the pipes can no + * longer be in use. */ rv = config_detach_children(self, flags); - if (rv) { - mutex_enter(>sc_lock); - sc->sc_dying = 0; - mutex_exit(>sc_lock); + if (rv) return rv; - } KASSERTMSG(sc->sc_refcnt == 0, "%s: %d refs remain", device_xname(sc->sc_dev), sc->sc_refcnt); @@ -650,8 +621,6 @@ uhidev_config_enter(struct uhidev_softc KASSERT(mutex_owned(>sc_lock)); for (;;) { - if (sc->sc_dying) - return ENXIO; if (sc->sc_configlock == NULL) break; error = cv_wait_sig(>sc_cv, >sc_lock); @@ -700,10 +669,6 @@ uhidev_open_pipes(struct uhidev_softc *s KASSERT(mutex_owned(>sc_lock)); - /* If the device is dying, refuse. */ - if (sc->sc_dying) - return ENXIO; - /* * If the pipes are already open, just increment the reference * count, or fail if it would overflow. @@ -1122,10 +1087,6 @@ uhidev_write(struct uhidev *scd, void *d mutex_enter(>sc_lock); KASSERT(sc->sc_refcnt); for (;;) { - if (sc->sc_dying) { - err = USBD_IOERROR; - goto out; - } if (scd->sc_state & UHIDEV_STOPPED) { err = USBD_CANCELLED; goto out; @@ -1210,10 +1171,6 @@ uhidev_write_async(struct uhidev *scd, v mutex_enter(>sc_lock); KASSERT(sc->sc_refcnt); - if (sc->sc_dying) { - err = USBD_IOERROR; - goto out; - } if (scd->sc_state & UHIDEV_STOPPED) { err = USBD_CANCELLED; goto out;
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:44:28 UTC 2022 Modified Files: src/sys/dev/usb: uhidev.c Log Message: uhidev(9): Omit needless sc_dying. To generate a diff of this commit: cvs rdiff -u -r1.90 -r1.91 src/sys/dev/usb/uhidev.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:44:17 UTC 2022 Modified Files: src/sys/dev/usb: uatp.c ucycom.c uhid.c uhidev.c uhidev.h ukbd.c ums.c uthum.c uts.c Log Message: uhidev(9): Make uhidev state opaque. This makes the API simpler and clearer and gives us more latitude to fix bugs in the state management without breaking the ABI. XXX kernel ABI change to signature of uhidev_get_report_desc and uhidev_open, and to struct uhidev_attach_arg, requires bump for uhidev driver modules To generate a diff of this commit: cvs rdiff -u -r1.28 -r1.29 src/sys/dev/usb/uatp.c cvs rdiff -u -r1.54 -r1.55 src/sys/dev/usb/ucycom.c cvs rdiff -u -r1.122 -r1.123 src/sys/dev/usb/uhid.c cvs rdiff -u -r1.89 -r1.90 src/sys/dev/usb/uhidev.c cvs rdiff -u -r1.25 -r1.26 src/sys/dev/usb/uhidev.h cvs rdiff -u -r1.158 -r1.159 src/sys/dev/usb/ukbd.c cvs rdiff -u -r1.102 -r1.103 src/sys/dev/usb/ums.c cvs rdiff -u -r1.22 -r1.23 src/sys/dev/usb/uthum.c cvs rdiff -u -r1.14 -r1.15 src/sys/dev/usb/uts.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/dev/usb/uatp.c diff -u src/sys/dev/usb/uatp.c:1.28 src/sys/dev/usb/uatp.c:1.29 --- src/sys/dev/usb/uatp.c:1.28 Mon Mar 28 12:43:12 2022 +++ src/sys/dev/usb/uatp.c Mon Mar 28 12:44:17 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: uatp.c,v 1.28 2022/03/28 12:43:12 riastradh Exp $ */ +/* $NetBSD: uatp.c,v 1.29 2022/03/28 12:44:17 riastradh Exp $ */ /*- * Copyright (c) 2011-2014 The NetBSD Foundation, Inc. @@ -146,7 +146,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: uatp.c,v 1.28 2022/03/28 12:43:12 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uatp.c,v 1.29 2022/03/28 12:44:17 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -301,7 +301,7 @@ static void geyser34_initialize(struct u static int geyser34_finalize(struct uatp_softc *); static void geyser34_deferred_reset(struct uatp_softc *); static void geyser34_reset_task(void *); -static void uatp_intr(struct uhidev *, void *, unsigned int); +static void uatp_intr(void *, void *, unsigned int); static bool base_sample_softc_flag(const struct uatp_softc *, const uint8_t *); static bool base_sample_input_flag(const struct uatp_softc *, const uint8_t *); static void read_sample_1(uint8_t *, uint8_t *, const uint8_t *); @@ -486,7 +486,8 @@ static const struct uatp_knobs default_k }; struct uatp_softc { - struct uhidev sc_hdev; /* uhidev(9) parent. */ + device_t sc_dev; + struct uhidev *sc_hdev; /* uhidev(9) parent. */ struct usbd_device *sc_udev; /* USB device. */ device_t sc_wsmousedev; /* Attached wsmouse device. */ const struct uatp_parameters *sc_parameters; @@ -691,7 +692,7 @@ find_uatp_descriptor(const struct uhidev static device_t uatp_dev(const struct uatp_softc *sc) { - return sc->sc_hdev.sc_dev; + return sc->sc_dev; } static uint8_t * @@ -931,12 +932,8 @@ uatp_attach(device_t parent, device_t se int report_size, input_size; struct wsmousedev_attach_args a; - /* Set up uhidev state. (Why doesn't uhidev do most of this?) */ - sc->sc_hdev.sc_dev = self; - sc->sc_hdev.sc_intr = uatp_intr; - sc->sc_hdev.sc_parent = uha->parent; - sc->sc_hdev.sc_report_id = uha->reportid; - + sc->sc_dev = self; + sc->sc_hdev = uha->parent; sc->sc_udev = uha->uiaa->uiaa_device; /* Identify ourselves to dmesg. */ @@ -948,7 +945,7 @@ uatp_attach(device_t parent, device_t se "vendor 0x%04x, product 0x%04x, report id %d\n", (unsigned int)uha->uiaa->uiaa_vendor, (unsigned int)uha->uiaa->uiaa_product, - (int)uha->reportid); + uha->reportid); uhidev_get_report_desc(uha->parent, _descriptor, _size); input_size = hid_report_size(report_descriptor, report_size, hid_input, @@ -1251,8 +1248,8 @@ uatp_enable(void *v) tap_enable(sc); uatp_clear_position(sc); - DPRINTF(sc, UATP_DEBUG_MISC, ("uhidev_open(%p)\n", >sc_hdev)); - return uhidev_open(>sc_hdev); + DPRINTF(sc, UATP_DEBUG_MISC, ("uhidev_open(%p)\n", sc->sc_hdev)); + return uhidev_open(sc->sc_hdev, _intr, sc); } static void @@ -1270,8 +1267,8 @@ uatp_disable(void *v) tap_disable(sc); sc->sc_status &=~ UATP_ENABLED; - DPRINTF(sc, UATP_DEBUG_MISC, ("uhidev_close(%p)\n", >sc_hdev)); - uhidev_close(>sc_hdev); + DPRINTF(sc, UATP_DEBUG_MISC, ("uhidev_close(%p)\n", sc->sc_hdev)); + uhidev_close(sc->sc_hdev); } static int @@ -1399,15 +1396,15 @@ geyser34_reset_task(void *arg) /* Interrupt handler */ static void -uatp_intr(struct uhidev *addr, void *ibuf, unsigned int len) +uatp_intr(void *cookie, void *ibuf, unsigned int len) { - struct uatp_softc *sc = (struct uatp_softc *)addr; + struct uatp_softc *sc = cookie; uint8_t *input; int dx, dy, dz, dw; uint32_t buttons; DPRINTF(sc, UATP_DEBUG_INTR, ("softc %p, ibuf %p, len %u\n", - addr, ibuf, len)); + sc, ibuf, len)); /* * Some devices break packets up into chunks, so we accumulate Index:
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:44:17 UTC 2022 Modified Files: src/sys/dev/usb: uatp.c ucycom.c uhid.c uhidev.c uhidev.h ukbd.c ums.c uthum.c uts.c Log Message: uhidev(9): Make uhidev state opaque. This makes the API simpler and clearer and gives us more latitude to fix bugs in the state management without breaking the ABI. XXX kernel ABI change to signature of uhidev_get_report_desc and uhidev_open, and to struct uhidev_attach_arg, requires bump for uhidev driver modules To generate a diff of this commit: cvs rdiff -u -r1.28 -r1.29 src/sys/dev/usb/uatp.c cvs rdiff -u -r1.54 -r1.55 src/sys/dev/usb/ucycom.c cvs rdiff -u -r1.122 -r1.123 src/sys/dev/usb/uhid.c cvs rdiff -u -r1.89 -r1.90 src/sys/dev/usb/uhidev.c cvs rdiff -u -r1.25 -r1.26 src/sys/dev/usb/uhidev.h cvs rdiff -u -r1.158 -r1.159 src/sys/dev/usb/ukbd.c cvs rdiff -u -r1.102 -r1.103 src/sys/dev/usb/ums.c cvs rdiff -u -r1.22 -r1.23 src/sys/dev/usb/uthum.c cvs rdiff -u -r1.14 -r1.15 src/sys/dev/usb/uts.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:44:06 UTC 2022 Modified Files: src/sys/dev/usb: uhidev.c Log Message: uhidev(9): Fix race between uhidev_close and uhidev_intr. uhidev_intr currently relies on the kernel lock to serialize access to struct uhidev::sc_state, but if the driver's sc_intr function sleeps (which it may do, even though this runs is softint context -- it may sleep on an adaptive lock), uhidev_close might return while the driver's sc_intr function is still in flight. This avoids that race, and makes progress toward MP-safe uhidev. To generate a diff of this commit: cvs rdiff -u -r1.88 -r1.89 src/sys/dev/usb/uhidev.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/dev/usb/uhidev.c diff -u src/sys/dev/usb/uhidev.c:1.88 src/sys/dev/usb/uhidev.c:1.89 --- src/sys/dev/usb/uhidev.c:1.88 Mon Mar 28 12:43:58 2022 +++ src/sys/dev/usb/uhidev.c Mon Mar 28 12:44:06 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: uhidev.c,v 1.88 2022/03/28 12:43:58 riastradh Exp $ */ +/* $NetBSD: uhidev.c,v 1.89 2022/03/28 12:44:06 riastradh Exp $ */ /* * Copyright (c) 2001, 2012 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.88 2022/03/28 12:43:58 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.89 2022/03/28 12:44:06 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -44,6 +44,7 @@ __KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1 #include #include +#include #include #include #include @@ -53,6 +54,7 @@ __KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1 #include #include #include +#include #include #include @@ -622,7 +624,7 @@ uhidev_intr(struct usbd_xfer *xfer, void scd = device_private(cdev); DPRINTFN(5,("uhidev_intr: rep=%d, scd=%p state=%#x\n", rep, scd, scd ? scd->sc_state : 0)); - if (!(scd->sc_state & UHIDEV_OPEN)) + if (!(atomic_load_acquire(>sc_state) & UHIDEV_OPEN)) return; #ifdef UHIDEV_DEBUG if (scd->sc_in_rep_size != cc) { @@ -921,7 +923,7 @@ uhidev_open(struct uhidev *scd) error = EBUSY; goto out; } - scd->sc_state |= UHIDEV_OPEN; + atomic_store_release(>sc_state, scd->sc_state | UHIDEV_OPEN); /* Open the pipes which are shared by all report ids. */ error = uhidev_open_pipes(sc); @@ -935,7 +937,8 @@ out: if (error) { KASSERTMSG(scd->sc_state & UHIDEV_OPEN, "%s: report id %d: closed while opening", device_xname(sc->sc_dev), scd->sc_report_id); - scd->sc_state &= ~UHIDEV_OPEN; + atomic_store_relaxed(>sc_state, + scd->sc_state & ~UHIDEV_OPEN); } mutex_exit(>sc_lock); return error; @@ -962,7 +965,7 @@ uhidev_stop(struct uhidev *scd) mutex_enter(>sc_lock); /* Prevent further writes on this report from starting. */ - scd->sc_state |= UHIDEV_STOPPED; + atomic_store_relaxed(>sc_state, scd->sc_state | UHIDEV_STOPPED); /* If there's no output pipe at all, nothing to do. */ if (sc->sc_opipe == NULL) @@ -1052,9 +1055,21 @@ uhidev_close(struct uhidev *scd) KASSERT(scd->sc_state & UHIDEV_OPEN); uhidev_close_pipes(sc); KASSERT(scd->sc_state & UHIDEV_OPEN); - scd->sc_state &= ~(UHIDEV_OPEN | UHIDEV_STOPPED); + atomic_store_relaxed(>sc_state, + scd->sc_state & ~(UHIDEV_OPEN | UHIDEV_STOPPED)); + /* + * Make sure the next uhidev_intr (which runs in softint, like + * XC_HIGHPRI) notices that UHIDEV_OPEN is cleared, and wait + * for any current one to finish, in case the pipe is still + * open for other report ids. + * + * We must drop the lock while doing this, because + * uhidev_write_callback takes the lock in softint context and + * it could deadlock with the xcall softint. + */ mutex_exit(>sc_lock); + xc_barrier(XC_HIGHPRI); } usbd_status
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:44:06 UTC 2022 Modified Files: src/sys/dev/usb: uhidev.c Log Message: uhidev(9): Fix race between uhidev_close and uhidev_intr. uhidev_intr currently relies on the kernel lock to serialize access to struct uhidev::sc_state, but if the driver's sc_intr function sleeps (which it may do, even though this runs is softint context -- it may sleep on an adaptive lock), uhidev_close might return while the driver's sc_intr function is still in flight. This avoids that race, and makes progress toward MP-safe uhidev. To generate a diff of this commit: cvs rdiff -u -r1.88 -r1.89 src/sys/dev/usb/uhidev.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:43:58 UTC 2022 Modified Files: src/sys/dev/usb: uhidev.c Log Message: uhidev(9): Refactor error branch to use one label. No functional change intended. To generate a diff of this commit: cvs rdiff -u -r1.87 -r1.88 src/sys/dev/usb/uhidev.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/dev/usb/uhidev.c diff -u src/sys/dev/usb/uhidev.c:1.87 src/sys/dev/usb/uhidev.c:1.88 --- src/sys/dev/usb/uhidev.c:1.87 Mon Mar 28 12:43:48 2022 +++ src/sys/dev/usb/uhidev.c Mon Mar 28 12:43:58 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: uhidev.c,v 1.87 2022/03/28 12:43:48 riastradh Exp $ */ +/* $NetBSD: uhidev.c,v 1.88 2022/03/28 12:43:58 riastradh Exp $ */ /* * Copyright (c) 2001, 2012 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.87 2022/03/28 12:43:48 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.88 2022/03/28 12:43:58 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -919,27 +919,25 @@ uhidev_open(struct uhidev *scd) /* Mark the report id open. This is an exclusive lock. */ if (scd->sc_state & UHIDEV_OPEN) { error = EBUSY; - goto fail0; + goto out; } scd->sc_state |= UHIDEV_OPEN; /* Open the pipes which are shared by all report ids. */ error = uhidev_open_pipes(sc); if (error) - goto fail1; - - mutex_exit(>sc_lock); + goto out; /* Success! */ - return 0; + error = 0; -fail2: __unused - uhidev_close_pipes(sc); -fail1: KASSERTMSG(scd->sc_state & UHIDEV_OPEN, - "%s: report id %d: closed while opening", - device_xname(sc->sc_dev), scd->sc_report_id); - scd->sc_state &= ~UHIDEV_OPEN; -fail0: mutex_exit(>sc_lock); +out: if (error) { + KASSERTMSG(scd->sc_state & UHIDEV_OPEN, + "%s: report id %d: closed while opening", + device_xname(sc->sc_dev), scd->sc_report_id); + scd->sc_state &= ~UHIDEV_OPEN; + } + mutex_exit(>sc_lock); return error; }
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:43:58 UTC 2022 Modified Files: src/sys/dev/usb: uhidev.c Log Message: uhidev(9): Refactor error branch to use one label. No functional change intended. To generate a diff of this commit: cvs rdiff -u -r1.87 -r1.88 src/sys/dev/usb/uhidev.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:43:48 UTC 2022 Modified Files: src/sys/dev/usb: uhidev.c Log Message: uhidev(9): Make some private functions static and fix comment. No functional change. To generate a diff of this commit: cvs rdiff -u -r1.86 -r1.87 src/sys/dev/usb/uhidev.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/dev/usb/uhidev.c diff -u src/sys/dev/usb/uhidev.c:1.86 src/sys/dev/usb/uhidev.c:1.87 --- src/sys/dev/usb/uhidev.c:1.86 Mon Mar 28 12:43:39 2022 +++ src/sys/dev/usb/uhidev.c Mon Mar 28 12:43:48 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: uhidev.c,v 1.86 2022/03/28 12:43:39 riastradh Exp $ */ +/* $NetBSD: uhidev.c,v 1.87 2022/03/28 12:43:48 riastradh Exp $ */ /* * Copyright (c) 2001, 2012 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.86 2022/03/28 12:43:39 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.87 2022/03/28 12:43:48 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -124,10 +124,10 @@ int uhidevdebug = 0; #define DPRINTFN(n,x) #endif -Static void uhidev_intr(struct usbd_xfer *, void *, usbd_status); +static void uhidev_intr(struct usbd_xfer *, void *, usbd_status); -Static int uhidev_maxrepid(void *, int); -Static int uhidevprint(void *, const char *); +static int uhidev_maxrepid(void *, int); +static int uhidevprint(void *, const char *); static int uhidev_match(device_t, cfdata_t, void *); static void uhidev_attach(device_t, device_t, void *); @@ -444,7 +444,7 @@ uhidev_attach(device_t parent, device_t return; } -int +static int uhidev_maxrepid(void *buf, int len) { struct hid_data *d; @@ -460,7 +460,7 @@ uhidev_maxrepid(void *buf, int len) return maxid; } -int +static int uhidevprint(void *aux, const char *pnp) { struct uhidev_attach_arg *uha = aux; @@ -573,7 +573,7 @@ uhidev_detach(device_t self, int flags) return rv; } -void +static void uhidev_intr(struct usbd_xfer *xfer, void *addr, usbd_status status) { struct uhidev_softc *sc = addr; @@ -731,8 +731,8 @@ uhidev_open_pipes(struct uhidev_softc *s return 0; /* - * Lock the configuration and release sc_lock we may sleep to - * allocate. If someone else got in first, we're done; + * Lock the configuration and release sc_lock -- we may sleep + * to allocate. If someone else got in first, we're done; * otherwise open the pipes. */ error = uhidev_config_enter(sc);
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:43:48 UTC 2022 Modified Files: src/sys/dev/usb: uhidev.c Log Message: uhidev(9): Make some private functions static and fix comment. No functional change. To generate a diff of this commit: cvs rdiff -u -r1.86 -r1.87 src/sys/dev/usb/uhidev.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:43:39 UTC 2022 Modified Files: src/sys/dev/usb: uhidev.c uhidev.h Log Message: uhidev(9): Make uhidev_stop work reliably. To generate a diff of this commit: cvs rdiff -u -r1.85 -r1.86 src/sys/dev/usb/uhidev.c cvs rdiff -u -r1.24 -r1.25 src/sys/dev/usb/uhidev.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/dev/usb/uhidev.c diff -u src/sys/dev/usb/uhidev.c:1.85 src/sys/dev/usb/uhidev.c:1.86 --- src/sys/dev/usb/uhidev.c:1.85 Mon Mar 28 12:43:22 2022 +++ src/sys/dev/usb/uhidev.c Mon Mar 28 12:43:39 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: uhidev.c,v 1.85 2022/03/28 12:43:22 riastradh Exp $ */ +/* $NetBSD: uhidev.c,v 1.86 2022/03/28 12:43:39 riastradh Exp $ */ /* * Copyright (c) 2001, 2012 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.85 2022/03/28 12:43:22 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.86 2022/03/28 12:43:39 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -96,6 +96,7 @@ struct uhidev_softc { struct lwp *sc_configlock; int sc_refcnt; int sc_writereportid; + int sc_stopreportid; u_char sc_dying; /* @@ -187,6 +188,10 @@ uhidev_attach(device_t parent, device_t cv_init(>sc_cv, "uhidev"); sc->sc_writelock = NULL; sc->sc_configlock = NULL; + sc->sc_refcnt = 0; + sc->sc_writereportid = -1; + sc->sc_stopreportid = -1; + sc->sc_dying = false; id = usbd_get_interface_descriptor(iface); @@ -938,21 +943,72 @@ fail0: mutex_exit(>sc_lock); return error; } +/* + * uhidev_stop(scd) + * + * Make all current and future output reports or xfers by scd to + * the output pipe to fail. Caller must then ensure no more will + * be submitted and then call uhidev_close. + * + * Side effect: If uhidev_write was in progress for this scd, + * blocks all other uhidev_writes until uhidev_close on this scd. + * + * May sleep but only for a short duration to wait for USB + * transfer completion callbacks to run. + */ void uhidev_stop(struct uhidev *scd) { struct uhidev_softc *sc = scd->sc_parent; - bool abort = false; mutex_enter(>sc_lock); - if (sc->sc_writereportid == scd->sc_report_id) - abort = true; + + /* Prevent further writes on this report from starting. */ + scd->sc_state |= UHIDEV_STOPPED; + + /* If there's no output pipe at all, nothing to do. */ + if (sc->sc_opipe == NULL) + goto out; + + /* + * If there's no write on this report in progress, nothing to + * do -- any subsequent attempts will be prevented by + * UHIDEV_STOPPED. + */ + if (sc->sc_writereportid != scd->sc_report_id) + goto out; + + /* + * Caller must wait for uhidev_open to succeed before calling + * uhidev_write, and must wait for all uhidev_writes to return + * before calling uhidev_close, so neither on can be in flight + * right now. + * + * Suspend the pipe, but hold up uhidev_write from any report + * until we confirm this one has finished. We will resume the + * pipe only after all uhidev_writes on this report have + * finished -- when the caller calls uhidev_close. + */ + KASSERTMSG(sc->sc_stopreportid == -1, "%d", sc->sc_stopreportid); + sc->sc_stopreportid = scd->sc_report_id; mutex_exit(>sc_lock); - if (abort && sc->sc_opipe) /* XXX sc_opipe might go away */ - usbd_abort_pipe(sc->sc_opipe); + usbd_suspend_pipe(sc->sc_opipe); + + mutex_enter(>sc_lock); + KASSERT(sc->sc_stopreportid == scd->sc_report_id); + sc->sc_stopreportid = scd->sc_report_id; + cv_broadcast(>sc_cv); +out: mutex_exit(>sc_lock); } +/* + * uhidev_close(scd) + * + * Close a uhidev previously opened with uhidev_open. If writes + * had been stopped with uhidev_stop, allow writes at other report + * ids again. + */ void uhidev_close(struct uhidev *scd) { @@ -970,11 +1026,35 @@ uhidev_close(struct uhidev *scd) KASSERTMSG(scd->sc_state & UHIDEV_OPEN, "%s: report id %d: unpaired close", device_xname(sc->sc_dev), scd->sc_report_id); + + /* + * If the caller had issued uhidev_stop to interrupt a write + * for this report, then resume the pipe now that no further + * uhidev_write on the same report is possible, and wake anyone + * trying to write on other reports. + */ + if (sc->sc_stopreportid == scd->sc_report_id) { + KASSERT(scd->sc_state & UHIDEV_STOPPED); + mutex_exit(>sc_lock); + + usbd_resume_pipe(sc->sc_opipe); + + mutex_enter(>sc_lock); + KASSERT(sc->sc_stopreportid == scd->sc_report_id); + KASSERT(scd->sc_state & UHIDEV_STOPPED); + sc->sc_stopreportid = -1; + cv_broadcast(>sc_cv); + } + + /* + * Close our reference to the pipes, and mark our report as no + * longer open. If it was stopped, clear that too -- drivers + * are forbidden from issuing writes after uhidev_close anyway. + */ + KASSERT(scd->sc_state & UHIDEV_OPEN); uhidev_close_pipes(sc); - KASSERTMSG(scd->sc_state & UHIDEV_OPEN, - "%s:
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:43:39 UTC 2022 Modified Files: src/sys/dev/usb: uhidev.c uhidev.h Log Message: uhidev(9): Make uhidev_stop work reliably. To generate a diff of this commit: cvs rdiff -u -r1.85 -r1.86 src/sys/dev/usb/uhidev.c cvs rdiff -u -r1.24 -r1.25 src/sys/dev/usb/uhidev.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:43:30 UTC 2022 Modified Files: src/sys/dev/usb: ucycom.c Log Message: ucycom(4): Defer uhidev_write_async to taskq. Can't submit USB transfers while holding tty_lock, a spin lock. To generate a diff of this commit: cvs rdiff -u -r1.53 -r1.54 src/sys/dev/usb/ucycom.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/dev/usb/ucycom.c diff -u src/sys/dev/usb/ucycom.c:1.53 src/sys/dev/usb/ucycom.c:1.54 --- src/sys/dev/usb/ucycom.c:1.53 Mon Mar 28 12:43:03 2022 +++ src/sys/dev/usb/ucycom.c Mon Mar 28 12:43:30 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: ucycom.c,v 1.53 2022/03/28 12:43:03 riastradh Exp $ */ +/* $NetBSD: ucycom.c,v 1.54 2022/03/28 12:43:30 riastradh Exp $ */ /* * Copyright (c) 2005 The NetBSD Foundation, Inc. @@ -38,7 +38,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ucycom.c,v 1.53 2022/03/28 12:43:03 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ucycom.c,v 1.54 2022/03/28 12:43:30 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -118,7 +118,9 @@ int ucycomdebug = 20; struct ucycom_softc { struct uhidev sc_hdev; + struct usbd_device *sc_udev; + struct usb_task sc_task; struct tty *sc_tty; enum { @@ -172,6 +174,7 @@ const struct cdevsw ucycom_cdevsw = { Static int ucycomparam(struct tty *, struct termios *); Static void ucycomstart(struct tty *); +Static void ucycomstarttask(void *); Static void ucycomwritecb(struct usbd_xfer *, void *, usbd_status); Static void ucycom_intr(struct uhidev *, void *, u_int); Static int ucycom_configure(struct ucycom_softc *, uint32_t, uint8_t); @@ -223,6 +226,7 @@ ucycom_attach(device_t parent, device_t sc->sc_hdev.sc_intr = ucycom_intr; sc->sc_hdev.sc_parent = uha->parent; sc->sc_hdev.sc_report_id = uha->reportid; + sc->sc_udev = uha->uiaa->uiaa_device; sc->sc_init_state = UCYCOM_INIT_NONE; uhidev_get_report_desc(uha->parent, , ); @@ -237,6 +241,9 @@ ucycom_attach(device_t parent, device_t sc->sc_msr = sc->sc_mcr = 0; + /* not MP-safe */ + usb_init_task(>sc_task, ucycomstarttask, sc, 0); + /* set up tty */ sc->sc_tty = tty_alloc(); sc->sc_tty->t_sc = sc; @@ -287,6 +294,8 @@ ucycom_detach(device_t self, int flags) vdevgone(maj, mn | UCYCOMDIALOUT_MASK, mn | UCYCOMDIALOUT_MASK, VCHR); vdevgone(maj, mn | UCYCOMCALLUNIT_MASK, mn | UCYCOMCALLUNIT_MASK, VCHR); + usb_rem_task_wait(sc->sc_udev, >sc_task, USB_TASKQ_DRIVER, NULL); + /* Detach and free the tty. */ if (tp != NULL) { DPRINTF(("ucycom_detach: tty_detach %p\n", tp)); @@ -482,6 +491,8 @@ ucycomstart(struct tty *tp) u_char *data; int cnt, len, s; + KASSERT(mutex_owned(_lock)); + if (sc->sc_dying) return; @@ -592,6 +603,19 @@ ucycomstart(struct tty *tp) } #endif DPRINTFN(4,("ucycomstart: %d chars\n", len)); + usb_add_task(sc->sc_udev, >sc_task, USB_TASKQ_DRIVER); + return; + +out: + splx(s); +} + +Static void +ucycomstarttask(void *cookie) +{ + struct ucycom_softc *sc = cookie; + usbd_status err; + /* What can we do on error? */ err = uhidev_write_async(>sc_hdev, sc->sc_obuf, sc->sc_olen, 0, USBD_NO_TIMEOUT, ucycomwritecb, sc); @@ -599,11 +623,9 @@ ucycomstart(struct tty *tp) #ifdef UCYCOM_DEBUG if (err != USBD_IN_PROGRESS) DPRINTF(("ucycomstart: err=%s\n", usbd_errstr(err))); +#else + __USE(err); #endif - return; - -out: - splx(s); } Static void
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:43:30 UTC 2022 Modified Files: src/sys/dev/usb: ucycom.c Log Message: ucycom(4): Defer uhidev_write_async to taskq. Can't submit USB transfers while holding tty_lock, a spin lock. To generate a diff of this commit: cvs rdiff -u -r1.53 -r1.54 src/sys/dev/usb/ucycom.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:43:22 UTC 2022 Modified Files: src/sys/dev/usb: uhidev.c uhidev.h Log Message: uhidev(9): Move struct uhidev_softc into uhidev.c. No longer part of any ABI for uhidev modules. To generate a diff of this commit: cvs rdiff -u -r1.84 -r1.85 src/sys/dev/usb/uhidev.c cvs rdiff -u -r1.23 -r1.24 src/sys/dev/usb/uhidev.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/dev/usb/uhidev.c diff -u src/sys/dev/usb/uhidev.c:1.84 src/sys/dev/usb/uhidev.c:1.85 --- src/sys/dev/usb/uhidev.c:1.84 Mon Mar 28 12:43:03 2022 +++ src/sys/dev/usb/uhidev.c Mon Mar 28 12:43:22 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: uhidev.c,v 1.84 2022/03/28 12:43:03 riastradh Exp $ */ +/* $NetBSD: uhidev.c,v 1.85 2022/03/28 12:43:22 riastradh Exp $ */ /* * Copyright (c) 2001, 2012 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.84 2022/03/28 12:43:03 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.85 2022/03/28 12:43:22 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -74,6 +74,46 @@ __KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1 #include "locators.h" +struct uhidev_softc { + device_t sc_dev; /* base device */ + struct usbd_device *sc_udev; + struct usbd_interface *sc_iface; /* interface */ + int sc_iep_addr; + int sc_oep_addr; + u_int sc_isize; + + int sc_repdesc_size; + void *sc_repdesc; + + u_int sc_nrepid; + device_t *sc_subdevs; + + kmutex_t sc_lock; + kcondvar_t sc_cv; + + /* Read/written under sc_lock. */ + struct lwp *sc_writelock; + struct lwp *sc_configlock; + int sc_refcnt; + int sc_writereportid; + u_char sc_dying; + + /* + * - Read under sc_lock, provided sc_refcnt > 0. + * - Written under sc_configlock only when transitioning to and + * from sc_refcnt = 0. + */ + u_char *sc_ibuf; + struct usbd_pipe *sc_ipipe; /* input interrupt pipe */ + struct usbd_pipe *sc_opipe; /* output interrupt pipe */ + struct usbd_xfer *sc_oxfer; /* write request */ + usbd_callback sc_writecallback; /* async write request callback */ + void *sc_writecookie; + + u_int sc_flags; +#define UHIDEV_F_XB1 0x0001 /* Xbox 1 controller */ +}; + #ifdef UHIDEV_DEBUG #define DPRINTF(x) if (uhidevdebug) printf x #define DPRINTFN(n,x) if (uhidevdebug>(n)) printf x Index: src/sys/dev/usb/uhidev.h diff -u src/sys/dev/usb/uhidev.h:1.23 src/sys/dev/usb/uhidev.h:1.24 --- src/sys/dev/usb/uhidev.h:1.23 Mon Mar 28 12:43:03 2022 +++ src/sys/dev/usb/uhidev.h Mon Mar 28 12:43:22 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: uhidev.h,v 1.23 2022/03/28 12:43:03 riastradh Exp $ */ +/* $NetBSD: uhidev.h,v 1.24 2022/03/28 12:43:22 riastradh Exp $ */ /* * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -35,46 +35,6 @@ #include -struct uhidev_softc { - device_t sc_dev; /* base device */ - struct usbd_device *sc_udev; - struct usbd_interface *sc_iface; /* interface */ - int sc_iep_addr; - int sc_oep_addr; - u_int sc_isize; - - int sc_repdesc_size; - void *sc_repdesc; - - u_int sc_nrepid; - device_t *sc_subdevs; - - kmutex_t sc_lock; - kcondvar_t sc_cv; - - /* Read/written under sc_lock. */ - struct lwp *sc_writelock; - struct lwp *sc_configlock; - int sc_refcnt; - int sc_writereportid; - u_char sc_dying; - - /* - * - Read under sc_lock, provided sc_refcnt > 0. - * - Written under sc_configlock only when transitioning to and - * from sc_refcnt = 0. - */ - u_char *sc_ibuf; - struct usbd_pipe *sc_ipipe; /* input interrupt pipe */ - struct usbd_pipe *sc_opipe; /* output interrupt pipe */ - struct usbd_xfer *sc_oxfer; /* write request */ - usbd_callback sc_writecallback; /* async write request callback */ - void *sc_writecookie; - - u_int sc_flags; -#define UHIDEV_F_XB1 0x0001 /* Xbox 1 controller */ -}; - struct uhidev { device_t sc_dev; /* base device */ struct uhidev_softc *sc_parent;
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:43:22 UTC 2022 Modified Files: src/sys/dev/usb: uhidev.c uhidev.h Log Message: uhidev(9): Move struct uhidev_softc into uhidev.c. No longer part of any ABI for uhidev modules. To generate a diff of this commit: cvs rdiff -u -r1.84 -r1.85 src/sys/dev/usb/uhidev.c cvs rdiff -u -r1.23 -r1.24 src/sys/dev/usb/uhidev.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:43:12 UTC 2022 Modified Files: src/sys/arch/macppc/dev: pbms.c src/sys/dev/usb: uatp.c uhid.c ukbd.c ums.c uthum.c Log Message: uhidev(9): Get the device and interface through attach args. This way uhidev drivers don't need access to uhidev_softc itself for it. To generate a diff of this commit: cvs rdiff -u -r1.19 -r1.20 src/sys/arch/macppc/dev/pbms.c cvs rdiff -u -r1.27 -r1.28 src/sys/dev/usb/uatp.c cvs rdiff -u -r1.121 -r1.122 src/sys/dev/usb/uhid.c cvs rdiff -u -r1.157 -r1.158 src/sys/dev/usb/ukbd.c cvs rdiff -u -r1.101 -r1.102 src/sys/dev/usb/ums.c cvs rdiff -u -r1.21 -r1.22 src/sys/dev/usb/uthum.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/arch/macppc/dev/pbms.c diff -u src/sys/arch/macppc/dev/pbms.c:1.19 src/sys/arch/macppc/dev/pbms.c:1.20 --- src/sys/arch/macppc/dev/pbms.c:1.19 Sat Aug 7 16:18:57 2021 +++ src/sys/arch/macppc/dev/pbms.c Mon Mar 28 12:43:12 2022 @@ -1,4 +1,4 @@ -/* $Id: pbms.c,v 1.19 2021/08/07 16:18:57 thorpej Exp $ */ +/* $Id: pbms.c,v 1.20 2022/03/28 12:43:12 riastradh Exp $ */ /* * Copyright (c) 2005, Johan Wallén @@ -307,7 +307,8 @@ pbms_match(device_t parent, cfdata_t mat * we expect. */ if (uha->uiaa->uiaa_proto == UIPROTO_MOUSE && - (udd = usbd_get_device_descriptor(uha->parent->sc_udev)) != NULL) { + ((udd = usbd_get_device_descriptor(uha->uiaa->uiaa_device)) + != NULL)) { vendor = UGETW(udd->idVendor); product = UGETW(udd->idProduct); for (i = 0; i < PBMS_NUM_DEVICES; i++) { @@ -329,6 +330,7 @@ pbms_attach(device_t parent, device_t se struct uhidev_attach_arg *uha = aux; struct pbms_dev *pd; struct pbms_softc *sc = device_private(self); + struct usbd_device *udev; usb_device_descriptor_t *udd; int i; uint16_t vendor, product; @@ -341,7 +343,8 @@ pbms_attach(device_t parent, device_t se sc->sc_datalen = PBMS_DATA_LEN; /* Fill in device-specific parameters. */ - if ((udd = usbd_get_device_descriptor(uha->parent->sc_udev)) != NULL) { + udev = uha->uiaa->uiaa_udevice; + if ((udd = usbd_get_device_descriptor(udev)) != NULL) { product = UGETW(udd->idProduct); vendor = UGETW(udd->idVendor); for (i = 0; i < PBMS_NUM_DEVICES; i++) { Index: src/sys/dev/usb/uatp.c diff -u src/sys/dev/usb/uatp.c:1.27 src/sys/dev/usb/uatp.c:1.28 --- src/sys/dev/usb/uatp.c:1.27 Sat Aug 7 16:19:17 2021 +++ src/sys/dev/usb/uatp.c Mon Mar 28 12:43:12 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: uatp.c,v 1.27 2021/08/07 16:19:17 thorpej Exp $ */ +/* $NetBSD: uatp.c,v 1.28 2022/03/28 12:43:12 riastradh Exp $ */ /*- * Copyright (c) 2011-2014 The NetBSD Foundation, Inc. @@ -146,7 +146,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: uatp.c,v 1.27 2021/08/07 16:19:17 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uatp.c,v 1.28 2022/03/28 12:43:12 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -486,7 +486,8 @@ static const struct uatp_knobs default_k }; struct uatp_softc { - struct uhidev sc_hdev; /* USB parent. */ + struct uhidev sc_hdev; /* uhidev(9) parent. */ + struct usbd_device *sc_udev; /* USB device. */ device_t sc_wsmousedev; /* Attached wsmouse device. */ const struct uatp_parameters *sc_parameters; struct uatp_knobs sc_knobs; @@ -936,6 +937,8 @@ uatp_attach(device_t parent, device_t se sc->sc_hdev.sc_parent = uha->parent; sc->sc_hdev.sc_report_id = uha->reportid; + sc->sc_udev = uha->uiaa->uiaa_device; + /* Identify ourselves to dmesg. */ uatp_descriptor = find_uatp_descriptor(uha); KASSERT(uatp_descriptor != NULL); @@ -1296,7 +1299,7 @@ uatp_ioctl(void *v, unsigned long cmd, v static void geyser34_enable_raw_mode(struct uatp_softc *sc) { - struct usbd_device *udev = sc->sc_hdev.sc_parent->sc_udev; + struct usbd_device *udev = sc->sc_udev; usb_device_request_t req; usbd_status status; uint8_t report[GEYSER34_MODE_PACKET_SIZE]; @@ -1368,8 +1371,8 @@ geyser34_finalize(struct uatp_softc *sc) { DPRINTF(sc, UATP_DEBUG_MISC, ("finalizing\n")); - usb_rem_task_wait(sc->sc_hdev.sc_parent->sc_udev, >sc_reset_task, - USB_TASKQ_DRIVER, NULL); + usb_rem_task_wait(sc->sc_udev, >sc_reset_task, USB_TASKQ_DRIVER, + NULL); return 0; } @@ -1379,8 +1382,7 @@ geyser34_deferred_reset(struct uatp_soft { DPRINTF(sc, UATP_DEBUG_RESET, ("deferring reset\n")); - usb_add_task(sc->sc_hdev.sc_parent->sc_udev, >sc_reset_task, - USB_TASKQ_DRIVER); + usb_add_task(sc->sc_udev, >sc_reset_task, USB_TASKQ_DRIVER); } static void Index: src/sys/dev/usb/uhid.c diff -u src/sys/dev/usb/uhid.c:1.121 src/sys/dev/usb/uhid.c:1.122 --- src/sys/dev/usb/uhid.c:1.121 Mon Mar 28 12:42:54 2022 +++ src/sys/dev/usb/uhid.c Mon Mar 28 12:43:12 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: uhid.c,v 1.121 2022/03/28 12:42:54 riastradh Exp $ */ +/* $NetBSD: uhid.c,v 1.122 2022/03/28 12:43:12 riastradh Exp $ */ /* * Copyright
CVS commit: src/sys
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:43:12 UTC 2022 Modified Files: src/sys/arch/macppc/dev: pbms.c src/sys/dev/usb: uatp.c uhid.c ukbd.c ums.c uthum.c Log Message: uhidev(9): Get the device and interface through attach args. This way uhidev drivers don't need access to uhidev_softc itself for it. To generate a diff of this commit: cvs rdiff -u -r1.19 -r1.20 src/sys/arch/macppc/dev/pbms.c cvs rdiff -u -r1.27 -r1.28 src/sys/dev/usb/uatp.c cvs rdiff -u -r1.121 -r1.122 src/sys/dev/usb/uhid.c cvs rdiff -u -r1.157 -r1.158 src/sys/dev/usb/ukbd.c cvs rdiff -u -r1.101 -r1.102 src/sys/dev/usb/ums.c cvs rdiff -u -r1.21 -r1.22 src/sys/dev/usb/uthum.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:43:03 UTC 2022 Modified Files: src/sys/dev/usb: ucycom.c uhidev.c uhidev.h Log Message: uhidev(9): New uhidev_write_async. Like uhidev_write but issues the transfer asynchronously with a callback. Use it in ucycom(4). Also, clear endpoint stalls asynchronously -- can't do them synchronously in xfer callbacks which run at softint and therefore can't wait in cv_wait as usbd_do_request does. To generate a diff of this commit: cvs rdiff -u -r1.52 -r1.53 src/sys/dev/usb/ucycom.c cvs rdiff -u -r1.83 -r1.84 src/sys/dev/usb/uhidev.c cvs rdiff -u -r1.22 -r1.23 src/sys/dev/usb/uhidev.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/dev/usb/ucycom.c diff -u src/sys/dev/usb/ucycom.c:1.52 src/sys/dev/usb/ucycom.c:1.53 --- src/sys/dev/usb/ucycom.c:1.52 Mon Mar 28 12:42:54 2022 +++ src/sys/dev/usb/ucycom.c Mon Mar 28 12:43:03 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: ucycom.c,v 1.52 2022/03/28 12:42:54 riastradh Exp $ */ +/* $NetBSD: ucycom.c,v 1.53 2022/03/28 12:43:03 riastradh Exp $ */ /* * Copyright (c) 2005 The NetBSD Foundation, Inc. @@ -38,7 +38,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ucycom.c,v 1.52 2022/03/28 12:42:54 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ucycom.c,v 1.53 2022/03/28 12:43:03 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -592,11 +592,9 @@ ucycomstart(struct tty *tp) } #endif DPRINTFN(4,("ucycomstart: %d chars\n", len)); - usbd_setup_xfer(sc->sc_hdev.sc_parent->sc_oxfer, sc, sc->sc_obuf, - sc->sc_olen, 0, USBD_NO_TIMEOUT, ucycomwritecb); - /* What can we do on error? */ - err = usbd_transfer(sc->sc_hdev.sc_parent->sc_oxfer); + err = uhidev_write_async(>sc_hdev, sc->sc_obuf, sc->sc_olen, 0, + USBD_NO_TIMEOUT, ucycomwritecb, sc); #ifdef UCYCOM_DEBUG if (err != USBD_IN_PROGRESS) @@ -621,7 +619,6 @@ ucycomwritecb(struct usbd_xfer *xfer, vo if (status) { DPRINTF(("ucycomwritecb: status=%d\n", status)); - usbd_clear_endpoint_stall(sc->sc_hdev.sc_parent->sc_opipe); /* XXX we should restart after some delay. */ goto error; } Index: src/sys/dev/usb/uhidev.c diff -u src/sys/dev/usb/uhidev.c:1.83 src/sys/dev/usb/uhidev.c:1.84 --- src/sys/dev/usb/uhidev.c:1.83 Mon Mar 28 12:42:54 2022 +++ src/sys/dev/usb/uhidev.c Mon Mar 28 12:43:03 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: uhidev.c,v 1.83 2022/03/28 12:42:54 riastradh Exp $ */ +/* $NetBSD: uhidev.c,v 1.84 2022/03/28 12:43:03 riastradh Exp $ */ /* * Copyright (c) 2001, 2012 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.83 2022/03/28 12:42:54 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.84 2022/03/28 12:43:03 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -1025,3 +1025,74 @@ uhidev_write(struct uhidev *scd, void *d out: mutex_exit(>sc_lock); return err; } + +static void +uhidev_write_callback(struct usbd_xfer *xfer, void *cookie, usbd_status err) +{ + struct uhidev_softc *sc = cookie; + usbd_callback writecallback; + void *writecookie; + + if (err) { + if (err != USBD_CANCELLED) + usbd_clear_endpoint_stall_async(sc->sc_opipe); + } + + mutex_enter(>sc_lock); + KASSERT(sc->sc_writelock == (void *)1); + writecallback = sc->sc_writecallback; + writecookie = sc->sc_writecookie; + sc->sc_writereportid = -1; + sc->sc_writelock = NULL; + sc->sc_writecallback = NULL; + sc->sc_writecookie = NULL; + cv_broadcast(>sc_cv); + mutex_exit(>sc_lock); + + (*writecallback)(xfer, writecookie, err); +} + +usbd_status +uhidev_write_async(struct uhidev *scd, void *data, int len, int flags, +int timo, usbd_callback writecallback, void *writecookie) +{ + struct uhidev_softc *sc = scd->sc_parent; + usbd_status err; + + DPRINTF(("%s: data=%p, len=%d\n", __func__, data, len)); + + if (sc->sc_opipe == NULL) + return USBD_INVAL; + + mutex_enter(>sc_lock); + KASSERT(sc->sc_refcnt); + if (sc->sc_dying) { + err = USBD_IOERROR; + goto out; + } + if (sc->sc_writelock != NULL) { + err = USBD_IN_USE; + goto out; + } + sc->sc_writelock = (void *)1; /* XXX no lwp to attribute async xfer */ + sc->sc_writereportid = scd->sc_report_id; + sc->sc_writecallback = writecallback; + sc->sc_writecookie = writecookie; + usbd_setup_xfer(sc->sc_oxfer, sc, data, len, flags, timo, + uhidev_write_callback); + err = usbd_transfer(sc->sc_oxfer); + switch (err) { + case USBD_IN_PROGRESS: + break; + case USBD_NORMAL_COMPLETION: + panic("unexpected normal completion of async xfer under lock"); + default: /* error */ + sc->sc_writelock = NULL; + sc->sc_writereportid = -1; + sc->sc_writecallback = NULL; + sc->sc_writecookie = NULL; + cv_broadcast(>sc_cv); + } +out: mutex_exit(>sc_lock); + return err; +} Index: src/sys/dev/usb/uhidev.h diff -u src/sys/dev/usb/uhidev.h:1.22 src/sys/dev/usb/uhidev.h:1.23 --- src/sys/dev/usb/uhidev.h:1.22 Mon Mar
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:43:03 UTC 2022 Modified Files: src/sys/dev/usb: ucycom.c uhidev.c uhidev.h Log Message: uhidev(9): New uhidev_write_async. Like uhidev_write but issues the transfer asynchronously with a callback. Use it in ucycom(4). Also, clear endpoint stalls asynchronously -- can't do them synchronously in xfer callbacks which run at softint and therefore can't wait in cv_wait as usbd_do_request does. To generate a diff of this commit: cvs rdiff -u -r1.52 -r1.53 src/sys/dev/usb/ucycom.c cvs rdiff -u -r1.83 -r1.84 src/sys/dev/usb/uhidev.c cvs rdiff -u -r1.22 -r1.23 src/sys/dev/usb/uhidev.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:42:54 UTC 2022 Modified Files: src/sys/dev/usb: ucycom.c uhid.c uhidev.c uhidev.h Log Message: uhidev(9): Partially fix uhidev_write aborting. In my previous change, I intended to make uhidev_stop abort any pending write -- but I forgot to initialize sc->sc_writereportid, so it never did anything. This changes the API and ABI of uhidev_write so it takes the struct uhidev pointer, rather than the struct uhidev_softc pointer; this way uhidev_write knows what the report id of the client is, so it can arrange to have uhidev_stop abort only this one. XXX Except it still doesn't actually work because we do this unlocked, ugh, so the write might complete before we abort anything. To be fixed some more in a later change. XXX kernel ABI change to uhidev_write signature, used by uhidev driver modules, requires bump To generate a diff of this commit: cvs rdiff -u -r1.51 -r1.52 src/sys/dev/usb/ucycom.c cvs rdiff -u -r1.120 -r1.121 src/sys/dev/usb/uhid.c cvs rdiff -u -r1.82 -r1.83 src/sys/dev/usb/uhidev.c cvs rdiff -u -r1.21 -r1.22 src/sys/dev/usb/uhidev.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/dev/usb/ucycom.c diff -u src/sys/dev/usb/ucycom.c:1.51 src/sys/dev/usb/ucycom.c:1.52 --- src/sys/dev/usb/ucycom.c:1.51 Sat Mar 14 02:35:33 2020 +++ src/sys/dev/usb/ucycom.c Mon Mar 28 12:42:54 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: ucycom.c,v 1.51 2020/03/14 02:35:33 christos Exp $ */ +/* $NetBSD: ucycom.c,v 1.52 2022/03/28 12:42:54 riastradh Exp $ */ /* * Copyright (c) 2005 The NetBSD Foundation, Inc. @@ -38,7 +38,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ucycom.c,v 1.51 2020/03/14 02:35:33 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ucycom.c,v 1.52 2022/03/28 12:42:54 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -1105,7 +1105,7 @@ ucycom_set_status(struct ucycom_softc *s memset(sc->sc_obuf, 0, sc->sc_olen); sc->sc_obuf[0] = sc->sc_mcr; - err = uhidev_write(sc->sc_hdev.sc_parent, sc->sc_obuf, sc->sc_olen); + err = uhidev_write(>sc_hdev, sc->sc_obuf, sc->sc_olen); if (err) { DPRINTF(("ucycom_set_status: err=%d\n", err)); } Index: src/sys/dev/usb/uhid.c diff -u src/sys/dev/usb/uhid.c:1.120 src/sys/dev/usb/uhid.c:1.121 --- src/sys/dev/usb/uhid.c:1.120 Mon Mar 28 12:42:45 2022 +++ src/sys/dev/usb/uhid.c Mon Mar 28 12:42:54 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: uhid.c,v 1.120 2022/03/28 12:42:45 riastradh Exp $ */ +/* $NetBSD: uhid.c,v 1.121 2022/03/28 12:42:54 riastradh Exp $ */ /* * Copyright (c) 1998, 2004, 2008, 2012 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: uhid.c,v 1.120 2022/03/28 12:42:45 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uhid.c,v 1.121 2022/03/28 12:42:54 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_compat_netbsd.h" @@ -495,8 +495,7 @@ uhidwrite(dev_t dev, struct uio *uio, in #endif if (!error) { if (sc->sc_raw) - err = uhidev_write(sc->sc_hdev.sc_parent, sc->sc_obuf, - size); + err = uhidev_write(>sc_hdev, sc->sc_obuf, size); else err = uhidev_set_report(>sc_hdev, UHID_OUTPUT_REPORT, sc->sc_obuf, size); Index: src/sys/dev/usb/uhidev.c diff -u src/sys/dev/usb/uhidev.c:1.82 src/sys/dev/usb/uhidev.c:1.83 --- src/sys/dev/usb/uhidev.c:1.82 Wed Feb 9 18:09:48 2022 +++ src/sys/dev/usb/uhidev.c Mon Mar 28 12:42:54 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: uhidev.c,v 1.82 2022/02/09 18:09:48 jakllsch Exp $ */ +/* $NetBSD: uhidev.c,v 1.83 2022/03/28 12:42:54 riastradh Exp $ */ /* * Copyright (c) 2001, 2012 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.82 2022/02/09 18:09:48 jakllsch Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.83 2022/03/28 12:42:54 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -909,7 +909,7 @@ uhidev_stop(struct uhidev *scd) abort = true; mutex_exit(>sc_lock); - if (abort && sc->sc_opipe) + if (abort && sc->sc_opipe) /* XXX sc_opipe might go away */ usbd_abort_pipe(sc->sc_opipe); } @@ -969,8 +969,9 @@ uhidev_get_report(struct uhidev *scd, in } usbd_status -uhidev_write(struct uhidev_softc *sc, void *data, int len) +uhidev_write(struct uhidev *scd, void *data, int len) { + struct uhidev_softc *sc = scd->sc_parent; usbd_status err; DPRINTF(("uhidev_write: data=%p, len=%d\n", data, len)); @@ -993,6 +994,7 @@ uhidev_write(struct uhidev_softc *sc, vo } } sc->sc_writelock = curlwp; + sc->sc_writereportid = scd->sc_report_id; mutex_exit(>sc_lock); #ifdef UHIDEV_DEBUG @@ -1014,6 +1016,10 @@ uhidev_write(struct uhidev_softc *sc, vo KASSERT(sc->sc_refcnt); KASSERTMSG(sc->sc_writelock == curlwp, "%s: migrated from %p to %p", device_xname(sc->sc_dev), curlwp, sc->sc_writelock); + KASSERTMSG(sc->sc_writereportid == scd->sc_report_id, + "%s:
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:42:54 UTC 2022 Modified Files: src/sys/dev/usb: ucycom.c uhid.c uhidev.c uhidev.h Log Message: uhidev(9): Partially fix uhidev_write aborting. In my previous change, I intended to make uhidev_stop abort any pending write -- but I forgot to initialize sc->sc_writereportid, so it never did anything. This changes the API and ABI of uhidev_write so it takes the struct uhidev pointer, rather than the struct uhidev_softc pointer; this way uhidev_write knows what the report id of the client is, so it can arrange to have uhidev_stop abort only this one. XXX Except it still doesn't actually work because we do this unlocked, ugh, so the write might complete before we abort anything. To be fixed some more in a later change. XXX kernel ABI change to uhidev_write signature, used by uhidev driver modules, requires bump To generate a diff of this commit: cvs rdiff -u -r1.51 -r1.52 src/sys/dev/usb/ucycom.c cvs rdiff -u -r1.120 -r1.121 src/sys/dev/usb/uhid.c cvs rdiff -u -r1.82 -r1.83 src/sys/dev/usb/uhidev.c cvs rdiff -u -r1.21 -r1.22 src/sys/dev/usb/uhidev.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:42:45 UTC 2022 Modified Files: src/sys/dev/usb: uhid.c Log Message: uhid(4): Use d_cfdriver/devtounit/cancel to avoid open/detach races. - Split uhidclose into separate uhidcancel and uhidclose parts. uhidcancel interrupts pending I/O operations (open, read, write, ioctl, ); uhidclose doesn't run until all I/O operations are done. - Handle case where, owing to revoke(2), uhidcancel/uhidclose run concurrently with a uhidopen that hasn't yet noticed that there isn't actually a device. - Handle case where, owing to revoke(2), uhidread might be cancelled by mere revoke, not by detach, so it has to wake up when the device is closing, not (just) when dying (but dying will lead to closing so no need to check for dying). - Omit needless reference-counting goo. vdevgone takes care of this for us by cancelling all I/O operations with uhidcancel, waiting for I/O operations to drain, closing the device, and waiting until it is closed if that is already happening concurrently. - Name the closed/changing/open states rather than using 0/1/2. - Omit needless sc_dying. To generate a diff of this commit: cvs rdiff -u -r1.119 -r1.120 src/sys/dev/usb/uhid.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:42:45 UTC 2022 Modified Files: src/sys/dev/usb: uhid.c Log Message: uhid(4): Use d_cfdriver/devtounit/cancel to avoid open/detach races. - Split uhidclose into separate uhidcancel and uhidclose parts. uhidcancel interrupts pending I/O operations (open, read, write, ioctl, ); uhidclose doesn't run until all I/O operations are done. - Handle case where, owing to revoke(2), uhidcancel/uhidclose run concurrently with a uhidopen that hasn't yet noticed that there isn't actually a device. - Handle case where, owing to revoke(2), uhidread might be cancelled by mere revoke, not by detach, so it has to wake up when the device is closing, not (just) when dying (but dying will lead to closing so no need to check for dying). - Omit needless reference-counting goo. vdevgone takes care of this for us by cancelling all I/O operations with uhidcancel, waiting for I/O operations to drain, closing the device, and waiting until it is closed if that is already happening concurrently. - Name the closed/changing/open states rather than using 0/1/2. - Omit needless sc_dying. To generate a diff of this commit: cvs rdiff -u -r1.119 -r1.120 src/sys/dev/usb/uhid.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/dev/usb/uhid.c diff -u src/sys/dev/usb/uhid.c:1.119 src/sys/dev/usb/uhid.c:1.120 --- src/sys/dev/usb/uhid.c:1.119 Sun Sep 26 15:07:17 2021 +++ src/sys/dev/usb/uhid.c Mon Mar 28 12:42:45 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: uhid.c,v 1.119 2021/09/26 15:07:17 thorpej Exp $ */ +/* $NetBSD: uhid.c,v 1.120 2022/03/28 12:42:45 riastradh Exp $ */ /* * Copyright (c) 1998, 2004, 2008, 2012 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: uhid.c,v 1.119 2021/09/26 15:07:17 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uhid.c,v 1.120 2022/03/28 12:42:45 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_compat_netbsd.h" @@ -89,7 +89,6 @@ struct uhid_softc { kmutex_t sc_lock; kcondvar_t sc_cv; - kcondvar_t sc_detach_cv; int sc_isize; int sc_osize; @@ -104,10 +103,13 @@ struct uhid_softc { volatile uint32_t sc_state; /* driver state */ #define UHID_IMMED 0x02 /* return read data immediately */ - int sc_refcnt; int sc_raw; - u_char sc_open; - u_char sc_dying; + enum { + UHID_CLOSED, + UHID_OPENING, + UHID_OPEN, + } sc_open; + bool sc_closing; }; #define UHIDUNIT(dev) (minor(dev)) @@ -115,6 +117,7 @@ struct uhid_softc { #define UHID_BSIZE 1020 /* buffer size */ static dev_type_open(uhidopen); +static dev_type_cancel(uhidcancel); static dev_type_close(uhidclose); static dev_type_read(uhidread); static dev_type_write(uhidwrite); @@ -124,6 +127,7 @@ static dev_type_kqfilter(uhidkqfilter); const struct cdevsw uhid_cdevsw = { .d_open = uhidopen, + .d_cancel = uhidcancel, .d_close = uhidclose, .d_read = uhidread, .d_write = uhidwrite, @@ -134,22 +138,19 @@ const struct cdevsw uhid_cdevsw = { .d_mmap = nommap, .d_kqfilter = uhidkqfilter, .d_discard = nodiscard, + .d_cfdriver = _cd, + .d_devtounit = dev_minor_unit, .d_flag = D_OTHER }; -Static void uhid_intr(struct uhidev *, void *, u_int); - -Static int uhid_do_read(struct uhid_softc *, struct uio *, int); -Static int uhid_do_write(struct uhid_softc *, struct uio *, int); -Static int uhid_do_ioctl(struct uhid_softc*, u_long, void *, int, struct lwp *); +static void uhid_intr(struct uhidev *, void *, u_int); static int uhid_match(device_t, cfdata_t, void *); static void uhid_attach(device_t, device_t, void *); static int uhid_detach(device_t, int); -static int uhid_activate(device_t, enum devact); CFATTACH_DECL_NEW(uhid, sizeof(struct uhid_softc), uhid_match, uhid_attach, -uhid_detach, uhid_activate); +uhid_detach, NULL); static int uhid_match(device_t parent, cfdata_t match, void *aux) @@ -194,7 +195,6 @@ uhid_attach(device_t parent, device_t se mutex_init(>sc_lock, MUTEX_DEFAULT, IPL_SOFTUSB); cv_init(>sc_cv, "uhidrea"); - cv_init(>sc_detach_cv, "uhiddet"); if (!pmf_device_register(self, NULL, NULL)) aprint_error_dev(self, "couldn't establish power handler\n"); @@ -203,20 +203,6 @@ uhid_attach(device_t parent, device_t se } static int -uhid_activate(device_t self, enum devact act) -{ - struct uhid_softc *sc = device_private(self); - - switch (act) { - case DVACT_DEACTIVATE: - sc->sc_dying = 1; - return 0; - default: - return EOPNOTSUPP; - } -} - -static int uhid_detach(device_t self, int flags) { struct uhid_softc *sc = device_private(self); @@ -224,24 +210,6 @@ uhid_detach(device_t self, int flags) DPRINTF(("uhid_detach: sc=%p flags=%d\n", sc, flags)); - /* Prevent new I/O operations, and interrupt any pending reads. */ - mutex_enter(>sc_lock); - sc->sc_dying = 1; - cv_broadcast(>sc_cv); - mutex_exit(>sc_lock); - - /* Interrupt
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:42:37 UTC 2022 Modified Files: src/sys/dev/usb: ucom.c Log Message: ucom(4): Rework open/close/attach/detach logic. - Defer sleep after hangup until open. No need to make close hang; we just need to make sure some time has passed before we next try to open. This changes the wchan for the sleep. Oh well. - Use .d_cfdriver/devtounit/cancel to resolve races between attach, detach, open, close, and revoke. - Use a separate .sc_closing flag instead of a UCOM_CLOSING state. ucomcancel/ucomclose owns this flag, and it may be set in any state (except UCOM_DEAD). UCOM_OPENING remains owned by ucomopen, which might be interrupted by cancel/close. - Rework error branches in ucomopen. Much simpler this way. - Nix unnecessary reference counting. To generate a diff of this commit: cvs rdiff -u -r1.129 -r1.130 src/sys/dev/usb/ucom.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/dev/usb/ucom.c diff -u src/sys/dev/usb/ucom.c:1.129 src/sys/dev/usb/ucom.c:1.130 --- src/sys/dev/usb/ucom.c:1.129 Thu Jun 24 08:20:42 2021 +++ src/sys/dev/usb/ucom.c Mon Mar 28 12:42:37 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: ucom.c,v 1.129 2021/06/24 08:20:42 riastradh Exp $ */ +/* $NetBSD: ucom.c,v 1.130 2022/03/28 12:42:37 riastradh Exp $ */ /* * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ucom.c,v 1.129 2021/06/24 08:20:42 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ucom.c,v 1.130 2022/03/28 12:42:37 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_usb.h" @@ -180,11 +180,10 @@ struct ucom_softc { UCOM_DEAD, UCOM_ATTACHED, UCOM_OPENING, - UCOM_CLOSING, UCOM_OPEN } sc_state; - int sc_refcnt; - bool sc_dying; /* disconnecting */ + bool sc_closing; /* software is closing */ + bool sc_dying; /* hardware is gone */ struct pps_state sc_pps_state; /* pps state */ @@ -192,10 +191,12 @@ struct ucom_softc { kmutex_t sc_lock; kcondvar_t sc_statecv; - kcondvar_t sc_detachcv; + + struct timeval sc_hup_time; }; dev_type_open(ucomopen); +dev_type_cancel(ucomcancel); dev_type_close(ucomclose); dev_type_read(ucomread); dev_type_write(ucomwrite); @@ -206,6 +207,7 @@ dev_type_poll(ucompoll); const struct cdevsw ucom_cdevsw = { .d_open = ucomopen, + .d_cancel = ucomcancel, .d_close = ucomclose, .d_read = ucomread, .d_write = ucomwrite, @@ -216,16 +218,16 @@ const struct cdevsw ucom_cdevsw = { .d_mmap = nommap, .d_kqfilter = ttykqfilter, .d_discard = nodiscard, + .d_cfdriver = _cd, + .d_devtounit = dev_minor_unit, .d_flag = D_TTY | D_MPSAFE }; -static void ucom_cleanup(struct ucom_softc *); +static void ucom_cleanup(struct ucom_softc *, int); static int ucomparam(struct tty *, struct termios *); static int ucomhwiflow(struct tty *, int); static void ucomstart(struct tty *); static void ucom_shutdown(struct ucom_softc *); -static int ucom_do_ioctl(struct ucom_softc *, u_long, void *, - int, struct lwp *); static void ucom_dtr(struct ucom_softc *, int); static void ucom_rts(struct ucom_softc *, int); static void ucom_break(struct ucom_softc *, int); @@ -288,14 +290,13 @@ ucom_attach(device_t parent, device_t se sc->sc_mcr = 0; sc->sc_tx_stopped = 0; sc->sc_swflags = 0; - sc->sc_refcnt = 0; + sc->sc_closing = false; sc->sc_dying = false; sc->sc_state = UCOM_DEAD; sc->sc_si = softint_establish(SOFTINT_USB, ucom_softintr, sc); mutex_init(>sc_lock, MUTEX_DEFAULT, IPL_SOFTUSB); cv_init(>sc_statecv, "ucomstate"); - cv_init(>sc_detachcv, "ucomdtch"); SIMPLEQ_INIT(>sc_ibuff_empty); SIMPLEQ_INIT(>sc_ibuff_full); @@ -366,7 +367,6 @@ ucom_attach(device_t parent, device_t se aprint_error_dev(self, "couldn't establish power handler\n"); sc->sc_state = UCOM_ATTACHED; - return; fail_2: @@ -375,8 +375,8 @@ fail_2: if (ub->ub_xfer) usbd_destroy_xfer(ub->ub_xfer); } - usbd_close_pipe(sc->sc_bulkout_pipe); + sc->sc_bulkout_pipe = NULL; fail_1: for (ub = >sc_ibuff[0]; ub != >sc_ibuff[UCOM_IN_BUFFS]; @@ -385,11 +385,10 @@ fail_1: usbd_destroy_xfer(ub->ub_xfer); } usbd_close_pipe(sc->sc_bulkin_pipe); + sc->sc_bulkin_pipe = NULL; fail_0: aprint_error_dev(self, "attach failed, error=%d\n", error); - - return; } int @@ -406,49 +405,21 @@ ucom_detach(device_t self, int flags) (uintptr_t)tp, 0); DPRINTF("... pipe=%jd,%jd", sc->sc_bulkin_no, sc->sc_bulkout_no, 0, 0); + /* Prevent new opens from hanging. */ mutex_enter(>sc_lock); sc->sc_dying = true; mutex_exit(>sc_lock); pmf_device_deregister(self); - if (sc->sc_bulkin_pipe != NULL) { - usbd_abort_pipe(sc->sc_bulkin_pipe); - } - if (sc->sc_bulkout_pipe != NULL) { - usbd_abort_pipe(sc->sc_bulkout_pipe); - } - - mutex_enter(>sc_lock); - - /* wait for open/close to
CVS commit: src/sys/dev/usb
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:42:37 UTC 2022 Modified Files: src/sys/dev/usb: ucom.c Log Message: ucom(4): Rework open/close/attach/detach logic. - Defer sleep after hangup until open. No need to make close hang; we just need to make sure some time has passed before we next try to open. This changes the wchan for the sleep. Oh well. - Use .d_cfdriver/devtounit/cancel to resolve races between attach, detach, open, close, and revoke. - Use a separate .sc_closing flag instead of a UCOM_CLOSING state. ucomcancel/ucomclose owns this flag, and it may be set in any state (except UCOM_DEAD). UCOM_OPENING remains owned by ucomopen, which might be interrupted by cancel/close. - Rework error branches in ucomopen. Much simpler this way. - Nix unnecessary reference counting. To generate a diff of this commit: cvs rdiff -u -r1.129 -r1.130 src/sys/dev/usb/ucom.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/kern
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:41:17 UTC 2022 Modified Files: src/sys/kern: subr_devsw.c Log Message: subr_devsw.c: KNF and style nits. No functional change intended. To generate a diff of this commit: cvs rdiff -u -r1.44 -r1.45 src/sys/kern/subr_devsw.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/kern/subr_devsw.c diff -u src/sys/kern/subr_devsw.c:1.44 src/sys/kern/subr_devsw.c:1.45 --- src/sys/kern/subr_devsw.c:1.44 Mon Mar 28 12:39:10 2022 +++ src/sys/kern/subr_devsw.c Mon Mar 28 12:41:17 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: subr_devsw.c,v 1.44 2022/03/28 12:39:10 riastradh Exp $ */ +/* $NetBSD: subr_devsw.c,v 1.45 2022/03/28 12:41:17 riastradh Exp $ */ /*- * Copyright (c) 2001, 2002, 2007, 2008 The NetBSD Foundation, Inc. @@ -28,7 +28,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ - + /* * Overview * @@ -69,7 +69,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: subr_devsw.c,v 1.44 2022/03/28 12:39:10 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: subr_devsw.c,v 1.45 2022/03/28 12:41:17 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_dtrace.h" @@ -146,11 +146,11 @@ devsw_attach(const char *devname, int error, i; if (devname == NULL || cdev == NULL) - return (EINVAL); + return EINVAL; mutex_enter(_lock); - for (i = 0 ; i < max_devsw_convs ; i++) { + for (i = 0; i < max_devsw_convs; i++) { conv = _conv[i]; if (conv->d_name == NULL || strcmp(devname, conv->d_name) != 0) continue; @@ -162,17 +162,17 @@ devsw_attach(const char *devname, if (*bmajor != conv->d_bmajor || *cmajor != conv->d_cmajor) { error = EINVAL; - goto fail; + goto out; } if ((*bmajor >= 0 && bdev == NULL) || *cmajor < 0) { error = EINVAL; - goto fail; + goto out; } if ((*bmajor >= 0 && bdevsw[*bmajor] != NULL) || cdevsw[*cmajor] != NULL) { error = EEXIST; - goto fail; + goto out; } break; } @@ -182,12 +182,12 @@ devsw_attach(const char *devname, * need to flail around trying to unwind. */ error = bdevsw_attach(bdev, bmajor); - if (error != 0) - goto fail; + if (error != 0) + goto out; error = cdevsw_attach(cdev, cmajor); if (error != 0) { devsw_detach_locked(bdev, NULL); - goto fail; + goto out; } /* @@ -195,9 +195,9 @@ devsw_attach(const char *devname, * empty slot or extend the table. */ if (i == max_devsw_convs) - goto fail; + goto out; - for (i = 0 ; i < max_devsw_convs ; i++) { + for (i = 0; i < max_devsw_convs; i++) { if (devsw_conv[i].d_name == NULL) break; } @@ -212,7 +212,7 @@ devsw_attach(const char *devname, if (newptr == NULL) { devsw_detach_locked(bdev, cdev); error = ENOMEM; - goto fail; + goto out; } newptr[old_convs].d_name = NULL; newptr[old_convs].d_bmajor = -1; @@ -228,18 +228,16 @@ devsw_attach(const char *devname, if (name == NULL) { devsw_detach_locked(bdev, cdev); error = ENOMEM; - goto fail; + goto out; } devsw_conv[i].d_name = name; devsw_conv[i].d_bmajor = *bmajor; devsw_conv[i].d_cmajor = *cmajor; - - mutex_exit(_lock); - return (0); - fail: + error = 0; +out: mutex_exit(_lock); - return (error); + return error; } static int @@ -254,13 +252,13 @@ bdevsw_attach(const struct bdevsw *devsw KASSERT(mutex_owned(_lock)); if (devsw == NULL) - return (0); + return 0; if (*devmajor < 0) { - for (bmajor = sys_bdevsws ; bmajor < max_bdevsws ; bmajor++) { + for (bmajor = sys_bdevsws; bmajor < max_bdevsws; bmajor++) { if (bdevsw[bmajor] != NULL) continue; - for (i = 0 ; i < max_devsw_convs ; i++) { + for (i = 0; i < max_devsw_convs; i++) { if (devsw_conv[i].d_bmajor == bmajor) break; } @@ -272,8 +270,8 @@ bdevsw_attach(const struct bdevsw *devsw } if (*devmajor >= MAXDEVSW) { - printf("%s: block majors exhausted", __func__); - return (ENOMEM); + printf("%s: block majors exhausted\n", __func__); + return ENOMEM; } if (bdevswref == NULL) { @@ -296,7 +294,7 @@ bdevsw_attach(const struct bdevsw *devsw } if (bdevsw[*devmajor] != NULL) - return (EEXIST); + return EEXIST; KASSERT(bdevswref[*devmajor].dr_lc == NULL); lc = kmem_zalloc(sizeof(*lc), KM_SLEEP); @@ -305,7 +303,7 @@ bdevsw_attach(const struct bdevsw *devsw atomic_store_release([*devmajor], devsw); - return (0); + return 0; } static int @@ -320,10 +318,10 @@ cdevsw_attach(const struct cdevsw *devsw KASSERT(mutex_owned(_lock)); if (*devmajor < 0) { - for (cmajor = sys_cdevsws ; cmajor < max_cdevsws ; cmajor++) { + for (cmajor = sys_cdevsws; cmajor < max_cdevsws; cmajor++) { if (cdevsw[cmajor] != NULL) continue; - for (i = 0 ; i < max_devsw_convs ; i++) { + for (i = 0; i < max_devsw_convs; i++) { if (devsw_conv[i].d_cmajor == cmajor)
CVS commit: src/sys/kern
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:41:17 UTC 2022 Modified Files: src/sys/kern: subr_devsw.c Log Message: subr_devsw.c: KNF and style nits. No functional change intended. To generate a diff of this commit: cvs rdiff -u -r1.44 -r1.45 src/sys/kern/subr_devsw.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/dev/audio
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:39:57 UTC 2022 Modified Files: src/sys/dev/audio: audio.c Log Message: audio(4): Use d_cfdriver/devtounit to avoid open/detach races. To generate a diff of this commit: cvs rdiff -u -r1.120 -r1.121 src/sys/dev/audio/audio.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/dev/audio/audio.c diff -u src/sys/dev/audio/audio.c:1.120 src/sys/dev/audio/audio.c:1.121 --- src/sys/dev/audio/audio.c:1.120 Sat Mar 26 06:49:27 2022 +++ src/sys/dev/audio/audio.c Mon Mar 28 12:39:57 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: audio.c,v 1.120 2022/03/26 06:49:27 isaki Exp $ */ +/* $NetBSD: audio.c,v 1.121 2022/03/28 12:39:57 riastradh Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -181,7 +181,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.120 2022/03/26 06:49:27 isaki Exp $"); +__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.121 2022/03/28 12:39:57 riastradh Exp $"); #ifdef _KERNEL_OPT #include "audio.h" @@ -567,7 +567,6 @@ static int audio_exlock_mutex_enter(stru static void audio_exlock_mutex_exit(struct audio_softc *); static int audio_exlock_enter(struct audio_softc *); static void audio_exlock_exit(struct audio_softc *); -static void audio_sc_acquire_foropen(struct audio_softc *, struct psref *); static struct audio_softc *audio_sc_acquire_fromfile(audio_file_t *, struct psref *); static void audio_sc_release(struct audio_softc *, struct psref *); @@ -766,6 +765,13 @@ audio_volume_to_outer(u_int v) static dev_type_open(audioopen); /* XXXMRG use more dev_type_xxx */ +static int +audiounit(dev_t dev) +{ + + return AUDIOUNIT(dev); +} + const struct cdevsw audio_cdevsw = { .d_open = audioopen, .d_close = noclose, @@ -778,6 +784,8 @@ const struct cdevsw audio_cdevsw = { .d_mmap = nommap, .d_kqfilter = nokqfilter, .d_discard = nodiscard, + .d_cfdriver = _cd, + .d_devtounit = audiounit, .d_flag = D_OTHER | D_MPSAFE }; @@ -1590,31 +1598,6 @@ audio_exlock_exit(struct audio_softc *sc } /* - * Increment reference counter for this sc. - * This is intended to be used for open. - */ -void -audio_sc_acquire_foropen(struct audio_softc *sc, struct psref *refp) -{ - int s; - - /* Block audiodetach while we acquire a reference */ - s = pserialize_read_enter(); - - /* - * We don't examine sc_dying here. However, all open methods - * call audio_exlock_enter() right after this, so we can examine - * sc_dying in it. - */ - - /* Acquire a reference */ - psref_acquire(refp, >sc_psref, audio_psref_class); - - /* Now sc won't go away until we drop the reference count */ - pserialize_read_exit(s); -} - -/* * Get sc from file, and increment reference counter for this sc. * This is intended to be used for methods other than open. * If successful, returns sc. Otherwise returns NULL. @@ -1732,21 +1715,20 @@ static int audioopen(dev_t dev, int flags, int ifmt, struct lwp *l) { struct audio_softc *sc; - struct psref sc_ref; - int bound; int error; - /* Find the device */ + /* + * Find the device. Because we wired the cdevsw to the audio + * autoconf instance, the system ensures it will not go away + * until after we return. + */ sc = device_lookup_private(_cd, AUDIOUNIT(dev)); if (sc == NULL || sc->hw_if == NULL) return ENXIO; - bound = curlwp_bind(); - audio_sc_acquire_foropen(sc, _ref); - error = audio_exlock_enter(sc); if (error) - goto done; + return error; device_active(sc->sc_dev, DVA_SYSTEM); switch (AUDIODEV(dev)) { @@ -1766,9 +1748,6 @@ audioopen(dev_t dev, int flags, int ifmt } audio_exlock_exit(sc); -done: - audio_sc_release(sc, _ref); - curlwp_bindx(bound); return error; } @@ -2150,30 +2129,42 @@ done: int audiobellopen(dev_t dev, audio_file_t **filep) { + device_t audiodev = NULL; struct audio_softc *sc; - struct psref sc_ref; - int bound; + bool exlock = false; int error; - /* Find the device */ - sc = device_lookup_private(_cd, AUDIOUNIT(dev)); - if (sc == NULL || sc->hw_if == NULL) - return ENXIO; + /* + * Find the autoconf instance and make sure it doesn't go away + * while we are opening it. + */ + audiodev = device_lookup_acquire(_cd, AUDIOUNIT(dev)); + if (audiodev == NULL) { + error = ENXIO; + goto out; + } - bound = curlwp_bind(); - audio_sc_acquire_foropen(sc, _ref); + /* If attach failed, it's hopeless -- give up. */ + sc = device_private(audiodev); + if (sc->hw_if == NULL) { + error = ENXIO; + goto out; + } + /* Take the exclusive configuration lock. */ error = audio_exlock_enter(sc); if (error) - goto done; + goto out; + exlock = true; + /* Open the audio device. */ device_active(sc->sc_dev, DVA_SYSTEM); error = audio_open(dev, sc, FWRITE, 0, curlwp, filep); - audio_exlock_exit(sc); -done: - audio_sc_release(sc, _ref); - curlwp_bindx(bound); +out: if (exlock) + audio_exlock_exit(sc); + if
CVS commit: src/sys/dev/audio
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:39:57 UTC 2022 Modified Files: src/sys/dev/audio: audio.c Log Message: audio(4): Use d_cfdriver/devtounit to avoid open/detach races. To generate a diff of this commit: cvs rdiff -u -r1.120 -r1.121 src/sys/dev/audio/audio.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/dev/scsipi
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:39:47 UTC 2022 Modified Files: src/sys/dev/scsipi: sd.c Log Message: sd(4): Use d_cfdriver/devtounit to avoid open/detach races. To generate a diff of this commit: cvs rdiff -u -r1.333 -r1.334 src/sys/dev/scsipi/sd.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/dev/scsipi/sd.c diff -u src/sys/dev/scsipi/sd.c:1.333 src/sys/dev/scsipi/sd.c:1.334 --- src/sys/dev/scsipi/sd.c:1.333 Thu Jan 27 18:44:49 2022 +++ src/sys/dev/scsipi/sd.c Mon Mar 28 12:39:46 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: sd.c,v 1.333 2022/01/27 18:44:49 jakllsch Exp $ */ +/* $NetBSD: sd.c,v 1.334 2022/03/28 12:39:46 riastradh Exp $ */ /*- * Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc. @@ -47,7 +47,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: sd.c,v 1.333 2022/01/27 18:44:49 jakllsch Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sd.c,v 1.334 2022/03/28 12:39:46 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_scsi.h" @@ -167,6 +167,8 @@ const struct bdevsw sd_bdevsw = { .d_dump = sddump, .d_psize = sdsize, .d_discard = nodiscard, + .d_cfdriver = _cd, + .d_devtounit = disklabel_dev_unit, .d_flag = D_DISK | D_MPSAFE }; @@ -182,6 +184,8 @@ const struct cdevsw sd_cdevsw = { .d_mmap = nommap, .d_kqfilter = nokqfilter, .d_discard = nodiscard, + .d_cfdriver = _cd, + .d_devtounit = disklabel_dev_unit, .d_flag = D_DISK | D_MPSAFE };
CVS commit: src/sys/dev/scsipi
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:39:47 UTC 2022 Modified Files: src/sys/dev/scsipi: sd.c Log Message: sd(4): Use d_cfdriver/devtounit to avoid open/detach races. To generate a diff of this commit: cvs rdiff -u -r1.333 -r1.334 src/sys/dev/scsipi/sd.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/dev/ata
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:39:37 UTC 2022 Modified Files: src/sys/dev/ata: wd.c Log Message: wd(4): Use d_cfdriver/devtounit to avoid open/detach races. To generate a diff of this commit: cvs rdiff -u -r1.466 -r1.467 src/sys/dev/ata/wd.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/dev/ata/wd.c diff -u src/sys/dev/ata/wd.c:1.466 src/sys/dev/ata/wd.c:1.467 --- src/sys/dev/ata/wd.c:1.466 Tue Dec 28 13:27:32 2021 +++ src/sys/dev/ata/wd.c Mon Mar 28 12:39:37 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: wd.c,v 1.466 2021/12/28 13:27:32 riastradh Exp $ */ +/* $NetBSD: wd.c,v 1.467 2022/03/28 12:39:37 riastradh Exp $ */ /* * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved. @@ -54,7 +54,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.466 2021/12/28 13:27:32 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.467 2022/03/28 12:39:37 riastradh Exp $"); #include "opt_ata.h" #include "opt_wd.h" @@ -152,6 +152,8 @@ const struct bdevsw wd_bdevsw = { .d_dump = wddump, .d_psize = wdsize, .d_discard = wddiscard, + .d_cfdriver = _cd, + .d_devtounit = disklabel_dev_unit, .d_flag = D_DISK }; @@ -167,6 +169,8 @@ const struct cdevsw wd_cdevsw = { .d_mmap = nommap, .d_kqfilter = nokqfilter, .d_discard = wddiscard, + .d_cfdriver = _cd, + .d_devtounit = disklabel_dev_unit, .d_flag = D_DISK };
CVS commit: src/sys/dev/ata
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:39:37 UTC 2022 Modified Files: src/sys/dev/ata: wd.c Log Message: wd(4): Use d_cfdriver/devtounit to avoid open/detach races. To generate a diff of this commit: cvs rdiff -u -r1.466 -r1.467 src/sys/dev/ata/wd.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:39:29 UTC 2022 Modified Files: src/sys/kern: tty.c src/sys/sys: tty.h Log Message: tty(9): New ttycancel function. This causes any current and future ttyopens to fail until ttyclose. This is necessary for revoke to work reliably for device detach like ucom(4) removable USB devices. A tty driver for a removable device needs some way to interrupt a pending .d_open so it returns promptly. But ttyclose only interrupts ttyopen if it's already sleeping; it won't cause a concurrent .d_open call which _will call_ but _hasn't yet called_ ttyopen to avoid sleeping. Using ttycancel in the tty driver's .d_cancel makes this work. To generate a diff of this commit: cvs rdiff -u -r1.299 -r1.300 src/sys/kern/tty.c cvs rdiff -u -r1.95 -r1.96 src/sys/sys/tty.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/kern/tty.c diff -u src/sys/kern/tty.c:1.299 src/sys/kern/tty.c:1.300 --- src/sys/kern/tty.c:1.299 Sun Dec 5 07:44:53 2021 +++ src/sys/kern/tty.c Mon Mar 28 12:39:28 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: tty.c,v 1.299 2021/12/05 07:44:53 msaitoh Exp $ */ +/* $NetBSD: tty.c,v 1.300 2022/03/28 12:39:28 riastradh Exp $ */ /*- * Copyright (c) 2008, 2020 The NetBSD Foundation, Inc. @@ -63,7 +63,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: tty.c,v 1.299 2021/12/05 07:44:53 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tty.c,v 1.300 2022/03/28 12:39:28 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_compat_netbsd.h" @@ -420,6 +420,21 @@ ttylopen(dev_t device, struct tty *tp) } /* + * Interrupt any pending I/O and make it fail. Used before close to + * interrupt pending open/read/write/ and make it fail promptly. + */ +void +ttycancel(struct tty *tp) +{ + + mutex_spin_enter(_lock); + tp->t_state |= TS_CANCEL; + cv_broadcast(>t_outcv); + cv_broadcast(>t_rawcv); + mutex_spin_exit(_lock); +} + +/* * Handle close() on a tty line: flush and set to initial state, * bumping generation number so that pending read/write calls * can detect recycling of the tty. @@ -2750,7 +2765,9 @@ ttysleep(struct tty *tp, kcondvar_t *cv, KASSERT(mutex_owned(_lock)); gen = tp->t_gen; - if (cv == NULL) + if (ISSET(tp->t_state, TS_CANCEL)) + error = ERESTART; + else if (cv == NULL) error = kpause("ttypause", catch_p, timo, _lock); else if (catch_p) error = cv_timedwait_sig(cv, _lock, timo); Index: src/sys/sys/tty.h diff -u src/sys/sys/tty.h:1.95 src/sys/sys/tty.h:1.96 --- src/sys/sys/tty.h:1.95 Sun Jan 27 02:08:50 2019 +++ src/sys/sys/tty.h Mon Mar 28 12:39:28 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: tty.h,v 1.95 2019/01/27 02:08:50 pgoyette Exp $ */ +/* $NetBSD: tty.h,v 1.96 2022/03/28 12:39:28 riastradh Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -207,6 +207,8 @@ struct tty { #define TS_KERN_ONLY 0x1 /* Device is accessible by kernel * only, deny all userland access */ +#define TS_CANCEL 0x2 /* I/O cancelled pending close. */ + /* Character type information. */ #define ORDINARY 0 #define CONTROL 1 @@ -281,6 +283,7 @@ void ttwakeup(struct tty *); int ttwrite(struct tty *, struct uio *, int); void ttychars(struct tty *); int ttycheckoutq(struct tty *, int); +void ttycancel(struct tty *); int ttyclose(struct tty *); void ttyflush(struct tty *, int); void ttygetinfo(struct tty *, int, char *, size_t);
CVS commit: src/sys
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:39:29 UTC 2022 Modified Files: src/sys/kern: tty.c src/sys/sys: tty.h Log Message: tty(9): New ttycancel function. This causes any current and future ttyopens to fail until ttyclose. This is necessary for revoke to work reliably for device detach like ucom(4) removable USB devices. A tty driver for a removable device needs some way to interrupt a pending .d_open so it returns promptly. But ttyclose only interrupts ttyopen if it's already sleeping; it won't cause a concurrent .d_open call which _will call_ but _hasn't yet called_ ttyopen to avoid sleeping. Using ttycancel in the tty driver's .d_cancel makes this work. To generate a diff of this commit: cvs rdiff -u -r1.299 -r1.300 src/sys/kern/tty.c cvs rdiff -u -r1.95 -r1.96 src/sys/sys/tty.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:39:18 UTC 2022 Modified Files: src/sys/sys: conf.h src/sys/uvm: uvm_device.c Log Message: driver(9): New types dev_*_t for device driver devsw operations. These will serve to replace the archaic and kludgey dev_type_* macros which should've been typedefs all along. To generate a diff of this commit: cvs rdiff -u -r1.160 -r1.161 src/sys/sys/conf.h cvs rdiff -u -r1.72 -r1.73 src/sys/uvm/uvm_device.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/sys/conf.h diff -u src/sys/sys/conf.h:1.160 src/sys/sys/conf.h:1.161 --- src/sys/sys/conf.h:1.160 Mon Mar 28 12:39:10 2022 +++ src/sys/sys/conf.h Mon Mar 28 12:39:18 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: conf.h,v 1.160 2022/03/28 12:39:10 riastradh Exp $ */ +/* $NetBSD: conf.h,v 1.161 2022/03/28 12:39:18 riastradh Exp $ */ /*- * Copyright (c) 1990, 1993 @@ -116,22 +116,37 @@ const struct cdevsw *cdevsw_lookup(dev_t devmajor_t bdevsw_lookup_major(const struct bdevsw *); devmajor_t cdevsw_lookup_major(const struct cdevsw *); -#define dev_type_open(n) int n (dev_t, int, int, struct lwp *) -#define dev_type_cancel(n) int n (dev_t, int, int, struct lwp *) -#define dev_type_close(n) int n (dev_t, int, int, struct lwp *) -#define dev_type_read(n) int n (dev_t, struct uio *, int) -#define dev_type_write(n) int n (dev_t, struct uio *, int) -#define dev_type_ioctl(n) \ - int n (dev_t, u_long, void *, int, struct lwp *) -#define dev_type_stop(n) void n (struct tty *, int) -#define dev_type_tty(n) struct tty * n (dev_t) -#define dev_type_poll(n) int n (dev_t, int, struct lwp *) -#define dev_type_mmap(n) paddr_t n (dev_t, off_t, int) -#define dev_type_strategy(n) void n (struct buf *) -#define dev_type_dump(n) int n (dev_t, daddr_t, void *, size_t) -#define dev_type_size(n) int n (dev_t) -#define dev_type_kqfilter(n) int n (dev_t, struct knote *) -#define dev_type_discard(n) int n (dev_t, off_t, off_t) +typedef int dev_open_t(dev_t, int, int, struct lwp *); +typedef int dev_cancel_t(dev_t, int, int, struct lwp *); +typedef int dev_close_t(dev_t, int, int, struct lwp *); +typedef int dev_read_t(dev_t, struct uio *, int); +typedef int dev_write_t(dev_t, struct uio *, int); +typedef int dev_ioctl_t(dev_t, u_long, void *, int, struct lwp *); +typedef void dev_stop_t(struct tty *, int); +typedef struct tty *dev_tty_t(dev_t); +typedef int dev_poll_t(dev_t, int, struct lwp *); +typedef paddr_t dev_mmap_t(dev_t, off_t, int); +typedef void dev_strategy_t(struct buf *); +typedef int dev_dump_t(dev_t, daddr_t, void *, size_t); +typedef int dev_size_t(dev_t); +typedef int dev_kqfilter_t(dev_t, struct knote *); +typedef int dev_discard_t(dev_t, off_t, off_t); + +#define dev_type_open(n) dev_open_t n +#define dev_type_cancel(n) dev_cancel_t n +#define dev_type_close(n) dev_close_t n +#define dev_type_read(n) dev_read_t n +#define dev_type_write(n) dev_write_t n +#define dev_type_ioctl(n) dev_ioctl_t n +#define dev_type_stop(n) dev_stop_t n +#define dev_type_tty(n) dev_tty_t n +#define dev_type_poll(n) dev_poll_t n +#define dev_type_mmap(n) dev_mmap_t n +#define dev_type_strategy(n) dev_strategy_t n +#define dev_type_dump(n) dev_dump_t n +#define dev_type_size(n) dev_size_t n +#define dev_type_kqfilter(n) dev_kqfilter_t n +#define dev_type_discard(n) dev_discard_t n int devenodev(dev_t, ...); int deveopnotsupp(dev_t, ...); @@ -140,30 +155,30 @@ int ttyenodev(struct tty *, ...); void ttyvenodev(struct tty *, ...); void ttyvnullop(struct tty *, ...); -#define noopen ((dev_type_open((*)))devenodev) -#define noclose ((dev_type_close((*)))devenodev) -#define noread ((dev_type_read((*)))devenodev) -#define nowrite ((dev_type_write((*)))devenodev) -#define noioctl ((dev_type_ioctl((*)))devenodev) -#define nostop ((dev_type_stop((*)))ttyvenodev) +#define noopen ((dev_open_t *)devenodev) +#define noclose ((dev_close_t *)devenodev) +#define noread ((dev_read_t *)devenodev) +#define nowrite ((dev_write_t *)devenodev) +#define noioctl ((dev_ioctl_t *)devenodev) +#define nostop ((dev_stop_t *)ttyvenodev) #define notty NULL #define nopoll seltrue paddr_t nommap(dev_t, off_t, int); -#define nodump ((dev_type_dump((*)))devenodev) +#define nodump ((dev_dump_t *)devenodev) #define nosize NULL #define nokqfilter seltrue_kqfilter -#define nodiscard ((dev_type_discard((*)))devenodev) +#define nodiscard ((dev_discard_t *)devenodev) -#define nullopen ((dev_type_open((*)))devnullop) -#define nullclose ((dev_type_close((*)))devnullop) -#define nullread ((dev_type_read((*)))devnullop) -#define nullwrite ((dev_type_write((*)))devnullop) -#define nullioctl ((dev_type_ioctl((*)))devnullop) -#define nullstop ((dev_type_stop((*)))ttyvnullop) -#define nullpoll ((dev_type_poll((*)))devnullop) -#define nulldump ((dev_type_dump((*)))devnullop) -#define nullkqfilter
CVS commit: src/sys
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:39:18 UTC 2022 Modified Files: src/sys/sys: conf.h src/sys/uvm: uvm_device.c Log Message: driver(9): New types dev_*_t for device driver devsw operations. These will serve to replace the archaic and kludgey dev_type_* macros which should've been typedefs all along. To generate a diff of this commit: cvs rdiff -u -r1.160 -r1.161 src/sys/sys/conf.h cvs rdiff -u -r1.72 -r1.73 src/sys/uvm/uvm_device.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:39:10 UTC 2022 Modified Files: src/sys/kern: subr_devsw.c src/sys/miscfs/specfs: spec_vnops.c src/sys/sys: conf.h Log Message: driver(9): New devsw d_cancel op to interrupt I/O before close. If specified, when revoking a device node or closing its last open node, specfs will: 1. Call d_cancel, which should return promptly without blocking. 2. Wait for all concurrent d_read/write/ioctl/ to drain. 3. Call d_close. Otherwise, specfs will: 1. Call d_close. 2. Wait for all concurrent d_read/write/ioctl/ to drain. This fallback is problematic because often parts of d_close rely on concurrent devsw operations to have completed already, so it is up to each driver to have its own mechanism for waiting, and the extra step in (2) is almost redundant. But it is still important to ensure that devsw operations are not active by the time a module tries to invoke devsw_detach, because only d_open is protected against that. The signature of d_cancel matches d_close, mostly so we don't raise questions about `why is this different?'; the lwp argument is not useful but we should remove it from open/cancel/close all at the same time. The only way d_cancel should fail, if it does at all, is with ENODEV, meaning the driver doesn't support cancelling outstanding I/O, and will take responsibility for that in d_close. I would make it return void and only have bdev_cancel and cdev_cancel possibly return ENODEV so specfs can detect whether a driver supports it, but this would break the pattern around devsw operation types. Drivers are allowed to omit it from struct bdevsw, struct cdevsw -- if so, it is as if they used a function that just returns ENODEV. XXX kernel ABI change to struct bdevsw/cdevsw requires bump To generate a diff of this commit: cvs rdiff -u -r1.43 -r1.44 src/sys/kern/subr_devsw.c cvs rdiff -u -r1.209 -r1.210 src/sys/miscfs/specfs/spec_vnops.c cvs rdiff -u -r1.159 -r1.160 src/sys/sys/conf.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/kern/subr_devsw.c diff -u src/sys/kern/subr_devsw.c:1.43 src/sys/kern/subr_devsw.c:1.44 --- src/sys/kern/subr_devsw.c:1.43 Mon Mar 28 12:38:33 2022 +++ src/sys/kern/subr_devsw.c Mon Mar 28 12:39:10 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: subr_devsw.c,v 1.43 2022/03/28 12:38:33 riastradh Exp $ */ +/* $NetBSD: subr_devsw.c,v 1.44 2022/03/28 12:39:10 riastradh Exp $ */ /*- * Copyright (c) 2001, 2002, 2007, 2008 The NetBSD Foundation, Inc. @@ -69,7 +69,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: subr_devsw.c,v 1.43 2022/03/28 12:38:33 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: subr_devsw.c,v 1.44 2022/03/28 12:39:10 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_dtrace.h" @@ -934,6 +934,24 @@ bdev_open(dev_t dev, int flag, int devty } int +bdev_cancel(dev_t dev, int flag, int devtype, struct lwp *l) +{ + const struct bdevsw *d; + int rv, mpflag; + + if ((d = bdevsw_lookup(dev)) == NULL) + return ENXIO; + if (d->d_cancel == NULL) + return ENODEV; + + DEV_LOCK(d); + rv = (*d->d_cancel)(dev, flag, devtype, l); + DEV_UNLOCK(d); + + return rv; +} + +int bdev_close(dev_t dev, int flag, int devtype, lwp_t *l) { const struct bdevsw *d; @@ -1129,6 +1147,24 @@ cdev_open(dev_t dev, int flag, int devty } int +cdev_cancel(dev_t dev, int flag, int devtype, struct lwp *l) +{ + const struct cdevsw *d; + int rv, mpflag; + + if ((d = cdevsw_lookup(dev)) == NULL) + return ENXIO; + if (d->d_cancel == NULL) + return ENODEV; + + DEV_LOCK(d); + rv = (*d->d_cancel)(dev, flag, devtype, l); + DEV_UNLOCK(d); + + return rv; +} + +int cdev_close(dev_t dev, int flag, int devtype, lwp_t *l) { const struct cdevsw *d; Index: src/sys/miscfs/specfs/spec_vnops.c diff -u src/sys/miscfs/specfs/spec_vnops.c:1.209 src/sys/miscfs/specfs/spec_vnops.c:1.210 --- src/sys/miscfs/specfs/spec_vnops.c:1.209 Mon Mar 28 12:37:56 2022 +++ src/sys/miscfs/specfs/spec_vnops.c Mon Mar 28 12:39:10 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: spec_vnops.c,v 1.209 2022/03/28 12:37:56 riastradh Exp $ */ +/* $NetBSD: spec_vnops.c,v 1.210 2022/03/28 12:39:10 riastradh Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -58,7 +58,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.209 2022/03/28 12:37:56 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.210 2022/03/28 12:39:10 riastradh Exp $"); #include #include @@ -1688,6 +1688,22 @@ spec_close(void *v) if (!(flags & FNONBLOCK)) VOP_UNLOCK(vp); + /* + * If we can cancel all outstanding I/O, then wait for it to + * drain before we call .d_close. Drivers that split up + * .d_cancel and .d_close this way need not have any internal + * mechanism for waiting in .d_close for I/O to drain. + */ + if (vp->v_type == VBLK) + error = bdev_cancel(dev, flags, mode, curlwp); + else + error =
CVS commit: src/sys
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:39:10 UTC 2022 Modified Files: src/sys/kern: subr_devsw.c src/sys/miscfs/specfs: spec_vnops.c src/sys/sys: conf.h Log Message: driver(9): New devsw d_cancel op to interrupt I/O before close. If specified, when revoking a device node or closing its last open node, specfs will: 1. Call d_cancel, which should return promptly without blocking. 2. Wait for all concurrent d_read/write/ioctl/ to drain. 3. Call d_close. Otherwise, specfs will: 1. Call d_close. 2. Wait for all concurrent d_read/write/ioctl/ to drain. This fallback is problematic because often parts of d_close rely on concurrent devsw operations to have completed already, so it is up to each driver to have its own mechanism for waiting, and the extra step in (2) is almost redundant. But it is still important to ensure that devsw operations are not active by the time a module tries to invoke devsw_detach, because only d_open is protected against that. The signature of d_cancel matches d_close, mostly so we don't raise questions about `why is this different?'; the lwp argument is not useful but we should remove it from open/cancel/close all at the same time. The only way d_cancel should fail, if it does at all, is with ENODEV, meaning the driver doesn't support cancelling outstanding I/O, and will take responsibility for that in d_close. I would make it return void and only have bdev_cancel and cdev_cancel possibly return ENODEV so specfs can detect whether a driver supports it, but this would break the pattern around devsw operation types. Drivers are allowed to omit it from struct bdevsw, struct cdevsw -- if so, it is as if they used a function that just returns ENODEV. XXX kernel ABI change to struct bdevsw/cdevsw requires bump To generate a diff of this commit: cvs rdiff -u -r1.43 -r1.44 src/sys/kern/subr_devsw.c cvs rdiff -u -r1.209 -r1.210 src/sys/miscfs/specfs/spec_vnops.c cvs rdiff -u -r1.159 -r1.160 src/sys/sys/conf.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:38:59 UTC 2022 Modified Files: src/sys/arch/amiga/amiga: autoconf.c src/sys/arch/amiga/dev: grf_cc.c grf_cl.c grf_cv.c grf_cv3d.c grf_et.c grf_rh.c grf_rt.c grf_ul.c src/sys/arch/amigappc/amigappc: autoconf.c src/sys/arch/arm/iomd: iomdiic.c src/sys/arch/atari/atari: autoconf.c src/sys/arch/atari/dev: ite_cc.c ite_et.c src/sys/arch/dreamcast/dev/maple: maple.c src/sys/arch/mips/mips: cpu_subr.c src/sys/ddb: db_autoconf.c src/sys/dev/sbus: esp_sbus.c src/sys/dev/wscons: wsmux.c src/sys/kern: kern_pmf.c subr_autoconf.c subr_device.c src/sys/rump/librump/rumpkern: rump.c src/sys/sys: device.h Added Files: src/sys/sys: device_impl.h Log Message: sys: Split struct device into a private device_impl.h. Include this only inside autoconf itself, and a few files that abuse autoconf in ways I can't confidently make easy fixes for. XXX kernel ABI change requires bump -- no more use of struct device internals allowed, previously done by some drivers To generate a diff of this commit: cvs rdiff -u -r1.120 -r1.121 src/sys/arch/amiga/amiga/autoconf.c cvs rdiff -u -r1.43 -r1.44 src/sys/arch/amiga/dev/grf_cc.c cvs rdiff -u -r1.54 -r1.55 src/sys/arch/amiga/dev/grf_cl.c cvs rdiff -u -r1.63 -r1.64 src/sys/arch/amiga/dev/grf_cv.c cvs rdiff -u -r1.38 -r1.39 src/sys/arch/amiga/dev/grf_cv3d.c cvs rdiff -u -r1.39 -r1.40 src/sys/arch/amiga/dev/grf_et.c cvs rdiff -u -r1.60 -r1.61 src/sys/arch/amiga/dev/grf_rh.c \ src/sys/arch/amiga/dev/grf_rt.c cvs rdiff -u -r1.53 -r1.54 src/sys/arch/amiga/dev/grf_ul.c cvs rdiff -u -r1.9 -r1.10 src/sys/arch/amigappc/amigappc/autoconf.c cvs rdiff -u -r1.11 -r1.12 src/sys/arch/arm/iomd/iomdiic.c cvs rdiff -u -r1.71 -r1.72 src/sys/arch/atari/atari/autoconf.c cvs rdiff -u -r1.43 -r1.44 src/sys/arch/atari/dev/ite_cc.c cvs rdiff -u -r1.34 -r1.35 src/sys/arch/atari/dev/ite_et.c cvs rdiff -u -r1.55 -r1.56 src/sys/arch/dreamcast/dev/maple/maple.c cvs rdiff -u -r1.60 -r1.61 src/sys/arch/mips/mips/cpu_subr.c cvs rdiff -u -r1.2 -r1.3 src/sys/ddb/db_autoconf.c cvs rdiff -u -r1.56 -r1.57 src/sys/dev/sbus/esp_sbus.c cvs rdiff -u -r1.65 -r1.66 src/sys/dev/wscons/wsmux.c cvs rdiff -u -r1.47 -r1.48 src/sys/kern/kern_pmf.c cvs rdiff -u -r1.300 -r1.301 src/sys/kern/subr_autoconf.c cvs rdiff -u -r1.12 -r1.13 src/sys/kern/subr_device.c cvs rdiff -u -r1.353 -r1.354 src/sys/rump/librump/rumpkern/rump.c cvs rdiff -u -r1.181 -r1.182 src/sys/sys/device.h cvs rdiff -u -r0 -r1.1 src/sys/sys/device_impl.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/arch/amiga/amiga/autoconf.c diff -u src/sys/arch/amiga/amiga/autoconf.c:1.120 src/sys/arch/amiga/amiga/autoconf.c:1.121 --- src/sys/arch/amiga/amiga/autoconf.c:1.120 Sat Aug 7 16:18:41 2021 +++ src/sys/arch/amiga/amiga/autoconf.c Mon Mar 28 12:38:57 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: autoconf.c,v 1.120 2021/08/07 16:18:41 thorpej Exp $ */ +/* $NetBSD: autoconf.c,v 1.121 2022/03/28 12:38:57 riastradh Exp $ */ /* * Copyright (c) 1994 Christian E. Hopps @@ -31,7 +31,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.120 2021/08/07 16:18:41 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.121 2022/03/28 12:38:57 riastradh Exp $"); #include #include @@ -39,6 +39,7 @@ __KERNEL_RCSID(0, "$NetBSD: autoconf.c,v #include #include #include +#include /* XXX autoconf abuse */ #include #include #include Index: src/sys/arch/amiga/dev/grf_cc.c diff -u src/sys/arch/amiga/dev/grf_cc.c:1.43 src/sys/arch/amiga/dev/grf_cc.c:1.44 --- src/sys/arch/amiga/dev/grf_cc.c:1.43 Sat Aug 7 16:18:41 2021 +++ src/sys/arch/amiga/dev/grf_cc.c Mon Mar 28 12:38:57 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: grf_cc.c,v 1.43 2021/08/07 16:18:41 thorpej Exp $ */ +/* $NetBSD: grf_cc.c,v 1.44 2022/03/28 12:38:57 riastradh Exp $ */ /* * Copyright (c) 1994 Christian E. Hopps @@ -31,7 +31,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: grf_cc.c,v 1.43 2021/08/07 16:18:41 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: grf_cc.c,v 1.44 2022/03/28 12:38:57 riastradh Exp $"); #include "grfcc.h" #include "ite.h" @@ -47,6 +47,7 @@ __KERNEL_RCSID(0, "$NetBSD: grf_cc.c,v 1 #include #include #include +#include /* XXX autoconf abuse */ #include #include #include Index: src/sys/arch/amiga/dev/grf_cl.c diff -u src/sys/arch/amiga/dev/grf_cl.c:1.54 src/sys/arch/amiga/dev/grf_cl.c:1.55 --- src/sys/arch/amiga/dev/grf_cl.c:1.54 Sun Dec 26 16:08:19 2021 +++ src/sys/arch/amiga/dev/grf_cl.c Mon Mar 28 12:38:57 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: grf_cl.c,v 1.54 2021/12/26 16:08:19 andvar Exp $ */ +/* $NetBSD: grf_cl.c,v 1.55 2022/03/28 12:38:57 riastradh Exp $ */ /* * Copyright (c) 1997 Klaus Burkert @@ -36,7 +36,7 @@ #include "opt_amigacons.h" #include
CVS commit: src/sys
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:38:59 UTC 2022 Modified Files: src/sys/arch/amiga/amiga: autoconf.c src/sys/arch/amiga/dev: grf_cc.c grf_cl.c grf_cv.c grf_cv3d.c grf_et.c grf_rh.c grf_rt.c grf_ul.c src/sys/arch/amigappc/amigappc: autoconf.c src/sys/arch/arm/iomd: iomdiic.c src/sys/arch/atari/atari: autoconf.c src/sys/arch/atari/dev: ite_cc.c ite_et.c src/sys/arch/dreamcast/dev/maple: maple.c src/sys/arch/mips/mips: cpu_subr.c src/sys/ddb: db_autoconf.c src/sys/dev/sbus: esp_sbus.c src/sys/dev/wscons: wsmux.c src/sys/kern: kern_pmf.c subr_autoconf.c subr_device.c src/sys/rump/librump/rumpkern: rump.c src/sys/sys: device.h Added Files: src/sys/sys: device_impl.h Log Message: sys: Split struct device into a private device_impl.h. Include this only inside autoconf itself, and a few files that abuse autoconf in ways I can't confidently make easy fixes for. XXX kernel ABI change requires bump -- no more use of struct device internals allowed, previously done by some drivers To generate a diff of this commit: cvs rdiff -u -r1.120 -r1.121 src/sys/arch/amiga/amiga/autoconf.c cvs rdiff -u -r1.43 -r1.44 src/sys/arch/amiga/dev/grf_cc.c cvs rdiff -u -r1.54 -r1.55 src/sys/arch/amiga/dev/grf_cl.c cvs rdiff -u -r1.63 -r1.64 src/sys/arch/amiga/dev/grf_cv.c cvs rdiff -u -r1.38 -r1.39 src/sys/arch/amiga/dev/grf_cv3d.c cvs rdiff -u -r1.39 -r1.40 src/sys/arch/amiga/dev/grf_et.c cvs rdiff -u -r1.60 -r1.61 src/sys/arch/amiga/dev/grf_rh.c \ src/sys/arch/amiga/dev/grf_rt.c cvs rdiff -u -r1.53 -r1.54 src/sys/arch/amiga/dev/grf_ul.c cvs rdiff -u -r1.9 -r1.10 src/sys/arch/amigappc/amigappc/autoconf.c cvs rdiff -u -r1.11 -r1.12 src/sys/arch/arm/iomd/iomdiic.c cvs rdiff -u -r1.71 -r1.72 src/sys/arch/atari/atari/autoconf.c cvs rdiff -u -r1.43 -r1.44 src/sys/arch/atari/dev/ite_cc.c cvs rdiff -u -r1.34 -r1.35 src/sys/arch/atari/dev/ite_et.c cvs rdiff -u -r1.55 -r1.56 src/sys/arch/dreamcast/dev/maple/maple.c cvs rdiff -u -r1.60 -r1.61 src/sys/arch/mips/mips/cpu_subr.c cvs rdiff -u -r1.2 -r1.3 src/sys/ddb/db_autoconf.c cvs rdiff -u -r1.56 -r1.57 src/sys/dev/sbus/esp_sbus.c cvs rdiff -u -r1.65 -r1.66 src/sys/dev/wscons/wsmux.c cvs rdiff -u -r1.47 -r1.48 src/sys/kern/kern_pmf.c cvs rdiff -u -r1.300 -r1.301 src/sys/kern/subr_autoconf.c cvs rdiff -u -r1.12 -r1.13 src/sys/kern/subr_device.c cvs rdiff -u -r1.353 -r1.354 src/sys/rump/librump/rumpkern/rump.c cvs rdiff -u -r1.181 -r1.182 src/sys/sys/device.h cvs rdiff -u -r0 -r1.1 src/sys/sys/device_impl.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:38:34 UTC 2022 Modified Files: src/sys/kern: subr_devsw.c vfs_subr.c src/sys/sys: conf.h Log Message: driver(9): Make vdevgone call config_detach_commit if appropriate. Make sure to do this before spec_node_lookup_by_dev -- that might wait for a concurrent revoke to complete, which in turn might wait for a concurrent open to complete, which in turn might be waiting for the device to commit to detaching. To generate a diff of this commit: cvs rdiff -u -r1.42 -r1.43 src/sys/kern/subr_devsw.c cvs rdiff -u -r1.492 -r1.493 src/sys/kern/vfs_subr.c cvs rdiff -u -r1.158 -r1.159 src/sys/sys/conf.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/kern/subr_devsw.c diff -u src/sys/kern/subr_devsw.c:1.42 src/sys/kern/subr_devsw.c:1.43 --- src/sys/kern/subr_devsw.c:1.42 Mon Mar 28 12:34:08 2022 +++ src/sys/kern/subr_devsw.c Mon Mar 28 12:38:33 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: subr_devsw.c,v 1.42 2022/03/28 12:34:08 riastradh Exp $ */ +/* $NetBSD: subr_devsw.c,v 1.43 2022/03/28 12:38:33 riastradh Exp $ */ /*- * Copyright (c) 2001, 2002, 2007, 2008 The NetBSD Foundation, Inc. @@ -69,7 +69,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: subr_devsw.c,v 1.42 2022/03/28 12:34:08 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: subr_devsw.c,v 1.43 2022/03/28 12:38:33 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_dtrace.h" @@ -1068,6 +1068,24 @@ bdev_discard(dev_t dev, off_t pos, off_t return rv; } +void +bdev_detached(dev_t dev) +{ + const struct bdevsw *d; + device_t dv; + int unit; + + if ((d = bdevsw_lookup(dev)) == NULL) + return; + if (d->d_devtounit == NULL) + return; + if ((unit = (*d->d_devtounit)(dev)) == -1) + return; + if ((dv = device_lookup(d->d_cfdriver, unit)) == NULL) + return; + config_detach_commit(dv); +} + int cdev_open(dev_t dev, int flag, int devtype, lwp_t *l) { @@ -1288,6 +1306,24 @@ cdev_type(dev_t dev) return d->d_flag & D_TYPEMASK; } +void +cdev_detached(dev_t dev) +{ + const struct cdevsw *d; + device_t dv; + int unit; + + if ((d = cdevsw_lookup(dev)) == NULL) + return; + if (d->d_devtounit == NULL) + return; + if ((unit = (*d->d_devtounit)(dev)) == -1) + return; + if ((dv = device_lookup(d->d_cfdriver, unit)) == NULL) + return; + config_detach_commit(dv); +} + /* * nommap(dev, off, prot) * Index: src/sys/kern/vfs_subr.c diff -u src/sys/kern/vfs_subr.c:1.492 src/sys/kern/vfs_subr.c:1.493 --- src/sys/kern/vfs_subr.c:1.492 Mon Mar 28 12:37:46 2022 +++ src/sys/kern/vfs_subr.c Mon Mar 28 12:38:33 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: vfs_subr.c,v 1.492 2022/03/28 12:37:46 riastradh Exp $ */ +/* $NetBSD: vfs_subr.c,v 1.493 2022/03/28 12:38:33 riastradh Exp $ */ /*- * Copyright (c) 1997, 1998, 2004, 2005, 2007, 2008, 2019, 2020 @@ -69,7 +69,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.492 2022/03/28 12:37:46 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.493 2022/03/28 12:38:33 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_ddb.h" @@ -512,6 +512,20 @@ vdevgone(int maj, int minl, int minh, en for (mn = minl; mn <= minh; mn++) { dev = makedev(maj, mn); /* + * Notify anyone trying to get at this device that it + * has been detached, and then revoke it. + */ + switch (type) { + case VBLK: + bdev_detached(dev); + break; + case VCHR: + cdev_detached(dev); + break; + default: + panic("invalid specnode type: %d", type); + } + /* * Passing 0 as flags, instead of VDEAD_NOWAIT, means * spec_node_lookup_by_dev will wait for vnodes it * finds concurrently being revoked before returning. Index: src/sys/sys/conf.h diff -u src/sys/sys/conf.h:1.158 src/sys/sys/conf.h:1.159 --- src/sys/sys/conf.h:1.158 Mon Mar 28 12:34:17 2022 +++ src/sys/sys/conf.h Mon Mar 28 12:38:33 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: conf.h,v 1.158 2022/03/28 12:34:17 riastradh Exp $ */ +/* $NetBSD: conf.h,v 1.159 2022/03/28 12:38:33 riastradh Exp $ */ /*- * Copyright (c) 1990, 1993 @@ -172,6 +172,8 @@ dev_type_dump(bdev_dump); dev_type_size(bdev_size); dev_type_discard(bdev_discard); +void bdev_detached(dev_t); + dev_type_open(cdev_open); dev_type_close(cdev_close); dev_type_read(cdev_read); @@ -184,6 +186,8 @@ dev_type_mmap(cdev_mmap); dev_type_kqfilter(cdev_kqfilter); dev_type_discard(cdev_discard); +void cdev_detached(dev_t); + int cdev_type(dev_t); int cdev_flags(dev_t); int bdev_type(dev_t);
CVS commit: src/sys
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:38:34 UTC 2022 Modified Files: src/sys/kern: subr_devsw.c vfs_subr.c src/sys/sys: conf.h Log Message: driver(9): Make vdevgone call config_detach_commit if appropriate. Make sure to do this before spec_node_lookup_by_dev -- that might wait for a concurrent revoke to complete, which in turn might wait for a concurrent open to complete, which in turn might be waiting for the device to commit to detaching. To generate a diff of this commit: cvs rdiff -u -r1.42 -r1.43 src/sys/kern/subr_devsw.c cvs rdiff -u -r1.492 -r1.493 src/sys/kern/vfs_subr.c cvs rdiff -u -r1.158 -r1.159 src/sys/sys/conf.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/kern
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:38:25 UTC 2022 Modified Files: src/sys/kern: subr_autoconf.c Log Message: autoconf(9): Disentangle slightly circuitous config_detach logic. No functional change intended. To generate a diff of this commit: cvs rdiff -u -r1.299 -r1.300 src/sys/kern/subr_autoconf.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/kern/subr_autoconf.c diff -u src/sys/kern/subr_autoconf.c:1.299 src/sys/kern/subr_autoconf.c:1.300 --- src/sys/kern/subr_autoconf.c:1.299 Mon Mar 28 12:38:15 2022 +++ src/sys/kern/subr_autoconf.c Mon Mar 28 12:38:24 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: subr_autoconf.c,v 1.299 2022/03/28 12:38:15 riastradh Exp $ */ +/* $NetBSD: subr_autoconf.c,v 1.300 2022/03/28 12:38:24 riastradh Exp $ */ /* * Copyright (c) 1996, 2000 Christopher G. Demetriou @@ -77,7 +77,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.299 2022/03/28 12:38:15 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.300 2022/03/28 12:38:24 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_ddb.h" @@ -2023,6 +2023,11 @@ config_detach(device_t dev, int flags) alldevs_nwrite++; mutex_exit(_lock); + /* + * Call the driver's .ca_detach function, unless it has none or + * we are skipping it because it's unforced shutdown time and + * the driver didn't ask to detach on shutdown. + */ if (!detachall && (flags & (DETACH_SHUTDOWN|DETACH_FORCE)) == DETACH_SHUTDOWN && (dev->dv_flags & DVF_DETACH_SHUTDOWN) == 0) { @@ -2035,25 +2040,20 @@ config_detach(device_t dev, int flags) /* * If it was not possible to detach the device, then we either * panic() (for the forced but failed case), or return an error. - * - * If it was possible to detach the device, ensure that the - * device is deactivated. */ - if (rv == 0) { - config_detach_commit(dev); - dev->dv_flags &= ~DVF_ACTIVE; /* XXXSMP */ - } else if ((flags & DETACH_FORCE) == 0) { + if (rv) { /* - * Detach failed -- likely EBUSY. Driver must not have - * called config_detach_commit. + * Detach failed -- likely EOPNOTSUPP or EBUSY. Driver + * must not have called config_detach_commit. */ KASSERTMSG(!dev->dv_detached, "%s committed to detaching and then backed out", device_xname(dev)); + if (flags & DETACH_FORCE) { + panic("config_detach: forced detach of %s failed (%d)", + device_xname(dev), rv); + } goto out; - } else { - panic("config_detach: forced detach of %s failed (%d)", - device_xname(dev), rv); } /* @@ -2061,6 +2061,19 @@ config_detach(device_t dev, int flags) */ /* + * If .ca_detach didn't commit to detach, then do that for it. + * This wakes any pending device_lookup_acquire calls so they + * will fail. + */ + config_detach_commit(dev); + + /* + * If it was possible to detach the device, ensure that the + * device is deactivated. + */ + dev->dv_flags &= ~DVF_ACTIVE; /* XXXSMP */ + + /* * Wait for all device_lookup_acquire references -- mostly, for * all attempts to open the device -- to drain. It is the * responsibility of .ca_detach to ensure anything with open
CVS commit: src/sys/kern
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:38:25 UTC 2022 Modified Files: src/sys/kern: subr_autoconf.c Log Message: autoconf(9): Disentangle slightly circuitous config_detach logic. No functional change intended. To generate a diff of this commit: cvs rdiff -u -r1.299 -r1.300 src/sys/kern/subr_autoconf.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:38:15 UTC 2022 Modified Files: src/sys/kern: subr_autoconf.c src/sys/sys: device.h Log Message: autoconf(9): New function config_detach_commit. When a driver's .ca_detach function has committed to detaching -- it definitely won't back out with EBUSY, for instance -- it can call this to wake all pending calls to device_lookup_acquire and make them fail immediately. This is necessary to break a deadlock if the device_lookup_acquire calls happen inside I/O operations which the driver's .ca_detach function waits for the completion of -- without config_detach_commit, I/O operations would be stuck in device_lookup_acquire waiting for .ca_detach and .ca_detach would be stuck waiting for I/O operations to return. Most drivers won't need to call this: for autoconf drivers used the traditional way by devsw for userland device nodes, the .ca_detach routine uses vdevgone, and we will arrange to make vdevgone call config_detach_commit automagically in such drivers anyway. XXX kernel ABI change to struct device requires bump -- later change will make struct device opaque to ABI, but we're not there yet To generate a diff of this commit: cvs rdiff -u -r1.298 -r1.299 src/sys/kern/subr_autoconf.c cvs rdiff -u -r1.180 -r1.181 src/sys/sys/device.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/kern/subr_autoconf.c diff -u src/sys/kern/subr_autoconf.c:1.298 src/sys/kern/subr_autoconf.c:1.299 --- src/sys/kern/subr_autoconf.c:1.298 Mon Mar 28 12:33:41 2022 +++ src/sys/kern/subr_autoconf.c Mon Mar 28 12:38:15 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: subr_autoconf.c,v 1.298 2022/03/28 12:33:41 riastradh Exp $ */ +/* $NetBSD: subr_autoconf.c,v 1.299 2022/03/28 12:38:15 riastradh Exp $ */ /* * Copyright (c) 1996, 2000 Christopher G. Demetriou @@ -77,7 +77,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.298 2022/03/28 12:33:41 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.299 2022/03/28 12:38:15 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_ddb.h" @@ -2039,10 +2039,17 @@ config_detach(device_t dev, int flags) * If it was possible to detach the device, ensure that the * device is deactivated. */ - if (rv == 0) - dev->dv_flags &= ~DVF_ACTIVE; - else if ((flags & DETACH_FORCE) == 0) { - /* Detach failed -- likely EBUSY. */ + if (rv == 0) { + config_detach_commit(dev); + dev->dv_flags &= ~DVF_ACTIVE; /* XXXSMP */ + } else if ((flags & DETACH_FORCE) == 0) { + /* + * Detach failed -- likely EBUSY. Driver must not have + * called config_detach_commit. + */ + KASSERTMSG(!dev->dv_detached, + "%s committed to detaching and then backed out", + device_xname(dev)); goto out; } else { panic("config_detach: forced detach of %s failed (%d)", @@ -2059,7 +2066,8 @@ config_detach(device_t dev, int flags) * responsibility of .ca_detach to ensure anything with open * references will be interrupted and release them promptly, * not block indefinitely. All new attempts to acquire - * references will block until dv_detaching clears. + * references will fail, as config_detach_commit has arranged + * by now. */ mutex_enter(_misc_lock); localcount_drain(dev->dv_localcount, @@ -2133,6 +2141,30 @@ out: return rv; } +/* + * config_detach_commit(dev) + * + * Issued by a driver's .ca_detach routine to notify anyone + * waiting in device_lookup_acquire that the driver is committed + * to detaching the device, which allows device_lookup_acquire to + * wake up and fail immediately. + * + * Safe to call multiple times -- idempotent. Must be called + * during config_detach_enter/exit. Safe to use with + * device_lookup because the device is not actually removed from + * the table until after config_detach_exit. + */ +void +config_detach_commit(device_t dev) +{ + + mutex_enter(_misc_lock); + KASSERT(dev->dv_detaching == curlwp); + dev->dv_detached = true; + cv_broadcast(_misc_cv); + mutex_exit(_misc_lock); +} + int config_detach_children(device_t parent, int flags) { @@ -2640,7 +2672,8 @@ device_lookup_acquire(cfdriver_t cd, int mutex_enter(_lock); retry: if (unit < 0 || unit >= cd->cd_ndevs || (dv = cd->cd_devs[unit]) == NULL || - dv->dv_del_gen != 0) { + dv->dv_del_gen != 0 || + dv->dv_detached) { dv = NULL; } else { /* Index: src/sys/sys/device.h diff -u src/sys/sys/device.h:1.180 src/sys/sys/device.h:1.181 --- src/sys/sys/device.h:1.180 Mon Mar 28 12:33:41 2022 +++ src/sys/sys/device.h Mon Mar 28 12:38:15 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: device.h,v 1.180 2022/03/28 12:33:41 riastradh Exp $ */ +/* $NetBSD: device.h,v 1.181 2022/03/28 12:38:15 riastradh Exp $ */ /* * Copyright (c) 2021 The NetBSD Foundation, Inc. @@ -281,6 +281,7 @@ struct device { struct lwp *dv_attaching; /* thread not yet finished in attach
CVS commit: src/sys
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:38:15 UTC 2022 Modified Files: src/sys/kern: subr_autoconf.c src/sys/sys: device.h Log Message: autoconf(9): New function config_detach_commit. When a driver's .ca_detach function has committed to detaching -- it definitely won't back out with EBUSY, for instance -- it can call this to wake all pending calls to device_lookup_acquire and make them fail immediately. This is necessary to break a deadlock if the device_lookup_acquire calls happen inside I/O operations which the driver's .ca_detach function waits for the completion of -- without config_detach_commit, I/O operations would be stuck in device_lookup_acquire waiting for .ca_detach and .ca_detach would be stuck waiting for I/O operations to return. Most drivers won't need to call this: for autoconf drivers used the traditional way by devsw for userland device nodes, the .ca_detach routine uses vdevgone, and we will arrange to make vdevgone call config_detach_commit automagically in such drivers anyway. XXX kernel ABI change to struct device requires bump -- later change will make struct device opaque to ABI, but we're not there yet To generate a diff of this commit: cvs rdiff -u -r1.298 -r1.299 src/sys/kern/subr_autoconf.c cvs rdiff -u -r1.180 -r1.181 src/sys/sys/device.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/miscfs/specfs
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:38:04 UTC 2022 Modified Files: src/sys/miscfs/specfs: specdev.h Log Message: specfs: Reorder struct specnode members to save padding. Shrinks from 40 bytes to 32 bytes on LP64 systems this way. To generate a diff of this commit: cvs rdiff -u -r1.51 -r1.52 src/sys/miscfs/specfs/specdev.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/miscfs/specfs/specdev.h diff -u src/sys/miscfs/specfs/specdev.h:1.51 src/sys/miscfs/specfs/specdev.h:1.52 --- src/sys/miscfs/specfs/specdev.h:1.51 Mon Mar 28 12:37:46 2022 +++ src/sys/miscfs/specfs/specdev.h Mon Mar 28 12:38:04 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: specdev.h,v 1.51 2022/03/28 12:37:46 riastradh Exp $ */ +/* $NetBSD: specdev.h,v 1.52 2022/03/28 12:38:04 riastradh Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -66,8 +66,8 @@ typedef struct specnode { vnode_t *sn_next; struct specdev *sn_dev; - u_int sn_opencnt; /* # of opens, share of sd_opencnt */ dev_t sn_rdev; + u_int sn_opencnt; /* # of opens, share of sd_opencnt */ bool sn_gone; } specnode_t;
CVS commit: src/sys/miscfs/specfs
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:38:04 UTC 2022 Modified Files: src/sys/miscfs/specfs: specdev.h Log Message: specfs: Reorder struct specnode members to save padding. Shrinks from 40 bytes to 32 bytes on LP64 systems this way. To generate a diff of this commit: cvs rdiff -u -r1.51 -r1.52 src/sys/miscfs/specfs/specdev.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:37:56 UTC 2022 Modified Files: src/sys/kern: vfs_vnode.c src/sys/miscfs/specfs: spec_vnops.c Log Message: specfs: Remove specnode from hash table in spec_node_revoke. Previously, it was possible for spec_node_lookup_by_dev to handle a speconde that a concurrent spec_node_destroy is about to remove from the hash table and then free, as soon as spec_node_lookup_by_dev releases device_lock. Now, the ordering is: 1. Remove specnode from hash table in spec_node_revoke. At this point, no _new_ vnode references are possible (other than possibly one acquired by vcache_vget under v_interlock), but there may be existing ones. 2. Mark vnode reclaimed so vcache_vget will fail. 3. The last vrele (or equivalent logic in vcache_vget) will then free the specnode in spec_node_destroy. This way, _if_ a thread in spec_node_lookup_by_dev finds a specnode in the hash table under device_lock/v_interlock, _then_ it will not be freed until the thread completes vcache_vget. This change requires calling spec_node_revoke unconditionally for device special nodes, not just for active ones. Might introduce slightly more contention on device_lock but not much because we already have to take it in this path anyway a little later in spec_node_destroy. To generate a diff of this commit: cvs rdiff -u -r1.140 -r1.141 src/sys/kern/vfs_vnode.c cvs rdiff -u -r1.208 -r1.209 src/sys/miscfs/specfs/spec_vnops.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/kern/vfs_vnode.c diff -u src/sys/kern/vfs_vnode.c:1.140 src/sys/kern/vfs_vnode.c:1.141 --- src/sys/kern/vfs_vnode.c:1.140 Mon Mar 28 12:37:46 2022 +++ src/sys/kern/vfs_vnode.c Mon Mar 28 12:37:56 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: vfs_vnode.c,v 1.140 2022/03/28 12:37:46 riastradh Exp $ */ +/* $NetBSD: vfs_vnode.c,v 1.141 2022/03/28 12:37:56 riastradh Exp $ */ /*- * Copyright (c) 1997-2011, 2019, 2020 The NetBSD Foundation, Inc. @@ -148,7 +148,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.140 2022/03/28 12:37:46 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.141 2022/03/28 12:37:56 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_pax.h" @@ -1811,14 +1811,13 @@ vcache_reclaim(vnode_t *vp) uint32_t hash; uint8_t temp_buf[64], *temp_key; size_t temp_key_len; - bool recycle, active; + bool recycle; int error; KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE); KASSERT(mutex_owned(vp->v_interlock)); KASSERT(vrefcnt(vp) != 0); - active = (vrefcnt(vp) > 1); temp_key_len = vip->vi_key.vk_key_len; /* * Prevent the vnode from being recycled or brought into use @@ -1861,8 +1860,6 @@ vcache_reclaim(vnode_t *vp) /* * Clean out any cached data associated with the vnode. - * If purging an active vnode, it must be closed and - * deactivated before being reclaimed. */ error = vinvalbuf(vp, V_SAVE, NOCRED, l, 0, 0); if (error != 0) { @@ -1872,7 +1869,7 @@ vcache_reclaim(vnode_t *vp) } KASSERTMSG((error == 0), "vinvalbuf failed: %d", error); KASSERT((vp->v_iflag & VI_ONWORKLST) == 0); - if (active && (vp->v_type == VBLK || vp->v_type == VCHR)) { + if (vp->v_type == VBLK || vp->v_type == VCHR) { spec_node_revoke(vp); } Index: src/sys/miscfs/specfs/spec_vnops.c diff -u src/sys/miscfs/specfs/spec_vnops.c:1.208 src/sys/miscfs/specfs/spec_vnops.c:1.209 --- src/sys/miscfs/specfs/spec_vnops.c:1.208 Mon Mar 28 12:37:46 2022 +++ src/sys/miscfs/specfs/spec_vnops.c Mon Mar 28 12:37:56 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: spec_vnops.c,v 1.208 2022/03/28 12:37:46 riastradh Exp $ */ +/* $NetBSD: spec_vnops.c,v 1.209 2022/03/28 12:37:56 riastradh Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -58,7 +58,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.208 2022/03/28 12:37:46 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.209 2022/03/28 12:37:56 riastradh Exp $"); #include #include @@ -591,6 +591,7 @@ spec_node_revoke(vnode_t *vp) { specnode_t *sn; specdev_t *sd; + struct vnode **vpp; KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE); @@ -603,10 +604,10 @@ spec_node_revoke(vnode_t *vp) mutex_enter(_lock); KASSERT(sn->sn_opencnt <= sd->sd_opencnt); + sn->sn_gone = true; if (sn->sn_opencnt != 0) { sd->sd_opencnt -= (sn->sn_opencnt - 1); sn->sn_opencnt = 1; - sn->sn_gone = true; mutex_exit(_lock); VOP_CLOSE(vp, FNONBLOCK, NOCRED); @@ -624,6 +625,22 @@ spec_node_revoke(vnode_t *vp) */ while (sd->sd_closing) cv_wait(_iocv, _lock); + + /* + * Remove from the hash so lookups stop returning this + * specnode. We will dissociate it from the specdev -- and + * possibly free the specdev -- in spec_node_destroy. + */ + KASSERT(sn->sn_gone); + KASSERT(sn->sn_opencnt == 0); + for (vpp = _hash[SPECHASH(vp->v_rdev)];; + vpp =
CVS commit: src/sys
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:37:56 UTC 2022 Modified Files: src/sys/kern: vfs_vnode.c src/sys/miscfs/specfs: spec_vnops.c Log Message: specfs: Remove specnode from hash table in spec_node_revoke. Previously, it was possible for spec_node_lookup_by_dev to handle a speconde that a concurrent spec_node_destroy is about to remove from the hash table and then free, as soon as spec_node_lookup_by_dev releases device_lock. Now, the ordering is: 1. Remove specnode from hash table in spec_node_revoke. At this point, no _new_ vnode references are possible (other than possibly one acquired by vcache_vget under v_interlock), but there may be existing ones. 2. Mark vnode reclaimed so vcache_vget will fail. 3. The last vrele (or equivalent logic in vcache_vget) will then free the specnode in spec_node_destroy. This way, _if_ a thread in spec_node_lookup_by_dev finds a specnode in the hash table under device_lock/v_interlock, _then_ it will not be freed until the thread completes vcache_vget. This change requires calling spec_node_revoke unconditionally for device special nodes, not just for active ones. Might introduce slightly more contention on device_lock but not much because we already have to take it in this path anyway a little later in spec_node_destroy. To generate a diff of this commit: cvs rdiff -u -r1.140 -r1.141 src/sys/kern/vfs_vnode.c cvs rdiff -u -r1.208 -r1.209 src/sys/miscfs/specfs/spec_vnops.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:37:46 UTC 2022 Modified Files: src/sys/coda: coda_vfsops.c src/sys/kern: vfs_mount.c vfs_subr.c vfs_vnode.c src/sys/miscfs/specfs: spec_vnops.c specdev.h Log Message: specfs: Let spec_node_lookup_by_dev wait for reclaim to finish. vdevgone relies on this to ensure that if there is a concurrent revoke in progress, it will wait for that revoke to finish -- that way, it can guarantee all I/O operations have completed and the device is closed. To generate a diff of this commit: cvs rdiff -u -r1.89 -r1.90 src/sys/coda/coda_vfsops.c cvs rdiff -u -r1.91 -r1.92 src/sys/kern/vfs_mount.c cvs rdiff -u -r1.491 -r1.492 src/sys/kern/vfs_subr.c cvs rdiff -u -r1.139 -r1.140 src/sys/kern/vfs_vnode.c cvs rdiff -u -r1.207 -r1.208 src/sys/miscfs/specfs/spec_vnops.c cvs rdiff -u -r1.50 -r1.51 src/sys/miscfs/specfs/specdev.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/coda/coda_vfsops.c diff -u src/sys/coda/coda_vfsops.c:1.89 src/sys/coda/coda_vfsops.c:1.90 --- src/sys/coda/coda_vfsops.c:1.89 Fri Nov 20 10:08:47 2020 +++ src/sys/coda/coda_vfsops.c Mon Mar 28 12:37:46 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: coda_vfsops.c,v 1.89 2020/11/20 10:08:47 hannken Exp $ */ +/* $NetBSD: coda_vfsops.c,v 1.90 2022/03/28 12:37:46 riastradh Exp $ */ /* * @@ -45,7 +45,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: coda_vfsops.c,v 1.89 2020/11/20 10:08:47 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: coda_vfsops.c,v 1.90 2022/03/28 12:37:46 riastradh Exp $"); #include #include @@ -636,7 +636,7 @@ struct mount *devtomp(dev_t dev) struct mount *mp; struct vnode *vp; -if (spec_node_lookup_by_dev(VBLK, dev, ) == 0) { +if (spec_node_lookup_by_dev(VBLK, dev, VDEAD_NOWAIT, ) == 0) { mp = spec_node_getmountedfs(vp); vrele(vp); } else { Index: src/sys/kern/vfs_mount.c diff -u src/sys/kern/vfs_mount.c:1.91 src/sys/kern/vfs_mount.c:1.92 --- src/sys/kern/vfs_mount.c:1.91 Thu Mar 24 12:59:56 2022 +++ src/sys/kern/vfs_mount.c Mon Mar 28 12:37:46 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: vfs_mount.c,v 1.91 2022/03/24 12:59:56 riastradh Exp $ */ +/* $NetBSD: vfs_mount.c,v 1.92 2022/03/28 12:37:46 riastradh Exp $ */ /*- * Copyright (c) 1997-2020 The NetBSD Foundation, Inc. @@ -67,7 +67,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: vfs_mount.c,v 1.91 2022/03/24 12:59:56 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vfs_mount.c,v 1.92 2022/03/28 12:37:46 riastradh Exp $"); #include #include @@ -1376,7 +1376,8 @@ vfs_mountedon(vnode_t *vp) return ENOTBLK; if (spec_node_getmountedfs(vp) != NULL) return EBUSY; - if (spec_node_lookup_by_dev(vp->v_type, vp->v_rdev, ) == 0) { + if (spec_node_lookup_by_dev(vp->v_type, vp->v_rdev, VDEAD_NOWAIT, ) + == 0) { if (spec_node_getmountedfs(vq) != NULL) error = EBUSY; vrele(vq); Index: src/sys/kern/vfs_subr.c diff -u src/sys/kern/vfs_subr.c:1.491 src/sys/kern/vfs_subr.c:1.492 --- src/sys/kern/vfs_subr.c:1.491 Sat Oct 16 07:12:01 2021 +++ src/sys/kern/vfs_subr.c Mon Mar 28 12:37:46 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: vfs_subr.c,v 1.491 2021/10/16 07:12:01 simonb Exp $ */ +/* $NetBSD: vfs_subr.c,v 1.492 2022/03/28 12:37:46 riastradh Exp $ */ /*- * Copyright (c) 1997, 1998, 2004, 2005, 2007, 2008, 2019, 2020 @@ -69,7 +69,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.491 2021/10/16 07:12:01 simonb Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.492 2022/03/28 12:37:46 riastradh Exp $"); #ifdef _KERNEL_OPT #include "opt_ddb.h" @@ -495,7 +495,7 @@ int vfinddev(dev_t dev, enum vtype type, vnode_t **vpp) { - return (spec_node_lookup_by_dev(type, dev, vpp) == 0); + return (spec_node_lookup_by_dev(type, dev, VDEAD_NOWAIT, vpp) == 0); } /* @@ -511,7 +511,12 @@ vdevgone(int maj, int minl, int minh, en for (mn = minl; mn <= minh; mn++) { dev = makedev(maj, mn); - while (spec_node_lookup_by_dev(type, dev, ) == 0) { + /* + * Passing 0 as flags, instead of VDEAD_NOWAIT, means + * spec_node_lookup_by_dev will wait for vnodes it + * finds concurrently being revoked before returning. + */ + while (spec_node_lookup_by_dev(type, dev, 0, ) == 0) { VOP_REVOKE(vp, REVOKEALL); vrele(vp); } Index: src/sys/kern/vfs_vnode.c diff -u src/sys/kern/vfs_vnode.c:1.139 src/sys/kern/vfs_vnode.c:1.140 --- src/sys/kern/vfs_vnode.c:1.139 Sat Mar 19 13:53:32 2022 +++ src/sys/kern/vfs_vnode.c Mon Mar 28 12:37:46 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: vfs_vnode.c,v 1.139 2022/03/19 13:53:32 hannken Exp $ */ +/* $NetBSD: vfs_vnode.c,v 1.140 2022/03/28 12:37:46 riastradh Exp $ */ /*- * Copyright (c) 1997-2011, 2019, 2020 The NetBSD Foundation, Inc. @@ -148,7 +148,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.139 2022/03/19 13:53:32 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.140
CVS commit: src/sys
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:37:46 UTC 2022 Modified Files: src/sys/coda: coda_vfsops.c src/sys/kern: vfs_mount.c vfs_subr.c vfs_vnode.c src/sys/miscfs/specfs: spec_vnops.c specdev.h Log Message: specfs: Let spec_node_lookup_by_dev wait for reclaim to finish. vdevgone relies on this to ensure that if there is a concurrent revoke in progress, it will wait for that revoke to finish -- that way, it can guarantee all I/O operations have completed and the device is closed. To generate a diff of this commit: cvs rdiff -u -r1.89 -r1.90 src/sys/coda/coda_vfsops.c cvs rdiff -u -r1.91 -r1.92 src/sys/kern/vfs_mount.c cvs rdiff -u -r1.491 -r1.492 src/sys/kern/vfs_subr.c cvs rdiff -u -r1.139 -r1.140 src/sys/kern/vfs_vnode.c cvs rdiff -u -r1.207 -r1.208 src/sys/miscfs/specfs/spec_vnops.c cvs rdiff -u -r1.50 -r1.51 src/sys/miscfs/specfs/specdev.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/miscfs/specfs
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:37:35 UTC 2022 Modified Files: src/sys/miscfs/specfs: spec_vnops.c Log Message: specfs: Assert opencnt is nonzero before decrementing. To generate a diff of this commit: cvs rdiff -u -r1.206 -r1.207 src/sys/miscfs/specfs/spec_vnops.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/miscfs/specfs/spec_vnops.c diff -u src/sys/miscfs/specfs/spec_vnops.c:1.206 src/sys/miscfs/specfs/spec_vnops.c:1.207 --- src/sys/miscfs/specfs/spec_vnops.c:1.206 Mon Mar 28 12:37:26 2022 +++ src/sys/miscfs/specfs/spec_vnops.c Mon Mar 28 12:37:35 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: spec_vnops.c,v 1.206 2022/03/28 12:37:26 riastradh Exp $ */ +/* $NetBSD: spec_vnops.c,v 1.207 2022/03/28 12:37:35 riastradh Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -58,7 +58,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.206 2022/03/28 12:37:26 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.207 2022/03/28 12:37:35 riastradh Exp $"); #include #include @@ -944,6 +944,8 @@ spec_open(void *v) KASSERT(sn->sn_opencnt == 1); needclose = true; } else { + KASSERT(sd->sd_opencnt); + KASSERT(sn->sn_opencnt); sd->sd_opencnt--; sn->sn_opencnt--; if (vp->v_type == VBLK) @@ -1643,6 +1645,8 @@ spec_close(void *v) * between open and close can use fd_clone. */ mutex_enter(_lock); + KASSERT(sn->sn_opencnt); + KASSERT(sd->sd_opencnt); sn->sn_opencnt--; count = --sd->sd_opencnt; if (vp->v_type == VBLK) {
CVS commit: src/sys/miscfs/specfs
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:37:35 UTC 2022 Modified Files: src/sys/miscfs/specfs: spec_vnops.c Log Message: specfs: Assert opencnt is nonzero before decrementing. To generate a diff of this commit: cvs rdiff -u -r1.206 -r1.207 src/sys/miscfs/specfs/spec_vnops.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/miscfs/specfs
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:37:27 UTC 2022 Modified Files: src/sys/miscfs/specfs: spec_vnops.c Log Message: specfs: Take an I/O reference across bdev/cdev_open. - Revoke is used to invalidate all prior access control checks when device permissions are changing, so it must wait for .d_open to exit so any new access must go through new access control checks. - Revoke is used by vdevgone in xyz_detach to wait until all use of the driver's data structures have completed before xyz_detach frees them. So we need to make sure spec_close waits for .d_open too. To generate a diff of this commit: cvs rdiff -u -r1.205 -r1.206 src/sys/miscfs/specfs/spec_vnops.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/miscfs/specfs/spec_vnops.c diff -u src/sys/miscfs/specfs/spec_vnops.c:1.205 src/sys/miscfs/specfs/spec_vnops.c:1.206 --- src/sys/miscfs/specfs/spec_vnops.c:1.205 Mon Mar 28 12:37:18 2022 +++ src/sys/miscfs/specfs/spec_vnops.c Mon Mar 28 12:37:26 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: spec_vnops.c,v 1.205 2022/03/28 12:37:18 riastradh Exp $ */ +/* $NetBSD: spec_vnops.c,v 1.206 2022/03/28 12:37:26 riastradh Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -58,7 +58,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.205 2022/03/28 12:37:18 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.206 2022/03/28 12:37:26 riastradh Exp $"); #include #include @@ -694,10 +694,10 @@ spec_open(void *v) } */ *ap = v; struct lwp *l = curlwp; struct vnode *vp = ap->a_vp; - dev_t dev; + dev_t dev, dev1; int error; enum kauth_device_req req; - specnode_t *sn; + specnode_t *sn, *sn1; specdev_t *sd; spec_ioctl_t ioctl; u_int gen = 0; @@ -805,18 +805,34 @@ spec_open(void *v) } /* - * Open the device. If .d_open returns ENXIO (device not - * configured), the driver may not be loaded, so try - * autoloading a module and then try .d_open again if anything - * got loaded. - * * Because opening the device may block indefinitely, e.g. when * opening a tty, and loading a module may cross into many * other subsystems, we must not hold the vnode lock while * calling .d_open, so release it now and reacquire it when * done. + * + * Take an I/O reference so that any concurrent spec_close via + * spec_node_revoke will wait for us to finish calling .d_open. + * The vnode can't be dead at this point because we have it + * locked. Note that if revoked, the driver must interrupt + * .d_open before spec_close starts waiting for I/O to drain so + * this doesn't deadlock. */ VOP_UNLOCK(vp); + error = spec_io_enter(vp, , ); + if (error) { + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + return error; + } + KASSERT(sn1 == sn); + KASSERT(dev1 == dev); + + /* + * Open the device. If .d_open returns ENXIO (device not + * configured), the driver may not be loaded, so try + * autoloading a module and then try .d_open again if anything + * got loaded. + */ switch (vp->v_type) { case VCHR: do { @@ -871,7 +887,16 @@ spec_open(void *v) default: __unreachable(); } + + /* + * Release the I/O reference now that we have called .d_open, + * and reacquire the vnode lock. At this point, the device may + * have been revoked, so we must tread carefully. However, sn + * and sd remain valid pointers until we drop our reference. + */ + spec_io_exit(vp, sn); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + KASSERT(vp->v_specnode == sn); /* * If it has been revoked since we released the vnode lock and
CVS commit: src/sys/miscfs/specfs
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:37:27 UTC 2022 Modified Files: src/sys/miscfs/specfs: spec_vnops.c Log Message: specfs: Take an I/O reference across bdev/cdev_open. - Revoke is used to invalidate all prior access control checks when device permissions are changing, so it must wait for .d_open to exit so any new access must go through new access control checks. - Revoke is used by vdevgone in xyz_detach to wait until all use of the driver's data structures have completed before xyz_detach frees them. So we need to make sure spec_close waits for .d_open too. To generate a diff of this commit: cvs rdiff -u -r1.205 -r1.206 src/sys/miscfs/specfs/spec_vnops.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/miscfs/specfs
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:37:18 UTC 2022 Modified Files: src/sys/miscfs/specfs: spec_vnops.c Log Message: specfs: Wait for last close in spec_node_revoke. Otherwise, revoke -- and vdevgone, in the detach path of removable devices -- may complete while I/O operations are still running concurrently. To generate a diff of this commit: cvs rdiff -u -r1.204 -r1.205 src/sys/miscfs/specfs/spec_vnops.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/miscfs/specfs/spec_vnops.c diff -u src/sys/miscfs/specfs/spec_vnops.c:1.204 src/sys/miscfs/specfs/spec_vnops.c:1.205 --- src/sys/miscfs/specfs/spec_vnops.c:1.204 Mon Mar 28 12:37:09 2022 +++ src/sys/miscfs/specfs/spec_vnops.c Mon Mar 28 12:37:18 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: spec_vnops.c,v 1.204 2022/03/28 12:37:09 riastradh Exp $ */ +/* $NetBSD: spec_vnops.c,v 1.205 2022/03/28 12:37:18 riastradh Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -58,7 +58,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.204 2022/03/28 12:37:09 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.205 2022/03/28 12:37:18 riastradh Exp $"); #include #include @@ -597,6 +597,16 @@ spec_node_revoke(vnode_t *vp) mutex_enter(_lock); KASSERT(sn->sn_opencnt == 0); } + + /* + * We may have revoked the vnode in this thread while another + * thread was in the middle of spec_close, in the window when + * spec_close releases the vnode lock to call .d_close for the + * last close. In that case, wait for the concurrent + * spec_close to complete. + */ + while (sd->sd_closing) + cv_wait(_iocv, _lock); mutex_exit(_lock); }
CVS commit: src/sys/miscfs/specfs
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:37:18 UTC 2022 Modified Files: src/sys/miscfs/specfs: spec_vnops.c Log Message: specfs: Wait for last close in spec_node_revoke. Otherwise, revoke -- and vdevgone, in the detach path of removable devices -- may complete while I/O operations are still running concurrently. To generate a diff of this commit: cvs rdiff -u -r1.204 -r1.205 src/sys/miscfs/specfs/spec_vnops.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/miscfs/specfs
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:37:09 UTC 2022 Modified Files: src/sys/miscfs/specfs: spec_vnops.c specdev.h Log Message: specfs: Prevent new opens while close is waiting to drain. Otherwise, bdev/cdev_close could have cancelled all _existing_ opens, and waited for them to complete (and freed resources used by them) -- but a new one could start, and hang (e.g., a tty), at the same time spec_close tries to drain all pending I/O operations, one of which (the new open) is now hanging indefinitely. Preventing the new open from even starting until bdev/cdev_close is finished and all I/O operations have drained avoids this deadlock. To generate a diff of this commit: cvs rdiff -u -r1.203 -r1.204 src/sys/miscfs/specfs/spec_vnops.c cvs rdiff -u -r1.49 -r1.50 src/sys/miscfs/specfs/specdev.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/miscfs/specfs/spec_vnops.c diff -u src/sys/miscfs/specfs/spec_vnops.c:1.203 src/sys/miscfs/specfs/spec_vnops.c:1.204 --- src/sys/miscfs/specfs/spec_vnops.c:1.203 Mon Mar 28 12:37:01 2022 +++ src/sys/miscfs/specfs/spec_vnops.c Mon Mar 28 12:37:09 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: spec_vnops.c,v 1.203 2022/03/28 12:37:01 riastradh Exp $ */ +/* $NetBSD: spec_vnops.c,v 1.204 2022/03/28 12:37:09 riastradh Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -58,7 +58,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.203 2022/03/28 12:37:01 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.204 2022/03/28 12:37:09 riastradh Exp $"); #include #include @@ -397,6 +397,7 @@ spec_node_init(vnode_t *vp, dev_t rdev) sd->sd_bdevvp = NULL; sd->sd_iocnt = 0; sd->sd_opened = false; + sd->sd_closing = false; sn->sn_dev = sd; sd = NULL; } else { @@ -734,8 +735,17 @@ spec_open(void *v) case VCHR: /* * Character devices can accept opens from multiple - * vnodes. + * vnodes. But first, wait for any close to finish. + * Wait under the vnode lock so we don't have to worry + * about the vnode being revoked while we wait. */ + while (sd->sd_closing) { + error = cv_wait_sig(_iocv, _lock); + if (error) +break; + } + if (error) + break; sd->sd_opencnt++; sn->sn_opencnt++; break; @@ -1605,8 +1615,10 @@ spec_close(void *v) count + 1); sd->sd_bdevvp = NULL; } - if (count == 0) + if (count == 0) { sd->sd_opened = false; + sd->sd_closing = true; + } mutex_exit(_lock); if (count != 0) @@ -1631,6 +1643,18 @@ spec_close(void *v) */ spec_io_drain(sd); + /* + * Wake any spec_open calls waiting for close to finish -- do + * this before reacquiring the vnode lock, because spec_open + * holds the vnode lock while waiting, so doing this after + * reacquiring the lock would deadlock. + */ + mutex_enter(_lock); + KASSERT(sd->sd_closing); + sd->sd_closing = false; + cv_broadcast(_iocv); + mutex_exit(_lock); + if (!(flags & FNONBLOCK)) vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); Index: src/sys/miscfs/specfs/specdev.h diff -u src/sys/miscfs/specfs/specdev.h:1.49 src/sys/miscfs/specfs/specdev.h:1.50 --- src/sys/miscfs/specfs/specdev.h:1.49 Mon Mar 28 12:36:51 2022 +++ src/sys/miscfs/specfs/specdev.h Mon Mar 28 12:37:09 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: specdev.h,v 1.49 2022/03/28 12:36:51 riastradh Exp $ */ +/* $NetBSD: specdev.h,v 1.50 2022/03/28 12:37:09 riastradh Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -80,6 +80,7 @@ typedef struct specdev { dev_t sd_rdev; volatile u_int sd_iocnt; /* # bdev/cdev_* operations active */ bool sd_opened; /* true if successfully opened */ + bool sd_closing; /* true when bdev/cdev_close ongoing */ } specdev_t; /*
CVS commit: src/sys/miscfs/specfs
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:37:09 UTC 2022 Modified Files: src/sys/miscfs/specfs: spec_vnops.c specdev.h Log Message: specfs: Prevent new opens while close is waiting to drain. Otherwise, bdev/cdev_close could have cancelled all _existing_ opens, and waited for them to complete (and freed resources used by them) -- but a new one could start, and hang (e.g., a tty), at the same time spec_close tries to drain all pending I/O operations, one of which (the new open) is now hanging indefinitely. Preventing the new open from even starting until bdev/cdev_close is finished and all I/O operations have drained avoids this deadlock. To generate a diff of this commit: cvs rdiff -u -r1.203 -r1.204 src/sys/miscfs/specfs/spec_vnops.c cvs rdiff -u -r1.49 -r1.50 src/sys/miscfs/specfs/specdev.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/miscfs/specfs
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:37:01 UTC 2022 Modified Files: src/sys/miscfs/specfs: spec_vnops.c Log Message: specfs: Take an I/O reference in spec_node_setmountedfs. This is not quite correct. We _should_ require the caller to hold a vnode lock around spec_node_getmountedfs, and an exclusive vnode lock around spec_node_setmountedfs, so that it is only necessary to check whether revoke has already happened, not hold an I/O reference. Unfortunately, various callers in various file systems don't follow this sensible rule. So let's at least make sure the vnode can't be revoked in spec_node_setmountedfs, while we're in bdev_ioctl, and leave a comment explaining what the sorry state of affairs is and how to fix it later. To generate a diff of this commit: cvs rdiff -u -r1.202 -r1.203 src/sys/miscfs/specfs/spec_vnops.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/miscfs/specfs/spec_vnops.c diff -u src/sys/miscfs/specfs/spec_vnops.c:1.202 src/sys/miscfs/specfs/spec_vnops.c:1.203 --- src/sys/miscfs/specfs/spec_vnops.c:1.202 Mon Mar 28 12:36:51 2022 +++ src/sys/miscfs/specfs/spec_vnops.c Mon Mar 28 12:37:01 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: spec_vnops.c,v 1.202 2022/03/28 12:36:51 riastradh Exp $ */ +/* $NetBSD: spec_vnops.c,v 1.203 2022/03/28 12:37:01 riastradh Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -58,7 +58,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.202 2022/03/28 12:36:51 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.203 2022/03/28 12:37:01 riastradh Exp $"); #include #include @@ -498,6 +498,11 @@ spec_node_lookup_by_mount(struct mount * /* * Get the file system mounted on this block device. + * + * XXX Caller should hold the vnode lock -- shared or exclusive -- so + * that this can't changed, and the vnode can't be revoked while we + * examine it. But not all callers do, and they're scattered through a + * lot of file systems, so we can't assert this yet. */ struct mount * spec_node_getmountedfs(vnode_t *devvp) @@ -512,23 +517,51 @@ spec_node_getmountedfs(vnode_t *devvp) /* * Set the file system mounted on this block device. + * + * XXX Caller should hold the vnode lock exclusively so this can't be + * changed or assumed by spec_node_getmountedfs while we change it, and + * the vnode can't be revoked while we handle it. But not all callers + * do, and they're scattered through a lot of file systems, so we can't + * assert this yet. Instead, for now, we'll take an I/O reference so + * at least the ioctl doesn't race with revoke/detach. + * + * If you do change this to assert an exclusive vnode lock, you must + * also do vdead_check before trying bdev_ioctl, because the vnode may + * have been revoked by the time the caller locked it, and this is + * _not_ a vop -- calls to spec_node_setmountedfs don't go through + * v_op, so revoking the vnode doesn't prevent further calls. + * + * XXX Caller should additionally have the vnode open, at least if mp + * is nonnull, but I'm not sure all callers do that -- need to audit. + * Currently udf closes the vnode before clearing the mount. */ void spec_node_setmountedfs(vnode_t *devvp, struct mount *mp) { struct dkwedge_info dkw; + struct specnode *sn; + dev_t dev; + int error; KASSERT(devvp->v_type == VBLK); - KASSERT(devvp->v_specnode->sn_dev->sd_mountpoint == NULL || mp == NULL); - devvp->v_specnode->sn_dev->sd_mountpoint = mp; - if (mp == NULL) - return; - if (bdev_ioctl(devvp->v_rdev, DIOCGWEDGEINFO, , FREAD, curlwp) != 0) + error = spec_io_enter(devvp, , ); + if (error) return; + KASSERT(sn->sn_dev->sd_mountpoint == NULL || mp == NULL); + sn->sn_dev->sd_mountpoint = mp; + if (mp == NULL) + goto out; + + error = bdev_ioctl(dev, DIOCGWEDGEINFO, , FREAD, curlwp); + if (error) + goto out; + strlcpy(mp->mnt_stat.f_mntfromlabel, dkw.dkw_wname, sizeof(mp->mnt_stat.f_mntfromlabel)); + +out: spec_io_exit(devvp, sn); } /*
CVS commit: src/sys/miscfs/specfs
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:37:01 UTC 2022 Modified Files: src/sys/miscfs/specfs: spec_vnops.c Log Message: specfs: Take an I/O reference in spec_node_setmountedfs. This is not quite correct. We _should_ require the caller to hold a vnode lock around spec_node_getmountedfs, and an exclusive vnode lock around spec_node_setmountedfs, so that it is only necessary to check whether revoke has already happened, not hold an I/O reference. Unfortunately, various callers in various file systems don't follow this sensible rule. So let's at least make sure the vnode can't be revoked in spec_node_setmountedfs, while we're in bdev_ioctl, and leave a comment explaining what the sorry state of affairs is and how to fix it later. To generate a diff of this commit: cvs rdiff -u -r1.202 -r1.203 src/sys/miscfs/specfs/spec_vnops.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/miscfs/specfs
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:36:51 UTC 2022 Modified Files: src/sys/miscfs/specfs: spec_vnops.c specdev.h Log Message: specfs: Drain all I/O operations after last .d_close call. New kind of I/O reference on specdevs, sd_iocnt. This could be done with psref instead; I chose a reference count instead for now because we already have to take a per-object lock anyway, v_interlock, for vdead_check, so another atomic is not likely to hurt much more. We can always change the mechanism inside spec_io_enter/exit/drain later on. Make sure every access to vp->v_rdev or vp->v_specnode and every call to a devsw operation is protected either: - by the vnode lock (with vdead_check if we unlocked/relocked), - by positive sd_opencnt, - by spec_io_enter/exit, or - by sd_opencnt management in open/close. To generate a diff of this commit: cvs rdiff -u -r1.201 -r1.202 src/sys/miscfs/specfs/spec_vnops.c cvs rdiff -u -r1.48 -r1.49 src/sys/miscfs/specfs/specdev.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/miscfs/specfs/spec_vnops.c diff -u src/sys/miscfs/specfs/spec_vnops.c:1.201 src/sys/miscfs/specfs/spec_vnops.c:1.202 --- src/sys/miscfs/specfs/spec_vnops.c:1.201 Mon Mar 28 12:36:42 2022 +++ src/sys/miscfs/specfs/spec_vnops.c Mon Mar 28 12:36:51 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: spec_vnops.c,v 1.201 2022/03/28 12:36:42 riastradh Exp $ */ +/* $NetBSD: spec_vnops.c,v 1.202 2022/03/28 12:36:51 riastradh Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -58,7 +58,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.201 2022/03/28 12:36:42 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.202 2022/03/28 12:36:51 riastradh Exp $"); #include #include @@ -81,6 +81,7 @@ __KERNEL_RCSID(0, "$NetBSD: spec_vnops.c #include #include #include +#include #include #include @@ -173,6 +174,7 @@ const struct vnodeopv_desc spec_vnodeop_ { _vnodeop_p, spec_vnodeop_entries }; static kauth_listener_t rawio_listener; +static struct kcondvar specfs_iocv; /* Returns true if vnode is /dev/mem or /dev/kmem. */ bool @@ -218,6 +220,141 @@ spec_init(void) rawio_listener = kauth_listen_scope(KAUTH_SCOPE_DEVICE, rawio_listener_cb, NULL); + cv_init(_iocv, "specio"); +} + +/* + * spec_io_enter(vp, , ) + * + * Enter an operation that may not hold vp's vnode lock or an + * fstrans on vp's mount. Until spec_io_exit, the vnode will not + * be revoked. + * + * On success, set sn to the specnode pointer and dev to the dev_t + * number and return zero. Caller must later call spec_io_exit + * when done. + * + * On failure, return ENXIO -- the device has been revoked and no + * longer exists. + */ +static int +spec_io_enter(struct vnode *vp, struct specnode **snp, dev_t *devp) +{ + dev_t dev; + struct specnode *sn; + unsigned iocnt; + int error = 0; + + mutex_enter(vp->v_interlock); + + /* + * Extract all the info we need from the vnode, unless the + * vnode has already been reclaimed. This can happen if the + * underlying device has been removed and all the device nodes + * for it have been revoked. The caller may not hold a vnode + * lock or fstrans to prevent this from happening before it has + * had an opportunity to notice the vnode is dead. + */ + if (vdead_check(vp, VDEAD_NOWAIT) != 0 || + (sn = vp->v_specnode) == NULL || + (dev = vp->v_rdev) == NODEV) { + error = ENXIO; + goto out; + } + + /* + * Notify spec_close that we are doing an I/O operation which + * may not be not bracketed by fstrans(9) and thus is not + * blocked by vfs suspension. + * + * We could hold this reference with psref(9) instead, but we + * already have to take the interlock for vdead_check, so + * there's not much more cost here to another atomic operation. + */ + do { + iocnt = atomic_load_relaxed(>sn_dev->sd_iocnt); + if (__predict_false(iocnt == UINT_MAX)) { + /* + * The I/O count is limited by the number of + * LWPs (which will never overflow this) -- + * unless one driver uses another driver via + * specfs, which is rather unusual, but which + * could happen via pud(4) userspace drivers. + * We could use a 64-bit count, but can't use + * atomics for that on all platforms. + * (Probably better to switch to psref or + * localcount instead.) + */ + error = EBUSY; + goto out; + } + } while (atomic_cas_uint(>sn_dev->sd_iocnt, iocnt, iocnt + 1) + != iocnt); + + /* Success! */ + *snp = sn; + *devp = dev; + error = 0; + +out: mutex_exit(vp->v_interlock); + return error; +} + +/* + * spec_io_exit(vp, sn) + * + * Exit an operation entered with a successful spec_io_enter -- + * allow concurrent spec_node_revoke to proceed. The argument sn + * must match the struct specnode pointer returned by spec_io_exit + * for vp. + */ +static void +spec_io_exit(struct vnode *vp, struct
CVS commit: src/sys/miscfs/specfs
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:36:51 UTC 2022 Modified Files: src/sys/miscfs/specfs: spec_vnops.c specdev.h Log Message: specfs: Drain all I/O operations after last .d_close call. New kind of I/O reference on specdevs, sd_iocnt. This could be done with psref instead; I chose a reference count instead for now because we already have to take a per-object lock anyway, v_interlock, for vdead_check, so another atomic is not likely to hurt much more. We can always change the mechanism inside spec_io_enter/exit/drain later on. Make sure every access to vp->v_rdev or vp->v_specnode and every call to a devsw operation is protected either: - by the vnode lock (with vdead_check if we unlocked/relocked), - by positive sd_opencnt, - by spec_io_enter/exit, or - by sd_opencnt management in open/close. To generate a diff of this commit: cvs rdiff -u -r1.201 -r1.202 src/sys/miscfs/specfs/spec_vnops.c cvs rdiff -u -r1.48 -r1.49 src/sys/miscfs/specfs/specdev.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
CVS commit: src/sys/miscfs/specfs
Module Name:src Committed By: riastradh Date: Mon Mar 28 12:36:42 UTC 2022 Modified Files: src/sys/miscfs/specfs: spec_vnops.c specdev.h Log Message: specfs: Resolve a race between close and a failing reopen. To generate a diff of this commit: cvs rdiff -u -r1.200 -r1.201 src/sys/miscfs/specfs/spec_vnops.c cvs rdiff -u -r1.47 -r1.48 src/sys/miscfs/specfs/specdev.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. Modified files: Index: src/sys/miscfs/specfs/spec_vnops.c diff -u src/sys/miscfs/specfs/spec_vnops.c:1.200 src/sys/miscfs/specfs/spec_vnops.c:1.201 --- src/sys/miscfs/specfs/spec_vnops.c:1.200 Mon Mar 28 12:36:26 2022 +++ src/sys/miscfs/specfs/spec_vnops.c Mon Mar 28 12:36:42 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: spec_vnops.c,v 1.200 2022/03/28 12:36:26 riastradh Exp $ */ +/* $NetBSD: spec_vnops.c,v 1.201 2022/03/28 12:36:42 riastradh Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -58,7 +58,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.200 2022/03/28 12:36:26 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: spec_vnops.c,v 1.201 2022/03/28 12:36:42 riastradh Exp $"); #include #include @@ -258,6 +258,7 @@ spec_node_init(vnode_t *vp, dev_t rdev) sd->sd_refcnt = 1; sd->sd_opencnt = 0; sd->sd_bdevvp = NULL; + sd->sd_opened = false; sn->sn_dev = sd; sd = NULL; } else { @@ -518,6 +519,7 @@ spec_open(void *v) spec_ioctl_t ioctl; u_int gen; const char *name; + bool needclose = false; struct partinfo pi; l = curlwp; @@ -688,12 +690,9 @@ spec_open(void *v) * must fail with EBADF. * * Otherwise, if opening it failed, back out and release the - * open reference. - * - * XXX This is wrong -- we might release the last open - * reference here, but we don't close the device. If only this - * thread's call to open failed, that's fine, but we might - * have: + * open reference. If it was ever successfully opened and we + * got the last reference this way, it's now our job to close + * it. This might happen in the following scenario: * * Thread 1 Thread 2 * VOP_OPEN @@ -710,21 +709,54 @@ spec_open(void *v) * release vnode lock * acquire vnode lock * --sd_opencnt == 0 - * but no .d_close (***) + * + * We can't resolve this by making spec_close wait for .d_open + * to complete before examining sd_opencnt, because .d_open can + * hang indefinitely, e.g. for a tty. */ mutex_enter(_lock); if (sn->sn_gone) { if (error == 0) error = EBADF; - } else if (error != 0) { + } else if (error == 0) { + sd->sd_opened = true; + } else if (sd->sd_opencnt == 1 && sd->sd_opened) { + /* + * We're the last reference to a _previous_ open even + * though this one failed, so we have to close it. + * Don't decrement the reference count here -- + * spec_close will do that. + */ + KASSERT(sn->sn_opencnt == 1); + needclose = true; + } else { sd->sd_opencnt--; sn->sn_opencnt--; if (vp->v_type == VBLK) sd->sd_bdevvp = NULL; - } mutex_exit(_lock); + /* + * If this open failed, but the device was previously opened, + * and another thread concurrently closed the vnode while we + * were in the middle of reopening it, the other thread will + * see sd_opencnt > 0 and thus decide not to call .d_close -- + * it is now our responsibility to do so. + * + * XXX The flags passed to VOP_CLOSE here are wrong, but + * drivers can't rely on FREAD|FWRITE anyway -- e.g., consider + * a device opened by thread 0 with O_READ, then opened by + * thread 1 with O_WRITE, then closed by thread 0, and finally + * closed by thread 1; the last .d_close call will have FWRITE + * but not FREAD. We should just eliminate the FREAD/FWRITE + * parameter to .d_close altogether. + */ + if (needclose) { + KASSERT(error); + VOP_CLOSE(vp, FNONBLOCK, NOCRED); + } + /* If anything went wrong, we're done. */ if (error) return error; @@ -1341,6 +1373,25 @@ spec_close(void *v) * device. For block devices, the open reference count must be * 1 at this point. If the device's open reference count goes * to zero, we're the last one out so get the lights. + * + * We may find --sd->sd_opencnt gives zero, and yet + * sd->sd_opened is false. This happens if the vnode is + * revoked at the same time as it is being opened, which can + * happen when opening a tty blocks indefinitely. In that + * case, we still must call close -- it is the job of close to + * interrupt the open. Either way, the device will be no + * longer opened, so we have to clear sd->sd_opened; subsequent + * opens will have responsibility for issuing close. + * + * This has the side effect that the sequence of opens might + * happen out of order -- we might end up doing open, open, + * close, close, instead of open, close, open, close. This is + * unavoidable with the current devsw API, where open is +