From 663104a2e922d1af321db7392c6865c2cc4779bf Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Sat, 10 Jul 2021 23:52:17 +0800 Subject: [PATCH] fs: Simplify sendfile implementation and avoid call nx_ file API in the kernel space Signed-off-by: Xiang Xiao Change-Id: Id951ca161df2c2ee267dc4b5a0d7dfa67df4c1e6 --- .../cxd56xx/spresense/configs/rndis/defconfig | 2 +- .../spresense/configs/rndis_smp/defconfig | 2 +- .../cxd56xx/spresense/configs/wifi/defconfig | 2 +- .../spresense/configs/wifi_smp/defconfig | 2 +- .../olimexino-stm32/configs/can/defconfig | 1 - .../configs/composite/defconfig | 1 - .../olimexino-stm32/configs/nsh/defconfig | 1 - .../configs/smallnsh/defconfig | 1 - .../olimexino-stm32/configs/tiny/defconfig | 1 - .../configs/mmcsdspi/defconfig | 2 +- .../stm32f4discovery/configs/wifi/defconfig | 2 +- fs/Kconfig | 6 + fs/vfs/Make.defs | 18 +- fs/vfs/fs_sendfile.c | 309 +++++++++++++++--- include/nuttx/fs/fs.h | 24 +- include/nuttx/net/net.h | 2 +- include/sys/sendfile.h | 4 +- include/sys/syscall_lookup.h | 5 +- libs/libc/libc.csv | 1 - libs/libc/misc/Kconfig | 6 - libs/libc/misc/Make.defs | 2 - libs/libc/misc/lib_sendfile.c | 288 ---------------- net/socket/net_sendfile.c | 9 +- syscall/syscall.csv | 2 +- 24 files changed, 299 insertions(+), 394 deletions(-) delete mode 100644 libs/libc/misc/lib_sendfile.c diff --git a/boards/arm/cxd56xx/spresense/configs/rndis/defconfig b/boards/arm/cxd56xx/spresense/configs/rndis/defconfig index 6591398103..86af62c08b 100644 --- a/boards/arm/cxd56xx/spresense/configs/rndis/defconfig +++ b/boards/arm/cxd56xx/spresense/configs/rndis/defconfig @@ -62,7 +62,6 @@ CONFIG_I2C=y CONFIG_IOB_NBUFFERS=128 CONFIG_LIBC_EXECFUNCS=y CONFIG_LIB_ENVPATH=y -CONFIG_LIB_SENDFILE_BUFSIZE=1024 CONFIG_MEMCPY_VIK=y CONFIG_MEMSET_64BIT=y CONFIG_MEMSET_OPTSPEED=y @@ -132,6 +131,7 @@ CONFIG_SCHED_HPWORK=y CONFIG_SCHED_LPWORK=y CONFIG_SCHED_WAITPID=y CONFIG_SDCLONE_DISABLE=y +CONFIG_SENDFILE_BUFSIZE=1024 CONFIG_SMARTFS_ALIGNED_ACCESS=y CONFIG_SMARTFS_MAXNAMLEN=30 CONFIG_SMARTFS_MULTI_ROOT_DIRS=y diff --git a/boards/arm/cxd56xx/spresense/configs/rndis_smp/defconfig b/boards/arm/cxd56xx/spresense/configs/rndis_smp/defconfig index ef676f8c4b..d8f21a06e5 100644 --- a/boards/arm/cxd56xx/spresense/configs/rndis_smp/defconfig +++ b/boards/arm/cxd56xx/spresense/configs/rndis_smp/defconfig @@ -64,7 +64,6 @@ CONFIG_I2C=y CONFIG_IOB_NBUFFERS=128 CONFIG_LIBC_EXECFUNCS=y CONFIG_LIB_ENVPATH=y -CONFIG_LIB_SENDFILE_BUFSIZE=1024 CONFIG_MEMCPY_VIK=y CONFIG_MEMSET_64BIT=y CONFIG_MEMSET_OPTSPEED=y @@ -133,6 +132,7 @@ CONFIG_RTC_HIRES=y CONFIG_SCHED_HPWORK=y CONFIG_SCHED_LPWORK=y CONFIG_SDCLONE_DISABLE=y +CONFIG_SENDFILE_BUFSIZE=1024 CONFIG_SMARTFS_ALIGNED_ACCESS=y CONFIG_SMARTFS_MAXNAMLEN=30 CONFIG_SMARTFS_MULTI_ROOT_DIRS=y diff --git a/boards/arm/cxd56xx/spresense/configs/wifi/defconfig b/boards/arm/cxd56xx/spresense/configs/wifi/defconfig index 333d9068fd..0d59823d9b 100644 --- a/boards/arm/cxd56xx/spresense/configs/wifi/defconfig +++ b/boards/arm/cxd56xx/spresense/configs/wifi/defconfig @@ -76,7 +76,6 @@ CONFIG_LCD_ILI9340=y CONFIG_LCD_ILI9340_IFACE0=y CONFIG_LIBC_EXECFUNCS=y CONFIG_LIB_ENVPATH=y -CONFIG_LIB_SENDFILE_BUFSIZE=1024 CONFIG_MEMCPY_VIK=y CONFIG_MEMSET_64BIT=y CONFIG_MEMSET_OPTSPEED=y @@ -137,6 +136,7 @@ CONFIG_SCHED_HPWORK=y CONFIG_SCHED_LPWORKPRIORITY=60 CONFIG_SCHED_WAITPID=y CONFIG_SDCLONE_DISABLE=y +CONFIG_SENDFILE_BUFSIZE=1024 CONFIG_SMARTFS_ALIGNED_ACCESS=y CONFIG_SMARTFS_MAXNAMLEN=30 CONFIG_SMARTFS_MULTI_ROOT_DIRS=y diff --git a/boards/arm/cxd56xx/spresense/configs/wifi_smp/defconfig b/boards/arm/cxd56xx/spresense/configs/wifi_smp/defconfig index 5b04caf549..abb4d343ce 100644 --- a/boards/arm/cxd56xx/spresense/configs/wifi_smp/defconfig +++ b/boards/arm/cxd56xx/spresense/configs/wifi_smp/defconfig @@ -79,7 +79,6 @@ CONFIG_LCD_ILI9340=y CONFIG_LCD_ILI9340_IFACE0=y CONFIG_LIBC_EXECFUNCS=y CONFIG_LIB_ENVPATH=y -CONFIG_LIB_SENDFILE_BUFSIZE=1024 CONFIG_MEMCPY_VIK=y CONFIG_MEMSET_64BIT=y CONFIG_MEMSET_OPTSPEED=y @@ -141,6 +140,7 @@ CONFIG_RTC_HIRES=y CONFIG_SCHED_HPWORK=y CONFIG_SCHED_LPWORKPRIORITY=60 CONFIG_SDCLONE_DISABLE=y +CONFIG_SENDFILE_BUFSIZE=1024 CONFIG_SMARTFS_ALIGNED_ACCESS=y CONFIG_SMARTFS_MAXNAMLEN=30 CONFIG_SMARTFS_MULTI_ROOT_DIRS=y diff --git a/boards/arm/stm32/olimexino-stm32/configs/can/defconfig b/boards/arm/stm32/olimexino-stm32/configs/can/defconfig index fbca71c9bd..15f6f3b851 100644 --- a/boards/arm/stm32/olimexino-stm32/configs/can/defconfig +++ b/boards/arm/stm32/olimexino-stm32/configs/can/defconfig @@ -52,7 +52,6 @@ CONFIG_I2C=y CONFIG_I2C_RESET=y CONFIG_IDLETHREAD_STACKSIZE=300 CONFIG_INTELHEX_BINARY=y -CONFIG_LIB_SENDFILE_BUFSIZE=0 CONFIG_MM_SMALL=y CONFIG_NAME_MAX=8 CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=5 diff --git a/boards/arm/stm32/olimexino-stm32/configs/composite/defconfig b/boards/arm/stm32/olimexino-stm32/configs/composite/defconfig index dfc6fa095a..2b6c6205c0 100644 --- a/boards/arm/stm32/olimexino-stm32/configs/composite/defconfig +++ b/boards/arm/stm32/olimexino-stm32/configs/composite/defconfig @@ -70,7 +70,6 @@ CONFIG_HAVE_CXX=y CONFIG_HAVE_CXXINITIALIZE=y CONFIG_IDLETHREAD_STACKSIZE=300 CONFIG_INTELHEX_BINARY=y -CONFIG_LIB_SENDFILE_BUFSIZE=0 CONFIG_MMCSD=y CONFIG_MM_SMALL=y CONFIG_NAME_MAX=8 diff --git a/boards/arm/stm32/olimexino-stm32/configs/nsh/defconfig b/boards/arm/stm32/olimexino-stm32/configs/nsh/defconfig index a6ec658175..c339b0c150 100644 --- a/boards/arm/stm32/olimexino-stm32/configs/nsh/defconfig +++ b/boards/arm/stm32/olimexino-stm32/configs/nsh/defconfig @@ -58,7 +58,6 @@ CONFIG_HAVE_CXX=y CONFIG_HAVE_CXXINITIALIZE=y CONFIG_IDLETHREAD_STACKSIZE=300 CONFIG_INTELHEX_BINARY=y -CONFIG_LIB_SENDFILE_BUFSIZE=0 CONFIG_MMCSD=y CONFIG_MM_SMALL=y CONFIG_NAME_MAX=8 diff --git a/boards/arm/stm32/olimexino-stm32/configs/smallnsh/defconfig b/boards/arm/stm32/olimexino-stm32/configs/smallnsh/defconfig index dfa9814527..7c32b1ab1f 100644 --- a/boards/arm/stm32/olimexino-stm32/configs/smallnsh/defconfig +++ b/boards/arm/stm32/olimexino-stm32/configs/smallnsh/defconfig @@ -35,7 +35,6 @@ CONFIG_HAVE_CXX=y CONFIG_HAVE_CXXINITIALIZE=y CONFIG_IDLETHREAD_STACKSIZE=300 CONFIG_INTELHEX_BINARY=y -CONFIG_LIB_SENDFILE_BUFSIZE=0 CONFIG_MM_SMALL=y CONFIG_NAME_MAX=8 CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=5 diff --git a/boards/arm/stm32/olimexino-stm32/configs/tiny/defconfig b/boards/arm/stm32/olimexino-stm32/configs/tiny/defconfig index e4f31f1fef..5ec5973ab2 100644 --- a/boards/arm/stm32/olimexino-stm32/configs/tiny/defconfig +++ b/boards/arm/stm32/olimexino-stm32/configs/tiny/defconfig @@ -36,7 +36,6 @@ CONFIG_HAVE_CXXINITIALIZE=y CONFIG_IDLETHREAD_STACKSIZE=300 CONFIG_INTELHEX_BINARY=y CONFIG_LIB_BOARDCTL=y -CONFIG_LIB_SENDFILE_BUFSIZE=0 CONFIG_MM_SMALL=y CONFIG_NAME_MAX=8 CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=5 diff --git a/boards/arm/stm32/stm32f4discovery/configs/mmcsdspi/defconfig b/boards/arm/stm32/stm32f4discovery/configs/mmcsdspi/defconfig index ea00e7c627..11a1529f65 100644 --- a/boards/arm/stm32/stm32f4discovery/configs/mmcsdspi/defconfig +++ b/boards/arm/stm32/stm32f4discovery/configs/mmcsdspi/defconfig @@ -36,7 +36,6 @@ CONFIG_HAVE_CXX=y CONFIG_HAVE_CXXINITIALIZE=y CONFIG_HEAP_COLORATION=y CONFIG_INTELHEX_BINARY=y -CONFIG_LIB_SENDFILE_BUFSIZE=1024 CONFIG_MMCSD=y CONFIG_MM_REGIONS=2 CONFIG_NETUTILS_CODECS=y @@ -55,6 +54,7 @@ CONFIG_SCHED_LPWORK=y CONFIG_SCHED_LPWORKPRIORITY=30 CONFIG_SCHED_WAITPID=y CONFIG_SDCLONE_DISABLE=y +CONFIG_SENDFILE_BUFSIZE=1024 CONFIG_STACK_COLORATION=y CONFIG_START_DAY=17 CONFIG_START_MONTH=10 diff --git a/boards/arm/stm32/stm32f4discovery/configs/wifi/defconfig b/boards/arm/stm32/stm32f4discovery/configs/wifi/defconfig index b97710140f..d8a3e2d8b1 100644 --- a/boards/arm/stm32/stm32f4discovery/configs/wifi/defconfig +++ b/boards/arm/stm32/stm32f4discovery/configs/wifi/defconfig @@ -42,7 +42,6 @@ CONFIG_HEAP_COLORATION=y CONFIG_INTELHEX_BINARY=y CONFIG_LIBC_EXECFUNCS=y CONFIG_LIB_ENVPATH=y -CONFIG_LIB_SENDFILE_BUFSIZE=1024 CONFIG_MMCSD=y CONFIG_MM_REGIONS=2 CONFIG_NET=y @@ -78,6 +77,7 @@ CONFIG_RR_INTERVAL=200 CONFIG_SCHED_LPWORKPRIORITY=30 CONFIG_SCHED_WAITPID=y CONFIG_SDCLONE_DISABLE=y +CONFIG_SENDFILE_BUFSIZE=1024 CONFIG_STACK_COLORATION=y CONFIG_START_DAY=22 CONFIG_START_MONTH=10 diff --git a/fs/Kconfig b/fs/Kconfig index d646d06c54..02b62be683 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -67,6 +67,12 @@ config PSEUDOFS_SOFTLINKS to link a directory in the pseudo-file system, such as /bin, to to a directory in a mounted volume, say /mnt/sdcard/bin. +config SENDFILE_BUFSIZE + int "sendfile() buffer size" + default 512 + ---help--- + Size of the I/O buffer to allocate in sendfile(). Default: 512b + config EVENT_FD bool "EventFD" default n diff --git a/fs/vfs/Make.defs b/fs/vfs/Make.defs index 7b35b814ca..daacda4603 100644 --- a/fs/vfs/Make.defs +++ b/fs/vfs/Make.defs @@ -20,10 +20,10 @@ # 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_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 +CSRCS += fs_close.c fs_dup.c fs_dup2.c fs_fcntl.c fs_epoll.c fs_fstat.c +CSRCS += fs_fstatfs.c fs_ioctl.c fs_lseek.c fs_mkdir.c fs_open.c fs_poll.c +CSRCS += fs_pread.c fs_pwrite.c fs_read.c fs_rename.c fs_rmdir.c fs_select.c +CSRCS += fs_sendfile.c fs_stat.c fs_statfs.c fs_unlink.c fs_write.c # Certain interfaces are not available if there is no mountpoint support @@ -31,10 +31,6 @@ ifneq ($(CONFIG_DISABLE_MOUNTPOINT),y) CSRCS += fs_fsync.c fs_truncate.c endif -# Support for positional file access - -CSRCS += fs_pread.c fs_pwrite.c - ifneq ($(CONFIG_PSEUDOFS_SOFTLINKS),0) CSRCS += fs_symlink.c fs_readlink.c endif @@ -45,12 +41,6 @@ ifeq ($(CONFIG_FILE_STREAM),y) CSRCS += fs_fdopen.c endif -# Support for sendfile() - -ifeq ($(CONFIG_NET_SENDFILE),y) -CSRCS += fs_sendfile.c -endif - # Support for eventfd ifeq ($(CONFIG_EVENT_FD),y) diff --git a/fs/vfs/fs_sendfile.c b/fs/vfs/fs_sendfile.c index 3d2b8cd5da..5b4ec2cff5 100644 --- a/fs/vfs/fs_sendfile.c +++ b/fs/vfs/fs_sendfile.c @@ -26,20 +26,255 @@ #include #include -#include -#include #include -#include -#include +#include #include -#ifdef CONFIG_NET_SENDFILE +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static ssize_t copyfile(FAR struct file *outfile, FAR struct file *infile, + off_t *offset, size_t count) +{ + FAR uint8_t *iobuffer; + FAR uint8_t *wrbuffer; + off_t startpos = 0; + ssize_t nbytesread; + ssize_t nbyteswritten; + size_t ntransferred; + bool endxfr; + + /* Get the current file position. */ + + if (offset) + { + off_t newpos; + + /* Use file_seek to get the current file position */ + + startpos = file_seek(infile, 0, SEEK_CUR); + if (startpos < 0) + { + return startpos; + } + + /* Use file_seek again to set the new file position */ + + newpos = file_seek(infile, *offset, SEEK_SET); + if (newpos < 0) + { + return newpos; + } + } + + /* Allocate an I/O buffer */ + + iobuffer = kmm_malloc(CONFIG_SENDFILE_BUFSIZE); + if (!iobuffer) + { + return -ENOMEM; + } + + /* Now transfer 'count' bytes from the infile to the outfile */ + + for (ntransferred = 0, endxfr = false; ntransferred < count && !endxfr; ) + { + /* Loop until the read side of the transfer comes to some conclusion */ + + do + { + /* Read a buffer of data from the infile */ + + nbytesread = count - ntransferred; + if (nbytesread > CONFIG_SENDFILE_BUFSIZE) + { + nbytesread = CONFIG_SENDFILE_BUFSIZE; + } + + nbytesread = file_read(infile, iobuffer, nbytesread); + + /* Check for end of file */ + + if (nbytesread == 0) + { + /* End of file. Break out and return current number of bytes + * transferred. + */ + + endxfr = true; + break; + } + + /* Check for a read ERROR. EINTR is a special case. This function + * should break out and return an error if EINTR is returned and + * no data has been transferred. But what should it do if some + * data has been transferred? I suppose just continue? + */ + + else if (nbytesread < 0) + { + /* EINTR is not an error (but will still stop the copy) */ + + if (nbytesread != -EINTR || ntransferred == 0) + { + /* Read error. Break out and return the error condition. */ + + ntransferred = nbytesread; + endxfr = true; + break; + } + } + } + while (nbytesread < 0); + + /* Was anything read? */ + + if (!endxfr) + { + /* Yes.. Loop until the read side of the transfer comes to some + * conclusion. + */ + + wrbuffer = iobuffer; + do + { + /* Write the buffer of data to the outfile */ + + nbyteswritten = file_write(outfile, wrbuffer, nbytesread); + + /* Check for a complete (or partial) write. write() should not + * return zero. + */ + + if (nbyteswritten >= 0) + { + /* Advance the buffer pointer and decrement the number of + * bytes remaining in the iobuffer. Typically, nbytesread + * will now be zero. + */ + + wrbuffer += nbyteswritten; + nbytesread -= nbyteswritten; + + /* Increment the total number of bytes successfully + * transferred. + */ + + ntransferred += nbyteswritten; + } + + /* Otherwise an error occurred */ + + else + { + /* Check for a write ERROR. EINTR is a special case. This + * function should break out and return an error if EINTR + * is returned and no data has been transferred. But what + * should it do if some data has been transferred? I + * suppose just continue? + */ + + if (nbyteswritten != -EINTR || ntransferred == 0) + { + /* Write error. Break out and return the error + * condition. + */ + + ntransferred = nbyteswritten; + endxfr = true; + break; + } + } + } + while (nbytesread > 0); + } + } + + /* Release the I/O buffer */ + + kmm_free(iobuffer); + + /* Return the current file position */ + + if (offset) + { + /* Use file_seek to get the current file position */ + + off_t curpos = file_seek(infile, 0, SEEK_CUR); + if (curpos < 0) + { + return curpos; + } + + /* Return the current file position */ + + *offset = curpos; + + /* Use file_seek again to restore the original file position */ + + startpos = file_seek(infile, startpos, SEEK_SET); + if (startpos < 0) + { + return startpos; + } + } + + /* Finally return the number of bytes actually transferred (or ERROR + * if any failure occurred). + */ + + return ntransferred; +} /**************************************************************************** * Public Functions ****************************************************************************/ +/**************************************************************************** + * Name: file_sendfile + * + * Description: + * Equivalent to the standard sendfile function except that is accepts a + * struct file instance instead of a file descriptor. + * + ****************************************************************************/ + +ssize_t file_sendfile(FAR struct file *outfile, FAR struct file *infile, + off_t *offset, size_t count) +{ +#ifdef CONFIG_NET_SENDFILE + /* Check the destination file descriptor: Is it a (probable) file + * descriptor? Check the source file: Is it a normal file? + */ + + FAR struct socket *psock; + + psock = file_socket(outfile); + if (psock != NULL) + { + /* Then let psock_sendfile do the work. */ + + int ret = psock_sendfile(psock, infile, offset, count); + if (ret >= 0 || ret != -ENOSYS) + { + return ret; + } + + /* Fall back to the slow path if errno equals ENOSYS, + * because psock_sendfile fail to optimize this transfer. + */ + } +#endif + + /* No... then this is probably a file-to-file transfer. The generic + * copyfile() can handle that case. + */ + + return copyfile(outfile, infile, offset, count); +} + /**************************************************************************** * Name: sendfile * @@ -87,51 +322,31 @@ ssize_t sendfile(int outfd, int infd, off_t *offset, size_t count) { -#ifdef CONFIG_NET_SENDFILE - /* Check the destination file descriptor: Is it a (probable) file - * descriptor? Check the source file: Is it a normal file? - */ + FAR struct file *outfile; + FAR struct file *infile; + int ret; - FAR struct socket *psock; - - psock = sockfd_socket(outfd); - if (psock != NULL) + ret = fs_getfilep(outfd, &outfile); + if (ret < 0) { - FAR struct file *filep; - int ret; - - /* This appears to be a file-to-socket transfer. Get the file - * structure. - */ - - ret = fs_getfilep(infd, &filep); - if (ret < 0) - { - set_errno(-ret); - return ERROR; - } - - DEBUGASSERT(filep != NULL); - - /* Then let psock_sendfile do the work. */ - - ret = psock_sendfile(psock, filep, offset, count); - if (ret >= 0 || get_errno() != ENOSYS) - { - return ret; - } - - /* Fall back to the slow path if errno equals ENOSYS, - * because psock_sendfile fail to optimize this transfer. - */ + goto errout; } -#endif - /* No... then this is probably a file-to-file transfer. The generic - * lib_sendfile() can handle that case. - */ + ret = fs_getfilep(infd, &infile); + if (ret < 0) + { + goto errout; + } - return lib_sendfile(outfd, infd, offset, count); + ret = file_sendfile(outfile, infile, offset, count); + if (ret < 0) + { + goto errout; + } + + return ret; + +errout: + set_errno(-ret); + return ERROR; } - -#endif /* CONFIG_NET_SENDFILE */ diff --git a/include/nuttx/fs/fs.h b/include/nuttx/fs/fs.h index 5210f4462b..edff2656f4 100644 --- a/include/nuttx/fs/fs.h +++ b/include/nuttx/fs/fs.h @@ -977,18 +977,6 @@ int fs_fdopen(int fd, int oflags, FAR struct tcb_s *tcb, int lib_flushall(FAR struct streamlist *list); #endif -/**************************************************************************** - * Name: lib_sendfile - * - * Description: - * Transfer a file - * - ****************************************************************************/ - -#ifdef CONFIG_NET_SENDFILE -ssize_t lib_sendfile(int outfd, int infd, off_t *offset, size_t count); -#endif - /**************************************************************************** * Name: file_read * @@ -1119,6 +1107,18 @@ ssize_t file_pread(FAR struct file *filep, FAR void *buf, size_t nbytes, ssize_t file_pwrite(FAR struct file *filep, FAR const void *buf, size_t nbytes, off_t offset); +/**************************************************************************** + * Name: file_sendfile + * + * Description: + * Equivalent to the standard sendfile function except that is accepts a + * struct file instance instead of a file descriptor. + * + ****************************************************************************/ + +ssize_t file_sendfile(FAR struct file *outfile, FAR struct file *infile, + off_t *offset, size_t count); + /**************************************************************************** * Name: file_seek * diff --git a/include/nuttx/net/net.h b/include/nuttx/net/net.h index d79162ef14..c940e20f56 100644 --- a/include/nuttx/net/net.h +++ b/include/nuttx/net/net.h @@ -1334,7 +1334,7 @@ int psock_fstat(FAR struct socket *psock, FAR struct stat *buf); * * Returned Value: * On success, returns the number of characters sent. On error, - * -1 is returned, and errno is set appropriately: + * the negative errno is return appropriately: * * EAGAIN or EWOULDBLOCK * The socket is marked non-blocking and the requested operation diff --git a/include/sys/sendfile.h b/include/sys/sendfile.h index de4a5c2b34..cb583a9031 100644 --- a/include/sys/sendfile.h +++ b/include/sys/sendfile.h @@ -35,8 +35,8 @@ /* Configuration ************************************************************/ -#ifndef CONFIG_LIB_SENDFILE_BUFSIZE -# define CONFIG_LIB_SENDFILE_BUFSIZE 512 +#ifndef CONFIG_SENDFILE_BUFSIZE +# define CONFIG_SENDFILE_BUFSIZE 512 #endif /**************************************************************************** diff --git a/include/sys/syscall_lookup.h b/include/sys/syscall_lookup.h index 03de33c0d2..5d55d9f11a 100644 --- a/include/sys/syscall_lookup.h +++ b/include/sys/syscall_lookup.h @@ -247,6 +247,7 @@ SYSCALL_LOOKUP(fstat, 2) SYSCALL_LOOKUP(statfs, 2) SYSCALL_LOOKUP(fstatfs, 2) SYSCALL_LOOKUP(telldir, 1) +SYSCALL_LOOKUP(sendfile, 4) #if defined(CONFIG_FS_RAMMAP) SYSCALL_LOOKUP(munmap, 2) @@ -270,10 +271,6 @@ SYSCALL_LOOKUP(telldir, 1) SYSCALL_LOOKUP(nxsched_get_streams, 0) #endif -#ifdef CONFIG_NET_SENDFILE - SYSCALL_LOOKUP(sendfile, 4) -#endif - #ifndef CONFIG_DISABLE_MOUNTPOINT SYSCALL_LOOKUP(mount, 5) SYSCALL_LOOKUP(fsync, 1) diff --git a/libs/libc/libc.csv b/libs/libc/libc.csv index cbd6c5cdef..f0bd9c8d04 100644 --- a/libs/libc/libc.csv +++ b/libs/libc/libc.csv @@ -150,7 +150,6 @@ "sched_get_priority_min","sched.h","","int","int" "sem_getvalue","semaphore.h","","int","FAR sem_t *","FAR int *" "sem_init","semaphore.h","","int","FAR sem_t *","int","unsigned int" -"sendfile","sys/sendfile.h","","ssize_t","int","int","FAR off_t *","size_t" "setlocale","locale.h","defined(CONFIG_LIBC_LOCALE)","FAR char *","int","FAR const char *" "setlogmask","syslog.h","","int","int" "sigaddset","signal.h","","int","FAR sigset_t *","int" diff --git a/libs/libc/misc/Kconfig b/libs/libc/misc/Kconfig index c36b785c20..e8f8978c82 100644 --- a/libs/libc/misc/Kconfig +++ b/libs/libc/misc/Kconfig @@ -3,12 +3,6 @@ # see the file kconfig-language.txt in the NuttX tools repository. # -config LIB_SENDFILE_BUFSIZE - int "sendfile() buffer size" - default 512 - ---help--- - Size of the I/O buffer to allocate in sendfile(). Default: 512b - comment "Non-standard Library Support" config LIB_CRC64_FAST diff --git a/libs/libc/misc/Make.defs b/libs/libc/misc/Make.defs index f14f0abaef..2168826a12 100644 --- a/libs/libc/misc/Make.defs +++ b/libs/libc/misc/Make.defs @@ -34,8 +34,6 @@ CSRCS += lib_uadd32x64.c lib_uadd64.c lib_usub64x32.c lib_usub64.c # Add C files that depend on file OR socket descriptors -CSRCS += lib_sendfile.c - ifeq ($(CONFIG_FILE_STREAM),y) CSRCS += lib_streamsem.c endif diff --git a/libs/libc/misc/lib_sendfile.c b/libs/libc/misc/lib_sendfile.c deleted file mode 100644 index b7f9d0ddd6..0000000000 --- a/libs/libc/misc/lib_sendfile.c +++ /dev/null @@ -1,288 +0,0 @@ -/**************************************************************************** - * libs/libc/misc/lib_sendfile.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 "libc.h" - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: sendfile / lib_sendfile - * - * Description: - * sendfile() copies data between one file descriptor and another. - * sendfile() basically just wraps a sequence of reads() and writes() - * to perform a copy. It serves a purpose in systems where there is - * a penalty for copies to between user and kernal space, but really - * nothing in NuttX but provide some Linux compatible (and adding - * another 'almost standard' interface). - * - * NOTE: This interface is *not* specified in POSIX.1-2001, or other - * standards. The implementation here is very similar to the Linux - * sendfile interface. Other UNIX systems implement sendfile() with - * different semantics and prototypes. sendfile() should not be used - * in portable programs. - * - * Input Parameters: - * infd - A file (or socket) descriptor opened for reading - * outfd - A descriptor opened for writing. - * offset - If 'offset' is not NULL, then it points to a variable - * holding the file offset from which sendfile() will start - * reading data from 'infd'. When sendfile() returns, this - * variable will be set to the offset of the byte following - * the last byte that was read. If 'offset' is not NULL, - * then sendfile() does not modify the current file offset of - * 'infd'; otherwise the current file offset is adjusted to - * reflect the number of bytes read from 'infd.' - * - * If 'offset' is NULL, then data will be read from 'infd' - * starting at the current file offset, and the file offset - * will be updated by the call. - * count - The number of bytes to copy between the file descriptors. - * - * Returned Value: - * If the transfer was successful, the number of bytes written to outfd is - * returned. On error, -1 is returned, and errno is set appropriately. - * There error values are those returned by read() or write() plus: - * - * EINVAL - Bad input parameters. - * ENOMEM - Could not allocated an I/O buffer - * - ****************************************************************************/ - -#ifdef CONFIG_NET_SENDFILE -ssize_t lib_sendfile(int outfd, int infd, off_t *offset, size_t count) -#else -ssize_t sendfile(int outfd, int infd, off_t *offset, size_t count) -#endif -{ - FAR uint8_t *iobuffer; - FAR uint8_t *wrbuffer; - off_t startpos = 0; - ssize_t nbytesread; - ssize_t nbyteswritten; - size_t ntransferred; - bool endxfr; - - /* Get the current file position. */ - - if (offset) - { - off_t newpos; - - /* Use lseek to get the current file position */ - - startpos = _NX_SEEK(infd, 0, SEEK_CUR); - if (startpos < 0) - { - int errcode = _NX_GETERRNO(startpos); - _NX_SETERRNO(errcode); - return ERROR; - } - - /* Use lseek again to set the new file position */ - - newpos = _NX_SEEK(infd, *offset, SEEK_SET); - if (newpos < 0) - { - int errcode = _NX_GETERRNO(newpos); - _NX_SETERRNO(errcode); - return ERROR; - } - } - - /* Allocate an I/O buffer */ - - iobuffer = (FAR void *)lib_malloc(CONFIG_LIB_SENDFILE_BUFSIZE); - if (!iobuffer) - { - set_errno(ENOMEM); - return ERROR; - } - - /* Now transfer 'count' bytes from the infd to the outfd */ - - for (ntransferred = 0, endxfr = false; ntransferred < count && !endxfr; ) - { - /* Loop until the read side of the transfer comes to some conclusion */ - - do - { - /* Read a buffer of data from the infd */ - - nbytesread = _NX_READ(infd, iobuffer, CONFIG_LIB_SENDFILE_BUFSIZE); - - /* Check for end of file */ - - if (nbytesread == 0) - { - /* End of file. Break out and return current number of bytes - * transferred. - */ - - endxfr = true; - break; - } - - /* Check for a read ERROR. EINTR is a special case. This function - * should break out and return an error if EINTR is returned and - * no data has been transferred. But what should it do if some - * data has been transferred? I suppose just continue? - */ - - else if (nbytesread < 0) - { - int errcode = _NX_GETERRNO(nbytesread); - - /* EINTR is not an error (but will still stop the copy) */ - - if (errcode != EINTR || ntransferred == 0) - { - /* Read error. Break out and return the error condition. */ - - _NX_SETERRNO(nbytesread); - ntransferred = ERROR; - endxfr = true; - break; - } - } - } - while (nbytesread < 0); - - /* Was anything read? */ - - if (!endxfr) - { - /* Yes.. Loop until the read side of the transfer comes to some - * conclusion. - */ - - wrbuffer = iobuffer; - do - { - /* Write the buffer of data to the outfd */ - - nbyteswritten = _NX_WRITE(outfd, wrbuffer, nbytesread); - - /* Check for a complete (or parial) write. write() should not - * return zero. - */ - - if (nbyteswritten >= 0) - { - /* Advance the buffer pointer and decrement the number of - * bytes remaining in the iobuffer. Typically, nbytesread - * will now be zero. - */ - - wrbuffer += nbyteswritten; - nbytesread -= nbyteswritten; - - /* Increment the total number of bytes successfully - * transferred. - */ - - ntransferred += nbyteswritten; - } - - /* Otherwise an error occurred */ - - else - { - int errcode = _NX_GETERRNO(nbyteswritten); - - /* Check for a read ERROR. EINTR is a special case. This - * function should break out and return an error if EINTR - * is returned and no data has been transferred. But what - * should it do if some data has been transferred? I - * suppose just continue? - */ - - if (errcode != EINTR || ntransferred == 0) - { - /* Write error. Break out and return the error - * condition. - */ - - _NX_SETERRNO(nbyteswritten); - ntransferred = ERROR; - endxfr = true; - break; - } - } - } - while (nbytesread > 0); - } - } - - /* Release the I/O buffer */ - - lib_free(iobuffer); - - /* Return the current file position */ - - if (offset) - { - /* Use lseek to get the current file position */ - - off_t curpos = _NX_SEEK(infd, 0, SEEK_CUR); - if (curpos < 0) - { - int errcode = _NX_GETERRNO(curpos); - _NX_SETERRNO(errcode); - return ERROR; - } - - /* Return the current file position */ - - *offset = curpos; - - /* Use lseek again to restore the original file position */ - - startpos = _NX_SEEK(infd, startpos, SEEK_SET); - if (startpos < 0) - { - int errcode = _NX_GETERRNO(startpos); - _NX_SETERRNO(errcode); - return ERROR; - } - } - - /* Finally return the number of bytes actually transferred (or ERROR - * if any failure occurred). - */ - - return ntransferred; -} diff --git a/net/socket/net_sendfile.c b/net/socket/net_sendfile.c index c9407f7309..c3f7bd4d04 100644 --- a/net/socket/net_sendfile.c +++ b/net/socket/net_sendfile.c @@ -74,7 +74,7 @@ * * Returned Value: * On success, returns the number of characters sent. On error, - * -1 is returned, and errno is set appropriately: + * the negative errno is returned appropriately: * * EAGAIN or EWOULDBLOCK * The socket is marked non-blocking and the requested operation @@ -130,8 +130,8 @@ ssize_t psock_sendfile(FAR struct socket *psock, FAR struct file *infile, if (psock == NULL || psock->s_conn == NULL) { nerr("ERROR: Invalid socket\n"); - _SO_SETERRNO(psock, EBADF); - return ERROR; + psock->s_error = EBADF; + return -EBADF; } /* Check if the address family supports the optimized sendfile(). If not, @@ -151,8 +151,7 @@ ssize_t psock_sendfile(FAR struct socket *psock, FAR struct file *infile, if (ret < 0) { - _SO_SETERRNO(psock, -ret); - return ERROR; + psock->s_error = -ret; } return ret; diff --git a/syscall/syscall.csv b/syscall/syscall.csv index 0f96f4ed95..bfbe88cc80 100644 --- a/syscall/syscall.csv +++ b/syscall/syscall.csv @@ -139,7 +139,7 @@ "sem_unlink","semaphore.h","defined(CONFIG_FS_NAMED_SEMAPHORES)","int","FAR const char *" "sem_wait","semaphore.h","","int","FAR sem_t *" "send","sys/socket.h","defined(CONFIG_NET)","ssize_t","int","FAR const void *","size_t","int" -"sendfile","sys/sendfile.h","defined(CONFIG_NET_SENDFILE)","ssize_t","int","int","FAR off_t *","size_t" +"sendfile","sys/sendfile.h","","ssize_t","int","int","FAR off_t *","size_t" "sendmsg","sys/socket.h","defined(CONFIG_NET)","ssize_t","int","FAR struct msghdr *","int" "sendto","sys/socket.h","defined(CONFIG_NET)","ssize_t","int","FAR const void *","size_t","int","FAR const struct sockaddr *","socklen_t" "setenv","stdlib.h","!defined(CONFIG_DISABLE_ENVIRON)","int","FAR const char *","FAR const char *","int"