diff options
author | Koen Kooi <koen@dominion.thruhere.net> | 2012-08-08 10:41:23 +0200 |
---|---|---|
committer | Denys Dmytriyenko <denys@ti.com> | 2012-09-14 01:50:52 -0400 |
commit | 6203cbca5c9df9095882544f1eaa370a9cbd364a (patch) | |
tree | 737bb49b9f53b00ef177a9efbf648d0c0e5b7f0a /recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.24/0046-block-fix-infinite-loop-in-__getblk_slow.patch | |
parent | e4ea426bb5e7b9dc18cd9fc1e820744c05b63561 (diff) | |
download | meta-ti-6203cbca5c9df9095882544f1eaa370a9cbd364a.tar.gz |
linux-ti33x-psp 3.2: update to 3.2.25
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
Signed-off-by: Denys Dmytriyenko <denys@ti.com>
Diffstat (limited to 'recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.24/0046-block-fix-infinite-loop-in-__getblk_slow.patch')
-rw-r--r-- | recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.24/0046-block-fix-infinite-loop-in-__getblk_slow.patch | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.24/0046-block-fix-infinite-loop-in-__getblk_slow.patch b/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.24/0046-block-fix-infinite-loop-in-__getblk_slow.patch new file mode 100644 index 00000000..6c5d9b8b --- /dev/null +++ b/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.24/0046-block-fix-infinite-loop-in-__getblk_slow.patch | |||
@@ -0,0 +1,116 @@ | |||
1 | From 898f4d272514d19aafee8cd66b796c0553fca080 Mon Sep 17 00:00:00 2001 | ||
2 | From: Jeff Moyer <jmoyer@redhat.com> | ||
3 | Date: Thu, 12 Jul 2012 09:43:14 -0400 | ||
4 | Subject: [PATCH 046/109] block: fix infinite loop in __getblk_slow | ||
5 | |||
6 | commit 91f68c89d8f35fe98ea04159b9a3b42d0149478f upstream. | ||
7 | |||
8 | Commit 080399aaaf35 ("block: don't mark buffers beyond end of disk as | ||
9 | mapped") exposed a bug in __getblk_slow that causes mount to hang as it | ||
10 | loops infinitely waiting for a buffer that lies beyond the end of the | ||
11 | disk to become uptodate. | ||
12 | |||
13 | The problem was initially reported by Torsten Hilbrich here: | ||
14 | |||
15 | https://lkml.org/lkml/2012/6/18/54 | ||
16 | |||
17 | and also reported independently here: | ||
18 | |||
19 | http://www.sysresccd.org/forums/viewtopic.php?f=13&t=4511 | ||
20 | |||
21 | and then Richard W.M. Jones and Marcos Mello noted a few separate | ||
22 | bugzillas also associated with the same issue. This patch has been | ||
23 | confirmed to fix: | ||
24 | |||
25 | https://bugzilla.redhat.com/show_bug.cgi?id=835019 | ||
26 | |||
27 | The main problem is here, in __getblk_slow: | ||
28 | |||
29 | for (;;) { | ||
30 | struct buffer_head * bh; | ||
31 | int ret; | ||
32 | |||
33 | bh = __find_get_block(bdev, block, size); | ||
34 | if (bh) | ||
35 | return bh; | ||
36 | |||
37 | ret = grow_buffers(bdev, block, size); | ||
38 | if (ret < 0) | ||
39 | return NULL; | ||
40 | if (ret == 0) | ||
41 | free_more_memory(); | ||
42 | } | ||
43 | |||
44 | __find_get_block does not find the block, since it will not be marked as | ||
45 | mapped, and so grow_buffers is called to fill in the buffers for the | ||
46 | associated page. I believe the for (;;) loop is there primarily to | ||
47 | retry in the case of memory pressure keeping grow_buffers from | ||
48 | succeeding. However, we also continue to loop for other cases, like the | ||
49 | block lying beond the end of the disk. So, the fix I came up with is to | ||
50 | only loop when grow_buffers fails due to memory allocation issues | ||
51 | (return value of 0). | ||
52 | |||
53 | The attached patch was tested by myself, Torsten, and Rich, and was | ||
54 | found to resolve the problem in call cases. | ||
55 | |||
56 | Signed-off-by: Jeff Moyer <jmoyer@redhat.com> | ||
57 | Reported-and-Tested-by: Torsten Hilbrich <torsten.hilbrich@secunet.com> | ||
58 | Tested-by: Richard W.M. Jones <rjones@redhat.com> | ||
59 | Reviewed-by: Josh Boyer <jwboyer@redhat.com> | ||
60 | [ Jens is on vacation, taking this directly - Linus ] | ||
61 | -- | ||
62 | Stable Notes: this patch requires backport to 3.0, 3.2 and 3.3. | ||
63 | Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> | ||
64 | Signed-off-by: Ben Hutchings <ben@decadent.org.uk> | ||
65 | --- | ||
66 | fs/buffer.c | 22 +++++++++++++--------- | ||
67 | 1 files changed, 13 insertions(+), 9 deletions(-) | ||
68 | |||
69 | diff --git a/fs/buffer.c b/fs/buffer.c | ||
70 | index c807931..4115eca 100644 | ||
71 | --- a/fs/buffer.c | ||
72 | +++ b/fs/buffer.c | ||
73 | @@ -1087,6 +1087,9 @@ grow_buffers(struct block_device *bdev, sector_t block, int size) | ||
74 | static struct buffer_head * | ||
75 | __getblk_slow(struct block_device *bdev, sector_t block, int size) | ||
76 | { | ||
77 | + int ret; | ||
78 | + struct buffer_head *bh; | ||
79 | + | ||
80 | /* Size must be multiple of hard sectorsize */ | ||
81 | if (unlikely(size & (bdev_logical_block_size(bdev)-1) || | ||
82 | (size < 512 || size > PAGE_SIZE))) { | ||
83 | @@ -1099,20 +1102,21 @@ __getblk_slow(struct block_device *bdev, sector_t block, int size) | ||
84 | return NULL; | ||
85 | } | ||
86 | |||
87 | - for (;;) { | ||
88 | - struct buffer_head * bh; | ||
89 | - int ret; | ||
90 | +retry: | ||
91 | + bh = __find_get_block(bdev, block, size); | ||
92 | + if (bh) | ||
93 | + return bh; | ||
94 | |||
95 | + ret = grow_buffers(bdev, block, size); | ||
96 | + if (ret == 0) { | ||
97 | + free_more_memory(); | ||
98 | + goto retry; | ||
99 | + } else if (ret > 0) { | ||
100 | bh = __find_get_block(bdev, block, size); | ||
101 | if (bh) | ||
102 | return bh; | ||
103 | - | ||
104 | - ret = grow_buffers(bdev, block, size); | ||
105 | - if (ret < 0) | ||
106 | - return NULL; | ||
107 | - if (ret == 0) | ||
108 | - free_more_memory(); | ||
109 | } | ||
110 | + return NULL; | ||
111 | } | ||
112 | |||
113 | /* | ||
114 | -- | ||
115 | 1.7.7.6 | ||
116 | |||