Alexander Zagrebin
2010-Oct-28 06:17 UTC
8.1-STABLE: zfs and sendfile: problem still exists
Hi! I've noticed that ZFS on 8.1-STABLE still has problems with sendfile. When accessing a file at first time the transfer speed is too low, but on following attempts the transfer speed is normal. How to repeat: $ dd if=/dev/random of=/tmp/test bs=1m count=100 100+0 records in 100+0 records out 104857600 bytes transferred in 5.933945 secs (17670807 bytes/sec) $ sudo env LC_ALL=C /usr/libexec/ftpd -D The first attempt to fetch file: $ fetch -o /dev/null ftp://localhost/tmp/test /dev/null 1% of 100 MB 118 kBps 14m07s^C fetch: transfer interrupted The transfer rate is too low (approx. 120 kBps), but any subsequent attempts are success: $ fetch -o /dev/null ftp://localhost/tmp/test /dev/null 100% of 100 MB 42 MBps $ fetch -o /dev/null ftp://localhost/tmp/test /dev/null 100% of 100 MB 47 MBps ... To repeat it is enough to copy a file and to try again: $ cp /tmp/test /tmp/test1 $ fetch -o /dev/null ftp://localhost/tmp/test1 /dev/null 2% of 100 MB 119 kBps 13m50s^C fetch: transfer interrupted $ fetch -o /dev/null ftp://localhost/tmp/test1 /dev/null 100% of 100 MB 41 MBps $ fetch -o /dev/null ftp://localhost/tmp/test1 /dev/null 100% of 100 MB 47 MBps ...and again: $ cp /tmp/test1 /tmp/test2 $ fetch -o /dev/null ftp://localhost/tmp/test2 /dev/null 1% of 100 MB 118 kBps 14m07s^C fetch: transfer interrupted $ fetch -o /dev/null ftp://localhost/tmp/test2 /dev/null 100% of 100 MB 41 MBps $ fetch -o /dev/null ftp://localhost/tmp/test2 /dev/null 100% of 100 MB 47 MBps I've tried ftpd and nginx with "sendfile on". The behavior is the same. After disabling using sendfile in nginx ("sendfile off") the problem has gone. -- Alexander Zagrebin
On Thu, Oct 28, 2010 at 09:57:22AM +0400, Alexander Zagrebin wrote:> Hi! > > I've noticed that ZFS on 8.1-STABLE still has problems with sendfile. > When accessing a file at first time the transfer speed is too low, but > on following attempts the transfer speed is normal....> I've tried ftpd and nginx with "sendfile on". The behavior is the same. > After disabling using sendfile in nginx ("sendfile off") the problem has > gone.Yep, this problem exists. You may workaround it via bumping up net.inet.tcp.sendspace up to 128k. zfs sendfile is very ineffective. I have made a small investigation via DTrace, it reads MAXBSIZE chunks, but map in vm only one page (4K). I.e. if you have a file with size 512K, sendfile make calls freebsd_zfs_read 128 times.
on 28/10/2010 08:57 Alexander Zagrebin said the following:> Hi! > > I've noticed that ZFS on 8.1-STABLE still has problems with sendfile.Which svn revision, just in case?> When accessing a file at first time the transfer speed is too low, but > on following attempts the transfer speed is normal. > > How to repeat: > > $ dd if=/dev/random of=/tmp/test bs=1m count=100 > 100+0 records in > 100+0 records out > 104857600 bytes transferred in 5.933945 secs (17670807 bytes/sec) > $ sudo env LC_ALL=C /usr/libexec/ftpd -D > > The first attempt to fetch file: > > $ fetch -o /dev/null ftp://localhost/tmp/test > /dev/null 1% of 100 MB 118 kBps > 14m07s^C > fetch: transfer interrupted > > The transfer rate is too low (approx. 120 kBps), but any subsequent attempts > are success: > > $ fetch -o /dev/null ftp://localhost/tmp/test > /dev/null 100% of 100 MB 42 MBps > $ fetch -o /dev/null ftp://localhost/tmp/test > /dev/null 100% of 100 MB 47 MBpsCan you do an experiment with the same structure but sendfile excluded? -- Andriy Gapon
on 29/10/2010 12:04 Artemiev Igor said the following:> Yep, this problem exists. You may workaround it via bumping up > net.inet.tcp.sendspace up to 128k. zfs sendfile is very ineffective. I have > made a small investigation via DTrace, it reads MAXBSIZE chunks, but map in vm > only one page (4K). I.e. if you have a file with size 512K, sendfile make > calls freebsd_zfs_read 128 times.What svn revision of FreeBSD source tree did you test? -- Andriy Gapon
on 30/10/2010 11:16 Andriy Gapon said the following:> on 30/10/2010 11:16 Andriy Gapon said the following: >> Or maybe something like the following? >> It looks a little bit cleaner to me, but still is not perfect, as I have not >> handled unnecessary busy-ing of the pages where something more lightweight could >> have sufficed (e.g. wiring and shared busying). > > Note: I have only compile tested the patch.Missed one NULL check. Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c ==================================================================--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c (revision 214318) +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c (working copy) @@ -67,6 +67,7 @@ #include <sys/sf_buf.h> #include <sys/sched.h> #include <sys/acl.h> +#include <vm/vm_pageout.h> /* * Programming rules. @@ -464,7 +465,7 @@ uiomove_fromphys(&m, off, bytes, uio); VM_OBJECT_LOCK(obj); vm_page_wakeup(m); - } else if (m != NULL && uio->uio_segflg == UIO_NOCOPY) { + } else if (uio->uio_segflg == UIO_NOCOPY) { /* * The code below is here to make sendfile(2) work * correctly with ZFS. As pointed out by ups@ @@ -474,8 +475,18 @@ */ KASSERT(off == 0, ("unexpected offset in mappedread for sendfile")); - if (vm_page_sleep_if_busy(m, FALSE, "zfsmrb")) + if (m != NULL && vm_page_sleep_if_busy(m, FALSE, "zfsmrb")) goto again; + if (m == NULL) { + m = vm_page_alloc(obj, OFF_TO_IDX(start), + VM_ALLOC_NOBUSY | VM_ALLOC_SYSTEM); + if (m == NULL) { + VM_OBJECT_UNLOCK(obj); + VM_WAIT; + VM_OBJECT_LOCK(obj); + goto again; + } + } vm_page_busy(m); VM_OBJECT_UNLOCK(obj); if (dirbytes > 0) { -- Andriy Gapon
Heh, next try. Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c ==================================================================--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c (revision 214318) +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c (working copy) @@ -67,6 +67,7 @@ #include <sys/sf_buf.h> #include <sys/sched.h> #include <sys/acl.h> +#include <vm/vm_pageout.h> /* * Programming rules. @@ -464,7 +465,7 @@ uiomove_fromphys(&m, off, bytes, uio); VM_OBJECT_LOCK(obj); vm_page_wakeup(m); - } else if (m != NULL && uio->uio_segflg == UIO_NOCOPY) { + } else if (uio->uio_segflg == UIO_NOCOPY) { /* * The code below is here to make sendfile(2) work * correctly with ZFS. As pointed out by ups@ @@ -474,9 +475,23 @@ */ KASSERT(off == 0, ("unexpected offset in mappedread for sendfile")); - if (vm_page_sleep_if_busy(m, FALSE, "zfsmrb")) + if (m != NULL && vm_page_sleep_if_busy(m, FALSE, "zfsmrb")) goto again; - vm_page_busy(m); + if (m == NULL) { + m = vm_page_alloc(obj, OFF_TO_IDX(start), + VM_ALLOC_NOBUSY | VM_ALLOC_NORMAL); + if (m == NULL) { + VM_OBJECT_UNLOCK(obj); + VM_WAIT; + VM_OBJECT_LOCK(obj); + goto again; + } + } else { + vm_page_lock_queues(); + vm_page_wire(m); + vm_page_unlock_queues(); + } + vm_page_io_start(m); VM_OBJECT_UNLOCK(obj); if (dirbytes > 0) { error = dmu_read_uio(os, zp->z_id, uio, @@ -494,7 +509,10 @@ VM_OBJECT_LOCK(obj); if (error == 0) m->valid = VM_PAGE_BITS_ALL; - vm_page_wakeup(m); + vm_page_io_finish(m); + vm_page_lock_queues(); + vm_page_unwire(m, 0); + vm_page_unlock_queues(); if (error == 0) { uio->uio_resid -= bytes; uio->uio_offset += bytes; -- Andriy Gapon
On Sat, Oct 30, 2010 at 11:25:05AM +0300, Andriy Gapon wrote:> > Note: I have only compile tested the patch. > > Missed one NULL check. > > Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c > ==================================================================> --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c (revision 214318) > +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c (working copy) > @@ -67,6 +67,7 @@ > #include <sys/sf_buf.h> > #include <sys/sched.h> > #include <sys/acl.h> > +#include <vm/vm_pageout.h> > > /* > * Programming rules. > @@ -464,7 +465,7 @@ > uiomove_fromphys(&m, off, bytes, uio); > VM_OBJECT_LOCK(obj); > vm_page_wakeup(m); > - } else if (m != NULL && uio->uio_segflg == UIO_NOCOPY) { > + } else if (uio->uio_segflg == UIO_NOCOPY) { > /* > * The code below is here to make sendfile(2) work > * correctly with ZFS. As pointed out by ups@ > @@ -474,8 +475,18 @@ > */ > KASSERT(off == 0, > ("unexpected offset in mappedread for sendfile")); > - if (vm_page_sleep_if_busy(m, FALSE, "zfsmrb")) > + if (m != NULL && vm_page_sleep_if_busy(m, FALSE, "zfsmrb")) > goto again; > + if (m == NULL) { > + m = vm_page_alloc(obj, OFF_TO_IDX(start), > + VM_ALLOC_NOBUSY | VM_ALLOC_SYSTEM); > + if (m == NULL) { > + VM_OBJECT_UNLOCK(obj); > + VM_WAIT; > + VM_OBJECT_LOCK(obj); > + goto again; > + } > + } > vm_page_busy(m); > VM_OBJECT_UNLOCK(obj); > if (dirbytes > 0) {Ok, i tested this patch. It worked :) freebsd_zfs_read now calls (file_size/MAXBSIZE) times. Thanks!
On Sat, Oct 30, 2010 at 12:52:54PM +0300, Andriy Gapon wrote:> Heh, next try.Got a panic, "vm_page_unwire: invalid wire count: 0"
on 30/10/2010 13:12 Artemiev Igor said the following:> On Sat, Oct 30, 2010 at 12:52:54PM +0300, Andriy Gapon wrote: > >> Heh, next try. > > Got a panic, "vm_page_unwire: invalid wire count: 0"Oh, thank you for testing - forgot another piece (VM_ALLOC_WIRE for vm_page_alloc): Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c ==================================================================--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c (revision 214318) +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c (working copy) @@ -67,6 +67,7 @@ #include <sys/sf_buf.h> #include <sys/sched.h> #include <sys/acl.h> +#include <vm/vm_pageout.h> /* * Programming rules. @@ -464,7 +465,7 @@ uiomove_fromphys(&m, off, bytes, uio); VM_OBJECT_LOCK(obj); vm_page_wakeup(m); - } else if (m != NULL && uio->uio_segflg == UIO_NOCOPY) { + } else if (uio->uio_segflg == UIO_NOCOPY) { /* * The code below is here to make sendfile(2) work * correctly with ZFS. As pointed out by ups@ @@ -474,9 +475,23 @@ */ KASSERT(off == 0, ("unexpected offset in mappedread for sendfile")); - if (vm_page_sleep_if_busy(m, FALSE, "zfsmrb")) + if (m != NULL && vm_page_sleep_if_busy(m, FALSE, "zfsmrb")) goto again; - vm_page_busy(m); + if (m == NULL) { + m = vm_page_alloc(obj, OFF_TO_IDX(start), + VM_ALLOC_NOBUSY | VM_ALLOC_WIRE | VM_ALLOC_NORMAL); + if (m == NULL) { + VM_OBJECT_UNLOCK(obj); + VM_WAIT; + VM_OBJECT_LOCK(obj); + goto again; + } + } else { + vm_page_lock_queues(); + vm_page_wire(m); + vm_page_unlock_queues(); + } + vm_page_io_start(m); VM_OBJECT_UNLOCK(obj); if (dirbytes > 0) { error = dmu_read_uio(os, zp->z_id, uio, @@ -494,7 +509,10 @@ VM_OBJECT_LOCK(obj); if (error == 0) m->valid = VM_PAGE_BITS_ALL; - vm_page_wakeup(m); + vm_page_io_finish(m); + vm_page_lock_queues(); + vm_page_unwire(m, 0); + vm_page_unlock_queues(); if (error == 0) { uio->uio_resid -= bytes; uio->uio_offset += bytes; -- Andriy Gapon
On Sat, Oct 30, 2010 at 01:33:00PM +0300, Andriy Gapon wrote:> on 30/10/2010 13:12 Artemiev Igor said the following: > > On Sat, Oct 30, 2010 at 12:52:54PM +0300, Andriy Gapon wrote: > > > >> Heh, next try. > > > > Got a panic, "vm_page_unwire: invalid wire count: 0" > > Oh, thank you for testing - forgot another piece (VM_ALLOC_WIRE for vm_page_alloc):Yep, it work. But VM_ALLOC_WIRE not exists in RELENG_8, therefore i slightly modified your patch: --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c.orig 2010-10-30 11:56:41.621138440 +0200 +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c 2010-10-30 12:49:32.858692096 +0200 @@ -67,6 +67,7 @@ #include <sys/sf_buf.h> #include <sys/sched.h> #include <sys/acl.h> +#include <vm/vm_pageout.h> /* * Programming rules. @@ -464,7 +465,7 @@ uiomove_fromphys(&m, off, bytes, uio); VM_OBJECT_LOCK(obj); vm_page_wakeup(m); - } else if (m != NULL && uio->uio_segflg == UIO_NOCOPY) { + } else if (uio->uio_segflg == UIO_NOCOPY) { /* * The code below is here to make sendfile(2) work * correctly with ZFS. As pointed out by ups@ @@ -474,9 +475,23 @@ */ KASSERT(off == 0, ("unexpected offset in mappedread for sendfile")); - if (vm_page_sleep_if_busy(m, FALSE, "zfsmrb")) + if (m != NULL && vm_page_sleep_if_busy(m, FALSE, "zfsmrb")) goto again; - vm_page_busy(m); + if (m == NULL) { + m = vm_page_alloc(obj, OFF_TO_IDX(start), + VM_ALLOC_NOBUSY | VM_ALLOC_NORMAL); + if (m == NULL) { + VM_OBJECT_UNLOCK(obj); + VM_WAIT; + VM_OBJECT_LOCK(obj); + goto again; + } + } + vm_page_lock_queues(); + vm_page_wire(m); + vm_page_unlock_queues(); + + vm_page_io_start(m); VM_OBJECT_UNLOCK(obj); if (dirbytes > 0) { error = dmu_read_uio(os, zp->z_id, uio, @@ -494,6 +509,10 @@ VM_OBJECT_LOCK(obj); if (error == 0) m->valid = VM_PAGE_BITS_ALL; + vm_page_io_finish(m); + vm_page_lock_queues(); + vm_page_unwire(m, 0); + vm_page_unlock_queues(); vm_page_wakeup(m); if (error == 0) { uio->uio_resid -= bytes;
on 30/10/2010 14:25 Artemiev Igor said the following:> On Sat, Oct 30, 2010 at 01:33:00PM +0300, Andriy Gapon wrote: >> on 30/10/2010 13:12 Artemiev Igor said the following: >>> On Sat, Oct 30, 2010 at 12:52:54PM +0300, Andriy Gapon wrote: >>> >>>> Heh, next try. >>> >>> Got a panic, "vm_page_unwire: invalid wire count: 0" >> >> Oh, thank you for testing - forgot another piece (VM_ALLOC_WIRE for vm_page_alloc): > > Yep, it work. But VM_ALLOC_WIRE not exists in RELENG_8, therefore i slightly modified your patch:I apologize for my haste, it should have been VM_ALLOC_WIRED. Here is a corrected patch: Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c ==================================================================--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c (revision 214318) +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c (working copy) @@ -67,6 +67,7 @@ #include <sys/sf_buf.h> #include <sys/sched.h> #include <sys/acl.h> +#include <vm/vm_pageout.h> /* * Programming rules. @@ -464,7 +465,7 @@ uiomove_fromphys(&m, off, bytes, uio); VM_OBJECT_LOCK(obj); vm_page_wakeup(m); - } else if (m != NULL && uio->uio_segflg == UIO_NOCOPY) { + } else if (uio->uio_segflg == UIO_NOCOPY) { /* * The code below is here to make sendfile(2) work * correctly with ZFS. As pointed out by ups@ @@ -474,9 +475,23 @@ */ KASSERT(off == 0, ("unexpected offset in mappedread for sendfile")); - if (vm_page_sleep_if_busy(m, FALSE, "zfsmrb")) + if (m != NULL && vm_page_sleep_if_busy(m, FALSE, "zfsmrb")) goto again; - vm_page_busy(m); + if (m == NULL) { + m = vm_page_alloc(obj, OFF_TO_IDX(start), + VM_ALLOC_NOBUSY | VM_ALLOC_WIRED | VM_ALLOC_NORMAL); + if (m == NULL) { + VM_OBJECT_UNLOCK(obj); + VM_WAIT; + VM_OBJECT_LOCK(obj); + goto again; + } + } else { + vm_page_lock_queues(); + vm_page_wire(m); + vm_page_unlock_queues(); + } + vm_page_io_start(m); VM_OBJECT_UNLOCK(obj); if (dirbytes > 0) { error = dmu_read_uio(os, zp->z_id, uio, @@ -494,7 +509,10 @@ VM_OBJECT_LOCK(obj); if (error == 0) m->valid = VM_PAGE_BITS_ALL; - vm_page_wakeup(m); + vm_page_io_finish(m); + vm_page_lock_queues(); + vm_page_unwire(m, 0); + vm_page_unlock_queues(); if (error == 0) { uio->uio_resid -= bytes; uio->uio_offset += bytes; -- Andriy Gapon
On Sat, Oct 30, 2010 at 05:43:54PM +0300, Andriy Gapon wrote:> I apologize for my haste, it should have been VM_ALLOC_WIRED.Ok, applied and tested under some load(~1200 active connections, outgoing ~80MB/s). Patch work as expected and i has noted no side effects. Just one question - should grow Active memory counter, if some pages is "hot"(during multiple sendfile on one file)?
On Sat, Oct 30, 2010 at 05:43:54PM +0300, Andriy Gapon wrote:> on 30/10/2010 14:25 Artemiev Igor said the following: > > On Sat, Oct 30, 2010 at 01:33:00PM +0300, Andriy Gapon wrote: > >> on 30/10/2010 13:12 Artemiev Igor said the following: > >>> On Sat, Oct 30, 2010 at 12:52:54PM +0300, Andriy Gapon wrote: > >>> > >>>> Heh, next try. > >>> > >>> Got a panic, "vm_page_unwire: invalid wire count: 0" > >> > >> Oh, thank you for testing - forgot another piece (VM_ALLOC_WIRE for vm_page_alloc): > > > > Yep, it work. But VM_ALLOC_WIRE not exists in RELENG_8, therefore i slightly modified your patch: > > I apologize for my haste, it should have been VM_ALLOC_WIRED. > Here is a corrected patch: > Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c > ==================================================================> --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c (revision 214318) > +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c (working copy) > @@ -67,6 +67,7 @@ > #include <sys/sf_buf.h> > #include <sys/sched.h> > #include <sys/acl.h> > +#include <vm/vm_pageout.h> > > /* > * Programming rules. > @@ -464,7 +465,7 @@ > uiomove_fromphys(&m, off, bytes, uio); > VM_OBJECT_LOCK(obj); > vm_page_wakeup(m); > - } else if (m != NULL && uio->uio_segflg == UIO_NOCOPY) { > + } else if (uio->uio_segflg == UIO_NOCOPY) { > /* > * The code below is here to make sendfile(2) work > * correctly with ZFS. As pointed out by ups@ > @@ -474,9 +475,23 @@ > */ > KASSERT(off == 0, > ("unexpected offset in mappedread for sendfile")); > - if (vm_page_sleep_if_busy(m, FALSE, "zfsmrb")) > + if (m != NULL && vm_page_sleep_if_busy(m, FALSE, "zfsmrb")) > goto again; > - vm_page_busy(m); > + if (m == NULL) { > + m = vm_page_alloc(obj, OFF_TO_IDX(start), > + VM_ALLOC_NOBUSY | VM_ALLOC_WIRED | VM_ALLOC_NORMAL); > + if (m == NULL) { > + VM_OBJECT_UNLOCK(obj); > + VM_WAIT; > + VM_OBJECT_LOCK(obj); > + goto again; > + } > + } else { > + vm_page_lock_queues(); > + vm_page_wire(m); > + vm_page_unlock_queues(); > + } > + vm_page_io_start(m);Why wiring the page if it is busied ? -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 196 bytes Desc: not available Url : http://lists.freebsd.org/pipermail/freebsd-stable/attachments/20101030/4cfa2b62/attachment.pgp
on 31/10/2010 02:37 Kostik Belousov said the following:> On Sat, Oct 30, 2010 at 05:43:54PM +0300, Andriy Gapon wrote: >> on 30/10/2010 14:25 Artemiev Igor said the following: >>> On Sat, Oct 30, 2010 at 01:33:00PM +0300, Andriy Gapon wrote: >>>> on 30/10/2010 13:12 Artemiev Igor said the following: >>>>> On Sat, Oct 30, 2010 at 12:52:54PM +0300, Andriy Gapon wrote: >>>>> >>>>>> Heh, next try. >>>>> >>>>> Got a panic, "vm_page_unwire: invalid wire count: 0" >>>> >>>> Oh, thank you for testing - forgot another piece (VM_ALLOC_WIRE for vm_page_alloc): >>> >>> Yep, it work. But VM_ALLOC_WIRE not exists in RELENG_8, therefore i slightly modified your patch: >> >> I apologize for my haste, it should have been VM_ALLOC_WIRED. >> Here is a corrected patch: >> Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c >> ==================================================================>> --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c (revision 214318) >> +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c (working copy) >> @@ -67,6 +67,7 @@ >> #include <sys/sf_buf.h> >> #include <sys/sched.h> >> #include <sys/acl.h> >> +#include <vm/vm_pageout.h> >> >> /* >> * Programming rules. >> @@ -464,7 +465,7 @@ >> uiomove_fromphys(&m, off, bytes, uio); >> VM_OBJECT_LOCK(obj); >> vm_page_wakeup(m); >> - } else if (m != NULL && uio->uio_segflg == UIO_NOCOPY) { >> + } else if (uio->uio_segflg == UIO_NOCOPY) { >> /* >> * The code below is here to make sendfile(2) work >> * correctly with ZFS. As pointed out by ups@ >> @@ -474,9 +475,23 @@ >> */ >> KASSERT(off == 0, >> ("unexpected offset in mappedread for sendfile")); >> - if (vm_page_sleep_if_busy(m, FALSE, "zfsmrb")) >> + if (m != NULL && vm_page_sleep_if_busy(m, FALSE, "zfsmrb")) >> goto again; >> - vm_page_busy(m); >> + if (m == NULL) { >> + m = vm_page_alloc(obj, OFF_TO_IDX(start), >> + VM_ALLOC_NOBUSY | VM_ALLOC_WIRED | VM_ALLOC_NORMAL); >> + if (m == NULL) { >> + VM_OBJECT_UNLOCK(obj); >> + VM_WAIT; >> + VM_OBJECT_LOCK(obj); >> + goto again; >> + } >> + } else { >> + vm_page_lock_queues(); >> + vm_page_wire(m); >> + vm_page_unlock_queues(); >> + } >> + vm_page_io_start(m); > Why wiring the page if it is busied ?Eh? Because it is not? -- Andriy Gapon
on 30/10/2010 22:01 Artemiev Igor said the following:> On Sat, Oct 30, 2010 at 05:43:54PM +0300, Andriy Gapon wrote: > >> I apologize for my haste, it should have been VM_ALLOC_WIRED. > > Ok, applied and tested under some load(~1200 active connections, outgoing > ~80MB/s). Patch work as expected and i has noted no side effects. Just one > question - should grow Active memory counter, if some pages is "hot"(during > multiple sendfile on one file)?Pages used by sendfile are marked as Inactive for faster reclamation on demand. -- Andriy Gapon