8.1-STABLE: zfs and sendfile: problem still exists

Alexander Zagrebin alexz at visp.ru
Sat Oct 30 16:02:56 UTC 2010


> >> 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;
> 

Big thanks to Andriy, Igor and all who has paid attention to this problem.
I've tried this patch on the test system running under VirtualBox,
and it seems that it solves the problem.
I'll try to test this patch in real conditions today.

-- 
Alexander Zagrebin



More information about the freebsd-fs mailing list