Messages in this thread | | | Date | Mon, 22 May 2023 11:49:32 +0530 | Subject | Re: [PATCH V1] block: Fix null pointer dereference issue on struct io_cq | From | Pradeep Pragallapati <> |
| |
On 5/18/2023 6:14 PM, Yu Kuai wrote: > Hi, > > 在 2023/05/18 20:16, Yu Kuai 写道: > >> @@ -173,18 +171,17 @@ void ioc_clear_queue(struct request_queue *q) >> { >> LIST_HEAD(icq_list); >> >> + rcu_read_lock(); > > Sorry that I realized this is still not enough, following list_empty() > and list_entry() can still concurrent with list_del(). Please try the > following patch: sure will try and update the results. >> spin_lock_irq(&q->queue_lock); >> list_splice_init(&q->icq_list, &icq_list); >> spin_unlock_irq(&q->queue_lock); >> >> - rcu_read_lock(); >> while (!list_empty(&icq_list)) { >> struct io_cq *icq = >> list_entry(icq_list.next, struct io_cq, >> q_node); >> >> spin_lock_irq(&icq->ioc->lock); >> - if (!(icq->flags & ICQ_DESTROYED)) >> - ioc_destroy_icq(icq); >> + ioc_destroy_icq(icq); >> spin_unlock_irq(&icq->ioc->lock); >> } >> rcu_read_unlock(); >> >> . >> > > diff --git a/block/blk-ioc.c b/block/blk-ioc.c > index 63fc02042408..47684d1e9006 100644 > --- a/block/blk-ioc.c > +++ b/block/blk-ioc.c > @@ -78,6 +78,9 @@ static void ioc_destroy_icq(struct io_cq *icq) > > lockdep_assert_held(&ioc->lock); > > + if (icq->flags & ICQ_DESTROYED) > + return; > + > radix_tree_delete(&ioc->icq_tree, icq->q->id); > hlist_del_init(&icq->ioc_node); > list_del_init(&icq->q_node); > @@ -128,12 +131,7 @@ static void ioc_release_fn(struct work_struct *work) > spin_lock(&q->queue_lock); > spin_lock(&ioc->lock); > > - /* > - * The icq may have been destroyed when the > ioc lock > - * was released. > - */ > - if (!(icq->flags & ICQ_DESTROYED)) > - ioc_destroy_icq(icq); > + ioc_destroy_icq(icq); > > spin_unlock(&q->queue_lock); > rcu_read_unlock(); > @@ -175,19 +173,16 @@ void ioc_clear_queue(struct request_queue *q) > > spin_lock_irq(&q->queue_lock); > list_splice_init(&q->icq_list, &icq_list); > - spin_unlock_irq(&q->queue_lock); > > - rcu_read_lock(); > while (!list_empty(&icq_list)) { > struct io_cq *icq = > list_entry(icq_list.next, struct io_cq, q_node); > > spin_lock_irq(&icq->ioc->lock); > - if (!(icq->flags & ICQ_DESTROYED)) > - ioc_destroy_icq(icq); > + ioc_destroy_icq(icq); > spin_unlock_irq(&icq->ioc->lock); > } > - rcu_read_unlock(); > + spin_unlock_irq(&q->queue_lock); > } > #else /* CONFIG_BLK_ICQ */ > static inline void ioc_exit_icqs(struct io_context *ioc) >
| |