diff --git a/arch/arm/src/cxd56xx/cxd56_sph.c b/arch/arm/src/cxd56xx/cxd56_sph.c index f770d7753f..72e6b0cbb2 100644 --- a/arch/arm/src/cxd56xx/cxd56_sph.c +++ b/arch/arm/src/cxd56xx/cxd56_sph.c @@ -104,7 +104,7 @@ static int sph_open(struct file *filep) { /* Exclusive access */ - if (filep->f_inode->i_crefs > 2) + if (atomic_load(&filep->f_inode->i_crefs) > 2) { return ERROR; } diff --git a/arch/arm/src/cxd56xx/cxd56_uart0.c b/arch/arm/src/cxd56xx/cxd56_uart0.c index 1f1841f200..c0eeb97125 100644 --- a/arch/arm/src/cxd56xx/cxd56_uart0.c +++ b/arch/arm/src/cxd56xx/cxd56_uart0.c @@ -115,7 +115,7 @@ static int uart0_open(struct file *filep) int stop; int ret; - if (inode->i_crefs > 2) + if (atomic_load(&inode->i_crefs) > 2) { return OK; } @@ -172,7 +172,7 @@ static int uart0_close(struct file *filep) { struct inode *inode = filep->f_inode; - if (inode->i_crefs == 2) + if (atomic_load(&inode->i_crefs) == 2) { fw_pd_uartdisable(0); fw_pd_uartuninit(0); diff --git a/crypto/cryptodev.c b/crypto/cryptodev.c index 2e6adcf09e..1e545de8f3 100644 --- a/crypto/cryptodev.c +++ b/crypto/cryptodev.c @@ -154,7 +154,7 @@ static const struct file_operations g_cryptoops = static struct inode g_cryptoinode = { - .i_crefs = 1, + .i_crefs = ATOMIC_VAR_INIT(1), .u.i_ops = &g_cryptofops }; diff --git a/drivers/serial/pty.c b/drivers/serial/pty.c index 6e30277c5d..bc37f9050d 100644 --- a/drivers/serial/pty.c +++ b/drivers/serial/pty.c @@ -336,7 +336,7 @@ static int pty_close(FAR struct file *filep) /* Check if the decremented inode reference count would go to zero */ - if (inode->i_crefs == 1) + if (atomic_load(&inode->i_crefs) == 1) { /* Did the (single) master just close its reference? */ diff --git a/fs/inode/fs_inodeaddref.c b/fs/inode/fs_inodeaddref.c index 896e7d1d38..9187a8fae0 100644 --- a/fs/inode/fs_inodeaddref.c +++ b/fs/inode/fs_inodeaddref.c @@ -47,12 +47,7 @@ int inode_addref(FAR struct inode *inode) if (inode) { - ret = inode_lock(); - if (ret >= 0) - { - inode->i_crefs++; - inode_unlock(); - } + atomic_fetch_add(&inode->i_crefs, 1); } return ret; diff --git a/fs/inode/fs_inodefind.c b/fs/inode/fs_inodefind.c index d8e3a9815c..47fe84df95 100644 --- a/fs/inode/fs_inodefind.c +++ b/fs/inode/fs_inodefind.c @@ -71,7 +71,7 @@ int inode_find(FAR struct inode_search_s *desc) /* Increment the reference count on the inode */ - node->i_crefs++; + atomic_fetch_add(&node->i_crefs, 1); } inode_unlock(); diff --git a/fs/inode/fs_inoderelease.c b/fs/inode/fs_inoderelease.c index 0a32620316..0c5a680c66 100644 --- a/fs/inode/fs_inoderelease.c +++ b/fs/inode/fs_inoderelease.c @@ -47,49 +47,14 @@ void inode_release(FAR struct inode *inode) { - int ret; - if (inode) { /* Decrement the references of the inode */ - do + if (atomic_fetch_sub(&inode->i_crefs, 1) <= 1) { - ret = inode_lock(); - - /* This only possible error is due to cancellation of the thread. - * We need to try again anyway in this case, otherwise the - * reference count would be wrong. - */ - - DEBUGASSERT(ret == OK || ret == -ECANCELED); - } - while (ret < 0); - - if (inode->i_crefs) - { - inode->i_crefs--; - } - - /* If the subtree was previously deleted and the reference - * count has decrement to zero, then delete the inode - * now. - */ - - if (inode->i_crefs <= 0) - { - /* If the inode has been properly unlinked, then the peer pointer - * should be NULL. - */ - - inode_unlock(); - DEBUGASSERT(inode->i_peer == NULL); inode_free(inode); } - else - { - inode_unlock(); - } } } diff --git a/fs/inode/fs_inoderemove.c b/fs/inode/fs_inoderemove.c index e5396df2a0..0006855153 100644 --- a/fs/inode/fs_inoderemove.c +++ b/fs/inode/fs_inoderemove.c @@ -96,7 +96,7 @@ static FAR struct inode *inode_unlink(FAR const char *path) node->i_peer = NULL; node->i_parent = NULL; - node->i_crefs--; + atomic_fetch_sub(&node->i_crefs, 1); } RELEASE_SEARCH(&desc); @@ -134,7 +134,7 @@ int inode_remove(FAR const char *path) * to it */ - if (node->i_crefs) + if (atomic_load(&node->i_crefs)) { return -EBUSY; } diff --git a/fs/inode/fs_inodereserve.c b/fs/inode/fs_inodereserve.c index f7ba4002e3..33fdbfd043 100644 --- a/fs/inode/fs_inodereserve.c +++ b/fs/inode/fs_inodereserve.c @@ -85,7 +85,7 @@ static FAR struct inode *inode_alloc(FAR const char *name, mode_t mode) if (node) { node->i_ino = g_ino++; - node->i_crefs = 1; + atomic_init(&node->i_crefs, 1); #ifdef CONFIG_PSEUDOFS_ATTRIBUTES node->i_mode = mode; clock_gettime(CLOCK_REALTIME, &node->i_atime); diff --git a/fs/mount/fs_mount.c b/fs/mount/fs_mount.c index 55c3cd25e6..a23fdc364f 100644 --- a/fs/mount/fs_mount.c +++ b/fs/mount/fs_mount.c @@ -449,7 +449,7 @@ int nx_mount(FAR const char *source, FAR const char *target, if (drvr_inode != NULL) #endif { - drvr_inode->i_crefs++; + atomic_fetch_add(&drvr_inode->i_crefs, 1); } #endif @@ -477,7 +477,7 @@ int nx_mount(FAR const char *source, FAR const char *target, if (drvr_inode != NULL) #endif { - drvr_inode->i_crefs--; + atomic_fetch_sub(&drvr_inode->i_crefs, 1); } #endif diff --git a/fs/mount/fs_umount2.c b/fs/mount/fs_umount2.c index 121be901a8..76ee449ece 100644 --- a/fs/mount/fs_umount2.c +++ b/fs/mount/fs_umount2.c @@ -145,8 +145,7 @@ int nx_umount2(FAR const char *target, unsigned int flags) { /* Just decrement the reference count (without deleting it) */ - DEBUGASSERT(mountpt_inode->i_crefs > 0); - mountpt_inode->i_crefs--; + atomic_fetch_sub(&mountpt_inode->i_crefs, 1); inode_unlock(); } else diff --git a/fs/mqueue/mq_open.c b/fs/mqueue/mq_open.c index 9c4bbbc326..84d1454558 100644 --- a/fs/mqueue/mq_open.c +++ b/fs/mqueue/mq_open.c @@ -74,7 +74,7 @@ static int nxmq_file_close(FAR struct file *filep) { FAR struct inode *inode = filep->f_inode; - if (inode->i_crefs <= 0) + if (atomic_load(&inode->i_crefs) <= 0) { FAR struct mqueue_inode_s *msgq = inode->i_private; @@ -322,7 +322,7 @@ static int file_mq_vopen(FAR struct file *mq, FAR const char *mq_name, /* Set the initial reference count on this inode to one */ - inode->i_crefs++; + atomic_fetch_add(&inode->i_crefs, 1); if (created) { diff --git a/fs/mqueue/mq_unlink.c b/fs/mqueue/mq_unlink.c index c5280e51b1..d6a1c14e58 100644 --- a/fs/mqueue/mq_unlink.c +++ b/fs/mqueue/mq_unlink.c @@ -56,7 +56,7 @@ static void mq_inode_release(FAR struct inode *inode) { - if (inode->i_crefs <= 1) + if (atomic_load(&inode->i_crefs) <= 1) { FAR struct mqueue_inode_s *msgq = inode->i_private; diff --git a/fs/notify/inotify.c b/fs/notify/inotify.c index 5b22cfd8e3..3f95180fd4 100644 --- a/fs/notify/inotify.c +++ b/fs/notify/inotify.c @@ -131,7 +131,7 @@ static struct inode g_inotify_inode = NULL, NULL, NULL, - 1, + ATOMIC_VAR_INIT(1), FSNODEFLAG_TYPE_DRIVER, { &g_inotify_fops diff --git a/fs/semaphore/sem_close.c b/fs/semaphore/sem_close.c index fdab469486..ae8bd12652 100644 --- a/fs/semaphore/sem_close.c +++ b/fs/semaphore/sem_close.c @@ -71,7 +71,6 @@ int nxsem_close(FAR sem_t *sem) { FAR struct nsem_inode_s *nsem; struct inode *inode; - int ret; DEBUGASSERT(sem); @@ -81,34 +80,13 @@ int nxsem_close(FAR sem_t *sem) DEBUGASSERT(nsem->ns_inode); inode = nsem->ns_inode; - /* Decrement the reference count on the inode */ - - do - { - ret = inode_lock(); - - /* The only error that is expected is due to thread cancellation. - * At this point, we must continue to free the semaphore anyway. - */ - - DEBUGASSERT(ret == OK || ret == -ECANCELED); - } - while (ret < 0); - - if (inode->i_crefs > 0) - { - inode->i_crefs--; - } - /* If the semaphore was previously unlinked and the reference count has * decremented to zero, then release the semaphore and delete the inode * now. */ - if (inode->i_crefs <= 0) + if (atomic_fetch_sub(&inode->i_crefs, 1) <= 1) { - /* Destroy the semaphore and free the container */ - nxsem_destroy(&nsem->ns_sem); group_free(NULL, nsem); @@ -116,16 +94,13 @@ int nxsem_close(FAR sem_t *sem) * unlinked, then the peer pointer should be NULL. */ - inode_unlock(); #ifdef CONFIG_FS_NOTIFY notify_close2(inode); #endif DEBUGASSERT(inode->i_peer == NULL); inode_free(inode); - return OK; } - inode_unlock(); return OK; } diff --git a/fs/semaphore/sem_open.c b/fs/semaphore/sem_open.c index 03232b6b6c..406244b31d 100644 --- a/fs/semaphore/sem_open.c +++ b/fs/semaphore/sem_open.c @@ -211,7 +211,7 @@ int nxsem_open(FAR sem_t **sem, FAR const char *name, int oflags, ...) /* Initialize the inode */ INODE_SET_NAMEDSEM(inode); - inode->i_crefs++; + atomic_fetch_add(&inode->i_crefs, 1); /* Initialize the semaphore */ diff --git a/fs/shm/shm_open.c b/fs/shm/shm_open.c index 55ae338fba..cf980497e7 100644 --- a/fs/shm/shm_open.c +++ b/fs/shm/shm_open.c @@ -137,7 +137,7 @@ static int file_shm_open(FAR struct file *shm, FAR const char *name, INODE_SET_SHM(inode); inode->u.i_ops = &g_shmfs_operations; inode->i_private = NULL; - inode->i_crefs++; + atomic_fetch_add(&inode->i_crefs, 1); } /* Associate the inode with a file structure */ diff --git a/fs/shm/shmfs.c b/fs/shm/shmfs.c index 48e54e41db..cf826302c5 100644 --- a/fs/shm/shmfs.c +++ b/fs/shm/shmfs.c @@ -185,21 +185,13 @@ static int shmfs_release(FAR struct inode *inode) * The inode is released after this call, hence checking if i_crefs <= 1. */ - int ret = inode_lock(); - if (ret >= 0) + if (inode->i_parent == NULL && atomic_load(&inode->i_crefs) <= 1) { - if (inode->i_parent == NULL && - inode->i_crefs <= 1) - { - shmfs_free_object(inode->i_private); - inode->i_private = NULL; - ret = OK; - } - - inode_unlock(); + shmfs_free_object(inode->i_private); + inode->i_private = NULL; } - return ret; + return OK; } /**************************************************************************** @@ -267,20 +259,13 @@ static int shmfs_truncate(FAR struct file *filep, off_t length) #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS static int shmfs_unlink(FAR struct inode *inode) { - int ret = inode_lock(); - - if (ret >= 0) + if (atomic_load(&inode->i_crefs) <= 1) { - if (inode->i_crefs <= 1) - { - shmfs_free_object(inode->i_private); - inode->i_private = NULL; - } - - inode_unlock(); + shmfs_free_object(inode->i_private); + inode->i_private = NULL; } - return ret; + return OK; } #endif diff --git a/fs/socket/socket.c b/fs/socket/socket.c index 3675988e7a..47fcf35bfa 100644 --- a/fs/socket/socket.c +++ b/fs/socket/socket.c @@ -75,7 +75,7 @@ static struct inode g_sock_inode = NULL, /* i_parent */ NULL, /* i_peer */ NULL, /* i_child */ - 1, /* i_crefs */ + ATOMIC_VAR_INIT(1), /* i_crefs */ FSNODEFLAG_TYPE_SOCKET, /* i_flags */ { &g_sock_fileops /* u */ diff --git a/fs/vfs/fs_dir.c b/fs/vfs/fs_dir.c index fc78f619fe..a59a8578fb 100644 --- a/fs/vfs/fs_dir.c +++ b/fs/vfs/fs_dir.c @@ -80,7 +80,7 @@ static struct inode g_dir_inode = NULL, NULL, NULL, - 1, + ATOMIC_VAR_INIT(1), 0, { &g_dir_fileops }, }; @@ -216,7 +216,7 @@ static off_t seek_pseudodir(FAR struct file *filep, off_t offset) { /* Increment the reference count on this next node */ - curr->i_crefs++; + atomic_fetch_add(&curr->i_crefs, 1); } inode_unlock(); @@ -383,7 +383,7 @@ static int read_pseudodir(FAR struct fs_dirent_s *dir, { /* Increment the reference count on this next node */ - pdir->next->i_crefs++; + atomic_fetch_add(&pdir->next->i_crefs, 1); } inode_unlock(); diff --git a/fs/vfs/fs_epoll.c b/fs/vfs/fs_epoll.c index cf612b0a0a..f53a002f21 100644 --- a/fs/vfs/fs_epoll.c +++ b/fs/vfs/fs_epoll.c @@ -123,7 +123,7 @@ static struct inode g_epoll_inode = NULL, /* i_parent */ NULL, /* i_peer */ NULL, /* i_child */ - 1, /* i_crefs */ + ATOMIC_VAR_INIT(1), /* i_crefs */ FSNODEFLAG_TYPE_DRIVER, /* i_flags */ { &g_epoll_ops /* u */ diff --git a/fs/vfs/fs_eventfd.c b/fs/vfs/fs_eventfd.c index d89abf1ded..5bbd2286ed 100644 --- a/fs/vfs/fs_eventfd.c +++ b/fs/vfs/fs_eventfd.c @@ -112,7 +112,7 @@ static struct inode g_eventfd_inode = NULL, /* i_parent */ NULL, /* i_peer */ NULL, /* i_child */ - 1, /* i_crefs */ + ATOMIC_VAR_INIT(1), /* i_crefs */ FSNODEFLAG_TYPE_DRIVER, /* i_flags */ { &g_eventfd_fops /* u */ diff --git a/fs/vfs/fs_pseudofile.c b/fs/vfs/fs_pseudofile.c index 23890ef0bf..c600fab724 100644 --- a/fs/vfs/fs_pseudofile.c +++ b/fs/vfs/fs_pseudofile.c @@ -353,24 +353,18 @@ static int pseudofile_munmap(FAR struct task_group_s *group, * The inode is released after this call, hence checking if i_crefs <= 1. */ - int ret = inode_lock(); - if (ret >= 0) + if (inode->i_parent == NULL && + atomic_load(&inode->i_crefs) <= 1) { - if (inode->i_parent == NULL && - inode->i_crefs <= 1) + /* Delete the inode metadata */ + + if (inode->i_private) { - /* Delete the inode metadata */ - - if (inode->i_private) - { - fs_heap_free(inode->i_private); - } - - inode->i_private = NULL; - ret = OK; + fs_heap_free(inode->i_private); } - inode_unlock(); + inode->i_private = NULL; + ret = OK; } /* Unkeep the inode when unmapped, decrease refcount */ @@ -501,7 +495,6 @@ int pseudofile_create(FAR struct inode **node, FAR const char *path, goto reserve_err; } - (*node)->i_crefs = 0; (*node)->i_flags = 1; (*node)->u.i_ops = &g_pseudofile_ops; (*node)->i_private = pf; diff --git a/fs/vfs/fs_signalfd.c b/fs/vfs/fs_signalfd.c index 64f9cd61b3..cdd006ca1a 100644 --- a/fs/vfs/fs_signalfd.c +++ b/fs/vfs/fs_signalfd.c @@ -89,7 +89,7 @@ static struct inode g_signalfd_inode = NULL, /* i_parent */ NULL, /* i_peer */ NULL, /* i_child */ - 1, /* i_crefs */ + ATOMIC_VAR_INIT(1), /* i_crefs */ FSNODEFLAG_TYPE_DRIVER, /* i_flags */ { &g_signalfd_fileops /* u */ diff --git a/fs/vfs/fs_timerfd.c b/fs/vfs/fs_timerfd.c index 3b550d16be..a2b939ef57 100644 --- a/fs/vfs/fs_timerfd.c +++ b/fs/vfs/fs_timerfd.c @@ -123,7 +123,7 @@ static struct inode g_timerfd_inode = NULL, /* i_parent */ NULL, /* i_peer */ NULL, /* i_child */ - 1, /* i_crefs */ + ATOMIC_VAR_INIT(1), /* i_crefs */ FSNODEFLAG_TYPE_DRIVER, /* i_flags */ { &g_timerfd_fops /* u */ diff --git a/include/nuttx/fs/fs.h b/include/nuttx/fs/fs.h index 9a85594ff7..3787879d23 100644 --- a/include/nuttx/fs/fs.h +++ b/include/nuttx/fs/fs.h @@ -35,6 +35,7 @@ #include #include +#include #include #include #include @@ -410,7 +411,7 @@ struct inode FAR struct inode *i_parent; /* Link to parent level inode */ FAR struct inode *i_peer; /* Link to same level inode */ FAR struct inode *i_child; /* Link to lower level inode */ - int16_t i_crefs; /* References to inode */ + atomic_short i_crefs; /* References to inode */ uint16_t i_flags; /* Flags for inode */ union inode_ops_u u; /* Inode operations */ ino_t i_ino; /* Inode serial number */