Hi Zhenhua,

> Sometimes, Udev device 'remove' event could not report correct parent
> node of current udev_device. Current code replies on the devpath
> attached on the parent node to find modem and then remove it.
> 
> This fix is to change the way to store the devpath info into a
> hashtable. So that we search hashtable to get devpath and remove the
> modem.
> ---
>  plugins/udev.c |   59
>  +++++++++++++++++++++++++++++++++++++------------------ 1 files changed,
>  40 insertions(+), 19 deletions(-)
> 
> diff --git a/plugins/udev.c b/plugins/udev.c
> index 964ac65..6850bf9 100644
> --- a/plugins/udev.c
> +++ b/plugins/udev.c
> @@ -36,6 +36,7 @@
>  #include <ofono/log.h>
> 
>  static GSList *modem_list = NULL;
> +static GHashTable *devpath_list = NULL;
> 
>  static struct ofono_modem *find_modem(const char *devpath)
>  {
> @@ -258,7 +259,7 @@ static void add_modem(struct udev_device *udev_device)
>  {
>       struct ofono_modem *modem;
>       struct udev_device *parent;
> -     const char *devpath, *driver;
> +     const char *devpath, *curpath, *driver;
> 
>       parent = udev_device_get_parent(udev_device);
>       if (parent == NULL)
> @@ -294,6 +295,12 @@ static void add_modem(struct udev_device *udev_device)
>               modem_list = g_slist_prepend(modem_list, modem);
>       }
> 
> +     curpath = udev_device_get_devpath(udev_device);
> +     if (curpath == NULL)
> +             return;
> +
> +     g_hash_table_insert(devpath_list, g_strdup(curpath), g_strdup(devpath));
> +
>       if (g_strcmp0(driver, "mbm") == 0)
>               add_mbm(modem, udev_device);
>       else if (g_strcmp0(driver, "hso") == 0)
> @@ -306,30 +313,28 @@ static void add_modem(struct udev_device
>  *udev_device) add_novatel(modem, udev_device);
>  }
> 
> +static gboolean devpath_remove(gpointer key, gpointer value, gpointer
>  user_data) +{
> +     const char *path = value;
> +     const char *devpath = user_data;
> +
> +     if (!g_strcmp0(path, devpath))
> +             return TRUE;

How about a simple return g_str_equals here?

> +
> +     return FALSE;
> +}
> +
>  static void remove_modem(struct udev_device *udev_device)
>  {
>       struct ofono_modem *modem;
> -     struct udev_device *parent;
> -     const char *devpath, *driver = NULL;
> +     const char *curpath = udev_device_get_devpath(udev_device);
> +     char *devpath, *remove;
> 
> -     parent = udev_device_get_parent(udev_device);
> -     if (parent == NULL)
> +     if (curpath == NULL)
>               return;
> 
> -     driver = get_driver(parent);
> -     if (driver == NULL) {
> -             parent = udev_device_get_parent(parent);
> -             driver = get_driver(parent);
> -             if (driver == NULL) {
> -                     parent = udev_device_get_parent(parent);
> -                     driver = get_driver(parent);
> -                     if (driver == NULL)
> -                             return;
> -             }
> -     }
> -
> -     devpath = udev_device_get_devpath(parent);
> -     if (devpath == NULL)
> +     devpath = g_hash_table_lookup(devpath_list, curpath);
> +     if (!devpath)
>               return;
> 
>       modem = find_modem(devpath);
> @@ -339,6 +344,12 @@ static void remove_modem(struct udev_device
>  *udev_device) modem_list = g_slist_remove(modem_list, modem);
> 
>       ofono_modem_remove(modem);
> +
> +     remove = g_strdup(devpath);
> +
> +     g_hash_table_foreach_remove(devpath_list, devpath_remove, remove);
> +
> +     g_free(remove);
>  }
> 
>  static void enumerate_devices(struct udev *context)
> @@ -443,6 +454,13 @@ static void udev_start(void)
> 
>  static int udev_init(void)
>  {
> +     devpath_list = g_hash_table_new_full(g_str_hash, g_str_equal,
> +                                             g_free, g_free);
> +     if (!devpath_list) {
> +             ofono_error("Failed to create udev path list");
> +             return -ENOMEM;
> +     }
> +

You now need to take care of freeing the devpath_list on any further error 
conditions that might occur, otherwise you leak memory.

>       udev_ctx = udev_new();
>       if (udev_ctx == NULL) {
>               ofono_error("Failed to create udev context");
> @@ -483,6 +501,9 @@ static void udev_exit(void)
>       g_slist_free(modem_list);
>       modem_list = NULL;
> 
> +     g_hash_table_destroy(devpath_list);
> +     devpath_list = NULL;
> +
>       if (udev_ctx == NULL)
>               return;
> 

Regards,
-Denis
_______________________________________________
ofono mailing list
[email protected]
http://lists.ofono.org/listinfo/ofono

Reply via email to