[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