diff options
author | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-01-20 14:01:31 -0300 |
---|---|---|
committer | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-01-20 14:01:31 -0300 |
commit | b4b7ff4b08e691656c9d77c758fc355833128ac0 (patch) | |
tree | 82fcb00e6b918026dc9f2d1f05ed8eee83874cc0 /fs/aufs | |
parent | 35acfa0fc609f2a2cd95cef4a6a9c3a5c38f1778 (diff) |
Linux-libre 4.4-gnupck-4.4-gnu
Diffstat (limited to 'fs/aufs')
-rw-r--r-- | fs/aufs/xino.c | 66 |
1 files changed, 44 insertions, 22 deletions
diff --git a/fs/aufs/xino.c b/fs/aufs/xino.c index 90de8c56d..61df836cd 100644 --- a/fs/aufs/xino.c +++ b/fs/aufs/xino.c @@ -40,6 +40,9 @@ ssize_t xino_fread(vfs_readf_t func, struct file *file, void *kbuf, size_t size, /* ---------------------------------------------------------------------- */ +static ssize_t xino_fwrite_wkq(vfs_writef_t func, struct file *file, void *buf, + size_t size, loff_t *pos); + static ssize_t do_xino_fwrite(vfs_writef_t func, struct file *file, void *kbuf, size_t size, loff_t *pos) { @@ -49,14 +52,26 @@ static ssize_t do_xino_fwrite(vfs_writef_t func, struct file *file, void *kbuf, void *k; 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 { - /* todo: signal_pending? */ err = func(file, buf.u, size, pos); - } while (err == -EAGAIN || err == -EINTR); + 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 */ @@ -82,35 +97,42 @@ static void call_do_xino_fwrite(void *args) *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos); } +static ssize_t xino_fwrite_wkq(vfs_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; +} + ssize_t xino_fwrite(vfs_writef_t func, struct file *file, void *buf, size_t size, loff_t *pos) { 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; - } + } else + err = xino_fwrite_wkq(func, file, buf, size, pos); return err; } |