On Thu, Mar 06, 2025 at 11:03:22AM +0800, Herbert Xu wrote: > +void memcpy_sglist(struct scatterlist *dst, struct scatterlist *src, > + unsigned int nbytes) > +{ > + struct scatter_walk swalk; > + struct scatter_walk dwalk; > + > + if (unlikely(nbytes == 0)) /* in case sg == NULL */ > + return; > + > + scatterwalk_start(&swalk, src); > + scatterwalk_start(&dwalk, dst); > + > + do { > + unsigned int slen, dlen; > + unsigned int len; > + > + slen = scatterwalk_next(&swalk, nbytes); > + dlen = scatterwalk_next(&dwalk, nbytes); > + len = min(slen, dlen); > + memcpy(dwalk.addr, swalk.addr, len); > + scatterwalk_done_src(&swalk, len); > + scatterwalk_done_dst(&dwalk, len); > + nbytes -= len; > + } while (nbytes); > +} > +EXPORT_SYMBOL_GPL(memcpy_sglist); Local kmaps must be released in reverse order of the mapping, so scatterwalk_done_dst() must be done before scatterwalk_done_src() above. - Eric