libceph: avoid a __vmalloc() deadlock in ceph_kvmalloc()
authorIlya Dryomov <idryomov@gmail.com>
Fri, 30 Aug 2019 18:44:24 +0000 (20:44 +0200)
committerIlya Dryomov <idryomov@gmail.com>
Mon, 16 Sep 2019 10:06:25 +0000 (12:06 +0200)
commit10c12851a022662bf6085bd4384b4ebed4c447ce
tree609a2973a0bbbd33afc073e6a122ddec858efe3f
parent6fd4e634835208ddb331234bfa51d75396a5c42c
libceph: avoid a __vmalloc() deadlock in ceph_kvmalloc()

The vmalloc allocator doesn't fully respect the specified gfp mask:
while the actual pages are allocated as requested, the page table pages
are always allocated with GFP_KERNEL.  ceph_kvmalloc() may be called
with GFP_NOFS and GFP_NOIO (for ceph and rbd respectively), so this may
result in a deadlock.

There is no real reason for the current PAGE_ALLOC_COSTLY_ORDER logic,
it's just something that seemed sensible at the time (ceph_kvmalloc()
predates kvmalloc()).  kvmalloc() is smarter: in an attempt to reduce
long term fragmentation, it first tries to kmalloc non-disruptively.

Switch to kvmalloc() and set the respective PF_MEMALLOC_* flag using
the scope API to avoid the deadlock.  Note that kvmalloc() needs to be
passed GFP_KERNEL to enable the fallback.

Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
net/ceph/ceph_common.c