diff options
author | kib <kib@FreeBSD.org> | 2013-05-24 09:48:42 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2013-05-24 09:48:42 +0000 |
commit | 6023beb9dec8d71f3007154d4092db0eca926383 (patch) | |
tree | 23da013469d381d0c2b834ca81a889b4b40c3246 | |
parent | 10ab6671008c9ae3ac81b60ae8fde39d2aa133ad (diff) | |
download | FreeBSD-src-6023beb9dec8d71f3007154d4092db0eca926383.zip FreeBSD-src-6023beb9dec8d71f3007154d4092db0eca926383.tar.gz |
Fix the data corruption on the swap-backed md.
Assign the rv variable a success code if the pager was not asked for
the page. Using an error code from the previous processed page caused
zeroing of the valid page, when e.g. the previous page was not
available in the pager.
Reported by: lstewart
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
-rw-r--r-- | sys/dev/md/md.c | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/sys/dev/md/md.c b/sys/dev/md/md.c index e871d8f..57c5b57 100644 --- a/sys/dev/md/md.c +++ b/sys/dev/md/md.c @@ -829,7 +829,9 @@ mdstart_swap(struct md_s *sc, struct bio *bp) m = vm_page_grab(sc->object, i, VM_ALLOC_NORMAL | VM_ALLOC_RETRY); if (bp->bio_cmd == BIO_READ) { - if (m->valid != VM_PAGE_BITS_ALL) + if (m->valid == VM_PAGE_BITS_ALL) + rv = VM_PAGER_OK; + else rv = vm_pager_get_pages(sc->object, &m, 1, 0); if (rv == VM_PAGER_ERROR) { vm_page_wakeup(m); @@ -854,6 +856,8 @@ mdstart_swap(struct md_s *sc, struct bio *bp) } else if (bp->bio_cmd == BIO_WRITE) { if (len != PAGE_SIZE && m->valid != VM_PAGE_BITS_ALL) rv = vm_pager_get_pages(sc->object, &m, 1, 0); + else + rv = VM_PAGER_OK; if (rv == VM_PAGER_ERROR) { vm_page_wakeup(m); break; @@ -868,6 +872,8 @@ mdstart_swap(struct md_s *sc, struct bio *bp) } else if (bp->bio_cmd == BIO_DELETE) { if (len != PAGE_SIZE && m->valid != VM_PAGE_BITS_ALL) rv = vm_pager_get_pages(sc->object, &m, 1, 0); + else + rv = VM_PAGER_OK; if (rv == VM_PAGER_ERROR) { vm_page_wakeup(m); break; |