cifs: when CONFIG_HIGHMEM is set, serialize the read/write kmaps
Jian found that when he ran fsx on a 32 bit arch with a large wsize the
process and one of the bdi writeback kthreads would sometimes deadlock
with a stack trace like this:
crash> bt
PID: 2789 TASK:
f02edaa0 CPU: 3 COMMAND: "fsx"
#0 [
eed63cbc] schedule at
c083c5b3
#1 [
eed63d80] kmap_high at
c0500ec8
#2 [
eed63db0] cifs_async_writev at
f7fabcd7 [cifs]
#3 [
eed63df0] cifs_writepages at
f7fb7f5c [cifs]
#4 [
eed63e50] do_writepages at
c04f3e32
#5 [
eed63e54] __filemap_fdatawrite_range at
c04e152a
#6 [
eed63ea4] filemap_fdatawrite at
c04e1b3e
#7 [
eed63eb4] cifs_file_aio_write at
f7fa111a [cifs]
#8 [
eed63ecc] do_sync_write at
c052d202
#9 [
eed63f74] vfs_write at
c052d4ee
#10 [
eed63f94] sys_write at
c052df4c
#11 [
eed63fb0] ia32_sysenter_target at
c0409a98
EAX:
00000004 EBX:
00000003 ECX:
abd73b73 EDX:
012a65c6
DS: 007b ESI:
012a65c6 ES: 007b EDI:
00000000
SS: 007b ESP:
bf8db178 EBP:
bf8db1f8 GS: 0033
CS: 0073 EIP:
40000424 ERR:
00000004 EFLAGS:
00000246
Each task would kmap part of its address array before getting stuck, but
not enough to actually issue the write.
This patch fixes this by serializing the marshal_iov operations for
async reads and writes. The idea here is to ensure that cifs
aggressively tries to populate a request before attempting to fulfill
another one. As soon as all of the pages are kmapped for a request, then
we can unlock and allow another one to proceed.
There's no need to do this serialization on non-CONFIG_HIGHMEM arches
however, so optimize all of this out when CONFIG_HIGHMEM isn't set.
Cc: <stable@vger.kernel.org>
Reported-by: Jian Li <jiali@redhat.com>
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <smfrench@gmail.com>