On Tue, Jan 21, 2025 at 4:18 PM Bernd Schubert <bernd@xxxxxxxxxxx> wrote: > ... > >> > >>> > >>>> + > >>>> + err = fuse_ring_ent_set_commit(ring_ent); > >>>> + if (err != 0) { > >>>> + pr_info_ratelimited("qid=%d commit_id %llu state %d", > >>>> + queue->qid, commit_id, ring_ent->state); > >>>> + spin_unlock(&queue->lock); > >>>> + return err; > >>>> + } > >>>> + > >>>> + ring_ent->cmd = cmd; > >>>> + spin_unlock(&queue->lock); > >>>> + > >>>> + /* without the queue lock, as other locks are taken */ > >>>> + fuse_uring_commit(ring_ent, issue_flags); > >>>> + > >>>> + /* > >>>> + * Fetching the next request is absolutely required as queued > >>>> + * fuse requests would otherwise not get processed - committing > >>>> + * and fetching is done in one step vs legacy fuse, which has separated > >>>> + * read (fetch request) and write (commit result). > >>>> + */ > >>>> + fuse_uring_next_fuse_req(ring_ent, queue, issue_flags); > >>> > >>> If there's no request ready to read next, then no request will be > >>> fetched and this will return. However, as I understand it, once the > >>> uring is registered, userspace should only be interacting with the > >>> uring via FUSE_IO_URING_CMD_COMMIT_AND_FETCH. However for the case > >>> where no request was ready to read, it seems like userspace would have > >>> nothing to commit when it wants to fetch the next request? > >> > >> We have > >> > >> FUSE_IO_URING_CMD_REGISTER > >> FUSE_IO_URING_CMD_COMMIT_AND_FETCH > >> > >> > >> After _CMD_REGISTER the corresponding ring-entry is ready to get fuse > >> requests and waiting. After it gets a request assigned and handles it > >> by fuse server the _COMMIT_AND_FETCH scheme applies. Did you possibly > >> miss that _CMD_REGISTER will already have it waiting? > >> > > > > Sorry for the late reply. After _CMD_REGISTER and _COMMIT_AND_FETCH, > > it seems possible that there is no fuse request waiting until a later > > time? This is the scenario I'm envisioning: > > a) uring registers successfully and fetches request through _CMD_REGISTER > > b) server replies to request and fetches new request through _COMMIT_AND_FETCH > > c) server replies to request, tries to fetch new request but no > > request is ready, through _COMMIT_AND_FETCH > > > > maybe I'm missing something in my reading of the code, but how will > > the server then fetch the next request once the request is ready? It > > will have to commit something in order to fetch it since there's only > > _COMMIT_AND_FETCH which requires a commit, no? > > > > The right name would be '_COMMIT_AND_FETCH_OR_WAIT'. Please see > fuse_uring_next_fuse_req(). > > retry: > spin_lock(&queue->lock); > fuse_uring_ent_avail(ent, queue); --> entry available > has_next = fuse_uring_ent_assign_req(ent); > spin_unlock(&queue->lock); > > if (has_next) { > err = fuse_uring_send_next_to_ring(ent, issue_flags); > if (err) > goto retry; > } > > > If there is no available request, the io-uring cmd stored in ent->cmd is > just queued/available. Could you point me to where the wait happens? I think that's the part I'm missing. In my reading of the code, if there's no available request (eg queue->fuse_req_queue is empty), then I see that has_next will return false and fuse_uring_next_fuse_req() / fuse_uring_commit_fetch() returns without having fetched anything. Where does the "if there is no available request, the io-uring cmd is just queued/available" happen? > > Btw, Miklos added it to linux-next. > Awesome, can't wait to use it. Thanks, Joanne > > Cheers, > Bernd >