@@ -1145,20 +1145,34 @@ zvol_tag(zvol_state_t *zv)
1145
1145
/*
1146
1146
* Suspend the zvol for recv and rollback.
1147
1147
*/
1148
- zvol_state_t *
1149
- zvol_suspend (const char * name )
1148
+ int
1149
+ zvol_suspend (const char * name , zvol_state_t * * zvp )
1150
1150
{
1151
1151
zvol_state_t * zv ;
1152
1152
1153
1153
zv = zvol_find_by_name (name , RW_WRITER );
1154
1154
1155
1155
if (zv == NULL )
1156
- return (NULL );
1156
+ return (SET_ERROR ( ENOENT ) );
1157
1157
1158
1158
/* block all I/O, release in zvol_resume. */
1159
1159
ASSERT (MUTEX_HELD (& zv -> zv_state_lock ));
1160
1160
ASSERT (RW_WRITE_HELD (& zv -> zv_suspend_lock ));
1161
1161
1162
+ /*
1163
+ * If it's being removed, unlock and return error. It doesn't make any
1164
+ * sense to try to suspend a zvol being removed, but being here also
1165
+ * means that zvol_remove_minors_impl() is about to call zvol_remove()
1166
+ * and then destroy the zvol_state_t, so returning a pointer to it for
1167
+ * the caller to mess with would be a disaster anyway.
1168
+ */
1169
+ if (zv -> zv_flags & ZVOL_REMOVING ) {
1170
+ mutex_exit (& zv -> zv_state_lock );
1171
+ rw_exit (& zv -> zv_suspend_lock );
1172
+ /* NB: Returning EIO here to match zfsvfs_teardown() */
1173
+ return (SET_ERROR (EIO ));
1174
+ }
1175
+
1162
1176
atomic_inc (& zv -> zv_suspend_ref );
1163
1177
1164
1178
if (zv -> zv_open_count > 0 )
@@ -1171,7 +1185,8 @@ zvol_suspend(const char *name)
1171
1185
mutex_exit (& zv -> zv_state_lock );
1172
1186
1173
1187
/* zv_suspend_lock is released in zvol_resume() */
1174
- return (zv );
1188
+ * zvp = zv ;
1189
+ return (0 );
1175
1190
}
1176
1191
1177
1192
int
0 commit comments