From dac8af714439030e074970262f5f3d9b62cd1dc3 Mon Sep 17 00:00:00 2001 From: Jindong Yue Date: Mon, 2 Aug 2021 15:56:45 +0800 Subject: [PATCH 1/3] ANDROID: GKI: Enable CONFIG_USB_EHCI_ROOT_HUB_TT Enable CONFIG_USB_EHCI_ROOT_HUB_TT so that EHCI controllers on i.MX8MM can integrate transaction translators. Bug: 194108974 Signed-off-by: Jindong Yue Change-Id: If06b571e1a3a74946953fa48f86545b282b20b4d --- arch/arm64/configs/gki_defconfig | 1 + arch/x86/configs/gki_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig index 9e75fba692ad..92175e738c81 100644 --- a/arch/arm64/configs/gki_defconfig +++ b/arch/arm64/configs/gki_defconfig @@ -469,6 +469,7 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_OTG=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_EHCI_HCD_PLATFORM=y CONFIG_USB_ACM=y CONFIG_USB_STORAGE=y diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig index c4f89cd04566..65d05fc15038 100644 --- a/arch/x86/configs/gki_defconfig +++ b/arch/x86/configs/gki_defconfig @@ -421,6 +421,7 @@ CONFIG_USB_HIDDEV=y CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_EHCI_HCD_PLATFORM=y CONFIG_USB_ACM=y CONFIG_USB_STORAGE=y From 6b7e00716430761fa2c747ba04a83149ba20676c Mon Sep 17 00:00:00 2001 From: Sandeep Patil Date: Tue, 3 Aug 2021 21:09:25 +0000 Subject: [PATCH 2/3] ANDROID: Revert "ANDROID: fs: pipe: wakeup readers on small writes even if pipe had data" This reverts commit 76879a196435 ("ANDROID: fs: pipe: wakeup readers on small writes even if pipe had data") to replace that with the bug fix that landed upstream at https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3a34b13a88caeb2800ab44a4918f230041b37dd9 Bug: 193851993 Test: Build and boot cuttlefish. Signed-off-by: Sandeep Patil Change-Id: Ic4f5e2cc516b4ea68ae7d63225d1529217990431 --- fs/pipe.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/fs/pipe.c b/fs/pipe.c index 37c9d399258a..412b3b618994 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -406,7 +406,7 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from) ssize_t ret = 0; size_t total_len = iov_iter_count(from); ssize_t chars; - bool do_wakeup = false; + bool was_empty = false; bool wake_next_writer = false; /* Null write succeeds. */ @@ -429,11 +429,10 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from) #endif /* - * Wake up readers if the pipe was written to. Regardless - * of whether it was empty or not. Otherwise, threads - * waiting with EPOLLET will hang until the pipe is emptied. + * Only wake up if the pipe started out empty, since + * otherwise there should be no readers waiting. * - * If pipe wasn't empty we try to merge new data into + * If it wasn't empty we try to merge new data into * the last buffer. * * That naturally merges small writes, but it also @@ -441,8 +440,9 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from) * spanning multiple pages. */ head = pipe->head; + was_empty = pipe_empty(head, pipe->tail); chars = total_len & (PAGE_SIZE-1); - if (chars && !pipe_empty(head, pipe->tail)) { + if (chars && !was_empty) { unsigned int mask = pipe->ring_size - 1; struct pipe_buffer *buf = &pipe->bufs[(head - 1) & mask]; int offset = buf->offset + buf->len; @@ -460,7 +460,6 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from) } buf->len += ret; - do_wakeup = true; if (!iov_iter_count(from)) goto out; } @@ -527,7 +526,6 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from) ret += copied; buf->offset = 0; buf->len = copied; - do_wakeup = true; if (!iov_iter_count(from)) break; @@ -555,12 +553,13 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from) * become empty while we dropped the lock. */ __pipe_unlock(pipe); - if (do_wakeup) { + if (was_empty) { wake_up_interruptible_sync_poll(&pipe->rd_wait, EPOLLIN | EPOLLRDNORM); kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); } wait_event_interruptible_exclusive(pipe->wr_wait, pipe_writable(pipe)); __pipe_lock(pipe); + was_empty = pipe_empty(pipe->head, pipe->tail); wake_next_writer = true; } out: @@ -577,7 +576,7 @@ out: * how (for example) the GNU make jobserver uses small writes to * wake up pending jobs */ - if (do_wakeup) { + if (was_empty) { wake_up_interruptible_sync_poll(&pipe->rd_wait, EPOLLIN | EPOLLRDNORM); kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); } From 3de34cc5ea313cb67b03b05e0d2c09a2cb2a1a35 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 30 Jul 2021 15:42:34 -0700 Subject: [PATCH 3/3] UPSTREAM: pipe: make pipe writes always wake up readers Since commit 1b6b26ae7053 ("pipe: fix and clarify pipe write wakeup logic") we have sanitized the pipe write logic, and would only try to wake up readers if they needed it. In particular, if the pipe already had data in it before the write, there was no point in trying to wake up a reader, since any existing readers must have been aware of the pre-existing data already. Doing extraneous wakeups will only cause potential thundering herd problems. However, it turns out that some Android libraries have misused the EPOLL interface, and expected "edge triggered" be to "any new write will trigger it". Even if there was no edge in sight. Quoting Sandeep Patil: "The commit 1b6b26ae7053 ('pipe: fix and clarify pipe write wakeup logic') changed pipe write logic to wakeup readers only if the pipe was empty at the time of write. However, there are libraries that relied upon the older behavior for notification scheme similar to what's described in [1] One such library 'realm-core'[2] is used by numerous Android applications. The library uses a similar notification mechanism as GNU Make but it never drains the pipe until it is full. When Android moved to v5.10 kernel, all applications using this library stopped working. The library has since been fixed[3] but it will be a while before all applications incorporate the updated library" Our regression rule for the kernel is that if applications break from new behavior, it's a regression, even if it was because the application did something patently wrong. Also note the original report [4] by Michal Kerrisk about a test for this epoll behavior - but at that point we didn't know of any actual broken use case. So add the extraneous wakeup, to approximate the old behavior. [ I say "approximate", because the exact old behavior was to do a wakeup not for each write(), but for each pipe buffer chunk that was filled in. The behavior introduced by this change is not that - this is just "every write will cause a wakeup, whether necessary or not", which seems to be sufficient for the broken library use. ] It's worth noting that this adds the extraneous wakeup only for the write side, while the read side still considers the "edge" to be purely about reading enough from the pipe to allow further writes. See commit f467a6a66419 ("pipe: fix and clarify pipe read wakeup logic") for the pipe read case, which remains that "only wake up if the pipe was full, and we read something from it". Link: https://lore.kernel.org/lkml/CAHk-=wjeG0q1vgzu4iJhW5juPkTsjTYmiqiMUYAebWW+0bam6w@mail.gmail.com/ [1] Link: https://github.com/realm/realm-core [2] Link: https://github.com/realm/realm-core/issues/4666 [3] Link: https://lore.kernel.org/lkml/CAKgNAkjMBGeAwF=2MKK758BhxvW58wYTgYKB2V-gY1PwXxrH+Q@mail.gmail.com/ [4] Link: https://lore.kernel.org/lkml/20210729222635.2937453-1-sspatil@android.com/ Bug: 193851993 Reported-by: Sandeep Patil Cc: Michael Kerrisk Signed-off-by: Linus Torvalds (cherry picked from commit 3a34b13a88caeb2800ab44a4918f230041b37dd9) Signed-off-by: Sandeep Patil Change-Id: Idcf3e8faa31bff47ada4b815237a355e0757b964 --- fs/pipe.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/pipe.c b/fs/pipe.c index 412b3b618994..6f5f97c0fdee 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -429,20 +429,20 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from) #endif /* - * Only wake up if the pipe started out empty, since - * otherwise there should be no readers waiting. + * Epoll nonsensically wants a wakeup whether the pipe + * was already empty or not. * * If it wasn't empty we try to merge new data into * the last buffer. * * That naturally merges small writes, but it also - * page-aligs the rest of the writes for large writes + * page-aligns the rest of the writes for large writes * spanning multiple pages. */ head = pipe->head; - was_empty = pipe_empty(head, pipe->tail); + was_empty = true; chars = total_len & (PAGE_SIZE-1); - if (chars && !was_empty) { + if (chars && !pipe_empty(head, pipe->tail)) { unsigned int mask = pipe->ring_size - 1; struct pipe_buffer *buf = &pipe->bufs[(head - 1) & mask]; int offset = buf->offset + buf->len;