1.\" Copyright (c) 2018 Conrad Meyer <cem@FreeBSD.org> 2.\" All rights reserved. 3.\" 4.\" Redistribution and use in source and binary forms, with or without 5.\" modification, are permitted provided that the following conditions 6.\" are met: 7.\" 1. Redistributions of source code must retain the above copyright 8.\" notice, this list of conditions and the following disclaimer. 9.\" 2. Redistributions in binary form must reproduce the above copyright 10.\" notice, this list of conditions and the following disclaimer in the 11.\" documentation and/or other materials provided with the distribution. 12.\" 13.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23.\" SUCH DAMAGE. 24.\" 25.Dd August 29, 2018 26.Dt DEV_REFTHREAD 9 27.Os 28.Sh NAME 29.Nm dev_refthread , 30.Nm devvn_refthread , 31.Nm dev_relthread 32.Nd safely access device methods 33.Sh SYNOPSIS 34.In sys/param.h 35.In sys/conf.h 36.Ft "struct cdevsw *" 37.Fn dev_refthread "struct cdev *dev" "int *ref" 38.Ft "struct cdevsw *" 39.Fn devvn_refthread "struct vnode *vp" "struct cdev **devp" "int *ref" 40.Ft void 41.Fn dev_relthread "struct cdev *dev" "int ref" 42.Sh DESCRIPTION 43The 44.Fn dev_refthread 45(or 46.Fn devvn_refthread ) 47and 48.Fn dev_relthread 49routines provide a safe way to access 50.Xr devfs 5 51devices that may be concurrently destroyed by 52.Fn destroy_dev 53(e.g., removable media). 54.Pp 55If successful, 56.Fn dev_refthread 57and 58.Fn devvn_refthread 59acquire a "thread reference" to the associated 60.Vt "struct cdev" 61and return a non-NULL pointer to the cdev's 62.Vt "struct cdevsw" 63method table. 64For the duration of that reference, the cdev's associated private data and 65method table object are valid. 66Destruction of the cdev sleeps until the thread reference is released. 67.Pp 68A reference cannot prevent media removal. 69It is an implementation detail of individual drivers how method calls from 70callers with 71.Fn dev_refthread 72references are handled when the device is 73pending destruction. 74A common behavior for disk devices is to return the 75.Er ENXIO 76status, but that is not required by this KPI. 77.Pp 78The 79.Fn devvn_refthread 80variant of 81.Fn dev_refthread 82extracts the 83.Vt "struct cdev" 84pointer out of the 85.Dv VCHR 86.Xr vnode 9 87automatically before performing the same actions as 88.Fn dev_refthread . 89Additionally, a pointer to the 90.Vt "struct cdev" 91is returned to the caller via 92.Fa "*devp" . 93.Fn devvn_refthread 94correctly handles possible parallel reclamation of the vnode. 95.Pp 96.Fn dev_relthread 97is used to release a reference to a 98.Vt "struct cdev" . 99.Fn dev_relthread 100.Sy must 101only be invoked when the associated invocation of 102.Fn dev_refthread 103or 104.Fn devvn_refthread 105returned a non-NULL 106.Vt "struct cdevsw *" . 107.Sh CONTEXT 108.Vt struct cdev 109objects have two reference counts, 110.Va si_refcount 111and 112.Va si_threadcount . 113The 114.Fn dev_refthread , 115.Fn devvn_refthread , 116and 117.Fn dev_relthread 118functions manipulate the 119.Va si_threadcount . 120The 121.Va si_threadcount 122reference guarantees the liveness of the 123.Vt struct cdev 124object. 125The other 126.Va si_refcount 127reference provides only the weaker guarantee that the memory backing the 128.Vt struct cdev 129has not been freed. 130.Sh RETURN VALUES 131If 132.Fn dev_refthread 133or 134.Fn devvn_refthread 135are unsuccessful, they return 136.Dv NULL . 137.Bf Em 138If these routines are unsuccessful, they do not increment the 139.Vt "struct cdev" 140.Va si_threadcount 141and do not initialize the value pointed to by the 142.Fa "*ref" 143parameter in any way. 144.Ef 145.Sh SEE ALSO 146.Xr devfs 5 , 147.Xr destroy_dev 9 148.Sh CAVEATS 149Do not invoke 150.Fn dev_relthread 151unless the matching refthread routine succeeded! 152