[Devel] [PATCH RHEL7 COMMIT] vfs: make guard_bh_eod() more generic
Konstantin Khorenko
khorenko at virtuozzo.com
Mon Oct 24 04:55:38 PDT 2016
The commit is pushed to "branch-rh7-3.10.0-327.36.1.vz7.19.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-327.36.1.vz7.19.3
------>
commit 2573b25398754723ccd709d2411e8e0313ddeaec
Author: Maxim Patlasov <mpatlasov at virtuozzo.com>
Date: Mon Oct 24 15:55:38 2016 +0400
vfs: make guard_bh_eod() more generic
Patchset description:
vfs: avoid attempts to access beyond end of device
The series backports two commits from mainline fixing attempts to read beyond
end of device. This is useful because since we began to use dm-crypt over
ploop, the message "attempt to access beyond end of device" is printed
(to dmesg and /var/log/messages) every time we start encrypted container.
Maxim Patlasov (2):
vfs: make guard_bh_eod() more generic
vfs: guard end of device for mpage interface
==========================================
This patch description:
The patch backports commit 59d43914ed7b96255271ad6b7b735344beffa3c0 from mainline:
vfs: make guard_bh_eod() more generic
This patchset implements readpages() operation for block device by using
mpage_readpages() which can create multipage BIOs instead of BIOs for each
page and reduce system CPU time consumption.
This patch (of 3):
guard_bh_eod() is used in submit_bh() to allow us to do IO even on the odd
last sectors of a device, even if the block size is some multiple of the
physical sector size. This makes guard_bh_eod() more generic and renames
it guard_bio_eod() so that we can use it without struct buffer_head
argument.
The reason for this change is that using mpage_readpages() for block
device requires to add this guard check in mpage code.
Signed-off-by: Akinobu Mita <akinobu.mita at gmail.com>
Cc: Jens Axboe <axboe at kernel.dk>
Cc: Alexander Viro <viro at zeniv.linux.org.uk>
Cc: Jeff Moyer <jmoyer at redhat.com>
Signed-off-by: Andrew Morton <akpm at linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>
Signed-off-by: Maxim Patlasov <mpatlasov at virtuozzo.com>
---
fs/buffer.c | 26 ++++++++++++--------------
1 file changed, 12 insertions(+), 14 deletions(-)
diff --git a/fs/buffer.c b/fs/buffer.c
index 2b709d4..a7cb15c 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -2972,7 +2972,7 @@ static void end_bio_bh_io_sync(struct bio *bio, int err)
/*
* This allows us to do IO even on the odd last sectors
- * of a device, even if the bh block size is some multiple
+ * of a device, even if the block size is some multiple
* of the physical sector size.
*
* We'll just truncate the bio to the size of the device,
@@ -2982,10 +2982,11 @@ static void end_bio_bh_io_sync(struct bio *bio, int err)
* errors, this only handles the "we need to be able to
* do IO at the final sector" case.
*/
-static void guard_bh_eod(int rw, struct bio *bio, struct buffer_head *bh)
+static void guard_bio_eod(int rw, struct bio *bio)
{
sector_t maxsector;
- unsigned bytes;
+ struct bio_vec *bvec = &bio->bi_io_vec[bio->bi_vcnt - 1];
+ unsigned truncated_bytes;
maxsector = i_size_read(bio->bi_bdev->bd_inode) >> 9;
if (!maxsector)
@@ -3000,23 +3001,20 @@ static void guard_bh_eod(int rw, struct bio *bio, struct buffer_head *bh)
return;
maxsector -= bio->bi_sector;
- bytes = bio->bi_size;
- if (likely((bytes >> 9) <= maxsector))
+ if (likely((bio->bi_size >> 9) <= maxsector))
return;
- /* Uhhuh. We've got a bh that straddles the device size! */
- bytes = maxsector << 9;
+ /* Uhhuh. We've got a bio that straddles the device size! */
+ truncated_bytes = bio->bi_size - (maxsector << 9);
/* Truncate the bio.. */
- bio->bi_size = bytes;
- bio->bi_io_vec[0].bv_len = bytes;
+ bio->bi_size -= truncated_bytes;
+ bvec->bv_len -= truncated_bytes;
/* ..and clear the end of the buffer for reads */
if ((rw & RW_MASK) == READ) {
- void *kaddr = kmap_atomic(bh->b_page);
- memset(kaddr + bh_offset(bh) + bytes, 0, bh->b_size - bytes);
- kunmap_atomic(kaddr);
- flush_dcache_page(bh->b_page);
+ zero_user(bvec->bv_page, bvec->bv_offset + bvec->bv_len,
+ truncated_bytes);
}
}
@@ -3057,7 +3055,7 @@ int _submit_bh(int rw, struct buffer_head *bh, unsigned long bio_flags)
bio->bi_flags |= bio_flags;
/* Take care of bh's that straddle the end of the device */
- guard_bh_eod(rw, bio, bh);
+ guard_bio_eod(rw, bio);
if (buffer_meta(bh))
rw |= REQ_META;
More information about the Devel
mailing list