On 15/12/2020 09:37, David Laight wrote: > From: Pavel Begunkov >> Sent: 15 December 2020 00:20 >> >> iov_iter_advance() is heavily used, but implemented through generic >> iteration. As bvecs have a specifically crafted advance() function, i.e. >> bvec_iter_advance(), which is faster and slimmer, use it instead. >> >> lib/iov_iter.c | 19 +++++++++++++++++++ [...] >> void iov_iter_advance(struct iov_iter *i, size_t size) >> { >> if (unlikely(iov_iter_is_pipe(i))) { >> @@ -1077,6 +1092,10 @@ void iov_iter_advance(struct iov_iter *i, size_t size) >> i->count -= size; >> return; >> } >> + if (iov_iter_is_bvec(i)) { >> + iov_iter_bvec_advance(i, size); >> + return; >> + } >> iterate_and_advance(i, size, v, 0, 0, 0) >> } > > This seems to add yet another comparison before what is probably > the common case on an IOVEC (ie normal userspace buffer). If Al finally takes the patch for iov_iter_is_*() helpers it would be completely optimised out. > > Can't the call to bver_iter_advance be dropped into the 'advance' > path for BVEC's inside iterate_and_advance? It iterates by page/segment/etc., why would you want to do bver_iter_advance(i->count) there? > > iterate_and_advance itself has three 'unlikely' conditional tests > that may be mis-predicted taken before the 'likely' path. > One is for DISCARD which is checked twice on the object I just > looked at - the test in iov_iter_advance() is pointless. And again, both second checks, including for discards, would be optimised out by the iov_iter_is_* patch. -- Pavel Begunkov