@@ -56,12 +56,14 @@ struct virtio_fs_vq {
5656 bool connected ;
5757 long in_flight ;
5858 struct completion in_flight_zero ; /* No inflight requests */
59+ struct kobject * kobj ;
5960 char name [VQ_NAME_LEN ];
6061} ____cacheline_aligned_in_smp ;
6162
6263/* A virtio-fs device instance */
6364struct virtio_fs {
6465 struct kobject kobj ;
66+ struct kobject * mqs_kobj ;
6567 struct list_head list ; /* on virtio_fs_instances */
6668 char * tag ;
6769 struct virtio_fs_vq * vqs ;
@@ -200,6 +202,74 @@ static const struct kobj_type virtio_fs_ktype = {
200202 .default_groups = virtio_fs_groups ,
201203};
202204
205+ static struct virtio_fs_vq * virtio_fs_kobj_to_vq (struct virtio_fs * fs ,
206+ struct kobject * kobj )
207+ {
208+ int i ;
209+
210+ for (i = 0 ; i < fs -> nvqs ; i ++ ) {
211+ if (kobj == fs -> vqs [i ].kobj )
212+ return & fs -> vqs [i ];
213+ }
214+ return NULL ;
215+ }
216+
217+ static ssize_t name_show (struct kobject * kobj ,
218+ struct kobj_attribute * attr , char * buf )
219+ {
220+ struct virtio_fs * fs = container_of (kobj -> parent -> parent , struct virtio_fs , kobj );
221+ struct virtio_fs_vq * fsvq = virtio_fs_kobj_to_vq (fs , kobj );
222+
223+ if (!fsvq )
224+ return - EINVAL ;
225+ return sysfs_emit (buf , "%s\n" , fsvq -> name );
226+ }
227+
228+ static struct kobj_attribute virtio_fs_vq_name_attr = __ATTR_RO (name );
229+
230+ static ssize_t cpu_list_show (struct kobject * kobj ,
231+ struct kobj_attribute * attr , char * buf )
232+ {
233+ struct virtio_fs * fs = container_of (kobj -> parent -> parent , struct virtio_fs , kobj );
234+ struct virtio_fs_vq * fsvq = virtio_fs_kobj_to_vq (fs , kobj );
235+ unsigned int cpu , qid ;
236+ const size_t size = PAGE_SIZE - 1 ;
237+ bool first = true;
238+ int ret = 0 , pos = 0 ;
239+
240+ if (!fsvq )
241+ return - EINVAL ;
242+
243+ qid = fsvq -> vq -> index ;
244+ for (cpu = 0 ; cpu < nr_cpu_ids ; cpu ++ ) {
245+ if (qid < VQ_REQUEST || (fs -> mq_map [cpu ] == qid - VQ_REQUEST )) {
246+ if (first )
247+ ret = snprintf (buf + pos , size - pos , "%u" , cpu );
248+ else
249+ ret = snprintf (buf + pos , size - pos , ", %u" , cpu );
250+
251+ if (ret >= size - pos )
252+ break ;
253+ first = false;
254+ pos += ret ;
255+ }
256+ }
257+ ret = snprintf (buf + pos , size + 1 - pos , "\n" );
258+ return pos + ret ;
259+ }
260+
261+ static struct kobj_attribute virtio_fs_vq_cpu_list_attr = __ATTR_RO (cpu_list );
262+
263+ static struct attribute * virtio_fs_vq_attrs [] = {
264+ & virtio_fs_vq_name_attr .attr ,
265+ & virtio_fs_vq_cpu_list_attr .attr ,
266+ NULL
267+ };
268+
269+ static struct attribute_group virtio_fs_vq_attr_group = {
270+ .attrs = virtio_fs_vq_attrs ,
271+ };
272+
203273/* Make sure virtiofs_mutex is held */
204274static void virtio_fs_put_locked (struct virtio_fs * fs )
205275{
@@ -280,6 +350,50 @@ static void virtio_fs_start_all_queues(struct virtio_fs *fs)
280350 }
281351}
282352
353+ static void virtio_fs_delete_queues_sysfs (struct virtio_fs * fs )
354+ {
355+ struct virtio_fs_vq * fsvq ;
356+ int i ;
357+
358+ for (i = 0 ; i < fs -> nvqs ; i ++ ) {
359+ fsvq = & fs -> vqs [i ];
360+ kobject_put (fsvq -> kobj );
361+ }
362+ }
363+
364+ static int virtio_fs_add_queues_sysfs (struct virtio_fs * fs )
365+ {
366+ struct virtio_fs_vq * fsvq ;
367+ char buff [12 ];
368+ int i , j , ret ;
369+
370+ for (i = 0 ; i < fs -> nvqs ; i ++ ) {
371+ fsvq = & fs -> vqs [i ];
372+
373+ sprintf (buff , "%d" , i );
374+ fsvq -> kobj = kobject_create_and_add (buff , fs -> mqs_kobj );
375+ if (!fs -> mqs_kobj ) {
376+ ret = - ENOMEM ;
377+ goto out_del ;
378+ }
379+
380+ ret = sysfs_create_group (fsvq -> kobj , & virtio_fs_vq_attr_group );
381+ if (ret ) {
382+ kobject_put (fsvq -> kobj );
383+ goto out_del ;
384+ }
385+ }
386+
387+ return 0 ;
388+
389+ out_del :
390+ for (j = 0 ; j < i ; j ++ ) {
391+ fsvq = & fs -> vqs [j ];
392+ kobject_put (fsvq -> kobj );
393+ }
394+ return ret ;
395+ }
396+
283397/* Add a new instance to the list or return -EEXIST if tag name exists*/
284398static int virtio_fs_add_instance (struct virtio_device * vdev ,
285399 struct virtio_fs * fs )
@@ -303,17 +417,22 @@ static int virtio_fs_add_instance(struct virtio_device *vdev,
303417 */
304418 fs -> kobj .kset = virtio_fs_kset ;
305419 ret = kobject_add (& fs -> kobj , NULL , "%d" , vdev -> index );
306- if (ret < 0 ) {
307- mutex_unlock (& virtio_fs_mutex );
308- return ret ;
420+ if (ret < 0 )
421+ goto out_unlock ;
422+
423+ fs -> mqs_kobj = kobject_create_and_add ("mqs" , & fs -> kobj );
424+ if (!fs -> mqs_kobj ) {
425+ ret = - ENOMEM ;
426+ goto out_del ;
309427 }
310428
311429 ret = sysfs_create_link (& fs -> kobj , & vdev -> dev .kobj , "device" );
312- if (ret < 0 ) {
313- kobject_del (& fs -> kobj );
314- mutex_unlock (& virtio_fs_mutex );
315- return ret ;
316- }
430+ if (ret < 0 )
431+ goto out_put ;
432+
433+ ret = virtio_fs_add_queues_sysfs (fs );
434+ if (ret )
435+ goto out_remove ;
317436
318437 list_add_tail (& fs -> list , & virtio_fs_instances );
319438
@@ -322,6 +441,16 @@ static int virtio_fs_add_instance(struct virtio_device *vdev,
322441 kobject_uevent (& fs -> kobj , KOBJ_ADD );
323442
324443 return 0 ;
444+
445+ out_remove :
446+ sysfs_remove_link (& fs -> kobj , "device" );
447+ out_put :
448+ kobject_put (fs -> mqs_kobj );
449+ out_del :
450+ kobject_del (& fs -> kobj );
451+ out_unlock :
452+ mutex_unlock (& virtio_fs_mutex );
453+ return ret ;
325454}
326455
327456/* Return the virtio_fs with a given tag, or NULL */
@@ -1050,7 +1179,9 @@ static void virtio_fs_remove(struct virtio_device *vdev)
10501179 mutex_lock (& virtio_fs_mutex );
10511180 /* This device is going away. No one should get new reference */
10521181 list_del_init (& fs -> list );
1182+ virtio_fs_delete_queues_sysfs (fs );
10531183 sysfs_remove_link (& fs -> kobj , "device" );
1184+ kobject_put (fs -> mqs_kobj );
10541185 kobject_del (& fs -> kobj );
10551186 virtio_fs_stop_all_queues (fs );
10561187 virtio_fs_drain_all_queues_locked (fs );
0 commit comments