From 384f1d8dd5f2cac85f8210945ff8489b8aa9cac3 Mon Sep 17 00:00:00 2001 From: Somasundaram Krishnasamy Date: Thu, 3 Aug 2017 19:05:22 -0700 Subject: [PATCH] fs/fuse: fuse mount can cause panic with no memory numa node Orabug: 26591421 Host panics with the below stack trace:- [ 2509.835362] BUG: unable to handle kernel paging request at 0000000000001e08 [ 2509.843155] IP: [] __alloc_pages_nodemask+0xb7/0xa10 [ 2509.850466] PGD 7f5bbf5067 PUD 7f5c492067 PMD 0 .. .. [ 2510.108923] Call Trace: [ 2510.111658] [] ? native_sched_clock+0x35/0xa0 [ 2510.118360] [] ? sched_clock+0x9/0x10 [ 2510.124291] [] ? sched_clock_cpu+0x85/0xc0 [ 2510.130692] [] ? try_to_wake_up+0x47/0x370 [ 2510.137108] [] ? deactivate_slab+0x383/0x400 [ 2510.143712] [] new_slab+0xa7/0x460 [ 2510.149350] [] __slab_alloc+0x317/0x477 [ 2510.155473] [] ? fuse_conn_init+0x236/0x420 [fuse] [ 2510.162664] [] ? extract_entropy+0x14c/0x330 [ 2510.169260] [] ? get_random_bytes+0x40/0xa0 [ 2510.175769] [] kmem_cache_alloc_node_trace+0x95/0x2b0 [ 2510.183248] [] fuse_conn_init+0x236/0x420 [fuse] [ 2510.190241] [] fuse_fill_super+0x3a0/0x700 [fuse] [ 2510.197330] [] ? __kmalloc+0x266/0x2c0 [ 2510.203355] [] ? register_shrinker+0x3c/0xa0 [ 2510.209961] [] ? sget+0x3b8/0x3f0 [ 2510.215500] [] ? get_anon_bdev+0x120/0x120 [ 2510.221911] [] ? fuse_conn_init+0x420/0x420 [fuse] [ 2510.229096] [] mount_nodev+0x4d/0xb0 [ 2510.234927] [] fuse_mount+0x18/0x20 [fuse] [ 2510.241337] [] mount_fs+0x39/0x180 [ 2510.246975] [] vfs_kern_mount+0x6b/0x110 [ 2510.253191] [] do_mount+0x251/0xcf0 [ 2510.258922] [] SyS_mount+0xa2/0x110 [ 2510.264653] [] ? syscall_trace_leave+0xc6/0x150 [ 2510.271551] [] system_call_fastpath+0x12/0x71 This commit reverts the changes done in 937287c2e4ab ("fs/fuse: Fix for correct number of numa nodes") and fixes the original problem by calling kmalloc_node/kmem_cache_alloc_node, only on the online numa nodes. For the offline nodes, kmalloc or kmem_cache_alloc will be used for allocation. This problem happens only with slub allocator because it does not do fallback allocation if node is offline, unlike slab. And for that reason, the same behavior is emulated here. Signed-off-by: Somasundaram Krishnasamy Reviewed-by: Ashish Samant Reviewed-by: Babu Moger --- fs/fuse/dev.c | 13 +++++++++---- fs/fuse/inode.c | 9 ++++++--- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index d41bed1ed220..9ae98d471975 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -71,15 +71,20 @@ static struct fuse_req *__fuse_request_alloc(struct fuse_conn *fc, { struct fuse_req *req; struct fuse_node *fn; + int nid; fn = fuse_get_node(fc); if (fc->affinity == FUSE_CPU) - req = kmem_cache_alloc_node(fuse_req_cachep, GFP_KERNEL, - cpu_to_node(fn->node_id)); + nid = cpu_to_node(fn->node_id); else - req = kmem_cache_alloc_node(fuse_req_cachep, GFP_KERNEL, - fn->node_id); + nid = fn->node_id; + + if (node_online(nid)) + req = kmem_cache_alloc_node(fuse_req_cachep, GFP_KERNEL, nid); + else + req = kmem_cache_alloc(fuse_req_cachep, GFP_KERNEL); + if (req) { struct page **pages; struct fuse_page_desc *page_descs; diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 1d814cdade16..b6b9234e55a2 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -618,10 +618,10 @@ int fuse_conn_init(struct fuse_conn *fc, int affinity) if (affinity == FUSE_CPU) { fc->affinity = FUSE_CPU; - fc->nr_nodes = num_present_cpus(); + fc->nr_nodes = num_possible_cpus(); } else if (affinity == FUSE_NUMA) { fc->affinity = FUSE_NUMA; - fc->nr_nodes = nr_online_nodes; + fc->nr_nodes = nr_node_ids; } else { fc->affinity = FUSE_NONE; fc->nr_nodes = 1; @@ -648,7 +648,10 @@ int fuse_conn_init(struct fuse_conn *fc, int affinity) } else { sz = sizeof(struct fuse_node); for (i = 0; i < fc->nr_nodes; i++) { - fn = kmalloc_node(sz, GFP_KERNEL, i); + if (node_online(i)) + fn = kmalloc_node(sz, GFP_KERNEL, i); + else + fn = kmalloc(sz, GFP_KERNEL); if (!fn) goto out; memset(fn, 0, sz); -- 2.50.1