From patchwork Sat Jul 4 14:02:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greg Kroah-Hartman X-Patchwork-Id: 11643649 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4F9CF6C1 for ; Sat, 4 Jul 2020 14:03:25 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 35A8D21707 for ; Sat, 4 Jul 2020 14:03:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1593871405; bh=Yj+14217YtAOnGW+R47dIfZ8DJrAtcfTkhE3moybXhw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=N//6vTiYgBKeAK64We+f0CjvJpFobS6MQ+KG11/yxk+0LLECMI7YqhBCMIn0Lzzci ZyMo3s+R5qdBheLeEVsw9gWq+Nv8yn+wqh3oDfbMBP9I/DOYhpzMQW08oV1Sq67gEF wxlXaDeEYRLdJ89CmrbrK5S78ecTelRv+5KQKsis= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727118AbgGDODR (ORCPT ); Sat, 4 Jul 2020 10:03:17 -0400 Received: from mail.kernel.org ([198.145.29.99]:51584 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726948AbgGDODN (ORCPT ); Sat, 4 Jul 2020 10:03:13 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id BD589218AC; Sat, 4 Jul 2020 14:03:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1593871392; bh=Yj+14217YtAOnGW+R47dIfZ8DJrAtcfTkhE3moybXhw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bo1VVkDd19yyAM+xVbtMirVeDtHC8y8RVtHm53sL556lDzTRt7fNbrNRVslVhYZQh jB4FnUhzApA+tdrCHP5OK5i0o7VSGvrVwKwgJAUXYBs2Tlqpg3HLvxn5WJhZkYfTZw DyEvXIMAXEm++4fTgZWv/HtWpliLrfrV11Oh3GoU= From: Greg Kroah-Hartman To: viro@zeniv.linux.org.uk, mtk.manpages@gmail.com, shuah@kernel.org, linux-api@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-man@vger.kernel.org, linux-kselftest@vger.kernel.org, Greg Kroah-Hartman Subject: [PATCH] readfile.2: new page describing readfile(2) Date: Sat, 4 Jul 2020 16:02:50 +0200 Message-Id: <20200704140250.423345-5-gregkh@linuxfoundation.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200704140250.423345-1-gregkh@linuxfoundation.org> References: <20200704140250.423345-1-gregkh@linuxfoundation.org> MIME-Version: 1.0 Sender: linux-kselftest-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org readfile(2) is a new syscall to remove the need to do the open/read/close dance for small virtual files in places like procfs or sysfs. Signed-off-by: Greg Kroah-Hartman --- This patch is for the man-pages project, not the kernel source tree man2/readfile.2 | 159 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 man2/readfile.2 diff --git a/man2/readfile.2 b/man2/readfile.2 new file mode 100644 index 000000000000..449e722c3442 --- /dev/null +++ b/man2/readfile.2 @@ -0,0 +1,159 @@ +.\" This manpage is Copyright (C) 2020 Greg Kroah-Hartman; +.\" and Copyright (C) 2020 The Linux Foundation +.\" +.\" %%%LICENSE_START(VERBATIM) +.\" Permission is granted to make and distribute verbatim copies of this +.\" manual provided the copyright notice and this permission notice are +.\" preserved on all copies. +.\" +.\" Permission is granted to copy and distribute modified versions of this +.\" manual under the conditions for verbatim copying, provided that the +.\" entire resulting derived work is distributed under the terms of a +.\" permission notice identical to this one. +.\" +.\" Since the Linux kernel and libraries are constantly changing, this +.\" manual page may be incorrect or out-of-date. The author(s) assume no +.\" responsibility for errors or omissions, or for damages resulting from +.\" the use of the information contained herein. The author(s) may not +.\" have taken the same level of care in the production of this manual, +.\" which is licensed free of charge, as they might when working +.\" professionally. +.\" +.\" Formatted or processed versions of this manual, if unaccompanied by +.\" the source, must acknowledge the copyright and authors of this work. +.\" %%%LICENSE_END +.\" +.TH READFILE 2 2020-07-04 "Linux" "Linux Programmer's Manual" +.SH NAME +readfile \- read a file into a buffer +.SH SYNOPSIS +.nf +.B #include +.PP +.BI "ssize_t readfile(int " dirfd ", const char *" pathname ", void *" buf \ +", size_t " count ", int " flags ); +.fi +.SH DESCRIPTION +.BR readfile () +attempts to open the file specified by +.IR pathname +and to read up to +.I count +bytes from the file into the buffer starting at +.IR buf . +It is to be a shortcut of doing the sequence of +.BR open () +and then +.BR read () +and then +.BR close () +for small files that are read frequently, such as those in +.B procfs +or +.BR sysfs . +.PP +If the size of file is smaller than the value provided in +.I count +then the whole file will be copied into +.IR buf . +.PP +If the file is larger than the value provided in +.I count +then only +.I count +number of bytes will be copied into +.IR buf . +.PP +The argument +.I flags +may contain one of the following +.IR "access modes" : +.BR O_NOFOLLOW ", or " O_NOATIME . +.PP +If the pathname given in +.I pathname +is relative, then it is interpreted relative to the directory +referred to by the file descriptor +.IR dirfd . +.PP +If +.I pathname +is relative and +.I dirfd +is the special value +.BR AT_FDCWD , +then +.I pathname +is interpreted relative to the current working +directory of the calling process (like +.BR openat ()). +.PP +If +.I pathname +is absolute, then +.I dirfd +is ignored. +.SH RETURN VALUE +On success, the number of bytes read is returned. +It is not an error if this number is smaller than the number of bytes +requested; this can happen if the file is smaller than the number of +bytes requested. +.PP +On error, \-1 is returned, and +.I errno +is set appropriately. +.SH ERRORS +.TP +.B EFAULT +.I buf +is outside your accessible address space. +.TP +.B EINTR +The call was interrupted by a signal before any data was read; see +.BR signal (7). +.TP +.B EINVAL +.I flags +was set to a value that is not allowed. +.TP +.B EIO +I/O error. +This will happen for example when the process is in a +background process group, tries to read from its controlling terminal, +and either it is ignoring or blocking +.B SIGTTIN +or its process group +is orphaned. +It may also occur when there is a low-level I/O error +while reading from a disk or tape. +A further possible cause of +.B EIO +on networked filesystems is when an advisory lock had been taken +out on the file descriptor and this lock has been lost. +See the +.I "Lost locks" +section of +.BR fcntl (2) +for further details. +.SH CONFORMING TO +None, this is a Linux-specific system call at this point in time. +.SH NOTES +The type +.I size_t +is an unsigned integer data type specified by POSIX.1. +.PP +On Linux, +.BR read () +(and similar system calls) will transfer at most +0x7ffff000 (2,147,479,552) bytes, +returning the number of bytes actually transferred. +.\" commit e28cc71572da38a5a12c1cfe4d7032017adccf69 +(This is true on both 32-bit and 64-bit systems.) +.SH BUGS +None yet! +.SH SEE ALSO +.BR close (2), +.BR open (2), +.BR openat (2), +.BR read (2), +.BR fread (3) From patchwork Sat Jul 4 14:02:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greg Kroah-Hartman X-Patchwork-Id: 11643655 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id F14E86C1 for ; Sat, 4 Jul 2020 14:03:28 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CDBDF21707 for ; Sat, 4 Jul 2020 14:03:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1593871408; bh=vl0bF9x98gBDq/mYiHrmRVl5AgmGg3AjzPq7KnoM3i8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=FDGGUUolipXJG2jM7tK0dL4vKTm/rp92ZYu5nYtpY66ZQiObMjoTXbFSBf2APEy4m jB0iHDg0keHvdVY2YAMcIL4YP+8yf9TksUa4z+2WNvs/x0JL3rVCz2xGqdtZXXxG4X ZHeKidZ+egU5qla1cTAx0TqBqFzoPii9Wv8fdFus= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727072AbgGDODK (ORCPT ); Sat, 4 Jul 2020 10:03:10 -0400 Received: from mail.kernel.org ([198.145.29.99]:51536 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726948AbgGDODI (ORCPT ); Sat, 4 Jul 2020 10:03:08 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id A0C37217D8; Sat, 4 Jul 2020 14:03:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1593871387; bh=vl0bF9x98gBDq/mYiHrmRVl5AgmGg3AjzPq7KnoM3i8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FSn72jn1D62fHCGRt3MVlmWTqLMh4gip2x2DmpTvU9oveRnLjFA4Imb0+vJeekj5h BWzRIO7HVLg4Di6wVti2CskeioPwuxA/xauctOwAEsdOkdB90mHaIXpnLdzmywyJew GJ+xaCk3Bwcpv/Pc58nQZ6JisnJXEyJR/ybG+6iM= From: Greg Kroah-Hartman To: viro@zeniv.linux.org.uk, mtk.manpages@gmail.com, shuah@kernel.org, linux-api@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-man@vger.kernel.org, linux-kselftest@vger.kernel.org, Greg Kroah-Hartman Subject: [PATCH 2/3] arch: wire up the readfile syscall Date: Sat, 4 Jul 2020 16:02:48 +0200 Message-Id: <20200704140250.423345-3-gregkh@linuxfoundation.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200704140250.423345-1-gregkh@linuxfoundation.org> References: <20200704140250.423345-1-gregkh@linuxfoundation.org> MIME-Version: 1.0 Sender: linux-kselftest-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org This wires up the readfile syscall for all architectures Signed-off-by: Greg Kroah-Hartman Acked-by: Geert Uytterhoeven --- arch/alpha/kernel/syscalls/syscall.tbl | 1 + arch/arm/tools/syscall.tbl | 1 + arch/arm64/include/asm/unistd.h | 2 +- arch/arm64/include/asm/unistd32.h | 2 ++ arch/ia64/kernel/syscalls/syscall.tbl | 1 + arch/m68k/kernel/syscalls/syscall.tbl | 1 + arch/microblaze/kernel/syscalls/syscall.tbl | 1 + arch/mips/kernel/syscalls/syscall_n32.tbl | 1 + arch/mips/kernel/syscalls/syscall_n64.tbl | 1 + arch/mips/kernel/syscalls/syscall_o32.tbl | 1 + arch/parisc/kernel/syscalls/syscall.tbl | 1 + arch/powerpc/kernel/syscalls/syscall.tbl | 1 + arch/s390/kernel/syscalls/syscall.tbl | 1 + arch/sh/kernel/syscalls/syscall.tbl | 1 + arch/sparc/kernel/syscalls/syscall.tbl | 1 + arch/x86/entry/syscalls/syscall_32.tbl | 1 + arch/x86/entry/syscalls/syscall_64.tbl | 1 + arch/xtensa/kernel/syscalls/syscall.tbl | 1 + include/linux/syscalls.h | 2 ++ include/uapi/asm-generic/unistd.h | 4 +++- 20 files changed, 24 insertions(+), 2 deletions(-) diff --git a/arch/alpha/kernel/syscalls/syscall.tbl b/arch/alpha/kernel/syscalls/syscall.tbl index 5ddd128d4b7a..4132380e997f 100644 --- a/arch/alpha/kernel/syscalls/syscall.tbl +++ b/arch/alpha/kernel/syscalls/syscall.tbl @@ -478,3 +478,4 @@ 547 common openat2 sys_openat2 548 common pidfd_getfd sys_pidfd_getfd 549 common faccessat2 sys_faccessat2 +550 common readfile sys_readfile diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl index d5cae5ffede0..454873892ba3 100644 --- a/arch/arm/tools/syscall.tbl +++ b/arch/arm/tools/syscall.tbl @@ -452,3 +452,4 @@ 437 common openat2 sys_openat2 438 common pidfd_getfd sys_pidfd_getfd 439 common faccessat2 sys_faccessat2 +440 common readfile sys_readfile diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h index 3b859596840d..b3b2019f8d16 100644 --- a/arch/arm64/include/asm/unistd.h +++ b/arch/arm64/include/asm/unistd.h @@ -38,7 +38,7 @@ #define __ARM_NR_compat_set_tls (__ARM_NR_COMPAT_BASE + 5) #define __ARM_NR_COMPAT_END (__ARM_NR_COMPAT_BASE + 0x800) -#define __NR_compat_syscalls 440 +#define __NR_compat_syscalls 441 #endif #define __ARCH_WANT_SYS_CLONE diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h index 6d95d0c8bf2f..524d19779612 100644 --- a/arch/arm64/include/asm/unistd32.h +++ b/arch/arm64/include/asm/unistd32.h @@ -885,6 +885,8 @@ __SYSCALL(__NR_openat2, sys_openat2) __SYSCALL(__NR_pidfd_getfd, sys_pidfd_getfd) #define __NR_faccessat2 439 __SYSCALL(__NR_faccessat2, sys_faccessat2) +#define __NR_readfile 440 +__SYSCALL(__NR_readfile, sys_readfile) /* * Please add new compat syscalls above this comment and update diff --git a/arch/ia64/kernel/syscalls/syscall.tbl b/arch/ia64/kernel/syscalls/syscall.tbl index 49e325b604b3..b188f03736bb 100644 --- a/arch/ia64/kernel/syscalls/syscall.tbl +++ b/arch/ia64/kernel/syscalls/syscall.tbl @@ -359,3 +359,4 @@ 437 common openat2 sys_openat2 438 common pidfd_getfd sys_pidfd_getfd 439 common faccessat2 sys_faccessat2 +440 common readfile sys_readfile diff --git a/arch/m68k/kernel/syscalls/syscall.tbl b/arch/m68k/kernel/syscalls/syscall.tbl index f71b1bbcc198..ab24bcb91344 100644 --- a/arch/m68k/kernel/syscalls/syscall.tbl +++ b/arch/m68k/kernel/syscalls/syscall.tbl @@ -438,3 +438,4 @@ 437 common openat2 sys_openat2 438 common pidfd_getfd sys_pidfd_getfd 439 common faccessat2 sys_faccessat2 +440 common readfile sys_readfile diff --git a/arch/microblaze/kernel/syscalls/syscall.tbl b/arch/microblaze/kernel/syscalls/syscall.tbl index edacc4561f2b..46c06f800e8e 100644 --- a/arch/microblaze/kernel/syscalls/syscall.tbl +++ b/arch/microblaze/kernel/syscalls/syscall.tbl @@ -444,3 +444,4 @@ 437 common openat2 sys_openat2 438 common pidfd_getfd sys_pidfd_getfd 439 common faccessat2 sys_faccessat2 +440 common readfile sys_readfile diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/syscalls/syscall_n32.tbl index f777141f5256..552ba4dafbef 100644 --- a/arch/mips/kernel/syscalls/syscall_n32.tbl +++ b/arch/mips/kernel/syscalls/syscall_n32.tbl @@ -377,3 +377,4 @@ 437 n32 openat2 sys_openat2 438 n32 pidfd_getfd sys_pidfd_getfd 439 n32 faccessat2 sys_faccessat2 +440 n32 readfile sys_readfile diff --git a/arch/mips/kernel/syscalls/syscall_n64.tbl b/arch/mips/kernel/syscalls/syscall_n64.tbl index da8c76394e17..e12581bf900b 100644 --- a/arch/mips/kernel/syscalls/syscall_n64.tbl +++ b/arch/mips/kernel/syscalls/syscall_n64.tbl @@ -353,3 +353,4 @@ 437 n64 openat2 sys_openat2 438 n64 pidfd_getfd sys_pidfd_getfd 439 n64 faccessat2 sys_faccessat2 +440 n64 readfile sys_readfile diff --git a/arch/mips/kernel/syscalls/syscall_o32.tbl b/arch/mips/kernel/syscalls/syscall_o32.tbl index 13280625d312..67cb8f8fbdb2 100644 --- a/arch/mips/kernel/syscalls/syscall_o32.tbl +++ b/arch/mips/kernel/syscalls/syscall_o32.tbl @@ -426,3 +426,4 @@ 437 o32 openat2 sys_openat2 438 o32 pidfd_getfd sys_pidfd_getfd 439 o32 faccessat2 sys_faccessat2 +440 o32 readfile sys_readfile diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/syscalls/syscall.tbl index 5a758fa6ec52..775e5228ab51 100644 --- a/arch/parisc/kernel/syscalls/syscall.tbl +++ b/arch/parisc/kernel/syscalls/syscall.tbl @@ -436,3 +436,4 @@ 437 common openat2 sys_openat2 438 common pidfd_getfd sys_pidfd_getfd 439 common faccessat2 sys_faccessat2 +440 common readfile sys_readfile diff --git a/arch/powerpc/kernel/syscalls/syscall.tbl b/arch/powerpc/kernel/syscalls/syscall.tbl index f833a3190822..d452db708635 100644 --- a/arch/powerpc/kernel/syscalls/syscall.tbl +++ b/arch/powerpc/kernel/syscalls/syscall.tbl @@ -528,3 +528,4 @@ 437 common openat2 sys_openat2 438 common pidfd_getfd sys_pidfd_getfd 439 common faccessat2 sys_faccessat2 +440 common readfile sys_readfile diff --git a/arch/s390/kernel/syscalls/syscall.tbl b/arch/s390/kernel/syscalls/syscall.tbl index bfdcb7633957..7ab529813a42 100644 --- a/arch/s390/kernel/syscalls/syscall.tbl +++ b/arch/s390/kernel/syscalls/syscall.tbl @@ -441,3 +441,4 @@ 437 common openat2 sys_openat2 sys_openat2 438 common pidfd_getfd sys_pidfd_getfd sys_pidfd_getfd 439 common faccessat2 sys_faccessat2 sys_faccessat2 +440 common readfile sys_readfile sys_readfile diff --git a/arch/sh/kernel/syscalls/syscall.tbl b/arch/sh/kernel/syscalls/syscall.tbl index acc35daa1b79..ce8862cdb707 100644 --- a/arch/sh/kernel/syscalls/syscall.tbl +++ b/arch/sh/kernel/syscalls/syscall.tbl @@ -441,3 +441,4 @@ 437 common openat2 sys_openat2 438 common pidfd_getfd sys_pidfd_getfd 439 common faccessat2 sys_faccessat2 +440 common readfile sys_readfile diff --git a/arch/sparc/kernel/syscalls/syscall.tbl b/arch/sparc/kernel/syscalls/syscall.tbl index 8004a276cb74..d89e7224bb0f 100644 --- a/arch/sparc/kernel/syscalls/syscall.tbl +++ b/arch/sparc/kernel/syscalls/syscall.tbl @@ -484,3 +484,4 @@ 437 common openat2 sys_openat2 438 common pidfd_getfd sys_pidfd_getfd 439 common faccessat2 sys_faccessat2 +440 common readfile sys_readfile diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl index d8f8a1a69ed1..6f8d0b0acb6a 100644 --- a/arch/x86/entry/syscalls/syscall_32.tbl +++ b/arch/x86/entry/syscalls/syscall_32.tbl @@ -443,3 +443,4 @@ 437 i386 openat2 sys_openat2 438 i386 pidfd_getfd sys_pidfd_getfd 439 i386 faccessat2 sys_faccessat2 +440 i386 readfile sys_readfile diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl index 78847b32e137..9c54081b7c14 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -360,6 +360,7 @@ 437 common openat2 sys_openat2 438 common pidfd_getfd sys_pidfd_getfd 439 common faccessat2 sys_faccessat2 +440 common readfile sys_readfile # # x32-specific system call numbers start at 512 to avoid cache impact diff --git a/arch/xtensa/kernel/syscalls/syscall.tbl b/arch/xtensa/kernel/syscalls/syscall.tbl index 69d0d73876b3..7b1f2ea76621 100644 --- a/arch/xtensa/kernel/syscalls/syscall.tbl +++ b/arch/xtensa/kernel/syscalls/syscall.tbl @@ -409,3 +409,4 @@ 437 common openat2 sys_openat2 438 common pidfd_getfd sys_pidfd_getfd 439 common faccessat2 sys_faccessat2 +440 common readfile sys_readfile diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index b951a87da987..9d338ef7802d 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -1005,6 +1005,8 @@ asmlinkage long sys_pidfd_send_signal(int pidfd, int sig, siginfo_t __user *info, unsigned int flags); asmlinkage long sys_pidfd_getfd(int pidfd, int fd, unsigned int flags); +asmlinkage long sys_readfile(int dfd, const char __user *filename, + char __user *buffer, size_t bufsize, int flags); /* * Architecture-specific system calls diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h index f4a01305d9a6..81b677c01266 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h @@ -857,9 +857,11 @@ __SYSCALL(__NR_openat2, sys_openat2) __SYSCALL(__NR_pidfd_getfd, sys_pidfd_getfd) #define __NR_faccessat2 439 __SYSCALL(__NR_faccessat2, sys_faccessat2) +#define __NR_readfile 440 +__SYSCALL(__NR_readfile, sys_readfile) #undef __NR_syscalls -#define __NR_syscalls 440 +#define __NR_syscalls 441 /* * 32 bit systems traditionally used different From patchwork Sat Jul 4 14:02:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greg Kroah-Hartman X-Patchwork-Id: 11643651 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B580314B7 for ; Sat, 4 Jul 2020 14:03:27 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8F3F9208E4 for ; Sat, 4 Jul 2020 14:03:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1593871407; bh=QbVSl3oLPOXYImHDoGUqheNC6ixh/nQxUqncQKrHdUI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=e/ditF3ijmLpvjk745k3IFouWNRCWfuRqtcx52HqdKduZXG2OPm43iZU1kpm6gizK DdeA0uWnZahg9H8Ox8b8em2OsP3QZjsl8xdSXiyC76jJdxgJJtzfzjgbZcVqLPnTI8 SfI5inWQYe+3iqwAs4GOyFjt4LGZy8Cnv0mkg0EU= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727899AbgGDODN (ORCPT ); Sat, 4 Jul 2020 10:03:13 -0400 Received: from mail.kernel.org ([198.145.29.99]:51556 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726909AbgGDODM (ORCPT ); Sat, 4 Jul 2020 10:03:12 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 376BF21883; Sat, 4 Jul 2020 14:03:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1593871389; bh=QbVSl3oLPOXYImHDoGUqheNC6ixh/nQxUqncQKrHdUI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=d7MM4KK/XY/rLpBgDLs24yd08b6v6DAqGqi8TiGqs0dfUMLQzf9BEze8tWV9g49tH goFze2nW/zWlkvIHFfPQLviRdwzgjjbf75CgOxqJm5dsRzp2IjifM1uiBThEHBvaT2 KKU8Ixz1ZJeNbe/t7azgpjzakv/vn4ZlqOPyegpA= From: Greg Kroah-Hartman To: viro@zeniv.linux.org.uk, mtk.manpages@gmail.com, shuah@kernel.org, linux-api@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-man@vger.kernel.org, linux-kselftest@vger.kernel.org, Greg Kroah-Hartman Subject: [PATCH 3/3] selftests: add readfile(2) selftests Date: Sat, 4 Jul 2020 16:02:49 +0200 Message-Id: <20200704140250.423345-4-gregkh@linuxfoundation.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200704140250.423345-1-gregkh@linuxfoundation.org> References: <20200704140250.423345-1-gregkh@linuxfoundation.org> MIME-Version: 1.0 Sender: linux-kselftest-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org Test the functionality of readfile(2) in various ways. Also provide a simple speed test program to benchmark using readfile() instead of using open()/read()/close(). Signed-off-by: Greg Kroah-Hartman --- tools/testing/selftests/Makefile | 1 + tools/testing/selftests/readfile/.gitignore | 3 + tools/testing/selftests/readfile/Makefile | 7 + tools/testing/selftests/readfile/readfile.c | 285 +++++++++++++++++ .../selftests/readfile/readfile_speed.c | 301 ++++++++++++++++++ 5 files changed, 597 insertions(+) create mode 100644 tools/testing/selftests/readfile/.gitignore create mode 100644 tools/testing/selftests/readfile/Makefile create mode 100644 tools/testing/selftests/readfile/readfile.c create mode 100644 tools/testing/selftests/readfile/readfile_speed.c diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index 1195bd85af38..82359233b945 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -46,6 +46,7 @@ TARGETS += ptrace TARGETS += openat2 TARGETS += rseq TARGETS += rtc +TARGETS += readfile TARGETS += seccomp TARGETS += sigaltstack TARGETS += size diff --git a/tools/testing/selftests/readfile/.gitignore b/tools/testing/selftests/readfile/.gitignore new file mode 100644 index 000000000000..f0e758d437e4 --- /dev/null +++ b/tools/testing/selftests/readfile/.gitignore @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 +readfile +readfile_speed diff --git a/tools/testing/selftests/readfile/Makefile b/tools/testing/selftests/readfile/Makefile new file mode 100644 index 000000000000..1bf1bdec40f8 --- /dev/null +++ b/tools/testing/selftests/readfile/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 +CFLAGS += -g -I../../../../usr/include/ +CFLAGS += -O2 -Wl,-no-as-needed -Wall + +TEST_GEN_PROGS := readfile readfile_speed + +include ../lib.mk diff --git a/tools/testing/selftests/readfile/readfile.c b/tools/testing/selftests/readfile/readfile.c new file mode 100644 index 000000000000..f0736c6dfa69 --- /dev/null +++ b/tools/testing/selftests/readfile/readfile.c @@ -0,0 +1,285 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 Greg Kroah-Hartman + * Copyright (c) 2020 The Linux Foundation + * + * Test the readfile() syscall in various ways. + */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../kselftest.h" + +//#ifndef __NR_readfile +//#define __NR_readfile -1 +//#endif + +#define __NR_readfile 440 + +#define TEST_FILE1 "/sys/devices/system/cpu/vulnerabilities/meltdown" +#define TEST_FILE2 "/sys/devices/system/cpu/vulnerabilities/spectre_v1" +#define TEST_FILE4 "/sys/kernel/debug/usb/devices" + +static int sys_readfile(int fd, const char *filename, unsigned char *buffer, + size_t bufsize, int flags) +{ + return syscall(__NR_readfile, fd, filename, buffer, bufsize, flags); +} + +/* + * Test that readfile() is even in the running kernel or not. + */ +static void test_readfile_supported(void) +{ + const char *proc_map = "/proc/self/maps"; + unsigned char buffer[10]; + int retval; + + if (__NR_readfile < 0) + ksft_exit_skip("readfile() syscall is not defined for the kernel this test was built against\n"); + + /* + * Do a simple test to see if the syscall really is present in the + * running kernel + */ + retval = sys_readfile(0, proc_map, &buffer[0], sizeof(buffer), 0); + if (retval == -1) + ksft_exit_skip("readfile() syscall not present on running kernel\n"); + + ksft_test_result_pass("readfile() syscall present\n"); +} + +/* + * Open all files in a specific sysfs directory and read from them + * + * This tests the "openat" type functionality of opening all files relative to a + * directory. We don't care at the moment about the contents. + */ +static void test_sysfs_files(void) +{ + static unsigned char buffer[8000]; + const char *sysfs_dir = "/sys/devices/system/cpu/vulnerabilities/"; + struct dirent *dirent; + DIR *vuln_sysfs_dir; + int sysfs_fd; + int retval; + + sysfs_fd = open(sysfs_dir, O_PATH | O_DIRECTORY); + if (sysfs_fd == -1) { + ksft_test_result_skip("unable to open %s directory\n", + sysfs_dir); + return; + } + + vuln_sysfs_dir = opendir(sysfs_dir); + if (!vuln_sysfs_dir) { + ksft_test_result_skip("%s unable to be opened, skipping test\n"); + return; + } + + ksft_print_msg("readfile: testing relative path functionality by reading files in %s\n", + sysfs_dir); + /* open all sysfs file in this directory and read the whole thing */ + while ((dirent = readdir(vuln_sysfs_dir))) { + /* ignore . and .. */ + if (strcmp(dirent->d_name, ".") == 0 || + strcmp(dirent->d_name, "..") == 0) + continue; + + retval = sys_readfile(sysfs_fd, dirent->d_name, &buffer[0], + sizeof(buffer), 0); + + if (retval <= 0) { + ksft_test_result_fail("readfile(%s) failed with %d\n", + dirent->d_name, retval); + goto exit; + } + + /* cut off trailing \n character */ + buffer[retval - 1] = 0x00; + ksft_print_msg(" '%s' contains \"%s\"\n", dirent->d_name, + buffer); + } + + ksft_test_result_pass("readfile() relative path functionality passed\n"); + +exit: + closedir(vuln_sysfs_dir); + close(sysfs_fd); +} + +/* Temporary directory variables */ +static int root_fd; /* test root directory file handle */ +static char tmpdir[PATH_MAX]; + +static void setup_tmpdir(void) +{ + char *tmpdir_root; + + tmpdir_root = getenv("TMPDIR"); + if (!tmpdir_root) + tmpdir_root = "/tmp"; + + snprintf(tmpdir, PATH_MAX, "%s/readfile.XXXXXX", tmpdir_root); + if (!mkdtemp(tmpdir)) { + ksft_test_result_fail("mkdtemp(%s) failed\n", tmpdir); + ksft_exit_fail(); + } + + root_fd = open(tmpdir, O_PATH | O_DIRECTORY); + if (root_fd == -1) { + ksft_exit_fail_msg("%s unable to be opened, error = %d\n", + tmpdir, root_fd); + ksft_exit_fail(); + } + + ksft_print_msg("%s created to use for testing\n", tmpdir); +} + +static void teardown_tmpdir(void) +{ + int retval; + + close(root_fd); + + retval = rmdir(tmpdir); + if (retval) { + ksft_exit_fail_msg("%s removed with return value %d\n", + tmpdir, retval); + ksft_exit_fail(); + } + ksft_print_msg("%s cleaned up and removed\n", tmpdir); + +} + +static void test_filesize(size_t size) +{ + char filename[PATH_MAX]; + unsigned char *write_data; + unsigned char *read_data; + int fd; + int retval; + size_t i; + + snprintf(filename, PATH_MAX, "size-%ld", size); + + read_data = malloc(size); + write_data = malloc(size); + if (!read_data || !write_data) + ksft_exit_fail_msg("Unable to allocate %ld bytes\n", size); + + fd = openat(root_fd, filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); + if (fd < 0) + ksft_exit_fail_msg("Unable to create file %s\n", filename); + + ksft_print_msg("%s created\n", filename); + + for (i = 0; i < size; ++i) + write_data[i] = (unsigned char)(0xff & i); + + write(fd, write_data, size); + close(fd); + + retval = sys_readfile(root_fd, filename, read_data, size, 0); + + if (retval != size) { + ksft_test_result_fail("Read %d bytes but wanted to read %ld bytes.\n", + retval, size); + goto exit; + } + + if (memcmp(read_data, write_data, size) != 0) { + ksft_test_result_fail("Read data of buffer size %d did not match written data\n", + size); + goto exit; + } + + ksft_test_result_pass("readfile() of size %ld succeeded.\n", size); + +exit: + unlinkat(root_fd, filename, 0); + free(write_data); + free(read_data); +} + + +/* + * Create a bunch of differently sized files, and verify we read the correct + * amount of data from them. + */ +static void test_filesizes(void) +{ + setup_tmpdir(); + + test_filesize(0x10); + test_filesize(0x100); + test_filesize(0x1000); + test_filesize(0x10000); + test_filesize(0x100000); + test_filesize(0x1000000); + + teardown_tmpdir(); + +} + +static void readfile(const char *filename) +{ +// int root_fd; + unsigned char buffer[16000]; + int retval; + + memset(buffer, 0x00, sizeof(buffer)); + +// root_fd = open("/", O_DIRECTORY); +// if (root_fd == -1) +// ksft_exit_fail_msg("error with root_fd\n"); + + retval = sys_readfile(root_fd, filename, &buffer[0], sizeof(buffer), 0); + +// close(root_fd); + + if (retval <= 0) + ksft_test_result_fail("readfile() test of filename=%s failed with retval %d\n", + filename, retval); + else + ksft_test_result_pass("readfile() test of filename=%s succeeded with retval=%d\n", + filename, retval); +// buffer='%s'\n", +// filename, retval, &buffer[0]); + +} + + +int main(int argc, char *argv[]) +{ + ksft_print_header(); + ksft_set_plan(10); + + test_readfile_supported(); // 1 test + + test_sysfs_files(); // 1 test + + test_filesizes(); // 6 tests + + setup_tmpdir(); + + readfile(TEST_FILE1); + readfile(TEST_FILE2); +// readfile(TEST_FILE4); + + teardown_tmpdir(); + + if (ksft_get_fail_cnt()) + return ksft_exit_fail(); + + return ksft_exit_pass(); +} + diff --git a/tools/testing/selftests/readfile/readfile_speed.c b/tools/testing/selftests/readfile/readfile_speed.c new file mode 100644 index 000000000000..11ca79163131 --- /dev/null +++ b/tools/testing/selftests/readfile/readfile_speed.c @@ -0,0 +1,301 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 Greg Kroah-Hartman + * Copyright (c) 2020 The Linux Foundation + * + * Tiny test program to try to benchmark the speed of the readfile syscall vs. + * the open/read/close sequence it can replace. + */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Default test file if no one wants to pick something else */ +#define DEFAULT_TEST_FILE "/sys/devices/system/cpu/vulnerabilities/meltdown" + +#define DEFAULT_TEST_LOOPS 1000 + +#define DEFAULT_TEST_TYPE "both" + +/* Max number of bytes that will be read from the file */ +#define TEST_BUFFER_SIZE 10000 +static unsigned char test_buffer[TEST_BUFFER_SIZE]; + +enum test_type { + TEST_READFILE, + TEST_OPENREADCLOSE, + TEST_BOTH, +}; + +/* Find the readfile syscall number */ +//#ifndef __NR_readfile +//#define __NR_readfile -1 +//#endif +#define __NR_readfile 440 + +static int sys_readfile(int fd, const char *filename, unsigned char *buffer, + size_t bufsize, int flags) +{ + return syscall(__NR_readfile, fd, filename, buffer, bufsize, flags); +} + +/* Test that readfile() is even in the running kernel or not. */ +static void test_readfile_supported(void) +{ + const char *proc_map = "/proc/self/maps"; + unsigned char buffer[10]; + int retval; + + if (__NR_readfile < 0) { + fprintf(stderr, + "readfile() syscall is not defined for the kernel this test was built against.\n"); + exit(1); + } + + /* + * Do a simple test to see if the syscall really is present in the + * running kernel + */ + retval = sys_readfile(0, proc_map, &buffer[0], sizeof(buffer), 0); + if (retval == -1) { + fprintf(stderr, + "readfile() syscall not present on running kernel.\n"); + exit(1); + } +} + +static inline long long get_time_ns(void) +{ + struct timespec t; + + clock_gettime(CLOCK_MONOTONIC, &t); + + return (long long)t.tv_sec * 1000000000 + t.tv_nsec; +} + +/* taken from all-io.h from util-linux repo */ +static inline ssize_t read_all(int fd, unsigned char *buf, size_t count) +{ + ssize_t ret; + ssize_t c = 0; + int tries = 0; + + while (count > 0) { + ret = read(fd, buf, count); + if (ret <= 0) { + if (ret < 0 && (errno == EAGAIN || errno == EINTR) && + (tries++ < 5)) { + usleep(250000); + continue; + } + return c ? c : -1; + } + tries = 0; + count -= ret; + buf += ret; + c += ret; + } + return c; +} + +static int openreadclose(const char *filename, unsigned char *buffer, + size_t bufsize) +{ + size_t count; + int fd; + + fd = openat(0, filename, O_RDONLY); + if (fd < 0) { + printf("error opening %s\n", filename); + return fd; + } + + count = read_all(fd, buffer, bufsize); + if (count < 0) { + printf("Error %ld reading from %s\n", count, filename); + } + + close(fd); + return count; +} + +static int run_test(enum test_type test_type, const char *filename) +{ + switch (test_type) { + case TEST_READFILE: + return sys_readfile(0, filename, &test_buffer[0], + TEST_BUFFER_SIZE, O_RDONLY); + + case TEST_OPENREADCLOSE: + return openreadclose(filename, &test_buffer[0], + TEST_BUFFER_SIZE); + default: + return -EINVAL; + } +} + +static const char * const test_names[] = { + [TEST_READFILE] = "readfile", + [TEST_OPENREADCLOSE] = "open/read/close", +}; + +static int run_test_loop(int loops, enum test_type test_type, + const char *filename) +{ + long long time_start; + long long time_end; + long long time_elapsed; + int retval = 0; + int i; + + fprintf(stdout, + "Running %s test on file %s for %d loops...\n", + test_names[test_type], filename, loops); + + /* Fill the cache with one run of the read first */ + retval = run_test(test_type, filename); + if (retval < 0) { + fprintf(stderr, + "test %s was unable to run with error %d\n", + test_names[test_type], retval); + return retval; + } + + time_start = get_time_ns(); + + for (i = 0; i < loops; ++i) { + retval = run_test(test_type, filename); + + if (retval < 0) { + fprintf(stderr, + "test failed on loop %d with error %d\n", + i, retval); + break; + } + } + time_end = get_time_ns(); + + time_elapsed = time_end - time_start; + + fprintf(stdout, "Took %lld ns\n", time_elapsed); + + return retval; +} + +static int do_read_file_test(int loops, enum test_type test_type, + const char *filename) +{ + int retval; + + if (test_type == TEST_BOTH) { + retval = do_read_file_test(loops, TEST_READFILE, filename); + retval = do_read_file_test(loops, TEST_OPENREADCLOSE, filename); + return retval; + } + return run_test_loop(loops, test_type, filename); +} + +static int check_file_present(const char *filename) +{ + struct stat sb; + int retval; + + retval = stat(filename, &sb); + if (retval == -1) { + fprintf(stderr, + "filename %s is not present\n", filename); + return retval; + } + + if ((sb.st_mode & S_IFMT) != S_IFREG) { + fprintf(stderr, + "filename %s must be a real file, not anything else.\n", + filename); + return -1; + } + return 0; +} + +static void usage(char *progname) +{ + fprintf(stderr, + "usage: %s [options]\n" + " -l loops Number of loops to run the test for.\n" + " default is %d\n" + " -t testtype Test type to run.\n" + " types are: readfile, openreadclose, both\n" + " default is %s\n" + " -f filename Filename to read from, full path, not relative.\n" + " default is %s\n", + progname, + DEFAULT_TEST_LOOPS, DEFAULT_TEST_TYPE, DEFAULT_TEST_FILE); +} + +int main(int argc, char *argv[]) +{ + char *progname; + char *testtype = DEFAULT_TEST_TYPE; + char *filename = DEFAULT_TEST_FILE; + int loops = DEFAULT_TEST_LOOPS; + enum test_type test_type; + int retval; + char c; + + progname = strrchr(argv[0], '/'); + progname = progname ? 1+progname : argv[0]; + + while (EOF != (c = getopt(argc, argv, "t:l:f:h"))) { + switch (c) { + case 'l': + loops = atoi(optarg); + break; + + case 't': + testtype = optarg; + break; + + case 'f': + filename = optarg; + break; + + case 'h': + usage(progname); + return 0; + + default: + usage(progname); + return -1; + } + } + + if (strcmp(testtype, "readfile") == 0) + test_type = TEST_READFILE; + else if (strcmp(testtype, "openreadclose") == 0) + test_type = TEST_OPENREADCLOSE; + else if (strcmp(testtype, "both") == 0) + test_type = TEST_BOTH; + else { + usage(progname); + return -1; + } + + test_readfile_supported(); + + retval = check_file_present(filename); + if (retval) + return retval; + + return do_read_file_test(loops, test_type, filename); +}