流程如下:
virtblk_probe(struct virtio_device *vdev)
------>set_disk_ro(vblk->disk, 1)
------->set_disk_ro_uevent(disk, flag)
----->dev_uevent()
------->part_uevent()
在文件drivers/block/virtio_blk.c中:
620 static int virtblk_probe(struct virtio_device *vdev)
621 {
622 struct virtio_blk *vblk;
623 struct request_queue *q;
624 int err, index;
625
626 u64 cap;
627 u32 v, blk_size, sg_elems, opt_io_size;
628 u16 min_io_size;
629 u8 physical_block_exp, alignment_offset;
630
631 if (!vdev->config->get) {
632 dev_err(&vdev->dev, "%s failure: config access disabled\n",
633 __func__);
634 return -EINVAL;
635 }
..........
717 /* configure queue flush support */
718 virtblk_update_cache_mode(vdev);
719
720 /* If disk is read-only in the host, the guest should obey */
721 if (virtio_has_feature(vdev, VIRTIO_BLK_F_RO))
722 set_disk_ro(vblk->disk, 1);
..............
在722行调用set_disk_ro函数 set_disk_ro(vblk->disk, 1)。
文件block/genhd.c中:
1474 void set_disk_ro(struct gendisk *disk, int flag)
1475 {
1476 struct disk_part_iter piter;
1477 struct hd_struct *part;
1478
1479 if (disk->part0.policy != flag) {
1480 set_disk_ro_uevent(disk, flag);
1481 disk->part0.policy = flag;
1482 }
1483
1484 disk_part_iter_init(&piter, disk, DISK_PITER_INCL_EMPTY);
1485 while ((part = disk_part_iter_next(&piter)))
1486 part->policy = flag;
1487 disk_part_iter_exit(&piter);
1488 }
在1480行调用函数set_disk_ro_uevent(disk, flag)。
在文件block/genhd.c 中。
1457 static void set_disk_ro_uevent(struct gendisk *gd, int ro)
1458 {
1459 char event[] = "DISK_RO=1";
1460 char *envp[] = { event, NULL };
1461
1462 if (!ro)
1463 event[8] = '0';
1464 kobject_uevent_env(&disk_to_dev(gd)->kobj, KOBJ_CHANGE, envp);
1465 }
在1464行调用函数kobject_uevent_env(&disk_to_dev(gd)->kobj, KOBJ_CHANGE, envp)。
327 int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
328 char *envp_ext[])
329 {
330 struct kobj_uevent_env *env;
331 const char *action_string = kobject_actions[action];
............
409 /* default keys */
410 retval = add_uevent_var(env, "ACTION=%s", action_string);
411 if (retval)
412 goto exit;
413 retval = add_uevent_var(env, "DEVPATH=%s", devpath);
414 if (retval)
415 goto exit;
416 retval = add_uevent_var(env, "SUBSYSTEM=%s", subsystem);
417 if (retval)
418 goto exit;
则env->envp的内容如下:
[ 1.332974] tom F=kobject_uevent_env L=452 env1->envp[0]=ACTION=add
[ 1.333570] tom F=kobject_uevent_env L=452 env1->envp[1]=DEVPATH=/devices/pci0000:00/0000:00:03.0/virtio0/block/vda/vda2
[ 1.334239] tom F=kobject_uevent_env L=452 env1->envp[2]=SUBSYSTEM=block
420 /* keys passed in from the caller */
421 if (envp_ext) {
422 for (i = 0; envp_ext[i]; i++) {
423 retval = add_uevent_var(env, "%s", envp_ext[i]);
424 if (retval)
425 goto exit;
426 }
427 }
则env->envp[3]的内容如下:
[ 1.346066] tom F=kobject_uevent_env L=462 env1->envp[3]=SYNTH_UUID=0
429 /* let the kset specific function add its stuff */
430 if (uevent_ops && uevent_ops->uevent) {
431 retval = uevent_ops->uevent(kset, kobj, env);
432 if (retval) {
433 pr_debug("kobject: '%s' (%p): %s: uevent() returned "
434 "%d\n", kobject_name(kobj), kobj,
435 __func__, retval);
436 goto exit;
437 }
438 }
在431行调用 uevent_ops->uevent(kset, kobj, env);
在drivers/base/core.c中dev_uevent函数:
875 static int dev_uevent(struct kset *kset, struct kobject *kobj,
876 struct kobj_uevent_env *env)
877 {
878 struct device *dev = kobj_to_dev(kobj);
879 int retval = 0;
880
881 /* add device node properties if present */
882 if (MAJOR(dev->devt)) {
883 const char *tmp;
884 const char *name;
885 umode_t mode = 0;
886 kuid_t uid = GLOBAL_ROOT_UID;
887 kgid_t gid = GLOBAL_ROOT_GID;
888
889 add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt));
890 add_uevent_var(env, "MINOR=%u", MINOR(dev->devt));
891 name = device_get_devnode(dev, &mode, &uid, &gid, &tmp);
892 if (name) {
893 add_uevent_var(env, "DEVNAME=%s", name);
894 if (mode)
895 add_uevent_var(env, "DEVMODE=%#o", mode & 0777);
896 if (!uid_eq(uid, GLOBAL_ROOT_UID))
897 add_uevent_var(env, "DEVUID=%u", from_kuid(&init_user_ns, uid));
898 if (!gid_eq(gid, GLOBAL_ROOT_GID))
899 add_uevent_var(env, "DEVGID=%u", from_kgid(&init_user_ns, gid));
900 kfree(tmp);
901 }
902 }
903
904 if (dev->type && dev->type->name)
905 add_uevent_var(env, "DEVTYPE=%s", dev->type->name);
906
907 if (dev->driver)
908 add_uevent_var(env, "DRIVER=%s", dev->driver->name);
909
910 /* Add common DT information about the device */
911 of_device_uevent(dev, env);
912
913 /* have the bus specific function add its stuff */
914 if (dev->bus && dev->bus->uevent) {
915 retval = dev->bus->uevent(dev, env);
916 if (retval)
917 pr_debug("device: '%s': %s: bus uevent() returned %d\n",
918 dev_name(dev), __func__, retval);
919 }
920
921 /* have the class specific function add its stuff */
922 if (dev->class && dev->class->dev_uevent) {
923 retval = dev->class->dev_uevent(dev, env);
924 if (retval)
925 pr_debug("device: '%s': %s: class uevent() "
926 "returned %d\n", dev_name(dev),
927 __func__, retval);
928 }
929
930 /* have the device type specific function add its stuff */
931 if (dev->type && dev->type->uevent) {
932 retval = dev->type->uevent(dev, env);
933 if (retval)
934 pr_debug("device: '%s': %s: dev_type uevent() "
935 "returned %d\n", dev_name(dev),
936 __func__, retval);
937 }
938
939 return retval;
940 }
执行到908行
[ 1.346815] tom F=kobject_uevent_env L=462 env1->envp[4]=MAJOR=253
[ 1.347566] tom F=kobject_uevent_env L=462 env1->envp[5]=MINOR=2
[ 1.348232] tom F=kobject_uevent_env L=462 env1->envp[6]=DEVNAME=vda2
[ 1.348963] tom F=kobject_uevent_env L=462 env1->envp[7]=DEVTYPE=partition
932行执行retval = dev->type->uevent(dev, env).
在文件block/partition-generic.c中的part_uevent函数:
231 static int part_uevent(struct device *dev, struct kobj_uevent_env *env)
232 {
233 struct hd_struct *part = dev_to_part(dev);
234
235 add_uevent_var(env, "PARTN=%u", part->partno);
236 if (part->info && part->info->volname[0])
237 add_uevent_var(env, "PARTNAME=%s", part->info->volname);
238 return 0;
239 }
执行完函数env->envp数组情况。
[ 1.349706] tom F=kobject_uevent_env L=462 env1->envp[8]=PARTN=2
[ 1.350547] tom F=kobject_uevent_env L=462 env1->envp[9]=PARTNAME=super
关于sda1中的env->envp中的字符串赋值。
可以知道PARTNAME=super是由part->info->volname赋值。
下一节看part->info->volname怎么赋值。