Disable direct reclaim for z_wr_* threads
The direct reclaim path in the z_wr_* threads must be disabled to ensure forward progress is always maintained for txg processing. This ensures that a txg will never get stuck waiting on itself because it entered the following memory reclaim callpath. ->prune_icache()->dispose_list()->zpl_clear_inode()->zfs_inactive() ->dmu_tx_assign()->dmu_tx_wait()->tgx_wait_open() It would be preferable to target this exact code path but the kernel offers no way to do this without custom patches. To avoid this we are forced to disable all reclaim for these threads. It should not be necessary to do this for other other z_* threads because they will not hold a txg open. Closes #232
This commit is contained in:
parent
3117dd0b90
commit
21ade34764
|
@ -368,6 +368,7 @@ typedef void (task_func_t)(void *);
|
||||||
#define TASKQ_DYNAMIC 0x0004 /* Use dynamic thread scheduling */
|
#define TASKQ_DYNAMIC 0x0004 /* Use dynamic thread scheduling */
|
||||||
#define TASKQ_THREADS_CPU_PCT 0x0008 /* Scale # threads by # cpus */
|
#define TASKQ_THREADS_CPU_PCT 0x0008 /* Scale # threads by # cpus */
|
||||||
#define TASKQ_DC_BATCH 0x0010 /* Mark threads as batch */
|
#define TASKQ_DC_BATCH 0x0010 /* Mark threads as batch */
|
||||||
|
#define TASKQ_NORECLAIM 0x0020 /* Disable direct memory reclaim */
|
||||||
|
|
||||||
#define TQ_SLEEP KM_SLEEP /* Can block for memory */
|
#define TQ_SLEEP KM_SLEEP /* Can block for memory */
|
||||||
#define TQ_NOSLEEP KM_NOSLEEP /* cannot block for memory; may fail */
|
#define TQ_NOSLEEP KM_NOSLEEP /* cannot block for memory; may fail */
|
||||||
|
|
|
@ -614,9 +614,8 @@ spa_get_errlists(spa_t *spa, avl_tree_t *last, avl_tree_t *scrub)
|
||||||
|
|
||||||
static taskq_t *
|
static taskq_t *
|
||||||
spa_taskq_create(spa_t *spa, const char *name, enum zti_modes mode,
|
spa_taskq_create(spa_t *spa, const char *name, enum zti_modes mode,
|
||||||
uint_t value)
|
uint_t value, uint_t flags)
|
||||||
{
|
{
|
||||||
uint_t flags = TASKQ_PREPOPULATE;
|
|
||||||
boolean_t batch = B_FALSE;
|
boolean_t batch = B_FALSE;
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
|
@ -666,13 +665,17 @@ spa_create_zio_taskqs(spa_t *spa)
|
||||||
const zio_taskq_info_t *ztip = &zio_taskqs[t][q];
|
const zio_taskq_info_t *ztip = &zio_taskqs[t][q];
|
||||||
enum zti_modes mode = ztip->zti_mode;
|
enum zti_modes mode = ztip->zti_mode;
|
||||||
uint_t value = ztip->zti_value;
|
uint_t value = ztip->zti_value;
|
||||||
|
uint_t flags = TASKQ_PREPOPULATE;
|
||||||
char name[32];
|
char name[32];
|
||||||
|
|
||||||
|
if (t == ZIO_TYPE_WRITE)
|
||||||
|
flags |= TASKQ_NORECLAIM;
|
||||||
|
|
||||||
(void) snprintf(name, sizeof (name),
|
(void) snprintf(name, sizeof (name),
|
||||||
"%s_%s", zio_type_name[t], zio_taskq_types[q]);
|
"%s_%s", zio_type_name[t], zio_taskq_types[q]);
|
||||||
|
|
||||||
spa->spa_zio_taskq[t][q] =
|
spa->spa_zio_taskq[t][q] =
|
||||||
spa_taskq_create(spa, name, mode, value);
|
spa_taskq_create(spa, name, mode, value, flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue