kernel - Add /dev/part-by-label
authorMatthew Dillon <dillon@apollo.backplane.com>
Thu, 28 Feb 2019 06:36:27 +0000 (22:36 -0800)
committerMatthew Dillon <dillon@apollo.backplane.com>
Thu, 28 Feb 2019 06:41:29 +0000 (22:41 -0800)
* The DragonFly disklabel has a 'label' field which accepts up to
  a 63 byte ascii label.

* When this field is not empty, the kernel will now create a
  "/dev/part-by-label/<label>.<part>" alias.

  For example, if the label is FUBAR and you create a label with
  partitions 'a', 'b', and 'd', then you will get:

  # ls /dev/part-by-label
  FUBAR.a      FUBAR.b      FUBAR.d

* WARNING!  Duplicate labels will replace each other, so the
  label that shows up will be non-deterministic.

Suggested-by: Aaron LI
sys/kern/subr_disk.c
sys/kern/subr_disklabel32.c
sys/kern/subr_disklabel64.c
sys/sys/disklabel.h

index e5b64e7..fb67ceb 100644 (file)
@@ -208,14 +208,23 @@ disk_probe_slice(struct disk *dp, cdev_t dev, int slice, int reprobe)
        }
 
        if (msg == NULL) {
+               char packname[DISKLABEL_MAXPACKNAME];
+
                if (slice != WHOLE_DISK_SLICE)
                        ops->op_adjust_label_reserved(dp->d_slice, slice, sp);
                else
                        sp->ds_reserved = 0;
 
+               ops->op_getpackname(sp->ds_label, packname, sizeof(packname));
+
+               destroy_dev_alias(dev, "by-label/*");
+               if (packname[0])
+                       make_dev_alias(dev, "by-label/%s", packname);
+
                sp->ds_ops = ops;
                for (i = 0; i < ops->op_getnumparts(sp->ds_label); i++) {
                        ops->op_loadpartinfo(sp->ds_label, i, &part);
+
                        if (part.fstype) {
                                if (reprobe &&
                                    (ndev = devfs_find_device_by_name("%s%c",
@@ -230,7 +239,10 @@ disk_probe_slice(struct disk *dp, cdev_t dev, int slice, int reprobe)
                                        /*
                                         * Destroy old UUID alias
                                         */
-                                       destroy_dev_alias(ndev, "part-by-uuid/*");
+                                       destroy_dev_alias(ndev,
+                                                         "part-by-uuid/*");
+                                       destroy_dev_alias(ndev,
+                                                         "part-by-label/*");
 
                                        /* Create UUID alias */
                                        if (!kuuid_is_nil(&part.storage_uuid)) {
@@ -242,6 +254,11 @@ disk_probe_slice(struct disk *dp, cdev_t dev, int slice, int reprobe)
                                                    uuid_buf);
                                                udev_dict_set_cstr(ndev, "uuid", uuid_buf);
                                        }
+                                       if (packname[0]) {
+                                               make_dev_alias(ndev,
+                                                   "part-by-label/%s.%c",
+                                                   packname, 'a' + i);
+                                       }
                                } else {
                                        ndev = make_dev_covering(dops,
                                                dp->d_rawdev->si_ops,
@@ -277,6 +294,11 @@ disk_probe_slice(struct disk *dp, cdev_t dev, int slice, int reprobe)
                                                    uuid_buf);
                                                udev_dict_set_cstr(ndev, "uuid", uuid_buf);
                                        }
+                                       if (packname[0]) {
+                                               make_dev_alias(ndev,
+                                                   "part-by-label/%s.%c",
+                                                   packname, 'a' + i);
+                                       }
                                        ndev->si_flags |= SI_REPROBE_TEST;
                                }
                        }
index 3012137..323bb02 100644 (file)
@@ -155,6 +155,24 @@ l32_getnumparts(disklabel_t lp)
        return(lp.lab32->d_npartitions);
 }
 
+static int
+l32_getpackname(disklabel_t lp, char *buf, size_t bytes)
+{
+       size_t slen;
+
+       if (lp.lab32->d_packname[0] == 0) {
+               buf[0] = 0;
+               return -1;
+       }
+       slen = strnlen(lp.lab32->d_packname, sizeof(lp.lab32->d_packname));
+       if (slen >= bytes)
+               slen = bytes - 1;
+       bcopy(lp.lab32->d_packname, buf, slen);
+       buf[slen] = 0;
+
+       return 0;
+}
+
 static void
 l32_freedisklabel(disklabel_t *lpp)
 {
@@ -636,6 +654,7 @@ struct disklabel_ops disklabel32_ops = {
        .op_loadpartinfo = l32_loadpartinfo,
        .op_getnumparts = l32_getnumparts,
        .op_makevirginlabel = l32_makevirginlabel,
+       .op_getpackname = l32_getpackname,
        .op_freedisklabel = l32_freedisklabel
 };
 
index fff9262..d83743b 100644 (file)
@@ -110,6 +110,24 @@ l64_getnumparts(disklabel_t lp)
        return(lp.lab64->d_npartitions);
 }
 
+static int
+l64_getpackname(disklabel_t lp, char *buf, size_t bytes)
+{
+       size_t slen;
+
+       if (lp.lab64->d_packname[0] == 0) {
+               buf[0] = 0;
+               return -1;
+       }
+       slen = strnlen(lp.lab64->d_packname, sizeof(lp.lab64->d_packname));
+       if (slen >= bytes)
+               slen = bytes - 1;
+       bcopy(lp.lab64->d_packname, buf, slen);
+       buf[slen] = 0;
+
+       return 0;
+}
+
 static void
 l64_freedisklabel(disklabel_t *lpp)
 {
@@ -517,6 +535,7 @@ struct disklabel_ops disklabel64_ops = {
        .op_getpartbounds = l64_getpartbounds,
        .op_loadpartinfo = l64_loadpartinfo,
        .op_getnumparts = l64_getnumparts,
+       .op_getpackname = l64_getpackname,
        .op_makevirginlabel = l64_makevirginlabel,
        .op_freedisklabel = l64_freedisklabel
 };
index 608165a..7b0bfbd 100644 (file)
@@ -62,6 +62,8 @@ struct diskslices;
 struct disk_info;
 struct partinfo;
 
+#define DISKLABEL_MAXPACKNAME  64
+
 struct disklabel_ops {
        struct uuid type;       /* uuid specifies disklabel type */
        int labelsize;          /* size of disklabel in bytes */
@@ -86,6 +88,8 @@ struct disklabel_ops {
                    (disklabel_t, u_int32_t, struct partinfo *);
        u_int32_t (*op_getnumparts)
                    (disklabel_t);
+       int  (*op_getpackname)
+                   (disklabel_t, char *, size_t);
        void (*op_makevirginlabel)
                    (disklabel_t, struct diskslices *,
                     struct diskslice *, struct disk_info *);