From gleb.kurtsou@gmail.com  Fri Oct  2 19:45:49 2009
Return-Path: <gleb.kurtsou@gmail.com>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id C6032106568D
	for <bug-followup@freebsd.org>; Fri,  2 Oct 2009 19:45:49 +0000 (UTC)
	(envelope-from gleb.kurtsou@gmail.com)
Received: from fg-out-1718.google.com (fg-out-1718.google.com [72.14.220.158])
	by mx1.freebsd.org (Postfix) with ESMTP id 3B8B48FC16
	for <bug-followup@freebsd.org>; Fri,  2 Oct 2009 19:45:48 +0000 (UTC)
Received: by fg-out-1718.google.com with SMTP id e21so2103594fga.13
        for <bug-followup@freebsd.org>; Fri, 02 Oct 2009 12:45:48 -0700 (PDT)
Received: by 10.86.254.17 with SMTP id b17mr2574899fgi.65.1254512748117;
        Fri, 02 Oct 2009 12:45:48 -0700 (PDT)
Received: from localhost (lan-78-157-90-54.vln.skynet.lt [78.157.90.54])
        by mx.google.com with ESMTPS id e11sm151196fga.18.2009.10.02.12.45.47
        (version=TLSv1/SSLv3 cipher=RC4-MD5);
        Fri, 02 Oct 2009 12:45:47 -0700 (PDT)
Message-Id: <20091002194528.GA37060@tops>
Date: Fri, 2 Oct 2009 22:45:28 +0300
From: Gleb Kurtsou <gleb.kurtsou@gmail.com>
To: bug-followup@FreeBSD.org, citrin@citrin.ru
In-Reply-To: <20080908173436.6F01C5C3B@mx3.rambler.ru>
Subject: Re: sendfile on tmpfs data corruption
References: <20080908173436.6F01C5C3B@mx3.rambler.ru>

