Tue Apr 25 21:31:33 2017 UTC ()
Call localcount_init() before publishing the new {b,c}devsw.

Thanks to riastradh@


(pgoyette)
diff -r1.34.2.14 -r1.34.2.15 src/sys/kern/subr_devsw.c

cvs diff -r1.34.2.14 -r1.34.2.15 src/sys/kern/subr_devsw.c (expand / switch to unified diff)

--- src/sys/kern/subr_devsw.c 2017/01/07 08:56:49 1.34.2.14
+++ src/sys/kern/subr_devsw.c 2017/04/25 21:31:33 1.34.2.15
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: subr_devsw.c,v 1.34.2.14 2017/01/07 08:56:49 pgoyette Exp $ */ 1/* $NetBSD: subr_devsw.c,v 1.34.2.15 2017/04/25 21:31:33 pgoyette Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2001, 2002, 2007, 2008 The NetBSD Foundation, Inc. 4 * Copyright (c) 2001, 2002, 2007, 2008 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by MAEKAWA Masahide <gehenna@NetBSD.org>, and by Andrew Doran. 8 * by MAEKAWA Masahide <gehenna@NetBSD.org>, and by Andrew Doran.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -59,27 +59,27 @@ @@ -59,27 +59,27 @@
59 * o Regardless of whether other threads see the old or new 59 * o Regardless of whether other threads see the old or new
60 * pointers, they will point to a correct device switch 60 * pointers, they will point to a correct device switch
61 * structure for the operation being performed. 61 * structure for the operation being performed.
62 * 62 *
63 * XXX Currently, the wrapper methods such as cdev_read() verify 63 * XXX Currently, the wrapper methods such as cdev_read() verify
64 * that a device driver does in fact exist before calling the 64 * that a device driver does in fact exist before calling the
65 * associated driver method. This should be changed so that 65 * associated driver method. This should be changed so that
66 * once the device is has been referenced by a vnode (opened), 66 * once the device is has been referenced by a vnode (opened),
67 * calling the other methods should be valid until that reference 67 * calling the other methods should be valid until that reference
68 * is dropped. 68 * is dropped.
69 */ 69 */
70 70
71#include <sys/cdefs.h> 71#include <sys/cdefs.h>
72__KERNEL_RCSID(0, "$NetBSD: subr_devsw.c,v 1.34.2.14 2017/01/07 08:56:49 pgoyette Exp $"); 72__KERNEL_RCSID(0, "$NetBSD: subr_devsw.c,v 1.34.2.15 2017/04/25 21:31:33 pgoyette Exp $");
73 73
74#ifdef _KERNEL_OPT 74#ifdef _KERNEL_OPT
75#include "opt_dtrace.h" 75#include "opt_dtrace.h"
76#endif 76#endif
77 77
78#include <sys/param.h> 78#include <sys/param.h>
79#include <sys/conf.h> 79#include <sys/conf.h>
80#include <sys/kmem.h> 80#include <sys/kmem.h>
81#include <sys/systm.h> 81#include <sys/systm.h>
82#include <sys/poll.h> 82#include <sys/poll.h>
83#include <sys/tty.h> 83#include <sys/tty.h>
84#include <sys/cpu.h> 84#include <sys/cpu.h>
85#include <sys/buf.h> 85#include <sys/buf.h>
@@ -290,33 +290,34 @@ bdevsw_attach(const struct bdevsw *devsw @@ -290,33 +290,34 @@ bdevsw_attach(const struct bdevsw *devsw
290 if (*devmajor >= max_bdevsws) { 290 if (*devmajor >= max_bdevsws) {
291 KASSERT(bdevsw == bdevsw0); 291 KASSERT(bdevsw == bdevsw0);
292 newptr = kmem_zalloc(MAXDEVSW * BDEVSW_SIZE, KM_NOSLEEP); 292 newptr = kmem_zalloc(MAXDEVSW * BDEVSW_SIZE, KM_NOSLEEP);
293 if (newptr == NULL) 293 if (newptr == NULL)
294 return (ENOMEM); 294 return (ENOMEM);
295 memcpy(newptr, bdevsw, max_bdevsws * BDEVSW_SIZE); 295 memcpy(newptr, bdevsw, max_bdevsws * BDEVSW_SIZE);
296 bdevsw = newptr; 296 bdevsw = newptr;
297 max_bdevsws = MAXDEVSW; 297 max_bdevsws = MAXDEVSW;
298 } 298 }
299 299
300 if (bdevsw[*devmajor] != NULL) 300 if (bdevsw[*devmajor] != NULL)
301 return (EEXIST); 301 return (EEXIST);
302 302
 303 KASSERTMSG(devsw->d_localcount != NULL, "%s: bdev for major %d has "
 304 "no localcount", __func__, *devmajor);
 305 localcount_init(devsw->d_localcount);
 306
303 /* ensure visibility of the bdevsw */ 307 /* ensure visibility of the bdevsw */
304 membar_producer(); 308 membar_producer();
305 309
306 bdevsw[*devmajor] = devsw; 310 bdevsw[*devmajor] = devsw;
307 KASSERTMSG(devsw->d_localcount != NULL, "%s: bdev for major %d has " 
308 "no localcount", __func__, *devmajor); 
309 localcount_init(devsw->d_localcount); 
310 311
311 return (0); 312 return (0);
312} 313}
313 314
314static int 315static int
315cdevsw_attach(const struct cdevsw *devsw, devmajor_t *devmajor) 316cdevsw_attach(const struct cdevsw *devsw, devmajor_t *devmajor)
316{ 317{
317 const struct cdevsw **newptr; 318 const struct cdevsw **newptr;
318 devmajor_t cmajor; 319 devmajor_t cmajor;
319 int i; 320 int i;
320 321
321 KASSERT(mutex_owned(&device_lock)); 322 KASSERT(mutex_owned(&device_lock));
322 323
@@ -343,33 +344,34 @@ cdevsw_attach(const struct cdevsw *devsw @@ -343,33 +344,34 @@ cdevsw_attach(const struct cdevsw *devsw
343 if (*devmajor >= max_cdevsws) { 344 if (*devmajor >= max_cdevsws) {
344 KASSERT(cdevsw == cdevsw0); 345 KASSERT(cdevsw == cdevsw0);
345 newptr = kmem_zalloc(MAXDEVSW * CDEVSW_SIZE, KM_NOSLEEP); 346 newptr = kmem_zalloc(MAXDEVSW * CDEVSW_SIZE, KM_NOSLEEP);
346 if (newptr == NULL) 347 if (newptr == NULL)
347 return (ENOMEM); 348 return (ENOMEM);
348 memcpy(newptr, cdevsw, max_cdevsws * CDEVSW_SIZE); 349 memcpy(newptr, cdevsw, max_cdevsws * CDEVSW_SIZE);
349 cdevsw = newptr; 350 cdevsw = newptr;
350 max_cdevsws = MAXDEVSW; 351 max_cdevsws = MAXDEVSW;
351 } 352 }
352 353
353 if (cdevsw[*devmajor] != NULL) 354 if (cdevsw[*devmajor] != NULL)
354 return (EEXIST); 355 return (EEXIST);
355 356
 357 KASSERTMSG(devsw->d_localcount != NULL, "%s: cdev for major %d has "
 358 "no localcount", __func__, *devmajor);
 359 localcount_init(devsw->d_localcount);
 360
356 /* ensure visibility of the cdevsw */ 361 /* ensure visibility of the cdevsw */
357 membar_producer(); 362 membar_producer();
358 363
359 cdevsw[*devmajor] = devsw; 364 cdevsw[*devmajor] = devsw;
360 KASSERTMSG(devsw->d_localcount != NULL, "%s: cdev for major %d has " 
361 "no localcount", __func__, *devmajor); 
362 localcount_init(devsw->d_localcount); 
363 365
364 return (0); 366 return (0);
365} 367}
366 368
367/* 369/*
368 * First, look up both bdev and cdev indices, and remove the 370 * First, look up both bdev and cdev indices, and remove the
369 * {b,c]devsw[] entries so no new references can be taken. Then 371 * {b,c]devsw[] entries so no new references can be taken. Then
370 * drain any existing references. 372 * drain any existing references.
371 */ 373 */
372 374
373static void 375static void
374devsw_detach_locked(const struct bdevsw *bdev, const struct cdevsw *cdev) 376devsw_detach_locked(const struct bdevsw *bdev, const struct cdevsw *cdev)
375{ 377{