build/patch/kernel/pine64-default/aufs-hang.patch
James Kingdon 96688fd4dd Fix aufs busy loop
This patch fixes a bug in aufs that can cause docker processes to enter
a defunct state but still consume 100% cpu. The processes are unkillable
as is the entire docker container, with the only recourse being to reboot
the machine. The problem was reported to Debian in the following report:
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=812207
Message #47 in that exchange contains two patches which resolve the problem,
and this commit is the simple combination of those two.
2017-09-20 21:17:36 -04:00

134 lines
3.2 KiB
Diff

*** a/fs/aufs/xino.c 2017-09-20 14:25:41.841850111 +0000
--- b/fs/aufs/xino.c 2017-09-20 19:23:31.065603010 +0000
*************** ssize_t xino_fread(au_readf_t func, stru
*** 53,58 ****
--- 53,61 ----
/* ---------------------------------------------------------------------- */
+ static ssize_t xino_fwrite_wkq(au_writef_t func, struct file *file, void *buf,
+ size_t size, loff_t *pos);
+
static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *kbuf,
size_t size, loff_t *pos)
{
*************** static ssize_t do_xino_fwrite(au_writef_
*** 63,75 ****
const char __user *u;
} buf;
buf.k = kbuf;
oldfs = get_fs();
set_fs(KERNEL_DS);
do {
- /* todo: signal_pending? */
err = func(file, buf.u, size, pos);
! } while (err == -EAGAIN || err == -EINTR);
set_fs(oldfs);
#if 0 /* reserved for future use */
--- 66,92 ----
const char __user *u;
} buf;
+ int i;
+ const int prevent_endless = 10;
+
+ i = 0;
buf.k = kbuf;
oldfs = get_fs();
set_fs(KERNEL_DS);
do {
err = func(file, buf.u, size, pos);
! if (err == -EINTR
! && !au_wkq_test()
! && fatal_signal_pending(current)) {
! set_fs(oldfs);
! err = xino_fwrite_wkq(func, file, kbuf, size, pos);
! BUG_ON(err == -EINTR);
! oldfs = get_fs();
! set_fs(KERNEL_DS);
! }
! } while (i++ < prevent_endless &&
! (err == -EAGAIN || err == -EINTR));
!
set_fs(oldfs);
#if 0 /* reserved for future use */
*************** ssize_t xino_fwrite(au_writef_t func, st
*** 100,132 ****
{
ssize_t err;
- /* todo: signal block and no wkq? */
if (rlimit(RLIMIT_FSIZE) == RLIM_INFINITY) {
lockdep_off();
err = do_xino_fwrite(func, file, buf, size, pos);
lockdep_on();
} else {
! /*
! * it breaks RLIMIT_FSIZE and normal user's limit,
! * users should care about quota and real 'filesystem full.'
! */
! int wkq_err;
! struct do_xino_fwrite_args args = {
! .errp = &err,
! .func = func,
! .file = file,
! .buf = buf,
! .size = size,
! .pos = pos
! };
!
! wkq_err = au_wkq_wait(call_do_xino_fwrite, &args);
! if (unlikely(wkq_err))
! err = wkq_err;
}
return err;
}
/* ---------------------------------------------------------------------- */
--- 117,157 ----
{
ssize_t err;
if (rlimit(RLIMIT_FSIZE) == RLIM_INFINITY) {
lockdep_off();
err = do_xino_fwrite(func, file, buf, size, pos);
lockdep_on();
} else {
! err = xino_fwrite_wkq(func, file, buf, size, pos);
}
return err;
}
+
+ static ssize_t xino_fwrite_wkq(au_writef_t func, struct file *file, void *buf,
+ size_t size, loff_t *pos)
+ {
+ ssize_t err;
+ int wkq_err;
+ struct do_xino_fwrite_args args = {
+ .errp = &err,
+ .func = func,
+ .file = file,
+ .buf = buf,
+ .size = size,
+ .pos = pos
+ };
+
+ /*
+ * it breaks RLIMIT_FSIZE and normal user's limit,
+ * users should care about quota and real 'filesystem full.'
+ */
+ wkq_err = au_wkq_wait(call_do_xino_fwrite, &args);
+ if (unlikely(wkq_err))
+ err = wkq_err;
+
+ return err;
+ }
/* ---------------------------------------------------------------------- */