diff options
author | kib <kib@FreeBSD.org> | 2008-09-26 14:50:49 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2008-09-26 14:50:49 +0000 |
commit | 496b70bc6ae4c9f8b2f01168acbb39b39e6f3112 (patch) | |
tree | 83ec201504ae8c58d18c3600f36c7e08a41162df /sys/vm/device_pager.c | |
parent | d421caabf98d87498154b13c49b8f5d352aea70c (diff) | |
download | FreeBSD-src-496b70bc6ae4c9f8b2f01168acbb39b39e6f3112.zip FreeBSD-src-496b70bc6ae4c9f8b2f01168acbb39b39e6f3112.tar.gz |
Save previous content of the td_fpop before storing the current
filedescriptor into it. Make sure that td_fpop is NULL when calling
d_mmap from dev_pager_getpages().
Change guards against td_fpop field being non-NULL with private state
for another device, and against sudden clearing the td_fpop. This
could occur when either a driver method calls another driver through
the filedescriptor operation, or a page fault happen while driver is
writing to a memory backed by another driver.
Noted by: rwatson
Tested by: rnoland
MFC after: 3 days
Diffstat (limited to 'sys/vm/device_pager.c')
-rw-r--r-- | sys/vm/device_pager.c | 6 |
1 files changed, 6 insertions, 0 deletions
diff --git a/sys/vm/device_pager.c b/sys/vm/device_pager.c index e771928..5e31e2b 100644 --- a/sys/vm/device_pager.c +++ b/sys/vm/device_pager.c @@ -214,6 +214,8 @@ dev_pager_getpages(object, m, count, reqpage) int i, ret; int prot; struct cdevsw *csw; + struct thread *td; + struct file *fpop; VM_OBJECT_LOCK_ASSERT(object, MA_OWNED); dev = object->handle; @@ -224,8 +226,12 @@ dev_pager_getpages(object, m, count, reqpage) panic("dev_pager_getpage: no cdevsw"); prot = PROT_READ; /* XXX should pass in? */ + td = curthread; + fpop = td->td_fpop; + td->td_fpop = NULL; ret = (*csw->d_mmap)(dev, (vm_offset_t)offset << PAGE_SHIFT, &paddr, prot); KASSERT(ret == 0, ("dev_pager_getpage: map function returns error")); + td->td_fpop = fpop; dev_relthread(dev); if ((m[reqpage]->flags & PG_FICTITIOUS) != 0) { |