fs_inode:Change the type of i_crefs to atomic_int

Summary:
  1.Modified the i_crefs from int16_t to atomic_int
  2.Modified the i_crefs add, delete, read, and initialize interfaces to atomic operations
The purpose of this change is to avoid deadlock in cross-core scenarios, where A Core blocks B Core’s request for a write operation to A Core when A Core requests a read operation to B Core.

Signed-off-by: chenrun1 <chenrun1@xiaomi.com>
This commit is contained in:
chenrun1 2024-07-23 19:30:19 +08:00 committed by Xiang Xiao
parent 56bcc3bb12
commit 4cec713dbf
26 changed files with 47 additions and 134 deletions

View File

@ -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;
}

View File

@ -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);

View File

@ -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
};

View File

@ -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? */

View File

@ -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;

View File

@ -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();

View File

@ -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();
}
}
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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)
{

View File

@ -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;

View File

@ -131,7 +131,7 @@ static struct inode g_inotify_inode =
NULL,
NULL,
NULL,
1,
ATOMIC_VAR_INIT(1),
FSNODEFLAG_TYPE_DRIVER,
{
&g_inotify_fops

View File

@ -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;
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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();

View File

@ -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 */

View File

@ -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 */

View File

@ -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;

View File

@ -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 */

View File

@ -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 */

View File

@ -35,6 +35,7 @@
#include <time.h>
#include <dirent.h>
#include <nuttx/atomic.h>
#include <nuttx/mutex.h>
#include <nuttx/semaphore.h>
#include <nuttx/mm/map.h>
@ -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 */