aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/cifssmb.c30
1 files changed, 29 insertions, 1 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 5b400730c213..4ee522b3f66f 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -86,7 +86,31 @@ static struct {
86#endif /* CONFIG_CIFS_WEAK_PW_HASH */ 86#endif /* CONFIG_CIFS_WEAK_PW_HASH */
87#endif /* CIFS_POSIX */ 87#endif /* CIFS_POSIX */
88 88
89/* Forward declarations */ 89#ifdef CONFIG_HIGHMEM
90/*
91 * On arches that have high memory, kmap address space is limited. By
92 * serializing the kmap operations on those arches, we ensure that we don't
93 * end up with a bunch of threads in writeback with partially mapped page
94 * arrays, stuck waiting for kmap to come back. That situation prevents
95 * progress and can deadlock.
96 */
97static DEFINE_MUTEX(cifs_kmap_mutex);
98
99static inline void
100cifs_kmap_lock(void)
101{
102 mutex_lock(&cifs_kmap_mutex);
103}
104
105static inline void
106cifs_kmap_unlock(void)
107{
108 mutex_unlock(&cifs_kmap_mutex);
109}
110#else /* !CONFIG_HIGHMEM */
111#define cifs_kmap_lock() do { ; } while(0)
112#define cifs_kmap_unlock() do { ; } while(0)
113#endif /* CONFIG_HIGHMEM */
90 114
91/* Mark as invalid, all open files on tree connections since they 115/* Mark as invalid, all open files on tree connections since they
92 were closed when session to server was lost */ 116 were closed when session to server was lost */
@@ -1503,7 +1527,9 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1503 } 1527 }
1504 1528
1505 /* marshal up the page array */ 1529 /* marshal up the page array */
1530 cifs_kmap_lock();
1506 len = rdata->marshal_iov(rdata, data_len); 1531 len = rdata->marshal_iov(rdata, data_len);
1532 cifs_kmap_unlock();
1507 data_len -= len; 1533 data_len -= len;
1508 1534
1509 /* issue the read if we have any iovecs left to fill */ 1535 /* issue the read if we have any iovecs left to fill */
@@ -2069,7 +2095,9 @@ cifs_async_writev(struct cifs_writedata *wdata)
2069 * and set the iov_len properly for each one. It may also set 2095 * and set the iov_len properly for each one. It may also set
2070 * wdata->bytes too. 2096 * wdata->bytes too.
2071 */ 2097 */
2098 cifs_kmap_lock();
2072 wdata->marshal_iov(iov, wdata); 2099 wdata->marshal_iov(iov, wdata);
2100 cifs_kmap_unlock();
2073 2101
2074 cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes); 2102 cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
2075 2103