@@ -91,40 +91,67 @@ zfsdev_get_dev(void)
9191 return ((dev_t )tsd_get (zfsdev_private_tsd ));
9292}
9393
94- /* Not sure what these are supposed to be - upstream assumes they can be set */
94+ /* We can't set ->private method, so this function does nothing */
9595void
9696zfsdev_private_set_state (void * priv , zfsdev_state_t * zs )
9797{
98+ zfsdev_state_t * * actual_zs = (zfsdev_state_t * * )priv ;
99+ if (actual_zs != NULL )
100+ * actual_zs = zs ;
98101}
99102
103+ /* Loop all zs looking for matching dev_t */
100104zfsdev_state_t *
101105zfsdev_private_get_state (void * priv )
102106{
107+ dev_t dev = (dev_t )priv ;
108+ zfsdev_state_t * zs ;
109+ mutex_enter (& zfsdev_state_lock );
110+ zs = zfsdev_get_state (dev , ZST_ALL );
111+ mutex_exit (& zfsdev_state_lock );
112+ return (zs );
103113}
104114
105115static int
106116zfsdev_open (dev_t dev , int flags , int devtype , struct proc * p )
107117{
108118 int error ;
119+ zfsdev_state_t * actual_zs = NULL ;
109120
110121 mutex_enter (& zfsdev_state_lock );
111- if (zfsdev_get_state (minor (dev ), ZST_ALL )) {
112- mutex_exit (& zfsdev_state_lock );
113- return (0 );
114- }
115- error = zfsdev_state_init ((void * )dev );
116- mutex_exit (& zfsdev_state_lock );
117122
118- return (- error );
123+ /*
124+ * Check if the minor already exists, something that zfsdev_state_init()
125+ * does internally, but it doesn't know of the minor we are to use.
126+ * This should never happen, so use ASSERT()
127+ */
128+ ASSERT3P (zfsdev_get_state (minor (dev ), ZST_ALL ), = = , NULL );
129+
130+ error = zfsdev_state_init ((void * )& actual_zs );
131+ /*
132+ * We are given the minor to use, so we set it here. We can't use
133+ * zfsdev_private_set_state() as it is called before zfsdev_state_init()
134+ * sets the minor. Also, since zfsdev_state_init() doesn't return zs
135+ * nor the minor they pick, we ab/use "priv" to return it to us.
136+ * Maybe we should change zfsdev_state_init() instead of this dance,
137+ * either to take 'minor' to use, or, to return zs.
138+ */
139+ if (error == 0 && actual_zs != NULL )
140+ actual_zs -> zs_minor = minor (dev );
141+ mutex_exit (& zfsdev_state_lock );
142+ return (error );
119143}
120144
121145static int
122146zfsdev_release (dev_t dev , int flags , int devtype , struct proc * p )
123147{
124- mutex_enter (& zfsdev_state_lock );
125- zfsdev_state_destroy ((void * )dev );
126- mutex_exit (& zfsdev_state_lock );
148+ /* zfsdev_state_destroy() doesn't check for NULL, so pre-lookup here */
149+ void * priv ;
127150
151+ priv = (void * )(uintptr_t )minor (dev );
152+ zfsdev_state_t * zs = zfsdev_private_get_state (priv );
153+ if (zs != NULL )
154+ zfsdev_state_destroy (priv );
128155 return (0 );
129156}
130157
@@ -240,9 +267,7 @@ static int
240267zfs_ioc_osx_proxy_remove (const char * unused , nvlist_t * innvl ,
241268 nvlist_t * outnvl )
242269{
243- int error ;
244270 char * osname = NULL ;
245- char value [MAXPATHLEN * 2 ];
246271
247272 if (nvlist_lookup_string (innvl ,
248273 ZPOOL_CONFIG_POOL_NAME , & osname ) != 0 )
@@ -304,6 +329,33 @@ static struct cdevsw zfs_cdevsw = {
304329 .d_type = D_DISK
305330};
306331
332+ /*
333+ * This is an identical copy of zfsdev_minor_alloc() except we check if
334+ * 'last_minor + 0' is available instead of 'last_minor + 1'. The latter
335+ * will cycle through minors unnecessarily, when it 'often' is available
336+ * again. Which gives us unattractive things like;
337+ * crw-rw-rw- 1 root wheel 34, 0x0000213A May 31 14:42 /dev/zfs
338+ */
339+ static minor_t
340+ zfsdev_minor_alloc_os (void )
341+ {
342+ static minor_t last_minor = 0 ;
343+ minor_t m ;
344+
345+ ASSERT (MUTEX_HELD (& zfsdev_state_lock ));
346+
347+ for (m = last_minor ; m != last_minor ; m ++ ) {
348+ if (m > ZFSDEV_MAX_MINOR )
349+ m = 1 ;
350+ if (zfsdev_get_state (m , ZST_ALL ) == NULL ) {
351+ last_minor = m ;
352+ return (m );
353+ }
354+ }
355+
356+ return (0 );
357+ }
358+
307359/* Callback to create a unique minor for each open */
308360static int
309361zfs_devfs_clone (__unused dev_t dev , int action )
@@ -312,7 +364,7 @@ zfs_devfs_clone(__unused dev_t dev, int action)
312364
313365 if (action == DEVFS_CLONE_ALLOC ) {
314366 mutex_enter (& zfsdev_state_lock );
315- minorx = zfsdev_minor_alloc ();
367+ minorx = zfsdev_minor_alloc_os ();
316368 mutex_exit (& zfsdev_state_lock );
317369 return (minorx );
318370 }
0 commit comments