mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-12-25 18:59:33 +03:00
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. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Tony Hutter <hutter2@llnl.gov> Closes #15351
This commit is contained in:
parent
252f46be7d
commit
7c9b6fed16
@ -73,13 +73,6 @@ typedef struct zfs_uio {
|
||||
size_t uio_skip;
|
||||
|
||||
struct request *rq;
|
||||
|
||||
/*
|
||||
* Used for saving rq_for_each_segment() state between calls
|
||||
* to zfs_uiomove_bvec_rq().
|
||||
*/
|
||||
struct req_iterator iter;
|
||||
struct bio_vec bv;
|
||||
} zfs_uio_t;
|
||||
|
||||
|
||||
@ -138,7 +131,6 @@ zfs_uio_bvec_init(zfs_uio_t *uio, struct bio *bio, struct request *rq)
|
||||
} else {
|
||||
uio->uio_bvec = NULL;
|
||||
uio->uio_iovcnt = 0;
|
||||
memset(&uio->iter, 0, sizeof (uio->iter));
|
||||
}
|
||||
|
||||
uio->uio_loffset = io_offset(bio, rq);
|
||||
|
@ -204,22 +204,6 @@ zfs_uiomove_bvec_rq(void *p, size_t n, zfs_uio_rw_t rw, zfs_uio_t *uio)
|
||||
this_seg_start = orig_loffset;
|
||||
|
||||
rq_for_each_segment(bv, rq, iter) {
|
||||
if (uio->iter.bio) {
|
||||
/*
|
||||
* If uio->iter.bio is present, then we know we've saved
|
||||
* uio->iter from a previous call to this function, and
|
||||
* we can skip ahead in this rq_for_each_segment() loop
|
||||
* to where we last left off. That way, we don't need
|
||||
* to iterate over tons of segments we've already
|
||||
* processed - we can just restore the "saved state".
|
||||
*/
|
||||
iter = uio->iter;
|
||||
bv = uio->bv;
|
||||
this_seg_start = uio->uio_loffset;
|
||||
memset(&uio->iter, 0, sizeof (uio->iter));
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Lookup what the logical offset of the last byte of this
|
||||
* segment is.
|
||||
@ -260,19 +244,6 @@ zfs_uiomove_bvec_rq(void *p, size_t n, zfs_uio_rw_t rw, zfs_uio_t *uio)
|
||||
copied = 1; /* We copied some data */
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
/*
|
||||
* All done copying. Save our 'iter' value to the uio.
|
||||
* This allows us to "save our state" and skip ahead in
|
||||
* the rq_for_each_segment() loop the next time we call
|
||||
* call zfs_uiomove_bvec_rq() on this uio (which we
|
||||
* will be doing for any remaining data in the uio).
|
||||
*/
|
||||
uio->iter = iter; /* make a copy of the struct data */
|
||||
uio->bv = bv;
|
||||
return (0);
|
||||
}
|
||||
|
||||
this_seg_start = this_seg_end + 1;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user