[PATCH] iov_iter: Four fixes for ITER_XARRAY

Al Viro viro at zeniv.linux.org.uk
Mon Apr 26 18:14:33 BST 2021


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.



More information about the linux-afs mailing list