[prev in list] [next in list] [prev in thread] [next in thread]
List: freebsd-commits-all
Subject: Re: svn commit: r292373 - in head: share/man/man9 sys/cddl/contrib/opensolaris/uts/common/fs/zfs sys
From: Gleb Kurtsou <gleb () freebsd ! org>
Date: 2016-02-14 23:04:35
Message-ID: 20160214230435.GA4547 () reks
[Download RAW message or body]
On (16/12/2015 21:30), Gleb Smirnoff wrote:
> Author: glebius
> Date: Wed Dec 16 21:30:45 2015
> New Revision: 292373
> URL: https://svnweb.freebsd.org/changeset/base/292373
>
> Log:
> A change to KPI of vm_pager_get_pages() and underlying VOP_GETPAGES().
>
> o With new KPI consumers can request contiguous ranges of pages, and
> unlike before, all pages will be kept busied on return, like it was
> done before with the 'reqpage' only. Now the reqpage goes away. With
> new interface it is easier to implement code protected from race
> conditions.
>
> Such arrayed requests for now should be preceeded by a call to
> vm_pager_haspage() to make sure that request is possible. This
> could be improved later, making vm_pager_haspage() obsolete.
vm_pager_haspage is essentially wrapper around VOP_BMAP. VOP_BMAP is a
stub for all non UFS-like file systems. E.g. it's return (0) in zfs and
return (EOPNOTSUPP) in tmpfs.
Could you elaborate on how strong the requirement of "should be preceded
by a call to vm_pager_haspage" is. It's also not clear how to approach
it if file system doesn't have bmap and getpages/putpages, but uses
standard fallback pager through read/write.
You've added vm_pager_has_page to exec_map_first_page. Should we now
assume that vm_pager_get_pages(VM_INITIAL_PAGEIN) may fail if 'after'
returned by vm_pager_has_page is less than VM_INITIAL_PAGEIN?
Could you please take a look at 2 patches attached. I'd like to commit
the one fixing vnode_pager_haspage, but I'm not sure about
vm_pager_has_page usage in exec_map_first_page.
0001-Emulate-vop_stdbmap-in-vnode_pager_haspage-if-bmap-i.patch
'after' will be uninitialized if VOP_BMAP returns error. KASSERT in
exec_map_first_page may fail because of it. I'm not sure if after = 0
is currently expected in exec_map_first_page.
Extend the logic to treat EOPNOTSUPP as vop_stdbmap (set before and
after to 0). Then extend both to fs block size.
0002-Handle-vm_pager_has_page-failure-during-exec.patch
Patch may be dropped if vm_pager_has_page is required to succeed as
described above.
Thanks,
Gleb.
["0001-Emulate-vop_stdbmap-in-vnode_pager_haspage-if-bmap-i.patch" (text/x-diff)]
From 40978eba392bcb20bf59704eac3d744d15f1e080 Mon Sep 17 00:00:00 2001
From: Gleb Kurtsou <gleb.kurtsou@gmail.com>
Date: Sat, 13 Feb 2016 23:00:00 -0800
Subject: [PATCH 1/2] Emulate vop_stdbmap in vnode_pager_haspage if bmap is not
supported fs.
Reset 'before' and 'after' to zero if VOP_BMAP fails. Assume no error
if bmap is not supported by file system and adjust 'before', 'after'
accordingly.
---
sys/vm/vnode_pager.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c
index 66dd29d7686..063d8d55495 100644
--- a/sys/vm/vnode_pager.c
+++ b/sys/vm/vnode_pager.c
@@ -321,32 +321,39 @@ vnode_pager_haspage(vm_object_t object, vm_pindex_t pindex, int *before,
if (IDX_TO_OFF(pindex) >= object->un_pager.vnp.vnp_size)
return FALSE;
bsize = vp->v_mount->mnt_stat.f_iosize;
pagesperblock = bsize / PAGE_SIZE;
blocksperpage = 0;
if (pagesperblock > 0) {
reqblock = pindex / pagesperblock;
} else {
blocksperpage = (PAGE_SIZE / bsize);
reqblock = pindex * blocksperpage;
}
VM_OBJECT_WUNLOCK(object);
err = VOP_BMAP(vp, reqblock, NULL, &bn, after, before);
VM_OBJECT_WLOCK(object);
- if (err)
- return TRUE;
+ if (err) {
+ if (before)
+ *before = 0;
+ if (after)
+ *after = 0;
+ if (err != EOPNOTSUPP)
+ return TRUE;
+ bn = reqblock;
+ }
if (bn == -1)
return FALSE;
if (pagesperblock > 0) {
poff = pindex - (reqblock * pagesperblock);
if (before) {
*before *= pagesperblock;
*before += poff;
}
if (after) {
/*
* The BMAP vop can report a partial block in the
* 'after', but must not report blocks after EOF.
* Assert the latter, and truncate 'after' in case
* of the former.
*/
--
2.4.2
["0002-Handle-vm_pager_has_page-failure-during-exec.patch" (text/x-diff)]
From 0d4ed2d975a796b612914ee70b82064ba5fa19e3 Mon Sep 17 00:00:00 2001
From: Gleb Kurtsou <gleb.kurtsou@gmail.com>
Date: Sat, 13 Feb 2016 23:07:50 -0800
Subject: [PATCH 2/2] Handle vm_pager_has_page failure during exec.
Relax exec_map_first_page dependency on vm_pager_has_page to calculate
initial number of pages. r292373 changed behavior to completely rely on
vm_pager_has_page().
Fallback to VM_INITIAL_PAGEIN if vm_pager_has_page fails or number of
pages reported as available ('after' argument) is zero.
---
sys/kern/kern_exec.c | 13 ++++---------
1 file changed, 4 insertions(+), 9 deletions(-)
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 741bc3e48c6..e71a32fca09 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -954,39 +954,34 @@ exec_map_first_page(imgp)
vm_page_t ma[VM_INITIAL_PAGEIN];
vm_object_t object;
if (imgp->firstpage != NULL)
exec_unmap_first_page(imgp);
object = imgp->vp->v_object;
if (object == NULL)
return (EACCES);
VM_OBJECT_WLOCK(object);
#if VM_NRESERVLEVEL > 0
vm_object_color(object, 0);
#endif
ma[0] = vm_page_grab(object, 0, VM_ALLOC_NORMAL);
if (ma[0]->valid != VM_PAGE_BITS_ALL) {
- if (!vm_pager_has_page(object, 0, NULL, &after)) {
- vm_page_lock(ma[0]);
- vm_page_free(ma[0]);
- vm_page_unlock(ma[0]);
- vm_page_xunbusy(ma[0]);
- VM_OBJECT_WUNLOCK(object);
- return (EIO);
- }
- initial_pagein = min(after, VM_INITIAL_PAGEIN);
+ if (vm_pager_has_page(object, 0, NULL, &after) && after > 0)
+ initial_pagein = min(after, VM_INITIAL_PAGEIN);
+ else
+ initial_pagein = min(object->size, VM_INITIAL_PAGEIN);
KASSERT(initial_pagein <= object->size,
("%s: initial_pagein %d object->size %ju",
__func__, initial_pagein, (uintmax_t )object->size));
for (i = 1; i < initial_pagein; i++) {
if ((ma[i] = vm_page_next(ma[i - 1])) != NULL) {
if (ma[i]->valid)
break;
if (vm_page_tryxbusy(ma[i]))
break;
} else {
ma[i] = vm_page_alloc(object, i,
VM_ALLOC_NORMAL | VM_ALLOC_IFNOTCACHED);
if (ma[i] == NULL)
break;
}
--
2.4.2
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic