@@ -1064,12 +1064,9 @@ static bool vfio_assert_device_open(struct vfio_device *device)
10641064 return !WARN_ON_ONCE (!READ_ONCE (device -> open_count ));
10651065}
10661066
1067- static int vfio_group_get_device_fd (struct vfio_group * group , char * buf )
1067+ static int vfio_device_assign_container (struct vfio_device * device )
10681068{
1069- struct vfio_device * device ;
1070- struct file * filep ;
1071- int fdno ;
1072- int ret = 0 ;
1069+ struct vfio_group * group = device -> group ;
10731070
10741071 if (0 == atomic_read (& group -> container_users ) ||
10751072 !group -> container -> iommu_driver )
@@ -1078,13 +1075,22 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf)
10781075 if (group -> type == VFIO_NO_IOMMU && !capable (CAP_SYS_RAWIO ))
10791076 return - EPERM ;
10801077
1081- device = vfio_device_get_from_name (group , buf );
1082- if (IS_ERR (device ))
1083- return PTR_ERR (device );
1078+ atomic_inc (& group -> container_users );
1079+ return 0 ;
1080+ }
1081+
1082+ static struct file * vfio_device_open (struct vfio_device * device )
1083+ {
1084+ struct file * filep ;
1085+ int ret ;
1086+
1087+ ret = vfio_device_assign_container (device );
1088+ if (ret )
1089+ return ERR_PTR (ret );
10841090
10851091 if (!try_module_get (device -> dev -> driver -> owner )) {
10861092 ret = - ENODEV ;
1087- goto err_device_put ;
1093+ goto err_unassign_container ;
10881094 }
10891095
10901096 mutex_lock (& device -> dev_set -> lock );
@@ -1100,15 +1106,11 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf)
11001106 * We can't use anon_inode_getfd() because we need to modify
11011107 * the f_mode flags directly to allow more than just ioctls
11021108 */
1103- fdno = ret = get_unused_fd_flags (O_CLOEXEC );
1104- if (ret < 0 )
1105- goto err_close_device ;
1106-
11071109 filep = anon_inode_getfile ("[vfio-device]" , & vfio_device_fops ,
11081110 device , O_RDWR );
11091111 if (IS_ERR (filep )) {
11101112 ret = PTR_ERR (filep );
1111- goto err_fd ;
1113+ goto err_close_device ;
11121114 }
11131115
11141116 /*
@@ -1118,17 +1120,15 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf)
11181120 */
11191121 filep -> f_mode |= (FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE );
11201122
1121- atomic_inc (& group -> container_users );
1122-
1123- fd_install (fdno , filep );
1124-
1125- if (group -> type == VFIO_NO_IOMMU )
1123+ if (device -> group -> type == VFIO_NO_IOMMU )
11261124 dev_warn (device -> dev , "vfio-noiommu device opened by user "
11271125 "(%s:%d)\n" , current -> comm , task_pid_nr (current ));
1128- return fdno ;
1126+ /*
1127+ * On success the ref of device is moved to the file and
1128+ * put in vfio_device_fops_release()
1129+ */
1130+ return filep ;
11291131
1130- err_fd :
1131- put_unused_fd (fdno );
11321132err_close_device :
11331133 mutex_lock (& device -> dev_set -> lock );
11341134 if (device -> open_count == 1 && device -> ops -> close_device )
@@ -1137,7 +1137,40 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf)
11371137 device -> open_count -- ;
11381138 mutex_unlock (& device -> dev_set -> lock );
11391139 module_put (device -> dev -> driver -> owner );
1140- err_device_put :
1140+ err_unassign_container :
1141+ vfio_group_try_dissolve_container (device -> group );
1142+ return ERR_PTR (ret );
1143+ }
1144+
1145+ static int vfio_group_get_device_fd (struct vfio_group * group , char * buf )
1146+ {
1147+ struct vfio_device * device ;
1148+ struct file * filep ;
1149+ int fdno ;
1150+ int ret ;
1151+
1152+ device = vfio_device_get_from_name (group , buf );
1153+ if (IS_ERR (device ))
1154+ return PTR_ERR (device );
1155+
1156+ fdno = get_unused_fd_flags (O_CLOEXEC );
1157+ if (fdno < 0 ) {
1158+ ret = fdno ;
1159+ goto err_put_device ;
1160+ }
1161+
1162+ filep = vfio_device_open (device );
1163+ if (IS_ERR (filep )) {
1164+ ret = PTR_ERR (filep );
1165+ goto err_put_fdno ;
1166+ }
1167+
1168+ fd_install (fdno , filep );
1169+ return fdno ;
1170+
1171+ err_put_fdno :
1172+ put_unused_fd (fdno );
1173+ err_put_device :
11411174 vfio_device_put (device );
11421175 return ret ;
11431176}
0 commit comments