Skip to content

Commit 099b6cb

Browse files
tonyhutterdarkbasic
authored andcommitted
zvol: Remove broken blk-mq optimization
This fix removes a dubious optimization in zfs_uiomove_bvec_rq() that saved the iterator contents of a rq_for_each_segment(). This optimization allowed restoring the "saved state" from a previous rq_for_each_segment() call on the same uio so that you wouldn't need to iterate though each bvec on every zfs_uiomove_bvec_rq() call. However, if the kernel is manipulating the requests/bios/bvecs under the covers between zfs_uiomove_bvec_rq() calls, then it could result in corruption from using the "saved state". This optimization results in an unbootable system after installing an OS on a zvol with blk-mq enabled. Fixes: openzfs#15351 Signed-off-by: Tony Hutter <[email protected]>
1 parent acdbbb2 commit 099b6cb

File tree

2 files changed

+0
-37
lines changed

2 files changed

+0
-37
lines changed

include/os/linux/spl/sys/uio.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,6 @@ typedef struct zfs_uio {
7373
size_t uio_skip;
7474

7575
struct request *rq;
76-
77-
/*
78-
* Used for saving rq_for_each_segment() state between calls
79-
* to zfs_uiomove_bvec_rq().
80-
*/
81-
struct req_iterator iter;
82-
struct bio_vec bv;
8376
} zfs_uio_t;
8477

8578

@@ -138,7 +131,6 @@ zfs_uio_bvec_init(zfs_uio_t *uio, struct bio *bio, struct request *rq)
138131
} else {
139132
uio->uio_bvec = NULL;
140133
uio->uio_iovcnt = 0;
141-
memset(&uio->iter, 0, sizeof (uio->iter));
142134
}
143135

144136
uio->uio_loffset = io_offset(bio, rq);

module/os/linux/zfs/zfs_uio.c

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -204,22 +204,6 @@ zfs_uiomove_bvec_rq(void *p, size_t n, zfs_uio_rw_t rw, zfs_uio_t *uio)
204204
this_seg_start = orig_loffset;
205205

206206
rq_for_each_segment(bv, rq, iter) {
207-
if (uio->iter.bio) {
208-
/*
209-
* If uio->iter.bio is present, then we know we've saved
210-
* uio->iter from a previous call to this function, and
211-
* we can skip ahead in this rq_for_each_segment() loop
212-
* to where we last left off. That way, we don't need
213-
* to iterate over tons of segments we've already
214-
* processed - we can just restore the "saved state".
215-
*/
216-
iter = uio->iter;
217-
bv = uio->bv;
218-
this_seg_start = uio->uio_loffset;
219-
memset(&uio->iter, 0, sizeof (uio->iter));
220-
continue;
221-
}
222-
223207
/*
224208
* Lookup what the logical offset of the last byte of this
225209
* segment is.
@@ -260,19 +244,6 @@ zfs_uiomove_bvec_rq(void *p, size_t n, zfs_uio_rw_t rw, zfs_uio_t *uio)
260244
copied = 1; /* We copied some data */
261245
}
262246

263-
if (n == 0) {
264-
/*
265-
* All done copying. Save our 'iter' value to the uio.
266-
* This allows us to "save our state" and skip ahead in
267-
* the rq_for_each_segment() loop the next time we call
268-
* call zfs_uiomove_bvec_rq() on this uio (which we
269-
* will be doing for any remaining data in the uio).
270-
*/
271-
uio->iter = iter; /* make a copy of the struct data */
272-
uio->bv = bv;
273-
return (0);
274-
}
275-
276247
this_seg_start = this_seg_end + 1;
277248
}
278249

0 commit comments

Comments
 (0)