Skip to content

Commit 87cbdc3

Browse files
mgurtovoymstsirkin
authored andcommitted
virtio_fs: add sysfs entries for queue information
Introduce sysfs entries to provide visibility to the multiple queues used by the Virtio FS device. This enhancement allows users to query information about these queues. Specifically, add two sysfs entries: 1. Queue name: Provides the name of each queue (e.g. hiprio/requests.8). 2. CPU list: Shows the list of CPUs that can process requests for each queue. The CPU list feature is inspired by similar functionality in the block MQ layer, which provides analogous sysfs entries for block devices. These new sysfs entries will improve observability and aid in debugging and performance tuning of Virtio FS devices. Reviewed-by: Idan Zach <[email protected]> Reviewed-by: Shai Malin <[email protected]> Signed-off-by: Max Gurtovoy <[email protected]> Message-Id: <[email protected]> Signed-off-by: Michael S. Tsirkin <[email protected]>
1 parent 4045b64 commit 87cbdc3

File tree

1 file changed

+139
-8
lines changed

1 file changed

+139
-8
lines changed

fs/fuse/virtio_fs.c

Lines changed: 139 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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 */
6364
struct 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 */
204274
static 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*/
284398
static 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

Comments
 (0)