diff --git a/fs/inode/fs_files.c b/fs/inode/fs_files.c index 8374ad06d3041..bf4de35c3b005 100644 --- a/fs/inode/fs_files.c +++ b/fs/inode/fs_files.c @@ -73,9 +73,12 @@ static FAR struct file *files_fget_by_index(FAR struct filelist *list, irqstate_t flags; flags = spin_lock_irqsave(&list->fl_lock); - filep = &list->fl_files[l1][l2]; + spin_unlock_irqrestore(&list->fl_lock, flags); + #ifdef CONFIG_FS_REFCOUNT + + flags = spin_lock_irqsave(&filep->lock); if (filep->f_inode != NULL) { /* When the reference count is zero but the inode has not yet been @@ -84,26 +87,32 @@ static FAR struct file *files_fget_by_index(FAR struct filelist *list, if (filep->f_refs == 0) { + spin_unlock_irqrestore(&filep->lock, flags); filep = NULL; } else { filep->f_refs++; + spin_unlock_irqrestore(&filep->lock, flags); } } else if (new == NULL) { + spin_unlock_irqrestore(&filep->lock, flags); filep = NULL; } else if (filep->f_refs) { filep->f_refs++; + spin_unlock_irqrestore(&filep->lock, flags); } else { filep->f_refs = 2; *new = true; + spin_unlock_irqrestore(&filep->lock, flags); } + #else if (filep->f_inode == NULL && new == NULL) { @@ -111,7 +120,6 @@ static FAR struct file *files_fget_by_index(FAR struct filelist *list, } #endif - spin_unlock_irqrestore(&list->fl_lock, flags); return filep; } @@ -629,6 +637,7 @@ int file_allocate_from_tcb(FAR struct tcb_s *tcb, FAR struct inode *inode, filep->f_priv = priv; #ifdef CONFIG_FS_REFCOUNT filep->f_refs = 1; + spin_lock_init(&filep->lock); #endif #ifdef CONFIG_FDSAN filep->f_tag_fdsan = 0; @@ -861,9 +870,9 @@ void fs_reffilep(FAR struct file *filep) irqstate_t flags; DEBUGASSERT(filep); - flags = spin_lock_irqsave(NULL); + flags = spin_lock_irqsave(&filep->lock); filep->f_refs++; - spin_unlock_irqrestore(NULL, flags); + spin_unlock_irqrestore(&filep->lock, flags); } /**************************************************************************** @@ -885,11 +894,11 @@ int fs_putfilep(FAR struct file *filep) int refs; DEBUGASSERT(filep); - flags = spin_lock_irqsave(NULL); + flags = spin_lock_irqsave(&filep->lock); refs = --filep->f_refs; - spin_unlock_irqrestore(NULL, flags); + spin_unlock_irqrestore(&filep->lock, flags); /* If refs is zero, the close() had called, closing it now. */ diff --git a/include/nuttx/fs/fs.h b/include/nuttx/fs/fs.h index e82df41bffea5..6c17a051797e3 100644 --- a/include/nuttx/fs/fs.h +++ b/include/nuttx/fs/fs.h @@ -462,6 +462,7 @@ struct file int f_oflags; /* Open mode flags */ #ifdef CONFIG_FS_REFCOUNT int f_refs; /* Reference count */ + spinlock_t lock; /* Reference spinlock */ #endif off_t f_pos; /* File position */ FAR struct inode *f_inode; /* Driver or file system interface */