diff options
author | Brian Behlendorf <[email protected]> | 2012-11-26 16:52:28 -0800 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2012-11-27 13:43:27 -0800 |
commit | 043f9b57247eafb8e28e7b9465470ece87090228 (patch) | |
tree | 02c339bf4afa9748fffc14c9c86617c38ce0dc57 /module/spl/spl-kmem.c | |
parent | e71a4534b340228d2e73bdadacaff570ade5ab6a (diff) |
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 <[email protected]>
Issue zfsonlinux/zfs#1101
Diffstat (limited to 'module/spl/spl-kmem.c')
-rw-r--r-- | module/spl/spl-kmem.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/module/spl/spl-kmem.c b/module/spl/spl-kmem.c index f3113e0f4..b171d446a 100644 --- a/module/spl/spl-kmem.c +++ b/module/spl/spl-kmem.c @@ -1773,7 +1773,7 @@ spl_cache_grow(spl_kmem_cache_t *skc, int flags, void **obj) 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); } |