Skip to content

Commit 032f920

Browse files
committed
macOS: changes to zfsdev_get_state
macOS: use our minor with zfsdev_state_init() [squash] macOS: avoid cycling through minors
1 parent 547b854 commit 032f920

File tree

1 file changed

+66
-14
lines changed

1 file changed

+66
-14
lines changed

module/os/macos/zfs/zfs_ioctl_os.c

Lines changed: 66 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -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 */
9595
void
9696
zfsdev_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 */
100104
zfsdev_state_t *
101105
zfsdev_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

105115
static int
106116
zfsdev_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

121145
static int
122146
zfsdev_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
240267
zfs_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 */
308360
static int
309361
zfs_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

Comments
 (0)