Projects
Mega:23.03
systemd
_service:tar_scm:backport-fileio-lower-maximum-...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:backport-fileio-lower-maximum-virtual-file-buffer-size-by-one.patch of Package systemd
From feb68f6aad36930f0b0c6c70164287c5bc46b64c Mon Sep 17 00:00:00 2001 From: Lennart Poettering <lennart@poettering.net> Date: Tue, 14 Sep 2021 23:03:37 +0200 Subject: [PATCH] fileio: lower maximum virtual file buffer size by one byte MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When reading virtual files (i.e. procfs, sysfs, …) we currently put a limit of 4M-1 on that. We have to pick something, and we have to read these files in a single read() (since the kernel generally doesn't support continuation read()s for them). 4M-1 is actually the maximum size the kernel allows for reads from files in /proc/sys/, all larger reads will result in an ENOMEM error (which is really weird, but the kernel does what the kernel does). Hence 4M-1 sounds like a smart choice. However, we made one mistake here: in order to be able to detect EOFs properly we actually read one byte more than we actually intend to return: if that extra byte can be read, then we know the file is actually larger than our limit and we can generate an EFBIG error from that. However, if it cannot be read then we know EOF was hit, and we are good. So ultimately after all we issued a single 4M read, which the kernel then responds with ENOMEM to. And that means read_virtual_file() actually doesn't work properly right now on /proc/sys/. Let's fix that. The fix is simple, lower the limit of the the buffer we intend to return by one, i.e. 4M-2. That way, the read() we'll issue is exactly as large as the limit the kernel allows, and we still get safely detect EOF from it. (cherry picked from commit 7ab7547a40d456d34120b2f44b26385ac1338ebd) Conflict:NA Reference:https://github.com/systemd/systemd/commit/feb68f6aad36930f0b0c6c70164287c5bc46b64c --- src/basic/fileio.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/basic/fileio.c b/src/basic/fileio.c index 99a44fdea2..ba0ca98d72 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -30,14 +30,16 @@ /* The maximum size of the file we'll read in one go in read_full_file() (64M). */ #define READ_FULL_BYTES_MAX (64U*1024U*1024U - 1U) -/* The maximum size of virtual files we'll read in one go in read_virtual_file() (4M). Note that this limit - * is different (and much lower) than the READ_FULL_BYTES_MAX limit. This reflects the fact that we use - * different strategies for reading virtual and regular files: virtual files are generally size constrained: - * there we allocate the full buffer size in advance. Regular files OTOH can be much larger, and here we grow - * the allocations exponentially in a loop. In glibc large allocations are immediately backed by mmap() - * making them relatively slow (measurably so). Thus, when allocating the full buffer in advance the large - * limit is a problem. When allocating piecemeal it's not. Hence pick two distinct limits. */ -#define READ_VIRTUAL_BYTES_MAX (4U*1024U*1024U - 1U) +/* The maximum size of virtual files (i.e. procfs, sysfs, and other virtual "API" files) we'll read in one go + * in read_virtual_file(). Note that this limit is different (and much lower) than the READ_FULL_BYTES_MAX + * limit. This reflects the fact that we use different strategies for reading virtual and regular files: + * virtual files we generally have to read in a single read() syscall since the kernel doesn't support + * continuation read()s for them. Thankfully they are somewhat size constrained. Thus we can allocate the + * full potential buffer in advance. Regular files OTOH can be much larger, and there we grow the allocations + * exponentially in a loop. We use a size limit of 4M-2 because 4M-1 is the maximum buffer that /proc/sys/ + * allows us to read() (larger reads will fail with ENOMEM), and we want to read one extra byte so that we + * can detect EOFs. */ +#define READ_VIRTUAL_BYTES_MAX (4U*1024U*1024U - 2U) int fopen_unlocked(const char *path, const char *options, FILE **ret) { assert(ret); -- 2.33.0
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2