summaryrefslogtreecommitdiff
blob: 41b14c55c085a9226170dba4c85d3584c64c70b6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
From 043f9b57247eafb8e28e7b9465470ece87090228 Mon Sep 17 00:00:00 2001
From: Brian Behlendorf <behlendorf1@llnl.gov>
Date: Mon, 26 Nov 2012 16:52:28 -0800
Subject: [PATCH] Disable FS reclaim when allocating new slabs

Allowing the spl_cache_grow_work() function to reclaim inodes
allows for two unlikely deadlocks.  Therefore, we clear __GFP_FS
for these allocations.  The two deadlocks are:

* While holding the ZFS_OBJ_HOLD_ENTER(zsb, obj1) lock a function
  calls kmem_cache_alloc() which happens to need to allocate a
  new slab.  To allocate the new slab we enter FS level reclaim
  and attempt to evict several inodes.  To evict these inodes we
  need to take the ZFS_OBJ_HOLD_ENTER(zsb, obj2) lock and it
  just happens that obj1 and obj2 use the same hashed lock.

* Similar to the first case however instead of getting blocked
  on the hash lock we block in txg_wait_open() which is waiting
  for the next txg which isn't coming because the txg_sync
  thread is blocked in kmem_cache_alloc().

Note this isn't a 100% fix because vmalloc() won't strictly
honor __GFP_FS.  However, it practice this is sufficient because
several very unlikely things must all occur concurrently.

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Issue zfsonlinux/zfs#1101
---
 module/spl/spl-kmem.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/module/spl/spl-kmem.c b/module/spl/spl-kmem.c
index f3113e0..b171d44 100644
--- a/module/spl/spl-kmem.c
+++ b/module/spl/spl-kmem.c
@@ -1773,7 +1773,7 @@ static int spl_cache_flush(spl_kmem_cache_t *skc,
 
 		atomic_inc(&skc->skc_ref);
 		ska->ska_cache = skc;
-		ska->ska_flags = flags;
+		ska->ska_flags = flags & ~__GFP_FS;
 		spl_init_delayed_work(&ska->ska_work, spl_cache_grow_work, ska);
 		schedule_delayed_work(&ska->ska_work, 0);
 	}
-- 
1.7.10