diff --git a/arch/arm/src/common/arm_exit.c b/arch/arm/src/common/arm_exit.c index a0ecd6c971..18d69ecbd9 100644 --- a/arch/arm/src/common/arm_exit.c +++ b/arch/arm/src/common/arm_exit.c @@ -69,18 +69,23 @@ static void _up_dumponexit(FAR struct tcb_s *tcb, FAR void *arg) FAR struct file_struct *filep; #endif int i; + int j; sinfo(" TCB=%p name=%s pid=%d\n", tcb, tcb->argv[0], tcb->pid); sinfo(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state); filelist = tcb->group->tg_filelist; - for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++) + for (i = 0; i < filelist->fl_rows; i++) { - struct inode *inode = filelist->fl_files[i].f_inode; - if (inode) + for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++) { - sinfo(" fd=%d refcount=%d\n", - i, inode->i_crefs); + struct inode *inode = filelist->fl_files[i][j].f_inode; + if (inode) + { + sinfo(" fd=%d refcount=%d\n", + i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j, + inode->i_crefs); + } } } diff --git a/arch/avr/src/common/up_exit.c b/arch/avr/src/common/up_exit.c index 23ffeb1979..92d0e1a992 100644 --- a/arch/avr/src/common/up_exit.c +++ b/arch/avr/src/common/up_exit.c @@ -84,18 +84,23 @@ static void _up_dumponexit(FAR struct tcb_s *tcb, FAR void *arg) FAR struct file_struct *filep; #endif int i; + int j; sinfo(" TCB=%p name=%s pid=%d\n", tcb, tcb->argv[0], tcb->pid); sinfo(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state); filelist = tcb->group->tg_filelist; - for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++) + for (i = 0; i < filelist->fl_rows; i++) { - struct inode *inode = filelist->fl_files[i].f_inode; - if (inode) + for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++) { - sinfo(" fd=%d refcount=%d\n", - i, inode->i_crefs); + struct inode *inode = filelist->fl_files[i][j].f_inode; + if (inode) + { + sinfo(" fd=%d refcount=%d\n", + i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j, + inode->i_crefs); + } } } diff --git a/arch/hc/src/common/up_exit.c b/arch/hc/src/common/up_exit.c index 96763f548f..fc6182b7a9 100644 --- a/arch/hc/src/common/up_exit.c +++ b/arch/hc/src/common/up_exit.c @@ -68,18 +68,23 @@ static void _up_dumponexit(FAR struct tcb_s *tcb, FAR void *arg) FAR struct file_struct *filep; #endif int i; + int j; sinfo(" TCB=%p name=%s pid=%d\n", tcb, tcb->argv[0], tcb->pid); sinfo(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state); filelist = tcb->group->tg_filelist; - for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++) + for (i = 0; i < filelist->fl_rows; i++) { - struct inode *inode = filelist->fl_files[i].f_inode; - if (inode) + for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++) { - sinfo(" fd=%d refcount=%d\n", - i, inode->i_crefs); + struct inode *inode = filelist->fl_files[i][j].f_inode; + if (inode) + { + sinfo(" fd=%d refcount=%d\n", + i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j, + inode->i_crefs); + } } } diff --git a/arch/mips/src/common/mips_exit.c b/arch/mips/src/common/mips_exit.c index c1d657bd8c..0bca718f4d 100644 --- a/arch/mips/src/common/mips_exit.c +++ b/arch/mips/src/common/mips_exit.c @@ -86,18 +86,23 @@ static void _up_dumponexit(FAR struct tcb_s *tcb, FAR void *arg) FAR struct file_struct *filep; #endif int i; + int j; sinfo(" TCB=%p name=%s pid=%d\n", tcb, tcb->argv[0], tcb->pid); sinfo(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state); filelist = tcb->group->tg_filelist; - for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++) + for (i = 0; i < filelist->fl_rows; i++) { - struct inode *inode = filelist->fl_files[i].f_inode; - if (inode) + for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++) { - sinfo(" fd=%d refcount=%d\n", - i, inode->i_crefs); + struct inode *inode = filelist->fl_files[i][j].f_inode; + if (inode) + { + sinfo(" fd=%d refcount=%d\n", + i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j, + inode->i_crefs); + } } } diff --git a/arch/misoc/src/lm32/lm32_exit.c b/arch/misoc/src/lm32/lm32_exit.c index a4d552fb4d..8715dbe4f2 100644 --- a/arch/misoc/src/lm32/lm32_exit.c +++ b/arch/misoc/src/lm32/lm32_exit.c @@ -79,18 +79,23 @@ static void _up_dumponexit(FAR struct tcb_s *tcb, FAR void *arg) FAR struct file_struct *filep; #endif int i; + int j; sinfo(" TCB=%p name=%s pid=%d\n", tcb, tcb->argv[0], tcb->pid); sinfo(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state); filelist = tcb->group->tg_filelist; - for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++) + for (i = 0; i < filelist->fl_rows; i++) { - struct inode *inode = filelist->fl_files[i].f_inode; - if (inode) + for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++) { - sinfo(" fd=%d refcount=%d\n", - i, inode->i_crefssinfo); + struct inode *inode = filelist->fl_files[i][j].f_inode; + if (inode) + { + sinfo(" fd=%d refcount=%d\n", + i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j, + inode->i_crefs); + } } } diff --git a/arch/misoc/src/minerva/minerva_exit.c b/arch/misoc/src/minerva/minerva_exit.c index d3edbeb4b1..da3feb687d 100644 --- a/arch/misoc/src/minerva/minerva_exit.c +++ b/arch/misoc/src/minerva/minerva_exit.c @@ -79,17 +79,23 @@ static void _up_dumponexit(FAR struct tcb_s *tcb, FAR void *arg) FAR struct file_struct *filep; #endif int i; + int j; sinfo(" TCB=%p name=%s pid=%d\n", tcb, tcb->argv[0], tcb->pid); sinfo(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state); filelist = tcb->group->tg_filelist; - for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++) + for (i = 0; i < filelist->fl_rows; i++) { - struct inode *inode = filelist->fl_files[i].f_inode; - if (inode) + for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++) { - sinfo(" fd=%d refcount=%d\n", i, inode->i_crefssinfo); + struct inode *inode = filelist->fl_files[i][j].f_inode; + if (inode) + { + sinfo(" fd=%d refcount=%d\n", + i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j, + inode->i_crefs); + } } } diff --git a/arch/or1k/src/common/up_exit.c b/arch/or1k/src/common/up_exit.c index 3343b82cec..47472b53fc 100644 --- a/arch/or1k/src/common/up_exit.c +++ b/arch/or1k/src/common/up_exit.c @@ -84,18 +84,23 @@ static void _up_dumponexit(FAR struct tcb_s *tcb, FAR void *arg) FAR struct file_struct *filep; #endif int i; + int j; sinfo(" TCB=%p name=%s pid=%d\n", tcb, tcb->argv[0], tcb->pid); sinfo(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state); filelist = tcb->group->tg_filelist; - for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++) + for (i = 0; i < filelist->fl_rows; i++) { - struct inode *inode = filelist->fl_files[i].f_inode; - if (inode != NULL) + for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++) { - sinfo(" fd=%d refcount=%d\n", - i, inode->i_crefssinfo); + struct inode *inode = filelist->fl_files[i][j].f_inode; + if (inode) + { + sinfo(" fd=%d refcount=%d\n", + i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j, + inode->i_crefs); + } } } diff --git a/arch/renesas/src/common/up_exit.c b/arch/renesas/src/common/up_exit.c index 8bcdc6bb2b..07f9b5baeb 100644 --- a/arch/renesas/src/common/up_exit.c +++ b/arch/renesas/src/common/up_exit.c @@ -68,18 +68,23 @@ static void _up_dumponexit(FAR struct tcb_s *tcb, FAR void *arg) FAR struct file_struct *filep; #endif int i; + int j; sinfo(" TCB=%p name=%s\n", tcb, tcb->argv[0]); sinfo(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state); filelist = tcb->group->tg_filelist; - for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++) + for (i = 0; i < filelist->fl_rows; i++) { - struct inode *inode = filelist->fl_files[i].f_inode; - if (inode) + for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++) { - sinfo(" fd=%d refcount=%d\n", - i, inode->i_crefs); + struct inode *inode = filelist->fl_files[i][j].f_inode; + if (inode) + { + sinfo(" fd=%d refcount=%d\n", + i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j, + inode->i_crefs); + } } } diff --git a/arch/risc-v/src/common/riscv_exit.c b/arch/risc-v/src/common/riscv_exit.c index 012972827c..ad59d60649 100644 --- a/arch/risc-v/src/common/riscv_exit.c +++ b/arch/risc-v/src/common/riscv_exit.c @@ -86,18 +86,23 @@ static void _up_dumponexit(FAR struct tcb_s *tcb, FAR void *arg) FAR struct file_struct *filep; #endif int i; + int j; sinfo(" TCB=%p name=%s pid=%d\n", tcb, tcb->argv[0], tcb->pid); sinfo(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state); filelist = tcb->group->tg_filelist; - for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++) + for (i = 0; i < filelist->fl_rows; i++) { - struct inode *inode = filelist->fl_files[i].f_inode; - if (inode) + for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++) { - sinfo(" fd=%d refcount=%d\n", - i, inode->i_crefs); + struct inode *inode = filelist->fl_files[i][j].f_inode; + if (inode) + { + sinfo(" fd=%d refcount=%d\n", + i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j, + inode->i_crefs); + } } } diff --git a/arch/x86/src/common/up_exit.c b/arch/x86/src/common/up_exit.c index cc0b569029..88cd77c0a2 100644 --- a/arch/x86/src/common/up_exit.c +++ b/arch/x86/src/common/up_exit.c @@ -68,18 +68,23 @@ static void _up_dumponexit(FAR struct tcb_s *tcb, FAR void *arg) FAR struct file_struct *filep; #endif int i; + int j; sinfo(" TCB=%p name=%s pid=%d\n", tcb, tcb->argv[0], tcb->pid); sinfo(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state); filelist = tcb->group->tg_filelist; - for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++) + for (i = 0; i < filelist->fl_rows; i++) { - struct inode *inode = filelist->fl_files[i].f_inode; - if (inode) + for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++) { - sinfo(" fd=%d refcount=%d\n", - i, inode->i_crefs); + struct inode *inode = filelist->fl_files[i][j].f_inode; + if (inode) + { + sinfo(" fd=%d refcount=%d\n", + i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j, + inode->i_crefs); + } } } diff --git a/arch/x86_64/src/common/up_exit.c b/arch/x86_64/src/common/up_exit.c index e8fa24f687..7352c45cdb 100644 --- a/arch/x86_64/src/common/up_exit.c +++ b/arch/x86_64/src/common/up_exit.c @@ -63,29 +63,30 @@ #ifdef CONFIG_DUMP_ON_EXIT static void _up_dumponexit(FAR struct tcb_s *tcb, FAR void *arg) { -#if CONFIG_NFILE_DESCRIPTORS > 0 FAR struct filelist *filelist; #ifdef CONFIG_FILE_STREAM FAR struct file_struct *filep; #endif int i; -#endif + int j; sinfo(" TCB=%p name=%s pid=%d\n", tcb, tcb->argv[0], tcb->pid); sinfo(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state); -#if CONFIG_NFILE_DESCRIPTORS > 0 filelist = tcb->group->tg_filelist; - for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++) + for (i = 0; i < filelist->fl_rows; i++) { - struct inode *inode = filelist->fl_files[i].f_inode; - if (inode) + for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++) { - sinfo(" fd=%d refcount=%d\n", - i, inode->i_crefs); + struct inode *inode = filelist->fl_files[i][j].f_inode; + if (inode) + { + sinfo(" fd=%d refcount=%d\n", + i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j, + inode->i_crefs); + } } } -#endif #ifdef CONFIG_FILE_STREAM filep = tcb->group->tg_streamlist->sl_head; diff --git a/arch/x86_64/src/common/up_internal.h b/arch/x86_64/src/common/up_internal.h index 7e0c5280fe..9157662f8f 100644 --- a/arch/x86_64/src/common/up_internal.h +++ b/arch/x86_64/src/common/up_internal.h @@ -57,7 +57,7 @@ * assumed. */ -#if !defined(CONFIG_DEV_CONSOLE) || CONFIG_NFILE_DESCRIPTORS <= 0 +#if !defined(CONFIG_DEV_CONSOLE) # undef USE_SERIALDRIVER # undef USE_EARLYSERIALINIT # undef CONFIG_DEV_LOWCONSOLE @@ -115,9 +115,9 @@ typedef void (*up_vector_t)(void); extern volatile uint64_t *g_current_regs; -/* This is the beginning of heap as provided from up_head.S. This is the first - * address in DRAM after the loaded program+bss+idle stack. The end of the - * heap is CONFIG_RAM_END +/* This is the beginning of heap as provided from up_head.S. This is the + * first address in DRAM after the loaded program+bss+idle stack. The + * end of the heap is CONFIG_RAM_END */ extern uint64_t g_idle_topstack; @@ -128,14 +128,14 @@ extern uint64_t g_idle_topstack; extern uint64_t g_intstackbase; #endif -/* These 'addresses' of these values are setup by the linker script. They are - * not actual uint32_t storage locations! They are only used meaningfully in the - * following way: +/* These 'addresses' of these values are setup by the linker script. They + * are not actual uint32_t storage locations! They are only used + * meaningfully in the following way: * * - The linker script defines, for example, the symbol_sdata. * - The declareion extern uint32_t _sdata; makes C happy. C will believe - * that the value _sdata is the address of a uint32_t variable _data (it is - * not!). + * that the value _sdata is the address of a uint32_t variable _data + * (it is not!). * - We can recoved the linker value then by simply taking the address of * of _data. like: uint32_t *pdata = &_sdata; */ @@ -202,13 +202,8 @@ void up_addregion(void); /* Defined in xyz_serial.c */ -#if CONFIG_NFILE_DESCRIPTORS > 0 void up_earlyserialinit(void); void up_serialinit(void); -#else -# define up_earlyserialinit() -# define up_serialinit() -#endif /* Defined in xyz_watchdog.c */ diff --git a/arch/xtensa/src/common/xtensa_exit.c b/arch/xtensa/src/common/xtensa_exit.c index e9243e6a71..06f1efe707 100644 --- a/arch/xtensa/src/common/xtensa_exit.c +++ b/arch/xtensa/src/common/xtensa_exit.c @@ -85,18 +85,23 @@ static void _xtensa_dumponexit(FAR struct tcb_s *tcb, FAR void *arg) FAR struct file_struct *filep; #endif int i; + int j; sinfo(" TCB=%p name=%s pid=%d\n", tcb, tcb->argv[0], tcb->pid); sinfo(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state); filelist = tcb->group->tg_filelist; - for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++) + for (i = 0; i < filelist->fl_rows; i++) { - struct inode *inode = filelist->fl_files[i].f_inode; - if (inode) + for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++) { - sinfo(" fd=%d refcount=%d\n", - i, inode->i_crefs); + struct inode *inode = filelist->fl_files[i][j].f_inode; + if (inode) + { + sinfo(" fd=%d refcount=%d\n", + i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j, + inode->i_crefs); + } } } diff --git a/arch/z16/src/common/z16_exit.c b/arch/z16/src/common/z16_exit.c index 15a3487e91..4e29a34c4d 100644 --- a/arch/z16/src/common/z16_exit.c +++ b/arch/z16/src/common/z16_exit.c @@ -68,18 +68,23 @@ static void _z16_dumponexit(FAR struct tcb_s *tcb, FAR void *arg) FAR struct file_struct *filep; #endif int i; + int j; sinfo(" TCB=%p name=%s\n", tcb, tcb->argv[0]); sinfo(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state); filelist = tcb->group->tg_filelist; - for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++) + for (i = 0; i < filelist->fl_rows; i++) { - struct inode *inode = filelist->fl_files[i].f_inode; - if (inode) + for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++) { - sinfo(" fd=%d refcount=%d\n", - i, inode->i_crefs); + struct inode *inode = filelist->fl_files[i][j].f_inode; + if (inode) + { + sinfo(" fd=%d refcount=%d\n", + i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j, + inode->i_crefs); + } } } diff --git a/arch/z80/src/common/z80_exit.c b/arch/z80/src/common/z80_exit.c index 495bf27dcb..6173866427 100644 --- a/arch/z80/src/common/z80_exit.c +++ b/arch/z80/src/common/z80_exit.c @@ -70,18 +70,23 @@ static void _up_dumponexit(FAR struct tcb_s *tcb, FAR void *arg) FAR struct file_struct *filep; #endif int i; + int j; sinfo(" TCB=%p name=%s\n", tcb, tcb->argv[0]); sinfo(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state); filelist = tcb->group->tg_filelist; - for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++) + for (i = 0; i < filelist->fl_rows; i++) { - struct inode *inode = filelist->fl_files[i].f_inode; - if (inode) + for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++) { - sinfo(" fd=%d refcount=%d\n", - i, inode->i_crefs); + struct inode *inode = filelist->fl_files[i][j].f_inode; + if (inode) + { + sinfo(" fd=%d refcount=%d\n", + i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j, + inode->i_crefs); + } } } diff --git a/boards/sim/sim/sim/src/sim_zoneinfo.c b/boards/sim/sim/sim/src/sim_zoneinfo.c index 16059a7c49..554bed63be 100644 --- a/boards/sim/sim/sim/src/sim_zoneinfo.c +++ b/boards/sim/sim/sim/src/sim_zoneinfo.c @@ -62,10 +62,6 @@ # error "Mountpoint support is disabled" #endif -#if CONFIG_NFILE_DESCRIPTORS < 4 -# error "Not enough file descriptors" -#endif - #ifndef CONFIG_FS_ROMFS # error "ROMFS support not enabled" #endif diff --git a/fs/hostfs/hostfs_rpmsg_server.c b/fs/hostfs/hostfs_rpmsg_server.c index c659378425..830cd0f095 100644 --- a/fs/hostfs/hostfs_rpmsg_server.c +++ b/fs/hostfs/hostfs_rpmsg_server.c @@ -44,8 +44,10 @@ struct hostfs_rpmsg_server_s { struct rpmsg_endpoint ept; - struct file files[CONFIG_NFILE_DESCRIPTORS]; - void *dirs[CONFIG_NFILE_DESCRIPTORS]; + FAR struct file **files; + FAR void **dirs; + int file_rows; + int dir_nums; sem_t sem; }; @@ -154,33 +156,181 @@ static const rpmsg_ept_cb g_hostfs_rpmsg_handler[] = * Private Functions ****************************************************************************/ +static int hostfs_rpmsg_attach_file(FAR struct hostfs_rpmsg_server_s *priv, + FAR struct file *filep) +{ + FAR struct file **tmp; + int ret; + int i; + int j; + + nxsem_wait(&priv->sem); + + for (i = 0; i < priv->file_rows; i++) + { + for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++) + { + if (priv->files[i][j].f_inode == NULL) + { + memcpy(&priv->files[i][j], filep, sizeof(*filep)); + ret = i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j; + goto out; + } + } + } + + tmp = kmm_realloc(priv->files, sizeof(FAR struct file *) * (i + 1)); + DEBUGASSERT(tmp); + if (tmp == NULL) + { + ret = -ENFILE; + goto out; + } + + tmp[i] = kmm_zalloc(sizeof(struct file) * + CONFIG_NFILE_DESCRIPTORS_PER_BLOCK); + DEBUGASSERT(tmp[i]); + if (tmp[i] == NULL) + { + kmm_free(tmp); + ret = -ENFILE; + goto out; + } + + priv->files = tmp; + priv->file_rows++; + + memcpy(&priv->files[i][0], filep, sizeof(*filep)); + ret = i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; + +out: + nxsem_post(&priv->sem); + return ret; +} + +static int hostfs_rpmsg_detach_file(FAR struct hostfs_rpmsg_server_s *priv, + int fd, FAR struct file *filep) +{ + struct file *tfilep; + + if (fd < 0 || fd >= priv->file_rows * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK) + { + return -EBADF; + } + + nxsem_wait(&priv->sem); + tfilep = &priv->files[fd / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK] + [fd % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK]; + memcpy(filep, tfilep, sizeof(*filep)); + memset(tfilep, 0, sizeof(*tfilep)); + nxsem_post(&priv->sem); + + return 0; +} + +static FAR struct file *hostfs_rpmsg_get_file( + FAR struct hostfs_rpmsg_server_s *priv, + int fd) +{ + FAR struct file *filep; + + if (fd < 0 || fd >= priv->file_rows * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK) + { + return NULL; + } + + nxsem_wait(&priv->sem); + filep = &priv->files[fd / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK] + [fd % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK]; + nxsem_post(&priv->sem); + + return filep; +} + +static int hostfs_rpmsg_attach_dir(FAR struct hostfs_rpmsg_server_s *priv, + FAR void *dir) +{ + FAR void **tmp; + int i; + + nxsem_wait(&priv->sem); + for (i = 1; i < priv->dir_nums; i++) + { + if (priv->dirs[i] == NULL) + { + priv->dirs[i] = dir; + nxsem_post(&priv->sem); + return i; + } + } + + tmp = kmm_realloc(priv->dirs, sizeof(FAR void *) * + (priv->dir_nums + CONFIG_NFILE_DESCRIPTORS_PER_BLOCK)); + DEBUGASSERT(tmp); + if (tmp == NULL) + { + nxsem_post(&priv->sem); + return -ENOMEM; + } + + priv->dirs = tmp; + priv->dir_nums += CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; + + priv->dirs[i] = dir; + nxsem_post(&priv->sem); + return i; +} + +static void *hostfs_rpmsg_detach_dir(FAR struct hostfs_rpmsg_server_s *priv, + int fd) +{ + FAR void *dir = NULL; + + if (fd >= 1 && fd < priv->dir_nums) + { + nxsem_wait(&priv->sem); + dir = priv->dirs[fd]; + priv->dirs[fd] = NULL; + nxsem_post(&priv->sem); + } + + return dir; +} + +static FAR void *hostfs_rpmsg_get_dir( + FAR struct hostfs_rpmsg_server_s *priv, + int fd) +{ + FAR void *dir = NULL; + + if (fd >= 1 && fd < priv->dir_nums) + { + nxsem_wait(&priv->sem); + dir = priv->dirs[fd]; + nxsem_post(&priv->sem); + } + + return dir; +} + static int hostfs_rpmsg_open_handler(FAR struct rpmsg_endpoint *ept, FAR void *data, size_t len, uint32_t src, FAR void *priv_) { - FAR struct hostfs_rpmsg_server_s *priv = priv_; FAR struct hostfs_rpmsg_open_s *msg = data; - int i; - int ret = -ENOENT; + struct file file; + int ret; - nxsem_wait(&priv->sem); - for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++) + ret = file_open(&file, msg->pathname, msg->flags, msg->mode); + if (ret >= 0) { - if (!priv->files[i].f_inode) + ret = hostfs_rpmsg_attach_file(priv_, &file); + if (ret < 0) { - ret = file_open(&priv->files[i], msg->pathname, msg->flags, - msg->mode); - if (ret >= 0) - { - ret = i; - } - - break; + file_close(&file); } } - nxsem_post(&priv->sem); - msg->header.result = ret; return rpmsg_send(ept, msg, sizeof(*msg)); } @@ -189,15 +339,14 @@ static int hostfs_rpmsg_close_handler(FAR struct rpmsg_endpoint *ept, FAR void *data, size_t len, uint32_t src, FAR void *priv_) { - FAR struct hostfs_rpmsg_server_s *priv = priv_; FAR struct hostfs_rpmsg_close_s *msg = data; - int ret = -ENOENT; + struct file file; + int ret; - if (msg->fd >= 0 && msg->fd < CONFIG_NFILE_DESCRIPTORS) + ret = hostfs_rpmsg_detach_file(priv_, msg->fd, &file); + if (ret >= 0) { - nxsem_wait(&priv->sem); - ret = file_close(&priv->files[msg->fd]); - nxsem_post(&priv->sem); + ret = file_close(&file); } msg->header.result = ret; @@ -208,9 +357,9 @@ static int hostfs_rpmsg_read_handler(FAR struct rpmsg_endpoint *ept, FAR void *data, size_t len, uint32_t src, FAR void *priv_) { - FAR struct hostfs_rpmsg_server_s *priv = priv_; FAR struct hostfs_rpmsg_read_s *msg = data; FAR struct hostfs_rpmsg_read_s *rsp; + FAR struct file *filep; int ret = -ENOENT; uint32_t space; @@ -228,9 +377,10 @@ static int hostfs_rpmsg_read_handler(FAR struct rpmsg_endpoint *ept, space = msg->count; } - if (msg->fd >= 0 && msg->fd < CONFIG_NFILE_DESCRIPTORS) + filep = hostfs_rpmsg_get_file(priv_, msg->fd); + if (filep != NULL) { - ret = file_read(&priv->files[msg->fd], rsp->buf, space); + ret = file_read(filep, rsp->buf, space); } rsp->header.result = ret; @@ -241,13 +391,14 @@ static int hostfs_rpmsg_write_handler(FAR struct rpmsg_endpoint *ept, FAR void *data, size_t len, uint32_t src, FAR void *priv_) { - FAR struct hostfs_rpmsg_server_s *priv = priv_; FAR struct hostfs_rpmsg_write_s *msg = data; + FAR struct file *filep; int ret = -ENOENT; - if (msg->fd >= 0 && msg->fd < CONFIG_NFILE_DESCRIPTORS) + filep = hostfs_rpmsg_get_file(priv_, msg->fd); + if (filep != NULL) { - ret = file_write(&priv->files[msg->fd], msg->buf, msg->count); + ret = file_write(filep, msg->buf, msg->count); } msg->header.result = ret; @@ -258,13 +409,14 @@ static int hostfs_rpmsg_lseek_handler(FAR struct rpmsg_endpoint *ept, FAR void *data, size_t len, uint32_t src, FAR void *priv_) { - FAR struct hostfs_rpmsg_server_s *priv = priv_; FAR struct hostfs_rpmsg_lseek_s *msg = data; + FAR struct file *filep; int ret = -ENOENT; - if (msg->fd >= 0 && msg->fd < CONFIG_NFILE_DESCRIPTORS) + filep = hostfs_rpmsg_get_file(priv_, msg->fd); + if (filep != NULL) { - ret = file_seek(&priv->files[msg->fd], msg->offset, msg->whence); + ret = file_seek(filep, msg->offset, msg->whence); } msg->header.result = ret; @@ -275,13 +427,14 @@ static int hostfs_rpmsg_ioctl_handler(FAR struct rpmsg_endpoint *ept, FAR void *data, size_t len, uint32_t src, FAR void *priv_) { - FAR struct hostfs_rpmsg_server_s *priv = priv_; FAR struct hostfs_rpmsg_ioctl_s *msg = data; + FAR struct file *filep; int ret = -ENOENT; - if (msg->fd >= 0 && msg->fd < CONFIG_NFILE_DESCRIPTORS) + filep = hostfs_rpmsg_get_file(priv_, msg->fd); + if (filep != NULL) { - ret = file_ioctl(&priv->files[msg->fd], msg->request, msg->arg); + ret = file_ioctl(filep, msg->request, msg->arg); } msg->header.result = ret; @@ -292,13 +445,14 @@ static int hostfs_rpmsg_sync_handler(FAR struct rpmsg_endpoint *ept, FAR void *data, size_t len, uint32_t src, FAR void *priv_) { - FAR struct hostfs_rpmsg_server_s *priv = priv_; FAR struct hostfs_rpmsg_sync_s *msg = data; + FAR struct file *filep; int ret = -ENOENT; - if (msg->fd >= 0 && msg->fd < CONFIG_NFILE_DESCRIPTORS) + filep = hostfs_rpmsg_get_file(priv_, msg->fd); + if (filep != NULL) { - ret = file_fsync(&priv->files[msg->fd]); + ret = file_fsync(filep); } msg->header.result = ret; @@ -309,29 +463,23 @@ static int hostfs_rpmsg_dup_handler(FAR struct rpmsg_endpoint *ept, FAR void *data, size_t len, uint32_t src, FAR void *priv_) { - FAR struct hostfs_rpmsg_server_s *priv = priv_; FAR struct hostfs_rpmsg_dup_s *msg = data; - int i; + FAR struct file *filep; + struct file newfile; int ret = -ENOENT; - if (msg->fd >= 0 && msg->fd < CONFIG_NFILE_DESCRIPTORS) + filep = hostfs_rpmsg_get_file(priv_, msg->fd); + if (filep != NULL) { - nxsem_wait(&priv->sem); - for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++) + ret = file_dup2(filep, &newfile); + if (ret >= 0) { - if (!priv->files[i].f_inode) + ret = hostfs_rpmsg_attach_file(priv_, &newfile); + if (ret < 0) { - ret = file_dup2(&priv->files[msg->fd], &priv->files[i]); - if (ret >= 0) - { - ret = i; - } - - break; + file_close(&newfile); } } - - nxsem_post(&priv->sem); } msg->header.result = ret; @@ -342,14 +490,15 @@ static int hostfs_rpmsg_fstat_handler(FAR struct rpmsg_endpoint *ept, FAR void *data, size_t len, uint32_t src, FAR void *priv_) { - FAR struct hostfs_rpmsg_server_s *priv = priv_; FAR struct hostfs_rpmsg_fstat_s *msg = data; + FAR struct file *filep; int ret = -ENOENT; struct stat buf; - if (msg->fd >= 0 && msg->fd < CONFIG_NFILE_DESCRIPTORS) + filep = hostfs_rpmsg_get_file(priv_, msg->fd); + if (filep != NULL) { - ret = file_fstat(&priv->files[msg->fd], &buf); + ret = file_fstat(filep, &buf); if (ret >= 0) { msg->buf = buf; @@ -364,13 +513,14 @@ static int hostfs_rpmsg_ftruncate_handler(FAR struct rpmsg_endpoint *ept, FAR void *data, size_t len, uint32_t src, FAR void *priv_) { - FAR struct hostfs_rpmsg_server_s *priv = priv_; FAR struct hostfs_rpmsg_ftruncate_s *msg = data; + FAR struct file *filep; int ret = -ENOENT; - if (msg->fd >= 0 && msg->fd < CONFIG_NFILE_DESCRIPTORS) + filep = hostfs_rpmsg_get_file(priv_, msg->fd); + if (filep != NULL) { - ret = file_truncate(&priv->files[msg->fd], msg->length); + ret = file_truncate(filep, msg->length); } msg->header.result = ret; @@ -381,28 +531,14 @@ static int hostfs_rpmsg_opendir_handler(FAR struct rpmsg_endpoint *ept, FAR void *data, size_t len, uint32_t src, FAR void *priv_) { - FAR struct hostfs_rpmsg_server_s *priv = priv_; FAR struct hostfs_rpmsg_opendir_s *msg = data; FAR void *dir; - int i; int ret = -ENOENT; dir = opendir(msg->pathname); if (dir) { - nxsem_wait(&priv->sem); - for (i = 1; i < CONFIG_NFILE_DESCRIPTORS; i++) - { - if (!priv->dirs[i]) - { - priv->dirs[i] = dir; - ret = i; - break; - } - } - - nxsem_post(&priv->sem); - + ret = hostfs_rpmsg_attach_dir(priv_, dir); if (ret < 0) { closedir(dir); @@ -417,14 +553,15 @@ static int hostfs_rpmsg_readdir_handler(FAR struct rpmsg_endpoint *ept, FAR void *data, size_t len, uint32_t src, FAR void *priv_) { - FAR struct hostfs_rpmsg_server_s *priv = priv_; FAR struct hostfs_rpmsg_readdir_s *msg = data; FAR struct dirent *entry; int ret = -ENOENT; + FAR void *dir; - if (msg->fd >= 1 && msg->fd < CONFIG_NFILE_DESCRIPTORS) + dir = hostfs_rpmsg_get_dir(priv_, msg->fd); + if (dir) { - entry = readdir(priv->dirs[msg->fd]); + entry = readdir(dir); if (entry) { msg->type = entry->d_type; @@ -442,13 +579,14 @@ static int hostfs_rpmsg_rewinddir_handler(FAR struct rpmsg_endpoint *ept, FAR void *data, size_t len, uint32_t src, FAR void *priv_) { - FAR struct hostfs_rpmsg_server_s *priv = priv_; FAR struct hostfs_rpmsg_rewinddir_s *msg = data; int ret = -ENOENT; + FAR void *dir; - if (msg->fd >= 1 && msg->fd < CONFIG_NFILE_DESCRIPTORS) + dir = hostfs_rpmsg_get_dir(priv_, msg->fd); + if (dir) { - rewinddir(priv->dirs[msg->fd]); + rewinddir(dir); ret = 0; } @@ -460,17 +598,14 @@ static int hostfs_rpmsg_closedir_handler(FAR struct rpmsg_endpoint *ept, FAR void *data, size_t len, uint32_t src, FAR void *priv_) { - FAR struct hostfs_rpmsg_server_s *priv = priv_; FAR struct hostfs_rpmsg_closedir_s *msg = data; int ret = -ENOENT; + FAR void *dir; - if (msg->fd >= 1 && msg->fd < CONFIG_NFILE_DESCRIPTORS) + dir = hostfs_rpmsg_detach_dir(priv_, msg->fd); + if (dir) { - ret = closedir(priv->dirs[msg->fd]); - nxsem_wait(&priv->sem); - priv->dirs[msg->fd] = NULL; - nxsem_post(&priv->sem); - ret = ret ? -get_errno() : 0; + ret = closedir(dir) ? -get_errno() : 0; } msg->header.result = ret; @@ -603,16 +738,22 @@ static void hostfs_rpmsg_ns_unbind(FAR struct rpmsg_endpoint *ept) { FAR struct hostfs_rpmsg_server_s *priv = ept->priv; int i; + int j; - for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++) + for (i = 0; i < priv->file_rows; i++) { - if (priv->files[i].f_inode) + for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++) { - file_close(&priv->files[i]); + if (priv->files[i][j].f_inode) + { + file_close(&priv->files[i][j]); + } } + + kmm_free(priv->files[i]); } - for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++) + for (i = 0; i < priv->dir_nums; i++) { if (priv->dirs[i]) { @@ -623,6 +764,8 @@ static void hostfs_rpmsg_ns_unbind(FAR struct rpmsg_endpoint *ept) rpmsg_destroy_ept(&priv->ept); nxsem_destroy(&priv->sem); + kmm_free(priv->files); + kmm_free(priv->dirs); kmm_free(priv); } diff --git a/fs/inode/fs_files.c b/fs/inode/fs_files.c index 137184c64b..0894e9c1a4 100644 --- a/fs/inode/fs_files.c +++ b/fs/inode/fs_files.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -56,6 +57,50 @@ static int _files_semtake(FAR struct filelist *list) #define _files_semgive(list) nxsem_post(&list->fl_sem) +/**************************************************************************** + * Name: files_extend + ****************************************************************************/ + +static int files_extend(FAR struct filelist *list, size_t row) +{ + FAR struct file **tmp; + int i; + + if (row <= list->fl_rows) + { + return 0; + } + + tmp = kmm_realloc(list->fl_files, sizeof(FAR struct file *) * row); + DEBUGASSERT(tmp); + if (tmp == NULL) + { + return -ENFILE; + } + + i = list->fl_rows; + do + { + tmp[i] = kmm_zalloc(sizeof(struct file) * + CONFIG_NFILE_DESCRIPTORS_PER_BLOCK); + if (tmp[i] == NULL) + { + while (--i >= list->fl_rows) + { + kmm_free(tmp[i]); + } + + kmm_free(tmp); + return -ENFILE; + } + } + while (++i < row); + + list->fl_files = tmp; + list->fl_rows = row; + return 0; +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -87,6 +132,7 @@ void files_initlist(FAR struct filelist *list) void files_releaselist(FAR struct filelist *list) { int i; + int j; DEBUGASSERT(list); @@ -95,11 +141,18 @@ void files_releaselist(FAR struct filelist *list) * because there should not be any references in this context. */ - for (i = CONFIG_NFILE_DESCRIPTORS; i > 0; i--) + for (i = list->fl_rows - 1; i >= 0; i--) { - file_close(&list->fl_files[i - 1]); + for (j = CONFIG_NFILE_DESCRIPTORS_PER_BLOCK - 1; j >= 0; j--) + { + file_close(&list->fl_files[i][j]); + } + + kmm_free(list->fl_files[i]); } + kmm_free(list->fl_files); + /* Destroy the semaphore */ nxsem_destroy(&list->fl_sem); @@ -120,6 +173,7 @@ int files_allocate(FAR struct inode *inode, int oflags, off_t pos, FAR struct filelist *list; int ret; int i; + int j; /* Get the file descriptor list. It should not be NULL in this context. */ @@ -134,21 +188,188 @@ int files_allocate(FAR struct inode *inode, int oflags, off_t pos, return ret; } - for (i = minfd; i < CONFIG_NFILE_DESCRIPTORS; i++) + /* Calcuate minfd whether is in list->fl_files. + * if not, allocate a new filechunk. + */ + + i = minfd / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; + if (i >= list->fl_rows) { - if (!list->fl_files[i].f_inode) + ret = files_extend(list, i + 1); + if (ret < 0) { - list->fl_files[i].f_oflags = oflags; - list->fl_files[i].f_pos = pos; - list->fl_files[i].f_inode = inode; - list->fl_files[i].f_priv = priv; _files_semgive(list); - return i; + return ret; } } + /* Find free file */ + + j = minfd % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; + do + { + do + { + if (!list->fl_files[i][j].f_inode) + { + list->fl_files[i][j].f_oflags = oflags; + list->fl_files[i][j].f_pos = pos; + list->fl_files[i][j].f_inode = inode; + list->fl_files[i][j].f_priv = priv; + _files_semgive(list); + return i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j; + } + } + 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) + { + list->fl_files[i][0].f_oflags = oflags; + list->fl_files[i][0].f_pos = pos; + list->fl_files[i][0].f_inode = inode; + list->fl_files[i][0].f_priv = priv; + ret = i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; + } + _files_semgive(list); - return -EMFILE; + return ret; +} + +/**************************************************************************** + * Name: files_duplist + * + * Description: + * Duplicate parent task's file descriptors. + * + ****************************************************************************/ + +int files_duplist(FAR struct filelist *plist, FAR struct filelist *clist) +{ + int ret; + int i; + int j; + + ret = _files_semtake(plist); + if (ret < 0) + { + /* Probably canceled */ + + return ret; + } + + for (i = 0; i < plist->fl_rows; i++) + { + for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++) + { + FAR struct file *filep; +#ifdef CONFIG_FDCLONE_STDIO + + /* Determine how many file descriptors to clone. If + * CONFIG_FDCLONE_DISABLE is set, no file descriptors will be + * cloned. If CONFIG_FDCLONE_STDIO is set, only the first + * three descriptors (stdin, stdout, and stderr) will be + * cloned. Otherwise all file descriptors will be cloned. + */ + + if (i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + j >= 3) + { + goto out; + } +#endif + + filep = &plist->fl_files[i][j]; + if (filep->f_inode == NULL || (filep->f_oflags & O_CLOEXEC) != 0) + { + continue; + } + + ret = files_extend(clist, i + 1); + if (ret < 0) + { + goto out; + } + + /* Yes... duplicate it for the child */ + + ret = file_dup2(filep, &clist->fl_files[i][j]); + if (ret < 0) + { + goto out; + } + } + } + +out: + _files_semgive(plist); + return ret; +} + +/**************************************************************************** + * Name: fs_getfilep + * + * Description: + * Given a file descriptor, return the corresponding instance of struct + * file. + * + * Input Parameters: + * fd - The file descriptor + * filep - The location to return the struct file instance + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure. + * + ****************************************************************************/ + +int fs_getfilep(int fd, FAR struct file **filep) +{ + FAR struct filelist *list; + int ret; + + DEBUGASSERT(filep != NULL); + *filep = (FAR struct file *)NULL; + + list = nxsched_get_files(); + + /* The file list can be NULL under two cases: (1) One is an obscure + * cornercase: When memory management debug output is enabled. Then + * there may be attempts to write to stdout from malloc before the group + * data has been allocated. The other other is (2) if this is a kernel + * thread. Kernel threads have no allocated file descriptors. + */ + + if (list == NULL) + { + return -EAGAIN; + } + + if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS_PER_BLOCK * list->fl_rows) + { + return -EBADF; + } + + /* The descriptor is in a valid range to file descriptor... Get the + * thread-specific file list. + */ + + /* And return the file pointer from the list */ + + ret = _files_semtake(list); + if (ret >= 0) + { + *filep = &list->fl_files[fd / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK] + [fd % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK]; + _files_semgive(list); + } + + return OK; } /**************************************************************************** @@ -174,17 +395,17 @@ int nx_dup2(int fd1, int fd2) FAR struct filelist *list; int ret; - if (fd1 < 0 || fd1 >= CONFIG_NFILE_DESCRIPTORS || - fd2 < 0 || fd2 >= CONFIG_NFILE_DESCRIPTORS) - { - return -EBADF; - } - /* Get the file descriptor list. It should not be NULL in this context. */ list = nxsched_get_files(); DEBUGASSERT(list != NULL); + if (fd1 < 0 || fd1 >= CONFIG_NFILE_DESCRIPTORS_PER_BLOCK * list->fl_rows || + fd2 < 0) + { + return -EBADF; + } + ret = _files_semtake(list); if (ret < 0) { @@ -193,16 +414,25 @@ int nx_dup2(int fd1, int fd2) return ret; } - /* Perform the dup2 operation */ - - ret = file_dup2(&list->fl_files[fd1], &list->fl_files[fd2]); - _files_semgive(list); - if (ret < 0) + if (fd2 >= CONFIG_NFILE_DESCRIPTORS_PER_BLOCK * list->fl_rows) { - return ret; + ret = files_extend(list, fd2 / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + 1); + if (ret < 0) + { + _files_semgive(list); + return ret; + } } - return fd2; + /* Perform the dup2 operation */ + + ret = file_dup2(&list->fl_files[fd1 / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK] + [fd1 % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK], + &list->fl_files[fd2 / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK] + [fd2 % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK]); + _files_semgive(list); + + return ret < 0 ? ret : fd2; } /**************************************************************************** @@ -262,23 +492,28 @@ int nx_close(int fd) list = nxsched_get_files(); DEBUGASSERT(list != NULL); - /* If the file was properly opened, there should be an inode assigned */ - - if (fd < 0 || fd >= CONFIG_NFILE_DESCRIPTORS || - !list->fl_files[fd].f_inode) - { - return -EBADF; - } - /* Perform the protected close operation */ ret = _files_semtake(list); - if (ret >= 0) + if (ret < 0) { - ret = file_close(&list->fl_files[fd]); - _files_semgive(list); + return ret; } + /* If the file was properly opened, there should be an inode assigned */ + + if (fd < 0 || fd >= list->fl_rows * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK || + !list->fl_files[fd / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK] + [fd % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK].f_inode) + { + _files_semgive(list); + return -EBADF; + } + + ret = file_close(&list->fl_files[fd / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK] + [fd % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK]); + _files_semgive(list); + return ret; } diff --git a/fs/procfs/fs_procfsproc.c b/fs/procfs/fs_procfsproc.c index 266197e18e..a3af61f65d 100644 --- a/fs/procfs/fs_procfsproc.c +++ b/fs/procfs/fs_procfsproc.c @@ -1024,6 +1024,7 @@ static ssize_t proc_groupfd(FAR struct proc_file_s *procfile, size_t copysize; size_t totalsize; int i; + int j; DEBUGASSERT(group != NULL); @@ -1046,27 +1047,32 @@ static ssize_t proc_groupfd(FAR struct proc_file_s *procfile, /* Examine each open file descriptor */ - for (i = 0, file = group->tg_filelist.fl_files; - i < CONFIG_NFILE_DESCRIPTORS; - i++, file++) + for (i = 0; i < group->tg_filelist.fl_rows; i++) { - /* Is there an inode associated with the file descriptor? */ - - if (file->f_inode && !INODE_IS_SOCKET(file->f_inode)) + for (j = 0, file = group->tg_filelist.fl_files[i]; + j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; + j++, file++) { - linesize = snprintf(procfile->line, STATUS_LINELEN, - "%3d %8ld %04x\n", i, (long)file->f_pos, - file->f_oflags); - copysize = procfs_memcpy(procfile->line, linesize, buffer, - remaining, &offset); + /* Is there an inode associated with the file descriptor? */ - totalsize += copysize; - buffer += copysize; - remaining -= copysize; - - if (totalsize >= buflen) + if (file->f_inode && !INODE_IS_SOCKET(file->f_inode)) { - return totalsize; + linesize = snprintf(procfile->line, STATUS_LINELEN, + "%3d %8ld %04x\n", + i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + + j, (long)file->f_pos, + file->f_oflags); + copysize = procfs_memcpy(procfile->line, linesize, buffer, + remaining, &offset); + + totalsize += copysize; + buffer += copysize; + remaining -= copysize; + + if (totalsize >= buflen) + { + return totalsize; + } } } } @@ -1089,30 +1095,33 @@ static ssize_t proc_groupfd(FAR struct proc_file_s *procfile, /* Examine each open socket descriptor */ - for (i = 0, file = group->tg_filelist.fl_files; - i < CONFIG_NFILE_DESCRIPTORS; - i++, file++) + for (i = 0; i < group->tg_filelist.fl_rows; i++) { - /* Is there an connection associated with the socket descriptor? */ - - if (file->f_inode && INODE_IS_SOCKET(file->f_inode)) + for (j = 0, file = group->tg_filelist.fl_files[i]; + j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; + j++, file++) { - FAR struct socket *socket = file->f_priv; - linesize = snprintf(procfile->line, STATUS_LINELEN, - "%3d %3d %02x", - i + CONFIG_NFILE_DESCRIPTORS, - socket->s_type, - socket->s_flags); - copysize = procfs_memcpy(procfile->line, linesize, buffer, - remaining, &offset); + /* Is there an connection associated with the socket descriptor? */ - totalsize += copysize; - buffer += copysize; - remaining -= copysize; - - if (totalsize >= buflen) + if (file->f_inode && INODE_IS_SOCKET(file->f_inode)) { - return totalsize; + FAR struct socket *socket = file->f_priv; + linesize = snprintf(procfile->line, STATUS_LINELEN, + "%3d %3d %02x", + i * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + + j, socket->s_type, + socket->s_flags); + copysize = procfs_memcpy(procfile->line, linesize, buffer, + remaining, &offset); + + totalsize += copysize; + buffer += copysize; + remaining -= copysize; + + if (totalsize >= buflen) + { + return totalsize; + } } } } diff --git a/fs/vfs/Make.defs b/fs/vfs/Make.defs index 7adc1e88e1..7b35b814ca 100644 --- a/fs/vfs/Make.defs +++ b/fs/vfs/Make.defs @@ -21,7 +21,7 @@ # Common file/socket descriptor support CSRCS += fs_close.c fs_dup.c fs_dup2.c fs_fcntl.c -CSRCS += fs_epoll.c fs_fstat.c fs_fstatfs.c fs_getfilep.c fs_ioctl.c +CSRCS += fs_epoll.c fs_fstat.c fs_fstatfs.c fs_ioctl.c CSRCS += fs_lseek.c fs_mkdir.c fs_open.c fs_poll.c fs_read.c fs_rename.c CSRCS += fs_rmdir.c fs_statfs.c fs_stat.c fs_select.c fs_unlink.c fs_write.c diff --git a/fs/vfs/fs_getfilep.c b/fs/vfs/fs_getfilep.c deleted file mode 100644 index f5b14704fb..0000000000 --- a/fs/vfs/fs_getfilep.c +++ /dev/null @@ -1,92 +0,0 @@ -/**************************************************************************** - * fs/vfs/fs_getfilep.c - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. The - * ASF licenses this file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include -#include -#include - -#include -#include -#include -#include - -#include "inode/inode.h" - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: fs_getfilep - * - * Description: - * Given a file descriptor, return the corresponding instance of struct - * file. NOTE that this function will currently fail if it is provided - * with a socket descriptor. - * - * Input Parameters: - * fd - The file descriptor - * filep - The location to return the struct file instance - * - * Returned Value: - * Zero (OK) is returned on success; a negated errno value is returned on - * any failure. - * - ****************************************************************************/ - -int fs_getfilep(int fd, FAR struct file **filep) -{ - FAR struct filelist *list; - - DEBUGASSERT(filep != NULL); - *filep = (FAR struct file *)NULL; - - if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS) - { - return -EBADF; - } - - /* The descriptor is in a valid range to file descriptor... Get the - * thread-specific file list. - */ - - list = nxsched_get_files(); - - /* The file list can be NULL under two cases: (1) One is an obscure - * cornercase: When memory management debug output is enabled. Then - * there may be attempts to write to stdout from malloc before the group - * data has been allocated. The other other is (2) if this is a kernel - * thread. Kernel threads have no allocated file descriptors. - */ - - if (list == NULL) - { - return -EAGAIN; - } - - /* And return the file pointer from the list */ - - *filep = &list->fl_files[fd]; - return OK; -} diff --git a/include/aio.h b/include/aio.h index a5846da45b..a1455dd19d 100644 --- a/include/aio.h +++ b/include/aio.h @@ -113,11 +113,7 @@ struct aiocb FAR volatile void *aio_buf; /* Location of buffer */ off_t aio_offset; /* File offset */ size_t aio_nbytes; /* Length of transfer */ -#if CONFIG_NFILE_DESCRIPTORS > 127 int16_t aio_fildes; /* File descriptor (should be int) */ -#else - int8_t aio_fildes; /* File descriptor (should be int) */ -#endif int8_t aio_reqprio; /* Request priority offset (not used, should be int) */ uint8_t aio_lio_opcode; /* Operation to be performed (should be int) */ diff --git a/include/limits.h b/include/limits.h index 4d47f4e89e..889d8b774a 100644 --- a/include/limits.h +++ b/include/limits.h @@ -120,10 +120,10 @@ #define _POSIX_MAX_INPUT 255 #define _POSIX_NAME_MAX CONFIG_NAME_MAX #define _POSIX_NGROUPS_MAX 0 -#define _POSIX_OPEN_MAX CONFIG_NFILE_DESCRIPTORS +#define _POSIX_OPEN_MAX INT_MAX #define _POSIX_PATH_MAX CONFIG_PATH_MAX #define _POSIX_PIPE_BUF 512 -#define _POSIX_STREAM_MAX CONFIG_NFILE_DESCRIPTORS +#define _POSIX_STREAM_MAX INT_MAX #define _POSIX_TZNAME_MAX 3 #ifdef CONFIG_SMALL_MEMORY diff --git a/include/nuttx/fs/fs.h b/include/nuttx/fs/fs.h index 676b2cf2dd..4438598127 100644 --- a/include/nuttx/fs/fs.h +++ b/include/nuttx/fs/fs.h @@ -377,12 +377,18 @@ struct file FAR void *f_priv; /* Per file driver private data */ }; -/* This defines a list of files indexed by the file descriptor */ +/* This defines a two layer array of files indexed by the file descriptor. + * Each row of this array is fixed size: CONFIG_NFILE_DESCRIPTORS_PER_BLOCK. + * You can get file instance in filelist by the follow methods: + * (file descriptor / CONFIG_NFILE_DESCRIPTORS_PER_BLOCK) as row index and + * (file descriptor % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK) as column index. + */ struct filelist { - sem_t fl_sem; /* Manage access to the file list */ - struct file fl_files[CONFIG_NFILE_DESCRIPTORS]; + sem_t fl_sem; /* Manage access to the file list */ + uint8_t fl_rows; /* The number of rows of fl_files array */ + FAR struct file **fl_files; /* The pointer of two layer file descriptors array */ }; /* The following structure defines the list of files used for standard C I/O. @@ -713,6 +719,20 @@ void files_initlist(FAR struct filelist *list); void files_releaselist(FAR struct filelist *list); +/**************************************************************************** + * Name: files_duplist + * + * Description: + * Duplicate parent task's file descriptors. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure. + * + ****************************************************************************/ + +int files_duplist(FAR struct filelist *plist, FAR struct filelist *clist); + /**************************************************************************** * Name: file_dup * diff --git a/include/nuttx/net/net.h b/include/nuttx/net/net.h index 1a04f98ce2..21c50df6cc 100644 --- a/include/nuttx/net/net.h +++ b/include/nuttx/net/net.h @@ -77,13 +77,6 @@ # define _NX_RECVFROM(s,b,l,f,a,n) recvfrom(s,b,l,f,a,n) #endif -/* Socket descriptors are the index into the TCB sockets list, offset by the - * following amount. This offset is used to distinguish file descriptors from - * socket descriptors - */ - -#define __SOCKFD_OFFSET CONFIG_NFILE_DESCRIPTORS - /* Capabilities of a socket */ #define SOCKCAP_NONBLOCKING (1 << 0) /* Bit 0: Socket supports non-blocking diff --git a/include/sys/select.h b/include/sys/select.h index 128b7d0fa4..11b7c97e32 100644 --- a/include/sys/select.h +++ b/include/sys/select.h @@ -37,7 +37,7 @@ /* Get the total number of descriptors that we will have to support */ -#define FD_SETSIZE CONFIG_NFILE_DESCRIPTORS +#define FD_SETSIZE 256 /* We will use a 32-bit bitsets to represent the set of descriptors. How * many uint32_t's do we need to span all descriptors? diff --git a/libs/libc/spawn/lib_psfa_addclose.c b/libs/libc/spawn/lib_psfa_addclose.c index 84edf75ff2..9a86436202 100644 --- a/libs/libc/spawn/lib_psfa_addclose.c +++ b/libs/libc/spawn/lib_psfa_addclose.c @@ -64,7 +64,7 @@ int posix_spawn_file_actions_addclose( { FAR struct spawn_close_file_action_s *entry; - DEBUGASSERT(file_actions && fd >= 0 && fd < CONFIG_NFILE_DESCRIPTORS); + DEBUGASSERT(file_actions && fd >= 0); /* Allocate the action list entry */ diff --git a/libs/libc/spawn/lib_psfa_adddup2.c b/libs/libc/spawn/lib_psfa_adddup2.c index e5308a6904..97cc04557f 100644 --- a/libs/libc/spawn/lib_psfa_adddup2.c +++ b/libs/libc/spawn/lib_psfa_adddup2.c @@ -65,9 +65,7 @@ int posix_spawn_file_actions_adddup2( { FAR struct spawn_dup2_file_action_s *entry; - DEBUGASSERT(file_actions && - fd1 >= 0 && fd1 < CONFIG_NFILE_DESCRIPTORS && - fd2 >= 0 && fd2 < CONFIG_NFILE_DESCRIPTORS); + DEBUGASSERT(file_actions && fd1 >= 0 && fd2 >= 0); /* Allocate the action list entry */ diff --git a/libs/libc/spawn/lib_psfa_addopen.c b/libs/libc/spawn/lib_psfa_addopen.c index 9c43772701..e66a059a03 100644 --- a/libs/libc/spawn/lib_psfa_addopen.c +++ b/libs/libc/spawn/lib_psfa_addopen.c @@ -79,16 +79,16 @@ * ****************************************************************************/ -int posix_spawn_file_actions_addopen(FAR posix_spawn_file_actions_t *file_actions, - int fd, FAR const char *path, int oflags, - mode_t mode) +int posix_spawn_file_actions_addopen( + FAR posix_spawn_file_actions_t *file_actions, + int fd, FAR const char *path, int oflags, + mode_t mode) { FAR struct spawn_open_file_action_s *entry; size_t len; size_t alloc; - DEBUGASSERT(file_actions && path && - fd >= 0 && fd < CONFIG_NFILE_DESCRIPTORS); + DEBUGASSERT(file_actions && path && fd >= 0); /* Get the size of the action including storage for the path plus its NUL * terminating character. @@ -111,10 +111,11 @@ int posix_spawn_file_actions_addopen(FAR posix_spawn_file_actions_t *file_action entry->fd = fd; entry->oflags = oflags; entry->mode = mode; - strncpy(entry->path, path, len+1); + strncpy(entry->path, path, len + 1); /* And add it to the file action list */ - add_file_action(file_actions, (FAR struct spawn_general_file_action_s *)entry); + add_file_action(file_actions, + (FAR struct spawn_general_file_action_s *)entry); return OK; } diff --git a/libs/libc/unistd/lib_sysconf.c b/libs/libc/unistd/lib_sysconf.c index 9e135bac67..84e37ab1b1 100644 --- a/libs/libc/unistd/lib_sysconf.c +++ b/libs/libc/unistd/lib_sysconf.c @@ -208,7 +208,7 @@ long sysconf(int name) switch (name) { case _SC_OPEN_MAX: - return CONFIG_NFILE_DESCRIPTORS; + return _POSIX_OPEN_MAX; case _SC_ATEXIT_MAX: #ifdef CONFIG_SCHED_EXIT_MAX diff --git a/net/socket/accept.c b/net/socket/accept.c index 130dd03686..772a27354d 100644 --- a/net/socket/accept.c +++ b/net/socket/accept.c @@ -229,6 +229,7 @@ int accept(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen) { FAR struct socket *psock = sockfd_socket(sockfd); FAR struct socket *newsock; + FAR struct file *filep; int newfd; int errcode; int ret; @@ -246,7 +247,7 @@ int accept(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen) * used in the wrong context. */ - if ((unsigned int)sockfd < CONFIG_NFILE_DESCRIPTORS) + if (fs_getfilep(sockfd, &filep) == 0) { errcode = ENOTSOCK; } diff --git a/net/socket/listen.c b/net/socket/listen.c index 8f2355f9df..83f88a7cd3 100644 --- a/net/socket/listen.c +++ b/net/socket/listen.c @@ -29,6 +29,8 @@ #include #include +#include + #include "socket/socket.h" /**************************************************************************** @@ -128,6 +130,7 @@ int psock_listen(FAR struct socket *psock, int backlog) int listen(int sockfd, int backlog) { FAR struct socket *psock = sockfd_socket(sockfd); + FAR struct file *filep; int errcode; int ret; @@ -140,7 +143,7 @@ int listen(int sockfd, int backlog) * descriptor used in the wrong context. */ - if ((unsigned int)sockfd < CONFIG_NFILE_DESCRIPTORS) + if (fs_getfilep(sockfd, &filep) == 0) { errcode = ENOTSOCK; } diff --git a/net/socket/net_dup.c b/net/socket/net_dup.c deleted file mode 100644 index 9fbf60dd30..0000000000 --- a/net/socket/net_dup.c +++ /dev/null @@ -1,134 +0,0 @@ -/**************************************************************************** - * net/socket/net_dup.c - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. The - * ASF licenses this file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -#include -#include -#include -#include - -#include "socket/socket.h" - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: psock_dup - * - * Description: - * Clone a socket descriptor to an arbitrary descriptor number. - * - * Returned Value: - * On success, returns the number of new socket. On any error, - * a negated errno value is returned. - * - ****************************************************************************/ - -int psock_dup(FAR struct socket *psock, int minsd) -{ - FAR struct socket *psock2; - int sockfd2; - int ret; - - /* Make sure that the minimum socket descriptor is within the legal range. - * The minimum value we receive is relative to file descriptor 0; we need - * map it relative of the first socket descriptor. - */ - - if (minsd >= CONFIG_NFILE_DESCRIPTORS) - { - minsd -= CONFIG_NFILE_DESCRIPTORS; - } - else - { - minsd = 0; - } - - /* Lock the scheduler throughout the following */ - - sched_lock(); - - /* Verify that the sockfd corresponds to valid, allocated socket */ - - if (!psock || psock->s_crefs <= 0) - { - ret = -EBADF; - goto errout; - } - - /* Allocate a new socket descriptor */ - - sockfd2 = sockfd_allocate(minsd); - if (sockfd2 < 0) - { - ret = -ENFILE; - goto errout; - } - - /* Get the socket structure underlying the new descriptor */ - - psock2 = sockfd_socket(sockfd2); - if (!psock2) - { - ret = -ENOSYS; /* Should not happen */ - goto errout_with_sockfd; - } - - /* Duplicate the socket state */ - - ret = psock_dup2(psock, psock2); - if (ret < 0) - { - goto errout_with_sockfd; - } - - sched_unlock(); - return sockfd2; - -errout_with_sockfd: - sockfd_release(sockfd2); - -errout: - sched_unlock(); - return ret; -} - -/**************************************************************************** - * Name: net_dup - * - * Description: - * Clone a socket descriptor to an arbitrary descriptor number. - * - * Returned Value: - * On success, returns the number of new socket. On any error, - * a negated errno value is returned. - * - ****************************************************************************/ - -int net_dup(int sockfd, int minsd) -{ - return psock_dup(sockfd_socket(sockfd), minsd); -} diff --git a/sched/Kconfig b/sched/Kconfig index 2201df6407..b2f69f1cff 100644 --- a/sched/Kconfig +++ b/sched/Kconfig @@ -1058,12 +1058,12 @@ config SDCLONE_DISABLE descriptors by task_create() when a new task is started. If set, all sockets will appear to be closed in the new task. -config NFILE_DESCRIPTORS - int "Maximum number of file descriptors per task" - default 16 +config NFILE_DESCRIPTORS_PER_BLOCK + int "The number of file descriptors per block" + default 8 range 3 99999 ---help--- - The maximum number of file descriptors per task (one for each open) + The number of file descriptors per block(one for each open) config FILE_STREAM bool "Enable FILE stream" diff --git a/sched/group/group_setuptaskfiles.c b/sched/group/group_setuptaskfiles.c index 41fc7eadf1..43c6434930 100644 --- a/sched/group/group_setuptaskfiles.c +++ b/sched/group/group_setuptaskfiles.c @@ -25,94 +25,12 @@ #include #include -#include -#include #include -#include #include "sched/sched.h" #include "group/group.h" -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/* Determine how many file descriptors to clone. If CONFIG_FDCLONE_DISABLE - * is set, no file descriptors will be cloned. If CONFIG_FDCLONE_STDIO is - * set, only the first three descriptors (stdin, stdout, and stderr) will - * be cloned. Otherwise all file descriptors will be cloned. - */ - -#if defined(CONFIG_FDCLONE_STDIO) && CONFIG_NFILE_DESCRIPTORS > 3 -# define NFDS_TOCLONE 3 -#else -# define NFDS_TOCLONE CONFIG_NFILE_DESCRIPTORS -#endif - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: sched_dupfiles - * - * Description: - * Duplicate parent task's file descriptors. - * - * Input Parameters: - * tcb - tcb of the new task. - * - * Returned Value: - * None - * - ****************************************************************************/ - -#ifndef CONFIG_FDCLONE_DISABLE -static inline void sched_dupfiles(FAR struct task_tcb_s *tcb) -{ - /* The parent task is the one at the head of the ready-to-run list */ - - FAR struct tcb_s *rtcb = this_task(); - FAR struct file *parent; - FAR struct file *child; - int i; - - DEBUGASSERT(tcb && tcb->cmn.group && rtcb->group); - - /* Duplicate the file descriptors. This will be either all of the - * file descriptors or just the first three (stdin, stdout, and stderr) - * if CONFIG_FDCLONE_STDIO is defined. NFSDS_TOCLONE is set - * accordingly above. - */ - - /* Get pointers to the parent and child task file lists */ - - parent = rtcb->group->tg_filelist.fl_files; - child = tcb->cmn.group->tg_filelist.fl_files; - - /* Check each file in the parent file list */ - - for (i = 0; i < NFDS_TOCLONE; i++) - { - /* Check if this file is opened by the parent. We can tell if - * if the file is open because it contain a reference to a non-NULL - * i-node structure. - */ - - if (parent[i].f_inode && - (parent[i].f_oflags & O_CLOEXEC) == 0) - { - /* Yes... duplicate it for the child */ - - file_dup2(&parent[i], &child[i]); - } - } -} -#else /* !CONFIG_FDCLONE_DISABLE */ -# define sched_dupfiles(tcb) -#endif /* !CONFIG_FDCLONE_DISABLE */ - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -138,6 +56,10 @@ static inline void sched_dupfiles(FAR struct task_tcb_s *tcb) int group_setuptaskfiles(FAR struct task_tcb_s *tcb) { FAR struct task_group_s *group = tcb->cmn.group; +#ifndef CONFIG_FDCLONE_DISABLE + FAR struct tcb_s *rtcb = this_task(); + int ret; +#endif DEBUGASSERT(group); #ifndef CONFIG_DISABLE_PTHREAD @@ -149,9 +71,17 @@ int group_setuptaskfiles(FAR struct task_tcb_s *tcb) files_initlist(&group->tg_filelist); +#ifndef CONFIG_FDCLONE_DISABLE + DEBUGASSERT(rtcb->group); + /* Duplicate the parent task's file descriptors */ - sched_dupfiles(tcb); + ret = files_duplist(&rtcb->group->tg_filelist, &group->tg_filelist); + if (ret < 0) + { + return ret; + } +#endif /* Allocate file/socket streams for the new TCB */