Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iov_iter: add iter_iovec() helper

This returns a pointer to the current iovec entry in the iterator. Only
useful with ITER_IOVEC right now, but it prepares us to treat ITER_UBUF
and ITER_IOVEC identically for the first segment.

Rename struct iov_iter->iov to iov_iter->__iov to find any potentially
troublesome spots, and also to prevent anyone from adding new code that
accesses iter->iov directly.

Signed-off-by: Jens Axboe <axboe@kernel.dk>

+73 -53
+2 -2
block/blk-map.c
··· 31 31 return NULL; 32 32 bmd->iter = *data; 33 33 if (iter_is_iovec(data)) { 34 - memcpy(bmd->iov, data->iov, sizeof(struct iovec) * data->nr_segs); 35 - bmd->iter.iov = bmd->iov; 34 + memcpy(bmd->iov, iter_iov(data), sizeof(struct iovec) * data->nr_segs); 35 + bmd->iter.__iov = bmd->iov; 36 36 } 37 37 return bmd; 38 38 }
+2 -1
drivers/infiniband/hw/hfi1/file_ops.c
··· 287 287 } 288 288 289 289 while (dim) { 290 + const struct iovec *iov = iter_iov(from); 290 291 int ret; 291 292 unsigned long count = 0; 292 293 293 294 ret = hfi1_user_sdma_process_request( 294 - fd, (struct iovec *)(from->iov + done), 295 + fd, (struct iovec *)(iov + done), 295 296 dim, &count); 296 297 if (ret) { 297 298 reqs = ret;
+1 -1
drivers/infiniband/hw/qib/qib_file_ops.c
··· 2248 2248 if (!iter_is_iovec(from) || !from->nr_segs || !pq) 2249 2249 return -EINVAL; 2250 2250 2251 - return qib_user_sdma_writev(rcd, pq, from->iov, from->nr_segs); 2251 + return qib_user_sdma_writev(rcd, pq, iter_iov(from), from->nr_segs); 2252 2252 } 2253 2253 2254 2254 static struct class *qib_class;
+2 -1
drivers/net/tun.c
··· 1486 1486 skb->truesize += skb->data_len; 1487 1487 1488 1488 for (i = 1; i < it->nr_segs; i++) { 1489 - size_t fragsz = it->iov[i].iov_len; 1489 + const struct iovec *iov = iter_iov(it); 1490 + size_t fragsz = iov->iov_len; 1490 1491 struct page *page; 1491 1492 void *frag; 1492 1493
+1 -1
drivers/vhost/scsi.c
··· 671 671 { 672 672 int sgl_count = 0; 673 673 674 - if (!iter || !iter->iov) { 674 + if (!iter || !iter_iov(iter)) { 675 675 pr_err("%s: iter->iov is NULL, but expected bytes: %zu" 676 676 " present\n", __func__, bytes); 677 677 return -EINVAL;
+8 -3
fs/btrfs/file.c
··· 3730 3730 if (!iter_is_iovec(iter)) 3731 3731 return 0; 3732 3732 3733 - for (seg = 0; seg < iter->nr_segs; seg++) 3734 - for (i = seg + 1; i < iter->nr_segs; i++) 3735 - if (iter->iov[seg].iov_base == iter->iov[i].iov_base) 3733 + for (seg = 0; seg < iter->nr_segs; seg++) { 3734 + for (i = seg + 1; i < iter->nr_segs; i++) { 3735 + const struct iovec *iov1 = iter_iov(iter) + seg; 3736 + const struct iovec *iov2 = iter_iov(iter) + i; 3737 + 3738 + if (iov1->iov_base == iov2->iov_base) 3736 3739 return -EINVAL; 3740 + } 3741 + } 3737 3742 return 0; 3738 3743 } 3739 3744
+1 -1
fs/fuse/file.c
··· 1419 1419 1420 1420 static inline unsigned long fuse_get_user_addr(const struct iov_iter *ii) 1421 1421 { 1422 - return (unsigned long)ii->iov->iov_base + ii->iov_offset; 1422 + return (unsigned long)iter_iov(ii)->iov_base + ii->iov_offset; 1423 1423 } 1424 1424 1425 1425 static inline size_t fuse_get_frag_size(const struct iov_iter *ii,
+6 -3
include/linux/uio.h
··· 51 51 }; 52 52 size_t count; 53 53 union { 54 - const struct iovec *iov; 54 + /* use iter_iov() to get the current vec */ 55 + const struct iovec *__iov; 55 56 const struct kvec *kvec; 56 57 const struct bio_vec *bvec; 57 58 struct xarray *xarray; ··· 68 67 loff_t xarray_start; 69 68 }; 70 69 }; 70 + 71 + #define iter_iov(iter) (iter)->__iov 71 72 72 73 static inline enum iter_type iov_iter_type(const struct iov_iter *i) 73 74 { ··· 149 146 static inline struct iovec iov_iter_iovec(const struct iov_iter *iter) 150 147 { 151 148 return (struct iovec) { 152 - .iov_base = iter->iov->iov_base + iter->iov_offset, 149 + .iov_base = iter_iov(iter)->iov_base + iter->iov_offset, 153 150 .iov_len = min(iter->count, 154 - iter->iov->iov_len - iter->iov_offset), 151 + iter_iov(iter)->iov_len - iter->iov_offset), 155 152 }; 156 153 } 157 154
+2 -2
io_uring/net.c
··· 184 184 async_msg->msg.msg_name = &async_msg->addr; 185 185 /* if were using fast_iov, set it to the new one */ 186 186 if (iter_is_iovec(&kmsg->msg.msg_iter) && !kmsg->free_iov) { 187 - size_t fast_idx = kmsg->msg.msg_iter.iov - kmsg->fast_iov; 188 - async_msg->msg.msg_iter.iov = &async_msg->fast_iov[fast_idx]; 187 + size_t fast_idx = iter_iov(&kmsg->msg.msg_iter) - kmsg->fast_iov; 188 + async_msg->msg.msg_iter.__iov = &async_msg->fast_iov[fast_idx]; 189 189 } 190 190 191 191 return -EAGAIN;
+4 -4
io_uring/rw.c
··· 503 503 if (!iovec) { 504 504 unsigned iov_off = 0; 505 505 506 - io->s.iter.iov = io->s.fast_iov; 507 - if (iter->iov != fast_iov) { 508 - iov_off = iter->iov - fast_iov; 509 - io->s.iter.iov += iov_off; 506 + io->s.iter.__iov = io->s.fast_iov; 507 + if (iter->__iov != fast_iov) { 508 + iov_off = iter_iov(iter) - fast_iov; 509 + io->s.iter.__iov += iov_off; 510 510 } 511 511 if (io->s.fast_iov != fast_iov) 512 512 memcpy(io->s.fast_iov + iov_off, fast_iov + iov_off,
+30 -26
lib/iov_iter.c
··· 126 126 iterate_buf(i, n, base, len, off, \ 127 127 i->ubuf, (I)) \ 128 128 } else if (likely(iter_is_iovec(i))) { \ 129 - const struct iovec *iov = i->iov; \ 129 + const struct iovec *iov = iter_iov(i); \ 130 130 void __user *base; \ 131 131 size_t len; \ 132 132 iterate_iovec(i, n, base, len, off, \ 133 133 iov, (I)) \ 134 - i->nr_segs -= iov - i->iov; \ 135 - i->iov = iov; \ 134 + i->nr_segs -= iov - iter_iov(i); \ 135 + i->__iov = iov; \ 136 136 } else if (iov_iter_is_bvec(i)) { \ 137 137 const struct bio_vec *bvec = i->bvec; \ 138 138 void *base; \ ··· 355 355 size_t skip; 356 356 357 357 size -= count; 358 - for (p = i->iov, skip = i->iov_offset; count; p++, skip = 0) { 358 + for (p = iter_iov(i), skip = i->iov_offset; count; p++, skip = 0) { 359 359 size_t len = min(count, p->iov_len - skip); 360 360 size_t ret; 361 361 ··· 398 398 size_t skip; 399 399 400 400 size -= count; 401 - for (p = i->iov, skip = i->iov_offset; count; p++, skip = 0) { 401 + for (p = iter_iov(i), skip = i->iov_offset; count; p++, skip = 0) { 402 402 size_t len = min(count, p->iov_len - skip); 403 403 size_t ret; 404 404 ··· 425 425 .nofault = false, 426 426 .user_backed = true, 427 427 .data_source = direction, 428 - .iov = iov, 428 + .__iov = iov, 429 429 .nr_segs = nr_segs, 430 430 .iov_offset = 0, 431 431 .count = count ··· 876 876 i->count -= size; 877 877 878 878 size += i->iov_offset; // from beginning of current segment 879 - for (iov = i->iov, end = iov + i->nr_segs; iov < end; iov++) { 879 + for (iov = iter_iov(i), end = iov + i->nr_segs; iov < end; iov++) { 880 880 if (likely(size < iov->iov_len)) 881 881 break; 882 882 size -= iov->iov_len; 883 883 } 884 884 i->iov_offset = size; 885 - i->nr_segs -= iov - i->iov; 886 - i->iov = iov; 885 + i->nr_segs -= iov - iter_iov(i); 886 + i->__iov = iov; 887 887 } 888 888 889 889 void iov_iter_advance(struct iov_iter *i, size_t size) ··· 958 958 unroll -= n; 959 959 } 960 960 } else { /* same logics for iovec and kvec */ 961 - const struct iovec *iov = i->iov; 961 + const struct iovec *iov = iter_iov(i); 962 962 while (1) { 963 963 size_t n = (--iov)->iov_len; 964 964 i->nr_segs++; 965 965 if (unroll <= n) { 966 - i->iov = iov; 966 + i->__iov = iov; 967 967 i->iov_offset = n - unroll; 968 968 return; 969 969 } ··· 980 980 { 981 981 if (i->nr_segs > 1) { 982 982 if (likely(iter_is_iovec(i) || iov_iter_is_kvec(i))) 983 - return min(i->count, i->iov->iov_len - i->iov_offset); 983 + return min(i->count, iter_iov(i)->iov_len - i->iov_offset); 984 984 if (iov_iter_is_bvec(i)) 985 985 return min(i->count, i->bvec->bv_len - i->iov_offset); 986 986 } ··· 1095 1095 unsigned k; 1096 1096 1097 1097 for (k = 0; k < i->nr_segs; k++, skip = 0) { 1098 - size_t len = i->iov[k].iov_len - skip; 1098 + const struct iovec *iov = iter_iov(i) + k; 1099 + size_t len = iov->iov_len - skip; 1099 1100 1100 1101 if (len > size) 1101 1102 len = size; 1102 1103 if (len & len_mask) 1103 1104 return false; 1104 - if ((unsigned long)(i->iov[k].iov_base + skip) & addr_mask) 1105 + if ((unsigned long)(iov->iov_base + skip) & addr_mask) 1105 1106 return false; 1106 1107 1107 1108 size -= len; ··· 1195 1194 unsigned k; 1196 1195 1197 1196 for (k = 0; k < i->nr_segs; k++, skip = 0) { 1198 - size_t len = i->iov[k].iov_len - skip; 1197 + const struct iovec *iov = iter_iov(i) + k; 1198 + size_t len = iov->iov_len - skip; 1199 1199 if (len) { 1200 - res |= (unsigned long)i->iov[k].iov_base + skip; 1200 + res |= (unsigned long)iov->iov_base + skip; 1201 1201 if (len > size) 1202 1202 len = size; 1203 1203 res |= len; ··· 1275 1273 return ~0U; 1276 1274 1277 1275 for (k = 0; k < i->nr_segs; k++) { 1278 - if (i->iov[k].iov_len) { 1279 - unsigned long base = (unsigned long)i->iov[k].iov_base; 1276 + const struct iovec *iov = iter_iov(i) + k; 1277 + if (iov->iov_len) { 1278 + unsigned long base = (unsigned long)iov->iov_base; 1280 1279 if (v) // if not the first one 1281 1280 res |= base | v; // this start | previous end 1282 - v = base + i->iov[k].iov_len; 1283 - if (size <= i->iov[k].iov_len) 1281 + v = base + iov->iov_len; 1282 + if (size <= iov->iov_len) 1284 1283 break; 1285 - size -= i->iov[k].iov_len; 1284 + size -= iov->iov_len; 1286 1285 } 1287 1286 } 1288 1287 return res; ··· 1399 1396 return (unsigned long)i->ubuf + i->iov_offset; 1400 1397 1401 1398 for (k = 0, skip = i->iov_offset; k < i->nr_segs; k++, skip = 0) { 1402 - size_t len = i->iov[k].iov_len - skip; 1399 + const struct iovec *iov = iter_iov(i) + k; 1400 + size_t len = iov->iov_len - skip; 1403 1401 1404 1402 if (unlikely(!len)) 1405 1403 continue; 1406 1404 if (*size > len) 1407 1405 *size = len; 1408 - return (unsigned long)i->iov[k].iov_base + skip; 1406 + return (unsigned long)iov->iov_base + skip; 1409 1407 } 1410 1408 BUG(); // if it had been empty, we wouldn't get called 1411 1409 } ··· 1618 1614 const struct iovec *p; 1619 1615 int npages = 0; 1620 1616 1621 - for (p = i->iov; size; skip = 0, p++) { 1617 + for (p = iter_iov(i); size; skip = 0, p++) { 1622 1618 unsigned offs = offset_in_page(p->iov_base + skip); 1623 1619 size_t len = min(p->iov_len - skip, size); 1624 1620 ··· 1695 1691 flags); 1696 1692 else if (iov_iter_is_kvec(new) || iter_is_iovec(new)) 1697 1693 /* iovec and kvec have identical layout */ 1698 - return new->iov = kmemdup(new->iov, 1694 + return new->__iov = kmemdup(new->__iov, 1699 1695 new->nr_segs * sizeof(struct iovec), 1700 1696 flags); 1701 1697 return NULL; ··· 1922 1918 if (iov_iter_is_bvec(i)) 1923 1919 i->bvec -= state->nr_segs - i->nr_segs; 1924 1920 else 1925 - i->iov -= state->nr_segs - i->nr_segs; 1921 + i->__iov -= state->nr_segs - i->nr_segs; 1926 1922 i->nr_segs = state->nr_segs; 1927 1923 } 1928 1924
+14 -8
sound/core/pcm_native.c
··· 3521 3521 unsigned long i; 3522 3522 void __user **bufs; 3523 3523 snd_pcm_uframes_t frames; 3524 + const struct iovec *iov = iter_iov(to); 3524 3525 3525 3526 pcm_file = iocb->ki_filp->private_data; 3526 3527 substream = pcm_file->substream; ··· 3535 3534 return -EINVAL; 3536 3535 if (to->nr_segs > 1024 || to->nr_segs != runtime->channels) 3537 3536 return -EINVAL; 3538 - if (!frame_aligned(runtime, to->iov->iov_len)) 3537 + if (!frame_aligned(runtime, iov->iov_len)) 3539 3538 return -EINVAL; 3540 - frames = bytes_to_samples(runtime, to->iov->iov_len); 3539 + frames = bytes_to_samples(runtime, iov->iov_len); 3541 3540 bufs = kmalloc_array(to->nr_segs, sizeof(void *), GFP_KERNEL); 3542 3541 if (bufs == NULL) 3543 3542 return -ENOMEM; 3544 - for (i = 0; i < to->nr_segs; ++i) 3545 - bufs[i] = to->iov[i].iov_base; 3543 + for (i = 0; i < to->nr_segs; ++i) { 3544 + bufs[i] = iov->iov_base; 3545 + iov++; 3546 + } 3546 3547 result = snd_pcm_lib_readv(substream, bufs, frames); 3547 3548 if (result > 0) 3548 3549 result = frames_to_bytes(runtime, result); ··· 3561 3558 unsigned long i; 3562 3559 void __user **bufs; 3563 3560 snd_pcm_uframes_t frames; 3561 + const struct iovec *iov = iter_iov(from); 3564 3562 3565 3563 pcm_file = iocb->ki_filp->private_data; 3566 3564 substream = pcm_file->substream; ··· 3574 3570 if (!iter_is_iovec(from)) 3575 3571 return -EINVAL; 3576 3572 if (from->nr_segs > 128 || from->nr_segs != runtime->channels || 3577 - !frame_aligned(runtime, from->iov->iov_len)) 3573 + !frame_aligned(runtime, iov->iov_len)) 3578 3574 return -EINVAL; 3579 - frames = bytes_to_samples(runtime, from->iov->iov_len); 3575 + frames = bytes_to_samples(runtime, iov->iov_len); 3580 3576 bufs = kmalloc_array(from->nr_segs, sizeof(void *), GFP_KERNEL); 3581 3577 if (bufs == NULL) 3582 3578 return -ENOMEM; 3583 - for (i = 0; i < from->nr_segs; ++i) 3584 - bufs[i] = from->iov[i].iov_base; 3579 + for (i = 0; i < from->nr_segs; ++i) { 3580 + bufs[i] = iov->iov_base; 3581 + iov++; 3582 + } 3585 3583 result = snd_pcm_lib_writev(substream, bufs, frames); 3586 3584 if (result > 0) 3587 3585 result = frames_to_bytes(runtime, result);