@@ -277,28 +277,14 @@ zpl_test_super(struct super_block *s, void *data)
277
277
{
278
278
zfsvfs_t * zfsvfs = s -> s_fs_info ;
279
279
objset_t * os = data ;
280
- int match ;
281
-
282
280
/*
283
281
* If the os doesn't match the z_os in the super_block, assume it is
284
282
* not a match. Matching would imply a multimount of a dataset. It is
285
283
* possible that during a multimount, there is a simultaneous operation
286
284
* that changes the z_os, e.g., rollback, where the match will be
287
285
* missed, but in that case the user will get an EBUSY.
288
286
*/
289
- if (zfsvfs == NULL || os != zfsvfs -> z_os )
290
- return (0 );
291
-
292
- /*
293
- * If they do match, recheck with the lock held to prevent mounting the
294
- * wrong dataset since z_os can be stale when the teardown lock is held.
295
- */
296
- if (zpl_enter (zfsvfs , FTAG ) != 0 )
297
- return (0 );
298
- match = (os == zfsvfs -> z_os );
299
- zpl_exit (zfsvfs , FTAG );
300
-
301
- return (match );
287
+ return (zfsvfs != NULL && os == zfsvfs -> z_os );
302
288
}
303
289
304
290
static struct super_block *
@@ -324,12 +310,35 @@ zpl_mount_impl(struct file_system_type *fs_type, int flags, zfs_mnt_t *zm)
324
310
325
311
s = sget (fs_type , zpl_test_super , set_anon_super , flags , os );
326
312
313
+ /*
314
+ * Recheck with the lock held to prevent mounting the wrong dataset
315
+ * since z_os can be stale when the teardown lock is held.
316
+ *
317
+ * We can't do this in zpl_test_super in since it's under spinlock and
318
+ * also s_umount lock is not held there so it would race with
319
+ * zfs_umount and zfsvfs can be freed.
320
+ */
321
+ if (!IS_ERR (s ) && s -> s_fs_info != NULL ) {
322
+ zfsvfs_t * zfsvfs = s -> s_fs_info ;
323
+ if (zpl_enter (zfsvfs , FTAG ) == 0 ) {
324
+ if (os != zfsvfs -> z_os )
325
+ err = - SET_ERROR (EBUSY );
326
+ zpl_exit (zfsvfs , FTAG );
327
+ } else {
328
+ err = - SET_ERROR (EBUSY );
329
+ }
330
+ }
327
331
dsl_dataset_long_rele (dmu_objset_ds (os ), FTAG );
328
332
dsl_dataset_rele (dmu_objset_ds (os ), FTAG );
329
333
330
334
if (IS_ERR (s ))
331
335
return (ERR_CAST (s ));
332
336
337
+ if (err ) {
338
+ deactivate_locked_super (s );
339
+ return (ERR_PTR (err ));
340
+ }
341
+
333
342
if (s -> s_root == NULL ) {
334
343
err = zpl_fill_super (s , zm , flags & SB_SILENT ? 1 : 0 );
335
344
if (err ) {
0 commit comments