]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
fs/fuse: fuse mount can cause panic with no memory numa node
authorSomasundaram Krishnasamy <somasundaram.krishnasamy@oracle.com>
Fri, 4 Aug 2017 02:05:22 +0000 (19:05 -0700)
committerSomasundaram Krishnasamy <somasundaram.krishnasamy@oracle.com>
Tue, 8 Aug 2017 20:26:02 +0000 (13:26 -0700)
Orabug: 26591421

Host panics with the below stack trace:-

[ 2509.835362] BUG: unable to handle kernel paging request at
0000000000001e08
[ 2509.843155] IP: [<ffffffff8119e1a7>]
__alloc_pages_nodemask+0xb7/0xa10
[ 2509.850466] PGD 7f5bbf5067 PUD 7f5c492067 PMD 0
..
..
[ 2510.108923] Call Trace:
[ 2510.111658]  [<ffffffff81022075>] ? native_sched_clock+0x35/0xa0
[ 2510.118360]  [<ffffffff810220e9>] ? sched_clock+0x9/0x10
[ 2510.124291]  [<ffffffff810b9ad5>] ? sched_clock_cpu+0x85/0xc0
[ 2510.130692]  [<ffffffff810b6227>] ? try_to_wake_up+0x47/0x370
[ 2510.137108]  [<ffffffff811f0c43>] ? deactivate_slab+0x383/0x400
[ 2510.143712]  [<ffffffff811f1e37>] new_slab+0xa7/0x460
[ 2510.149350]  [<ffffffff81733cc0>] __slab_alloc+0x317/0x477
[ 2510.155473]  [<ffffffffa0380336>] ? fuse_conn_init+0x236/0x420 [fuse]
[ 2510.162664]  [<ffffffff8146184c>] ? extract_entropy+0x14c/0x330
[ 2510.169260]  [<ffffffff814622b0>] ? get_random_bytes+0x40/0xa0
[ 2510.175769]  [<ffffffff811f2c75>] kmem_cache_alloc_node_trace+0x95/0x2b0
[ 2510.183248]  [<ffffffffa0380336>] fuse_conn_init+0x236/0x420 [fuse]
[ 2510.190241]  [<ffffffffa03808c0>] fuse_fill_super+0x3a0/0x700 [fuse]
[ 2510.197330]  [<ffffffff811f30f6>] ? __kmalloc+0x266/0x2c0
[ 2510.203355]  [<ffffffff811a6dcc>] ? register_shrinker+0x3c/0xa0
[ 2510.209961]  [<ffffffff81216728>] ? sget+0x3b8/0x3f0
[ 2510.215500]  [<ffffffff81215880>] ? get_anon_bdev+0x120/0x120
[ 2510.221911]  [<ffffffffa0380520>] ? fuse_conn_init+0x420/0x420 [fuse]
[ 2510.229096]  [<ffffffff8121686d>] mount_nodev+0x4d/0xb0
[ 2510.234927]  [<ffffffffa037ec38>] fuse_mount+0x18/0x20 [fuse]
[ 2510.241337]  [<ffffffff812173e9>] mount_fs+0x39/0x180
[ 2510.246975]  [<ffffffff8123366b>] vfs_kern_mount+0x6b/0x110
[ 2510.253191]  [<ffffffff81236411>] do_mount+0x251/0xcf0
[ 2510.258922]  [<ffffffff812371f2>] SyS_mount+0xa2/0x110
[ 2510.264653]  [<ffffffff81028666>] ? syscall_trace_leave+0xc6/0x150
[ 2510.271551]  [<ffffffff8173d96e>] 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 <somasundaram.krishnasamy@oracle.com>
Reviewed-by: Ashish Samant<ashish.samant@oracle.com>
Reviewed-by: Babu Moger <babu.moger@oracle.com>
fs/fuse/dev.c
fs/fuse/inode.c

index d41bed1ed2203be2b2b1a2fe0fccf35c9269f8a5..9ae98d4719750944e471a10e41d3ca1c7366d2d9 100644 (file)
@@ -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;
index 1d814cdade1685f6b8c0199a6c8639fc90f714f4..b6b9234e55a2ea158b537286569f2750ff1b026a 100644 (file)
@@ -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);