>Number:         139316
>Category:       kern
>Synopsis:       Re: sendfile on tmpfs data corruption
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-ports-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Oct 02 19:50:00 UTC 2009
>Closed-Date:    Fri Oct 02 21:40:01 UTC 2009
>Last-Modified:  Fri Oct 02 21:40:01 UTC 2009
>Originator:     
>Release:        
>Organization:
>Environment:
>Description:
 --6TrnltStXW4iwmi0
 Content-Type: text/plain; charset=utf-8
 Content-Disposition: inline
 
 Try the patch attached, it fixes the bug for me.
 The same workaround is used by zfs.
 
 
 --6TrnltStXW4iwmi0
 Content-Type: text/plain; charset=utf-8
 Content-Disposition: attachment; filename="tmpfs-sendfile.patch.txt"
 
 diff --git a/sys/fs/tmpfs/tmpfs_vnops.c b/sys/fs/tmpfs/tmpfs_vnops.c
 index db8ceea..a6e4510 100644
 --- a/sys/fs/tmpfs/tmpfs_vnops.c
 +++ b/sys/fs/tmpfs/tmpfs_vnops.c
 @@ -43,6 +43,8 @@ __FBSDID("$FreeBSD$");
  #include <sys/priv.h>
  #include <sys/proc.h>
  #include <sys/resourcevar.h>
 +#include <sys/sched.h>
 +#include <sys/sf_buf.h>
  #include <sys/stat.h>
  #include <sys/systm.h>
  #include <sys/unistd.h>
 @@ -428,15 +430,72 @@ tmpfs_setattr(struct vop_setattr_args *v)
  }
  
  /* --------------------------------------------------------------------- */
 +static int
 +tmpfs_nocacheread(vm_object_t tobj, vm_pindex_t idx,
 +    vm_offset_t offset, size_t tlen, struct uio *uio)
 +{
 +	vm_page_t	m;
 +	int		error;
 +
 +	VM_OBJECT_LOCK(tobj);
 +	vm_object_pip_add(tobj, 1);
 +	m = vm_page_grab(tobj, idx, VM_ALLOC_WIRED |
 +	    VM_ALLOC_ZERO | VM_ALLOC_NORMAL | VM_ALLOC_RETRY);
 +	if (m->valid != VM_PAGE_BITS_ALL) {
 +		if (vm_pager_has_page(tobj, idx, NULL, NULL)) {
 +			error = vm_pager_get_pages(tobj, &m, 1, 0);
 +			if (error != 0) {
 +				printf("tmpfs get pages from pager error [read]\n");
 +				goto out;
 +			}
 +		} else
 +			vm_page_zero_invalid(m, TRUE);
 +	}
 +	VM_OBJECT_UNLOCK(tobj);
 +	error = uiomove_fromphys(&m, offset, tlen, uio);
 +	VM_OBJECT_LOCK(tobj);
 +out:
 +	vm_page_lock_queues();
 +	vm_page_unwire(m, TRUE);
 +	vm_page_unlock_queues();
 +	vm_page_wakeup(m);
 +	vm_object_pip_subtract(tobj, 1);
 +	VM_OBJECT_UNLOCK(tobj);
 +
 +	return (error);
 +}
 +
 +static __inline int
 +tmpfs_nocacheread_buf(vm_object_t tobj, vm_pindex_t idx,
 +    vm_offset_t offset, size_t tlen, void *buf)
 +{
 +	struct uio uio;
 +	struct iovec iov;
 +
 +	uio.uio_iovcnt = 1;
 +	uio.uio_iov = &iov;
 +	iov.iov_base = buf;
 +	iov.iov_len = tlen;
 +
 +	uio.uio_offset = 0;
 +	uio.uio_resid = tlen;
 +	uio.uio_rw = UIO_READ;
 +	uio.uio_segflg = UIO_SYSSPACE;
 +	uio.uio_td = curthread;
 +
 +	return (tmpfs_nocacheread(tobj, idx, offset, tlen, &uio));
 +}
  
  static int
  tmpfs_mappedread(vm_object_t vobj, vm_object_t tobj, size_t len, struct uio *uio)
  {
 +	struct sf_buf	*sf;
  	vm_pindex_t	idx;
  	vm_page_t	m;
  	vm_offset_t	offset;
  	off_t		addr;
  	size_t		tlen;
 +	char		*ma;
  	int		error;
  
  	addr = uio->uio_offset;
 @@ -460,33 +519,30 @@ lookupvpg:
  		vm_page_wakeup(m);
  		VM_OBJECT_UNLOCK(vobj);
  		return	(error);
 +	} else if (m != NULL && uio->uio_segflg == UIO_NOCOPY) {
 +		if (vm_page_sleep_if_busy(m, FALSE, "tmfsmr"))
 +			goto lookupvpg;
 +		vm_page_busy(m);
 +		VM_OBJECT_UNLOCK(vobj);
 +		sched_pin();
 +		sf = sf_buf_alloc(m, SFB_CPUPRIVATE);
 +		ma = (char *)sf_buf_kva(sf);
 +		error = tmpfs_nocacheread_buf(tobj, idx, offset, tlen,
 +		    ma + offset);
 +		if (error == 0) {
 +			uio->uio_offset += tlen;
 +			uio->uio_resid -= tlen;
 +		}
 +		sf_buf_free(sf);
 +		sched_unpin();
 +		VM_OBJECT_LOCK(vobj);
 +		vm_page_wakeup(m);
 +		VM_OBJECT_UNLOCK(vobj);
 +		return	(error);
  	}
  	VM_OBJECT_UNLOCK(vobj);
  nocache:
 -	VM_OBJECT_LOCK(tobj);
 -	vm_object_pip_add(tobj, 1);
 -	m = vm_page_grab(tobj, idx, VM_ALLOC_WIRED |
 -	    VM_ALLOC_ZERO | VM_ALLOC_NORMAL | VM_ALLOC_RETRY);
 -	if (m->valid != VM_PAGE_BITS_ALL) {
 -		if (vm_pager_has_page(tobj, idx, NULL, NULL)) {
 -			error = vm_pager_get_pages(tobj, &m, 1, 0);
 -			if (error != 0) {
 -				printf("tmpfs get pages from pager error [read]\n");
 -				goto out;
 -			}
 -		} else
 -			vm_page_zero_invalid(m, TRUE);
 -	}
 -	VM_OBJECT_UNLOCK(tobj);
 -	error = uiomove_fromphys(&m, offset, tlen, uio);
 -	VM_OBJECT_LOCK(tobj);
 -out:
 -	vm_page_lock_queues();
 -	vm_page_unwire(m, TRUE);
 -	vm_page_unlock_queues();
 -	vm_page_wakeup(m);
 -	vm_object_pip_subtract(tobj, 1);
 -	VM_OBJECT_UNLOCK(tobj);
 +	error = tmpfs_nocacheread(tobj, idx, offset, tlen, uio);
  
  	return	(error);
  }
 
 --6TrnltStXW4iwmi0--
>How-To-Repeat:
>Fix:
>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->closed 
State-Changed-By: linimon 
State-Changed-When: Fri Oct 2 21:39:18 UTC 2009 
State-Changed-Why:  
Misfiled followup to kern/127213; content migrated. 


Responsible-Changed-From-To: gnats-admin->freebsd-ports-bugs 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Fri Oct 2 21:39:18 UTC 2009 
Responsible-Changed-Why:  

http://www.freebsd.org/cgi/query-pr.cgi?pr=139316 
>Unformatted:
