From: Christoph Hellwig > Sent: 21 September 2020 15:22 > > So looking at the various callers I'm not sure this API is the > best. If we want to do something fancy I'd hide the struct iovec > instances entirely with something like: > > struct iov_storage { > struct iovec stack[UIO_FASTIOV], *vec; > } > > int iov_iter_import_iovec(struct iov_iter *iter, struct iov_storage *s, > const struct iovec __user *vec, unsigned long nr_segs, > int type); > > and then add a new helper to free the thing if needed: > > void iov_iter_release_iovec(struct iov_storage *s) > { > if (s->vec != s->stack) > kfree(s->vec); > } I've been looking at this code again now most of the pending changes are in Linus's tree. I was actually looking at going one stage further. The 'iov_iter' is always allocated with the 'iov_storage' *above). Usually both are on the callers stack - possibly in different functions. So add: struct iovec_iter { struct iov_iter iter; struct iovec to_free; struct iovec stack[UIO_FASTIOV]; }; int __iovec_import(struct iovec_iter *, const struct iovec __user *vec, unsigned long nr_segs, int type, bool compat); And a 'clean' function to do kfree(iovec->to_free); This reduces the complexity of most of the callers. I started doing the changes, but got in a mess in io_uring.c (as usual). I think I've got a patch pending (in my brain) to simplify the io_uring code. The plan is to add: if (iter->iov != xxx->to_free) iter->iov = xxx->stack; Prior to every use of the iter. This fixes up anything that got broken by a memcpy() of the fields. The tidyup code is then always kfree(xxx->to_free). David - Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)