Skip to content

Commit e33b936

Browse files
leitaoaxboe
authored andcommitted
blk-iocost: Pass gendisk to ioc_refresh_params
Current kernel (d2980d8) crashes when blk_iocost_init for `nvme1` disk. BUG: kernel NULL pointer dereference, address: 0000000000000050 #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page blk_iocost_init (include/asm-generic/qspinlock.h:128 include/linux/spinlock.h:203 include/linux/spinlock_api_smp.h:158 include/linux/spinlock.h:400 block/blk-iocost.c:2884) ioc_qos_write (block/blk-iocost.c:3198) ? kretprobe_perf_func (kernel/trace/trace_kprobe.c:1566) ? kernfs_fop_write_iter (include/linux/slab.h:584 fs/kernfs/file.c:311) ? __kmem_cache_alloc_node (mm/slab.h:? mm/slub.c:3452 mm/slub.c:3491) ? _copy_from_iter (arch/x86/include/asm/uaccess_64.h:46 arch/x86/include/asm/uaccess_64.h:52 lib/iov_iter.c:183 lib/iov_iter.c:628) ? kretprobe_dispatcher (kernel/trace/trace_kprobe.c:1693) cgroup_file_write (kernel/cgroup/cgroup.c:4061) kernfs_fop_write_iter (fs/kernfs/file.c:334) vfs_write (include/linux/fs.h:1849 fs/read_write.c:491 fs/read_write.c:584) ksys_write (fs/read_write.c:637) do_syscall_64 (arch/x86/entry/common.c:50 arch/x86/entry/common.c:80) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:120) This happens because ioc_refresh_params() is being called without a properly initialized ioc->rqos, which is happening later in the callee side. ioc_refresh_params() -> ioc_autop_idx() tries to access ioc->rqos.disk->queue but ioc->rqos.disk is NULL, causing the BUG above. Create function, called ioc_refresh_params_disk(), that is similar to ioc_refresh_params() but where the "struct gendisk" could be passed as an explicit argument. This function will be called when ioc->rqos.disk is not initialized. Fixes: ce57b55 ("blk-rq-qos: make rq_qos_add and rq_qos_del more useful") Signed-off-by: Breno Leitao <[email protected]> Acked-by: Tejun Heo <[email protected]> Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Christoph Hellwig <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent 310726c commit e33b936

File tree

1 file changed

+20
-6
lines changed

1 file changed

+20
-6
lines changed

block/blk-iocost.c

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -800,19 +800,23 @@ static void ioc_refresh_period_us(struct ioc *ioc)
800800
ioc_refresh_margins(ioc);
801801
}
802802

803-
static int ioc_autop_idx(struct ioc *ioc)
803+
/*
804+
* ioc->rqos.disk isn't initialized when this function is called from
805+
* the init path.
806+
*/
807+
static int ioc_autop_idx(struct ioc *ioc, struct gendisk *disk)
804808
{
805809
int idx = ioc->autop_idx;
806810
const struct ioc_params *p = &autop[idx];
807811
u32 vrate_pct;
808812
u64 now_ns;
809813

810814
/* rotational? */
811-
if (!blk_queue_nonrot(ioc->rqos.disk->queue))
815+
if (!blk_queue_nonrot(disk->queue))
812816
return AUTOP_HDD;
813817

814818
/* handle SATA SSDs w/ broken NCQ */
815-
if (blk_queue_depth(ioc->rqos.disk->queue) == 1)
819+
if (blk_queue_depth(disk->queue) == 1)
816820
return AUTOP_SSD_QD1;
817821

818822
/* use one of the normal ssd sets */
@@ -901,14 +905,19 @@ static void ioc_refresh_lcoefs(struct ioc *ioc)
901905
&c[LCOEF_WPAGE], &c[LCOEF_WSEQIO], &c[LCOEF_WRANDIO]);
902906
}
903907

904-
static bool ioc_refresh_params(struct ioc *ioc, bool force)
908+
/*
909+
* struct gendisk is required as an argument because ioc->rqos.disk
910+
* is not properly initialized when called from the init path.
911+
*/
912+
static bool ioc_refresh_params_disk(struct ioc *ioc, bool force,
913+
struct gendisk *disk)
905914
{
906915
const struct ioc_params *p;
907916
int idx;
908917

909918
lockdep_assert_held(&ioc->lock);
910919

911-
idx = ioc_autop_idx(ioc);
920+
idx = ioc_autop_idx(ioc, disk);
912921
p = &autop[idx];
913922

914923
if (idx == ioc->autop_idx && !force)
@@ -939,6 +948,11 @@ static bool ioc_refresh_params(struct ioc *ioc, bool force)
939948
return true;
940949
}
941950

951+
static bool ioc_refresh_params(struct ioc *ioc, bool force)
952+
{
953+
return ioc_refresh_params_disk(ioc, force, ioc->rqos.disk);
954+
}
955+
942956
/*
943957
* When an iocg accumulates too much vtime or gets deactivated, we throw away
944958
* some vtime, which lowers the overall device utilization. As the exact amount
@@ -2880,7 +2894,7 @@ static int blk_iocost_init(struct gendisk *disk)
28802894

28812895
spin_lock_irq(&ioc->lock);
28822896
ioc->autop_idx = AUTOP_INVALID;
2883-
ioc_refresh_params(ioc, true);
2897+
ioc_refresh_params_disk(ioc, true, disk);
28842898
spin_unlock_irq(&ioc->lock);
28852899

28862900
/*

0 commit comments

Comments
 (0)