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:
parent
56bcc3bb12
commit
4cec713dbf
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -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? */
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
||||
|
@ -131,7 +131,7 @@ static struct inode g_inotify_inode =
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
1,
|
||||
ATOMIC_VAR_INIT(1),
|
||||
FSNODEFLAG_TYPE_DRIVER,
|
||||
{
|
||||
&g_inotify_fops
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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 &&
|
||||
inode->i_crefs <= 1)
|
||||
if (inode->i_parent == NULL && atomic_load(&inode->i_crefs) <= 1)
|
||||
{
|
||||
shmfs_free_object(inode->i_private);
|
||||
inode->i_private = NULL;
|
||||
ret = OK;
|
||||
}
|
||||
|
||||
inode_unlock();
|
||||
}
|
||||
|
||||
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 (inode->i_crefs <= 1)
|
||||
if (atomic_load(&inode->i_crefs) <= 1)
|
||||
{
|
||||
shmfs_free_object(inode->i_private);
|
||||
inode->i_private = NULL;
|
||||
}
|
||||
|
||||
inode_unlock();
|
||||
}
|
||||
|
||||
return ret;
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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();
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -353,11 +353,8 @@ 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 &&
|
||||
inode->i_crefs <= 1)
|
||||
atomic_load(&inode->i_crefs) <= 1)
|
||||
{
|
||||
/* Delete the inode metadata */
|
||||
|
||||
@ -370,9 +367,6 @@ static int pseudofile_munmap(FAR struct task_group_s *group,
|
||||
ret = OK;
|
||||
}
|
||||
|
||||
inode_unlock();
|
||||
}
|
||||
|
||||
/* Unkeep the inode when unmapped, decrease refcount */
|
||||
|
||||
if (ret == OK)
|
||||
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user