Fix driver_settings in kernel mode outside of drivers.

The API allows to create driver settings which are not added to the
global list, however those were left partially uninitialized, and there
was no way to cleanly delete them.

Tag such unattached settings with a ref_count of -1, and have
delete_driver_settings check for this and handle the case correctly.

Note: #10494 comment 2 says the settings for packagefs shouldn't be
added to the kernel driver settings list, which is why I went with this
solution. An alternative would be always using the list and the
reference counting, but I don't know what the consequences are.

Fixes #10494.
This commit is contained in:
Adrien Destugues 2015-01-14 11:47:51 +01:00
parent 0687a01b53
commit bcb793d37b

View File

@ -77,6 +77,8 @@ typedef struct settings_handle {
list_link link;
char name[B_OS_NAME_LENGTH];
int32 ref_count;
// A negative ref_count means the node is not reference counted and not
// stored in the list.
#endif
int32 magic;
struct driver_settings settings;
@ -101,8 +103,9 @@ static mutex sLock = MUTEX_INITIALIZER("driver settings");
/*!
Returns true for any characters that separate parameters -
those are ignored in the input stream and won't be added
\brief Returns true for any characters that separate parameters
Those characters are ignored in the input stream and won't be added
to any words.
*/
static inline bool
@ -112,9 +115,8 @@ is_parameter_separator(char c)
}
/** Indicates if "c" begins a new word or not.
*/
/*! Indicates if "c" begins a new word or not.
*/
static inline bool
is_word_break(char c)
{
@ -413,6 +415,9 @@ new_settings(char *buffer, const char *driverName)
if (driverName != NULL) {
handle->ref_count = 1;
strlcpy(handle->name, driverName, sizeof(handle->name));
} else {
handle->ref_count = -1;
handle->name[0] = 0;
}
#endif
@ -687,11 +692,14 @@ unload_driver_settings(void *_handle)
#ifdef _KERNEL_MODE
mutex_lock(&sLock);
if (--handle->ref_count == 0 && gBootDevice > 0) {
// don't unload an handle when /boot is not available
list_remove_link(&handle->link);
} else
handle = NULL;
if (handle->ref_count > 0) {
if (--handle->ref_count == 0 && gBootDevice > 0) {
// don't unload an handle when /boot is not available
list_remove_link(&handle->link);
} else
handle = NULL;
}
mutex_unlock(&sLock);
#endif