disk: disk_access: changed mutex for a spinlock

disk_access functions were called from an interupt context, thus
crashing on mutexes (no sleep is allowed in interrupt context).
The usage of a spinlock is permitted. The functions guarded by
the spinlock are executed very quickly anyway, so the spinlock
is applicable.

Signed-off-by: Alexi Demers <alexi.demers@axceta.com>
This commit is contained in:
Alexi Demers 2024-07-22 15:52:50 -04:00 committed by Anas Nashif
parent 32481b6418
commit bf41e53e00

View file

@ -22,15 +22,15 @@ LOG_MODULE_REGISTER(disk);
static sys_dlist_t disk_access_list = SYS_DLIST_STATIC_INIT(&disk_access_list); static sys_dlist_t disk_access_list = SYS_DLIST_STATIC_INIT(&disk_access_list);
/* lock to protect storage layer registration */ /* lock to protect storage layer registration */
static K_MUTEX_DEFINE(mutex); static struct k_spinlock lock;
struct disk_info *disk_access_get_di(const char *name) struct disk_info *disk_access_get_di(const char *name)
{ {
struct disk_info *disk = NULL, *itr; struct disk_info *disk = NULL, *itr;
size_t name_len = strlen(name); size_t name_len = strlen(name);
sys_dnode_t *node; sys_dnode_t *node;
k_spinlock_key_t spinlock_key = k_spin_lock(&lock);
k_mutex_lock(&mutex, K_FOREVER);
SYS_DLIST_FOR_EACH_NODE(&disk_access_list, node) { SYS_DLIST_FOR_EACH_NODE(&disk_access_list, node) {
itr = CONTAINER_OF(node, struct disk_info, node); itr = CONTAINER_OF(node, struct disk_info, node);
@ -49,7 +49,7 @@ struct disk_info *disk_access_get_di(const char *name)
break; break;
} }
} }
k_mutex_unlock(&mutex); k_spin_unlock(&lock, spinlock_key);
return disk; return disk;
} }
@ -167,52 +167,47 @@ int disk_access_ioctl(const char *pdrv, uint8_t cmd, void *buf)
int disk_access_register(struct disk_info *disk) int disk_access_register(struct disk_info *disk)
{ {
int rc = 0; k_spinlock_key_t spinlock_key;
k_mutex_lock(&mutex, K_FOREVER);
if ((disk == NULL) || (disk->name == NULL)) { if ((disk == NULL) || (disk->name == NULL)) {
LOG_ERR("invalid disk interface!!"); LOG_ERR("invalid disk interface!!");
rc = -EINVAL; return -EINVAL;
goto reg_err;
} }
if (disk_access_get_di(disk->name) != NULL) { if (disk_access_get_di(disk->name) != NULL) {
LOG_ERR("disk interface already registered!!"); LOG_ERR("disk interface already registered!!");
rc = -EINVAL; return -EINVAL;
goto reg_err;
} }
/* Initialize reference count to zero */ /* Initialize reference count to zero */
disk->refcnt = 0U; disk->refcnt = 0U;
spinlock_key = k_spin_lock(&lock);
/* append to the disk list */ /* append to the disk list */
sys_dlist_append(&disk_access_list, &disk->node); sys_dlist_append(&disk_access_list, &disk->node);
LOG_DBG("disk interface(%s) registered", disk->name); LOG_DBG("disk interface(%s) registered", disk->name);
reg_err: k_spin_unlock(&lock, spinlock_key);
k_mutex_unlock(&mutex); return 0;
return rc;
} }
int disk_access_unregister(struct disk_info *disk) int disk_access_unregister(struct disk_info *disk)
{ {
int rc = 0; k_spinlock_key_t spinlock_key;
k_mutex_lock(&mutex, K_FOREVER);
if ((disk == NULL) || (disk->name == NULL)) { if ((disk == NULL) || (disk->name == NULL)) {
LOG_ERR("invalid disk interface!!"); LOG_ERR("invalid disk interface!!");
rc = -EINVAL; return -EINVAL;
goto unreg_err;
} }
if (disk_access_get_di(disk->name) == NULL) { if (disk_access_get_di(disk->name) == NULL) {
LOG_ERR("disk interface not registered!!"); LOG_ERR("disk interface not registered!!");
rc = -EINVAL; return -EINVAL;
goto unreg_err;
} }
spinlock_key = k_spin_lock(&lock);
/* remove disk node from the list */ /* remove disk node from the list */
sys_dlist_remove(&disk->node); sys_dlist_remove(&disk->node);
k_spin_unlock(&lock, spinlock_key);
LOG_DBG("disk interface(%s) unregistered", disk->name); LOG_DBG("disk interface(%s) unregistered", disk->name);
unreg_err: return 0;
k_mutex_unlock(&mutex);
return rc;
} }