[PATCH 08/10] base-manager: process initial kernel events from an input file

Dan Williams dcbw at redhat.com
Fri Aug 19 20:01:41 UTC 2016


On Sat, 2016-08-06 at 15:03 +0200, Aleksander Morgado wrote:
> In order to cope with devices already available in the system when
> the daemon
> starts, we allow loading a list of kernel events from an input text
> file where
> the kernel events were recorded since boot.

What's the use-case for this functionality?  It seems to me (though I
haven't thought deeply about it) that it's pretty much redundant with
the new mmcli commands.  Wouldn't this be better done in mmcli, parsing
the file and shoving the commands to MM?

Dan

> The file will contain one line per event, e.g.:
>   action=add, name=wwan0,    subsystem=net
>   action=add, name=cdc-wdm2, subsystem=usbmisc
> ---
>  src/main.c            |   1 +
>  src/mm-base-manager.c | 249 +++++++++++++++++++++++++++++++++-------
> ----------
>  src/mm-base-manager.h |   2 +
>  src/mm-context.c      |  21 ++++-
>  src/mm-context.h      |  19 ++--
>  5 files changed, 199 insertions(+), 93 deletions(-)
> 
> diff --git a/src/main.c b/src/main.c
> index 5e5628c..d83baaf 100644
> --- a/src/main.c
> +++ b/src/main.c
> @@ -87,6 +87,7 @@ bus_acquired_cb (GDBusConnection *connection,
>      manager = mm_base_manager_new (connection,
>                                     mm_context_get_test_plugin_dir
> (),
>                                     !mm_context_get_no_auto_scan (),
> +                                   mm_context_get_initial_kernel_eve
> nts (),
>                                     mm_context_get_test_enable (),
>                                     &error);
>      if (!manager) {
> diff --git a/src/mm-base-manager.c b/src/mm-base-manager.c
> index 528c5e9..72f5ffc 100644
> --- a/src/mm-base-manager.c
> +++ b/src/mm-base-manager.c
> @@ -53,6 +53,7 @@ enum {
>      PROP_AUTO_SCAN,
>      PROP_ENABLE_TEST,
>      PROP_PLUGIN_DIR,
> +    PROP_INITIAL_KERNEL_EVENTS,
>      LAST_PROP
>  };
>  
> @@ -65,6 +66,8 @@ struct _MMBaseManagerPrivate {
>      gboolean enable_test;
>      /* Path to look for plugins */
>      gchar *plugin_dir;
> +    /* Path to the list of initial kernel events */
> +    gchar *initial_kernel_events;
>      /* The authorization provider */
>      MMAuthProvider *authp;
>      GCancellable *authp_cancellable;
> @@ -311,6 +314,57 @@ device_added (MMBaseManager  *manager,
>      mm_device_grab_port (device, port);
>  }
>  
> +static gboolean
> +handle_kernel_event (MMBaseManager            *self,
> +                     MMKernelEventProperties  *properties,
> +                     GError                  **error)
> +{
> +    const gchar    *action;
> +    MMKernelDevice *kernel_device;
> +
> +    action = mm_kernel_event_properties_get_action (properties);
> +    if (g_strcmp0 (action, "add") != 0 && g_strcmp0 (action,
> "remove") != 0) {
> +        g_set_error (error, MM_CORE_ERROR,
> MM_CORE_ERROR_INVALID_ARGS, "Invalid action");
> +        return FALSE;
> +    }
> +
> +    mm_dbg ("Kernel event reported:");
> +    mm_dbg ("  action:      %s",     action);
> +    if (mm_kernel_event_properties_get_subsystem (properties))
> +        mm_dbg ("  subsystem:   %s",
> mm_kernel_event_properties_get_subsystem (properties));
> +    if (mm_kernel_event_properties_get_name (properties))
> +        mm_dbg ("  name:        %s",
> mm_kernel_event_properties_get_name (properties));
> +    if (mm_kernel_event_properties_get_driver (properties))
> +        mm_dbg ("  driver:      %s",
> mm_kernel_event_properties_get_driver (properties));
> +    if (mm_kernel_event_properties_get_physdev_uid (properties))
> +        mm_dbg ("  physdev-uid: %s",
> mm_kernel_event_properties_get_physdev_uid (properties));
> +    if (mm_kernel_event_properties_get_physdev_vid (properties))
> +        mm_dbg ("  physdev-vid: 0x%04X",
> mm_kernel_event_properties_get_physdev_vid (properties));
> +    if (mm_kernel_event_properties_get_physdev_pid (properties))
> +        mm_dbg ("  physdev-pid: 0x%04X",
> mm_kernel_event_properties_get_physdev_pid (properties));
> +    if (mm_kernel_event_properties_get_candidate (properties))
> +        mm_dbg ("  candidate:   yes");
> +
> +#if WITH_UDEV
> +    kernel_device = mm_kernel_device_udev_new_from_properties
> (properties, error);
> +#else
> +    kernel_device = mm_kernel_device_generic_new (properties,
> error);
> +#endif
> +
> +    if (!kernel_device)
> +        return FALSE;
> +
> +    if (g_strcmp0 (action, "add") == 0)
> +        device_added (self, kernel_device, TRUE, TRUE);
> +    else if (g_strcmp0 (action, "remove") == 0)
> +        device_removed (self, kernel_device);
> +    else
> +        g_assert_not_reached ();
> +    g_object_unref (kernel_device);
> +
> +    return TRUE;
> +}
> +
>  #if WITH_UDEV
>  
>  static void
> @@ -381,63 +435,116 @@ start_device_added (MMBaseManager *self,
>      g_idle_add ((GSourceFunc)start_device_added_idle, ctx);
>  }
>  
> +static void
> +process_scan (MMBaseManager *self,
> +              gboolean       manual_scan)
> +{
> +    GList *devices, *iter;
> +
> +    devices = g_udev_client_query_by_subsystem (self->priv->udev,
> "tty");
> +    for (iter = devices; iter; iter = g_list_next (iter)) {
> +        start_device_added (self, G_UDEV_DEVICE (iter->data),
> manual_scan);
> +        g_object_unref (G_OBJECT (iter->data));
> +    }
> +    g_list_free (devices);
> +
> +    devices = g_udev_client_query_by_subsystem (self->priv->udev,
> "net");
> +    for (iter = devices; iter; iter = g_list_next (iter)) {
> +        start_device_added (self, G_UDEV_DEVICE (iter->data),
> manual_scan);
> +        g_object_unref (G_OBJECT (iter->data));
> +    }
> +    g_list_free (devices);
> +
> +    devices = g_udev_client_query_by_subsystem (self->priv->udev,
> "usb");
> +    for (iter = devices; iter; iter = g_list_next (iter)) {
> +        const gchar *name;
> +
> +        name = g_udev_device_get_name (G_UDEV_DEVICE (iter->data));
> +        if (name && g_str_has_prefix (name, "cdc-wdm"))
> +            start_device_added (self, G_UDEV_DEVICE (iter->data),
> manual_scan);
> +        g_object_unref (G_OBJECT (iter->data));
> +    }
> +    g_list_free (devices);
> +
> +    /* Newer kernels report 'usbmisc' subsystem */
> +    devices = g_udev_client_query_by_subsystem (self->priv->udev,
> "usbmisc");
> +    for (iter = devices; iter; iter = g_list_next (iter)) {
> +        const gchar *name;
> +
> +        name = g_udev_device_get_name (G_UDEV_DEVICE (iter->data));
> +        if (name && g_str_has_prefix (name, "cdc-wdm"))
> +            start_device_added (self, G_UDEV_DEVICE (iter->data),
> manual_scan);
> +        g_object_unref (G_OBJECT (iter->data));
> +    }
> +    g_list_free (devices);
> +}
> +
>  #endif
>  
> -void
> -mm_base_manager_start (MMBaseManager *manager,
> -                       gboolean       manual_scan)
> +static void
> +process_initial_kernel_events (MMBaseManager *self)
>  {
> -    g_return_if_fail (manager != NULL);
> -    g_return_if_fail (MM_IS_BASE_MANAGER (manager));
> +    gchar *contents = NULL;
> +    gchar *line;
> +    GError *error = NULL;
>  
> -    if (!manager->priv->auto_scan && !manual_scan)
> +    if (!self->priv->initial_kernel_events)
>          return;
>  
> -#if WITH_UDEV
> -    {
> -        GList *devices, *iter;
> +    if (!g_file_get_contents (self->priv->initial_kernel_events,
> &contents, NULL, &error)) {
> +        g_warning ("Couldn't load initial kernel events: %s", error-
> >message);
> +        g_error_free (error);
> +        return;
> +    }
>  
> -        mm_dbg ("Starting %s device scan...", manual_scan ? "manual"
> : "automatic");
> +    line = contents;
> +    while (line) {
> +        gchar *next;
>  
> -        devices = g_udev_client_query_by_subsystem (manager->priv-
> >udev, "tty");
> -        for (iter = devices; iter; iter = g_list_next (iter)) {
> -            start_device_added (manager, G_UDEV_DEVICE (iter->data), 
> manual_scan);
> -            g_object_unref (G_OBJECT (iter->data));
> +        next = strchr (line, '\n');
> +        if (next) {
> +            *next = '\0';
> +            next++;
>          }
> -        g_list_free (devices);
>  
> -        devices = g_udev_client_query_by_subsystem (manager->priv-
> >udev, "net");
> -        for (iter = devices; iter; iter = g_list_next (iter)) {
> -            start_device_added (manager, G_UDEV_DEVICE (iter->data), 
> manual_scan);
> -            g_object_unref (G_OBJECT (iter->data));
> +        /* ignore empty lines */
> +        if (line[0] != '\0') {
> +            MMKernelEventProperties *properties;
> +
> +            properties = mm_kernel_event_properties_new_from_string
> (line, &error);
> +            if (!properties) {
> +                g_warning ("Couldn't parse line '%s' as initial
> kernel event %s", line, error->message);
> +                g_clear_error (&error);
> +            } else if (!handle_kernel_event (self, properties,
> &error)) {
> +                g_warning ("Couldn't process line '%s' as initial
> kernel event %s", line, error->message);
> +                g_clear_error (&error);
> +            } else
> +                g_debug ("Processed initial kernel event:' %s'",
> line);
>          }
> -        g_list_free (devices);
>  
> -        devices = g_udev_client_query_by_subsystem (manager->priv-
> >udev, "usb");
> -        for (iter = devices; iter; iter = g_list_next (iter)) {
> -            const gchar *name;
> -
> -            name = g_udev_device_get_name (G_UDEV_DEVICE (iter-
> >data));
> -            if (name && g_str_has_prefix (name, "cdc-wdm"))
> -                start_device_added (manager, G_UDEV_DEVICE (iter-
> >data), manual_scan);
> -            g_object_unref (G_OBJECT (iter->data));
> -        }
> -        g_list_free (devices);
> +        line = next;
> +    }
>  
> -        /* Newer kernels report 'usbmisc' subsystem */
> -        devices = g_udev_client_query_by_subsystem (manager->priv-
> >udev, "usbmisc");
> -        for (iter = devices; iter; iter = g_list_next (iter)) {
> -            const gchar *name;
> +    g_free (contents);
> +}
>  
> -            name = g_udev_device_get_name (G_UDEV_DEVICE (iter-
> >data));
> -            if (name && g_str_has_prefix (name, "cdc-wdm"))
> -                start_device_added (manager, G_UDEV_DEVICE (iter-
> >data), manual_scan);
> -            g_object_unref (G_OBJECT (iter->data));
> -        }
> -        g_list_free (devices);
> +void
> +mm_base_manager_start (MMBaseManager *self,
> +                       gboolean       manual_scan)
> +{
> +    g_return_if_fail (self != NULL);
> +    g_return_if_fail (MM_IS_BASE_MANAGER (self));
>  
> -        mm_dbg ("Finished device scan...");
> +    if (!self->priv->auto_scan && !manual_scan) {
> +        /* If we have a list of initial kernel events, process it
> now */
> +        process_initial_kernel_events (self);
> +        return;
>      }
> +
> +#if WITH_UDEV
> +    mm_dbg ("Starting %s device scan...", manual_scan ? "manual" :
> "automatic");
> +    process_scan (self, manual_scan);
> +    mm_dbg ("Finished device scan...");
>  #else
>      mm_dbg ("Unsupported %s device scan...", manual_scan ? "manual"
> : "automatic");
>  #endif
> @@ -677,8 +784,6 @@ report_kernel_event_auth_ready
> (MMAuthProvider           *authp,
>  {
>      GError                  *error = NULL;
>      MMKernelEventProperties *properties = NULL;
> -    MMKernelDevice          *kernel_device;
> -    const gchar             *action;
>  
>      if (!mm_auth_provider_authorize_finish (authp, res, &error))
>          goto out;
> @@ -696,45 +801,7 @@ report_kernel_event_auth_ready
> (MMAuthProvider           *authp,
>      if (!properties)
>          goto out;
>  
> -    action = mm_kernel_event_properties_get_action (properties);
> -    if (g_strcmp0 (action, "add") != 0 && g_strcmp0 (action,
> "remove") != 0) {
> -        error = g_error_new_literal (MM_CORE_ERROR,
> MM_CORE_ERROR_INVALID_ARGS, "Invalid action");
> -        goto out;
> -    }
> -
> -    mm_dbg ("Kernel event reported:");
> -    mm_dbg ("  action:      %s",     action);
> -    if (mm_kernel_event_properties_get_subsystem (properties))
> -        mm_dbg ("  subsystem:   %s",
> mm_kernel_event_properties_get_subsystem (properties));
> -    if (mm_kernel_event_properties_get_name (properties))
> -        mm_dbg ("  name:        %s",
> mm_kernel_event_properties_get_name (properties));
> -    if (mm_kernel_event_properties_get_driver (properties))
> -        mm_dbg ("  driver:      %s",
> mm_kernel_event_properties_get_driver (properties));
> -    if (mm_kernel_event_properties_get_physdev_uid (properties))
> -        mm_dbg ("  physdev-uid: %s",
> mm_kernel_event_properties_get_physdev_uid (properties));
> -    if (mm_kernel_event_properties_get_physdev_vid (properties))
> -        mm_dbg ("  physdev-vid: 0x%04X",
> mm_kernel_event_properties_get_physdev_vid (properties));
> -    if (mm_kernel_event_properties_get_physdev_pid (properties))
> -        mm_dbg ("  physdev-pid: 0x%04X",
> mm_kernel_event_properties_get_physdev_pid (properties));
> -    if (mm_kernel_event_properties_get_candidate (properties))
> -        mm_dbg ("  candidate:   yes");
> -
> -#if WITH_UDEV
> -    kernel_device = mm_kernel_device_udev_new_from_properties
> (properties, &error);
> -#else
> -    kernel_device = mm_kernel_device_generic_new (properties,
> &error);
> -#endif
> -
> -    if (!kernel_device)
> -        goto out;
> -
> -    if (g_strcmp0 (action, "add") == 0)
> -        device_added (ctx->self, kernel_device, TRUE, TRUE);
> -    else if (g_strcmp0 (action, "remove") == 0)
> -        device_removed (ctx->self, kernel_device);
> -    else
> -        g_assert_not_reached ();
> -    g_object_unref (kernel_device);
> +    handle_kernel_event (ctx->self, properties, &error);
>  
>  out:
>      if (error)
> @@ -840,6 +907,7 @@ MMBaseManager *
>  mm_base_manager_new (GDBusConnection *connection,
>                       const gchar *plugin_dir,
>                       gboolean auto_scan,
> +                     const gchar *initial_kernel_events,
>                       gboolean enable_test,
>                       GError **error)
>  {
> @@ -851,6 +919,7 @@ mm_base_manager_new (GDBusConnection *connection,
>                             MM_BASE_MANAGER_CONNECTION, connection,
>                             MM_BASE_MANAGER_PLUGIN_DIR, plugin_dir,
>                             MM_BASE_MANAGER_AUTO_SCAN, auto_scan,
> +                           MM_BASE_MANAGER_INITIAL_KERNEL_EVENTS,
> initial_kernel_events,
>                             MM_BASE_MANAGER_ENABLE_TEST, enable_test,
>                             NULL);
>  }
> @@ -896,6 +965,10 @@ set_property (GObject *object,
>          g_free (priv->plugin_dir);
>          priv->plugin_dir = g_value_dup_string (value);
>          break;
> +    case PROP_INITIAL_KERNEL_EVENTS:
> +        g_free (priv->initial_kernel_events);
> +        priv->initial_kernel_events = g_value_dup_string (value);
> +        break;
>      default:
>          G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
>          break;
> @@ -923,6 +996,9 @@ get_property (GObject *object,
>      case PROP_PLUGIN_DIR:
>          g_value_set_string (value, priv->plugin_dir);
>          break;
> +    case PROP_INITIAL_KERNEL_EVENTS:
> +        g_value_set_string (value, priv->initial_kernel_events);
> +        break;
>      default:
>          G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
>          break;
> @@ -1031,6 +1107,7 @@ finalize (GObject *object)
>  {
>      MMBaseManagerPrivate *priv = MM_BASE_MANAGER (object)->priv;
>  
> +    g_free (priv->initial_kernel_events);
>      g_free (priv->plugin_dir);
>  
>      g_hash_table_destroy (priv->devices);
> @@ -1112,4 +1189,12 @@ mm_base_manager_class_init (MMBaseManagerClass
> *manager_class)
>                                "Where to look for plugins",
>                                NULL,
>                                G_PARAM_READWRITE |
> G_PARAM_CONSTRUCT_ONLY));
> +
> +    g_object_class_install_property
> +        (object_class, PROP_INITIAL_KERNEL_EVENTS,
> +         g_param_spec_string (MM_BASE_MANAGER_INITIAL_KERNEL_EVENTS,
> +                              "Initial kernel events",
> +                              "Path to a file with the list of
> initial kernel events",
> +                              NULL,
> +                              G_PARAM_READWRITE |
> G_PARAM_CONSTRUCT_ONLY));
>  }
> diff --git a/src/mm-base-manager.h b/src/mm-base-manager.h
> index 43e7cae..56b3016 100644
> --- a/src/mm-base-manager.h
> +++ b/src/mm-base-manager.h
> @@ -34,6 +34,7 @@
>  #define MM_BASE_MANAGER_AUTO_SCAN   "auto-scan"   /* Construct-only
> */
>  #define MM_BASE_MANAGER_ENABLE_TEST "enable-test" /* Construct-only
> */
>  #define MM_BASE_MANAGER_PLUGIN_DIR  "plugin-dir"  /* Construct-only
> */
> +#define MM_BASE_MANAGER_INITIAL_KERNEL_EVENTS "initial-kernel-
> events" /* Construct-only */
>  
>  typedef struct _MMBaseManagerPrivate MMBaseManagerPrivate;
>  
> @@ -51,6 +52,7 @@ GType mm_base_manager_get_type (void);
>  MMBaseManager   *mm_base_manager_new         (GDBusConnection *bus,
>                                                const gchar
> *plugin_dir,
>                                                gboolean auto_scan,
> +                                              const gchar
> *initial_kernel_events,
>                                                gboolean enable_test,
>                                                GError **error);
>  
> diff --git a/src/mm-context.c b/src/mm-context.c
> index b6af1a3..9c0b3d0 100644
> --- a/src/mm-context.c
> +++ b/src/mm-context.c
> @@ -27,7 +27,7 @@ static const gchar *log_level;
>  static const gchar *log_file;
>  static gboolean show_ts;
>  static gboolean rel_ts;
> -
> +static const gchar *initial_kernel_events;
>  #if WITH_UDEV
>  static gboolean no_auto_scan;
>  #endif
> @@ -41,6 +41,9 @@ static const GOptionEntry entries[] = {
>      { "relative-timestamps", 0, 0, G_OPTION_ARG_NONE, &rel_ts, "Use
> relative timestamps (from MM start)", NULL },
>  #if WITH_UDEV
>      { "no-auto-scan", 0, 0, G_OPTION_ARG_NONE, &no_auto_scan, "Don't
> auto-scan looking for devices", NULL },
> +    { "initial-kernel-events", 0, 0, G_OPTION_ARG_FILENAME,
> &initial_kernel_events, "Path to initial kernel events file (requires
> --no-auto-scan)", "[PATH]" },
> +#else
> +    { "initial-kernel-events", 0, 0, G_OPTION_ARG_FILENAME,
> &initial_kernel_events, "Path to initial kernel events file",
> "[PATH]" },
>  #endif
>      { NULL }
>  };
> @@ -75,6 +78,12 @@ mm_context_get_relative_timestamps (void)
>      return rel_ts;
>  }
>  
> +const gchar *
> +mm_context_get_initial_kernel_events (void)
> +{
> +    return initial_kernel_events;
> +}
> +
>  gboolean
>  mm_context_get_no_auto_scan (void)
>  {
> @@ -159,7 +168,7 @@ mm_context_init (gint argc,
>      g_option_context_add_group (ctx, test_get_option_group ());
>  
>      if (!g_option_context_parse (ctx, &argc, &argv, &error)) {
> -        g_warning ("%s\n", error->message);
> +        g_warning ("error: %s", error->message);
>          g_error_free (error);
>          exit (1);
>      }
> @@ -176,4 +185,12 @@ mm_context_init (gint argc,
>      /* If just version requested, print and exit */
>      if (version_flag)
>          print_version ();
> +
> +    /* Initial kernel events processing may only be used if autoscan
> is disabled */
> +#if WITH_UDEV
> +    if (!no_auto_scan && initial_kernel_events) {
> +        g_warning ("error: --initial-kernel-events must be used only
> if --no-auto-scan is also used");
> +        exit (1);
> +    }
> +#endif
>  }
> diff --git a/src/mm-context.h b/src/mm-context.h
> index b2ba07f..63a8ec4 100644
> --- a/src/mm-context.h
> +++ b/src/mm-context.h
> @@ -26,16 +26,17 @@
>  void mm_context_init (gint argc,
>                        gchar **argv);
>  
> -gboolean     mm_context_get_debug               (void);
> -const gchar *mm_context_get_log_level           (void);
> -const gchar *mm_context_get_log_file            (void);
> -gboolean     mm_context_get_timestamps          (void);
> -gboolean     mm_context_get_relative_timestamps (void);
> -gboolean     mm_context_get_no_auto_scan        (void);
> +gboolean     mm_context_get_debug                 (void);
> +const gchar *mm_context_get_log_level             (void);
> +const gchar *mm_context_get_log_file              (void);
> +gboolean     mm_context_get_timestamps            (void);
> +gboolean     mm_context_get_relative_timestamps   (void);
> +const gchar *mm_context_get_initial_kernel_events (void);
> +gboolean     mm_context_get_no_auto_scan          (void);
>  
>  /* Testing support */
> -gboolean     mm_context_get_test_session        (void);
> -gboolean     mm_context_get_test_enable         (void);
> -const gchar *mm_context_get_test_plugin_dir     (void);
> +gboolean     mm_context_get_test_session    (void);
> +gboolean     mm_context_get_test_enable     (void);
> +const gchar *mm_context_get_test_plugin_dir (void);
>  
>  #endif /* MM_CONTEXT_H */


More information about the ModemManager-devel mailing list