Messages in this thread | | | Date | Mon, 26 Apr 2021 17:14:33 +0000 | From | Al Viro <> | Subject | Re: [PATCH] iov_iter: Four fixes for ITER_XARRAY |
| |
On Mon, Apr 26, 2021 at 12:14:50AM +0100, David Howells wrote: > Hi Al, > > I think this patch should include all the fixes necessary. I could merge > it in, but I think it might be better to tag it on the end as an additional > patch.
Looks sane, but I wonder if it would've been better to deal with this
> @@ -791,6 +791,8 @@ size_t _copy_mc_to_iter(const void *addr, size_t bytes, struct iov_iter *i) > curr_addr = (unsigned long) from; > bytes = curr_addr - s_addr - rem; > rcu_read_unlock(); > + i->iov_offset += bytes; > + i->count -= bytes; > return bytes; > } > })
by having your iterator check the return value of X callback and, having decremented .bv_len by return value, broke out of the loop.
__label__ __bugger_off;
xas_for_each(&xas, head, ULONG_MAX) { \ if (xas_retry(&xas, head)) \ continue; \ if (WARN_ON(xa_is_value(head))) \ break; \ if (WARN_ON(PageHuge(head))) \ break; \ for (j = (head->index < index) ? index - head->index : 0; \ j < thp_nr_pages(head); j++) { \ __v.bv_page = head + j; \
size_t left;
offset = (i->xarray_start + skip) & ~PAGE_MASK; \ seg = PAGE_SIZE - offset; \ __v.bv_offset = offset; \ __v.bv_len = min(n, seg); \
left = (STEP); __v.bv_len -= left;
n -= __v.bv_len; \ skip += __v.bv_len; \
if (!n || left) goto __bugger_off;
} \ if (n == 0) \ break; \ } \
__bugger_off:
Then rename iterate_and_advance() to __iterate_and_advance() and have #define iterate_and_advance(....., X) __iterate_and_advance(....., ((void)(X),0)) with iterate_all_kinds() using iterate_xarray(....,((void)(X),0)
Then _copy_mc_to_iter() could use __iterate_and_advance(), getting rid of the need of doing anything special in case of short copy. OTOH, I can do that myself in a followup - not a problem.
| |