Skip to content

Commit de4f5fe

Browse files
committed
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 <[email protected]>
1 parent 0a2481c commit de4f5fe

File tree

12 files changed

+73
-53
lines changed

12 files changed

+73
-53
lines changed

block/blk-map.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ static struct bio_map_data *bio_alloc_map_data(struct iov_iter *data,
3131
return NULL;
3232
bmd->iter = *data;
3333
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;
3636
}
3737
return bmd;
3838
}

drivers/infiniband/hw/hfi1/file_ops.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,11 +287,12 @@ static ssize_t hfi1_write_iter(struct kiocb *kiocb, struct iov_iter *from)
287287
}
288288

289289
while (dim) {
290+
const struct iovec *iov = iter_iov(from);
290291
int ret;
291292
unsigned long count = 0;
292293

293294
ret = hfi1_user_sdma_process_request(
294-
fd, (struct iovec *)(from->iov + done),
295+
fd, (struct iovec *)(iov + done),
295296
dim, &count);
296297
if (ret) {
297298
reqs = ret;

drivers/infiniband/hw/qib/qib_file_ops.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2248,7 +2248,7 @@ static ssize_t qib_write_iter(struct kiocb *iocb, struct iov_iter *from)
22482248
if (!iter_is_iovec(from) || !from->nr_segs || !pq)
22492249
return -EINVAL;
22502250

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);
22522252
}
22532253

22542254
static struct class *qib_class;

