Print this page
4846 HAL partition names don't match real partition names
   1 /***************************************************************************
   2  *
   3  * devinfo_storage.c : storage devices
   4  *
   5  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
   6  * Copyright 2013 Garrett D'Amore <garrett@damore.org>

   7  *
   8  * Licensed under the Academic Free License version 2.1
   9  *
  10  **************************************************************************/
  11 
  12 #ifdef HAVE_CONFIG_H
  13 #  include <config.h>
  14 #endif
  15 
  16 #include <stdio.h>
  17 #include <string.h>
  18 #include <strings.h>
  19 #include <ctype.h>
  20 #include <libdevinfo.h>
  21 #include <sys/types.h>
  22 #include <sys/mkdev.h>
  23 #include <sys/stat.h>
  24 #include <sys/mntent.h>
  25 #include <sys/mnttab.h>
  26 


  64 HalDevice *devinfo_blkdev_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
  65 static HalDevice *devinfo_blkdev_storage_add(HalDevice *parent, di_node_t node, char *devfs_path);
  66 HalDevice *devinfo_floppy_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
  67 static void devinfo_floppy_add_volume(HalDevice *parent, di_node_t node);
  68 static HalDevice *devinfo_lofi_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
  69 static void devinfo_lofi_add_minor(HalDevice *parent, di_node_t node, char *minor_path, char *devlink, dev_t dev);
  70 static void devinfo_storage_minors(HalDevice *parent, di_node_t node, gchar *devfs_path, gboolean);
  71 static struct devinfo_storage_minor *devinfo_storage_new_minor(char *maindev_path, char *slice,
  72     char *devlink, dev_t dev, int dosnum);
  73 static void devinfo_storage_free_minor(struct devinfo_storage_minor *m);
  74 HalDevice *devinfo_volume_add(HalDevice *parent, di_node_t node, devinfo_storage_minor_t *m);
  75 static void devinfo_volume_preprobing_done(HalDevice *d, gpointer userdata1, gpointer userdata2);
  76 static void devinfo_volume_hotplug_begin_add (HalDevice *d, HalDevice *parent, DevinfoDevHandler *handler, void *end_token);
  77 static void devinfo_storage_hotplug_begin_add (HalDevice *d, HalDevice *parent, DevinfoDevHandler *handler, void *end_token);
  78 static void devinfo_storage_probing_done (HalDevice *d, guint32 exit_type, gint return_code, char **error, gpointer userdata1, gpointer userdata2);
  79 const gchar *devinfo_volume_get_prober (HalDevice *d, int *timeout);
  80 const gchar *devinfo_storage_get_prober (HalDevice *d, int *timeout);
  81 
  82 static char *devinfo_scsi_dtype2str(int dtype);
  83 static char *devinfo_volume_get_slice_name (char *devlink);
  84 static gboolean dos_to_dev(char *path, char **devpath, int *partnum);
  85 static gboolean is_dos_path(char *path, int *partnum);
  86 
  87 static void devinfo_storage_set_nicknames (HalDevice *d);
  88 
  89 DevinfoDevHandler devinfo_ide_handler = {
  90         devinfo_ide_add,
  91         NULL,
  92         NULL,
  93         NULL,
  94         NULL,
  95         NULL
  96 };
  97 DevinfoDevHandler devinfo_scsi_handler = {
  98         devinfo_scsi_add,
  99         NULL,
 100         NULL,
 101         NULL,
 102         NULL,
 103         NULL
 104 };
 105 DevinfoDevHandler devinfo_blkdev_handler = {


 842         while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
 843                 dev = di_minor_devt(minor);
 844                 if ((major != major(dev)) ||
 845                     (di_minor_type(minor) != DDM_MINOR) ||
 846                     (di_minor_spectype(minor) != S_IFBLK) ||
 847                     ((minor_path = di_devfs_minor_path(minor)) == NULL)) {
 848                         continue;
 849                 }
 850                 if ((devlink = get_devlink(devlink_hdl, NULL, minor_path)) == NULL) {
 851                         di_devfs_path_free (minor_path);
 852                         continue;
 853                 }
 854 
 855                 slice = devinfo_volume_get_slice_name (devlink);
 856                 if (strlen (slice) < 2) {
 857                         free (devlink);
 858                         di_devfs_path_free (minor_path);
 859                         continue;
 860                 }
 861 
 862                 /* ignore p1..N - we'll use p0:N instead */
 863                 if ((strlen (slice) > 1) && (slice[0] == 'p') && isdigit(slice[1]) &&
 864                     ((atol(&slice[1])) > 0)) {
 865                         free (devlink);
 866                         di_devfs_path_free (minor_path);
 867                         continue;
 868                 }
 869 
 870                 m = devinfo_storage_new_minor(minor_path, slice, devlink, dev, -1);
 871                 if (m == NULL) {
 872                         free (devlink);
 873                         di_devfs_path_free (minor_path);
 874                         continue;
 875                 }
 876 
 877                 /* main device is either s2/p0 or d0, the latter taking precedence */
 878                 if ((strcmp (slice, "d0") == 0) ||
 879                     (((strcmp (slice, whole_disk) == 0) && (maindev == NULL)))) {
 880                         if (maindev_path != NULL) {
 881                                 di_devfs_path_free (maindev_path);
 882                         }
 883                         maindev_path = minor_path;
 884                         maindev = m;
 885                         g_queue_push_head (mq, maindev);
 886                 } else {
 887                         di_devfs_path_free (minor_path);
 888                         g_queue_push_tail (mq, m);
 889                 }


 896                 /* shouldn't typically happen */
 897                 while (!g_queue_is_empty (mq)) {
 898                         devinfo_storage_free_minor (g_queue_pop_head (mq));
 899                 }
 900                 goto err;
 901         }
 902 
 903         /* first enqueue main storage device */
 904         if (!rescan) {
 905                 hal_device_property_set_int (parent, "block.major", major);
 906                 hal_device_property_set_int (parent, "block.minor", minor(maindev->dev));
 907                 hal_device_property_set_string (parent, "block.device", maindev->devlink);
 908                 raw = dsk_to_rdsk (maindev->devlink);
 909                 hal_device_property_set_string (parent, "block.solaris.raw_device", raw);
 910                 free (raw);
 911                 hal_device_property_set_bool (parent, "block.is_volume", FALSE);
 912                 hal_device_property_set_string (parent, "solaris.devfs_path", maindev_path);
 913                 devinfo_add_enqueue (parent, maindev_path, &devinfo_storage_handler);
 914         }
 915 
 916         /* add virtual dos volumes to enable pcfs probing */
 917         if (!is_cdrom) {
 918                 doslink_len = strlen (maindev->devlink) + sizeof (":NNN") + 1;
 919                 if ((doslink = (char *)calloc (1, doslink_len)) != NULL) {
 920                         for (i = 1; i < 16; i++) {
 921                                 snprintf(dospath, sizeof (dospath), "%s:%d", maindev->slice, i);
 922                                 snprintf(doslink, doslink_len, "%s:%d", maindev->devlink, i);
 923                                 m = devinfo_storage_new_minor(maindev_path, dospath, doslink, maindev->dev, i);
 924                                 g_queue_push_tail (mq, m);
 925                         }
 926                         free (doslink);
 927                 }
 928         }
 929 
 930         maindev_is_d0 = (strcmp (maindev->slice, "d0") == 0);
 931 
 932         /* enqueue all volumes */
 933         while (!g_queue_is_empty (mq)) {
 934                 m = g_queue_pop_head (mq);
 935 
 936                 /* if main device is d0, we'll throw away s2/p0 */
 937                 if (maindev_is_d0 && (strcmp (m->slice, whole_disk) == 0)) {
 938                         devinfo_storage_free_minor (m);
 939                         continue;
 940                 }
 941                 /* don't do p0 on cdrom */
 942                 if (is_cdrom && (strcmp (m->slice, "p0") == 0)) {
 943                         devinfo_storage_free_minor (m);
 944                         continue;
 945                 }
 946                 if (rescan) {
 947                         /* in rescan mode, don't reprobe existing volumes */
 948                         /* XXX detect volume removal? */
 949                         volume = hal_device_store_match_key_value_string (hald_get_gdl (),


1060         /*
1061          * Optimizations: only probe if there's a chance to find something
1062          */
1063         block_device = (char *)hal_device_property_get_string (d, "block.device");
1064         storage_udi = hal_device_property_get_string (d, "block.storage_device");
1065         slice = hal_device_property_get_string(d, "block.solaris.slice");
1066         if ((block_device == NULL) || (storage_udi == NULL) ||
1067             (slice == NULL) || (strlen (slice) < 2)) {
1068                 HAL_INFO (("Malformed volume properties %s", hal_device_get_udi (d)));
1069                 goto skip;
1070         }
1071         storage_d = hal_device_store_match_key_value_string (hald_get_gdl (), "info.udi", storage_udi);
1072         if (storage_d == NULL) {
1073                 HAL_INFO (("Storage device not found %s", hal_device_get_udi (d)));
1074                 goto skip;
1075         }
1076 
1077         whole_disk = hal_device_has_capability (storage_d,
1078             "storage.cdrom") ? "s2" : WHOLE_DISK;
1079 
1080         if (is_dos_path(block_device, &dos_num)) {
1081                 /* don't probe more dos volumes than probe-storage found */
1082                 if ((hal_device_property_get_bool (storage_d, "storage.no_partitions_hint") ||
1083                     (dos_num > hal_device_property_get_int (storage_d, "storage.solaris.num_dos_partitions")))) {
1084                             HAL_INFO (("%d > %d %s", dos_num, hal_device_property_get_int (storage_d,
1085                                 "storage.solaris.num_dos_partitions"), hal_device_get_udi (storage_d)));
1086                         goto skip;
1087                 }
1088         } else {
1089                 /* if no VTOC slices found, don't probe slices except s2 */
1090                 if ((slice[0] == 's') && (isdigit(slice[1])) && ((strcmp (slice, whole_disk)) != 0) &&
1091                     !hal_device_property_get_bool (storage_d, "storage.solaris.vtoc_slices")) {
1092                         HAL_INFO (("Not probing slice %s", hal_device_get_udi (d)));
1093                         goto skip;
1094                 }
1095         }
1096 
1097         HAL_INFO(("Probing udi=%s", hal_device_get_udi (d)));
1098         hald_runner_run (d,
1099                         "hald-probe-volume", NULL,
1100                         DEVINFO_PROBE_VOLUME_TIMEOUT,


1381         }
1382 
1383         part = strrchr(devlink, 'p');
1384         slice = strrchr(devlink, 's');
1385         disk = strrchr(devlink, 'd');
1386 
1387         if ((part != NULL) && (part > slice) && (part > disk)) {
1388                 s = part;
1389         } else if ((slice != NULL) && (slice > disk)) {
1390                 s = slice;
1391         } else {
1392                 s = disk;
1393         }
1394         if ((s != NULL) && isdigit(s[1])) {
1395                 return (s);
1396         } else {
1397                 return ("");
1398         }
1399 }
1400 
1401 static gboolean
1402 is_dos_path(char *path, int *partnum)
1403 {
1404         char *p;
1405 
1406         if ((p = strrchr (path, ':')) == NULL) {
1407                 return (FALSE);

1408         }
1409         return ((*partnum = atoi(p + 1)) != 0);
1410 }
1411 
1412 static gboolean
1413 dos_to_dev(char *path, char **devpath, int *partnum)
1414 {
1415         char *p;
1416 
1417         if ((p = strrchr (path, ':')) == NULL) {
1418                 return (FALSE);
1419         }
1420         if ((*partnum = atoi(p + 1)) == 0) {
1421                 return (FALSE);
1422         }
1423         p[0] = '\0';
1424         *devpath = strdup(path);
1425         p[0] = ':';
1426         return (*devpath != NULL);
1427 }
1428 
1429 static void
1430 devinfo_storage_cleanup_mountpoint_cb (HalDevice *d, guint32 exit_type, 
1431                        gint return_code, gchar **error,
1432                        gpointer data1, gpointer data2)
1433 {
1434         char *mount_point = (char *) data1;
1435 
1436         HAL_INFO (("Cleaned up mount point '%s'", mount_point));
1437         g_free (mount_point);
1438 }
1439 
1440 
1441 void
1442 devinfo_storage_mnttab_event (HalDevice *hal_volume)
1443 {
1444         FILE *fp = NULL;
1445         struct extmnttab m;
1446         HalDevice *d;


   1 /***************************************************************************
   2  *
   3  * devinfo_storage.c : storage devices
   4  *
   5  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
   6  * Copyright 2013 Garrett D'Amore <garrett@damore.org>
   7  * Copyright 2014 Andrew Stormont.
   8  *
   9  * Licensed under the Academic Free License version 2.1
  10  *
  11  **************************************************************************/
  12 
  13 #ifdef HAVE_CONFIG_H
  14 #  include <config.h>
  15 #endif
  16 
  17 #include <stdio.h>
  18 #include <string.h>
  19 #include <strings.h>
  20 #include <ctype.h>
  21 #include <libdevinfo.h>
  22 #include <sys/types.h>
  23 #include <sys/mkdev.h>
  24 #include <sys/stat.h>
  25 #include <sys/mntent.h>
  26 #include <sys/mnttab.h>
  27 


  65 HalDevice *devinfo_blkdev_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
  66 static HalDevice *devinfo_blkdev_storage_add(HalDevice *parent, di_node_t node, char *devfs_path);
  67 HalDevice *devinfo_floppy_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
  68 static void devinfo_floppy_add_volume(HalDevice *parent, di_node_t node);
  69 static HalDevice *devinfo_lofi_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
  70 static void devinfo_lofi_add_minor(HalDevice *parent, di_node_t node, char *minor_path, char *devlink, dev_t dev);
  71 static void devinfo_storage_minors(HalDevice *parent, di_node_t node, gchar *devfs_path, gboolean);
  72 static struct devinfo_storage_minor *devinfo_storage_new_minor(char *maindev_path, char *slice,
  73     char *devlink, dev_t dev, int dosnum);
  74 static void devinfo_storage_free_minor(struct devinfo_storage_minor *m);
  75 HalDevice *devinfo_volume_add(HalDevice *parent, di_node_t node, devinfo_storage_minor_t *m);
  76 static void devinfo_volume_preprobing_done(HalDevice *d, gpointer userdata1, gpointer userdata2);
  77 static void devinfo_volume_hotplug_begin_add (HalDevice *d, HalDevice *parent, DevinfoDevHandler *handler, void *end_token);
  78 static void devinfo_storage_hotplug_begin_add (HalDevice *d, HalDevice *parent, DevinfoDevHandler *handler, void *end_token);
  79 static void devinfo_storage_probing_done (HalDevice *d, guint32 exit_type, gint return_code, char **error, gpointer userdata1, gpointer userdata2);
  80 const gchar *devinfo_volume_get_prober (HalDevice *d, int *timeout);
  81 const gchar *devinfo_storage_get_prober (HalDevice *d, int *timeout);
  82 
  83 static char *devinfo_scsi_dtype2str(int dtype);
  84 static char *devinfo_volume_get_slice_name (char *devlink);
  85 static boolean_t is_dos_slice(const char *slice, int *partnum);

  86 
  87 static void devinfo_storage_set_nicknames (HalDevice *d);
  88 
  89 DevinfoDevHandler devinfo_ide_handler = {
  90         devinfo_ide_add,
  91         NULL,
  92         NULL,
  93         NULL,
  94         NULL,
  95         NULL
  96 };
  97 DevinfoDevHandler devinfo_scsi_handler = {
  98         devinfo_scsi_add,
  99         NULL,
 100         NULL,
 101         NULL,
 102         NULL,
 103         NULL
 104 };
 105 DevinfoDevHandler devinfo_blkdev_handler = {


 842         while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
 843                 dev = di_minor_devt(minor);
 844                 if ((major != major(dev)) ||
 845                     (di_minor_type(minor) != DDM_MINOR) ||
 846                     (di_minor_spectype(minor) != S_IFBLK) ||
 847                     ((minor_path = di_devfs_minor_path(minor)) == NULL)) {
 848                         continue;
 849                 }
 850                 if ((devlink = get_devlink(devlink_hdl, NULL, minor_path)) == NULL) {
 851                         di_devfs_path_free (minor_path);
 852                         continue;
 853                 }
 854 
 855                 slice = devinfo_volume_get_slice_name (devlink);
 856                 if (strlen (slice) < 2) {
 857                         free (devlink);
 858                         di_devfs_path_free (minor_path);
 859                         continue;
 860                 }
 861 








 862                 m = devinfo_storage_new_minor(minor_path, slice, devlink, dev, -1);
 863                 if (m == NULL) {
 864                         free (devlink);
 865                         di_devfs_path_free (minor_path);
 866                         continue;
 867                 }
 868 
 869                 /* main device is either s2/p0 or d0, the latter taking precedence */
 870                 if ((strcmp (slice, "d0") == 0) ||
 871                     (((strcmp (slice, whole_disk) == 0) && (maindev == NULL)))) {
 872                         if (maindev_path != NULL) {
 873                                 di_devfs_path_free (maindev_path);
 874                         }
 875                         maindev_path = minor_path;
 876                         maindev = m;
 877                         g_queue_push_head (mq, maindev);
 878                 } else {
 879                         di_devfs_path_free (minor_path);
 880                         g_queue_push_tail (mq, m);
 881                 }


 888                 /* shouldn't typically happen */
 889                 while (!g_queue_is_empty (mq)) {
 890                         devinfo_storage_free_minor (g_queue_pop_head (mq));
 891                 }
 892                 goto err;
 893         }
 894 
 895         /* first enqueue main storage device */
 896         if (!rescan) {
 897                 hal_device_property_set_int (parent, "block.major", major);
 898                 hal_device_property_set_int (parent, "block.minor", minor(maindev->dev));
 899                 hal_device_property_set_string (parent, "block.device", maindev->devlink);
 900                 raw = dsk_to_rdsk (maindev->devlink);
 901                 hal_device_property_set_string (parent, "block.solaris.raw_device", raw);
 902                 free (raw);
 903                 hal_device_property_set_bool (parent, "block.is_volume", FALSE);
 904                 hal_device_property_set_string (parent, "solaris.devfs_path", maindev_path);
 905                 devinfo_add_enqueue (parent, maindev_path, &devinfo_storage_handler);
 906         }
 907 














 908         maindev_is_d0 = (strcmp (maindev->slice, "d0") == 0);
 909 
 910         /* enqueue all volumes */
 911         while (!g_queue_is_empty (mq)) {
 912                 m = g_queue_pop_head (mq);
 913 
 914                 /* if main device is d0, we'll throw away s2/p0 */
 915                 if (maindev_is_d0 && (strcmp (m->slice, whole_disk) == 0)) {
 916                         devinfo_storage_free_minor (m);
 917                         continue;
 918                 }
 919                 /* don't do p0 on cdrom */
 920                 if (is_cdrom && (strcmp (m->slice, "p0") == 0)) {
 921                         devinfo_storage_free_minor (m);
 922                         continue;
 923                 }
 924                 if (rescan) {
 925                         /* in rescan mode, don't reprobe existing volumes */
 926                         /* XXX detect volume removal? */
 927                         volume = hal_device_store_match_key_value_string (hald_get_gdl (),


1038         /*
1039          * Optimizations: only probe if there's a chance to find something
1040          */
1041         block_device = (char *)hal_device_property_get_string (d, "block.device");
1042         storage_udi = hal_device_property_get_string (d, "block.storage_device");
1043         slice = hal_device_property_get_string(d, "block.solaris.slice");
1044         if ((block_device == NULL) || (storage_udi == NULL) ||
1045             (slice == NULL) || (strlen (slice) < 2)) {
1046                 HAL_INFO (("Malformed volume properties %s", hal_device_get_udi (d)));
1047                 goto skip;
1048         }
1049         storage_d = hal_device_store_match_key_value_string (hald_get_gdl (), "info.udi", storage_udi);
1050         if (storage_d == NULL) {
1051                 HAL_INFO (("Storage device not found %s", hal_device_get_udi (d)));
1052                 goto skip;
1053         }
1054 
1055         whole_disk = hal_device_has_capability (storage_d,
1056             "storage.cdrom") ? "s2" : WHOLE_DISK;
1057 
1058         if (is_dos_slice(slice, &dos_num)) {
1059                 /* don't probe more dos volumes than probe-storage found */
1060                 if ((hal_device_property_get_bool (storage_d, "storage.no_partitions_hint") ||
1061                     (dos_num > hal_device_property_get_int (storage_d, "storage.solaris.num_dos_partitions")))) {
1062                             HAL_INFO (("%d > %d %s", dos_num, hal_device_property_get_int (storage_d,
1063                                 "storage.solaris.num_dos_partitions"), hal_device_get_udi (storage_d)));
1064                         goto skip;
1065                 }
1066         } else {
1067                 /* if no VTOC slices found, don't probe slices except s2 */
1068                 if ((slice[0] == 's') && (isdigit(slice[1])) && ((strcmp (slice, whole_disk)) != 0) &&
1069                     !hal_device_property_get_bool (storage_d, "storage.solaris.vtoc_slices")) {
1070                         HAL_INFO (("Not probing slice %s", hal_device_get_udi (d)));
1071                         goto skip;
1072                 }
1073         }
1074 
1075         HAL_INFO(("Probing udi=%s", hal_device_get_udi (d)));
1076         hald_runner_run (d,
1077                         "hald-probe-volume", NULL,
1078                         DEVINFO_PROBE_VOLUME_TIMEOUT,


1359         }
1360 
1361         part = strrchr(devlink, 'p');
1362         slice = strrchr(devlink, 's');
1363         disk = strrchr(devlink, 'd');
1364 
1365         if ((part != NULL) && (part > slice) && (part > disk)) {
1366                 s = part;
1367         } else if ((slice != NULL) && (slice > disk)) {
1368                 s = slice;
1369         } else {
1370                 s = disk;
1371         }
1372         if ((s != NULL) && isdigit(s[1])) {
1373                 return (s);
1374         } else {
1375                 return ("");
1376         }
1377 }
1378 
1379 static boolean_t
1380 is_dos_slice(const char *slice, int *partnum)
1381 {
1382         char *p;
1383 
1384         if ((p = strrchr(slice, 'p')) == NULL &&
1385             (p = strrchr(slice, ':')) == NULL) {
1386                 return (B_FALSE);
1387         }







1388 
1389         return ((*partnum = atoi(p + 1)) != 0);









1390 }
1391 
1392 static void
1393 devinfo_storage_cleanup_mountpoint_cb (HalDevice *d, guint32 exit_type, 
1394                        gint return_code, gchar **error,
1395                        gpointer data1, gpointer data2)
1396 {
1397         char *mount_point = (char *) data1;
1398 
1399         HAL_INFO (("Cleaned up mount point '%s'", mount_point));
1400         g_free (mount_point);
1401 }
1402 
1403 
1404 void
1405 devinfo_storage_mnttab_event (HalDevice *hal_volume)
1406 {
1407         FILE *fp = NULL;
1408         struct extmnttab m;
1409         HalDevice *d;