diff --git a/arch/arm/src/common/arm_exit.c b/arch/arm/src/common/arm_exit.c index b538826f10a..1326d150e97 100644 --- a/arch/arm/src/common/arm_exit.c +++ b/arch/arm/src/common/arm_exit.c @@ -69,18 +69,22 @@ 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_NFCHUNK_DESCRIPTORS; 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_NFCHUNK_DESCRIPTORS + j, inode->i_crefs); + } } } diff --git a/arch/avr/src/common/up_exit.c b/arch/avr/src/common/up_exit.c index 09939d6b847..53436b6d527 100644 --- a/arch/avr/src/common/up_exit.c +++ b/arch/avr/src/common/up_exit.c @@ -84,18 +84,22 @@ 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_NFCHUNK_DESCRIPTORS; 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_NFCHUNK_DESCRIPTORS + j, inode->i_crefs); + } } } diff --git a/arch/hc/src/common/up_exit.c b/arch/hc/src/common/up_exit.c index febd544fa00..1d7dcebd243 100644 --- a/arch/hc/src/common/up_exit.c +++ b/arch/hc/src/common/up_exit.c @@ -68,18 +68,22 @@ 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_NFCHUNK_DESCRIPTORS; 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_NFCHUNK_DESCRIPTORS + j, inode->i_crefs); + } } } diff --git a/arch/mips/src/common/mips_exit.c b/arch/mips/src/common/mips_exit.c index 30d421682d4..9ca231f4508 100644 --- a/arch/mips/src/common/mips_exit.c +++ b/arch/mips/src/common/mips_exit.c @@ -86,18 +86,22 @@ 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_NFCHUNK_DESCRIPTORS; 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_NFCHUNK_DESCRIPTORS + j, inode->i_crefs); + } } } diff --git a/arch/misoc/src/lm32/lm32_exit.c b/arch/misoc/src/lm32/lm32_exit.c index 9a779317c0b..b56141ebecd 100644 --- a/arch/misoc/src/lm32/lm32_exit.c +++ b/arch/misoc/src/lm32/lm32_exit.c @@ -79,18 +79,22 @@ 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_NFCHUNK_DESCRIPTORS; 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_NFCHUNK_DESCRIPTORS + j, inode->i_crefs); + } } } diff --git a/arch/misoc/src/minerva/minerva_exit.c b/arch/misoc/src/minerva/minerva_exit.c index f4377666e27..d627df0ea98 100644 --- a/arch/misoc/src/minerva/minerva_exit.c +++ b/arch/misoc/src/minerva/minerva_exit.c @@ -79,17 +79,22 @@ 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_NFCHUNK_DESCRIPTORS; 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_NFCHUNK_DESCRIPTORS + j, inode->i_crefs); + } } } diff --git a/arch/or1k/src/common/up_exit.c b/arch/or1k/src/common/up_exit.c index 4d50254e7fc..1fa0659fda5 100644 --- a/arch/or1k/src/common/up_exit.c +++ b/arch/or1k/src/common/up_exit.c @@ -84,18 +84,22 @@ 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_NFCHUNK_DESCRIPTORS; 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_NFCHUNK_DESCRIPTORS + j, inode->i_crefs); + } } } diff --git a/arch/renesas/src/common/up_exit.c b/arch/renesas/src/common/up_exit.c index b272fcb5f4a..9792f296357 100644 --- a/arch/renesas/src/common/up_exit.c +++ b/arch/renesas/src/common/up_exit.c @@ -68,18 +68,22 @@ 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_NFCHUNK_DESCRIPTORS; 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_NFCHUNK_DESCRIPTORS + 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 b4f797e6cbb..ad8acee7a38 100644 --- a/arch/risc-v/src/common/riscv_exit.c +++ b/arch/risc-v/src/common/riscv_exit.c @@ -86,18 +86,22 @@ 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_NFCHUNK_DESCRIPTORS; 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_NFCHUNK_DESCRIPTORS + j, inode->i_crefs); + } } } diff --git a/arch/x86/src/common/up_exit.c b/arch/x86/src/common/up_exit.c index 22edf7e4d58..d4eb337c856 100644 --- a/arch/x86/src/common/up_exit.c +++ b/arch/x86/src/common/up_exit.c @@ -68,18 +68,22 @@ 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_NFCHUNK_DESCRIPTORS; 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_NFCHUNK_DESCRIPTORS + 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 36808da727f..0e604ecf86e 100644 --- a/arch/x86_64/src/common/up_exit.c +++ b/arch/x86_64/src/common/up_exit.c @@ -63,29 +63,29 @@ #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_NFCHUNK_DESCRIPTORS; 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_NFCHUNK_DESCRIPTORS + 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 7e0c5280feb..2f999172e03 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 @@ -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 fb16154fd92..7dabe24238f 100644 --- a/arch/xtensa/src/common/xtensa_exit.c +++ b/arch/xtensa/src/common/xtensa_exit.c @@ -85,18 +85,22 @@ 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_NFCHUNK_DESCRIPTORS; 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_NFCHUNK_DESCRIPTORS + j, inode->i_crefs); + } } } diff --git a/arch/z16/src/common/z16_exit.c b/arch/z16/src/common/z16_exit.c index f92b03f9d8e..9c33a8edf82 100644 --- a/arch/z16/src/common/z16_exit.c +++ b/arch/z16/src/common/z16_exit.c @@ -68,18 +68,22 @@ 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_NFCHUNK_DESCRIPTORS; 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_NFCHUNK_DESCRIPTORS + j, inode->i_crefs); + } } } diff --git a/arch/z80/src/common/z80_exit.c b/arch/z80/src/common/z80_exit.c index 1a73ac91216..c8b63cc1c8d 100644 --- a/arch/z80/src/common/z80_exit.c +++ b/arch/z80/src/common/z80_exit.c @@ -70,18 +70,22 @@ 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_NFCHUNK_DESCRIPTORS; 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_NFCHUNK_DESCRIPTORS + 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 bf5f2bd8a00..5083c1bdd97 100644 --- a/boards/sim/sim/sim/src/sim_zoneinfo.c +++ b/boards/sim/sim/sim/src/sim_zoneinfo.c @@ -61,10 +61,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 938472e0a55..3e01ece17f0 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_NFCHUNK_DESCRIPTORS; j++) + { + if (priv->files[i][j].f_inode == NULL) + { + memcpy(&priv->files[i][j], filep, sizeof(*filep)); + ret = i * CONFIG_NFCHUNK_DESCRIPTORS + 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_NFCHUNK_DESCRIPTORS); + 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_NFCHUNK_DESCRIPTORS; + +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_NFCHUNK_DESCRIPTORS) + { + return -EBADF; + } + + nxsem_wait(&priv->sem); + tfilep = &priv->files[fd / CONFIG_NFCHUNK_DESCRIPTORS] + [fd % CONFIG_NFCHUNK_DESCRIPTORS]; + 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_NFCHUNK_DESCRIPTORS) + { + return NULL; + } + + nxsem_wait(&priv->sem); + filep = &priv->files[fd / CONFIG_NFCHUNK_DESCRIPTORS] + [fd % CONFIG_NFCHUNK_DESCRIPTORS]; + 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_NFCHUNK_DESCRIPTORS)); + DEBUGASSERT(tmp); + if (tmp == NULL) + { + nxsem_post(&priv->sem); + return -ENOMEM; + } + + priv->dirs = tmp; + priv->dir_nums += CONFIG_NFCHUNK_DESCRIPTORS; + + 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; @@ -609,16 +744,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_NFCHUNK_DESCRIPTORS; 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]) { @@ -629,6 +770,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 4a4d0fe9679..79d21a76907 100644 --- a/fs/inode/fs_files.c +++ b/fs/inode/fs_files.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -57,6 +58,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_NFCHUNK_DESCRIPTORS); + 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 ****************************************************************************/ @@ -100,6 +145,7 @@ void files_initlist(FAR struct filelist *list) void files_releaselist(FAR struct filelist *list) { int i; + int j; DEBUGASSERT(list); @@ -108,11 +154,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_NFCHUNK_DESCRIPTORS - 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); @@ -133,6 +186,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. */ @@ -147,21 +201,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_NFCHUNK_DESCRIPTORS; + 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_NFCHUNK_DESCRIPTORS; + 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_NFCHUNK_DESCRIPTORS + j; + } + } + while (++j < CONFIG_NFCHUNK_DESCRIPTORS); + + 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_NFCHUNK_DESCRIPTORS; + } + _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_NFCHUNK_DESCRIPTORS; 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_NFCHUNK_DESCRIPTORS + 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_NFCHUNK_DESCRIPTORS * 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_NFCHUNK_DESCRIPTORS] + [fd % CONFIG_NFCHUNK_DESCRIPTORS]; + _files_semgive(list); + } + + return OK; } /**************************************************************************** @@ -187,17 +408,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_NFCHUNK_DESCRIPTORS * list->fl_rows || + fd2 < 0) + { + return -EBADF; + } + ret = _files_semtake(list); if (ret < 0) { @@ -206,16 +427,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_NFCHUNK_DESCRIPTORS * list->fl_rows) { - return ret; + ret = files_extend(list, fd2 / CONFIG_NFCHUNK_DESCRIPTORS + 1); + if (ret < 0) + { + _files_semgive(list); + return ret; + } } - return fd2; + /* Perform the dup2 operation */ + + ret = file_dup2(&list->fl_files[fd1 / CONFIG_NFCHUNK_DESCRIPTORS] + [fd1 % CONFIG_NFCHUNK_DESCRIPTORS], + &list->fl_files[fd2 / CONFIG_NFCHUNK_DESCRIPTORS] + [fd2 % CONFIG_NFCHUNK_DESCRIPTORS]); + _files_semgive(list); + + return ret < 0 ? ret : fd2; } /**************************************************************************** @@ -275,23 +505,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_NFCHUNK_DESCRIPTORS || + !list->fl_files[fd / CONFIG_NFCHUNK_DESCRIPTORS] + [fd % CONFIG_NFCHUNK_DESCRIPTORS].f_inode) + { + _files_semgive(list); + return -EBADF; + } + + ret = file_close(&list->fl_files[fd / CONFIG_NFCHUNK_DESCRIPTORS] + [fd % CONFIG_NFCHUNK_DESCRIPTORS]); + _files_semgive(list); + return ret; } diff --git a/fs/mmap/fs_rammap.c b/fs/mmap/fs_rammap.c index d81832e2956..23e6ceb330d 100644 --- a/fs/mmap/fs_rammap.c +++ b/fs/mmap/fs_rammap.c @@ -140,12 +140,6 @@ FAR void *rammap(int fd, size_t length, off_t offset) /* Allocate a region of memory of the specified size */ - if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS) - { - errcode = EBADF; - goto errout; - } - alloc = (FAR uint8_t *)kumm_malloc(sizeof(struct fs_rammap_s) + length); if (!alloc) { diff --git a/fs/procfs/fs_procfsproc.c b/fs/procfs/fs_procfsproc.c index c16a855aba7..d1772e76145 100644 --- a/fs/procfs/fs_procfsproc.c +++ b/fs/procfs/fs_procfsproc.c @@ -1080,6 +1080,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); @@ -1102,27 +1103,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_NFCHUNK_DESCRIPTORS; + 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_NFCHUNK_DESCRIPTORS + 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; + } } } } @@ -1145,30 +1151,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_NFCHUNK_DESCRIPTORS; + 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_NFCHUNK_DESCRIPTORS + 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 3b92ef6807d..aeb521e5796 100644 --- a/fs/vfs/Make.defs +++ b/fs/vfs/Make.defs @@ -36,7 +36,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 ed6d16b1908..00000000000 --- a/fs/vfs/fs_getfilep.c +++ /dev/null @@ -1,107 +0,0 @@ -/**************************************************************************** - * fs/vfs/fs_getfilep.c - * - * Copyright (C) 2014, 2016-2017 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name NuttX nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************/ - -/**************************************************************************** - * 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 a740073ab82..7a537b5dc2d 100644 --- a/include/aio.h +++ b/include/aio.h @@ -128,11 +128,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 4a84ff24816..64a3b42e208 100644 --- a/include/limits.h +++ b/include/limits.h @@ -135,10 +135,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 ce49050cbfd..797d34d3313 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_NFCHUNK_DESCRIPTORS. + * You can get file instance in filelist by the follow methods: + * (file descriptor / CONFIG_NFCHUNK_DESCRIPTORS) as row index and + * (file descriptor % CONFIG_NFCHUNK_DESCRIPTORS) 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 17be9a67465..a5da18e56fb 100644 --- a/include/nuttx/net/net.h +++ b/include/nuttx/net/net.h @@ -81,13 +81,6 @@ # define _NX_GETERRVAL(r) (-errno) #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 912d5d1ca3a..78acf63795d 100644 --- a/include/sys/select.h +++ b/include/sys/select.h @@ -52,7 +52,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 88dcfc7817e..683ab7c9a58 100644 --- a/libs/libc/spawn/lib_psfa_addclose.c +++ b/libs/libc/spawn/lib_psfa_addclose.c @@ -78,7 +78,7 @@ int posix_spawn_file_actions_addclose(FAR posix_spawn_file_actions_t *file_actio { 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 9e43a20f0c7..251a086f832 100644 --- a/libs/libc/spawn/lib_psfa_adddup2.c +++ b/libs/libc/spawn/lib_psfa_adddup2.c @@ -79,9 +79,7 @@ int posix_spawn_file_actions_adddup2(FAR posix_spawn_file_actions_t *file_action { 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 b591bbc25ce..df538496ee6 100644 --- a/libs/libc/spawn/lib_psfa_addopen.c +++ b/libs/libc/spawn/lib_psfa_addopen.c @@ -87,8 +87,7 @@ int posix_spawn_file_actions_addopen(FAR posix_spawn_file_actions_t *file_action 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. diff --git a/libs/libc/unistd/lib_sysconf.c b/libs/libc/unistd/lib_sysconf.c index c6ae9fb78e5..061eb84a070 100644 --- a/libs/libc/unistd/lib_sysconf.c +++ b/libs/libc/unistd/lib_sysconf.c @@ -224,7 +224,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 67450dfaf87..a4ac2d88753 100644 --- a/net/socket/accept.c +++ b/net/socket/accept.c @@ -244,6 +244,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; @@ -261,7 +262,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 82ab9084df3..54eef521b9e 100644 --- a/net/socket/listen.c +++ b/net/socket/listen.c @@ -44,6 +44,8 @@ #include #include +#include + #include "socket/socket.h" /**************************************************************************** @@ -143,6 +145,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; @@ -155,7 +158,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/sched/Kconfig b/sched/Kconfig index 559274cfc77..9c4bf2cf88a 100644 --- a/sched/Kconfig +++ b/sched/Kconfig @@ -1065,12 +1065,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 NFCHUNK_DESCRIPTORS + int "The number of file descriptors per row" + default 8 range 3 99999 ---help--- - The maximum number of file descriptors per task (one for each open) + The number of file descriptors per row (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 6a1742d4939..6547f5635f6 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 */