drivers/net/tun.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1486,7 +1486,8 @@ static struct sk_buff *tun_napi_alloc_frags(struct tun_file *tfile,
14861486
skb->truesize += skb->data_len;
14871487

14881488
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;
14901491
struct page *page;
14911492
void *frag;
14921493

drivers/vhost/scsi.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -671,7 +671,7 @@ vhost_scsi_calc_sgls(struct iov_iter *iter, size_t bytes, int max_sgls)
671671
{
672672
int sgl_count = 0;
673673

674-
if (!iter || !iter->iov) {
674+
if (!iter || !iter_iov(iter)) {
675675
pr_err("%s: iter->iov is NULL, but expected bytes: %zu"
676676
" present\n", __func__, bytes);
677677
return -EINVAL;

fs/btrfs/file.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3730,10 +3730,15 @@ static int check_direct_read(struct btrfs_fs_info *fs_info,
37303730
if (!iter_is_iovec(iter))
37313731
return 0;
37323732

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)
37363739
return -EINVAL;
3740+
}
3741+
}
37373742
return 0;
37383743
}
37393744

fs/fuse/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1419,7 +1419,7 @@ static ssize_t fuse_cache_write_iter(struct kiocb *iocb, struct iov_iter *from)
14191419

14201420
static inline unsigned long fuse_get_user_addr(const struct iov_iter *ii)
14211421
{
1422-
return (unsigned long)ii->iov->iov_base + ii->iov_offset;
1422+
return (unsigned long)iter_iov(ii)->iov_base + ii->iov_offset;
14231423
}
14241424

14251425
static inline size_t fuse_get_frag_size(const struct iov_iter *ii,

include/linux/uio.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ struct iov_iter {
5151
};
5252
size_t count;
5353
union {
54-
const struct iovec *iov;
54+
/* use iter_iov() to get the current vec */
55+
const struct iovec *__iov;
5556
const struct kvec *kvec;
5657
const struct bio_vec *bvec;
5758
struct xarray *xarray;
@@ -68,6 +69,8 @@ struct iov_iter {
6869
};
6970
};
7071

72+
#define iter_iov(iter) (iter)->__iov
73+
7174
static inline enum iter_type iov_iter_type(const struct iov_iter *i)
7275
{
7376
return i->iter_type;
@@ -146,9 +149,9 @@ static inline size_t iov_length(const struct iovec *iov, unsigned long nr_segs)
146149
static inline struct iovec iov_iter_iovec(const struct iov_iter *iter)
147150
{
148151
return (struct iovec) {
149-
.iov_base = iter->iov->iov_base + iter->iov_offset,
152+
.iov_base = iter_iov(iter)->iov_base + iter->iov_offset,
150153
.iov_len = min(iter->count,
151-
iter->iov->iov_len - iter->iov_offset),
154+
iter_iov(iter)->iov_len - iter->iov_offset),
152155
};
153156
}
154157

io_uring/net.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,8 @@ static int io_setup_async_msg(struct io_kiocb *req,
184184
async_msg->msg.msg_name = &async_msg->addr;
185185
/* if were using fast_iov, set it to the new one */
186186
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];
189189
}
190190

191191
return -EAGAIN;

io_uring/rw.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -503,10 +503,10 @@ static void io_req_map_rw(struct io_kiocb *req, const struct iovec *iovec,
503503
if (!iovec) {
504504
unsigned iov_off = 0;
505505

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;
510510
}
511511
if (io->s.fast_iov != fast_iov)
512512
memcpy(io->s.fast_iov + iov_off, fast_iov + iov_off,

lib/iov_iter.c

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -126,13 +126,13 @@ __out: \
126126
iterate_buf(i, n, base, len, off, \
127127
i->ubuf, (I)) \
128128
} else if (likely(iter_is_iovec(i))) { \
129-
const struct iovec *iov = i->iov; \
129+
const struct iovec *iov = iter_iov(i); \
130130
void __user *base; \
131131
size_t len; \
132132
iterate_iovec(i, n, base, len, off, \
133133
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; \
136136
} else if (iov_iter_is_bvec(i)) { \
137137
const struct bio_vec *bvec = i->bvec; \
138138
void *base; \
@@ -355,7 +355,7 @@ size_t fault_in_iov_iter_readable(const struct iov_iter *i, size_t size)
355355
size_t skip;
356356

357357
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) {
359359
size_t len = min(count, p->iov_len - skip);
360360
size_t ret;
361361

@@ -398,7 +398,7 @@ size_t fault_in_iov_iter_writeable(const struct iov_iter *i, size_t size)
398398
size_t skip;
399399

400400
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) {
402402
size_t len = min(count, p->iov_len - skip);
403403
size_t ret;
404404

@@ -425,7 +425,7 @@ void iov_iter_init(struct iov_iter *i, unsigned int direction,
425425
.nofault = false,
426426
.user_backed = true,
427427
.data_source = direction,
428-
.iov = iov,
428+
.__iov = iov,
429429
.nr_segs = nr_segs,
430430
.iov_offset = 0,
431431
.count = count
@@ -876,14 +876,14 @@ static void iov_iter_iovec_advance(struct iov_iter *i, size_t size)
876876
i->count -= size;
877877

878878
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++) {
880880
if (likely(size < iov->iov_len))
881881
break;
882882
size -= iov->iov_len;
883883
}
884884
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;
887887
}
888888

889889
void iov_iter_advance(struct iov_iter *i, size_t size)
@@ -958,12 +958,12 @@ void iov_iter_revert(struct iov_iter *i, size_t unroll)
958958
unroll -= n;
959959
}
960960
} else { /* same logics for iovec and kvec */
961-
const struct iovec *iov = i->iov;
961+
const struct iovec *iov = iter_iov(i);
962962
while (1) {
963963
size_t n = (--iov)->iov_len;
964964
i->nr_segs++;
965965
if (unroll <= n) {
966-
i->iov = iov;
966+
i->__iov = iov;
967967
i->iov_offset = n - unroll;
968968
return;
969969
}
@@ -980,7 +980,7 @@ size_t iov_iter_single_seg_count(const struct iov_iter *i)
980980
{
981981
if (i->nr_segs > 1) {
982982
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);
984984
if (iov_iter_is_bvec(i))
985985
return min(i->count, i->bvec->bv_len - i->iov_offset);
986986
}
@@ -1095,13 +1095,14 @@ static bool iov_iter_aligned_iovec(const struct iov_iter *i, unsigned addr_mask,
10951095
unsigned k;
10961096

10971097
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;
10991100

11001101
if (len > size)
11011102
len = size;
11021103
if (len & len_mask)
11031104
return false;
1104-
if ((unsigned long)(i->iov[k].iov_base + skip) & addr_mask)
1105+
if ((unsigned long)(iov->iov_base + skip) & addr_mask)
11051106
return false;
11061107

11071108
size -= len;
@@ -1194,9 +1195,10 @@ static unsigned long iov_iter_alignment_iovec(const struct iov_iter *i)
11941195
unsigned k;
11951196

11961197
for (k = 0; k < i->nr_segs; k++, skip = 0) {
1197-
size_t len = i->iov[k].iov_len - skip;
1198+
const struct iovec *iov = iter_iov(i) + k;
1199+
size_t len = iov->iov_len - skip;
11981200
if (len) {
1199-
res |= (unsigned long)i->iov[k].iov_base + skip;
1201+
res |= (unsigned long)iov->iov_base + skip;
12001202
if (len > size)
12011203
len = size;
12021204
res |= len;
@@ -1273,14 +1275,15 @@ unsigned long iov_iter_gap_alignment(const struct iov_iter *i)
12731275
return ~0U;
12741276

12751277
for (k = 0; k < i->nr_segs; k++) {
1276-
if (i->iov[k].iov_len) {
1277-
unsigned long base = (unsigned long)i->iov[k].iov_base;
1278+
const struct iovec *iov = iter_iov(i) + k;
1279+
if (iov->iov_len) {
1280+
unsigned long base = (unsigned long)iov->iov_base;
12781281
if (v) // if not the first one
12791282
res |= base | v; // this start | previous end
1280-
v = base + i->iov[k].iov_len;
1281-
if (size <= i->iov[k].iov_len)
1283+
v = base + iov->iov_len;
1284+
if (size <= iov->iov_len)
12821285
break;
1283-
size -= i->iov[k].iov_len;
1286+
size -= iov->iov_len;
12841287
}
12851288
}
12861289
return res;
@@ -1396,13 +1399,14 @@ static unsigned long first_iovec_segment(const struct iov_iter *i, size_t *size)
13961399
return (unsigned long)i->ubuf + i->iov_offset;
13971400

13981401
for (k = 0, skip = i->iov_offset; k < i->nr_segs; k++, skip = 0) {
1399-
size_t len = i->iov[k].iov_len - skip;
1402+
const struct iovec *iov = iter_iov(i) + k;
1403+
size_t len = iov->iov_len - skip;
14001404

14011405
if (unlikely(!len))
14021406
continue;
14031407
if (*size > len)
14041408
*size = len;
1405-
return (unsigned long)i->iov[k].iov_base + skip;
1409+
return (unsigned long)iov->iov_base + skip;
14061410
}
14071411
BUG(); // if it had been empty, we wouldn't get called
14081412
}
@@ -1614,7 +1618,7 @@ static int iov_npages(const struct iov_iter *i, int maxpages)
16141618
const struct iovec *p;
16151619
int npages = 0;
16161620

1617-
for (p = i->iov; size; skip = 0, p++) {
1621+
for (p = iter_iov(i); size; skip = 0, p++) {
16181622
unsigned offs = offset_in_page(p->iov_base + skip);
16191623
size_t len = min(p->iov_len - skip, size);
16201624

@@ -1691,7 +1695,7 @@ const void *dup_iter(struct iov_iter *new, struct iov_iter *old, gfp_t flags)
16911695
flags);
16921696
else if (iov_iter_is_kvec(new) || iter_is_iovec(new))
16931697
/* iovec and kvec have identical layout */
1694-
return new->iov = kmemdup(new->iov,
1698+
return new->__iov = kmemdup(new->__iov,
16951699
new->nr_segs * sizeof(struct iovec),
16961700
flags);
16971701
return NULL;
@@ -1918,7 +1922,7 @@ void iov_iter_restore(struct iov_iter *i, struct iov_iter_state *state)
19181922
if (iov_iter_is_bvec(i))
19191923
i->bvec -= state->nr_segs - i->nr_segs;
19201924
else
1921-
i->iov -= state->nr_segs - i->nr_segs;
1925+
i->__iov -= state->nr_segs - i->nr_segs;
19221926
i->nr_segs = state->nr_segs;
19231927
}
19241928

sound/core/pcm_native.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3521,6 +3521,7 @@ static ssize_t snd_pcm_readv(struct kiocb *iocb, struct iov_iter *to)
35213521
unsigned long i;
35223522
void __user **bufs;
35233523
snd_pcm_uframes_t frames;
3524+
const struct iovec *iov = iter_iov(to);
35243525

35253526
pcm_file = iocb->ki_filp->private_data;
35263527
substream = pcm_file->substream;
@@ -3534,14 +3535,16 @@ static ssize_t snd_pcm_readv(struct kiocb *iocb, struct iov_iter *to)
35343535
return -EINVAL;
35353536
if (to->nr_segs > 1024 || to->nr_segs != runtime->channels)
35363537
return -EINVAL;
3537-
if (!frame_aligned(runtime, to->iov->iov_len))
3538+
if (!frame_aligned(runtime, iov->iov_len))
35383539
return -EINVAL;
3539-
frames = bytes_to_samples(runtime, to->iov->iov_len);
3540+
frames = bytes_to_samples(runtime, iov->iov_len);
35403541
bufs = kmalloc_array(to->nr_segs, sizeof(void *), GFP_KERNEL);
35413542
if (bufs == NULL)
35423543
return -ENOMEM;
3543-
for (i = 0; i < to->nr_segs; ++i)
3544-
bufs[i] = to->iov[i].iov_base;
3544+
for (i = 0; i < to->nr_segs; ++i) {
3545+
bufs[i] = iov->iov_base;
3546+
iov++;
3547+
}
35453548
result = snd_pcm_lib_readv(substream, bufs, frames);
35463549
if (result > 0)
35473550
result = frames_to_bytes(runtime, result);
@@ -3558,6 +3561,7 @@ static ssize_t snd_pcm_writev(struct kiocb *iocb, struct iov_iter *from)
35583561
unsigned long i;
35593562
void __user **bufs;
35603563
snd_pcm_uframes_t frames;
3564+
const struct iovec *iov = iter_iov(from);
35613565

35623566
pcm_file = iocb->ki_filp->private_data;
35633567
substream = pcm_file->substream;
@@ -3570,14 +3574,16 @@ static ssize_t snd_pcm_writev(struct kiocb *iocb, struct iov_iter *from)
35703574
if (!iter_is_iovec(from))
35713575
return -EINVAL;
35723576
if (from->nr_segs > 128 || from->nr_segs != runtime->channels ||
3573-
!frame_aligned(runtime, from->iov->iov_len))
3577+
!frame_aligned(runtime, iov->iov_len))
35743578
return -EINVAL;
3575-
frames = bytes_to_samples(runtime, from->iov->iov_len);
3579+
frames = bytes_to_samples(runtime, iov->iov_len);
35763580
bufs = kmalloc_array(from->nr_segs, sizeof(void *), GFP_KERNEL);
35773581
if (bufs == NULL)
35783582
return -ENOMEM;
3579-
for (i = 0; i < from->nr_segs; ++i)
3580-
bufs[i] = from->iov[i].iov_base;
3583+
for (i = 0; i < from->nr_segs; ++i) {
3584+
bufs[i] = iov->iov_base;
3585+
iov++;
3586+
}
35813587
result = snd_pcm_lib_writev(substream, bufs, frames);
35823588
if (result > 0)
35833589
result = frames_to_bytes(runtime, result);

0 commit comments

Comments
 (0)