This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch releases/12.8 in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 40e62f4d43aeb9b4cd4d3b3b50dab7cac43d8fe4 Author: hujun5 <[email protected]> AuthorDate: Fri Dec 13 16:50:59 2024 +0800 use atomic to protect f_refs fix regresion from https://github.com/apache/nuttx/pull/14801 Signed-off-by: hujun5 <[email protected]> --- fs/inode/fs_files.c | 48 ++++++++++++++++++++++-------------------------- include/nuttx/fs/fs.h | 3 ++- 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/fs/inode/fs_files.c b/fs/inode/fs_files.c index 42cd054759..fc9be258cc 100644 --- a/fs/inode/fs_files.c +++ b/fs/inode/fs_files.c @@ -76,33 +76,40 @@ static FAR struct file *files_fget_by_index(FAR struct filelist *list, filep = &list->fl_files[l1][l2]; #ifdef CONFIG_FS_REFCOUNT + int32_t refs = 0; + if (filep->f_inode != NULL) { /* When the reference count is zero but the inode has not yet been * released, At this point we should return a null pointer */ - if (filep->f_refs == 0) - { - filep = NULL; - } - else + do { - filep->f_refs++; + refs = atomic_read(&filep->f_refs); + if (refs == 0) + { + filep = NULL; + break; + } } + while (!atomic_try_cmpxchg(&filep->f_refs, &refs, refs + 1)); } else if (new == NULL) { filep = NULL; } - else if (filep->f_refs) - { - filep->f_refs++; - } else { - filep->f_refs = 2; - *new = true; + do + { + if (atomic_cmpxchg(&filep->f_refs, &refs, 2)) + { + *new = true; + break; + } + } + while (!atomic_try_cmpxchg(&filep->f_refs, &refs, refs + 1)); } #else if (filep->f_inode == NULL && new == NULL) @@ -617,7 +624,7 @@ int file_allocate_from_tcb(FAR struct tcb_s *tcb, FAR struct inode *inode, filep->f_inode = inode; filep->f_priv = priv; #ifdef CONFIG_FS_REFCOUNT - filep->f_refs = 1; + atomic_set(&filep->f_refs, 1); #endif #ifdef CONFIG_FDSAN filep->f_tag_fdsan = 0; @@ -847,12 +854,8 @@ void fs_reffilep(FAR struct file *filep) { /* This interface is used to increase the reference count of filep */ - irqstate_t flags; - DEBUGASSERT(filep); - flags = spin_lock_irqsave(NULL); - filep->f_refs++; - spin_unlock_irqrestore(NULL, flags); + atomic_fetch_add(&filep->f_refs, 1); } /**************************************************************************** @@ -869,20 +872,13 @@ void fs_reffilep(FAR struct file *filep) int fs_putfilep(FAR struct file *filep) { - irqstate_t flags; int ret = 0; - int refs; DEBUGASSERT(filep); - flags = spin_lock_irqsave(NULL); - - refs = --filep->f_refs; - - spin_unlock_irqrestore(NULL, flags); /* If refs is zero, the close() had called, closing it now. */ - if (refs == 0) + if (atomic_fetch_sub(&filep->f_refs, 1) == 1) { ret = file_close(filep); if (ret < 0) diff --git a/include/nuttx/fs/fs.h b/include/nuttx/fs/fs.h index e82df41bff..81502ea8ae 100644 --- a/include/nuttx/fs/fs.h +++ b/include/nuttx/fs/fs.h @@ -50,6 +50,7 @@ #include <nuttx/queue.h> #include <nuttx/irq.h> #include <nuttx/spinlock_type.h> +#include <nuttx/atomic.h> /**************************************************************************** * Pre-processor Definitions @@ -461,7 +462,7 @@ struct file { int f_oflags; /* Open mode flags */ #ifdef CONFIG_FS_REFCOUNT - int f_refs; /* Reference count */ + atomic_t f_refs; /* Reference count */ #endif off_t f_pos; /* File position */ FAR struct inode *f_inode; /* Driver or file system interface */
