Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

virtiofs: export filesystem tags through sysfs

The virtiofs filesystem is mounted using a "tag" which is exported by
the virtiofs device:

# mount -t virtiofs <tag> /mnt

The virtiofs driver knows about all the available tags but these are
currently not exported to user space.

People have asked for these tags to be exported to user space. Most
recently Lennart Poettering has asked for it as he wants to scan the
tags and mount virtiofs automatically in certain cases.

https://gitlab.com/virtio-fs/virtiofsd/-/issues/128

This patch exports tags at /sys/fs/virtiofs/<N>/tag where N is the id of
the virtiofs device. The filesystem tag can be obtained by reading this
"tag" file.

There is also a symlink at /sys/fs/virtiofs/<N>/device that points to
the virtiofs device that exports this tag.

This patch converts the existing struct virtio_fs into a full kobject.
It already had a refcount so it's an easy change. The virtio_fs objects
can then be exposed in a kset at /sys/fs/virtiofs/. Note that virtio_fs
objects may live slightly longer than we wish for them to be exposed to
userspace, so kobject_del() is called explicitly when the underlying
virtio_device is removed. The virtio_fs object is freed when all
references are dropped (e.g. active mounts) but disappears as soon as
the virtiofs device is gone.

Originally-by: Vivek Goyal <vgoyal@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Vivek Goyal <vgoyal@redhat.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>

authored by

Stefan Hajnoczi and committed by
Miklos Szeredi
a8f62f50 40488cc1

