xref: /haiku/src/system/kernel/module.cpp (revision 579f1dbca962a2a03df54f69fdc6e9423f91f20e)
1 /*
2  * Copyright 2002-2008, Haiku Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Copyright 2001, Thomas Kurschel. All rights reserved.
6  * Distributed under the terms of the NewOS License.
7  */
8 
9 /*!	Manages kernel add-ons and their exported modules. */
10 
11 
12 #include <kmodule.h>
13 
14 #include <dirent.h>
15 #include <errno.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <sys/stat.h>
19 
20 #include <FindDirectory.h>
21 #include <NodeMonitor.h>
22 
23 #include <boot_device.h>
24 #include <boot/elf.h>
25 #include <boot/kernel_args.h>
26 #include <elf.h>
27 #include <fs/KPath.h>
28 #include <fs/node_monitor.h>
29 #include <lock.h>
30 #include <Notifications.h>
31 #include <safemode.h>
32 #include <syscalls.h>
33 #include <util/AutoLock.h>
34 #include <util/khash.h>
35 #include <util/Stack.h>
36 #include <vfs.h>
37 
38 
39 //#define TRACE_MODULE
40 #ifdef TRACE_MODULE
41 #	define TRACE(x) dprintf x
42 #else
43 #	define TRACE(x) ;
44 #endif
45 #define FATAL(x) dprintf x
46 
47 
48 #define MODULE_HASH_SIZE 16
49 
50 /*! The modules referenced by this structure are built-in
51 	modules that can't be loaded from disk.
52 */
53 extern module_info gDeviceManagerModule;
54 extern module_info gDeviceRootModule;
55 extern module_info gDeviceGenericModule;
56 extern module_info gFrameBufferConsoleModule;
57 
58 // file systems
59 extern module_info gRootFileSystem;
60 extern module_info gDeviceFileSystem;
61 
62 static module_info* sBuiltInModules[] = {
63 	&gDeviceManagerModule,
64 	&gDeviceRootModule,
65 	&gDeviceGenericModule,
66 	&gFrameBufferConsoleModule,
67 
68 	&gRootFileSystem,
69 	&gDeviceFileSystem,
70 	NULL
71 };
72 
73 enum module_state {
74 	MODULE_QUERIED = 0,
75 	MODULE_LOADED,
76 	MODULE_INIT,
77 	MODULE_READY,
78 	MODULE_UNINIT,
79 	MODULE_ERROR
80 };
81 
82 
83 /* Each loaded module image (which can export several modules) is put
84  * in a hash (gModuleImagesHash) to be easily found when you search
85  * for a specific file name.
86  * TODO: Could use only the inode number for hashing. Would probably be
87  * a little bit slower, but would lower the memory foot print quite a lot.
88  */
89 
90 struct module_image {
91 	struct module_image* next;
92 	module_info**		info;		// the module_info we use
93 	module_dependency*	dependencies;
94 	char*				path;		// the full path for the module
95 	image_id			image;
96 	int32				ref_count;	// how many ref's to this file
97 };
98 
99 /* Each known module will have this structure which is put in the
100  * gModulesHash, and looked up by name.
101  */
102 
103 struct module {
104 	struct module*		next;
105 	::module_image*		module_image;
106 	char*				name;
107 	int32				ref_count;
108 	module_info*		info;		// will only be valid if ref_count > 0
109 	int32				offset;		// this is the offset in the headers
110 	module_state		state;
111 	uint32				flags;
112 };
113 
114 #define B_BUILT_IN_MODULE	2
115 
116 typedef struct module_path {
117 	const char*			name;
118 	uint32				base_length;
119 } module_path;
120 
121 typedef struct module_iterator {
122 	module_path*		stack;
123 	int32				stack_size;
124 	int32				stack_current;
125 
126 	char*				prefix;
127 	size_t				prefix_length;
128 	const char*			suffix;
129 	size_t				suffix_length;
130 	DIR*				current_dir;
131 	status_t			status;
132 	int32				module_offset;
133 		// This is used to keep track of which module_info
134 		// within a module we're addressing.
135 	::module_image*		module_image;
136 	module_info**		current_header;
137 	const char*			current_path;
138 	uint32				path_base_length;
139 	const char*			current_module_path;
140 	bool				builtin_modules;
141 	bool				loaded_modules;
142 } module_iterator;
143 
144 namespace Module {
145 
146 struct entry {
147 	dev_t				device;
148 	ino_t				node;
149 };
150 
151 struct hash_entry : entry {
152 	~hash_entry()
153 	{
154 		free((char*)path);
155 	}
156 
157 	hash_entry*			hash_link;
158 	const char*			path;
159 };
160 
161 struct NodeHashDefinition {
162 	typedef entry* KeyType;
163 	typedef hash_entry ValueType;
164 
165 	size_t Hash(ValueType* entry) const
166 		{ return HashKey(entry); }
167 	ValueType*& GetLink(ValueType* entry) const
168 		{ return entry->hash_link; }
169 
170 	size_t HashKey(KeyType key) const
171 	{
172 		return ((uint32)(key->node >> 32) + (uint32)key->node) ^ key->device;
173 	}
174 
175 	bool Compare(KeyType key, ValueType* entry) const
176 	{
177 		return key->device == entry->device
178 			&& key->node == entry->node;
179 	}
180 };
181 
182 typedef BOpenHashTable<NodeHashDefinition> NodeHash;
183 
184 struct module_listener : DoublyLinkedListLinkImpl<module_listener> {
185 	~module_listener()
186 	{
187 		free((char*)prefix);
188 	}
189 
190 	NotificationListener* listener;
191 	const char*			prefix;
192 };
193 
194 typedef DoublyLinkedList<module_listener> ModuleListenerList;
195 
196 struct module_notification : DoublyLinkedListLinkImpl<module_notification> {
197 	~module_notification()
198 	{
199 		free((char*)name);
200 	}
201 
202 	int32		opcode;
203 	dev_t		device;
204 	ino_t		directory;
205 	ino_t		node;
206 	const char*	name;
207 };
208 
209 typedef DoublyLinkedList<module_notification> NotificationList;
210 
211 class DirectoryWatcher : public NotificationListener {
212 public:
213 						DirectoryWatcher();
214 	virtual				~DirectoryWatcher();
215 
216 	virtual void		EventOccurred(NotificationService& service,
217 							const KMessage* event);
218 };
219 
220 class ModuleWatcher : public NotificationListener {
221 public:
222 						ModuleWatcher();
223 	virtual				~ModuleWatcher();
224 
225 	virtual void		EventOccurred(NotificationService& service,
226 							const KMessage* event);
227 };
228 
229 class ModuleNotificationService : public NotificationService {
230 public:
231 						ModuleNotificationService();
232 	virtual				~ModuleNotificationService();
233 
234 			status_t	InitCheck();
235 
236 			status_t	AddListener(const KMessage* eventSpecifier,
237 							NotificationListener& listener);
238 			status_t	UpdateListener(const KMessage* eventSpecifier,
239 							NotificationListener& listener);
240 			status_t	RemoveListener(const KMessage* eventSpecifier,
241 							NotificationListener& listener);
242 
243 			bool		HasNode(dev_t device, ino_t node);
244 
245 			void		Notify(int32 opcode, dev_t device, ino_t directory,
246 							ino_t node, const char* name);
247 
248 	virtual const char*	Name() { return "modules"; }
249 
250 	static	void		HandleNotifications(void *data, int iteration);
251 
252 private:
253 			status_t	_RemoveNode(dev_t device, ino_t node);
254 			status_t	_AddNode(dev_t device, ino_t node, const char* path,
255 							uint32 flags, NotificationListener& listener);
256 			status_t	_AddDirectoryNode(dev_t device, ino_t node);
257 			status_t	_AddModuleNode(dev_t device, ino_t node, int fd,
258 							const char* name);
259 
260 			status_t	_AddDirectory(const char* prefix);
261 			status_t	_ScanDirectory(char* directoryPath, const char* prefix,
262 							size_t& prefixPosition);
263 			status_t	_ScanDirectory(Stack<DIR*>& stack, DIR* dir,
264 							const char* prefix, size_t prefixPosition);
265 
266 			void		_Notify(int32 opcode, dev_t device, ino_t directory,
267 							ino_t node, const char* name);
268 			void		_HandleNotifications();
269 
270 	recursive_lock		fLock;
271 	ModuleListenerList	fListeners;
272 	NodeHash			fNodes;
273 	DirectoryWatcher	fDirectoryWatcher;
274 	ModuleWatcher		fModuleWatcher;
275 	NotificationList	fNotifications;
276 };
277 
278 }	// namespace Module
279 
280 using namespace Module;
281 
282 /* These are the standard base paths where we start to look for modules
283  * to load. Order is important, the last entry here will be searched
284  * first.
285  */
286 static const directory_which kModulePaths[] = {
287 	B_BEOS_ADDONS_DIRECTORY,
288 	B_COMMON_ADDONS_DIRECTORY,
289 	B_USER_ADDONS_DIRECTORY,
290 };
291 
292 static const uint32 kNumModulePaths = sizeof(kModulePaths)
293 	/ sizeof(kModulePaths[0]);
294 static const uint32 kFirstNonSystemModulePath = 1;
295 
296 
297 static ModuleNotificationService sModuleNotificationService;
298 static bool sDisableUserAddOns = false;
299 
300 /*	Locking scheme: There is a global lock only; having several locks
301 	makes trouble if dependent modules get loaded concurrently ->
302 	they have to wait for each other, i.e. we need one lock per module;
303 	also we must detect circular references during init and not dead-lock.
304 
305 	Reference counting: get_module() increments the ref count of a module,
306 	put_module() decrements it. When a B_KEEP_LOADED module is initialized
307 	the ref count is incremented once more, so it never gets
308 	uninitialized/unloaded. A referenced module, unless it's built-in, has a
309 	non-null module_image and owns a reference to the image. When the last
310 	module reference is put, the image's reference is released and module_image
311 	zeroed (as long as the boot volume has not been mounted, it is not zeroed).
312 	An unreferenced module image is unloaded (when the boot volume is mounted).
313 */
314 static recursive_lock sModulesLock;
315 
316 /* We store the loaded modules by directory path, and all known modules
317  * by module name in a hash table for quick access
318  */
319 static hash_table* sModuleImagesHash;
320 static hash_table* sModulesHash;
321 
322 
323 /*!	Calculates hash for a module using its name */
324 static uint32
325 module_hash(void* _module, const void* _key, uint32 range)
326 {
327 	module* module = (struct module*)_module;
328 	const char* name = (const char*)_key;
329 
330 	if (module != NULL)
331 		return hash_hash_string(module->name) % range;
332 
333 	if (name != NULL)
334 		return hash_hash_string(name) % range;
335 
336 	return 0;
337 }
338 
339 
340 /*!	Compares a module to a given name */
341 static int
342 module_compare(void* _module, const void* _key)
343 {
344 	module* module = (struct module*)_module;
345 	const char* name = (const char*)_key;
346 	if (name == NULL)
347 		return -1;
348 
349 	return strcmp(module->name, name);
350 }
351 
352 
353 /*!	Calculates the hash of a module image using its path */
354 static uint32
355 module_image_hash(void* _module, const void* _key, uint32 range)
356 {
357 	module_image* image = (module_image*)_module;
358 	const char* path = (const char*)_key;
359 
360 	if (image != NULL)
361 		return hash_hash_string(image->path) % range;
362 
363 	if (path != NULL)
364 		return hash_hash_string(path) % range;
365 
366 	return 0;
367 }
368 
369 
370 /*!	Compares a module image to a path */
371 static int
372 module_image_compare(void* _module, const void* _key)
373 {
374 	module_image* image = (module_image*)_module;
375 	const char* path = (const char*)_key;
376 	if (path == NULL)
377 		return -1;
378 
379 	return strcmp(image->path, path);
380 }
381 
382 
383 /*!	Try to load the module image at the specified \a path.
384 	If it could be loaded, it returns \c B_OK, and stores a pointer
385 	to the module_image object in \a _moduleImage.
386 	Needs to be called with the sModulesLock held.
387 */
388 static status_t
389 load_module_image(const char* path, module_image** _moduleImage)
390 {
391 	module_image* moduleImage;
392 	status_t status;
393 	image_id image;
394 
395 	TRACE(("load_module_image(path = \"%s\", _image = %p)\n", path,
396 		_moduleImage));
397 	ASSERT_LOCKED_RECURSIVE(&sModulesLock);
398 	ASSERT(_moduleImage != NULL);
399 
400 	image = load_kernel_add_on(path);
401 	if (image < 0) {
402 		dprintf("load_module_image(%s) failed: %s\n", path, strerror(image));
403 		return image;
404 	}
405 
406 	moduleImage = (module_image*)malloc(sizeof(module_image));
407 	if (moduleImage == NULL) {
408 		status = B_NO_MEMORY;
409 		goto err;
410 	}
411 
412 	if (get_image_symbol(image, "modules", B_SYMBOL_TYPE_DATA,
413 			(void**)&moduleImage->info) != B_OK) {
414 		TRACE(("load_module_image: Failed to load \"%s\" due to lack of "
415 			"'modules' symbol\n", path));
416 		status = B_BAD_TYPE;
417 		goto err1;
418 	}
419 
420 	moduleImage->dependencies = NULL;
421 	get_image_symbol(image, "module_dependencies", B_SYMBOL_TYPE_DATA,
422 		(void**)&moduleImage->dependencies);
423 		// this is allowed to be NULL
424 
425 	moduleImage->path = strdup(path);
426 	if (!moduleImage->path) {
427 		status = B_NO_MEMORY;
428 		goto err1;
429 	}
430 
431 	moduleImage->image = image;
432 	moduleImage->ref_count = 0;
433 
434 	hash_insert(sModuleImagesHash, moduleImage);
435 
436 	TRACE(("load_module_image(\"%s\"): image loaded: %p\n", path, moduleImage));
437 
438 	*_moduleImage = moduleImage;
439 	return B_OK;
440 
441 err1:
442 	free(moduleImage);
443 err:
444 	unload_kernel_add_on(image);
445 
446 	return status;
447 }
448 
449 
450 /*!	Unloads the module's kernel add-on. The \a image will be freed.
451 	Needs to be called with the sModulesLock held.
452 */
453 static status_t
454 unload_module_image(module_image* moduleImage, bool remove)
455 {
456 	TRACE(("unload_module_image(image %p, remove %d)\n", moduleImage, remove));
457 	ASSERT_LOCKED_RECURSIVE(&sModulesLock);
458 
459 	if (moduleImage->ref_count != 0) {
460 		FATAL(("Can't unload %s due to ref_cnt = %" B_PRId32 "\n", moduleImage->path,
461 			moduleImage->ref_count));
462 		return B_ERROR;
463 	}
464 
465 	if (remove)
466 		hash_remove(sModuleImagesHash, moduleImage);
467 
468 	unload_kernel_add_on(moduleImage->image);
469 	free(moduleImage->path);
470 	free(moduleImage);
471 
472 	return B_OK;
473 }
474 
475 
476 static void
477 put_module_image(module_image* image)
478 {
479 	RecursiveLocker locker(sModulesLock);
480 
481 	int32 refCount = atomic_add(&image->ref_count, -1);
482 	ASSERT(refCount > 0);
483 
484 	// Don't unload anything when there is no boot device yet
485 	// (because chances are that we will never be able to access it again)
486 
487 	if (refCount == 1 && gBootDevice > 0)
488 		unload_module_image(image, true);
489 }
490 
491 
492 static status_t
493 get_module_image(const char* path, module_image** _image)
494 {
495 	struct module_image* image;
496 
497 	TRACE(("get_module_image(path = \"%s\")\n", path));
498 
499 	RecursiveLocker _(sModulesLock);
500 
501 	image = (module_image*)hash_lookup(sModuleImagesHash, path);
502 	if (image == NULL) {
503 		status_t status = load_module_image(path, &image);
504 		if (status < B_OK)
505 			return status;
506 	}
507 
508 	atomic_add(&image->ref_count, 1);
509 	*_image = image;
510 
511 	return B_OK;
512 }
513 
514 
515 /*!	Extract the information from the module_info structure pointed at
516 	by "info" and create the entries required for access to it's details.
517 */
518 static status_t
519 create_module(module_info* info, int offset, module** _module)
520 {
521 	module* module;
522 
523 	TRACE(("create_module(info = %p, offset = %d, _module = %p)\n",
524 		info, offset, _module));
525 
526 	if (!info->name)
527 		return B_BAD_VALUE;
528 
529 	module = (struct module*)hash_lookup(sModulesHash, info->name);
530 	if (module) {
531 		FATAL(("Duplicate module name (%s) detected... ignoring new one\n",
532 			info->name));
533 		return B_FILE_EXISTS;
534 	}
535 
536 	if ((module = (struct module*)malloc(sizeof(struct module))) == NULL)
537 		return B_NO_MEMORY;
538 
539 	TRACE(("create_module: name = \"%s\"\n", info->name));
540 
541 	module->module_image = NULL;
542 	module->name = strdup(info->name);
543 	if (module->name == NULL) {
544 		free(module);
545 		return B_NO_MEMORY;
546 	}
547 
548 	module->state = MODULE_QUERIED;
549 	module->info = info;
550 	module->offset = offset;
551 		// record where the module_info can be found in the module_info array
552 	module->ref_count = 0;
553 	module->flags = info->flags;
554 
555 	recursive_lock_lock(&sModulesLock);
556 	hash_insert(sModulesHash, module);
557 	recursive_lock_unlock(&sModulesLock);
558 
559 	if (_module)
560 		*_module = module;
561 
562 	return B_OK;
563 }
564 
565 
566 /*!	Loads the file at \a path and scans all modules contained therein.
567 	Returns \c B_OK if \a searchedName could be found under those modules,
568 	and will return the referenced image in \a _moduleImage.
569 	Returns \c B_ENTRY_NOT_FOUND if the module could not be found.
570 
571 	Must only be called for files that haven't been scanned yet.
572 	\a searchedName is allowed to be \c NULL (if all modules should be scanned)
573 */
574 static status_t
575 check_module_image(const char* path, const char* searchedName,
576 	module_image** _moduleImage)
577 {
578 	status_t status = B_ENTRY_NOT_FOUND;
579 	module_image* image;
580 	module_info** info;
581 	int index = 0;
582 
583 	TRACE(("check_module_image(path = \"%s\", searchedName = \"%s\")\n", path,
584 		searchedName));
585 
586 	if (get_module_image(path, &image) < B_OK)
587 		return B_ENTRY_NOT_FOUND;
588 
589 	for (info = image->info; *info; info++) {
590 		// try to create a module for every module_info, check if the
591 		// name matches if it was a new entry
592 		bool freshModule = false;
593 		struct module* module = (struct module*)hash_lookup(sModulesHash,
594 			(*info)->name);
595 		if (module != NULL) {
596 			// Module does already exist
597 			if (module->module_image == NULL && module->ref_count == 0) {
598 				module->info = *info;
599 				module->offset = index;
600 				module->flags = (*info)->flags;
601 				module->state = MODULE_QUERIED;
602 				freshModule = true;
603 			}
604 		} else if (create_module(*info, index, NULL) == B_OK)
605 			freshModule = true;
606 
607 		if (freshModule && searchedName != NULL
608 			&& strcmp((*info)->name, searchedName) == 0) {
609 			status = B_OK;
610 		}
611 
612 		index++;
613 	}
614 
615 	if (status != B_OK) {
616 		// decrement the ref we got in get_module_image
617 		put_module_image(image);
618 		return status;
619 	}
620 
621 	*_moduleImage = image;
622 	return B_OK;
623 }
624 
625 
626 static module*
627 search_module(const char* name, module_image** _moduleImage)
628 {
629 	status_t status = B_ENTRY_NOT_FOUND;
630 	uint32 i;
631 
632 	TRACE(("search_module(%s)\n", name));
633 
634 	for (i = kNumModulePaths; i-- > 0;) {
635 		if (sDisableUserAddOns && i >= kFirstNonSystemModulePath)
636 			continue;
637 
638 		// let the VFS find that module for us
639 
640 		KPath basePath;
641 		if (find_directory(kModulePaths[i], gBootDevice, true,
642 				basePath.LockBuffer(), basePath.BufferSize()) != B_OK)
643 			continue;
644 
645 		basePath.UnlockBuffer();
646 		basePath.Append("kernel");
647 
648 		KPath path;
649 		status = vfs_get_module_path(basePath.Path(), name, path.LockBuffer(),
650 			path.BufferSize());
651 		if (status == B_OK) {
652 			path.UnlockBuffer();
653 			status = check_module_image(path.Path(), name, _moduleImage);
654 			if (status == B_OK)
655 				break;
656 		}
657 	}
658 
659 	if (status != B_OK)
660 		return NULL;
661 
662 	return (module*)hash_lookup(sModulesHash, name);
663 }
664 
665 
666 static status_t
667 put_dependent_modules(struct module* module)
668 {
669 	module_image* image = module->module_image;
670 	module_dependency* dependencies;
671 
672 	// built-in modules don't have a module_image structure
673 	if (image == NULL
674 		|| (dependencies = image->dependencies) == NULL)
675 		return B_OK;
676 
677 	for (int32 i = 0; dependencies[i].name != NULL; i++) {
678 		status_t status = put_module(dependencies[i].name);
679 		if (status < B_OK)
680 			return status;
681 	}
682 
683 	return B_OK;
684 }
685 
686 
687 static status_t
688 get_dependent_modules(struct module* module)
689 {
690 	module_image* image = module->module_image;
691 	module_dependency* dependencies;
692 
693 	// built-in modules don't have a module_image structure
694 	if (image == NULL
695 		|| (dependencies = image->dependencies) == NULL)
696 		return B_OK;
697 
698 	TRACE(("resolving module dependencies...\n"));
699 
700 	for (int32 i = 0; dependencies[i].name != NULL; i++) {
701 		status_t status = get_module(dependencies[i].name,
702 			dependencies[i].info);
703 		if (status < B_OK) {
704 			dprintf("loading dependent module %s of %s failed!\n",
705 				dependencies[i].name, module->name);
706 			return status;
707 		}
708 	}
709 
710 	return B_OK;
711 }
712 
713 
714 /*!	Initializes a loaded module depending on its state */
715 static inline status_t
716 init_module(module* module)
717 {
718 	switch (module->state) {
719 		case MODULE_QUERIED:
720 		case MODULE_LOADED:
721 		{
722 			status_t status;
723 			module->state = MODULE_INIT;
724 
725 			// resolve dependencies
726 
727 			status = get_dependent_modules(module);
728 			if (status < B_OK) {
729 				module->state = MODULE_LOADED;
730 				return status;
731 			}
732 
733 			// init module
734 
735 			TRACE(("initializing module %s (at %p)... \n", module->name,
736 				module->info->std_ops));
737 
738 			if (module->info->std_ops != NULL)
739 				status = module->info->std_ops(B_MODULE_INIT);
740 
741 			TRACE(("...done (%s)\n", strerror(status)));
742 
743 			if (status >= B_OK)
744 				module->state = MODULE_READY;
745 			else {
746 				put_dependent_modules(module);
747 				module->state = MODULE_LOADED;
748 			}
749 
750 			return status;
751 		}
752 
753 		case MODULE_READY:
754 			return B_OK;
755 
756 		case MODULE_INIT:
757 			FATAL(("circular reference to %s\n", module->name));
758 			return B_ERROR;
759 
760 		case MODULE_UNINIT:
761 			FATAL(("tried to load module %s which is currently unloading\n",
762 				module->name));
763 			return B_ERROR;
764 
765 		case MODULE_ERROR:
766 			FATAL(("cannot load module %s because its earlier unloading "
767 				"failed\n", module->name));
768 			return B_ERROR;
769 
770 		default:
771 			return B_ERROR;
772 	}
773 	// never trespasses here
774 }
775 
776 
777 /*!	Uninitializes a module depeding on its state */
778 static inline int
779 uninit_module(module* module)
780 {
781 	TRACE(("uninit_module(%s)\n", module->name));
782 
783 	switch (module->state) {
784 		case MODULE_QUERIED:
785 		case MODULE_LOADED:
786 			return B_NO_ERROR;
787 
788 		case MODULE_INIT:
789 			panic("Trying to unload module %s which is initializing\n",
790 				module->name);
791 			return B_ERROR;
792 
793 		case MODULE_UNINIT:
794 			panic("Trying to unload module %s which is un-initializing\n",
795 				module->name);
796 			return B_ERROR;
797 
798 		case MODULE_READY:
799 		{
800 			status_t status = B_OK;
801 			module->state = MODULE_UNINIT;
802 
803 			TRACE(("uninitializing module %s...\n", module->name));
804 
805 			if (module->info->std_ops != NULL)
806 				status = module->info->std_ops(B_MODULE_UNINIT);
807 
808 			TRACE(("...done (%s)\n", strerror(status)));
809 
810 			if (status == B_OK) {
811 				module->state = MODULE_LOADED;
812 				put_dependent_modules(module);
813 				return B_OK;
814 			}
815 
816 			FATAL(("Error unloading module %s (%s)\n", module->name,
817 				strerror(status)));
818 
819 			module->state = MODULE_ERROR;
820 			module->flags |= B_KEEP_LOADED;
821 			module->ref_count++;
822 
823 			return status;
824 		}
825 		default:
826 			return B_ERROR;
827 	}
828 	// never trespasses here
829 }
830 
831 
832 static const char*
833 iterator_pop_path_from_stack(module_iterator* iterator, uint32* _baseLength)
834 {
835 	if (iterator->stack_current <= 0)
836 		return NULL;
837 
838 	if (_baseLength)
839 		*_baseLength = iterator->stack[iterator->stack_current - 1].base_length;
840 
841 	return iterator->stack[--iterator->stack_current].name;
842 }
843 
844 
845 static status_t
846 iterator_push_path_on_stack(module_iterator* iterator, const char* path,
847 	uint32 baseLength)
848 {
849 	if (iterator->stack_current + 1 > iterator->stack_size) {
850 		// allocate new space on the stack
851 		module_path* stack = (module_path*)realloc(iterator->stack,
852 			(iterator->stack_size + 8) * sizeof(module_path));
853 		if (stack == NULL)
854 			return B_NO_MEMORY;
855 
856 		iterator->stack = stack;
857 		iterator->stack_size += 8;
858 	}
859 
860 	iterator->stack[iterator->stack_current].name = path;
861 	iterator->stack[iterator->stack_current++].base_length = baseLength;
862 	return B_OK;
863 }
864 
865 
866 static bool
867 match_iterator_suffix(module_iterator* iterator, const char* name)
868 {
869 	if (iterator->suffix == NULL || iterator->suffix_length == 0)
870 		return true;
871 
872 	size_t length = strlen(name);
873 	if (length <= iterator->suffix_length)
874 		return false;
875 
876 	return name[length - iterator->suffix_length - 1] == '/'
877 		&& !strcmp(name + length - iterator->suffix_length, iterator->suffix);
878 }
879 
880 
881 static status_t
882 iterator_get_next_module(module_iterator* iterator, char* buffer,
883 	size_t* _bufferSize)
884 {
885 	status_t status;
886 
887 	TRACE(("iterator_get_next_module() -- start\n"));
888 
889 	if (iterator->builtin_modules) {
890 		for (int32 i = iterator->module_offset; sBuiltInModules[i] != NULL;
891 				i++) {
892 			// the module name must fit the prefix
893 			if (strncmp(sBuiltInModules[i]->name, iterator->prefix,
894 					iterator->prefix_length)
895 				|| !match_iterator_suffix(iterator, sBuiltInModules[i]->name))
896 				continue;
897 
898 			*_bufferSize = strlcpy(buffer, sBuiltInModules[i]->name,
899 				*_bufferSize);
900 			iterator->module_offset = i + 1;
901 			return B_OK;
902 		}
903 		iterator->builtin_modules = false;
904 	}
905 
906 	if (iterator->loaded_modules) {
907 		recursive_lock_lock(&sModulesLock);
908 		hash_iterator hashIterator;
909 		hash_open(sModulesHash, &hashIterator);
910 
911 		struct module* module = (struct module*)hash_next(sModulesHash,
912 			&hashIterator);
913 		for (int32 i = 0; module != NULL; i++) {
914 			if (i >= iterator->module_offset) {
915 				if (!strncmp(module->name, iterator->prefix,
916 						iterator->prefix_length)
917 					&& match_iterator_suffix(iterator, module->name)) {
918 					*_bufferSize = strlcpy(buffer, module->name, *_bufferSize);
919 					iterator->module_offset = i + 1;
920 
921 					hash_close(sModulesHash, &hashIterator, false);
922 					recursive_lock_unlock(&sModulesLock);
923 					return B_OK;
924 				}
925 			}
926 			module = (struct module*)hash_next(sModulesHash, &hashIterator);
927 		}
928 
929 		hash_close(sModulesHash, &hashIterator, false);
930 		recursive_lock_unlock(&sModulesLock);
931 
932 		// prevent from falling into modules hash iteration again
933 		iterator->loaded_modules = false;
934 	}
935 
936 nextPath:
937 	if (iterator->current_dir == NULL) {
938 		// get next directory path from the stack
939 		const char* path = iterator_pop_path_from_stack(iterator,
940 			&iterator->path_base_length);
941 		if (path == NULL) {
942 			// we are finished, there are no more entries on the stack
943 			return B_ENTRY_NOT_FOUND;
944 		}
945 
946 		free((char*)iterator->current_path);
947 		iterator->current_path = path;
948 		iterator->current_dir = opendir(path);
949 		TRACE(("open directory at %s -> %p\n", path, iterator->current_dir));
950 
951 		if (iterator->current_dir == NULL) {
952 			// we don't throw an error here, but silently go to
953 			// the next directory on the stack
954 			goto nextPath;
955 		}
956 	}
957 
958 nextModuleImage:
959 	// TODO: remember which directories were already scanned, and don't search
960 	// through them again, unless they change (use DirectoryWatcher)
961 
962 	if (iterator->current_header == NULL) {
963 		// get next entry from the current directory
964 
965 		errno = 0;
966 
967 		struct dirent* dirent;
968 		if ((dirent = readdir(iterator->current_dir)) == NULL) {
969 			closedir(iterator->current_dir);
970 			iterator->current_dir = NULL;
971 
972 			if (errno < B_OK)
973 				return errno;
974 
975 			goto nextPath;
976 		}
977 
978 		// check if the prefix matches
979 		int32 passedOffset, commonLength;
980 		passedOffset = strlen(iterator->current_path) + 1;
981 		commonLength = iterator->path_base_length + iterator->prefix_length
982 			- passedOffset;
983 
984 		if (commonLength > 0) {
985 			// the prefix still reaches into the new path part
986 			int32 length = strlen(dirent->d_name);
987 			if (commonLength > length)
988 				commonLength = length;
989 
990 			if (strncmp(dirent->d_name, iterator->prefix + passedOffset
991 					- iterator->path_base_length, commonLength))
992 				goto nextModuleImage;
993 		}
994 
995 		// we're not interested in traversing these (again)
996 		if (!strcmp(dirent->d_name, ".")
997 			|| !strcmp(dirent->d_name, "..")
998 			// TODO: this is a bit unclean, as we actually only want to prevent
999 			// drivers/bin and drivers/dev to be scanned
1000 			|| !strcmp(dirent->d_name, "bin")
1001 			|| !strcmp(dirent->d_name, "dev"))
1002 			goto nextModuleImage;
1003 
1004 		// build absolute path to current file
1005 		KPath path(iterator->current_path);
1006 		if (path.InitCheck() != B_OK)
1007 			return B_NO_MEMORY;
1008 
1009 		if (path.Append(dirent->d_name) != B_OK)
1010 			return B_BUFFER_OVERFLOW;
1011 
1012 		// find out if it's a directory or a file
1013 		struct stat stat;
1014 		if (::stat(path.Path(), &stat) < 0)
1015 			return errno;
1016 
1017 		iterator->current_module_path = strdup(path.Path());
1018 		if (iterator->current_module_path == NULL)
1019 			return B_NO_MEMORY;
1020 
1021 		if (S_ISDIR(stat.st_mode)) {
1022 			status = iterator_push_path_on_stack(iterator,
1023 				iterator->current_module_path, iterator->path_base_length);
1024 			if (status != B_OK)
1025 				return status;
1026 
1027 			iterator->current_module_path = NULL;
1028 			goto nextModuleImage;
1029 		}
1030 
1031 		if (!S_ISREG(stat.st_mode))
1032 			return B_BAD_TYPE;
1033 
1034 		TRACE(("open module at %s\n", path.Path()));
1035 
1036 		status = get_module_image(path.Path(), &iterator->module_image);
1037 		if (status < B_OK) {
1038 			free((char*)iterator->current_module_path);
1039 			iterator->current_module_path = NULL;
1040 			goto nextModuleImage;
1041 		}
1042 
1043 		iterator->current_header = iterator->module_image->info;
1044 		iterator->module_offset = 0;
1045 	}
1046 
1047 	// search the current module image until we've got a match
1048 	while (*iterator->current_header != NULL) {
1049 		module_info* info = *iterator->current_header;
1050 
1051 		// TODO: we might want to create a module here and cache it in the
1052 		// hash table
1053 
1054 		iterator->current_header++;
1055 		iterator->module_offset++;
1056 
1057 		if (strncmp(info->name, iterator->prefix, iterator->prefix_length)
1058 			|| !match_iterator_suffix(iterator, info->name))
1059 			continue;
1060 
1061 		*_bufferSize = strlcpy(buffer, info->name, *_bufferSize);
1062 		return B_OK;
1063 	}
1064 
1065 	// leave this module and get the next one
1066 
1067 	iterator->current_header = NULL;
1068 	free((char*)iterator->current_module_path);
1069 	iterator->current_module_path = NULL;
1070 
1071 	put_module_image(iterator->module_image);
1072 	iterator->module_image = NULL;
1073 
1074 	goto nextModuleImage;
1075 }
1076 
1077 
1078 static void
1079 register_builtin_modules(struct module_info** info)
1080 {
1081 	for (; *info; info++) {
1082 		(*info)->flags |= B_BUILT_IN_MODULE;
1083 			// this is an internal flag, it doesn't have to be set by modules
1084 			// itself
1085 
1086 		if (create_module(*info, -1, NULL) != B_OK) {
1087 			dprintf("creation of built-in module \"%s\" failed!\n",
1088 				(*info)->name);
1089 		}
1090 	}
1091 }
1092 
1093 
1094 static status_t
1095 register_preloaded_module_image(struct preloaded_image* image)
1096 {
1097 	module_image* moduleImage;
1098 	struct module_info** info;
1099 	status_t status;
1100 	int32 index = 0;
1101 
1102 	TRACE(("register_preloaded_module_image(image = %p, name = \"%s\")\n",
1103 		image, image->name.Pointer()));
1104 
1105 	image->is_module = false;
1106 
1107 	if (image->id < 0)
1108 		return B_BAD_VALUE;
1109 
1110 	moduleImage = (module_image*)malloc(sizeof(module_image));
1111 	if (moduleImage == NULL)
1112 		return B_NO_MEMORY;
1113 
1114 	if (get_image_symbol(image->id, "modules", B_SYMBOL_TYPE_DATA,
1115 			(void**)&moduleImage->info) != B_OK) {
1116 		status = B_BAD_TYPE;
1117 		goto error;
1118 	}
1119 
1120 	image->is_module = true;
1121 
1122 	if (moduleImage->info[0] == NULL) {
1123 		status = B_BAD_DATA;
1124 		goto error;
1125 	}
1126 
1127 	moduleImage->dependencies = NULL;
1128 	get_image_symbol(image->id, "module_dependencies", B_SYMBOL_TYPE_DATA,
1129 		(void**)&moduleImage->dependencies);
1130 		// this is allowed to be NULL
1131 
1132 	moduleImage->path = strdup(image->name);
1133 	if (moduleImage->path == NULL) {
1134 		status = B_NO_MEMORY;
1135 		goto error;
1136 	}
1137 
1138 	moduleImage->image = image->id;
1139 	moduleImage->ref_count = 0;
1140 
1141 	hash_insert(sModuleImagesHash, moduleImage);
1142 
1143 	for (info = moduleImage->info; *info; info++) {
1144 		struct module* module = NULL;
1145 		if (create_module(*info, index++, &module) == B_OK)
1146 			module->module_image = moduleImage;
1147 	}
1148 
1149 	return B_OK;
1150 
1151 error:
1152 	free(moduleImage);
1153 
1154 	// We don't need this image anymore. We keep it, if it doesn't look like
1155 	// a module at all. It might be an old-style driver.
1156 	if (image->is_module)
1157 		unload_kernel_add_on(image->id);
1158 
1159 	return status;
1160 }
1161 
1162 
1163 static int
1164 dump_modules(int argc, char** argv)
1165 {
1166 	hash_iterator iterator;
1167 	struct module_image* image;
1168 	struct module* module;
1169 
1170 	hash_rewind(sModulesHash, &iterator);
1171 	kprintf("-- known modules:\n");
1172 
1173 	while ((module = (struct module*)hash_next(sModulesHash, &iterator))
1174 			!= NULL) {
1175 		kprintf("%p: \"%s\", \"%s\" (%" B_PRId32 "), refcount = %" B_PRId32 ", "
1176 			"state = %d, mimage = %p\n", module, module->name,
1177 			module->module_image ? module->module_image->path : "",
1178 			module->offset, module->ref_count, module->state,
1179 			module->module_image);
1180 	}
1181 
1182 	hash_rewind(sModuleImagesHash, &iterator);
1183 	kprintf("\n-- loaded module images:\n");
1184 
1185 	while ((image = (struct module_image*)hash_next(sModuleImagesHash,
1186 				&iterator)) != NULL) {
1187 		kprintf("%p: \"%s\" (image_id = %" B_PRId32 "), info = %p, refcount = "
1188 			"%" B_PRId32 "\n", image, image->path, image->image, image->info,
1189 			image->ref_count);
1190 	}
1191 	return 0;
1192 }
1193 
1194 
1195 //	#pragma mark - DirectoryWatcher
1196 
1197 
1198 DirectoryWatcher::DirectoryWatcher()
1199 {
1200 }
1201 
1202 
1203 DirectoryWatcher::~DirectoryWatcher()
1204 {
1205 }
1206 
1207 
1208 void
1209 DirectoryWatcher::EventOccurred(NotificationService& service,
1210 	const KMessage* event)
1211 {
1212 	int32 opcode = event->GetInt32("opcode", -1);
1213 	dev_t device = event->GetInt32("device", -1);
1214 	ino_t directory = event->GetInt64("directory", -1);
1215 	ino_t node = event->GetInt64("node", -1);
1216 	const char *name = event->GetString("name", NULL);
1217 
1218 	if (opcode == B_ENTRY_MOVED) {
1219 		// Determine whether it's a move within, out of, or into one
1220 		// of our watched directories.
1221 		directory = event->GetInt64("to directory", -1);
1222 		if (!sModuleNotificationService.HasNode(device, directory)) {
1223 			directory = event->GetInt64("from directory", -1);
1224 			opcode = B_ENTRY_REMOVED;
1225 		} else {
1226 			// Move within, doesn't sound like a good idea for modules
1227 			opcode = B_ENTRY_CREATED;
1228 		}
1229 	}
1230 
1231 	sModuleNotificationService.Notify(opcode, device, directory, node, name);
1232 }
1233 
1234 
1235 //	#pragma mark - ModuleWatcher
1236 
1237 
1238 ModuleWatcher::ModuleWatcher()
1239 {
1240 }
1241 
1242 
1243 ModuleWatcher::~ModuleWatcher()
1244 {
1245 }
1246 
1247 
1248 void
1249 ModuleWatcher::EventOccurred(NotificationService& service, const KMessage* event)
1250 {
1251 	if (event->GetInt32("opcode", -1) != B_STAT_CHANGED
1252 		|| (event->GetInt32("fields", 0) & B_STAT_MODIFICATION_TIME) == 0)
1253 		return;
1254 
1255 	dev_t device = event->GetInt32("device", -1);
1256 	ino_t node = event->GetInt64("node", -1);
1257 
1258 	sModuleNotificationService.Notify(B_STAT_CHANGED, device, -1, node, NULL);
1259 }
1260 
1261 
1262 //	#pragma mark - ModuleNotificationService
1263 
1264 
1265 ModuleNotificationService::ModuleNotificationService()
1266 {
1267 	recursive_lock_init(&fLock, "module notifications");
1268 }
1269 
1270 
1271 ModuleNotificationService::~ModuleNotificationService()
1272 {
1273 	recursive_lock_destroy(&fLock);
1274 }
1275 
1276 
1277 status_t
1278 ModuleNotificationService::AddListener(const KMessage* eventSpecifier,
1279 	NotificationListener& listener)
1280 {
1281 	const char* prefix = eventSpecifier->GetString("prefix", NULL);
1282 	if (prefix == NULL)
1283 		return B_BAD_VALUE;
1284 
1285 	module_listener* moduleListener = new(std::nothrow) module_listener;
1286 	if (moduleListener == NULL)
1287 		return B_NO_MEMORY;
1288 
1289 	moduleListener->prefix = strdup(prefix);
1290 	if (moduleListener->prefix == NULL) {
1291 		delete moduleListener;
1292 		return B_NO_MEMORY;
1293 	}
1294 
1295 	status_t status = _AddDirectory(prefix);
1296 	if (status != B_OK) {
1297 		delete moduleListener;
1298 		return status;
1299 	}
1300 
1301 	moduleListener->listener = &listener;
1302 	fListeners.Add(moduleListener);
1303 
1304 	return B_OK;
1305 }
1306 
1307 
1308 status_t
1309 ModuleNotificationService::UpdateListener(const KMessage* eventSpecifier,
1310 	NotificationListener& listener)
1311 {
1312 	return B_ERROR;
1313 }
1314 
1315 
1316 status_t
1317 ModuleNotificationService::RemoveListener(const KMessage* eventSpecifier,
1318 	NotificationListener& listener)
1319 {
1320 	return B_ERROR;
1321 }
1322 
1323 
1324 bool
1325 ModuleNotificationService::HasNode(dev_t device, ino_t node)
1326 {
1327 	RecursiveLocker _(fLock);
1328 
1329 	struct entry entry = {device, node};
1330 	return fNodes.Lookup(&entry) != NULL;
1331 }
1332 
1333 
1334 status_t
1335 ModuleNotificationService::_RemoveNode(dev_t device, ino_t node)
1336 {
1337 	RecursiveLocker _(fLock);
1338 
1339 	struct entry key = {device, node};
1340 	hash_entry* entry = fNodes.Lookup(&key);
1341 	if (entry == NULL)
1342 		return B_ENTRY_NOT_FOUND;
1343 
1344 	remove_node_listener(device, node, entry->path != NULL
1345 		? (NotificationListener&)fModuleWatcher
1346 		: (NotificationListener&)fDirectoryWatcher);
1347 
1348 	fNodes.Remove(entry);
1349 	delete entry;
1350 
1351 	return B_OK;
1352 }
1353 
1354 
1355 status_t
1356 ModuleNotificationService::_AddNode(dev_t device, ino_t node, const char* path,
1357 	uint32 flags, NotificationListener& listener)
1358 {
1359 	RecursiveLocker locker(fLock);
1360 
1361 	if (HasNode(device, node))
1362 		return B_OK;
1363 
1364 	struct hash_entry* entry = new(std::nothrow) hash_entry;
1365 	if (entry == NULL)
1366 		return B_NO_MEMORY;
1367 
1368 	if (path != NULL) {
1369 		entry->path = strdup(path);
1370 		if (entry->path == NULL) {
1371 			delete entry;
1372 			return B_NO_MEMORY;
1373 		}
1374 	} else
1375 		entry->path = NULL;
1376 
1377 	status_t status = add_node_listener(device, node, flags, listener);
1378 	if (status != B_OK) {
1379 		delete entry;
1380 		return status;
1381 	}
1382 
1383 	//dprintf("  add %s %ld:%Ld (%s)\n", flags == B_WATCH_DIRECTORY
1384 	//	? "dir" : "file", device, node, path);
1385 
1386 	entry->device = device;
1387 	entry->node = node;
1388 	fNodes.Insert(entry);
1389 
1390 	return B_OK;
1391 }
1392 
1393 
1394 status_t
1395 ModuleNotificationService::_AddDirectoryNode(dev_t device, ino_t node)
1396 {
1397 	return _AddNode(device, node, NULL, B_WATCH_DIRECTORY, fDirectoryWatcher);
1398 }
1399 
1400 
1401 status_t
1402 ModuleNotificationService::_AddModuleNode(dev_t device, ino_t node, int fd,
1403 	const char* name)
1404 {
1405 	struct vnode* vnode;
1406 	status_t status = vfs_get_vnode_from_fd(fd, true, &vnode);
1407 	if (status != B_OK)
1408 		return status;
1409 
1410 	ino_t directory;
1411 	vfs_vnode_to_node_ref(vnode, &device, &directory);
1412 
1413 	KPath path;
1414 	status = path.InitCheck();
1415 	if (status == B_OK) {
1416 		status = vfs_entry_ref_to_path(device, directory, name, true,
1417 			path.LockBuffer(), path.BufferSize());
1418 	}
1419 	if (status != B_OK)
1420 		return status;
1421 
1422 	path.UnlockBuffer();
1423 
1424 	return _AddNode(device, node, path.Path(), B_WATCH_STAT, fModuleWatcher);
1425 }
1426 
1427 
1428 status_t
1429 ModuleNotificationService::_AddDirectory(const char* prefix)
1430 {
1431 	status_t status = B_ERROR;
1432 
1433 	for (uint32 i = 0; i < kNumModulePaths; i++) {
1434 		if (sDisableUserAddOns && i >= kFirstNonSystemModulePath)
1435 			break;
1436 
1437 		KPath pathBuffer;
1438 		if (find_directory(kModulePaths[i], gBootDevice, true,
1439 				pathBuffer.LockBuffer(), pathBuffer.BufferSize()) != B_OK)
1440 			continue;
1441 
1442 		pathBuffer.UnlockBuffer();
1443 		pathBuffer.Append("kernel");
1444 		pathBuffer.Append(prefix);
1445 
1446 		size_t prefixPosition = strlen(prefix);
1447 		status_t scanStatus = _ScanDirectory(pathBuffer.LockBuffer(), prefix,
1448 			prefixPosition);
1449 
1450 		pathBuffer.UnlockBuffer();
1451 
1452 		// It's enough if we succeed for one directory
1453 		if (status != B_OK)
1454 			status = scanStatus;
1455 	}
1456 
1457 	return status;
1458 }
1459 
1460 
1461 status_t
1462 ModuleNotificationService::_ScanDirectory(char* directoryPath,
1463 	const char* prefix, size_t& prefixPosition)
1464 {
1465 	DIR* dir = NULL;
1466 	while (true) {
1467 		dir = opendir(directoryPath);
1468 		if (dir != NULL || prefixPosition == 0)
1469 			break;
1470 
1471 		// the full prefix is not accessible, remove path components
1472 		const char* parentPrefix = prefix + prefixPosition - 1;
1473 		while (parentPrefix != prefix && parentPrefix[0] != '/')
1474 			parentPrefix--;
1475 
1476 		size_t cutPosition = parentPrefix - prefix;
1477 		size_t length = strlen(directoryPath);
1478 		directoryPath[length - prefixPosition + cutPosition] = '\0';
1479 		prefixPosition = cutPosition;
1480 	}
1481 
1482 	if (dir == NULL)
1483 		return B_ERROR;
1484 
1485 	Stack<DIR*> stack;
1486 	stack.Push(dir);
1487 
1488 	while (stack.Pop(&dir)) {
1489 		status_t status = _ScanDirectory(stack, dir, prefix, prefixPosition);
1490 		if (status != B_OK)
1491 			return status;
1492 	}
1493 
1494 	return B_OK;
1495 }
1496 
1497 
1498 status_t
1499 ModuleNotificationService::_ScanDirectory(Stack<DIR*>& stack, DIR* dir,
1500 	const char* prefix, size_t prefixPosition)
1501 {
1502 	bool directMatchAdded = false;
1503 	struct dirent* dirent;
1504 
1505 	while ((dirent = readdir(dir)) != NULL) {
1506 		if (dirent->d_name[0] == '.')
1507 			continue;
1508 
1509 		bool directMatch = false;
1510 
1511 		if (prefix[prefixPosition] != '\0') {
1512 			// the start must match
1513 			const char* startPrefix = prefix + prefixPosition;
1514 			if (startPrefix[0] == '/')
1515 				startPrefix++;
1516 
1517 			const char* endPrefix = strchr(startPrefix, '/');
1518 			size_t length;
1519 
1520 			if (endPrefix != NULL)
1521 				length = endPrefix - startPrefix;
1522 			else
1523 				length = strlen(startPrefix);
1524 
1525 			if (strncmp(dirent->d_name, startPrefix, length))
1526 				continue;
1527 
1528 			if (dirent->d_name[length] == '\0')
1529 				directMatch = true;
1530 		}
1531 
1532 		struct stat stat;
1533 		status_t status = vfs_read_stat(dirfd(dir), dirent->d_name, true, &stat,
1534 			true);
1535 		if (status != B_OK)
1536 			continue;
1537 
1538 		if (S_ISDIR(stat.st_mode)) {
1539 			int fd = _kern_open_dir(dirfd(dir), dirent->d_name);
1540 			if (fd < 0)
1541 				continue;
1542 
1543 			DIR* subDir = fdopendir(fd);
1544 			if (subDir == NULL) {
1545 				close(fd);
1546 				continue;
1547 			}
1548 
1549 			stack.Push(subDir);
1550 
1551 			if (_AddDirectoryNode(stat.st_dev, stat.st_ino) == B_OK
1552 				&& directMatch)
1553 				directMatchAdded = true;
1554 		} else if (S_ISREG(stat.st_mode)) {
1555 			if (_AddModuleNode(stat.st_dev, stat.st_ino, dirfd(dir),
1556 					dirent->d_name) == B_OK && directMatch)
1557 				directMatchAdded = true;
1558 		}
1559 	}
1560 
1561 	if (!directMatchAdded) {
1562 		// We need to monitor this directory to see if a matching file
1563 		// is added.
1564 		struct stat stat;
1565 		status_t status = vfs_read_stat(dirfd(dir), NULL, true, &stat, true);
1566 		if (status == B_OK)
1567 			_AddDirectoryNode(stat.st_dev, stat.st_ino);
1568 	}
1569 
1570 	closedir(dir);
1571 	return B_OK;
1572 }
1573 
1574 
1575 void
1576 ModuleNotificationService::_Notify(int32 opcode, dev_t device, ino_t directory,
1577 	ino_t node, const char* name)
1578 {
1579 	// construct path
1580 
1581 	KPath pathBuffer;
1582 	const char* path;
1583 
1584 	if (name != NULL) {
1585 		// we have an entry ref
1586 		if (pathBuffer.InitCheck() != B_OK
1587 			|| vfs_entry_ref_to_path(device, directory, name, true,
1588 				pathBuffer.LockBuffer(), pathBuffer.BufferSize()) != B_OK)
1589 			return;
1590 
1591 		pathBuffer.UnlockBuffer();
1592 		path = pathBuffer.Path();
1593 	} else {
1594 		// we only have a node ref
1595 		RecursiveLocker _(fLock);
1596 
1597 		struct entry key = {device, node};
1598 		hash_entry* entry = fNodes.Lookup(&key);
1599 		if (entry == NULL || entry->path == NULL)
1600 			return;
1601 
1602 		path = entry->path;
1603 	}
1604 
1605 	// remove kModulePaths from path
1606 
1607 	for (uint32 i = 0; i < kNumModulePaths; i++) {
1608 		KPath modulePath;
1609 		if (find_directory(kModulePaths[i], gBootDevice, true,
1610 				modulePath.LockBuffer(), modulePath.BufferSize()) != B_OK)
1611 			continue;
1612 
1613 		modulePath.UnlockBuffer();
1614 		modulePath.Append("kernel");
1615 
1616 		if (strncmp(path, modulePath.Path(), modulePath.Length()))
1617 			continue;
1618 
1619 		path += modulePath.Length();
1620 		if (path[i] == '/')
1621 			path++;
1622 
1623 		break;
1624 	}
1625 
1626 	KMessage event;
1627 
1628 	// find listeners by prefix/path
1629 
1630 	ModuleListenerList::Iterator iterator = fListeners.GetIterator();
1631 	while (iterator.HasNext()) {
1632 		module_listener* listener = iterator.Next();
1633 
1634 		if (strncmp(path, listener->prefix, strlen(listener->prefix)))
1635 			continue;
1636 
1637 		if (event.IsEmpty()) {
1638 			// construct message only when needed
1639 			event.AddInt32("opcode", opcode);
1640 			event.AddString("path", path);
1641 		}
1642 
1643 		// notify them!
1644 		listener->listener->EventOccurred(*this, &event);
1645 
1646 		// we might need to watch new files now
1647 		if (opcode == B_ENTRY_CREATED)
1648 			_AddDirectory(listener->prefix);
1649 
1650 	}
1651 
1652 	// remove notification listeners, if needed
1653 
1654 	if (opcode == B_ENTRY_REMOVED)
1655 		_RemoveNode(device, node);
1656 }
1657 
1658 
1659 void
1660 ModuleNotificationService::_HandleNotifications()
1661 {
1662 	RecursiveLocker _(fLock);
1663 
1664 	NotificationList::Iterator iterator = fNotifications.GetIterator();
1665 	while (iterator.HasNext()) {
1666 		module_notification* notification = iterator.Next();
1667 
1668 		_Notify(notification->opcode, notification->device,
1669 			notification->directory, notification->node, notification->name);
1670 
1671 		iterator.Remove();
1672 		delete notification;
1673 	}
1674 }
1675 
1676 
1677 void
1678 ModuleNotificationService::Notify(int32 opcode, dev_t device, ino_t directory,
1679 	ino_t node, const char* name)
1680 {
1681 	module_notification* notification = new(std::nothrow) module_notification;
1682 	if (notification == NULL)
1683 		return;
1684 
1685 	if (name != NULL) {
1686 		notification->name = strdup(name);
1687 		if (notification->name == NULL) {
1688 			delete notification;
1689 			return;
1690 		}
1691 	} else
1692 		notification->name = NULL;
1693 
1694 	notification->opcode = opcode;
1695 	notification->device = device;
1696 	notification->directory = directory;
1697 	notification->node = node;
1698 
1699 	RecursiveLocker _(fLock);
1700 	fNotifications.Add(notification);
1701 }
1702 
1703 
1704 /*static*/ void
1705 ModuleNotificationService::HandleNotifications(void */*data*/,
1706 	int /*iteration*/)
1707 {
1708 	sModuleNotificationService._HandleNotifications();
1709 }
1710 
1711 
1712 //	#pragma mark - Exported Kernel API (private part)
1713 
1714 
1715 /*!	Unloads a module in case it's not in use. This is the counterpart
1716 	to load_module().
1717 */
1718 status_t
1719 unload_module(const char* path)
1720 {
1721 	struct module_image* moduleImage;
1722 
1723 	recursive_lock_lock(&sModulesLock);
1724 	moduleImage = (module_image*)hash_lookup(sModuleImagesHash, path);
1725 	recursive_lock_unlock(&sModulesLock);
1726 
1727 	if (moduleImage == NULL)
1728 		return B_ENTRY_NOT_FOUND;
1729 
1730 	put_module_image(moduleImage);
1731 	return B_OK;
1732 }
1733 
1734 
1735 /*!	Unlike get_module(), this function lets you specify the add-on to
1736 	be loaded by path.
1737 	However, you must not use the exported modules without having called
1738 	get_module() on them. When you're done with the NULL terminated
1739 	\a modules array, you have to call unload_module(), no matter if
1740 	you're actually using any of the modules or not - of course, the
1741 	add-on won't be unloaded until the last put_module().
1742 */
1743 status_t
1744 load_module(const char* path, module_info*** _modules)
1745 {
1746 	module_image* moduleImage;
1747 	status_t status = get_module_image(path, &moduleImage);
1748 	if (status != B_OK)
1749 		return status;
1750 
1751 	*_modules = moduleImage->info;
1752 	return B_OK;
1753 }
1754 
1755 
1756 status_t
1757 start_watching_modules(const char* prefix, NotificationListener& listener)
1758 {
1759 	KMessage specifier;
1760 	status_t status = specifier.AddString("prefix", prefix);
1761 	if (status != B_OK)
1762 		return status;
1763 
1764 	return sModuleNotificationService.AddListener(&specifier, listener);
1765 }
1766 
1767 
1768 status_t
1769 stop_watching_modules(const char* prefix, NotificationListener& listener)
1770 {
1771 	KMessage specifier;
1772 	status_t status = specifier.AddString("prefix", prefix);
1773 	if (status != B_OK)
1774 		return status;
1775 
1776 	return sModuleNotificationService.RemoveListener(&specifier, listener);
1777 }
1778 
1779 
1780 /*! Setup the module structures and data for use - must be called
1781 	before any other module call.
1782 */
1783 status_t
1784 module_init(kernel_args* args)
1785 {
1786 	struct preloaded_image* image;
1787 
1788 	recursive_lock_init(&sModulesLock, "modules rlock");
1789 
1790 	sModulesHash = hash_init(MODULE_HASH_SIZE, 0, module_compare, module_hash);
1791 	if (sModulesHash == NULL)
1792 		return B_NO_MEMORY;
1793 
1794 	sModuleImagesHash = hash_init(MODULE_HASH_SIZE, 0, module_image_compare,
1795 		module_image_hash);
1796 	if (sModuleImagesHash == NULL)
1797 		return B_NO_MEMORY;
1798 
1799 	// register built-in modules
1800 
1801 	register_builtin_modules(sBuiltInModules);
1802 
1803 	// register preloaded images
1804 
1805 	for (image = args->preloaded_images; image != NULL; image = image->next) {
1806 		status_t status = register_preloaded_module_image(image);
1807 		if (status != B_OK && image->is_module) {
1808 			dprintf("Could not register image \"%s\": %s\n", (char *)image->name,
1809 				strerror(status));
1810 		}
1811 	}
1812 
1813 	new(&sModuleNotificationService) ModuleNotificationService();
1814 
1815 	sDisableUserAddOns = get_safemode_boolean(B_SAFEMODE_DISABLE_USER_ADD_ONS,
1816 		false);
1817 
1818 	add_debugger_command("modules", &dump_modules,
1819 		"list all known & loaded modules");
1820 
1821 	return B_OK;
1822 }
1823 
1824 
1825 status_t
1826 module_init_post_threads(void)
1827 {
1828 	return register_kernel_daemon(
1829 		&ModuleNotificationService::HandleNotifications, NULL, 10);
1830 		// once every second
1831 
1832 	return B_OK;
1833 }
1834 
1835 
1836 status_t
1837 module_init_post_boot_device(bool bootingFromBootLoaderVolume)
1838 {
1839 	// Remove all unused pre-loaded module images. Now that the boot device is
1840 	// available, we can load an image when we need it.
1841 	// When the boot volume is also where the boot loader pre-loaded the images
1842 	// from, we get the actual paths for those images.
1843 	TRACE(("module_init_post_boot_device(%d)\n", bootingFromBootLoaderVolume));
1844 
1845 	RecursiveLocker _(sModulesLock);
1846 
1847 	// First of all, clear all pre-loaded module's module_image, if the module
1848 	// isn't in use.
1849 	hash_iterator iterator;
1850 	hash_open(sModulesHash, &iterator);
1851 	struct module* module;
1852 	while ((module = (struct module*)hash_next(sModulesHash, &iterator))
1853 			!= NULL) {
1854 		if (module->ref_count == 0
1855 			&& (module->flags & B_BUILT_IN_MODULE) == 0) {
1856 			TRACE(("  module %p, \"%s\" unused, clearing image\n", module,
1857 				module->name));
1858 			module->module_image = NULL;
1859 		}
1860 	}
1861 
1862 	// Now iterate through the images and drop them respectively normalize their
1863 	// paths.
1864 	hash_open(sModuleImagesHash, &iterator);
1865 
1866 	module_image* imagesToReinsert = NULL;
1867 		// When renamed, an image is added to this list to be re-entered in the
1868 		// hash at the end. We can't do that during the iteration.
1869 
1870 	while (true) {
1871 		struct module_image* image
1872 			= (struct module_image*)hash_next(sModuleImagesHash, &iterator);
1873 		if (image == NULL)
1874 			break;
1875 
1876 		if (image->ref_count == 0) {
1877 			// not in use -- unload it
1878 			TRACE(("  module image %p, \"%s\" unused, removing\n", image,
1879 				image->path));
1880 			hash_remove_current(sModuleImagesHash, &iterator);
1881 			unload_module_image(image, false);
1882 		} else if (bootingFromBootLoaderVolume) {
1883 			bool pathNormalized = false;
1884 			KPath pathBuffer;
1885 			if (image->path[0] != '/') {
1886 				// relative path
1887 				for (uint32 i = kNumModulePaths; i-- > 0;) {
1888 					if (sDisableUserAddOns && i >= kFirstNonSystemModulePath)
1889 						continue;
1890 
1891 					if (find_directory(kModulePaths[i], gBootDevice, true,
1892 							pathBuffer.LockBuffer(), pathBuffer.BufferSize())
1893 								!= B_OK) {
1894 						pathBuffer.UnlockBuffer();
1895 						continue;
1896 					}
1897 
1898 					pathBuffer.UnlockBuffer();
1899 
1900 					// Append the relative boot module directory and the
1901 					// relative image path, normalize the path, and check
1902 					// whether it exists.
1903 					struct stat st;
1904 					if (pathBuffer.Append("kernel/boot") != B_OK
1905 						|| pathBuffer.Append(image->path) != B_OK
1906 						|| pathBuffer.Normalize(true) != B_OK
1907 						|| lstat(pathBuffer.Path(), &st) != 0) {
1908 						continue;
1909 					}
1910 
1911 					pathNormalized = true;
1912 					break;
1913 				}
1914 			} else {
1915 				// absolute path -- try to normalize it anyway
1916 				struct stat st;
1917 				if (pathBuffer.SetPath(image->path) == B_OK
1918 					&& pathBuffer.Normalize(true) == B_OK
1919 					&& lstat(pathBuffer.Path(), &st) == 0) {
1920 					pathNormalized = true;
1921 				}
1922 			}
1923 
1924 			if (pathNormalized) {
1925 				TRACE(("  normalized path of module image %p, \"%s\" -> "
1926 					"\"%s\"\n", image, image->path, pathBuffer.Path()));
1927 
1928 				// set the new path
1929 				free(image->path);
1930 				size_t pathLen = pathBuffer.Length();
1931 				image->path = (char*)realloc(pathBuffer.DetachBuffer(),
1932 					pathLen + 1);
1933 
1934 				// remove the image -- its hash value has probably changed,
1935 				// so we need to re-insert it later
1936 				hash_remove_current(sModuleImagesHash, &iterator);
1937 				image->next = imagesToReinsert;
1938 				imagesToReinsert = image;
1939 			} else {
1940 				dprintf("module_init_post_boot_device() failed to normalize "
1941 					"path of module image %p, \"%s\"\n", image, image->path);
1942 			}
1943 		}
1944 	}
1945 
1946 	// re-insert the images that have got a new path
1947 	while (module_image* image = imagesToReinsert) {
1948 		imagesToReinsert = image->next;
1949 		hash_insert(sModuleImagesHash, image);
1950 	}
1951 
1952 	TRACE(("module_init_post_boot_device() done\n"));
1953 
1954 	return B_OK;
1955 }
1956 
1957 
1958 //	#pragma mark - Exported Kernel API (public part)
1959 
1960 
1961 /*! This returns a pointer to a structure that can be used to
1962 	iterate through a list of all modules available under
1963 	a given prefix that adhere to the specified suffix.
1964 	All paths will be searched and the returned list will
1965 	contain all modules available under the prefix.
1966 	The structure is then used by read_next_module_name(), and
1967 	must be freed by calling close_module_list().
1968 */
1969 void*
1970 open_module_list_etc(const char* prefix, const char* suffix)
1971 {
1972 	TRACE(("open_module_list(prefix = %s)\n", prefix));
1973 
1974 	if (sModulesHash == NULL) {
1975 		dprintf("open_module_list() called too early!\n");
1976 		return NULL;
1977 	}
1978 
1979 	module_iterator* iterator = (module_iterator*)malloc(
1980 		sizeof(module_iterator));
1981 	if (iterator == NULL)
1982 		return NULL;
1983 
1984 	memset(iterator, 0, sizeof(module_iterator));
1985 
1986 	iterator->prefix = strdup(prefix != NULL ? prefix : "");
1987 	if (iterator->prefix == NULL) {
1988 		free(iterator);
1989 		return NULL;
1990 	}
1991 	iterator->prefix_length = strlen(iterator->prefix);
1992 
1993 	iterator->suffix = suffix;
1994 	if (suffix != NULL)
1995 		iterator->suffix_length = strlen(iterator->suffix);
1996 
1997 	if (gBootDevice > 0) {
1998 		// We do have a boot device to scan
1999 
2000 		// first, we'll traverse over the built-in modules
2001 		iterator->builtin_modules = true;
2002 		iterator->loaded_modules = false;
2003 
2004 		// put all search paths on the stack
2005 		for (uint32 i = 0; i < kNumModulePaths; i++) {
2006 			if (sDisableUserAddOns && i >= kFirstNonSystemModulePath)
2007 				break;
2008 
2009 			KPath pathBuffer;
2010 			if (find_directory(kModulePaths[i], gBootDevice, true,
2011 					pathBuffer.LockBuffer(), pathBuffer.BufferSize()) != B_OK)
2012 				continue;
2013 
2014 			pathBuffer.UnlockBuffer();
2015 			pathBuffer.Append("kernel");
2016 
2017 			// Copy base path onto the iterator stack
2018 			char* path = strdup(pathBuffer.Path());
2019 			if (path == NULL)
2020 				continue;
2021 
2022 			size_t length = strlen(path);
2023 
2024 			// TODO: it would currently be nicer to use the commented
2025 			// version below, but the iterator won't work if the prefix
2026 			// is inside a module then.
2027 			// It works this way, but should be done better.
2028 #if 0
2029 			// Build path component: base path + '/' + prefix
2030 			size_t length = strlen(sModulePaths[i]);
2031 			char* path = (char*)malloc(length + iterator->prefix_length + 2);
2032 			if (path == NULL) {
2033 				// ToDo: should we abort the whole operation here?
2034 				//	if we do, don't forget to empty the stack
2035 				continue;
2036 			}
2037 
2038 			memcpy(path, sModulePaths[i], length);
2039 			path[length] = '/';
2040 			memcpy(path + length + 1, iterator->prefix,
2041 				iterator->prefix_length + 1);
2042 #endif
2043 
2044 			iterator_push_path_on_stack(iterator, path, length + 1);
2045 		}
2046 	} else {
2047 		// include loaded modules in case there is no boot device yet
2048 		iterator->builtin_modules = false;
2049 		iterator->loaded_modules = true;
2050 	}
2051 
2052 	return (void*)iterator;
2053 }
2054 
2055 
2056 void*
2057 open_module_list(const char* prefix)
2058 {
2059 	return open_module_list_etc(prefix, NULL);
2060 }
2061 
2062 
2063 /*!	Frees the cookie allocated by open_module_list() */
2064 status_t
2065 close_module_list(void* cookie)
2066 {
2067 	module_iterator* iterator = (module_iterator*)cookie;
2068 	const char* path;
2069 
2070 	TRACE(("close_module_list()\n"));
2071 
2072 	if (iterator == NULL)
2073 		return B_BAD_VALUE;
2074 
2075 	// free stack
2076 	while ((path = iterator_pop_path_from_stack(iterator, NULL)) != NULL)
2077 		free((char*)path);
2078 
2079 	// close what have been left open
2080 	if (iterator->module_image != NULL)
2081 		put_module_image(iterator->module_image);
2082 
2083 	if (iterator->current_dir != NULL)
2084 		closedir(iterator->current_dir);
2085 
2086 	free(iterator->stack);
2087 	free((char*)iterator->current_path);
2088 	free((char*)iterator->current_module_path);
2089 
2090 	free(iterator->prefix);
2091 	free(iterator);
2092 
2093 	return B_OK;
2094 }
2095 
2096 
2097 /*!	Return the next module name from the available list, using
2098 	a structure previously created by a call to open_module_list().
2099 	Returns B_OK as long as it found another module, B_ENTRY_NOT_FOUND
2100 	when done.
2101 */
2102 status_t
2103 read_next_module_name(void* cookie, char* buffer, size_t* _bufferSize)
2104 {
2105 	module_iterator* iterator = (module_iterator*)cookie;
2106 	status_t status;
2107 
2108 	TRACE(("read_next_module_name: looking for next module\n"));
2109 
2110 	if (iterator == NULL || buffer == NULL || _bufferSize == NULL)
2111 		return B_BAD_VALUE;
2112 
2113 	if (iterator->status < B_OK)
2114 		return iterator->status;
2115 
2116 	status = iterator->status;
2117 	recursive_lock_lock(&sModulesLock);
2118 
2119 	status = iterator_get_next_module(iterator, buffer, _bufferSize);
2120 
2121 	iterator->status = status;
2122 	recursive_lock_unlock(&sModulesLock);
2123 
2124 	TRACE(("read_next_module_name: finished with status %s\n",
2125 		strerror(status)));
2126 	return status;
2127 }
2128 
2129 
2130 /*!	Iterates through all loaded modules, and stores its path in "buffer".
2131 	TODO: check if the function in BeOS really does that (could also mean:
2132 		iterate through all modules that are currently loaded; have a valid
2133 		module_image pointer)
2134 */
2135 status_t
2136 get_next_loaded_module_name(uint32* _cookie, char* buffer, size_t* _bufferSize)
2137 {
2138 	if (sModulesHash == NULL) {
2139 		dprintf("get_next_loaded_module_name() called too early!\n");
2140 		return B_ERROR;
2141 	}
2142 
2143 	//TRACE(("get_next_loaded_module_name(\"%s\")\n", buffer));
2144 
2145 	if (_cookie == NULL || buffer == NULL || _bufferSize == NULL)
2146 		return B_BAD_VALUE;
2147 
2148 	status_t status = B_ENTRY_NOT_FOUND;
2149 	uint32 offset = *_cookie;
2150 
2151 	RecursiveLocker _(sModulesLock);
2152 
2153 	hash_iterator iterator;
2154 	hash_open(sModulesHash, &iterator);
2155 	struct module* module = (struct module*)hash_next(sModulesHash, &iterator);
2156 
2157 	for (uint32 i = 0; module != NULL; i++) {
2158 		if (i >= offset) {
2159 			*_bufferSize = strlcpy(buffer, module->name, *_bufferSize);
2160 			*_cookie = i + 1;
2161 			status = B_OK;
2162 			break;
2163 		}
2164 		module = (struct module*)hash_next(sModulesHash, &iterator);
2165 	}
2166 
2167 	hash_close(sModulesHash, &iterator, false);
2168 
2169 	return status;
2170 }
2171 
2172 
2173 status_t
2174 get_module(const char* path, module_info** _info)
2175 {
2176 	module_image* moduleImage = NULL;
2177 	module* module;
2178 	status_t status;
2179 
2180 	TRACE(("get_module(%s)\n", path));
2181 
2182 	if (path == NULL)
2183 		return B_BAD_VALUE;
2184 
2185 	RecursiveLocker _(sModulesLock);
2186 
2187 	module = (struct module*)hash_lookup(sModulesHash, path);
2188 
2189 	// if we don't have it cached yet, search for it
2190 	if (module == NULL || ((module->flags & B_BUILT_IN_MODULE) == 0
2191 			&& module->module_image == NULL)) {
2192 		module = search_module(path, &moduleImage);
2193 		if (module == NULL) {
2194 			FATAL(("module: Search for %s failed.\n", path));
2195 			return B_ENTRY_NOT_FOUND;
2196 		}
2197 
2198 		module->info = moduleImage->info[module->offset];
2199 		module->module_image = moduleImage;
2200 	} else if ((module->flags & B_BUILT_IN_MODULE) == 0 && gBootDevice < 0
2201 		&& module->ref_count == 0) {
2202 		// The boot volume isn't available yet. I.e. instead of searching the
2203 		// right module image, we already know it and just increment the ref
2204 		// count.
2205 		atomic_add(&module->module_image->ref_count, 1);
2206 	}
2207 
2208 	// The state will be adjusted by the call to init_module
2209 	// if we have just loaded the file
2210 	if (module->ref_count == 0) {
2211 		status = init_module(module);
2212 		// For "keep loaded" modules we increment the ref count here. That will
2213 		// cause them never to get unloaded.
2214 		if (status == B_OK && (module->flags & B_KEEP_LOADED) != 0)
2215 			module->ref_count++;
2216 	} else
2217 		status = B_OK;
2218 
2219 	if (status == B_OK) {
2220 		ASSERT(module->ref_count >= 0);
2221 		module->ref_count++;
2222 		*_info = module->info;
2223 	} else if ((module->flags & B_BUILT_IN_MODULE) == 0
2224 		&& module->ref_count == 0) {
2225 		// initialization failed -- release the image reference
2226 		put_module_image(module->module_image);
2227 		if (gBootDevice >= 0)
2228 			module->module_image = NULL;
2229 	}
2230 
2231 	return status;
2232 }
2233 
2234 
2235 status_t
2236 put_module(const char* path)
2237 {
2238 	module* module;
2239 
2240 	TRACE(("put_module(path = %s)\n", path));
2241 
2242 	RecursiveLocker _(sModulesLock);
2243 
2244 	module = (struct module*)hash_lookup(sModulesHash, path);
2245 	if (module == NULL) {
2246 		FATAL(("module: We don't seem to have a reference to module %s\n",
2247 			path));
2248 		return B_BAD_VALUE;
2249 	}
2250 
2251 	if (module->ref_count == 0) {
2252 		panic("module %s has no references.\n", path);
2253 		return B_BAD_VALUE;
2254 	}
2255 
2256 	if (--module->ref_count == 0) {
2257 		if ((module->flags & B_KEEP_LOADED) != 0) {
2258 			panic("ref count of B_KEEP_LOADED module %s dropped to 0!",
2259 				module->name);
2260 			module->ref_count++;
2261 			return B_BAD_VALUE;
2262 		}
2263 
2264 		uninit_module(module);
2265 
2266 		if ((module->flags & B_BUILT_IN_MODULE) == 0
2267 			&& module->ref_count == 0) {
2268 				// uninit_module() increments the ref count on failure
2269 			put_module_image(module->module_image);
2270 			// Unless we don't have a boot device yet, we clear the module's
2271 			// image pointer if the ref count dropped to 0. get_module() will
2272 			// have to reload the image.
2273 			if (gBootDevice >= 0)
2274 				module->module_image = NULL;
2275 		}
2276 	}
2277 
2278 	return B_OK;
2279 }
2280