| From 1d037577c323e5090ce281e96bc313ab2eee5be2 Mon Sep 17 00:00:00 2001 |
| From: Ross Zwisler <ross.zwisler@linux.intel.com> |
| Date: Fri, 9 Mar 2018 08:36:36 -0700 |
| Subject: loop: Fix lost writes caused by missing flag |
| |
| From: Ross Zwisler <ross.zwisler@linux.intel.com> |
| |
| commit 1d037577c323e5090ce281e96bc313ab2eee5be2 upstream. |
| |
| The following commit: |
| |
| commit aa4d86163e4e ("block: loop: switch to VFS ITER_BVEC") |
| |
| replaced __do_lo_send_write(), which used ITER_KVEC iterators, with |
| lo_write_bvec() which uses ITER_BVEC iterators. In this change, though, |
| the WRITE flag was lost: |
| |
| - iov_iter_kvec(&from, ITER_KVEC | WRITE, &kvec, 1, len); |
| + iov_iter_bvec(&i, ITER_BVEC, bvec, 1, bvec->bv_len); |
| |
| This flag is necessary for the DAX case because we make decisions based on |
| whether or not the iterator is a READ or a WRITE in dax_iomap_actor() and |
| in dax_iomap_rw(). |
| |
| We end up going through this path in configurations where we combine a PMEM |
| device with 4k sectors, a loopback device and DAX. The consequence of this |
| missed flag is that what we intend as a write actually turns into a read in |
| the DAX code, so no data is ever written. |
| |
| The very simplest test case is to create a loopback device and try and |
| write a small string to it, then hexdump a few bytes of the device to see |
| if the write took. Without this patch you read back all zeros, with this |
| you read back the string you wrote. |
| |
| For XFS this causes us to fail or panic during the following xfstests: |
| |
| xfs/074 xfs/078 xfs/216 xfs/217 xfs/250 |
| |
| For ext4 we have a similar issue where writes never happen, but we don't |
| currently have any xfstests that use loopback and show this issue. |
| |
| Fix this by restoring the WRITE flag argument to iov_iter_bvec(). This |
| causes the xfstests to all pass. |
| |
| Cc: Al Viro <viro@zeniv.linux.org.uk> |
| Cc: stable@vger.kernel.org |
| Fixes: commit aa4d86163e4e ("block: loop: switch to VFS ITER_BVEC") |
| Reviewed-by: Christoph Hellwig <hch@lst.de> |
| Reviewed-by: Ming Lei <ming.lei@redhat.com> |
| Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com> |
| Signed-off-by: Jens Axboe <axboe@kernel.dk> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/block/loop.c | 2 +- |
| 1 file changed, 1 insertion(+), 1 deletion(-) |
| |
| --- a/drivers/block/loop.c |
| +++ b/drivers/block/loop.c |
| @@ -266,7 +266,7 @@ static int lo_write_bvec(struct file *fi |
| struct iov_iter i; |
| ssize_t bw; |
| |
| - iov_iter_bvec(&i, ITER_BVEC, bvec, 1, bvec->bv_len); |
| + iov_iter_bvec(&i, ITER_BVEC | WRITE, bvec, 1, bvec->bv_len); |
| |
| file_start_write(file); |
| bw = vfs_iter_write(file, &i, ppos, 0); |