]>
Commit | Line | Data |
---|---|---|
95244f99 GKH |
1 | From foo@baz Wed Dec 6 17:39:55 CET 2017 |
2 | From: Jan Kara <jack@suse.cz> | |
3 | Date: Wed, 8 Feb 2017 14:30:53 -0800 | |
4 | Subject: mm: avoid returning VM_FAULT_RETRY from ->page_mkwrite handlers | |
5 | ||
6 | From: Jan Kara <jack@suse.cz> | |
7 | ||
8 | ||
9 | [ Upstream commit 0911d0041c22922228ca52a977d7b0b0159fee4b ] | |
10 | ||
11 | Some ->page_mkwrite handlers may return VM_FAULT_RETRY as its return | |
12 | code (GFS2 or Lustre can definitely do this). However VM_FAULT_RETRY | |
13 | from ->page_mkwrite is completely unhandled by the mm code and results | |
14 | in locking and writeably mapping the page which definitely is not what | |
15 | the caller wanted. | |
16 | ||
17 | Fix Lustre and block_page_mkwrite_ret() used by other filesystems | |
18 | (notably GFS2) to return VM_FAULT_NOPAGE instead which results in | |
19 | bailing out from the fault code, the CPU then retries the access, and we | |
20 | fault again effectively doing what the handler wanted. | |
21 | ||
22 | Link: http://lkml.kernel.org/r/20170203150729.15863-1-jack@suse.cz | |
23 | Signed-off-by: Jan Kara <jack@suse.cz> | |
24 | Reported-by: Al Viro <viro@ZenIV.linux.org.uk> | |
25 | Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com> | |
26 | Cc: Matthew Wilcox <willy@infradead.org> | |
27 | Signed-off-by: Andrew Morton <akpm@linux-foundation.org> | |
28 | Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> | |
29 | Signed-off-by: Sasha Levin <alexander.levin@verizon.com> | |
30 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
31 | --- | |
32 | drivers/staging/lustre/lustre/llite/llite_mmap.c | 4 +--- | |
33 | include/linux/buffer_head.h | 4 +--- | |
34 | 2 files changed, 2 insertions(+), 6 deletions(-) | |
35 | ||
36 | --- a/drivers/staging/lustre/lustre/llite/llite_mmap.c | |
37 | +++ b/drivers/staging/lustre/lustre/llite/llite_mmap.c | |
38 | @@ -401,15 +401,13 @@ static int ll_page_mkwrite(struct vm_are | |
39 | result = VM_FAULT_LOCKED; | |
40 | break; | |
41 | case -ENODATA: | |
42 | + case -EAGAIN: | |
43 | case -EFAULT: | |
44 | result = VM_FAULT_NOPAGE; | |
45 | break; | |
46 | case -ENOMEM: | |
47 | result = VM_FAULT_OOM; | |
48 | break; | |
49 | - case -EAGAIN: | |
50 | - result = VM_FAULT_RETRY; | |
51 | - break; | |
52 | default: | |
53 | result = VM_FAULT_SIGBUS; | |
54 | break; | |
55 | --- a/include/linux/buffer_head.h | |
56 | +++ b/include/linux/buffer_head.h | |
57 | @@ -239,12 +239,10 @@ static inline int block_page_mkwrite_ret | |
58 | { | |
59 | if (err == 0) | |
60 | return VM_FAULT_LOCKED; | |
61 | - if (err == -EFAULT) | |
62 | + if (err == -EFAULT || err == -EAGAIN) | |
63 | return VM_FAULT_NOPAGE; | |
64 | if (err == -ENOMEM) | |
65 | return VM_FAULT_OOM; | |
66 | - if (err == -EAGAIN) | |
67 | - return VM_FAULT_RETRY; | |
68 | /* -ENOSPC, -EDQUOT, -EIO ... */ | |
69 | return VM_FAULT_SIGBUS; | |
70 | } |