summaryrefslogtreecommitdiffstats
path: root/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.25/0024-cifs-when-CONFIG_HIGHMEM-is-set-serialize-the-read-w.patch
diff options
context:
space:
mode:
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.patch124
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 @@
1From 3e3da899949f18869c6958a30a861d89f2d4b73c Mon Sep 17 00:00:00 2001
2From: Jeff Layton <jlayton@redhat.com>
3Date: Wed, 11 Jul 2012 09:09:36 -0400
4Subject: [PATCH 24/73] cifs: when CONFIG_HIGHMEM is set, serialize the
5 read/write kmaps
6
7commit 3cf003c08be785af4bee9ac05891a15bcbff856a upstream.
8
9Jian found that when he ran fsx on a 32 bit arch with a large wsize the
10process and one of the bdi writeback kthreads would sometimes deadlock
11with a stack trace like this:
12
13crash> bt
14PID: 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
32Each task would kmap part of its address array before getting stuck, but
33not enough to actually issue the write.
34
35This patch fixes this by serializing the marshal_iov operations for
36async reads and writes. The idea here is to ensure that cifs
37aggressively tries to populate a request before attempting to fulfill
38another one. As soon as all of the pages are kmapped for a request, then
39we can unlock and allow another one to proceed.
40
41There's no need to do this serialization on non-CONFIG_HIGHMEM arches
42however, so optimize all of this out when CONFIG_HIGHMEM isn't set.
43
44Reported-by: Jian Li <jiali@redhat.com>
45Signed-off-by: Jeff Layton <jlayton@redhat.com>
46Signed-off-by: Steve French <smfrench@gmail.com>
47[bwh: Backported to 3.2: adjust context]
48Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
49---
50 fs/cifs/cifssmb.c | 30 ++++++++++++++++++++++++++++++
51 1 files changed, 30 insertions(+), 0 deletions(-)
52
53diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
54index 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--
1231.7.7.6
124