LCOV - code coverage report
Current view: top level - core - device.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 316 538 58.7 %
Date: 2019-08-23 13:36:53 Functions: 29 36 80.6 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 205 600 34.2 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <errno.h>
       4                 :            : #include <sys/epoll.h>
       5                 :            : 
       6                 :            : #include "alloc-util.h"
       7                 :            : #include "bus-error.h"
       8                 :            : #include "dbus-device.h"
       9                 :            : #include "dbus-unit.h"
      10                 :            : #include "device-private.h"
      11                 :            : #include "device-util.h"
      12                 :            : #include "device.h"
      13                 :            : #include "log.h"
      14                 :            : #include "parse-util.h"
      15                 :            : #include "path-util.h"
      16                 :            : #include "serialize.h"
      17                 :            : #include "stat-util.h"
      18                 :            : #include "string-util.h"
      19                 :            : #include "swap.h"
      20                 :            : #include "udev-util.h"
      21                 :            : #include "unit-name.h"
      22                 :            : #include "unit.h"
      23                 :            : 
      24                 :            : static const UnitActiveState state_translation_table[_DEVICE_STATE_MAX] = {
      25                 :            :         [DEVICE_DEAD] = UNIT_INACTIVE,
      26                 :            :         [DEVICE_TENTATIVE] = UNIT_ACTIVATING,
      27                 :            :         [DEVICE_PLUGGED] = UNIT_ACTIVE,
      28                 :            : };
      29                 :            : 
      30                 :            : static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void *userdata);
      31                 :            : static void device_update_found_one(Device *d, DeviceFound found, DeviceFound mask);
      32                 :            : 
      33                 :      11792 : static void device_unset_sysfs(Device *d) {
      34                 :            :         Hashmap *devices;
      35                 :            :         Device *first;
      36                 :            : 
      37         [ -  + ]:      11792 :         assert(d);
      38                 :            : 
      39         [ +  + ]:      11792 :         if (!d->sysfs)
      40                 :       5896 :                 return;
      41                 :            : 
      42                 :            :         /* Remove this unit from the chain of devices which share the
      43                 :            :          * same sysfs path. */
      44         [ +  - ]:       5896 :         devices = UNIT(d)->manager->devices_by_sysfs;
      45                 :       5896 :         first = hashmap_get(devices, d->sysfs);
      46   [ -  +  +  +  :       5896 :         LIST_REMOVE(same_sysfs, first, d);
             +  +  -  + ]
      47                 :            : 
      48         [ +  + ]:       5896 :         if (first)
      49                 :       3520 :                 hashmap_remove_and_replace(devices, d->sysfs, first->sysfs, first);
      50                 :            :         else
      51                 :       2376 :                 hashmap_remove(devices, d->sysfs);
      52                 :            : 
      53                 :       5896 :         d->sysfs = mfree(d->sysfs);
      54                 :            : }
      55                 :            : 
      56                 :       6116 : static int device_set_sysfs(Device *d, const char *sysfs) {
      57                 :       6116 :         _cleanup_free_ char *copy = NULL;
      58                 :            :         Device *first;
      59                 :            :         int r;
      60                 :            : 
      61         [ -  + ]:       6116 :         assert(d);
      62                 :            : 
      63         [ +  + ]:       6116 :         if (streq_ptr(d->sysfs, sysfs))
      64                 :        220 :                 return 0;
      65                 :            : 
      66         [ +  - ]:       5896 :         r = hashmap_ensure_allocated(&UNIT(d)->manager->devices_by_sysfs, &path_hash_ops);
      67         [ -  + ]:       5896 :         if (r < 0)
      68                 :          0 :                 return r;
      69                 :            : 
      70                 :       5896 :         copy = strdup(sysfs);
      71         [ -  + ]:       5896 :         if (!copy)
      72                 :          0 :                 return -ENOMEM;
      73                 :            : 
      74                 :       5896 :         device_unset_sysfs(d);
      75                 :            : 
      76         [ +  - ]:       5896 :         first = hashmap_get(UNIT(d)->manager->devices_by_sysfs, sysfs);
      77   [ -  +  +  + ]:       5896 :         LIST_PREPEND(same_sysfs, first, d);
      78                 :            : 
      79         [ +  - ]:       5896 :         r = hashmap_replace(UNIT(d)->manager->devices_by_sysfs, copy, first);
      80         [ -  + ]:       5896 :         if (r < 0) {
      81   [ #  #  #  #  :          0 :                 LIST_REMOVE(same_sysfs, first, d);
             #  #  #  # ]
      82                 :          0 :                 return r;
      83                 :            :         }
      84                 :            : 
      85                 :       5896 :         d->sysfs = TAKE_PTR(copy);
      86                 :       5896 :         return 0;
      87                 :            : }
      88                 :            : 
      89                 :       5896 : static void device_init(Unit *u) {
      90                 :       5896 :         Device *d = DEVICE(u);
      91                 :            : 
      92         [ -  + ]:       5896 :         assert(d);
      93   [ +  -  -  + ]:       5896 :         assert(UNIT(d)->load_state == UNIT_STUB);
      94                 :            : 
      95                 :            :         /* In contrast to all other unit types we timeout jobs waiting
      96                 :            :          * for devices by default. This is because they otherwise wait
      97                 :            :          * indefinitely for plugged in devices, something which cannot
      98                 :            :          * happen for the other units since their operations time out
      99                 :            :          * anyway. */
     100                 :       5896 :         u->job_running_timeout = u->manager->default_timeout_start_usec;
     101                 :            : 
     102                 :       5896 :         u->ignore_on_isolate = true;
     103                 :            : 
     104                 :       5896 :         d->deserialized_state = _DEVICE_STATE_INVALID;
     105                 :       5896 : }
     106                 :            : 
     107                 :       5896 : static void device_done(Unit *u) {
     108                 :       5896 :         Device *d = DEVICE(u);
     109                 :            : 
     110         [ -  + ]:       5896 :         assert(d);
     111                 :            : 
     112                 :       5896 :         device_unset_sysfs(d);
     113                 :       5896 :         d->wants_property = strv_free(d->wants_property);
     114                 :       5896 : }
     115                 :            : 
     116                 :       5896 : static int device_load(Unit *u) {
     117                 :            :         int r;
     118                 :            : 
     119                 :       5896 :         r = unit_load_fragment_and_dropin_optional(u);
     120         [ -  + ]:       5896 :         if (r < 0)
     121                 :          0 :                 return r;
     122                 :            : 
     123         [ -  + ]:       5896 :         if (!u->description) {
     124                 :            :                 /* Generate a description based on the path, to be used until the
     125                 :            :                    device is initialized properly */
     126                 :          0 :                 r = unit_name_to_path(u->id, &u->description);
     127         [ #  # ]:          0 :                 if (r < 0)
     128         [ #  # ]:          0 :                         log_unit_debug_errno(u, r, "Failed to unescape name: %m");
     129                 :            :         }
     130                 :            : 
     131                 :       5896 :         return 0;
     132                 :            : }
     133                 :            : 
     134                 :       5896 : static void device_set_state(Device *d, DeviceState state) {
     135                 :            :         DeviceState old_state;
     136         [ -  + ]:       5896 :         assert(d);
     137                 :            : 
     138         [ +  - ]:       5896 :         if (d->state != state)
     139         [ +  - ]:       5896 :                 bus_unit_send_pending_change_signal(UNIT(d), false);
     140                 :            : 
     141                 :       5896 :         old_state = d->state;
     142                 :       5896 :         d->state = state;
     143                 :            : 
     144         [ -  + ]:       5896 :         if (state == DEVICE_DEAD)
     145                 :          0 :                 device_unset_sysfs(d);
     146                 :            : 
     147         [ +  - ]:       5896 :         if (state != old_state)
     148   [ +  -  +  - ]:       5896 :                 log_unit_debug(UNIT(d), "Changed %s -> %s", device_state_to_string(old_state), device_state_to_string(state));
     149                 :            : 
     150         [ +  - ]:       5896 :         unit_notify(UNIT(d), state_translation_table[old_state], state_translation_table[state], 0);
     151                 :       5896 : }
     152                 :            : 
     153                 :       5896 : static int device_coldplug(Unit *u) {
     154                 :       5896 :         Device *d = DEVICE(u);
     155                 :            : 
     156         [ -  + ]:       5896 :         assert(d);
     157         [ -  + ]:       5896 :         assert(d->state == DEVICE_DEAD);
     158                 :            : 
     159                 :            :         /* First, let's put the deserialized state and found mask into effect, if we have it. */
     160                 :            : 
     161         [ -  + ]:       5896 :         if (d->deserialized_state < 0 ||
     162         [ #  # ]:          0 :             (d->deserialized_state == d->state &&
     163         [ #  # ]:          0 :              d->deserialized_found == d->found))
     164                 :       5896 :                 return 0;
     165                 :            : 
     166                 :          0 :         d->found = d->deserialized_found;
     167                 :          0 :         device_set_state(d, d->deserialized_state);
     168                 :          0 :         return 0;
     169                 :            : }
     170                 :            : 
     171                 :       5896 : static void device_catchup(Unit *u) {
     172                 :       5896 :         Device *d = DEVICE(u);
     173                 :            : 
     174         [ -  + ]:       5896 :         assert(d);
     175                 :            : 
     176                 :            :         /* Second, let's update the state with the enumerated state if it's different */
     177         [ -  + ]:       5896 :         if (d->enumerated_found == d->found)
     178                 :          0 :                 return;
     179                 :            : 
     180                 :       5896 :         device_update_found_one(d, d->enumerated_found, DEVICE_FOUND_MASK);
     181                 :            : }
     182                 :            : 
     183                 :            : static const struct {
     184                 :            :         DeviceFound flag;
     185                 :            :         const char *name;
     186                 :            : } device_found_map[] = {
     187                 :            :         { DEVICE_FOUND_UDEV,  "found-udev"  },
     188                 :            :         { DEVICE_FOUND_MOUNT, "found-mount" },
     189                 :            :         { DEVICE_FOUND_SWAP,  "found-swap"  },
     190                 :            : };
     191                 :            : 
     192                 :       3216 : static int device_found_to_string_many(DeviceFound flags, char **ret) {
     193                 :       3216 :         _cleanup_free_ char *s = NULL;
     194                 :            :         unsigned i;
     195                 :            : 
     196         [ -  + ]:       3216 :         assert(ret);
     197                 :            : 
     198         [ +  + ]:      12864 :         for (i = 0; i < ELEMENTSOF(device_found_map); i++) {
     199         [ +  + ]:       9648 :                 if (!FLAGS_SET(flags, device_found_map[i].flag))
     200                 :       6336 :                         continue;
     201                 :            : 
     202         [ -  + ]:       3312 :                 if (!strextend_with_separator(&s, ",", device_found_map[i].name, NULL))
     203                 :          0 :                         return -ENOMEM;
     204                 :            :         }
     205                 :            : 
     206                 :       3216 :         *ret = TAKE_PTR(s);
     207                 :            : 
     208                 :       3216 :         return 0;
     209                 :            : }
     210                 :            : 
     211                 :          0 : static int device_found_from_string_many(const char *name, DeviceFound *ret) {
     212                 :          0 :         DeviceFound flags = 0;
     213                 :            :         int r;
     214                 :            : 
     215         [ #  # ]:          0 :         assert(ret);
     216                 :            : 
     217                 :          0 :         for (;;) {
     218      [ #  #  # ]:          0 :                 _cleanup_free_ char *word = NULL;
     219                 :          0 :                 DeviceFound f = 0;
     220                 :            :                 unsigned i;
     221                 :            : 
     222                 :          0 :                 r = extract_first_word(&name, &word, ",", 0);
     223         [ #  # ]:          0 :                 if (r < 0)
     224                 :          0 :                         return r;
     225         [ #  # ]:          0 :                 if (r == 0)
     226                 :          0 :                         break;
     227                 :            : 
     228         [ #  # ]:          0 :                 for (i = 0; i < ELEMENTSOF(device_found_map); i++)
     229         [ #  # ]:          0 :                         if (streq(word, device_found_map[i].name)) {
     230                 :          0 :                                 f = device_found_map[i].flag;
     231                 :          0 :                                 break;
     232                 :            :                         }
     233                 :            : 
     234         [ #  # ]:          0 :                 if (f == 0)
     235                 :          0 :                         return -EINVAL;
     236                 :            : 
     237                 :          0 :                 flags |= f;
     238                 :            :         }
     239                 :            : 
     240                 :          0 :         *ret = flags;
     241                 :          0 :         return 0;
     242                 :            : }
     243                 :            : 
     244                 :          0 : static int device_serialize(Unit *u, FILE *f, FDSet *fds) {
     245                 :          0 :         _cleanup_free_ char *s = NULL;
     246                 :          0 :         Device *d = DEVICE(u);
     247                 :            : 
     248         [ #  # ]:          0 :         assert(u);
     249         [ #  # ]:          0 :         assert(f);
     250         [ #  # ]:          0 :         assert(fds);
     251                 :            : 
     252                 :          0 :         (void) serialize_item(f, "state", device_state_to_string(d->state));
     253                 :            : 
     254         [ #  # ]:          0 :         if (device_found_to_string_many(d->found, &s) >= 0)
     255                 :          0 :                 (void) serialize_item(f, "found", s);
     256                 :            : 
     257                 :          0 :         return 0;
     258                 :            : }
     259                 :            : 
     260                 :          0 : static int device_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
     261                 :          0 :         Device *d = DEVICE(u);
     262                 :            :         int r;
     263                 :            : 
     264         [ #  # ]:          0 :         assert(u);
     265         [ #  # ]:          0 :         assert(key);
     266         [ #  # ]:          0 :         assert(value);
     267         [ #  # ]:          0 :         assert(fds);
     268                 :            : 
     269         [ #  # ]:          0 :         if (streq(key, "state")) {
     270                 :            :                 DeviceState state;
     271                 :            : 
     272                 :          0 :                 state = device_state_from_string(value);
     273         [ #  # ]:          0 :                 if (state < 0)
     274         [ #  # ]:          0 :                         log_unit_debug(u, "Failed to parse state value, ignoring: %s", value);
     275                 :            :                 else
     276                 :          0 :                         d->deserialized_state = state;
     277                 :            : 
     278         [ #  # ]:          0 :         } else if (streq(key, "found")) {
     279                 :          0 :                 r = device_found_from_string_many(value, &d->deserialized_found);
     280         [ #  # ]:          0 :                 if (r < 0)
     281         [ #  # ]:          0 :                         log_unit_debug_errno(u, r, "Failed to parse found value '%s', ignoring: %m", value);
     282                 :            : 
     283                 :            :         } else
     284         [ #  # ]:          0 :                 log_unit_debug(u, "Unknown serialization key: %s", key);
     285                 :            : 
     286                 :          0 :         return 0;
     287                 :            : }
     288                 :            : 
     289                 :       3216 : static void device_dump(Unit *u, FILE *f, const char *prefix) {
     290                 :       3216 :         Device *d = DEVICE(u);
     291                 :       3216 :         _cleanup_free_ char *s = NULL;
     292                 :            : 
     293         [ -  + ]:       3216 :         assert(d);
     294                 :            : 
     295                 :       3216 :         (void) device_found_to_string_many(d->found, &s);
     296                 :            : 
     297                 :       6432 :         fprintf(f,
     298                 :            :                 "%sDevice State: %s\n"
     299                 :            :                 "%sSysfs Path: %s\n"
     300                 :            :                 "%sFound: %s\n",
     301                 :            :                 prefix, device_state_to_string(d->state),
     302                 :       3216 :                 prefix, strna(d->sysfs),
     303                 :            :                 prefix, strna(s));
     304                 :            : 
     305         [ -  + ]:       3216 :         if (!strv_isempty(d->wants_property)) {
     306                 :            :                 char **i;
     307                 :            : 
     308   [ #  #  #  # ]:          0 :                 STRV_FOREACH(i, d->wants_property)
     309                 :          0 :                         fprintf(f, "%sudev SYSTEMD_WANTS: %s\n",
     310                 :            :                                 prefix, *i);
     311                 :            :         }
     312                 :       3216 : }
     313                 :            : 
     314                 :      30016 : _pure_ static UnitActiveState device_active_state(Unit *u) {
     315         [ -  + ]:      30016 :         assert(u);
     316                 :            : 
     317                 :      30016 :         return state_translation_table[DEVICE(u)->state];
     318                 :            : }
     319                 :            : 
     320                 :          0 : _pure_ static const char *device_sub_state_to_string(Unit *u) {
     321         [ #  # ]:          0 :         assert(u);
     322                 :            : 
     323                 :          0 :         return device_state_to_string(DEVICE(u)->state);
     324                 :            : }
     325                 :            : 
     326                 :       6116 : static int device_update_description(Unit *u, sd_device *dev, const char *path) {
     327                 :       6116 :         _cleanup_free_ char *j = NULL;
     328                 :            :         const char *model, *label, *desc;
     329                 :            :         int r;
     330                 :            : 
     331         [ -  + ]:       6116 :         assert(u);
     332         [ -  + ]:       6116 :         assert(path);
     333                 :            : 
     334                 :       6116 :         desc = path;
     335                 :            : 
     336   [ +  -  +  + ]:      12232 :         if (dev &&
     337         [ +  + ]:      11836 :             (sd_device_get_property_value(dev, "ID_MODEL_FROM_DATABASE", &model) >= 0 ||
     338                 :       5720 :              sd_device_get_property_value(dev, "ID_MODEL", &model) >= 0)) {
     339                 :       1584 :                 desc = model;
     340                 :            : 
     341                 :            :                 /* Try to concatenate the device model string with a label, if there is one */
     342   [ +  -  +  - ]:       3168 :                 if (sd_device_get_property_value(dev, "ID_FS_LABEL", &label) >= 0 ||
     343         [ +  + ]:       3168 :                     sd_device_get_property_value(dev, "ID_PART_ENTRY_NAME", &label) >= 0 ||
     344                 :       1584 :                     sd_device_get_property_value(dev, "ID_PART_ENTRY_NUMBER", &label) >= 0) {
     345                 :            : 
     346                 :        660 :                         desc = j = strjoin(model, " ", label);
     347         [ -  + ]:        660 :                         if (!j)
     348                 :          0 :                                 return log_oom();
     349                 :            :                 }
     350                 :            :         }
     351                 :            : 
     352                 :       6116 :         r = unit_set_description(u, desc);
     353         [ -  + ]:       6116 :         if (r < 0)
     354         [ #  # ]:          0 :                 return log_unit_error_errno(u, r, "Failed to set device description: %m");
     355                 :            : 
     356                 :       6116 :         return 0;
     357                 :            : }
     358                 :            : 
     359                 :       2332 : static int device_add_udev_wants(Unit *u, sd_device *dev) {
     360                 :       2332 :         _cleanup_strv_free_ char **added = NULL;
     361                 :            :         const char *wants, *property;
     362                 :       2332 :         Device *d = DEVICE(u);
     363                 :            :         int r;
     364                 :            : 
     365         [ -  + ]:       2332 :         assert(d);
     366         [ -  + ]:       2332 :         assert(dev);
     367                 :            : 
     368         [ +  - ]:       2332 :         property = MANAGER_IS_USER(u->manager) ? "SYSTEMD_USER_WANTS" : "SYSTEMD_WANTS";
     369                 :            : 
     370                 :       2332 :         r = sd_device_get_property_value(dev, property, &wants);
     371         [ +  - ]:       2332 :         if (r < 0)
     372                 :       2332 :                 return 0;
     373                 :            : 
     374                 :          0 :         for (;;) {
     375   [ #  #  #  #  :          0 :                 _cleanup_free_ char *word = NULL, *k = NULL;
                   #  # ]
     376                 :            : 
     377                 :          0 :                 r = extract_first_word(&wants, &word, NULL, EXTRACT_UNQUOTE);
     378         [ #  # ]:          0 :                 if (r == 0)
     379                 :          0 :                         break;
     380         [ #  # ]:          0 :                 if (r == -ENOMEM)
     381                 :          0 :                         return log_oom();
     382         [ #  # ]:          0 :                 if (r < 0)
     383         [ #  # ]:          0 :                         return log_unit_error_errno(u, r, "Failed to parse property %s with value %s: %m", property, wants);
     384                 :            : 
     385   [ #  #  #  # ]:          0 :                 if (unit_name_is_valid(word, UNIT_NAME_TEMPLATE) && d->sysfs) {
     386         [ #  # ]:          0 :                         _cleanup_free_ char *escaped = NULL;
     387                 :            : 
     388                 :            :                         /* If the unit name is specified as template, then automatically fill in the sysfs path of the
     389                 :            :                          * device as instance name, properly escaped. */
     390                 :            : 
     391                 :          0 :                         r = unit_name_path_escape(d->sysfs, &escaped);
     392         [ #  # ]:          0 :                         if (r < 0)
     393         [ #  # ]:          0 :                                 return log_unit_error_errno(u, r, "Failed to escape %s: %m", d->sysfs);
     394                 :            : 
     395                 :          0 :                         r = unit_name_replace_instance(word, escaped, &k);
     396         [ #  # ]:          0 :                         if (r < 0)
     397         [ #  # ]:          0 :                                 return log_unit_error_errno(u, r, "Failed to build %s instance of template %s: %m", escaped, word);
     398                 :            :                 } else {
     399                 :            :                         /* If this is not a template, then let's mangle it so, that it becomes a valid unit name. */
     400                 :            : 
     401                 :          0 :                         r = unit_name_mangle(word, UNIT_NAME_MANGLE_WARN, &k);
     402         [ #  # ]:          0 :                         if (r < 0)
     403         [ #  # ]:          0 :                                 return log_unit_error_errno(u, r, "Failed to mangle unit name \"%s\": %m", word);
     404                 :            :                 }
     405                 :            : 
     406                 :          0 :                 r = unit_add_dependency_by_name(u, UNIT_WANTS, k, true, UNIT_DEPENDENCY_UDEV);
     407         [ #  # ]:          0 :                 if (r < 0)
     408         [ #  # ]:          0 :                         return log_unit_error_errno(u, r, "Failed to add Wants= dependency: %m");
     409                 :            : 
     410                 :          0 :                 r = strv_push(&added, k);
     411         [ #  # ]:          0 :                 if (r < 0)
     412                 :          0 :                         return log_oom();
     413                 :            : 
     414                 :          0 :                 k = NULL;
     415                 :            :         }
     416                 :            : 
     417         [ #  # ]:          0 :         if (d->state != DEVICE_DEAD) {
     418                 :            :                 char **i;
     419                 :            : 
     420                 :            :                 /* So here's a special hack, to compensate for the fact that the udev database's reload cycles are not
     421                 :            :                  * synchronized with our own reload cycles: when we detect that the SYSTEMD_WANTS property of a device
     422                 :            :                  * changes while the device unit is already up, let's manually trigger any new units listed in it not
     423                 :            :                  * seen before. This typically happens during the boot-time switch root transition, as udev devices
     424                 :            :                  * will generally already be up in the initrd, but SYSTEMD_WANTS properties get then added through udev
     425                 :            :                  * rules only available on the host system, and thus only when the initial udev coldplug trigger runs.
     426                 :            :                  *
     427                 :            :                  * We do this only if the device has been up already when we parse this, as otherwise the usual
     428                 :            :                  * dependency logic that is run from the dead → plugged transition will trigger these deps. */
     429                 :            : 
     430   [ #  #  #  # ]:          0 :                 STRV_FOREACH(i, added) {
     431         [ #  # ]:          0 :                         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
     432                 :            : 
     433         [ #  # ]:          0 :                         if (strv_contains(d->wants_property, *i)) /* Was this unit already listed before? */
     434                 :          0 :                                 continue;
     435                 :            : 
     436                 :          0 :                         r = manager_add_job_by_name(u->manager, JOB_START, *i, JOB_FAIL, NULL, &error, NULL);
     437         [ #  # ]:          0 :                         if (r < 0)
     438         [ #  # ]:          0 :                                 log_unit_warning_errno(u, r, "Failed to enqueue SYSTEMD_WANTS= job, ignoring: %s", bus_error_message(&error, r));
     439                 :            :                 }
     440                 :            :         }
     441                 :            : 
     442                 :          0 :         strv_free(d->wants_property);
     443                 :          0 :         d->wants_property = TAKE_PTR(added);
     444                 :            : 
     445                 :          0 :         return 0;
     446                 :            : }
     447                 :            : 
     448                 :       6116 : static bool device_is_bound_by_mounts(Device *d, sd_device *dev) {
     449                 :            :         const char *bound_by;
     450                 :            :         int r;
     451                 :            : 
     452         [ -  + ]:       6116 :         assert(d);
     453         [ -  + ]:       6116 :         assert(dev);
     454                 :            : 
     455         [ -  + ]:       6116 :         if (sd_device_get_property_value(dev, "SYSTEMD_MOUNT_DEVICE_BOUND", &bound_by) >= 0) {
     456                 :          0 :                 r = parse_boolean(bound_by);
     457         [ #  # ]:          0 :                 if (r < 0)
     458   [ #  #  #  #  :          0 :                         log_device_warning_errno(dev, r, "Failed to parse SYSTEMD_MOUNT_DEVICE_BOUND='%s' udev property, ignoring: %m", bound_by);
                   #  # ]
     459                 :            : 
     460                 :          0 :                 d->bind_mounts = r > 0;
     461                 :            :         } else
     462                 :       6116 :                 d->bind_mounts = false;
     463                 :            : 
     464                 :       6116 :         return d->bind_mounts;
     465                 :            : }
     466                 :            : 
     467                 :          0 : static void device_upgrade_mount_deps(Unit *u) {
     468                 :            :         Unit *other;
     469                 :            :         Iterator i;
     470                 :            :         void *v;
     471                 :            :         int r;
     472                 :            : 
     473                 :            :         /* Let's upgrade Requires= to BindsTo= on us. (Used when SYSTEMD_MOUNT_DEVICE_BOUND is set) */
     474                 :            : 
     475         [ #  # ]:          0 :         HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_REQUIRED_BY], i) {
     476         [ #  # ]:          0 :                 if (other->type != UNIT_MOUNT)
     477                 :          0 :                         continue;
     478                 :            : 
     479                 :          0 :                 r = unit_add_dependency(other, UNIT_BINDS_TO, u, true, UNIT_DEPENDENCY_UDEV);
     480         [ #  # ]:          0 :                 if (r < 0)
     481         [ #  # ]:          0 :                         log_unit_warning_errno(u, r, "Failed to add BindsTo= dependency between device and mount unit, ignoring: %m");
     482                 :            :         }
     483                 :          0 : }
     484                 :            : 
     485                 :       6116 : static int device_setup_unit(Manager *m, sd_device *dev, const char *path, bool main) {
     486                 :       6116 :         _cleanup_free_ char *e = NULL;
     487                 :       6116 :         const char *sysfs = NULL;
     488                 :       6116 :         Unit *u = NULL;
     489                 :            :         bool delete;
     490                 :            :         int r;
     491                 :            : 
     492         [ -  + ]:       6116 :         assert(m);
     493         [ -  + ]:       6116 :         assert(path);
     494                 :            : 
     495         [ +  - ]:       6116 :         if (dev) {
     496                 :       6116 :                 r = sd_device_get_syspath(dev, &sysfs);
     497         [ -  + ]:       6116 :                 if (r < 0) {
     498   [ #  #  #  #  :          0 :                         log_device_debug_errno(dev, r, "Couldn't get syspath from device, ignoring: %m");
                   #  # ]
     499                 :          0 :                         return 0;
     500                 :            :                 }
     501                 :            :         }
     502                 :            : 
     503                 :       6116 :         r = unit_name_from_path(path, ".device", &e);
     504         [ -  + ]:       6116 :         if (r < 0)
     505   [ #  #  #  #  :          0 :                 return log_device_error_errno(dev, r, "Failed to generate unit name from device path: %m");
                   #  # ]
     506                 :            : 
     507                 :       6116 :         u = manager_get_unit(m, e);
     508         [ +  + ]:       6116 :         if (u) {
     509                 :            :                 /* The device unit can still be present even if the device was unplugged: a mount unit can reference it
     510                 :            :                  * hence preventing the GC to have garbaged it. That's desired since the device unit may have a
     511                 :            :                  * dependency on the mount unit which was added during the loading of the later. When the device is
     512                 :            :                  * plugged the sysfs might not be initialized yet, as we serialize the device's state but do not
     513                 :            :                  * serialize the sysfs path across reloads/reexecs. Hence, when coming back from a reload/restart we
     514                 :            :                  * might have the state valid, but not the sysfs path. Hence, let's filter out conflicting devices, but
     515                 :            :                  * let's accept devices in any state with no sysfs path set. */
     516                 :            : 
     517         [ -  + ]:        220 :                 if (DEVICE(u)->state == DEVICE_PLUGGED &&
     518   [ #  #  #  # ]:          0 :                     DEVICE(u)->sysfs &&
     519                 :          0 :                     sysfs &&
     520         [ #  # ]:          0 :                     !path_equal(DEVICE(u)->sysfs, sysfs)) {
     521         [ #  # ]:          0 :                         log_unit_debug(u, "Device %s appeared twice with different sysfs paths %s and %s, ignoring the latter.",
     522                 :            :                                        e, DEVICE(u)->sysfs, sysfs);
     523                 :          0 :                         return -EEXIST;
     524                 :            :                 }
     525                 :            : 
     526                 :        220 :                 delete = false;
     527                 :            : 
     528                 :            :                 /* Let's remove all dependencies generated due to udev properties. We'll re-add whatever is configured
     529                 :            :                  * now below. */
     530                 :        220 :                 unit_remove_dependencies(u, UNIT_DEPENDENCY_UDEV);
     531                 :            :         } else {
     532                 :       5896 :                 delete = true;
     533                 :            : 
     534                 :       5896 :                 r = unit_new_for_name(m, sizeof(Device), e, &u);
     535         [ -  + ]:       5896 :                 if (r < 0) {
     536   [ #  #  #  #  :          0 :                         log_device_error_errno(dev, r, "Failed to allocate device unit %s: %m", e);
                   #  # ]
     537                 :          0 :                         goto fail;
     538                 :            :                 }
     539                 :            : 
     540                 :       5896 :                 unit_add_to_load_queue(u);
     541                 :            :         }
     542                 :            : 
     543                 :            :         /* If this was created via some dependency and has not actually been seen yet ->sysfs will not be
     544                 :            :          * initialized. Hence initialize it if necessary. */
     545         [ +  - ]:       6116 :         if (sysfs) {
     546                 :       6116 :                 r = device_set_sysfs(DEVICE(u), sysfs);
     547         [ -  + ]:       6116 :                 if (r < 0) {
     548         [ #  # ]:          0 :                         log_unit_error_errno(u, r, "Failed to set sysfs path %s: %m", sysfs);
     549                 :          0 :                         goto fail;
     550                 :            :                 }
     551                 :            : 
     552                 :            :                 /* The additional systemd udev properties we only interpret for the main object */
     553         [ +  + ]:       6116 :                 if (main)
     554                 :       2332 :                         (void) device_add_udev_wants(u, dev);
     555                 :            :         }
     556                 :            : 
     557                 :       6116 :         (void) device_update_description(u, dev, path);
     558                 :            : 
     559                 :            :         /* So the user wants the mount units to be bound to the device but a mount unit might has been seen by systemd
     560                 :            :          * before the device appears on its radar. In this case the device unit is partially initialized and includes
     561                 :            :          * the deps on the mount unit but at that time the "bind mounts" flag wasn't not present. Fix this up now. */
     562   [ +  -  -  + ]:       6116 :         if (dev && device_is_bound_by_mounts(DEVICE(u), dev))
     563                 :          0 :                 device_upgrade_mount_deps(u);
     564                 :            : 
     565                 :            :         /* Note that this won't dispatch the load queue, the caller has to do that if needed and appropriate */
     566                 :       6116 :         unit_add_to_dbus_queue(u);
     567                 :            : 
     568                 :       6116 :         return 0;
     569                 :            : 
     570                 :          0 : fail:
     571         [ #  # ]:          0 :         if (delete)
     572                 :          0 :                 unit_free(u);
     573                 :            : 
     574                 :          0 :         return r;
     575                 :            : }
     576                 :            : 
     577                 :       2332 : static int device_process_new(Manager *m, sd_device *dev) {
     578                 :            :         const char *sysfs, *dn, *alias;
     579                 :            :         dev_t devnum;
     580                 :            :         int r;
     581                 :            : 
     582         [ -  + ]:       2332 :         assert(m);
     583                 :            : 
     584         [ -  + ]:       2332 :         if (sd_device_get_syspath(dev, &sysfs) < 0)
     585                 :          0 :                 return 0;
     586                 :            : 
     587                 :            :         /* Add the main unit named after the sysfs path */
     588                 :       2332 :         r = device_setup_unit(m, dev, sysfs, true);
     589         [ -  + ]:       2332 :         if (r < 0)
     590                 :          0 :                 return r;
     591                 :            : 
     592                 :            :         /* Add an additional unit for the device node */
     593         [ +  + ]:       2332 :         if (sd_device_get_devname(dev, &dn) >= 0)
     594                 :       1760 :                 (void) device_setup_unit(m, dev, dn, false);
     595                 :            : 
     596                 :            :         /* Add additional units for all symlinks */
     597         [ +  + ]:       2332 :         if (sd_device_get_devnum(dev, &devnum) >= 0) {
     598                 :            :                 const char *p;
     599                 :            : 
     600         [ +  + ]:       3168 :                 FOREACH_DEVICE_DEVLINK(dev, p) {
     601                 :            :                         struct stat st;
     602                 :            : 
     603         [ -  + ]:       1408 :                         if (PATH_STARTSWITH_SET(p, "/dev/block/", "/dev/char/"))
     604                 :          0 :                                 continue;
     605                 :            : 
     606                 :            :                         /* Verify that the symlink in the FS actually belongs
     607                 :            :                          * to this device. This is useful to deal with
     608                 :            :                          * conflicting devices, e.g. when two disks want the
     609                 :            :                          * same /dev/disk/by-label/xxx link because they have
     610                 :            :                          * the same label. We want to make sure that the same
     611                 :            :                          * device that won the symlink wins in systemd, so we
     612                 :            :                          * check the device node major/minor */
     613         [ +  - ]:       1408 :                         if (stat(p, &st) >= 0 &&
     614   [ -  +  #  # ]:       1408 :                             ((!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) ||
     615         [ -  + ]:       1408 :                              st.st_rdev != devnum))
     616                 :          0 :                                 continue;
     617                 :            : 
     618                 :       1408 :                         (void) device_setup_unit(m, dev, p, false);
     619                 :            :                 }
     620                 :            :         }
     621                 :            : 
     622                 :            :         /* Add additional units for all explicitly configured aliases */
     623         [ +  + ]:       2332 :         if (sd_device_get_property_value(dev, "SYSTEMD_ALIAS", &alias) < 0)
     624                 :       1980 :                 return 0;
     625                 :            : 
     626                 :        396 :         for (;;) {
     627      [ +  +  - ]:        748 :                 _cleanup_free_ char *word = NULL;
     628                 :            : 
     629                 :        748 :                 r = extract_first_word(&alias, &word, NULL, EXTRACT_UNQUOTE);
     630         [ +  + ]:        748 :                 if (r == 0)
     631                 :        352 :                         break;
     632         [ -  + ]:        396 :                 if (r == -ENOMEM)
     633                 :          0 :                         return log_oom();
     634         [ -  + ]:        396 :                 if (r < 0)
     635   [ #  #  #  #  :          0 :                         return log_device_warning_errno(dev, r, "Failed to parse SYSTEMD_ALIAS property: %m");
                   #  # ]
     636                 :            : 
     637         [ -  + ]:        396 :                 if (!path_is_absolute(word))
     638   [ #  #  #  #  :          0 :                         log_device_warning(dev, "SYSTEMD_ALIAS is not an absolute path, ignoring: %s", word);
                   #  # ]
     639         [ -  + ]:        396 :                 else if (!path_is_normalized(word))
     640   [ #  #  #  #  :          0 :                         log_device_warning(dev, "SYSTEMD_ALIAS is not a normalized path, ignoring: %s", word);
                   #  # ]
     641                 :            :                 else
     642                 :        396 :                         (void) device_setup_unit(m, dev, word, false);
     643                 :            :         }
     644                 :            : 
     645                 :        352 :         return 0;
     646                 :            : }
     647                 :            : 
     648                 :       5896 : static void device_found_changed(Device *d, DeviceFound previous, DeviceFound now) {
     649         [ -  + ]:       5896 :         assert(d);
     650                 :            : 
     651                 :            :         /* Didn't exist before, but does now? if so, generate a new invocation ID for it */
     652   [ +  -  +  - ]:       5896 :         if (previous == DEVICE_NOT_FOUND && now != DEVICE_NOT_FOUND)
     653         [ +  - ]:       5896 :                 (void) unit_acquire_invocation_id(UNIT(d));
     654                 :            : 
     655         [ +  + ]:       5896 :         if (FLAGS_SET(now, DEVICE_FOUND_UDEV))
     656                 :            :                 /* When the device is known to udev we consider it plugged. */
     657                 :       5852 :                 device_set_state(d, DEVICE_PLUGGED);
     658   [ +  -  +  - ]:         44 :         else if (now != DEVICE_NOT_FOUND && !FLAGS_SET(previous, DEVICE_FOUND_UDEV))
     659                 :            :                 /* If the device has not been seen by udev yet, but is now referenced by the kernel, then we assume the
     660                 :            :                  * kernel knows it now, and udev might soon too. */
     661                 :         44 :                 device_set_state(d, DEVICE_TENTATIVE);
     662                 :            :         else
     663                 :            :                 /* If nobody sees the device, or if the device was previously seen by udev and now is only referenced
     664                 :            :                  * from the kernel, then we consider the device is gone, the kernel just hasn't noticed it yet. */
     665                 :          0 :                 device_set_state(d, DEVICE_DEAD);
     666                 :       5896 : }
     667                 :            : 
     668                 :      11968 : static void device_update_found_one(Device *d, DeviceFound found, DeviceFound mask) {
     669                 :            :         Manager *m;
     670                 :            : 
     671         [ -  + ]:      11968 :         assert(d);
     672                 :            : 
     673         [ +  - ]:      11968 :         m = UNIT(d)->manager;
     674                 :            : 
     675   [ +  +  +  -  :      17864 :         if (MANAGER_IS_RUNNING(m) && (m->honor_device_enumeration || MANAGER_IS_USER(m))) {
                   +  - ]
     676                 :            :                 DeviceFound n, previous;
     677                 :            : 
     678                 :            :                 /* When we are already running, then apply the new mask right-away, and trigger state changes
     679                 :            :                  * right-away */
     680                 :            : 
     681                 :       5896 :                 n = (d->found & ~mask) | (found & mask);
     682         [ -  + ]:       5896 :                 if (n == d->found)
     683                 :          0 :                         return;
     684                 :            : 
     685                 :       5896 :                 previous = d->found;
     686                 :       5896 :                 d->found = n;
     687                 :            : 
     688                 :       5896 :                 device_found_changed(d, previous, n);
     689                 :            :         } else
     690                 :            :                 /* We aren't running yet, let's apply the new mask to the shadow variable instead, which we'll apply as
     691                 :            :                  * soon as we catch-up with the state. */
     692                 :       6072 :                 d->enumerated_found = (d->enumerated_found & ~mask) | (found & mask);
     693                 :            : }
     694                 :            : 
     695                 :       2332 : static void device_update_found_by_sysfs(Manager *m, const char *sysfs, DeviceFound found, DeviceFound mask) {
     696                 :            :         Device *d, *l, *n;
     697                 :            : 
     698         [ -  + ]:       2332 :         assert(m);
     699         [ -  + ]:       2332 :         assert(sysfs);
     700                 :            : 
     701         [ -  + ]:       2332 :         if (mask == 0)
     702                 :          0 :                 return;
     703                 :            : 
     704                 :       2332 :         l = hashmap_get(m->devices_by_sysfs, sysfs);
     705         [ +  + ]:       8184 :         LIST_FOREACH_SAFE(same_sysfs, d, n, l)
     706                 :       5852 :                 device_update_found_one(d, found, mask);
     707                 :            : }
     708                 :            : 
     709                 :        220 : static int device_update_found_by_name(Manager *m, const char *path, DeviceFound found, DeviceFound mask) {
     710                 :        220 :         _cleanup_free_ char *e = NULL;
     711                 :            :         Unit *u;
     712                 :            :         int r;
     713                 :            : 
     714         [ -  + ]:        220 :         assert(m);
     715         [ -  + ]:        220 :         assert(path);
     716                 :            : 
     717         [ -  + ]:        220 :         if (mask == 0)
     718                 :          0 :                 return 0;
     719                 :            : 
     720                 :        220 :         r = unit_name_from_path(path, ".device", &e);
     721         [ -  + ]:        220 :         if (r < 0)
     722         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to generate unit name from device path: %m");
     723                 :            : 
     724                 :        220 :         u = manager_get_unit(m, e);
     725         [ -  + ]:        220 :         if (!u)
     726                 :          0 :                 return 0;
     727                 :            : 
     728                 :        220 :         device_update_found_one(DEVICE(u), found, mask);
     729                 :        220 :         return 0;
     730                 :            : }
     731                 :            : 
     732                 :       2464 : static bool device_is_ready(sd_device *dev) {
     733                 :            :         const char *ready;
     734                 :            : 
     735         [ -  + ]:       2464 :         assert(dev);
     736                 :            : 
     737         [ -  + ]:       2464 :         if (device_is_renaming(dev) > 0)
     738                 :          0 :                 return false;
     739                 :            : 
     740         [ +  + ]:       2464 :         if (sd_device_get_property_value(dev, "SYSTEMD_READY", &ready) < 0)
     741                 :       2288 :                 return true;
     742                 :            : 
     743                 :        176 :         return parse_boolean(ready) != 0;
     744                 :            : }
     745                 :            : 
     746                 :       3216 : static Unit *device_following(Unit *u) {
     747                 :       3216 :         Device *d = DEVICE(u);
     748                 :       3216 :         Device *other, *first = NULL;
     749                 :            : 
     750         [ -  + ]:       3216 :         assert(d);
     751                 :            : 
     752         [ +  + ]:       3216 :         if (startswith(u->id, "sys-"))
     753                 :       1440 :                 return NULL;
     754                 :            : 
     755                 :            :         /* Make everybody follow the unit that's named after the sysfs path */
     756         [ +  + ]:       3600 :         LIST_FOREACH_AFTER(same_sysfs, other, d)
     757   [ +  -  +  + ]:       3480 :                 if (startswith(UNIT(other)->id, "sys-"))
     758         [ +  - ]:       1656 :                         return UNIT(other);
     759                 :            : 
     760         [ +  + ]:        120 :         LIST_FOREACH_BEFORE(same_sysfs, other, d) {
     761   [ +  -  +  - ]:         96 :                 if (startswith(UNIT(other)->id, "sys-"))
     762         [ +  - ]:         96 :                         return UNIT(other);
     763                 :            : 
     764                 :          0 :                 first = other;
     765                 :            :         }
     766                 :            : 
     767         [ -  + ]:         24 :         return UNIT(first);
     768                 :            : }
     769                 :            : 
     770                 :       3216 : static int device_following_set(Unit *u, Set **_set) {
     771                 :       3216 :         Device *d = DEVICE(u), *other;
     772                 :       3216 :         _cleanup_set_free_ Set *set = NULL;
     773                 :            :         int r;
     774                 :            : 
     775         [ -  + ]:       3216 :         assert(d);
     776         [ -  + ]:       3216 :         assert(_set);
     777                 :            : 
     778   [ +  +  +  + ]:       3216 :         if (LIST_JUST_US(same_sysfs, d)) {
     779                 :        168 :                 *_set = NULL;
     780                 :        168 :                 return 0;
     781                 :            :         }
     782                 :            : 
     783                 :       3048 :         set = set_new(NULL);
     784         [ -  + ]:       3048 :         if (!set)
     785                 :          0 :                 return -ENOMEM;
     786                 :            : 
     787         [ +  + ]:       7272 :         LIST_FOREACH_AFTER(same_sysfs, other, d) {
     788                 :       4224 :                 r = set_put(set, other);
     789         [ -  + ]:       4224 :                 if (r < 0)
     790                 :          0 :                         return r;
     791                 :            :         }
     792                 :            : 
     793         [ +  + ]:       7272 :         LIST_FOREACH_BEFORE(same_sysfs, other, d) {
     794                 :       4224 :                 r = set_put(set, other);
     795         [ -  + ]:       4224 :                 if (r < 0)
     796                 :          0 :                         return r;
     797                 :            :         }
     798                 :            : 
     799                 :       3048 :         *_set = TAKE_PTR(set);
     800                 :       3048 :         return 1;
     801                 :            : }
     802                 :            : 
     803                 :         56 : static void device_shutdown(Manager *m) {
     804         [ -  + ]:         56 :         assert(m);
     805                 :            : 
     806                 :         56 :         m->device_monitor = sd_device_monitor_unref(m->device_monitor);
     807                 :         56 :         m->devices_by_sysfs = hashmap_free(m->devices_by_sysfs);
     808                 :         56 : }
     809                 :            : 
     810                 :         44 : static void device_enumerate(Manager *m) {
     811         [ -  + ]:         44 :         _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
     812                 :            :         sd_device *dev;
     813                 :            :         int r;
     814                 :            : 
     815         [ -  + ]:         44 :         assert(m);
     816                 :            : 
     817         [ +  - ]:         44 :         if (!m->device_monitor) {
     818                 :         44 :                 r = sd_device_monitor_new(&m->device_monitor);
     819         [ -  + ]:         44 :                 if (r < 0) {
     820         [ #  # ]:          0 :                         log_error_errno(r, "Failed to allocate device monitor: %m");
     821                 :          0 :                         goto fail;
     822                 :            :                 }
     823                 :            : 
     824                 :            :                 /* This will fail if we are unprivileged, but that
     825                 :            :                  * should not matter much, as user instances won't run
     826                 :            :                  * during boot. */
     827                 :         44 :                 (void) sd_device_monitor_set_receive_buffer_size(m->device_monitor, 128*1024*1024);
     828                 :            : 
     829                 :         44 :                 r = sd_device_monitor_filter_add_match_tag(m->device_monitor, "systemd");
     830         [ -  + ]:         44 :                 if (r < 0) {
     831         [ #  # ]:          0 :                         log_error_errno(r, "Failed to add udev tag match: %m");
     832                 :          0 :                         goto fail;
     833                 :            :                 }
     834                 :            : 
     835                 :         44 :                 r = sd_device_monitor_attach_event(m->device_monitor, m->event);
     836         [ -  + ]:         44 :                 if (r < 0) {
     837         [ #  # ]:          0 :                         log_error_errno(r, "Failed to attach event to device monitor: %m");
     838                 :          0 :                         goto fail;
     839                 :            :                 }
     840                 :            : 
     841                 :         44 :                 r = sd_device_monitor_start(m->device_monitor, device_dispatch_io, m);
     842         [ -  + ]:         44 :                 if (r < 0) {
     843         [ #  # ]:          0 :                         log_error_errno(r, "Failed to start device monitor: %m");
     844                 :          0 :                         goto fail;
     845                 :            :                 }
     846                 :            :         }
     847                 :            : 
     848                 :         44 :         r = sd_device_enumerator_new(&e);
     849         [ -  + ]:         44 :         if (r < 0) {
     850         [ #  # ]:          0 :                 log_error_errno(r, "Failed to allocate device enumerator: %m");
     851                 :          0 :                 goto fail;
     852                 :            :         }
     853                 :            : 
     854                 :         44 :         r = sd_device_enumerator_add_match_tag(e, "systemd");
     855         [ -  + ]:         44 :         if (r < 0) {
     856         [ #  # ]:          0 :                 log_error_errno(r, "Failed to set tag for device enumeration: %m");
     857                 :          0 :                 goto fail;
     858                 :            :         }
     859                 :            : 
     860         [ +  + ]:       2508 :         FOREACH_DEVICE(e, dev) {
     861                 :            :                 const char *sysfs;
     862                 :            : 
     863         [ +  + ]:       2464 :                 if (!device_is_ready(dev))
     864                 :        132 :                         continue;
     865                 :            : 
     866                 :       2332 :                 (void) device_process_new(m, dev);
     867                 :            : 
     868         [ -  + ]:       2332 :                 if (sd_device_get_syspath(dev, &sysfs) < 0)
     869                 :          0 :                         continue;
     870                 :            : 
     871                 :       2332 :                 device_update_found_by_sysfs(m, sysfs, DEVICE_FOUND_UDEV, DEVICE_FOUND_UDEV);
     872                 :            :         }
     873                 :            : 
     874                 :         44 :         return;
     875                 :            : 
     876                 :          0 : fail:
     877                 :          0 :         device_shutdown(m);
     878                 :            : }
     879                 :            : 
     880                 :          0 : static void device_propagate_reload_by_sysfs(Manager *m, const char *sysfs) {
     881                 :            :         Device *d, *l, *n;
     882                 :            :         int r;
     883                 :            : 
     884         [ #  # ]:          0 :         assert(m);
     885         [ #  # ]:          0 :         assert(sysfs);
     886                 :            : 
     887                 :          0 :         l = hashmap_get(m->devices_by_sysfs, sysfs);
     888         [ #  # ]:          0 :         LIST_FOREACH_SAFE(same_sysfs, d, n, l) {
     889         [ #  # ]:          0 :                 if (d->state == DEVICE_DEAD)
     890                 :          0 :                         continue;
     891                 :            : 
     892         [ #  # ]:          0 :                 r = manager_propagate_reload(m, UNIT(d), JOB_REPLACE, NULL);
     893         [ #  # ]:          0 :                 if (r < 0)
     894         [ #  # ]:          0 :                         log_warning_errno(r, "Failed to propagate reload, ignoring: %m");
     895                 :            :         }
     896                 :          0 : }
     897                 :            : 
     898                 :          0 : static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void *userdata) {
     899                 :          0 :         Manager *m = userdata;
     900                 :            :         DeviceAction action;
     901                 :            :         const char *sysfs;
     902                 :            :         int r;
     903                 :            : 
     904         [ #  # ]:          0 :         assert(m);
     905         [ #  # ]:          0 :         assert(dev);
     906                 :            : 
     907                 :          0 :         r = sd_device_get_syspath(dev, &sysfs);
     908         [ #  # ]:          0 :         if (r < 0) {
     909   [ #  #  #  #  :          0 :                 log_device_error_errno(dev, r, "Failed to get device sys path: %m");
                   #  # ]
     910                 :          0 :                 return 0;
     911                 :            :         }
     912                 :            : 
     913                 :          0 :         r = device_get_action(dev, &action);
     914         [ #  # ]:          0 :         if (r < 0) {
     915   [ #  #  #  #  :          0 :                 log_device_error_errno(dev, r, "Failed to get udev action: %m");
                   #  # ]
     916                 :          0 :                 return 0;
     917                 :            :         }
     918                 :            : 
     919         [ #  # ]:          0 :         if (action == DEVICE_ACTION_CHANGE)
     920                 :          0 :                 device_propagate_reload_by_sysfs(m, sysfs);
     921                 :            : 
     922                 :            :         /* A change event can signal that a device is becoming ready, in particular if
     923                 :            :          * the device is using the SYSTEMD_READY logic in udev
     924                 :            :          * so we need to reach the else block of the following if, even for change events */
     925         [ #  # ]:          0 :         if (action == DEVICE_ACTION_REMOVE) {
     926                 :          0 :                 r = swap_process_device_remove(m, dev);
     927         [ #  # ]:          0 :                 if (r < 0)
     928   [ #  #  #  #  :          0 :                         log_device_warning_errno(dev, r, "Failed to process swap device remove event, ignoring: %m");
                   #  # ]
     929                 :            : 
     930                 :            :                 /* If we get notified that a device was removed by
     931                 :            :                  * udev, then it's completely gone, hence unset all
     932                 :            :                  * found bits */
     933                 :          0 :                 device_update_found_by_sysfs(m, sysfs, 0, DEVICE_FOUND_UDEV|DEVICE_FOUND_MOUNT|DEVICE_FOUND_SWAP);
     934                 :            : 
     935         [ #  # ]:          0 :         } else if (device_is_ready(dev)) {
     936                 :            : 
     937                 :          0 :                 (void) device_process_new(m, dev);
     938                 :            : 
     939                 :          0 :                 r = swap_process_device_new(m, dev);
     940         [ #  # ]:          0 :                 if (r < 0)
     941   [ #  #  #  #  :          0 :                         log_device_warning_errno(dev, r, "Failed to process swap device new event, ignoring: %m");
                   #  # ]
     942                 :            : 
     943                 :          0 :                 manager_dispatch_load_queue(m);
     944                 :            : 
     945                 :            :                 /* The device is found now, set the udev found bit */
     946                 :          0 :                 device_update_found_by_sysfs(m, sysfs, DEVICE_FOUND_UDEV, DEVICE_FOUND_UDEV);
     947                 :            : 
     948                 :            :         } else {
     949                 :            :                 /* The device is nominally around, but not ready for
     950                 :            :                  * us. Hence unset the udev bit, but leave the rest
     951                 :            :                  * around. */
     952                 :            : 
     953                 :          0 :                 device_update_found_by_sysfs(m, sysfs, 0, DEVICE_FOUND_UDEV);
     954                 :            :         }
     955                 :            : 
     956                 :          0 :         return 0;
     957                 :            : }
     958                 :            : 
     959                 :       1980 : static bool device_supported(void) {
     960                 :            :         static int read_only = -1;
     961                 :            : 
     962                 :            :         /* If /sys is read-only we don't support device units, and any
     963                 :            :          * attempts to start one should fail immediately. */
     964                 :            : 
     965         [ +  + ]:       1980 :         if (read_only < 0)
     966                 :         20 :                 read_only = path_is_read_only_fs("/sys");
     967                 :            : 
     968                 :       1980 :         return read_only <= 0;
     969                 :            : }
     970                 :            : 
     971                 :       1760 : static int validate_node(Manager *m, const char *node, sd_device **ret) {
     972                 :            :         struct stat st;
     973                 :            :         int r;
     974                 :            : 
     975         [ -  + ]:       1760 :         assert(m);
     976         [ -  + ]:       1760 :         assert(node);
     977         [ -  + ]:       1760 :         assert(ret);
     978                 :            : 
     979                 :            :         /* Validates a device node that showed up in /proc/swaps or /proc/self/mountinfo if it makes sense for us to
     980                 :            :          * track. Note that this validator is fine within missing device nodes, but not with badly set up ones! */
     981                 :            : 
     982         [ +  + ]:       1760 :         if (!path_startswith(node, "/dev")) {
     983                 :       1540 :                 *ret = NULL;
     984                 :       1540 :                 return 0; /* bad! */
     985                 :            :         }
     986                 :            : 
     987         [ -  + ]:        220 :         if (stat(node, &st) < 0) {
     988         [ #  # ]:          0 :                 if (errno != ENOENT)
     989         [ #  # ]:          0 :                         return log_error_errno(errno, "Failed to stat() device node file %s: %m", node);
     990                 :            : 
     991                 :          0 :                 *ret = NULL;
     992                 :          0 :                 return 1; /* good! (though missing) */
     993                 :            : 
     994                 :            :         } else {
     995                 :        220 :                 _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
     996                 :            : 
     997                 :        220 :                 r = device_new_from_stat_rdev(&dev, &st);
     998         [ -  + ]:        220 :                 if (r == -ENOENT) {
     999                 :          0 :                         *ret = NULL;
    1000                 :          0 :                         return 1; /* good! (though missing) */
    1001         [ -  + ]:        220 :                 } else if (r == -ENOTTY) {
    1002                 :          0 :                         *ret = NULL;
    1003                 :          0 :                         return 0; /* bad! (not a device node but some other kind of file system node) */
    1004         [ -  + ]:        220 :                 } else if (r < 0)
    1005         [ #  # ]:          0 :                         return log_error_errno(r, "Failed to get udev device from devnum %u:%u: %m", major(st.st_rdev), minor(st.st_rdev));
    1006                 :            : 
    1007                 :        220 :                 *ret = TAKE_PTR(dev);
    1008                 :        220 :                 return 1; /* good! */
    1009                 :            :         }
    1010                 :            : }
    1011                 :            : 
    1012                 :       1760 : void device_found_node(Manager *m, const char *node, DeviceFound found, DeviceFound mask) {
    1013                 :            :         int r;
    1014                 :            : 
    1015         [ -  + ]:       1760 :         assert(m);
    1016         [ -  + ]:       1760 :         assert(node);
    1017                 :            : 
    1018         [ -  + ]:       1760 :         if (!device_supported())
    1019                 :          0 :                 return;
    1020                 :            : 
    1021         [ -  + ]:       1760 :         if (mask == 0)
    1022                 :          0 :                 return;
    1023                 :            : 
    1024                 :            :         /* This is called whenever we find a device referenced in /proc/swaps or /proc/self/mounts. Such a device might
    1025                 :            :          * be mounted/enabled at a time where udev has not finished probing it yet, and we thus haven't learned about
    1026                 :            :          * it yet. In this case we will set the device unit to "tentative" state.
    1027                 :            :          *
    1028                 :            :          * This takes a pair of DeviceFound flags parameters. The 'mask' parameter is a bit mask that indicates which
    1029                 :            :          * bits of 'found' to copy into the per-device DeviceFound flags field. Thus, this function may be used to set
    1030                 :            :          * and unset individual bits in a single call, while merging partially with previous state. */
    1031                 :            : 
    1032         [ +  - ]:       1760 :         if ((found & mask) != 0) {
    1033         [ +  + ]:       1760 :                 _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
    1034                 :            : 
    1035                 :            :                 /* If the device is known in the kernel and newly appeared, then we'll create a device unit for it,
    1036                 :            :                  * under the name referenced in /proc/swaps or /proc/self/mountinfo. But first, let's validate if
    1037                 :            :                  * everything is alright with the device node. */
    1038                 :            : 
    1039                 :       1760 :                 r = validate_node(m, node, &dev);
    1040         [ +  + ]:       1760 :                 if (r <= 0)
    1041                 :       1540 :                         return; /* Don't create a device unit for this if the device node is borked. */
    1042                 :            : 
    1043                 :        220 :                 (void) device_setup_unit(m, dev, node, false);
    1044                 :            :         }
    1045                 :            : 
    1046                 :            :         /* Update the device unit's state, should it exist */
    1047                 :        220 :         (void) device_update_found_by_name(m, node, found, mask);
    1048                 :            : }
    1049                 :            : 
    1050                 :        132 : bool device_shall_be_bound_by(Unit *device, Unit *u) {
    1051         [ -  + ]:        132 :         assert(device);
    1052         [ -  + ]:        132 :         assert(u);
    1053                 :            : 
    1054         [ -  + ]:        132 :         if (u->type != UNIT_MOUNT)
    1055                 :          0 :                 return false;
    1056                 :            : 
    1057                 :        132 :         return DEVICE(device)->bind_mounts;
    1058                 :            : }
    1059                 :            : 
    1060                 :            : const UnitVTable device_vtable = {
    1061                 :            :         .object_size = sizeof(Device),
    1062                 :            :         .sections =
    1063                 :            :                 "Unit\0"
    1064                 :            :                 "Device\0"
    1065                 :            :                 "Install\0",
    1066                 :            : 
    1067                 :            :         .gc_jobs = true,
    1068                 :            : 
    1069                 :            :         .init = device_init,
    1070                 :            :         .done = device_done,
    1071                 :            :         .load = device_load,
    1072                 :            : 
    1073                 :            :         .coldplug = device_coldplug,
    1074                 :            :         .catchup = device_catchup,
    1075                 :            : 
    1076                 :            :         .serialize = device_serialize,
    1077                 :            :         .deserialize_item = device_deserialize_item,
    1078                 :            : 
    1079                 :            :         .dump = device_dump,
    1080                 :            : 
    1081                 :            :         .active_state = device_active_state,
    1082                 :            :         .sub_state_to_string = device_sub_state_to_string,
    1083                 :            : 
    1084                 :            :         .bus_vtable = bus_device_vtable,
    1085                 :            : 
    1086                 :            :         .following = device_following,
    1087                 :            :         .following_set = device_following_set,
    1088                 :            : 
    1089                 :            :         .enumerate = device_enumerate,
    1090                 :            :         .shutdown = device_shutdown,
    1091                 :            :         .supported = device_supported,
    1092                 :            : 
    1093                 :            :         .status_message_formats = {
    1094                 :            :                 .starting_stopping = {
    1095                 :            :                         [0] = "Expecting device %s...",
    1096                 :            :                 },
    1097                 :            :                 .finished_start_job = {
    1098                 :            :                         [JOB_DONE]       = "Found device %s.",
    1099                 :            :                         [JOB_TIMEOUT]    = "Timed out waiting for device %s.",
    1100                 :            :                 },
    1101                 :            :         },
    1102                 :            : };

Generated by: LCOV version 1.14