Do not assume length of bio segment is never larger than PAGE_SIZE.
With huge pages it's HPAGE_PMD_SIZE (2M on x86-64).

Signed-off-by: Kirill A. Shutemov <kirill.shute...@linux.intel.com>
---
 drivers/block/brd.c | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/drivers/block/brd.c b/drivers/block/brd.c
index 3adc32a3153b..d2f7dc87b545 100644
--- a/drivers/block/brd.c
+++ b/drivers/block/brd.c
@@ -202,12 +202,15 @@ static int copy_to_brd_setup(struct brd_device *brd, 
sector_t sector, size_t n)
        size_t copy;
 
        copy = min_t(size_t, n, PAGE_SIZE - offset);
+       n -= copy;
        if (!brd_insert_page(brd, sector))
                return -ENOSPC;
-       if (copy < n) {
+       while (n) {
                sector += copy >> SECTOR_SHIFT;
                if (!brd_insert_page(brd, sector))
                        return -ENOSPC;
+               copy = min_t(size_t, n, PAGE_SIZE);
+               n -= copy;
        }
        return 0;
 }
@@ -242,6 +245,7 @@ static void copy_to_brd(struct brd_device *brd, const void 
*src,
        size_t copy;
 
        copy = min_t(size_t, n, PAGE_SIZE - offset);
+       n -= copy;
        page = brd_lookup_page(brd, sector);
        BUG_ON(!page);
 
@@ -249,10 +253,11 @@ static void copy_to_brd(struct brd_device *brd, const 
void *src,
        memcpy(dst + offset, src, copy);
        kunmap_atomic(dst);
 
-       if (copy < n) {
+       while (n) {
                src += copy;
                sector += copy >> SECTOR_SHIFT;
-               copy = n - copy;
+               copy = min_t(size_t, n, PAGE_SIZE);
+               n -= copy;
                page = brd_lookup_page(brd, sector);
                BUG_ON(!page);
 
@@ -274,6 +279,7 @@ static void copy_from_brd(void *dst, struct brd_device *brd,
        size_t copy;
 
        copy = min_t(size_t, n, PAGE_SIZE - offset);
+       n -= copy;
        page = brd_lookup_page(brd, sector);
        if (page) {
                src = kmap_atomic(page);
@@ -282,10 +288,11 @@ static void copy_from_brd(void *dst, struct brd_device 
*brd,
        } else
                memset(dst, 0, copy);
 
-       if (copy < n) {
+       while (n) {
                dst += copy;
                sector += copy >> SECTOR_SHIFT;
-               copy = n - copy;
+               copy = min_t(size_t, n, PAGE_SIZE);
+               n -= copy;
                page = brd_lookup_page(brd, sector);
                if (page) {
                        src = kmap_atomic(page);
-- 
2.11.0

Reply via email to