Skip to content

Commit

Permalink
fs_inode:Change the type of i_crefs to atomic_int
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
crafcat7 committed Sep 14, 2024
1 parent 11f06eb commit 2f854a4
Show file tree
Hide file tree
Showing 21 changed files with 47 additions and 123 deletions.
7 changes: 1 addition & 6 deletions fs/inode/fs_inodeaddref.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion fs/inode/fs_inodefind.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
35 changes: 1 addition & 34 deletions fs/inode/fs_inoderelease.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,43 +53,10 @@ void inode_release(FAR struct inode *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();
}
}
}
4 changes: 2 additions & 2 deletions fs/inode/fs_inoderemove.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -134,7 +134,7 @@ int inode_remove(FAR const char *path)
* to it
*/

if (node->i_crefs)
if (atomic_load(&inode->i_crefs))

Check failure on line 137 in fs/inode/fs_inoderemove.c

View workflow job for this annotation

GitHub Actions / Linux (sim-02)

'inode' undeclared (first use in this function)

Check failure on line 137 in fs/inode/fs_inoderemove.c

View workflow job for this annotation

GitHub Actions / Linux (sim-02)

'__atomic_load_ptr' undeclared (first use in this function); did you mean '__atomic_load_n'?

Check failure on line 137 in fs/inode/fs_inoderemove.c

View workflow job for this annotation

GitHub Actions / Linux (sim-02)

argument 1 of '__atomic_load' must be a non-void pointer type

Check failure on line 137 in fs/inode/fs_inoderemove.c

View workflow job for this annotation

GitHub Actions / Linux (sim-02)

'inode' undeclared (first use in this function)

Check failure on line 137 in fs/inode/fs_inoderemove.c

View workflow job for this annotation

GitHub Actions / Linux (sim-02)

'__atomic_load_ptr' undeclared (first use in this function); did you mean '__atomic_load_n'?

Check failure on line 137 in fs/inode/fs_inoderemove.c

View workflow job for this annotation

GitHub Actions / Linux (sim-02)

argument 1 of '__atomic_load' must be a non-void pointer type

Check failure on line 137 in fs/inode/fs_inoderemove.c

View workflow job for this annotation

GitHub Actions / Linux (sim-02)

'inode' undeclared (first use in this function)

Check failure on line 137 in fs/inode/fs_inoderemove.c

View workflow job for this annotation

GitHub Actions / Linux (sim-02)

'__atomic_load_ptr' undeclared (first use in this function); did you mean '__atomic_load_n'?

Check failure on line 137 in fs/inode/fs_inoderemove.c

View workflow job for this annotation

GitHub Actions / Linux (sim-02)

argument 1 of '__atomic_load' must be a non-void pointer type

Check failure on line 137 in fs/inode/fs_inoderemove.c

View workflow job for this annotation

GitHub Actions / Linux (sim-02)

'inode' undeclared (first use in this function)

Check failure on line 137 in fs/inode/fs_inoderemove.c

View workflow job for this annotation

GitHub Actions / Linux (sim-01)

'inode' undeclared (first use in this function)

Check failure on line 137 in fs/inode/fs_inoderemove.c

View workflow job for this annotation

GitHub Actions / Linux (sim-01)

'__atomic_load_ptr' undeclared (first use in this function); did you mean '__atomic_load_n'?

Check failure on line 137 in fs/inode/fs_inoderemove.c

View workflow job for this annotation

GitHub Actions / Linux (sim-01)

argument 1 of '__atomic_load' must be a non-void pointer type

Check failure on line 137 in fs/inode/fs_inoderemove.c

View workflow job for this annotation

GitHub Actions / Linux (arm-02)

'inode' undeclared (first use in this function)

Check failure on line 137 in fs/inode/fs_inoderemove.c

View workflow job for this annotation

GitHub Actions / Linux (arm-02)

'__atomic_load_ptr' undeclared (first use in this function); did you mean '__atomic_load_n'?

Check failure on line 137 in fs/inode/fs_inoderemove.c

View workflow job for this annotation

GitHub Actions / Linux (arm-02)

argument 1 of '__atomic_load' must be a non-void pointer type

Check failure on line 137 in fs/inode/fs_inoderemove.c

View workflow job for this annotation

GitHub Actions / msys2 (msys2)

'inode' undeclared (first use in this function)

Check failure on line 137 in fs/inode/fs_inoderemove.c

View workflow job for this annotation

GitHub Actions / msys2 (msys2)

'__atomic_load_ptr' undeclared (first use in this function); did you mean '__atomic_load_n'?

Check failure on line 137 in fs/inode/fs_inoderemove.c

View workflow job for this annotation

GitHub Actions / msys2 (msys2)

argument 1 of '__atomic_load' must be a non-void pointer type
{
return -EBUSY;
}
Expand Down
2 changes: 1 addition & 1 deletion fs/inode/fs_inodereserve.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions fs/mount/fs_mount.c
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,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

Expand Down Expand Up @@ -466,7 +466,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

Expand Down
3 changes: 1 addition & 2 deletions fs/mount/fs_umount2.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions fs/mqueue/mq_open.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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)
{
Expand Down
2 changes: 1 addition & 1 deletion fs/mqueue/mq_unlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
25 changes: 1 addition & 24 deletions fs/semaphore/sem_close.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,42 +81,20 @@ 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);

/* Release and free the inode container. If it has been properly
* unlinked, then the peer pointer should be NULL.
*/

inode_unlock();
#ifdef CONFIG_FS_NOTIFY
notify_close2(inode);
#endif
Expand All @@ -125,7 +103,6 @@ int nxsem_close(FAR sem_t *sem)
return OK;
}

inode_unlock();
return OK;
}

Expand Down
2 changes: 1 addition & 1 deletion fs/semaphore/sem_open.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand Down
2 changes: 1 addition & 1 deletion fs/shm/shm_open.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
35 changes: 12 additions & 23 deletions fs/shm/shmfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,21 +185,15 @@ 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)
inode_lock();
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;
inode_unlock();
return OK;
}

/****************************************************************************
Expand Down Expand Up @@ -267,20 +261,15 @@ 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)
inode_lock();
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;
inode_unlock();
return OK;
}
#endif

Expand Down
2 changes: 1 addition & 1 deletion fs/socket/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
4 changes: 2 additions & 2 deletions fs/vfs/fs_dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion fs/vfs/fs_epoll.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
2 changes: 1 addition & 1 deletion fs/vfs/fs_eventfd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
26 changes: 11 additions & 15 deletions fs/vfs/fs_pseudofile.c
Original file line number Diff line number Diff line change
Expand Up @@ -353,26 +353,23 @@ 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)
inode_lock();
if (inode->i_parent == NULL &&
atomic_load(&inode->i_crefs) <= 1)
{
if (inode->i_parent == NULL &&
inode->i_crefs <= 1)
{
/* Delete the inode metadata */
/* Delete the inode metadata */

if (inode->i_private)
{
fs_heap_free(inode->i_private);
}

inode->i_private = NULL;
ret = OK;
if (inode->i_private)
{
fs_heap_free(inode->i_private);
}

inode_unlock();
inode->i_private = NULL;
ret = OK;
}

inode_unlock();

/* Unkeep the inode when unmapped, decrease refcount */

if (ret == OK)
Expand Down Expand Up @@ -501,7 +498,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;
Expand Down
2 changes: 1 addition & 1 deletion fs/vfs/fs_signalfd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
2 changes: 1 addition & 1 deletion fs/vfs/fs_timerfd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
Loading

0 comments on commit 2f854a4

Please sign in to comment.