summaryrefslogtreecommitdiffstats
path: root/sys/vm
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2006-10-14 22:09:03 +0000
committeralc <alc@FreeBSD.org>2006-10-14 22:09:03 +0000
commit07a6c3ab4ed79dd790146ab334bbd17a33f1770d (patch)
treeb751df58f617bb7a596f8ca61f0188df4073be1e /sys/vm
parentd36e6277cb28a342a0320420363e0f210cf5ceca (diff)
downloadFreeBSD-src-07a6c3ab4ed79dd790146ab334bbd17a33f1770d.zip
FreeBSD-src-07a6c3ab4ed79dd790146ab334bbd17a33f1770d.tar.gz
Change vnode_pager_addr() such that on returning it distinguishes between
an error returned by VOP_BMAP() and a hole in the file. Change the callers to vnode_pager_addr() such that they return VM_PAGER_ERROR when VOP_BMAP fails instead of a zero-filled page. Reviewed by: tegge MFC after: 3 weeks
Diffstat (limited to 'sys/vm')
-rw-r--r--sys/vm/vnode_pager.c43
1 files changed, 24 insertions, 19 deletions
diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c
index b4a9bf6..e6b88cd 100644
--- a/sys/vm/vnode_pager.c
+++ b/sys/vm/vnode_pager.c
@@ -75,8 +75,8 @@ __FBSDID("$FreeBSD$");
#include <vm/vnode_pager.h>
#include <vm/vm_extern.h>
-static daddr_t vnode_pager_addr(struct vnode *vp, vm_ooffset_t address,
- int *run);
+static int vnode_pager_addr(struct vnode *vp, vm_ooffset_t address,
+ daddr_t *rtaddress, int *run);
static int vnode_pager_input_smlfs(vm_object_t object, vm_page_t m);
static int vnode_pager_input_old(vm_object_t object, vm_page_t m);
static void vnode_pager_dealloc(vm_object_t);
@@ -437,15 +437,11 @@ vnode_pager_setsize(vp, nsize)
* calculate the linear (byte) disk address of specified virtual
* file address
*/
-static daddr_t
-vnode_pager_addr(vp, address, run)
- struct vnode *vp;
- vm_ooffset_t address;
- int *run;
+static int
+vnode_pager_addr(struct vnode *vp, vm_ooffset_t address, daddr_t *rtaddress,
+ int *run)
{
- daddr_t rtaddress;
int bsize;
- daddr_t block;
int err;
daddr_t vblock;
daddr_t voffset;
@@ -460,12 +456,10 @@ vnode_pager_addr(vp, address, run)
vblock = address / bsize;
voffset = address % bsize;
- err = VOP_BMAP(vp, vblock, NULL, &block, run, NULL);
-
- if (err || (block == -1))
- rtaddress = -1;
- else {
- rtaddress = block + voffset / DEV_BSIZE;
+ err = VOP_BMAP(vp, vblock, NULL, rtaddress, run, NULL);
+ if (err == 0) {
+ if (*rtaddress != -1)
+ *rtaddress += voffset / DEV_BSIZE;
if (run) {
*run += 1;
*run *= bsize/PAGE_SIZE;
@@ -473,7 +467,7 @@ vnode_pager_addr(vp, address, run)
}
}
- return rtaddress;
+ return (err);
}
/*
@@ -513,7 +507,9 @@ vnode_pager_input_smlfs(object, m)
if (address >= object->un_pager.vnp.vnp_size) {
fileaddr = -1;
} else {
- fileaddr = vnode_pager_addr(vp, address, NULL);
+ error = vnode_pager_addr(vp, address, &fileaddr, NULL);
+ if (error)
+ break;
}
if (fileaddr != -1) {
bp = getpbuf(&vnode_pbuf_freecnt);
@@ -804,8 +800,17 @@ vnode_pager_generic_getpages(vp, m, bytecount, reqpage)
* calculate the run that includes the required page
*/
for (first = 0, i = 0; i < count; i = runend) {
- firstaddr = vnode_pager_addr(vp,
- IDX_TO_OFF(m[i]->pindex), &runpg);
+ if (vnode_pager_addr(vp, IDX_TO_OFF(m[i]->pindex), &firstaddr,
+ &runpg) != 0) {
+ VM_OBJECT_LOCK(object);
+ vm_page_lock_queues();
+ for (; i < count; i++)
+ if (i != reqpage)
+ vm_page_free(m[i]);
+ vm_page_unlock_queues();
+ VM_OBJECT_UNLOCK(object);
+ return (VM_PAGER_ERROR);
+ }
if (firstaddr == -1) {
VM_OBJECT_LOCK(object);
if (i == reqpage && foff < object->un_pager.vnp.vnp_size) {
OpenPOWER on IntegriCloud