This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 60b25556d4b282c4f14e415e44365216d0457637
Author: ligd <[email protected]>
AuthorDate: Thu Dec 7 16:46:01 2023 +0800

    fs: enhance file_allocate_from_tcb() mulit-threads saftey
    
    Signed-off-by: ligd <[email protected]>
---
 fs/inode/fs_files.c | 58 ++++++++++++++++++++++-------------------------------
 1 file changed, 24 insertions(+), 34 deletions(-)

diff --git a/fs/inode/fs_files.c b/fs/inode/fs_files.c
index 7018bef995..bcf301d397 100644
--- a/fs/inode/fs_files.c
+++ b/fs/inode/fs_files.c
@@ -379,64 +379,54 @@ int file_allocate_from_tcb(FAR struct tcb_s *tcb, FAR 
struct inode *inode,
                            int oflags, off_t pos, FAR void *priv, int minfd,
                            bool addref)
 {
+  int i = minfd / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK;
+  int j = minfd % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK;
   FAR struct filelist *list;
   FAR struct file *filep;
+  irqstate_t flags;
   int ret;
-  int i;
-  int j;
 
   /* Get the file descriptor list.  It should not be NULL in this context. */
 
   list = nxsched_get_files_from_tcb(tcb);
 
-  /* Calculate minfd whether is in list->fl_files.
-   * if not, allocate a new filechunk.
-   */
+  /* Find free file */
+
+  flags = spin_lock_irqsave(&list->fl_lock);
 
-  i = minfd / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK;
-  if (i >= list->fl_rows)
+  for (; ; i++, j = 0)
     {
-      ret = files_extend(list, i + 1);
-      if (ret < 0)
+      if (i >= list->fl_rows)
         {
-          return ret;
-        }
-    }
+          spin_unlock_irqrestore(&list->fl_lock, flags);
 
-  /* Find free file */
+          ret = files_extend(list, i + 1);
+          if (ret < 0)
+            {
+              return ret;
+            }
+
+          flags = spin_lock_irqsave(&list->fl_lock);
+        }
 
-  j = minfd % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK;
-  do
-    {
       do
         {
-          filep = files_fget_by_index(list, i, j);
+          filep = &list->fl_files[i][j];
           if (filep->f_inode == NULL)
             {
+              filep->f_oflags = oflags;
+              filep->f_pos    = pos;
+              filep->f_inode  = inode;
+              filep->f_priv   = priv;
+
               goto found;
             }
         }
       while (++j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK);
-
-      j = 0;
     }
-  while (++i < list->fl_rows);
 
-  /* The space of file array isn't enough, allocate a new filechunk */
-
-  ret = files_extend(list, i + 1);
-  if (ret < 0)
-    {
-      return ret;
-    }
-
-  filep = files_fget_by_index(list, i, 0);
 found:
-
-  filep->f_oflags = oflags;
-  filep->f_pos    = pos;
-  filep->f_inode  = inode;
-  filep->f_priv   = priv;
+  spin_unlock_irqrestore(&list->fl_lock, flags);
 
   if (addref)
     {

Reply via email to