@@ -1064,12 +1064,9 @@ static bool vfio_assert_device_open(struct vfio_device *device)
1064
1064
return !WARN_ON_ONCE (!READ_ONCE (device -> open_count ));
1065
1065
}
1066
1066
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 )
1068
1068
{
1069
- struct vfio_device * device ;
1070
- struct file * filep ;
1071
- int fdno ;
1072
- int ret = 0 ;
1069
+ struct vfio_group * group = device -> group ;
1073
1070
1074
1071
if (0 == atomic_read (& group -> container_users ) ||
1075
1072
!group -> container -> iommu_driver )
@@ -1078,13 +1075,22 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf)
1078
1075
if (group -> type == VFIO_NO_IOMMU && !capable (CAP_SYS_RAWIO ))
1079
1076
return - EPERM ;
1080
1077
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 );
1084
1090
1085
1091
if (!try_module_get (device -> dev -> driver -> owner )) {
1086
1092
ret = - ENODEV ;
1087
- goto err_device_put ;
1093
+ goto err_unassign_container ;
1088
1094
}
1089
1095
1090
1096
mutex_lock (& device -> dev_set -> lock );
@@ -1100,15 +1106,11 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf)
1100
1106
* We can't use anon_inode_getfd() because we need to modify
1101
1107
* the f_mode flags directly to allow more than just ioctls
1102
1108
*/
1103
- fdno = ret = get_unused_fd_flags (O_CLOEXEC );
1104
- if (ret < 0 )
1105
- goto err_close_device ;
1106
-
1107
1109
filep = anon_inode_getfile ("[vfio-device]" , & vfio_device_fops ,
1108
1110
device , O_RDWR );
1109
1111
if (IS_ERR (filep )) {
1110
1112
ret = PTR_ERR (filep );
1111
- goto err_fd ;
1113
+ goto err_close_device ;
1112
1114
}
1113
1115
1114
1116
/*
@@ -1118,17 +1120,15 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf)
1118
1120
*/
1119
1121
filep -> f_mode |= (FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE );
1120
1122
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 )
1126
1124
dev_warn (device -> dev , "vfio-noiommu device opened by user "
1127
1125
"(%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 ;
1129
1131
1130
- err_fd :
1131
- put_unused_fd (fdno );
1132
1132
err_close_device :
1133
1133
mutex_lock (& device -> dev_set -> lock );
1134
1134
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)
1137
1137
device -> open_count -- ;
1138
1138
mutex_unlock (& device -> dev_set -> lock );
1139
1139
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 :
1141
1174
vfio_device_put (device );
1142
1175
return ret ;
1143
1176
}
0 commit comments