xref: /illumos-gate/usr/src/cmd/hal/hald/solaris/hotplug.c (revision 55fea89d)
118c2aff7Sartem /***************************************************************************
218c2aff7Sartem  *
318c2aff7Sartem  * hotplug.c : HAL-internal hotplug events
418c2aff7Sartem  *
58b80e8cbSLin Guo - Sun Microsystems  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
618c2aff7Sartem  * Use is subject to license terms.
718c2aff7Sartem  *
818c2aff7Sartem  * Licensed under the Academic Free License version 2.1
918c2aff7Sartem  *
1018c2aff7Sartem  **************************************************************************/
1118c2aff7Sartem 
1218c2aff7Sartem 
1318c2aff7Sartem #ifdef HAVE_CONFIG_H
1418c2aff7Sartem #  include <config.h>
1518c2aff7Sartem #endif
1618c2aff7Sartem 
1718c2aff7Sartem #include <stdio.h>
1818c2aff7Sartem #include <string.h>
1918c2aff7Sartem #include <errno.h>
2018c2aff7Sartem #include <sys/types.h>
2118c2aff7Sartem #include <sys/stat.h>
2218c2aff7Sartem #include <sys/un.h>
2318c2aff7Sartem #include <sys/utsname.h>
2418c2aff7Sartem #include <unistd.h>
2518c2aff7Sartem 
2618c2aff7Sartem #include <glib.h>
2718c2aff7Sartem #include <dbus/dbus.h>
2818c2aff7Sartem #include <dbus/dbus-glib.h>
2918c2aff7Sartem 
3018c2aff7Sartem #include "../osspec.h"
3118c2aff7Sartem #include "../logger.h"
3218c2aff7Sartem #include "../hald.h"
3318c2aff7Sartem #include "../device_info.h"
3418c2aff7Sartem 
3518c2aff7Sartem #include "osspec_solaris.h"
3618c2aff7Sartem #include "hotplug.h"
3718c2aff7Sartem #include "devinfo.h"
3818c2aff7Sartem 
3918c2aff7Sartem /** Queue of ordered hotplug events */
4018c2aff7Sartem GQueue *hotplug_event_queue;
4118c2aff7Sartem 
4218c2aff7Sartem /** List of HotplugEvent objects we are currently processing */
4318c2aff7Sartem GSList *hotplug_events_in_progress = NULL;
4418c2aff7Sartem 
4518c2aff7Sartem static void hotplug_event_begin (HotplugEvent *hotplug_event);
4618c2aff7Sartem 
47*55fea89dSDan Cross void
hotplug_event_end(void * end_token)4818c2aff7Sartem hotplug_event_end (void *end_token)
4918c2aff7Sartem {
5018c2aff7Sartem 	HotplugEvent *hotplug_event = (HotplugEvent *) end_token;
5118c2aff7Sartem 
5218c2aff7Sartem 	hotplug_events_in_progress = g_slist_remove (hotplug_events_in_progress, hotplug_event);
5318c2aff7Sartem 	g_free (hotplug_event);
5418c2aff7Sartem 	hotplug_event_process_queue ();
5518c2aff7Sartem }
5618c2aff7Sartem 
5718c2aff7Sartem static void
hotplug_event_begin_devfs_add(HotplugEvent * hotplug_event,HalDevice * d)5818c2aff7Sartem hotplug_event_begin_devfs_add (HotplugEvent *hotplug_event, HalDevice *d)
5918c2aff7Sartem {
6018c2aff7Sartem 	HalDevice *parent;
6118c2aff7Sartem 	const gchar *parent_udi;
6218c2aff7Sartem 	void (*begin_add_func) (HalDevice *, HalDevice *, DevinfoDevHandler *, void *);
6318c2aff7Sartem 
6418c2aff7Sartem 	if (d != NULL) {
6518c2aff7Sartem 		/* XXX */
6618c2aff7Sartem 		HAL_ERROR (("devpath %s already present in store, ignore event", hotplug_event->un.devfs.devfs_path));
678b80e8cbSLin Guo - Sun Microsystems 
688b80e8cbSLin Guo - Sun Microsystems 		goto out;
6918c2aff7Sartem 	}
7018c2aff7Sartem 
7118c2aff7Sartem 	/* find parent */
7218c2aff7Sartem 	parent_udi = hal_device_property_get_string (hotplug_event->d, "info.parent");
7318c2aff7Sartem 	if (parent_udi == NULL || strlen(parent_udi) == 0) {
7418c2aff7Sartem 		parent = NULL;
7518c2aff7Sartem 	} else {
7618c2aff7Sartem 		parent = hal_device_store_match_key_value_string (hald_get_gdl (), "info.udi", parent_udi);
7718c2aff7Sartem 	}
7818c2aff7Sartem 	/* only root node is allowed to be orphan */
7918c2aff7Sartem 	if (parent == NULL) {
8018c2aff7Sartem 		if (strcmp(hotplug_event->un.devfs.devfs_path, "/") != 0) {
8118c2aff7Sartem 			HAL_ERROR (("Parent is NULL devfs_path=%s parent_udi=%s", hotplug_event->un.devfs.devfs_path, parent_udi ? parent_udi : "<null>"));
828b80e8cbSLin Guo - Sun Microsystems 
838b80e8cbSLin Guo - Sun Microsystems 			goto out;
8418c2aff7Sartem 		}
8518c2aff7Sartem 	}
8618c2aff7Sartem 
8718c2aff7Sartem 	/* children of ignored parent should be ignored */
8800687e57Sartem 	if (parent != NULL && hal_device_property_get_bool (parent, "info.ignore")) {
8918c2aff7Sartem 		HAL_INFO (("parent ignored %s", parent_udi));
908b80e8cbSLin Guo - Sun Microsystems 
918b80e8cbSLin Guo - Sun Microsystems 		goto out;
9218c2aff7Sartem 	}
9318c2aff7Sartem 
9418c2aff7Sartem 	/* custom or generic add function */
9518c2aff7Sartem 	begin_add_func = hotplug_event->un.devfs.handler->hotplug_begin_add;
9618c2aff7Sartem 	if (begin_add_func == NULL) {
9718c2aff7Sartem 		begin_add_func = hotplug_event_begin_add_devinfo;
9818c2aff7Sartem 	}
99*55fea89dSDan Cross 	begin_add_func (hotplug_event->d,
10018c2aff7Sartem 			 parent,
101*55fea89dSDan Cross 			 hotplug_event->un.devfs.handler,
10218c2aff7Sartem 			 (void *) hotplug_event);
1038b80e8cbSLin Guo - Sun Microsystems 	 return;
1048b80e8cbSLin Guo - Sun Microsystems 
1058b80e8cbSLin Guo - Sun Microsystems out:
1068b80e8cbSLin Guo - Sun Microsystems 	g_object_unref (hotplug_event->d);
1078b80e8cbSLin Guo - Sun Microsystems 	hotplug_event_end ((void *) hotplug_event);
1088b80e8cbSLin Guo - Sun Microsystems 
1098b80e8cbSLin Guo - Sun Microsystems 	return;
11018c2aff7Sartem }
11118c2aff7Sartem 
11218c2aff7Sartem static void
hotplug_event_begin_devfs_remove(HotplugEvent * hotplug_event,HalDevice * d)11318c2aff7Sartem hotplug_event_begin_devfs_remove (HotplugEvent *hotplug_event, HalDevice *d)
11418c2aff7Sartem {
11518c2aff7Sartem 	if (d == NULL) {
11618c2aff7Sartem 		HAL_ERROR (("devpath %s not present in store, ignore event", hotplug_event->un.devfs.devfs_path));
11718c2aff7Sartem 		hotplug_event_end ((void *) hotplug_event);
11818c2aff7Sartem 		return;
11918c2aff7Sartem 	}
12000687e57Sartem 	HAL_INFO (("hotplug_event_begin_devfs_remove %s", hal_device_get_udi (d)));
12118c2aff7Sartem 
122*55fea89dSDan Cross 	hotplug_event_begin_remove_devinfo(d,
123*55fea89dSDan Cross 			 hotplug_event->un.devfs.devfs_path,
12418c2aff7Sartem 			 (void *) hotplug_event);
12518c2aff7Sartem }
12618c2aff7Sartem 
12718c2aff7Sartem static void
hotplug_event_begin_devfs(HotplugEvent * hotplug_event)12818c2aff7Sartem hotplug_event_begin_devfs (HotplugEvent *hotplug_event)
12918c2aff7Sartem {
13018c2aff7Sartem 	HalDevice *d;
13118c2aff7Sartem 
13218c2aff7Sartem 	HAL_INFO (("hotplug_event_begin_devfs: %s", hotplug_event->un.devfs.devfs_path));
13318c2aff7Sartem 	d = hal_device_store_match_key_value_string (hald_get_gdl (),
13418c2aff7Sartem 						"solaris.devfs_path",
13518c2aff7Sartem 						hotplug_event->un.devfs.devfs_path);
13618c2aff7Sartem 
13718c2aff7Sartem 	if (hotplug_event->action == HOTPLUG_ACTION_ADD) {
13818c2aff7Sartem 		hotplug_event_begin_devfs_add (hotplug_event, d);
13918c2aff7Sartem 	} else if (hotplug_event->action == HOTPLUG_ACTION_REMOVE) {
14018c2aff7Sartem 		hotplug_event_begin_devfs_remove (hotplug_event, d);
14118c2aff7Sartem 	} else {
1428b80e8cbSLin Guo - Sun Microsystems 		HAL_ERROR (("unsupported action %d", hotplug_event->action));
1438b80e8cbSLin Guo - Sun Microsystems 		g_object_unref (hotplug_event->d);
14418c2aff7Sartem 		hotplug_event_end ((void *) hotplug_event);
14518c2aff7Sartem 	}
14618c2aff7Sartem }
14718c2aff7Sartem 
14818c2aff7Sartem static void
hotplug_event_begin(HotplugEvent * hotplug_event)14918c2aff7Sartem hotplug_event_begin (HotplugEvent *hotplug_event)
15018c2aff7Sartem {
15118c2aff7Sartem 	switch (hotplug_event->type) {
15218c2aff7Sartem 
15318c2aff7Sartem 	case HOTPLUG_EVENT_DEVFS:
15418c2aff7Sartem 		hotplug_event_begin_devfs (hotplug_event);
15518c2aff7Sartem 		break;
15618c2aff7Sartem 
15718c2aff7Sartem 	default:
15818c2aff7Sartem 		HAL_ERROR (("Unknown hotplug event type %d", hotplug_event->type));
1598b80e8cbSLin Guo - Sun Microsystems 		g_object_unref (hotplug_event->d);
16018c2aff7Sartem 		hotplug_event_end ((void *) hotplug_event);
16118c2aff7Sartem 		break;
16218c2aff7Sartem 	}
16318c2aff7Sartem }
16418c2aff7Sartem 
165*55fea89dSDan Cross void
hotplug_event_enqueue(HotplugEvent * hotplug_event,int front)16618c2aff7Sartem hotplug_event_enqueue (HotplugEvent *hotplug_event, int front)
16718c2aff7Sartem {
16818c2aff7Sartem 	if (hotplug_event_queue == NULL)
16918c2aff7Sartem 		hotplug_event_queue = g_queue_new ();
17018c2aff7Sartem 
17118c2aff7Sartem 	if (front) {
17218c2aff7Sartem 		g_queue_push_head (hotplug_event_queue, hotplug_event);
17318c2aff7Sartem 	} else {
17418c2aff7Sartem 		g_queue_push_tail (hotplug_event_queue, hotplug_event);
17518c2aff7Sartem 	}
17618c2aff7Sartem }
17718c2aff7Sartem 
178*55fea89dSDan Cross void
hotplug_event_process_queue(void)17918c2aff7Sartem hotplug_event_process_queue (void)
18018c2aff7Sartem {
18118c2aff7Sartem 	HotplugEvent *hotplug_event;
18218c2aff7Sartem 
183*55fea89dSDan Cross 	if (hotplug_events_in_progress == NULL &&
18418c2aff7Sartem 	    (hotplug_event_queue == NULL || g_queue_is_empty (hotplug_event_queue))) {
18518c2aff7Sartem 		hotplug_queue_now_empty ();
18618c2aff7Sartem 		goto out;
18718c2aff7Sartem 	}
18818c2aff7Sartem 
18918c2aff7Sartem 	/* do not process events if some other event is in progress */
19018c2aff7Sartem 	if (hotplug_events_in_progress != NULL && g_slist_length (hotplug_events_in_progress) > 0)
19118c2aff7Sartem 		goto out;
19218c2aff7Sartem 
19318c2aff7Sartem 	hotplug_event = g_queue_pop_head (hotplug_event_queue);
19418c2aff7Sartem 	if (hotplug_event == NULL)
19518c2aff7Sartem 		goto out;
19618c2aff7Sartem 
19718c2aff7Sartem 	hotplug_events_in_progress = g_slist_append (hotplug_events_in_progress, hotplug_event);
19818c2aff7Sartem 	hotplug_event_begin (hotplug_event);
19918c2aff7Sartem 
20018c2aff7Sartem out:
201*55fea89dSDan Cross 	;
20218c2aff7Sartem }
203