Skip to content

Commit c405a7a

Browse files
khoang98amotin
authored andcommitted
Skip dbuf_evict_one() from dbuf_evict_notify() for reclaim thread
Avoid calling dbuf_evict_one() from memory reclaim contexts (e.g. Linux kswapd, FreeBSD pagedaemon). This prevents deadlock caused by reclaim threads waiting for the dbuf hash lock in the call sequence: dbuf_evict_one -> dbuf_destroy -> arc_buf_destroy Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Alexander Motin <[email protected]> Signed-off-by: Kaitlin Hoang <[email protected]> Closes #17561
1 parent 4808641 commit c405a7a

File tree

6 files changed

+46
-1
lines changed

6 files changed

+46
-1
lines changed

include/os/freebsd/spl/sys/misc.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,9 @@ struct opensolaris_utsname {
5656
#define task_io_account_read(n)
5757
#define task_io_account_write(n)
5858

59+
/*
60+
* Check if the current thread is a memory reclaim thread.
61+
*/
62+
extern int current_is_reclaim_thread(void);
63+
5964
#endif /* _OPENSOLARIS_SYS_MISC_H_ */

include/os/linux/spl/sys/misc.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,13 @@
2424
#define _OS_LINUX_SPL_MISC_H
2525

2626
#include <linux/kobject.h>
27+
#include <linux/swap.h>
2728

2829
extern void spl_signal_kobj_evt(struct block_device *bdev);
2930

31+
/*
32+
* Check if the current thread is a memory reclaim thread.
33+
*/
34+
extern int current_is_reclaim_thread(void);
35+
3036
#endif

include/sys/zfs_context.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,11 @@ typedef pthread_t kthread_t;
236236
#define thread_join(t) pthread_join((pthread_t)(t), NULL)
237237

238238
#define newproc(f, a, cid, pri, ctp, pid) (ENOSYS)
239+
/*
240+
* Check if the current thread is a memory reclaim thread.
241+
* Always returns false in userspace (no memory reclaim thread).
242+
*/
243+
#define current_is_reclaim_thread() (0)
239244

240245
/* in libzpool, p0 exists only to have its address taken */
241246
typedef struct proc {

module/os/freebsd/spl/spl_misc.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,15 @@ spl_panic(const char *file, const char *func, int line, const char *fmt, ...)
101101
va_end(ap);
102102
}
103103

104+
/*
105+
* Check if the current thread is a memory reclaim thread.
106+
* Returns true if curproc is pageproc (FreeBSD's page daemon).
107+
*/
108+
int
109+
current_is_reclaim_thread(void)
110+
{
111+
return (curproc == pageproc);
112+
}
104113

105114
SYSINIT(opensolaris_utsname_init, SI_SUB_TUNABLES, SI_ORDER_ANY,
106115
opensolaris_utsname_init, NULL);

module/os/linux/spl/spl-thread.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <sys/kmem.h>
2929
#include <sys/tsd.h>
3030
#include <sys/string.h>
31+
#include <sys/misc.h>
3132

3233
/*
3334
* Thread interfaces
@@ -197,3 +198,14 @@ issig(void)
197198
}
198199

199200
EXPORT_SYMBOL(issig);
201+
202+
/*
203+
* Check if the current thread is a memory reclaim thread.
204+
* Returns true if current thread is kswapd.
205+
*/
206+
int
207+
current_is_reclaim_thread(void)
208+
{
209+
return (current_is_kswapd());
210+
}
211+
EXPORT_SYMBOL(current_is_reclaim_thread);

module/zfs/dbuf.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -866,8 +866,16 @@ dbuf_evict_notify(uint64_t size)
866866
* and grabbing the lock results in massive lock contention.
867867
*/
868868
if (size > dbuf_cache_target_bytes()) {
869-
if (size > dbuf_cache_hiwater_bytes())
869+
/*
870+
* Avoid calling dbuf_evict_one() from memory reclaim context
871+
* (e.g. Linux kswapd, FreeBSD pagedaemon) to prevent deadlocks.
872+
* Memory reclaim threads can get stuck waiting for the dbuf
873+
* hash lock.
874+
*/
875+
if (size > dbuf_cache_hiwater_bytes() &&
876+
!current_is_reclaim_thread()) {
870877
dbuf_evict_one();
878+
}
871879
cv_signal(&dbuf_evict_cv);
872880
}
873881
}

0 commit comments

Comments
 (0)