diff options
Diffstat (limited to 'recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.25/0024-cifs-when-CONFIG_HIGHMEM-is-set-serialize-the-read-w.patch')
-rw-r--r-- | recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.25/0024-cifs-when-CONFIG_HIGHMEM-is-set-serialize-the-read-w.patch | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.25/0024-cifs-when-CONFIG_HIGHMEM-is-set-serialize-the-read-w.patch b/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.25/0024-cifs-when-CONFIG_HIGHMEM-is-set-serialize-the-read-w.patch new file mode 100644 index 00000000..004839e6 --- /dev/null +++ b/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.25/0024-cifs-when-CONFIG_HIGHMEM-is-set-serialize-the-read-w.patch | |||
@@ -0,0 +1,124 @@ | |||
1 | From 3e3da899949f18869c6958a30a861d89f2d4b73c Mon Sep 17 00:00:00 2001 | ||
2 | From: Jeff Layton <jlayton@redhat.com> | ||
3 | Date: Wed, 11 Jul 2012 09:09:36 -0400 | ||
4 | Subject: [PATCH 24/73] cifs: when CONFIG_HIGHMEM is set, serialize the | ||
5 | read/write kmaps | ||
6 | |||
7 | commit 3cf003c08be785af4bee9ac05891a15bcbff856a upstream. | ||
8 | |||
9 | Jian found that when he ran fsx on a 32 bit arch with a large wsize the | ||
10 | process and one of the bdi writeback kthreads would sometimes deadlock | ||
11 | with a stack trace like this: | ||
12 | |||
13 | crash> bt | ||
14 | PID: 2789 TASK: f02edaa0 CPU: 3 COMMAND: "fsx" | ||
15 | #0 [eed63cbc] schedule at c083c5b3 | ||
16 | #1 [eed63d80] kmap_high at c0500ec8 | ||
17 | #2 [eed63db0] cifs_async_writev at f7fabcd7 [cifs] | ||
18 | #3 [eed63df0] cifs_writepages at f7fb7f5c [cifs] | ||
19 | #4 [eed63e50] do_writepages at c04f3e32 | ||
20 | #5 [eed63e54] __filemap_fdatawrite_range at c04e152a | ||
21 | #6 [eed63ea4] filemap_fdatawrite at c04e1b3e | ||
22 | #7 [eed63eb4] cifs_file_aio_write at f7fa111a [cifs] | ||
23 | #8 [eed63ecc] do_sync_write at c052d202 | ||
24 | #9 [eed63f74] vfs_write at c052d4ee | ||
25 | #10 [eed63f94] sys_write at c052df4c | ||
26 | #11 [eed63fb0] ia32_sysenter_target at c0409a98 | ||
27 | EAX: 00000004 EBX: 00000003 ECX: abd73b73 EDX: 012a65c6 | ||
28 | DS: 007b ESI: 012a65c6 ES: 007b EDI: 00000000 | ||
29 | SS: 007b ESP: bf8db178 EBP: bf8db1f8 GS: 0033 | ||
30 | CS: 0073 EIP: 40000424 ERR: 00000004 EFLAGS: 00000246 | ||
31 | |||
32 | Each task would kmap part of its address array before getting stuck, but | ||
33 | not enough to actually issue the write. | ||
34 | |||
35 | This patch fixes this by serializing the marshal_iov operations for | ||
36 | async reads and writes. The idea here is to ensure that cifs | ||
37 | aggressively tries to populate a request before attempting to fulfill | ||
38 | another one. As soon as all of the pages are kmapped for a request, then | ||
39 | we can unlock and allow another one to proceed. | ||
40 | |||
41 | There's no need to do this serialization on non-CONFIG_HIGHMEM arches | ||
42 | however, so optimize all of this out when CONFIG_HIGHMEM isn't set. | ||
43 | |||
44 | Reported-by: Jian Li <jiali@redhat.com> | ||
45 | Signed-off-by: Jeff Layton <jlayton@redhat.com> | ||
46 | Signed-off-by: Steve French <smfrench@gmail.com> | ||
47 | [bwh: Backported to 3.2: adjust context] | ||
48 | Signed-off-by: Ben Hutchings <ben@decadent.org.uk> | ||
49 | --- | ||
50 | fs/cifs/cifssmb.c | 30 ++++++++++++++++++++++++++++++ | ||
51 | 1 files changed, 30 insertions(+), 0 deletions(-) | ||
52 | |||
53 | diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c | ||
54 | index 6aa7457..c858a29 100644 | ||
55 | --- a/fs/cifs/cifssmb.c | ||
56 | +++ b/fs/cifs/cifssmb.c | ||
57 | @@ -89,6 +89,32 @@ static struct { | ||
58 | /* Forward declarations */ | ||
59 | static void cifs_readv_complete(struct work_struct *work); | ||
60 | |||
61 | +#ifdef CONFIG_HIGHMEM | ||
62 | +/* | ||
63 | + * On arches that have high memory, kmap address space is limited. By | ||
64 | + * serializing the kmap operations on those arches, we ensure that we don't | ||
65 | + * end up with a bunch of threads in writeback with partially mapped page | ||
66 | + * arrays, stuck waiting for kmap to come back. That situation prevents | ||
67 | + * progress and can deadlock. | ||
68 | + */ | ||
69 | +static DEFINE_MUTEX(cifs_kmap_mutex); | ||
70 | + | ||
71 | +static inline void | ||
72 | +cifs_kmap_lock(void) | ||
73 | +{ | ||
74 | + mutex_lock(&cifs_kmap_mutex); | ||
75 | +} | ||
76 | + | ||
77 | +static inline void | ||
78 | +cifs_kmap_unlock(void) | ||
79 | +{ | ||
80 | + mutex_unlock(&cifs_kmap_mutex); | ||
81 | +} | ||
82 | +#else /* !CONFIG_HIGHMEM */ | ||
83 | +#define cifs_kmap_lock() do { ; } while(0) | ||
84 | +#define cifs_kmap_unlock() do { ; } while(0) | ||
85 | +#endif /* CONFIG_HIGHMEM */ | ||
86 | + | ||
87 | /* Mark as invalid, all open files on tree connections since they | ||
88 | were closed when session to server was lost */ | ||
89 | static void mark_open_files_invalid(struct cifs_tcon *pTcon) | ||
90 | @@ -1540,6 +1566,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) | ||
91 | eof_index = eof ? (eof - 1) >> PAGE_CACHE_SHIFT : 0; | ||
92 | cFYI(1, "eof=%llu eof_index=%lu", eof, eof_index); | ||
93 | |||
94 | + cifs_kmap_lock(); | ||
95 | list_for_each_entry_safe(page, tpage, &rdata->pages, lru) { | ||
96 | if (remaining >= PAGE_CACHE_SIZE) { | ||
97 | /* enough data to fill the page */ | ||
98 | @@ -1589,6 +1616,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) | ||
99 | page_cache_release(page); | ||
100 | } | ||
101 | } | ||
102 | + cifs_kmap_unlock(); | ||
103 | |||
104 | /* issue the read if we have any iovecs left to fill */ | ||
105 | if (rdata->nr_iov > 1) { | ||
106 | @@ -2171,6 +2199,7 @@ cifs_async_writev(struct cifs_writedata *wdata) | ||
107 | iov[0].iov_base = smb; | ||
108 | |||
109 | /* marshal up the pages into iov array */ | ||
110 | + cifs_kmap_lock(); | ||
111 | wdata->bytes = 0; | ||
112 | for (i = 0; i < wdata->nr_pages; i++) { | ||
113 | iov[i + 1].iov_len = min(inode->i_size - | ||
114 | @@ -2179,6 +2208,7 @@ cifs_async_writev(struct cifs_writedata *wdata) | ||
115 | iov[i + 1].iov_base = kmap(wdata->pages[i]); | ||
116 | wdata->bytes += iov[i + 1].iov_len; | ||
117 | } | ||
118 | + cifs_kmap_unlock(); | ||
119 | |||
120 | cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes); | ||
121 | |||
122 | -- | ||
123 | 1.7.7.6 | ||
124 | |||