| From ecc0c469f27765ed1e2b967be0aa17cee1a60b76 Mon Sep 17 00:00:00 2001 |
| From: NeilBrown <neilb@suse.com> |
| Date: Fri, 17 Nov 2017 15:29:13 -0800 |
| Subject: autofs: don't fail mount for transient error |
| |
| From: NeilBrown <neilb@suse.com> |
| |
| commit ecc0c469f27765ed1e2b967be0aa17cee1a60b76 upstream. |
| |
| Currently if the autofs kernel module gets an error when writing to the |
| pipe which links to the daemon, then it marks the whole moutpoint as |
| catatonic, and it will stop working. |
| |
| It is possible that the error is transient. This can happen if the |
| daemon is slow and more than 16 requests queue up. If a subsequent |
| process tries to queue a request, and is then signalled, the write to |
| the pipe will return -ERESTARTSYS and autofs will take that as total |
| failure. |
| |
| So change the code to assess -ERESTARTSYS and -ENOMEM as transient |
| failures which only abort the current request, not the whole mountpoint. |
| |
| It isn't a crash or a data corruption, but having autofs mountpoints |
| suddenly stop working is rather inconvenient. |
| |
| Ian said: |
| |
| : And given the problems with a half dozen (or so) user space applications |
| : consuming large amounts of CPU under heavy mount and umount activity this |
| : could happen more easily than we expect. |
| |
| Link: http://lkml.kernel.org/r/87y3norvgp.fsf@notabene.neil.brown.name |
| Signed-off-by: NeilBrown <neilb@suse.com> |
| Acked-by: Ian Kent <raven@themaw.net> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/autofs4/waitq.c | 15 ++++++++++++++- |
| 1 file changed, 14 insertions(+), 1 deletion(-) |
| |
| --- a/fs/autofs4/waitq.c |
| +++ b/fs/autofs4/waitq.c |
| @@ -87,7 +87,8 @@ static int autofs4_write(struct autofs_s |
| spin_unlock_irqrestore(¤t->sighand->siglock, flags); |
| } |
| |
| - return (bytes > 0); |
| + /* if 'wr' returned 0 (impossible) we assume -EIO (safe) */ |
| + return bytes == 0 ? 0 : wr < 0 ? wr : -EIO; |
| } |
| |
| static void autofs4_notify_daemon(struct autofs_sb_info *sbi, |
| @@ -101,6 +102,7 @@ static void autofs4_notify_daemon(struct |
| } pkt; |
| struct file *pipe = NULL; |
| size_t pktsz; |
| + int ret; |
| |
| DPRINTK("wait id = 0x%08lx, name = %.*s, type=%d", |
| (unsigned long) wq->wait_queue_token, wq->name.len, wq->name.name, type); |
| @@ -173,7 +175,18 @@ static void autofs4_notify_daemon(struct |
| mutex_unlock(&sbi->wq_mutex); |
| |
| if (autofs4_write(sbi, pipe, &pkt, pktsz)) |
| + switch (ret = autofs4_write(sbi, pipe, &pkt, pktsz)) { |
| + case 0: |
| + break; |
| + case -ENOMEM: |
| + case -ERESTARTSYS: |
| + /* Just fail this one */ |
| + autofs4_wait_release(sbi, wq->wait_queue_token, ret); |
| + break; |
| + default: |
| autofs4_catatonic_mode(sbi); |
| + break; |
| + } |
| fput(pipe); |
| } |
| |