> > +{ > > + DEFINE_WAIT_FUNC(wait, autoremove_wake_function); > > + > > + prepare_to_wait(&sess->rtrs_waitq, &wait, TASK_UNINTERRUPTIBLE); > > + if (IS_ERR_OR_NULL(sess->rtrs)) { > > + finish_wait(&sess->rtrs_waitq, &wait); > > + return; > > + } > > + mutex_unlock(&sess_lock); > > + /* After unlock session can be freed, so careful */ > > + schedule(); > > + mutex_lock(&sess_lock); > > +} > > How can a function that calls schedule() and that is not surrounded by a > loop be correct? What if e.g. schedule() finishes due to a spurious wakeup? I checked in git history, this no clean explanation why we have to call the mutex_unlock/schedul/mutex_lock magic It's allowed to call schedule inside mutex, seems we can remove the code snip, @Roman Penyaev do you remember why it was introduced? > > > +static struct rnbd_clt_session *__find_and_get_sess(const char *sessname) > > +__releases(&sess_lock) > > +__acquires(&sess_lock) > > +{ > > + struct rnbd_clt_session *sess; > > + int err; > > + > > +again: > > + list_for_each_entry(sess, &sess_list, list) { > > + if (strcmp(sessname, sess->sessname)) > > + continue; > > + > > + if (unlikely(sess->rtrs_ready && IS_ERR_OR_NULL(sess->rtrs))) > > + /* > > + * No RTRS connection, session is dying. > > + */ > > + continue; > > + > > + if (likely(rnbd_clt_get_sess(sess))) { > > + /* > > + * Alive session is found, wait for RTRS connection. > > + */ > > + mutex_unlock(&sess_lock); > > + err = wait_for_rtrs_connection(sess); > > + if (unlikely(err)) > > + rnbd_clt_put_sess(sess); > > + mutex_lock(&sess_lock); > > + > > + if (unlikely(err)) > > + /* Session is dying, repeat the loop */ > > + goto again; > > + > > + return sess; > > + } > > + /* > > + * Ref is 0, session is dying, wait for RTRS disconnect > > + * in order to avoid session names clashes. > > + */ > > + wait_for_rtrs_disconnection(sess); > > + /* > > + * RTRS is disconnected and soon session will be freed, > > + * so repeat a loop. > > + */ > > + goto again; > > + } > > + > > + return NULL; > > +} > > Since wait_for_rtrs_disconnection() unlocks sess_lock, can the > list_for_each_entry() above trigger a use-after-free of sess->next? > > > +static size_t rnbd_clt_get_sg_size(struct scatterlist *sglist, u32 len) > > +{ > > + struct scatterlist *sg; > > + size_t tsize = 0; > > + int i; > > + > > + for_each_sg(sglist, sg, len, i) > > + tsize += sg->length; > > + return tsize; > > +} > > Please follow the example of other block drivers and use blk_rq_bytes() > instead of iterating over the sg-list. The amount of data that belongs to an I/O and the amount of data that should be read or written to the disk (bi_size) can differ. E.g. When WRITE_SAME is used, only a small amount of data is transfered that is then written repeatedly over a lot of sectors. this is why we get the size of data to be transfered via RTRS by summing up the size of the scather-gather list entries. Will add a comment. Thanks