+101 -22
+11
Documentation/ABI/testing/sysfs-fs-virtiofs
··· 1 + What: /sys/fs/virtiofs/<n>/tag 2 + Date: Feb 2024 3 + Contact: virtio-fs@lists.linux.dev 4 + Description: 5 + [RO] The mount "tag" that can be used to mount this filesystem. 6 + 7 + What: /sys/fs/virtiofs/<n>/device 8 + Date: Feb 2024 9 + Contact: virtio-fs@lists.linux.dev 10 + Description: 11 + Symlink to the virtio device that exports this filesystem.
+90 -22
fs/fuse/virtio_fs.c
··· 31 31 static DEFINE_MUTEX(virtio_fs_mutex); 32 32 static LIST_HEAD(virtio_fs_instances); 33 33 34 + /* The /sys/fs/virtio_fs/ kset */ 35 + static struct kset *virtio_fs_kset; 36 + 34 37 enum { 35 38 VQ_HIPRIO, 36 39 VQ_REQUEST ··· 58 55 59 56 /* A virtio-fs device instance */ 60 57 struct virtio_fs { 61 - struct kref refcount; 58 + struct kobject kobj; 62 59 struct list_head list; /* on virtio_fs_instances */ 63 60 char *tag; 64 61 struct virtio_fs_vq *vqs; ··· 164 161 complete(&fsvq->in_flight_zero); 165 162 } 166 163 167 - static void release_virtio_fs_obj(struct kref *ref) 164 + static ssize_t tag_show(struct kobject *kobj, 165 + struct kobj_attribute *attr, char *buf) 168 166 { 169 - struct virtio_fs *vfs = container_of(ref, struct virtio_fs, refcount); 167 + struct virtio_fs *fs = container_of(kobj, struct virtio_fs, kobj); 168 + 169 + return sysfs_emit(buf, fs->tag); 170 + } 171 + 172 + static struct kobj_attribute virtio_fs_tag_attr = __ATTR_RO(tag); 173 + 174 + static struct attribute *virtio_fs_attrs[] = { 175 + &virtio_fs_tag_attr.attr, 176 + NULL 177 + }; 178 + ATTRIBUTE_GROUPS(virtio_fs); 179 + 180 + static void virtio_fs_ktype_release(struct kobject *kobj) 181 + { 182 + struct virtio_fs *vfs = container_of(kobj, struct virtio_fs, kobj); 170 183 171 184 kfree(vfs->vqs); 172 185 kfree(vfs); 173 186 } 174 187 188 + static const struct kobj_type virtio_fs_ktype = { 189 + .release = virtio_fs_ktype_release, 190 + .sysfs_ops = &kobj_sysfs_ops, 191 + .default_groups = virtio_fs_groups, 192 + }; 193 + 175 194 /* Make sure virtiofs_mutex is held */ 176 195 static void virtio_fs_put(struct virtio_fs *fs) 177 196 { 178 - kref_put(&fs->refcount, release_virtio_fs_obj); 197 + kobject_put(&fs->kobj); 179 198 } 180 199 181 200 static void virtio_fs_fiq_release(struct fuse_iqueue *fiq) ··· 268 243 } 269 244 270 245 /* Add a new instance to the list or return -EEXIST if tag name exists*/ 271 - static int virtio_fs_add_instance(struct virtio_fs *fs) 246 + static int virtio_fs_add_instance(struct virtio_device *vdev, 247 + struct virtio_fs *fs) 272 248 { 273 249 struct virtio_fs *fs2; 274 - bool duplicate = false; 250 + int ret; 275 251 276 252 mutex_lock(&virtio_fs_mutex); 277 253 278 254 list_for_each_entry(fs2, &virtio_fs_instances, list) { 279 - if (strcmp(fs->tag, fs2->tag) == 0) 280 - duplicate = true; 255 + if (strcmp(fs->tag, fs2->tag) == 0) { 256 + mutex_unlock(&virtio_fs_mutex); 257 + return -EEXIST; 258 + } 281 259 } 282 260 283 - if (!duplicate) 284 - list_add_tail(&fs->list, &virtio_fs_instances); 261 + /* Use the virtio_device's index as a unique identifier, there is no 262 + * need to allocate our own identifiers because the virtio_fs instance 263 + * is only visible to userspace as long as the underlying virtio_device 264 + * exists. 265 + */ 266 + fs->kobj.kset = virtio_fs_kset; 267 + ret = kobject_add(&fs->kobj, NULL, "%d", vdev->index); 268 + if (ret < 0) { 269 + mutex_unlock(&virtio_fs_mutex); 270 + return ret; 271 + } 272 + 273 + ret = sysfs_create_link(&fs->kobj, &vdev->dev.kobj, "device"); 274 + if (ret < 0) { 275 + kobject_del(&fs->kobj); 276 + mutex_unlock(&virtio_fs_mutex); 277 + return ret; 278 + } 279 + 280 + list_add_tail(&fs->list, &virtio_fs_instances); 285 281 286 282 mutex_unlock(&virtio_fs_mutex); 287 283 288 - if (duplicate) 289 - return -EEXIST; 290 284 return 0; 291 285 } 292 286 ··· 318 274 319 275 list_for_each_entry(fs, &virtio_fs_instances, list) { 320 276 if (strcmp(fs->tag, tag) == 0) { 321 - kref_get(&fs->refcount); 277 + kobject_get(&fs->kobj); 322 278 goto found; 323 279 } 324 280 } ··· 919 875 fs = kzalloc(sizeof(*fs), GFP_KERNEL); 920 876 if (!fs) 921 877 return -ENOMEM; 922 - kref_init(&fs->refcount); 878 + kobject_init(&fs->kobj, &virtio_fs_ktype); 923 879 vdev->priv = fs; 924 880 925 881 ret = virtio_fs_read_tag(vdev, fs); ··· 941 897 */ 942 898 virtio_device_ready(vdev); 943 899 944 - ret = virtio_fs_add_instance(fs); 900 + ret = virtio_fs_add_instance(vdev, fs); 945 901 if (ret < 0) 946 902 goto out_vqs; 947 903 ··· 950 906 out_vqs: 951 907 virtio_reset_device(vdev); 952 908 virtio_fs_cleanup_vqs(vdev); 953 - kfree(fs->vqs); 954 909 955 910 out: 956 911 vdev->priv = NULL; 957 - kfree(fs); 912 + kobject_put(&fs->kobj); 958 913 return ret; 959 914 } 960 915 ··· 977 934 mutex_lock(&virtio_fs_mutex); 978 935 /* This device is going away. No one should get new reference */ 979 936 list_del_init(&fs->list); 937 + sysfs_remove_link(&fs->kobj, "device"); 938 + kobject_del(&fs->kobj); 980 939 virtio_fs_stop_all_queues(fs); 981 940 virtio_fs_drain_all_queues_locked(fs); 982 941 virtio_reset_device(vdev); ··· 1565 1520 .kill_sb = virtio_kill_sb, 1566 1521 }; 1567 1522 1523 + static int __init virtio_fs_sysfs_init(void) 1524 + { 1525 + virtio_fs_kset = kset_create_and_add("virtiofs", NULL, fs_kobj); 1526 + if (!virtio_fs_kset) 1527 + return -ENOMEM; 1528 + return 0; 1529 + } 1530 + 1531 + static void __exit virtio_fs_sysfs_exit(void) 1532 + { 1533 + kset_unregister(virtio_fs_kset); 1534 + virtio_fs_kset = NULL; 1535 + } 1536 + 1568 1537 static int __init virtio_fs_init(void) 1569 1538 { 1570 1539 int ret; 1571 1540 1572 - ret = register_virtio_driver(&virtio_fs_driver); 1541 + ret = virtio_fs_sysfs_init(); 1573 1542 if (ret < 0) 1574 1543 return ret; 1575 1544 1545 + ret = register_virtio_driver(&virtio_fs_driver); 1546 + if (ret < 0) 1547 + goto sysfs_exit; 1548 + 1576 1549 ret = register_filesystem(&virtio_fs_type); 1577 - if (ret < 0) { 1578 - unregister_virtio_driver(&virtio_fs_driver); 1579 - return ret; 1580 - } 1550 + if (ret < 0) 1551 + goto unregister_virtio_driver; 1581 1552 1582 1553 return 0; 1554 + 1555 + unregister_virtio_driver: 1556 + unregister_virtio_driver(&virtio_fs_driver); 1557 + sysfs_exit: 1558 + virtio_fs_sysfs_exit(); 1559 + return ret; 1583 1560 } 1584 1561 module_init(virtio_fs_init); 1585 1562 ··· 1609 1542 { 1610 1543 unregister_filesystem(&virtio_fs_type); 1611 1544 unregister_virtio_driver(&virtio_fs_driver); 1545 + virtio_fs_sysfs_exit(); 1612 1546 } 1613 1547 module_exit(virtio_fs_exit); 1614 1548