@@ -43,9 +43,8 @@ static struct vfio {
43
43
struct list_head iommu_drivers_list ;
44
44
struct mutex iommu_drivers_lock ;
45
45
struct list_head group_list ;
46
- struct idr group_idr ;
47
- struct mutex group_lock ;
48
- struct cdev group_cdev ;
46
+ struct mutex group_lock ; /* locks group_list */
47
+ struct ida group_ida ;
49
48
dev_t group_devt ;
50
49
} vfio ;
51
50
@@ -69,14 +68,14 @@ struct vfio_unbound_dev {
69
68
};
70
69
71
70
struct vfio_group {
71
+ struct device dev ;
72
+ struct cdev cdev ;
72
73
refcount_t users ;
73
- int minor ;
74
74
atomic_t container_users ;
75
75
struct iommu_group * iommu_group ;
76
76
struct vfio_container * container ;
77
77
struct list_head device_list ;
78
78
struct mutex device_lock ;
79
- struct device * dev ;
80
79
struct notifier_block nb ;
81
80
struct list_head vfio_next ;
82
81
struct list_head container_next ;
@@ -98,6 +97,7 @@ MODULE_PARM_DESC(enable_unsafe_noiommu_mode, "Enable UNSAFE, no-IOMMU mode. Thi
98
97
#endif
99
98
100
99
static DEFINE_XARRAY (vfio_device_set_xa );
100
+ static const struct file_operations vfio_group_fops ;
101
101
102
102
int vfio_assign_device_set (struct vfio_device * device , void * set_id )
103
103
{
@@ -281,19 +281,6 @@ void vfio_unregister_iommu_driver(const struct vfio_iommu_driver_ops *ops)
281
281
}
282
282
EXPORT_SYMBOL_GPL (vfio_unregister_iommu_driver );
283
283
284
- /**
285
- * Group minor allocation/free - both called with vfio.group_lock held
286
- */
287
- static int vfio_alloc_group_minor (struct vfio_group * group )
288
- {
289
- return idr_alloc (& vfio .group_idr , group , 0 , MINORMASK + 1 , GFP_KERNEL );
290
- }
291
-
292
- static void vfio_free_group_minor (int minor )
293
- {
294
- idr_remove (& vfio .group_idr , minor );
295
- }
296
-
297
284
static int vfio_iommu_group_notifier (struct notifier_block * nb ,
298
285
unsigned long action , void * data );
299
286
static void vfio_group_get (struct vfio_group * group );
@@ -322,22 +309,6 @@ static void vfio_container_put(struct vfio_container *container)
322
309
kref_put (& container -> kref , vfio_container_release );
323
310
}
324
311
325
- static void vfio_group_unlock_and_free (struct vfio_group * group )
326
- {
327
- struct vfio_unbound_dev * unbound , * tmp ;
328
-
329
- mutex_unlock (& vfio .group_lock );
330
- iommu_group_unregister_notifier (group -> iommu_group , & group -> nb );
331
-
332
- list_for_each_entry_safe (unbound , tmp ,
333
- & group -> unbound_list , unbound_next ) {
334
- list_del (& unbound -> unbound_next );
335
- kfree (unbound );
336
- }
337
- iommu_group_put (group -> iommu_group );
338
- kfree (group );
339
- }
340
-
341
312
/**
342
313
* Group objects - create, release, get, put, search
343
314
*/
@@ -366,71 +337,112 @@ vfio_group_get_from_iommu(struct iommu_group *iommu_group)
366
337
return group ;
367
338
}
368
339
369
- static struct vfio_group * vfio_create_group (struct iommu_group * iommu_group ,
370
- enum vfio_group_type type )
340
+ static void vfio_group_release (struct device * dev )
371
341
{
372
- struct vfio_group * group , * existing_group ;
373
- struct device * dev ;
374
- int ret , minor ;
342
+ struct vfio_group * group = container_of (dev , struct vfio_group , dev );
343
+ struct vfio_unbound_dev * unbound , * tmp ;
344
+
345
+ list_for_each_entry_safe (unbound , tmp ,
346
+ & group -> unbound_list , unbound_next ) {
347
+ list_del (& unbound -> unbound_next );
348
+ kfree (unbound );
349
+ }
350
+
351
+ mutex_destroy (& group -> device_lock );
352
+ mutex_destroy (& group -> unbound_lock );
353
+ iommu_group_put (group -> iommu_group );
354
+ ida_free (& vfio .group_ida , MINOR (group -> dev .devt ));
355
+ kfree (group );
356
+ }
357
+
358
+ static struct vfio_group * vfio_group_alloc (struct iommu_group * iommu_group ,
359
+ enum vfio_group_type type )
360
+ {
361
+ struct vfio_group * group ;
362
+ int minor ;
375
363
376
364
group = kzalloc (sizeof (* group ), GFP_KERNEL );
377
365
if (!group )
378
366
return ERR_PTR (- ENOMEM );
379
367
368
+ minor = ida_alloc_max (& vfio .group_ida , MINORMASK , GFP_KERNEL );
369
+ if (minor < 0 ) {
370
+ kfree (group );
371
+ return ERR_PTR (minor );
372
+ }
373
+
374
+ device_initialize (& group -> dev );
375
+ group -> dev .devt = MKDEV (MAJOR (vfio .group_devt ), minor );
376
+ group -> dev .class = vfio .class ;
377
+ group -> dev .release = vfio_group_release ;
378
+ cdev_init (& group -> cdev , & vfio_group_fops );
379
+ group -> cdev .owner = THIS_MODULE ;
380
+
380
381
refcount_set (& group -> users , 1 );
381
382
INIT_LIST_HEAD (& group -> device_list );
382
383
mutex_init (& group -> device_lock );
383
384
INIT_LIST_HEAD (& group -> unbound_list );
384
385
mutex_init (& group -> unbound_lock );
385
- atomic_set (& group -> container_users , 0 );
386
- atomic_set (& group -> opened , 0 );
387
386
init_waitqueue_head (& group -> container_q );
388
387
group -> iommu_group = iommu_group ;
389
- /* put in vfio_group_unlock_and_free () */
388
+ /* put in vfio_group_release () */
390
389
iommu_group_ref_get (iommu_group );
391
390
group -> type = type ;
392
391
BLOCKING_INIT_NOTIFIER_HEAD (& group -> notifier );
393
392
393
+ return group ;
394
+ }
395
+
396
+ static struct vfio_group * vfio_create_group (struct iommu_group * iommu_group ,
397
+ enum vfio_group_type type )
398
+ {
399
+ struct vfio_group * group ;
400
+ struct vfio_group * ret ;
401
+ int err ;
402
+
403
+ group = vfio_group_alloc (iommu_group , type );
404
+ if (IS_ERR (group ))
405
+ return group ;
406
+
407
+ err = dev_set_name (& group -> dev , "%s%d" ,
408
+ group -> type == VFIO_NO_IOMMU ? "noiommu-" : "" ,
409
+ iommu_group_id (iommu_group ));
410
+ if (err ) {
411
+ ret = ERR_PTR (err );
412
+ goto err_put ;
413
+ }
414
+
394
415
group -> nb .notifier_call = vfio_iommu_group_notifier ;
395
- ret = iommu_group_register_notifier (iommu_group , & group -> nb );
396
- if (ret ) {
397
- iommu_group_put (iommu_group );
398
- kfree (group );
399
- return ERR_PTR (ret );
416
+ err = iommu_group_register_notifier (iommu_group , & group -> nb );
417
+ if (err ) {
418
+ ret = ERR_PTR (err );
419
+ goto err_put ;
400
420
}
401
421
402
422
mutex_lock (& vfio .group_lock );
403
423
404
424
/* Did we race creating this group? */
405
- existing_group = __vfio_group_get_from_iommu (iommu_group );
406
- if (existing_group ) {
407
- vfio_group_unlock_and_free (group );
408
- return existing_group ;
409
- }
410
-
411
- minor = vfio_alloc_group_minor (group );
412
- if (minor < 0 ) {
413
- vfio_group_unlock_and_free (group );
414
- return ERR_PTR (minor );
415
- }
425
+ ret = __vfio_group_get_from_iommu (iommu_group );
426
+ if (ret )
427
+ goto err_unlock ;
416
428
417
- dev = device_create (vfio .class , NULL ,
418
- MKDEV (MAJOR (vfio .group_devt ), minor ), group , "%s%d" ,
419
- group -> type == VFIO_NO_IOMMU ? "noiommu-" : "" ,
420
- iommu_group_id (iommu_group ));
421
- if (IS_ERR (dev )) {
422
- vfio_free_group_minor (minor );
423
- vfio_group_unlock_and_free (group );
424
- return ERR_CAST (dev );
429
+ err = cdev_device_add (& group -> cdev , & group -> dev );
430
+ if (err ) {
431
+ ret = ERR_PTR (err );
432
+ goto err_unlock ;
425
433
}
426
434
427
- group -> minor = minor ;
428
- group -> dev = dev ;
429
-
430
435
list_add (& group -> vfio_next , & vfio .group_list );
431
436
432
437
mutex_unlock (& vfio .group_lock );
433
438
return group ;
439
+
440
+ err_unlock :
441
+ mutex_unlock (& vfio .group_lock );
442
+ iommu_group_unregister_notifier (group -> iommu_group , & group -> nb );
443
+ err_put :
444
+ put_device (& group -> dev );
445
+ return ret ;
434
446
}
435
447
436
448
static void vfio_group_put (struct vfio_group * group )
@@ -448,33 +460,19 @@ static void vfio_group_put(struct vfio_group *group)
448
460
WARN_ON (atomic_read (& group -> container_users ));
449
461
WARN_ON (group -> notifier .head );
450
462
451
- device_destroy (vfio .class , MKDEV (MAJOR (vfio .group_devt ), group -> minor ));
452
463
list_del (& group -> vfio_next );
453
- vfio_free_group_minor (group -> minor );
454
- vfio_group_unlock_and_free (group );
464
+ cdev_device_del (& group -> cdev , & group -> dev );
465
+ mutex_unlock (& vfio .group_lock );
466
+
467
+ iommu_group_unregister_notifier (group -> iommu_group , & group -> nb );
468
+ put_device (& group -> dev );
455
469
}
456
470
457
471
static void vfio_group_get (struct vfio_group * group )
458
472
{
459
473
refcount_inc (& group -> users );
460
474
}
461
475
462
- static struct vfio_group * vfio_group_get_from_minor (int minor )
463
- {
464
- struct vfio_group * group ;
465
-
466
- mutex_lock (& vfio .group_lock );
467
- group = idr_find (& vfio .group_idr , minor );
468
- if (!group ) {
469
- mutex_unlock (& vfio .group_lock );
470
- return NULL ;
471
- }
472
- vfio_group_get (group );
473
- mutex_unlock (& vfio .group_lock );
474
-
475
- return group ;
476
- }
477
-
478
476
static struct vfio_group * vfio_group_get_from_dev (struct device * dev )
479
477
{
480
478
struct iommu_group * iommu_group ;
@@ -1479,11 +1477,12 @@ static long vfio_group_fops_unl_ioctl(struct file *filep,
1479
1477
1480
1478
static int vfio_group_fops_open (struct inode * inode , struct file * filep )
1481
1479
{
1482
- struct vfio_group * group ;
1480
+ struct vfio_group * group =
1481
+ container_of (inode -> i_cdev , struct vfio_group , cdev );
1483
1482
int opened ;
1484
1483
1485
- group = vfio_group_get_from_minor ( iminor ( inode ));
1486
- if (!group )
1484
+ /* users can be zero if this races with vfio_group_put() */
1485
+ if (!refcount_inc_not_zero ( & group -> users ) )
1487
1486
return - ENODEV ;
1488
1487
1489
1488
if (group -> type == VFIO_NO_IOMMU && !capable (CAP_SYS_RAWIO )) {
@@ -2293,7 +2292,7 @@ static int __init vfio_init(void)
2293
2292
{
2294
2293
int ret ;
2295
2294
2296
- idr_init (& vfio .group_idr );
2295
+ ida_init (& vfio .group_ida );
2297
2296
mutex_init (& vfio .group_lock );
2298
2297
mutex_init (& vfio .iommu_drivers_lock );
2299
2298
INIT_LIST_HEAD (& vfio .group_list );
@@ -2318,20 +2317,13 @@ static int __init vfio_init(void)
2318
2317
if (ret )
2319
2318
goto err_alloc_chrdev ;
2320
2319
2321
- cdev_init (& vfio .group_cdev , & vfio_group_fops );
2322
- ret = cdev_add (& vfio .group_cdev , vfio .group_devt , MINORMASK + 1 );
2323
- if (ret )
2324
- goto err_cdev_add ;
2325
-
2326
2320
pr_info (DRIVER_DESC " version: " DRIVER_VERSION "\n" );
2327
2321
2328
2322
#ifdef CONFIG_VFIO_NOIOMMU
2329
2323
vfio_register_iommu_driver (& vfio_noiommu_ops );
2330
2324
#endif
2331
2325
return 0 ;
2332
2326
2333
- err_cdev_add :
2334
- unregister_chrdev_region (vfio .group_devt , MINORMASK + 1 );
2335
2327
err_alloc_chrdev :
2336
2328
class_destroy (vfio .class );
2337
2329
vfio .class = NULL ;
@@ -2347,8 +2339,7 @@ static void __exit vfio_cleanup(void)
2347
2339
#ifdef CONFIG_VFIO_NOIOMMU
2348
2340
vfio_unregister_iommu_driver (& vfio_noiommu_ops );
2349
2341
#endif
2350
- idr_destroy (& vfio .group_idr );
2351
- cdev_del (& vfio .group_cdev );
2342
+ ida_destroy (& vfio .group_ida );
2352
2343
unregister_chrdev_region (vfio .group_devt , MINORMASK + 1 );
2353
2344
class_destroy (vfio .class );
2354
2345
vfio .class = NULL ;
0 commit comments