@@ -73,7 +73,7 @@ struct vfio_group {
73
73
struct mutex device_lock ;
74
74
struct list_head vfio_next ;
75
75
struct list_head container_next ;
76
- atomic_t opened ;
76
+ bool opened ;
77
77
enum vfio_group_type type ;
78
78
unsigned int dev_counter ;
79
79
struct rw_semaphore group_rwsem ;
@@ -1213,38 +1213,44 @@ static int vfio_group_fops_open(struct inode *inode, struct file *filep)
1213
1213
{
1214
1214
struct vfio_group * group =
1215
1215
container_of (inode -> i_cdev , struct vfio_group , cdev );
1216
- int opened ;
1216
+ int ret ;
1217
1217
1218
- /* users can be zero if this races with vfio_group_put() */
1219
- if (!refcount_inc_not_zero (& group -> users ))
1220
- return - ENODEV ;
1218
+ down_write (& group -> group_rwsem );
1221
1219
1222
- if (group -> type == VFIO_NO_IOMMU && !capable (CAP_SYS_RAWIO )) {
1223
- vfio_group_put (group );
1224
- return - EPERM ;
1220
+ /* users can be zero if this races with vfio_group_put() */
1221
+ if (!refcount_inc_not_zero (& group -> users )) {
1222
+ ret = - ENODEV ;
1223
+ goto err_unlock ;
1225
1224
}
1226
1225
1227
- /* Do we need multiple instances of the group open? Seems not. */
1228
- opened = atomic_cmpxchg (& group -> opened , 0 , 1 );
1229
- if (opened ) {
1230
- vfio_group_put (group );
1231
- return - EBUSY ;
1226
+ if (group -> type == VFIO_NO_IOMMU && !capable (CAP_SYS_RAWIO )) {
1227
+ ret = - EPERM ;
1228
+ goto err_put ;
1232
1229
}
1233
1230
1234
- /* Is something still in use from a previous open? */
1235
- if (group -> container ) {
1236
- atomic_dec (& group -> opened );
1237
- vfio_group_put (group );
1238
- return - EBUSY ;
1231
+ /*
1232
+ * Do we need multiple instances of the group open? Seems not.
1233
+ * Is something still in use from a previous open?
1234
+ */
1235
+ if (group -> opened || group -> container ) {
1236
+ ret = - EBUSY ;
1237
+ goto err_put ;
1239
1238
}
1239
+ group -> opened = true;
1240
1240
1241
1241
/* Warn if previous user didn't cleanup and re-init to drop them */
1242
1242
if (WARN_ON (group -> notifier .head ))
1243
1243
BLOCKING_INIT_NOTIFIER_HEAD (& group -> notifier );
1244
1244
1245
1245
filep -> private_data = group ;
1246
1246
1247
+ up_write (& group -> group_rwsem );
1247
1248
return 0 ;
1249
+ err_put :
1250
+ vfio_group_put (group );
1251
+ err_unlock :
1252
+ up_write (& group -> group_rwsem );
1253
+ return ret ;
1248
1254
}
1249
1255
1250
1256
static int vfio_group_fops_release (struct inode * inode , struct file * filep )
@@ -1255,7 +1261,9 @@ static int vfio_group_fops_release(struct inode *inode, struct file *filep)
1255
1261
1256
1262
vfio_group_try_dissolve_container (group );
1257
1263
1258
- atomic_dec (& group -> opened );
1264
+ down_write (& group -> group_rwsem );
1265
+ group -> opened = false;
1266
+ up_write (& group -> group_rwsem );
1259
1267
1260
1268
vfio_group_put (group );
1261
1269
0 commit comments