* [PATCH resend] fs/namei.c: micro-optimize acl_permission_check @ 2020-06-05 14:23 Rasmus Villemoes 2020-06-05 20:18 ` Linus Torvalds 0 siblings, 1 reply; 8+ messages in thread From: Rasmus Villemoes @ 2020-06-05 14:23 UTC (permalink / raw) To: Alexander Viro Cc: Linus Torvalds, Rasmus Villemoes, linux-fsdevel, linux-kernel Just something like open(/usr/include/sys/stat.h) causes five calls of generic_permission -> acl_permission_check -> in_group_p; if the compiler first tried /usr/local/include/..., that would be a few more. Altogether, on a bog-standard Ubuntu 20.04 install, a workload consisting of compiling lots of userspace programs (i.e., calling lots of short-lived programs that all need to get their shared libs mapped in, and the compilers poking around looking for system headers - lots of /usr/lib, /usr/bin, /usr/include/ accesses) puts in_group_p around 0.1% according to perf top. With an artificial load such as while true ; do find /usr/ -print0 | xargs -0 stat > /dev/null ; done that jumps to over 0.4%. System-installed files are almost always 0755 (directories and binaries) or 0644, so in most cases, we can avoid the binary search and the cost of pulling the cred->groups array and in_group_p() .text into the cpu cache. Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk> --- fs/namei.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/fs/namei.c b/fs/namei.c index d81f73ff1a8b..c6f0c6643db5 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -303,7 +303,12 @@ static int acl_permission_check(struct inode *inode, int mask) return error; } - if (in_group_p(inode->i_gid)) + /* + * If the "group" and "other" permissions are the same, + * there's no point calling in_group_p() to decide which + * set to use. + */ + if ((((mode >> 3) ^ mode) & 7) && in_group_p(inode->i_gid)) mode >>= 3; } -- 2.23.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH resend] fs/namei.c: micro-optimize acl_permission_check 2020-06-05 14:23 [PATCH resend] fs/namei.c: micro-optimize acl_permission_check Rasmus Villemoes @ 2020-06-05 20:18 ` Linus Torvalds 2020-06-07 13:22 ` Rasmus Villemoes 0 siblings, 1 reply; 8+ messages in thread From: Linus Torvalds @ 2020-06-05 20:18 UTC (permalink / raw) To: Rasmus Villemoes; +Cc: Alexander Viro, linux-fsdevel, Linux Kernel Mailing List [-- Attachment #1: Type: text/plain, Size: 1306 bytes --] On Fri, Jun 5, 2020 at 7:23 AM Rasmus Villemoes <linux@rasmusvillemoes.dk> wrote: > > + /* > + * If the "group" and "other" permissions are the same, > + * there's no point calling in_group_p() to decide which > + * set to use. > + */ > + if ((((mode >> 3) ^ mode) & 7) && in_group_p(inode->i_gid)) > mode >>= 3; Ugh. Not only is this ugly, but it's not even the best optimization. We don't care that group and other match exactly. We only care that they match in the low 3 bits of the "mask" bits. So if we want this optimization - and it sounds worth it - I think we should do it right. But I also think it should be written more legibly. And the "& 7" is the same "& (MAY_READ | MAY_WRITE | MAY_EXEC)" we do later. In other words, if we do this, I'd like it to be done even more aggressively, but I'd also like the end result to be a lot more readable and have more comments about why we do that odd thing. Something like this *UNTESTED* patch, perhaps? I might have gotten something wrong, so this would need double-checking, but if it's right, I find it a _lot_ more easy to understand than making one expression that is pretty complicated and opaque. Hmm? Linus [-- Attachment #2: patch --] [-- Type: application/octet-stream, Size: 1447 bytes --] fs/namei.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index d81f73ff1a8b..517bd6a25761 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -294,25 +294,34 @@ static int acl_permission_check(struct inode *inode, int mask) { unsigned int mode = inode->i_mode; - if (likely(uid_eq(current_fsuid(), inode->i_uid))) - mode >>= 6; - else { - if (IS_POSIXACL(inode) && (mode & S_IRWXG)) { - int error = check_acl(inode, mask); - if (error != -EAGAIN) - return error; - } + mask &= MAY_READ | MAY_WRITE | MAY_EXEC; + /* Are we the owner? If so, ACL's don't matter */ + if (likely(uid_eq(current_fsuid(), inode->i_uid))) { + if ((mask << 6) & ~mode) + return -EACCES; + return 0; + } + + /* Do we have ACL's? */ + if (IS_POSIXACL(inode) && (mode & S_IRWXG)) { + int error = check_acl(inode, mask); + if (error != -EAGAIN) + return error; + } + + /* + * Are the group permissions different from + * the other permissions in the bits we care + * about? Need to check group ownership if so. + */ + if (mask & (mode ^ (mode >> 3))) { if (in_group_p(inode->i_gid)) mode >>= 3; } - /* - * If the DACs are ok we don't need any capability check. - */ - if ((mask & ~mode & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0) - return 0; - return -EACCES; + /* Bits in 'mode' clear that we require? */ + return (mask & ~mode) ? -EACCES : 0; } /** ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH resend] fs/namei.c: micro-optimize acl_permission_check 2020-06-05 20:18 ` Linus Torvalds @ 2020-06-07 13:22 ` Rasmus Villemoes 2020-06-07 16:37 ` Linus Torvalds 0 siblings, 1 reply; 8+ messages in thread From: Rasmus Villemoes @ 2020-06-07 13:22 UTC (permalink / raw) To: Linus Torvalds; +Cc: Alexander Viro, linux-fsdevel, Linux Kernel Mailing List On 05/06/2020 22.18, Linus Torvalds wrote: > On Fri, Jun 5, 2020 at 7:23 AM Rasmus Villemoes > <linux@rasmusvillemoes.dk> wrote: >> >> + /* >> + * If the "group" and "other" permissions are the same, >> + * there's no point calling in_group_p() to decide which >> + * set to use. >> + */ >> + if ((((mode >> 3) ^ mode) & 7) && in_group_p(inode->i_gid)) >> mode >>= 3; > > Ugh. Not only is this ugly, but it's not even the best optimization. > > We don't care that group and other match exactly. We only care that > they match in the low 3 bits of the "mask" bits. Yes, I did think about that, but I thought this was the more obviously correct approach, and that in practice one only sees the 0X44 and 0X55 cases. > So if we want this optimization - and it sounds worth it - I think we > should do it right. But I also think it should be written more > legibly. > > And the "& 7" is the same "& (MAY_READ | MAY_WRITE | MAY_EXEC)" we do later. > > In other words, if we do this, I'd like it to be done even more > aggressively, but I'd also like the end result to be a lot more > readable and have more comments about why we do that odd thing. > > Something like this *UNTESTED* patch, perhaps? That will kinda work, except you do that mask &= MAY_RWX before check_acl(), which cares about MAY_NOT_BLOCK and who knows what other bits. > I might have gotten something wrong, so this would need > double-checking, but if it's right, I find it a _lot_ more easy to > understand than making one expression that is pretty complicated and > opaque. Well, I thought this was readable enough with the added comment. There's already that magic constant 3 in the shifts, so the 7 seemed entirely sensible, though one could spell it 0007. Whatever. Perhaps this? As a whole function, I think that's a bit easier for brain-storming. It's your patch, just with that rwx thing used instead of mask, except for the call to check_acl(). static int acl_permission_check(struct inode *inode, int mask) { unsigned int mode = inode->i_mode; unsigned int rwx = mask & (MAY_READ | MAY_WRITE | MAY_EXEC); /* Are we the owner? If so, ACL's don't matter */ if (likely(uid_eq(current_fsuid(), inode->i_uid))) { if ((rwx << 6) & ~mode) return -EACCES; return 0; } /* Do we have ACL's? */ if (IS_POSIXACL(inode) && (mode & S_IRWXG)) { int error = check_acl(inode, mask); if (error != -EAGAIN) return error; } /* * Are the group permissions different from * the other permissions in the bits we care * about? Need to check group ownership if so. */ if (rwx & (mode ^ (mode >> 3))) { if (in_group_p(inode->i_gid)) mode >>= 3; } /* Bits in 'mode' clear that we require? */ return (rwx & ~mode) ? -EACCES : 0; } Rasmus ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH resend] fs/namei.c: micro-optimize acl_permission_check 2020-06-07 13:22 ` Rasmus Villemoes @ 2020-06-07 16:37 ` Linus Torvalds 2020-06-07 19:48 ` Linus Torvalds 0 siblings, 1 reply; 8+ messages in thread From: Linus Torvalds @ 2020-06-07 16:37 UTC (permalink / raw) To: Rasmus Villemoes; +Cc: Alexander Viro, linux-fsdevel, Linux Kernel Mailing List On Sun, Jun 7, 2020 at 6:22 AM Rasmus Villemoes <linux@rasmusvillemoes.dk> wrote: > > Yes, I did think about that, but I thought this was the more obviously > correct approach, and that in practice one only sees the 0X44 and 0X55 > cases. I'm not sure about that - it probably depends on your umask. Because I see a lot of -rw-rw-r--. in my home directory, and it looks like I have a umask of 0002. That's just the Fedora default, I think. Looking at /etc/bashrc, it does if [ $UID -gt 199 ] && [ "`/usr/bin/id -gn`" = "`/usr/bin/id -un`" ]; then umask 002 else umask 022 fi iow, if you have the same user-name and group name, then umask is 002 by default for regular users. Honestly, I'm not sure why Fedora has that "each user has its own group" thing, but it's at least one common setup. So I think that the system you are looking at just happens to have umask 0022, which is traditional when you have just a 'user' group. > That will kinda work, except you do that mask &= MAY_RWX before > check_acl(), which cares about MAY_NOT_BLOCK and who knows what other bits. Good catch. > Perhaps this? As a whole function, I think that's a bit easier for > brain-storming. It's your patch, just with that rwx thing used instead > of mask, except for the call to check_acl(). Looks fine to me. Once we have to have rwx/mask separate, I'm not sure it's worth having that early masking at all (didn't check what the register pressure is over that "check_acl()" call, but at least it is fairly easy to follow along. Send me a patch with commit message etc, and I'll apply it. Linus ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH resend] fs/namei.c: micro-optimize acl_permission_check 2020-06-07 16:37 ` Linus Torvalds @ 2020-06-07 19:48 ` Linus Torvalds 2020-06-08 2:05 ` Al Viro 2020-06-08 10:08 ` Rasmus Villemoes 0 siblings, 2 replies; 8+ messages in thread From: Linus Torvalds @ 2020-06-07 19:48 UTC (permalink / raw) To: Rasmus Villemoes; +Cc: Alexander Viro, linux-fsdevel, Linux Kernel Mailing List [-- Attachment #1: Type: text/plain, Size: 1438 bytes --] On Sun, Jun 7, 2020 at 9:37 AM Linus Torvalds <torvalds@linux-foundation.org> wrote: > > > That will kinda work, except you do that mask &= MAY_RWX before > > check_acl(), which cares about MAY_NOT_BLOCK and who knows what other bits. > > Good catch. With the change to not clear the non-rwx bits in general, the owner case now wants to do the masking, and then the "shift left by 6" modification makes no sense since it only makes for a bigger constant (the only reason to do the shift-right was so that the bitwise not of the i_mode could be done in parallel with the shift, but with the masking that instruction scheduling optimization becomes kind of immaterial too). So I modified that patch to not bother, and add a comment about MAY_NOT_BLOCK. And since I was looking at the MAY_NOT_BLOCK logic, it was not only not mentioned in comments, it also had some really confusing code around it. The posix_acl_permission() looked like it tried to conserve that bit, which is completely wrong. It wasn't a bug only for the simple reason that the only two call-sites had either explicitly cleared the bit when calling, or had tested that the bit wasn't set in the first place. So as a result, I wrote a second patch to clear that confusion up. Rasmus, say the word and I'll mark you for authorship on the first one. Comments? Can you find something else wrong here, or some other fixup to do? Al, any reaction? Linus [-- Attachment #2: 0001-vfs-do-not-do-group-lookup-when-not-necessary.patch --] [-- Type: text/x-patch, Size: 3726 bytes --] From 09cc0faef0766da8ff8e6a82cfc5c8c53a01d0a7 Mon Sep 17 00:00:00 2001 From: Linus Torvalds <torvalds@linux-foundation.org> Date: Fri, 5 Jun 2020 13:40:45 -0700 Subject: [PATCH 1/2] vfs: do not do group lookup when not necessary Rasmus Villemoes points out that the 'in_group_p()' tests can be a noticeable expense, and often completely unnecessary. A common situation is that the 'group' bits are the same as the 'other' bits wrt the permissions we want to test. So rewrite 'acl_permission_check()' to not bother checking for group ownership when the permission check doesn't care. For example, if we're asking for read permissions, and both 'group' and 'other' allow reading, there's really no reason to check if we're part of the group or not: either way, we'll allow it. Rasmus says: "On a bog-standard Ubuntu 20.04 install, a workload consisting of compiling lots of userspace programs (i.e., calling lots of short-lived programs that all need to get their shared libs mapped in, and the compilers poking around looking for system headers - lots of /usr/lib, /usr/bin, /usr/include/ accesses) puts in_group_p around 0.1% according to perf top. System-installed files are almost always 0755 (directories and binaries) or 0644, so in most cases, we can avoid the binary search and the cost of pulling the cred->groups array and in_group_p() .text into the cpu cache" Reported-by: Rasmus Villemoes <linux@rasmusvillemoes.dk> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- fs/namei.c | 44 +++++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index d81f73ff1a8b..e74a7849e9b5 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -288,37 +288,51 @@ static int check_acl(struct inode *inode, int mask) } /* - * This does the basic permission checking + * This does the basic UNIX permission checking. + * + * Note that the POSIX ACL check cares about the MAY_NOT_BLOCK bit, + * for RCU walking. */ static int acl_permission_check(struct inode *inode, int mask) { unsigned int mode = inode->i_mode; - if (likely(uid_eq(current_fsuid(), inode->i_uid))) + /* Are we the owner? If so, ACL's don't matter */ + if (likely(uid_eq(current_fsuid(), inode->i_uid))) { + mask &= 7; mode >>= 6; - else { - if (IS_POSIXACL(inode) && (mode & S_IRWXG)) { - int error = check_acl(inode, mask); - if (error != -EAGAIN) - return error; - } + return (mask & ~mode) ? -EACCES : 0; + } - if (in_group_p(inode->i_gid)) - mode >>= 3; + /* Do we have ACL's? */ + if (IS_POSIXACL(inode) && (mode & S_IRWXG)) { + int error = check_acl(inode, mask); + if (error != -EAGAIN) + return error; } + /* Only RWX matters for group/other mode bits */ + mask &= 7; + /* - * If the DACs are ok we don't need any capability check. + * Are the group permissions different from + * the other permissions in the bits we care + * about? Need to check group ownership if so. */ - if ((mask & ~mode & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0) - return 0; - return -EACCES; + if (mask & (mode ^ (mode >> 3))) { + if (in_group_p(inode->i_gid)) + mode >>= 3; + } + + /* Bits in 'mode' clear that we require? */ + return (mask & ~mode) ? -EACCES : 0; } /** * generic_permission - check for access rights on a Posix-like filesystem * @inode: inode to check access rights for - * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC, ...) + * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC, + * %MAY_NOT_BLOCK ...) * * Used to check for read/write/execute permissions on a file. * We use "fsuid" for this, letting us set arbitrary permissions -- 2.27.0.rc1.8.g04bd0c80d7 [-- Attachment #3: 0002-vfs-clean-up-posix_acl_permission-logic-aroudn-MAY_N.patch --] [-- Type: text/x-patch, Size: 2119 bytes --] From ead0cfe68e04c167034405a785878058ceb6d589 Mon Sep 17 00:00:00 2001 From: Linus Torvalds <torvalds@linux-foundation.org> Date: Sun, 7 Jun 2020 12:19:06 -0700 Subject: [PATCH 2/2] vfs: clean up posix_acl_permission() logic aroudn MAY_NOT_BLOCK posix_acl_permission() does not care about MAY_NOT_BLOCK, and in fact the permission logic internally must not check that bit (it's only for upper layers to decide whether they can block to do IO to look up the acl information or not). But the way the code was written, it _looked_ like it cared, since the function explicitly did not mask that bit off. But it has exactly two callers: one for when that bit is set, which first clears the bit before calling posix_acl_permission(), and the other call site when that bit was clear. So stop the silly games "saving" the MAY_NOT_BLOCK bit that must not be used for the actual permission test, and that currently is pointlessly cleared by the callers when the function itself should just not care. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> --- fs/namei.c | 2 +- fs/posix_acl.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index e74a7849e9b5..72d4219c93ac 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -271,7 +271,7 @@ static int check_acl(struct inode *inode, int mask) /* no ->get_acl() calls in RCU mode... */ if (is_uncached_acl(acl)) return -ECHILD; - return posix_acl_permission(inode, acl, mask & ~MAY_NOT_BLOCK); + return posix_acl_permission(inode, acl, mask); } acl = get_acl(inode, ACL_TYPE_ACCESS); diff --git a/fs/posix_acl.c b/fs/posix_acl.c index 249672bf54fe..95882b3f5f62 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c @@ -350,7 +350,7 @@ posix_acl_permission(struct inode *inode, const struct posix_acl *acl, int want) const struct posix_acl_entry *pa, *pe, *mask_obj; int found = 0; - want &= MAY_READ | MAY_WRITE | MAY_EXEC | MAY_NOT_BLOCK; + want &= MAY_READ | MAY_WRITE | MAY_EXEC; FOREACH_ACL_ENTRY(pa, acl, pe) { switch(pa->e_tag) { -- 2.27.0.rc1.8.g04bd0c80d7 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH resend] fs/namei.c: micro-optimize acl_permission_check 2020-06-07 19:48 ` Linus Torvalds @ 2020-06-08 2:05 ` Al Viro 2020-06-08 19:18 ` Linus Torvalds 2020-06-08 10:08 ` Rasmus Villemoes 1 sibling, 1 reply; 8+ messages in thread From: Al Viro @ 2020-06-08 2:05 UTC (permalink / raw) To: Linus Torvalds; +Cc: Rasmus Villemoes, linux-fsdevel, Linux Kernel Mailing List On Sun, Jun 07, 2020 at 12:48:53PM -0700, Linus Torvalds wrote: > Rasmus, say the word and I'll mark you for authorship on the first one. > > Comments? Can you find something else wrong here, or some other fixup to do? > > Al, any reaction? It's correct, but this > + if (mask & (mode ^ (mode >> 3))) { > + if (in_group_p(inode->i_gid)) > + mode >>= 3; > + } > + > + /* Bits in 'mode' clear that we require? */ > + return (mask & ~mode) ? -EACCES : 0; might be easier to follow if we had, from the very beginning done unsigned int deny = ~inode->i_mode; and turned that into // for group the bits 3..5 apply, for others - 0..2 // we only care which to use when they do not // agree anyway. if (mask & (deny ^ (deny >> 3))) // mask & deny != mask & (deny >> 3) if (in_... deny >>= 3; return mask & deny ? -EACCES : 0; Hell knows... ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH resend] fs/namei.c: micro-optimize acl_permission_check 2020-06-08 2:05 ` Al Viro @ 2020-06-08 19:18 ` Linus Torvalds 0 siblings, 0 replies; 8+ messages in thread From: Linus Torvalds @ 2020-06-08 19:18 UTC (permalink / raw) To: Al Viro; +Cc: Rasmus Villemoes, linux-fsdevel, Linux Kernel Mailing List On Sun, Jun 7, 2020 at 7:05 PM Al Viro <viro@zeniv.linux.org.uk> wrote: > > return mask & deny ? -EACCES : 0; I agree that 'deny' would be simpler to read here, but in other places it would look odd. ie the IS_POSIXACL() thing that checks for "are group bits set" still wants the mode. And I'd hate to have us use code that then mixes 'deny' and 'mode' when they are directly related to each other. Anyway, I merged the patch as-is, I guess we can make future changes to this if you feel strongly about it. Linus ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH resend] fs/namei.c: micro-optimize acl_permission_check 2020-06-07 19:48 ` Linus Torvalds 2020-06-08 2:05 ` Al Viro @ 2020-06-08 10:08 ` Rasmus Villemoes 1 sibling, 0 replies; 8+ messages in thread From: Rasmus Villemoes @ 2020-06-08 10:08 UTC (permalink / raw) To: Linus Torvalds; +Cc: Alexander Viro, linux-fsdevel, Linux Kernel Mailing List On 07/06/2020 21.48, Linus Torvalds wrote: > On Sun, Jun 7, 2020 at 9:37 AM Linus Torvalds > <torvalds@linux-foundation.org> wrote: >> >>> That will kinda work, except you do that mask &= MAY_RWX before >>> check_acl(), which cares about MAY_NOT_BLOCK and who knows what other bits. >> >> Good catch. > > With the change to not clear the non-rwx bits in general, the owner > case now wants to do the masking, and then the "shift left by 6" > modification makes no sense since it only makes for a bigger constant > (the only reason to do the shift-right was so that the bitwise not of > the i_mode could be done in parallel with the shift, but with the > masking that instruction scheduling optimization becomes kind of > immaterial too). So I modified that patch to not bother, and add a > comment about MAY_NOT_BLOCK. > > And since I was looking at the MAY_NOT_BLOCK logic, it was not only > not mentioned in comments, it also had some really confusing code > around it. > > The posix_acl_permission() looked like it tried to conserve that bit, > which is completely wrong. It wasn't a bug only for the simple reason > that the only two call-sites had either explicitly cleared the bit > when calling, or had tested that the bit wasn't set in the first > place. > > So as a result, I wrote a second patch to clear that confusion up. > > Rasmus, say the word and I'll mark you for authorship on the first one. It might be a bit confusing with me mentioned in the third person and then also author, and it's really mostly your patch, so reported-by is fine with me. But it's up to you. > Comments? Can you find something else wrong here, or some other fixup to do? No, I think it's ok. I took a look at the disassembly and it looks fine. There's an extra push/pop of %r14 [that's where gcc computes mode>>3, then CSE allows it to do cmovne %r14d,%ebx after in_group_p), so the owner case gets slightly penalized. I think/hope the savings from avoiding the in_group_p should compensate for that - any absolute path open() by non-root saves at least two in_group_p. YMMV. Rasmus ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2020-06-08 19:18 UTC | newest] Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2020-06-05 14:23 [PATCH resend] fs/namei.c: micro-optimize acl_permission_check Rasmus Villemoes 2020-06-05 20:18 ` Linus Torvalds 2020-06-07 13:22 ` Rasmus Villemoes 2020-06-07 16:37 ` Linus Torvalds 2020-06-07 19:48 ` Linus Torvalds 2020-06-08 2:05 ` Al Viro 2020-06-08 19:18 ` Linus Torvalds 2020-06-08 10:08 ` Rasmus Villemoes
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).