Home | History | Annotate | Line # | Download | only in genfs
genfs_vnops.c revision 1.11.4.3
      1  1.11.4.3       chs /*	$NetBSD: genfs_vnops.c,v 1.11.4.3 1999/07/12 02:40:30 chs Exp $	*/
      2       1.6      fvdl 
      3       1.6      fvdl /*
      4       1.6      fvdl  * Copyright (c) 1982, 1986, 1989, 1993
      5       1.6      fvdl  *	The Regents of the University of California.  All rights reserved.
      6       1.6      fvdl  *
      7       1.6      fvdl  * Redistribution and use in source and binary forms, with or without
      8       1.6      fvdl  * modification, are permitted provided that the following conditions
      9       1.6      fvdl  * are met:
     10       1.6      fvdl  * 1. Redistributions of source code must retain the above copyright
     11       1.6      fvdl  *    notice, this list of conditions and the following disclaimer.
     12       1.6      fvdl  * 2. Redistributions in binary form must reproduce the above copyright
     13       1.6      fvdl  *    notice, this list of conditions and the following disclaimer in the
     14       1.6      fvdl  *    documentation and/or other materials provided with the distribution.
     15       1.6      fvdl  * 3. All advertising materials mentioning features or use of this software
     16       1.6      fvdl  *    must display the following acknowledgement:
     17       1.6      fvdl  *	This product includes software developed by the University of
     18       1.6      fvdl  *	California, Berkeley and its contributors.
     19       1.6      fvdl  * 4. Neither the name of the University nor the names of its contributors
     20       1.6      fvdl  *    may be used to endorse or promote products derived from this software
     21       1.6      fvdl  *    without specific prior written permission.
     22       1.6      fvdl  *
     23       1.6      fvdl  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24       1.6      fvdl  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25       1.6      fvdl  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26       1.6      fvdl  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27       1.6      fvdl  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28       1.6      fvdl  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29       1.6      fvdl  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30       1.6      fvdl  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31       1.6      fvdl  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32       1.6      fvdl  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33       1.6      fvdl  * SUCH DAMAGE.
     34       1.6      fvdl  *
     35       1.6      fvdl  */
     36       1.5     perry 
     37       1.8   thorpej #include "opt_nfsserver.h"
     38       1.8   thorpej 
     39       1.1   mycroft #include <sys/param.h>
     40       1.1   mycroft #include <sys/systm.h>
     41       1.6      fvdl #include <sys/proc.h>
     42       1.1   mycroft #include <sys/kernel.h>
     43       1.1   mycroft #include <sys/mount.h>
     44       1.1   mycroft #include <sys/namei.h>
     45       1.1   mycroft #include <sys/vnode.h>
     46       1.1   mycroft #include <sys/malloc.h>
     47       1.3   mycroft #include <sys/poll.h>
     48       1.1   mycroft 
     49       1.1   mycroft #include <miscfs/genfs/genfs.h>
     50       1.6      fvdl #include <miscfs/specfs/specdev.h>
     51       1.1   mycroft 
     52  1.11.4.1       chs #include <vm/vm.h>
     53  1.11.4.1       chs #include <uvm/uvm.h>
     54  1.11.4.1       chs 
     55       1.8   thorpej #ifdef NFSSERVER
     56       1.8   thorpej #include <nfs/rpcv2.h>
     57       1.8   thorpej #include <nfs/nfsproto.h>
     58       1.8   thorpej #include <nfs/nfs.h>
     59       1.8   thorpej #include <nfs/nqnfs.h>
     60       1.8   thorpej #include <nfs/nfs_var.h>
     61       1.8   thorpej #endif
     62       1.8   thorpej 
     63       1.1   mycroft int
     64       1.3   mycroft genfs_poll(v)
     65       1.1   mycroft 	void *v;
     66       1.1   mycroft {
     67       1.3   mycroft 	struct vop_poll_args /* {
     68       1.1   mycroft 		struct vnode *a_vp;
     69       1.3   mycroft 		int a_events;
     70       1.1   mycroft 		struct proc *a_p;
     71       1.1   mycroft 	} */ *ap = v;
     72       1.1   mycroft 
     73       1.3   mycroft 	return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
     74       1.1   mycroft }
     75       1.1   mycroft 
     76       1.1   mycroft int
     77       1.1   mycroft genfs_fsync(v)
     78       1.1   mycroft 	void *v;
     79       1.1   mycroft {
     80       1.1   mycroft 	struct vop_fsync_args /* {
     81       1.1   mycroft 		struct vnode *a_vp;
     82       1.1   mycroft 		struct ucred *a_cred;
     83       1.7    kleink 		int a_flags;
     84       1.1   mycroft 		struct proc *a_p;
     85       1.1   mycroft 	} */ *ap = v;
     86       1.1   mycroft 	register struct vnode *vp = ap->a_vp;
     87      1.11   mycroft 	int wait;
     88       1.1   mycroft 
     89      1.11   mycroft 	wait = (ap->a_flags & FSYNC_WAIT) != 0;
     90      1.11   mycroft 	vflushbuf(vp, wait);
     91      1.11   mycroft 	if ((ap->a_flags & FSYNC_DATAONLY) != 0)
     92       1.7    kleink 		return (0);
     93      1.11   mycroft 	else
     94      1.11   mycroft 		return (VOP_UPDATE(ap->a_vp, NULL, NULL, wait));
     95       1.1   mycroft }
     96       1.1   mycroft 
     97       1.1   mycroft int
     98       1.4    kleink genfs_seek(v)
     99       1.4    kleink 	void *v;
    100       1.4    kleink {
    101       1.4    kleink 	struct vop_seek_args /* {
    102       1.4    kleink 		struct vnode *a_vp;
    103       1.4    kleink 		off_t a_oldoff;
    104       1.4    kleink 		off_t a_newoff;
    105       1.4    kleink 		struct ucred *a_ucred;
    106       1.4    kleink 	} */ *ap = v;
    107       1.4    kleink 
    108       1.4    kleink 	if (ap->a_newoff < 0)
    109       1.4    kleink 		return (EINVAL);
    110       1.4    kleink 
    111       1.4    kleink 	return (0);
    112       1.4    kleink }
    113       1.4    kleink 
    114       1.4    kleink int
    115       1.1   mycroft genfs_abortop(v)
    116       1.1   mycroft 	void *v;
    117       1.1   mycroft {
    118       1.1   mycroft 	struct vop_abortop_args /* {
    119       1.1   mycroft 		struct vnode *a_dvp;
    120       1.1   mycroft 		struct componentname *a_cnp;
    121       1.1   mycroft 	} */ *ap = v;
    122       1.1   mycroft 
    123       1.1   mycroft 	if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
    124       1.1   mycroft 		FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
    125       1.1   mycroft 	return (0);
    126       1.1   mycroft }
    127       1.1   mycroft 
    128       1.1   mycroft /*ARGSUSED*/
    129       1.1   mycroft int
    130       1.1   mycroft genfs_badop(v)
    131       1.1   mycroft 	void *v;
    132       1.1   mycroft {
    133       1.1   mycroft 
    134       1.1   mycroft 	panic("genfs: bad op");
    135       1.1   mycroft }
    136       1.1   mycroft 
    137       1.1   mycroft /*ARGSUSED*/
    138       1.1   mycroft int
    139       1.1   mycroft genfs_nullop(v)
    140       1.1   mycroft 	void *v;
    141       1.1   mycroft {
    142       1.1   mycroft 
    143       1.1   mycroft 	return (0);
    144      1.10    kleink }
    145      1.10    kleink 
    146      1.10    kleink /*ARGSUSED*/
    147      1.10    kleink int
    148      1.10    kleink genfs_einval(v)
    149      1.10    kleink 	void *v;
    150      1.10    kleink {
    151      1.10    kleink 
    152      1.10    kleink 	return (EINVAL);
    153       1.1   mycroft }
    154       1.1   mycroft 
    155       1.1   mycroft /*ARGSUSED*/
    156       1.1   mycroft int
    157       1.1   mycroft genfs_eopnotsupp(v)
    158       1.1   mycroft 	void *v;
    159       1.1   mycroft {
    160       1.1   mycroft 
    161       1.1   mycroft 	return (EOPNOTSUPP);
    162       1.1   mycroft }
    163       1.1   mycroft 
    164       1.1   mycroft /*ARGSUSED*/
    165       1.1   mycroft int
    166       1.1   mycroft genfs_ebadf(v)
    167       1.1   mycroft 	void *v;
    168       1.1   mycroft {
    169       1.1   mycroft 
    170       1.1   mycroft 	return (EBADF);
    171       1.9  matthias }
    172       1.9  matthias 
    173       1.9  matthias /* ARGSUSED */
    174       1.9  matthias int
    175       1.9  matthias genfs_enoioctl(v)
    176       1.9  matthias 	void *v;
    177       1.9  matthias {
    178       1.9  matthias 
    179       1.9  matthias 	return (ENOTTY);
    180       1.6      fvdl }
    181       1.6      fvdl 
    182       1.6      fvdl 
    183       1.6      fvdl /*
    184       1.6      fvdl  * Eliminate all activity associated with  the requested vnode
    185       1.6      fvdl  * and with all vnodes aliased to the requested vnode.
    186       1.6      fvdl  */
    187       1.6      fvdl int
    188       1.6      fvdl genfs_revoke(v)
    189       1.6      fvdl 	void *v;
    190       1.6      fvdl {
    191       1.6      fvdl 	struct vop_revoke_args /* {
    192       1.6      fvdl 		struct vnode *a_vp;
    193       1.6      fvdl 		int a_flags;
    194       1.6      fvdl 	} */ *ap = v;
    195       1.6      fvdl 	struct vnode *vp, *vq;
    196       1.6      fvdl 	struct proc *p = curproc;	/* XXX */
    197       1.6      fvdl 
    198       1.6      fvdl #ifdef DIAGNOSTIC
    199       1.6      fvdl 	if ((ap->a_flags & REVOKEALL) == 0)
    200       1.6      fvdl 		panic("genfs_revoke: not revokeall");
    201       1.6      fvdl #endif
    202       1.6      fvdl 
    203       1.6      fvdl 	vp = ap->a_vp;
    204       1.6      fvdl 	simple_lock(&vp->v_interlock);
    205       1.6      fvdl 
    206       1.6      fvdl 	if (vp->v_flag & VALIASED) {
    207       1.6      fvdl 		/*
    208       1.6      fvdl 		 * If a vgone (or vclean) is already in progress,
    209       1.6      fvdl 		 * wait until it is done and return.
    210       1.6      fvdl 		 */
    211       1.6      fvdl 		if (vp->v_flag & VXLOCK) {
    212       1.6      fvdl 			vp->v_flag |= VXWANT;
    213       1.6      fvdl 			simple_unlock(&vp->v_interlock);
    214       1.6      fvdl 			tsleep((caddr_t)vp, PINOD, "vop_revokeall", 0);
    215       1.6      fvdl 			return (0);
    216       1.6      fvdl 		}
    217       1.6      fvdl 		/*
    218       1.6      fvdl 		 * Ensure that vp will not be vgone'd while we
    219       1.6      fvdl 		 * are eliminating its aliases.
    220       1.6      fvdl 		 */
    221       1.6      fvdl 		vp->v_flag |= VXLOCK;
    222       1.6      fvdl 		simple_unlock(&vp->v_interlock);
    223       1.6      fvdl 		while (vp->v_flag & VALIASED) {
    224       1.6      fvdl 			simple_lock(&spechash_slock);
    225       1.6      fvdl 			for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
    226       1.6      fvdl 				if (vq->v_rdev != vp->v_rdev ||
    227       1.6      fvdl 				    vq->v_type != vp->v_type || vp == vq)
    228       1.6      fvdl 					continue;
    229       1.6      fvdl 				simple_unlock(&spechash_slock);
    230       1.6      fvdl 				vgone(vq);
    231       1.6      fvdl 				break;
    232       1.6      fvdl 			}
    233       1.6      fvdl 			if (vq == NULLVP)
    234       1.6      fvdl 				simple_unlock(&spechash_slock);
    235       1.6      fvdl 		}
    236       1.6      fvdl 		/*
    237       1.6      fvdl 		 * Remove the lock so that vgone below will
    238       1.6      fvdl 		 * really eliminate the vnode after which time
    239       1.6      fvdl 		 * vgone will awaken any sleepers.
    240       1.6      fvdl 		 */
    241       1.6      fvdl 		simple_lock(&vp->v_interlock);
    242       1.6      fvdl 		vp->v_flag &= ~VXLOCK;
    243       1.6      fvdl 	}
    244       1.6      fvdl 	vgonel(vp, p);
    245       1.6      fvdl 	return (0);
    246       1.6      fvdl }
    247       1.6      fvdl 
    248       1.6      fvdl 
    249       1.6      fvdl /*
    250       1.6      fvdl  * Stubs to use when there is no locking to be done on the underlying object.
    251       1.6      fvdl  * A minimal shared lock is necessary to ensure that the underlying object
    252       1.6      fvdl  * is not revoked while an operation is in progress. So, an active shared
    253       1.6      fvdl  * count is maintained in an auxillary vnode lock structure.
    254       1.6      fvdl  */
    255       1.6      fvdl int
    256       1.6      fvdl genfs_nolock(v)
    257       1.6      fvdl 	void *v;
    258       1.6      fvdl {
    259       1.6      fvdl 	struct vop_lock_args /* {
    260       1.6      fvdl 		struct vnode *a_vp;
    261       1.6      fvdl 		int a_flags;
    262       1.6      fvdl 		struct proc *a_p;
    263       1.6      fvdl 	} */ *ap = v;
    264       1.6      fvdl 
    265       1.6      fvdl #ifdef notyet
    266       1.6      fvdl 	/*
    267       1.6      fvdl 	 * This code cannot be used until all the non-locking filesystems
    268       1.6      fvdl 	 * (notably NFS) are converted to properly lock and release nodes.
    269       1.6      fvdl 	 * Also, certain vnode operations change the locking state within
    270       1.6      fvdl 	 * the operation (create, mknod, remove, link, rename, mkdir, rmdir,
    271       1.6      fvdl 	 * and symlink). Ideally these operations should not change the
    272       1.6      fvdl 	 * lock state, but should be changed to let the caller of the
    273       1.6      fvdl 	 * function unlock them. Otherwise all intermediate vnode layers
    274       1.6      fvdl 	 * (such as union, umapfs, etc) must catch these functions to do
    275       1.6      fvdl 	 * the necessary locking at their layer. Note that the inactive
    276       1.6      fvdl 	 * and lookup operations also change their lock state, but this
    277       1.6      fvdl 	 * cannot be avoided, so these two operations will always need
    278       1.6      fvdl 	 * to be handled in intermediate layers.
    279       1.6      fvdl 	 */
    280       1.6      fvdl 	struct vnode *vp = ap->a_vp;
    281       1.6      fvdl 	int vnflags, flags = ap->a_flags;
    282       1.6      fvdl 
    283       1.6      fvdl 	if (vp->v_vnlock == NULL) {
    284       1.6      fvdl 		if ((flags & LK_TYPE_MASK) == LK_DRAIN)
    285       1.6      fvdl 			return (0);
    286       1.6      fvdl 		MALLOC(vp->v_vnlock, struct lock *, sizeof(struct lock),
    287       1.6      fvdl 		    M_VNODE, M_WAITOK);
    288       1.6      fvdl 		lockinit(vp->v_vnlock, PVFS, "vnlock", 0, 0);
    289       1.6      fvdl 	}
    290       1.6      fvdl 	switch (flags & LK_TYPE_MASK) {
    291       1.6      fvdl 	case LK_DRAIN:
    292       1.6      fvdl 		vnflags = LK_DRAIN;
    293       1.6      fvdl 		break;
    294       1.6      fvdl 	case LK_EXCLUSIVE:
    295       1.6      fvdl 	case LK_SHARED:
    296       1.6      fvdl 		vnflags = LK_SHARED;
    297       1.6      fvdl 		break;
    298       1.6      fvdl 	case LK_UPGRADE:
    299       1.6      fvdl 	case LK_EXCLUPGRADE:
    300       1.6      fvdl 	case LK_DOWNGRADE:
    301       1.6      fvdl 		return (0);
    302       1.6      fvdl 	case LK_RELEASE:
    303       1.6      fvdl 	default:
    304       1.6      fvdl 		panic("vop_nolock: bad operation %d", flags & LK_TYPE_MASK);
    305       1.6      fvdl 	}
    306       1.6      fvdl 	if (flags & LK_INTERLOCK)
    307       1.6      fvdl 		vnflags |= LK_INTERLOCK;
    308       1.6      fvdl 	return(lockmgr(vp->v_vnlock, vnflags, &vp->v_interlock));
    309       1.6      fvdl #else /* for now */
    310       1.6      fvdl 	/*
    311       1.6      fvdl 	 * Since we are not using the lock manager, we must clear
    312       1.6      fvdl 	 * the interlock here.
    313       1.6      fvdl 	 */
    314       1.6      fvdl 	if (ap->a_flags & LK_INTERLOCK)
    315       1.6      fvdl 		simple_unlock(&ap->a_vp->v_interlock);
    316       1.6      fvdl 	return (0);
    317       1.6      fvdl #endif
    318       1.6      fvdl }
    319       1.6      fvdl 
    320       1.6      fvdl /*
    321       1.6      fvdl  * Decrement the active use count.
    322       1.6      fvdl  */
    323       1.6      fvdl int
    324       1.6      fvdl genfs_nounlock(v)
    325       1.6      fvdl 	void *v;
    326       1.6      fvdl {
    327       1.6      fvdl 	struct vop_unlock_args /* {
    328       1.6      fvdl 		struct vnode *a_vp;
    329       1.6      fvdl 		int a_flags;
    330       1.6      fvdl 		struct proc *a_p;
    331       1.6      fvdl 	} */ *ap = v;
    332       1.6      fvdl 	struct vnode *vp = ap->a_vp;
    333       1.6      fvdl 
    334       1.6      fvdl 	if (vp->v_vnlock == NULL)
    335       1.6      fvdl 		return (0);
    336       1.6      fvdl 	return (lockmgr(vp->v_vnlock, LK_RELEASE, NULL));
    337       1.6      fvdl }
    338       1.6      fvdl 
    339       1.6      fvdl /*
    340       1.6      fvdl  * Return whether or not the node is in use.
    341       1.6      fvdl  */
    342       1.6      fvdl int
    343       1.6      fvdl genfs_noislocked(v)
    344       1.6      fvdl 	void *v;
    345       1.6      fvdl {
    346       1.6      fvdl 	struct vop_islocked_args /* {
    347       1.6      fvdl 		struct vnode *a_vp;
    348       1.6      fvdl 	} */ *ap = v;
    349       1.6      fvdl 	struct vnode *vp = ap->a_vp;
    350       1.6      fvdl 
    351       1.6      fvdl 	if (vp->v_vnlock == NULL)
    352       1.6      fvdl 		return (0);
    353       1.6      fvdl 	return (lockstatus(vp->v_vnlock));
    354       1.8   thorpej }
    355       1.8   thorpej 
    356       1.8   thorpej /*
    357       1.8   thorpej  * Local lease check for NFS servers.  Just set up args and let
    358       1.8   thorpej  * nqsrv_getlease() do the rest.  If NFSSERVER is not in the kernel,
    359       1.8   thorpej  * this is a null operation.
    360       1.8   thorpej  */
    361       1.8   thorpej int
    362       1.8   thorpej genfs_lease_check(v)
    363       1.8   thorpej 	void *v;
    364       1.8   thorpej {
    365       1.8   thorpej #ifdef NFSSERVER
    366       1.8   thorpej 	struct vop_lease_args /* {
    367       1.8   thorpej 		struct vnode *a_vp;
    368       1.8   thorpej 		struct proc *a_p;
    369       1.8   thorpej 		struct ucred *a_cred;
    370       1.8   thorpej 		int a_flag;
    371       1.8   thorpej 	} */ *ap = v;
    372       1.8   thorpej 	u_int32_t duration = 0;
    373       1.8   thorpej 	int cache;
    374       1.8   thorpej 	u_quad_t frev;
    375       1.8   thorpej 
    376       1.8   thorpej 	(void) nqsrv_getlease(ap->a_vp, &duration, ND_CHECK | ap->a_flag,
    377       1.8   thorpej 	    NQLOCALSLP, ap->a_p, (struct mbuf *)0, &cache, &frev, ap->a_cred);
    378       1.8   thorpej 	return (0);
    379       1.8   thorpej #else
    380       1.8   thorpej 	return (0);
    381       1.8   thorpej #endif /* NFSSERVER */
    382  1.11.4.1       chs }
    383  1.11.4.1       chs 
    384  1.11.4.1       chs 
    385  1.11.4.1       chs /*
    386  1.11.4.1       chs  * generic VM getpages routine.
    387  1.11.4.1       chs  * Return PG_BUSY pages for the given range,
    388  1.11.4.1       chs  * reading from backing store if necessary.
    389  1.11.4.1       chs  */
    390  1.11.4.1       chs int
    391  1.11.4.1       chs genfs_getpages(v)
    392  1.11.4.1       chs 	void *v;
    393  1.11.4.1       chs {
    394  1.11.4.1       chs 	struct vop_getpages_args /* {
    395  1.11.4.1       chs 		struct vnode *a_vp;
    396  1.11.4.1       chs 		vaddr_t a_offset;
    397  1.11.4.1       chs 		vm_page_t *a_m;
    398  1.11.4.1       chs 		int *a_count;
    399  1.11.4.1       chs 		int a_centeridx;
    400  1.11.4.1       chs 		vm_prot_t a_access_type;
    401  1.11.4.1       chs 		int a_advice;
    402  1.11.4.1       chs 		int a_flags;
    403  1.11.4.1       chs 	} */ *ap = v;
    404  1.11.4.1       chs 
    405  1.11.4.2       chs 	off_t offset, origoffset, startoffset;
    406  1.11.4.1       chs 	daddr_t lbn, blkno;
    407  1.11.4.2       chs 	int s, i, error, npages, run, cidx, pidx, pcount;
    408  1.11.4.2       chs 	int bsize, bshift, dev_bshift, dev_bsize;
    409  1.11.4.1       chs 	int flags = ap->a_flags;
    410  1.11.4.2       chs 	size_t bytes, iobytes, tailbytes, totalbytes, skipbytes;
    411  1.11.4.2       chs 	boolean_t sawhole = FALSE;
    412  1.11.4.1       chs 	char *kva;
    413  1.11.4.1       chs 	struct buf *bp, *mbp;
    414  1.11.4.1       chs 	struct vnode *vp = ap->a_vp;
    415  1.11.4.1       chs 	struct uvm_object *uobj = &vp->v_uvm.u_obj;
    416  1.11.4.2       chs 	struct vm_page *pg, *pgs[16];			/* XXX 16 */
    417  1.11.4.2       chs 	struct ucred *cred = curproc->p_ucred;		/* XXX curproc */
    418  1.11.4.1       chs 	UVMHIST_FUNC("genfs_getpages"); UVMHIST_CALLED(ubchist);
    419  1.11.4.1       chs 
    420  1.11.4.1       chs #ifdef DIAGNOSTIC
    421  1.11.4.1       chs 	if (ap->a_centeridx < 0 || ap->a_centeridx > *ap->a_count) {
    422  1.11.4.1       chs 		panic("genfs_getpages: centeridx %d out of range",
    423  1.11.4.1       chs 		      ap->a_centeridx);
    424  1.11.4.1       chs 	}
    425  1.11.4.1       chs 	if (ap->a_offset & (PAGE_SIZE - 1)) {
    426  1.11.4.1       chs 		panic("genfs_getpages: offset 0x%x", (int)ap->a_offset);
    427  1.11.4.1       chs 	}
    428  1.11.4.1       chs #endif
    429  1.11.4.1       chs 
    430  1.11.4.1       chs 	/*
    431  1.11.4.1       chs 	 * Bounds-check the request.
    432  1.11.4.1       chs 	 */
    433  1.11.4.1       chs 
    434  1.11.4.1       chs 	if (ap->a_offset >= vp->v_uvm.u_size) {
    435  1.11.4.1       chs 		if ((flags & PGO_LOCKED) == 0) {
    436  1.11.4.1       chs 			simple_unlock(&uobj->vmobjlock);
    437  1.11.4.1       chs 		}
    438  1.11.4.2       chs 		UVMHIST_LOG(ubchist, "off 0x%x past EOF 0x%x",
    439  1.11.4.2       chs 			    (int)ap->a_offset, (int)vp->v_uvm.u_size,0,0);
    440  1.11.4.2       chs 		return EINVAL;
    441  1.11.4.1       chs 	}
    442  1.11.4.1       chs 
    443  1.11.4.1       chs 	/*
    444  1.11.4.1       chs 	 * For PGO_LOCKED requests, just return whatever's in memory.
    445  1.11.4.1       chs 	 */
    446  1.11.4.1       chs 
    447  1.11.4.1       chs 	if (flags & PGO_LOCKED) {
    448  1.11.4.1       chs 		uvn_findpages(uobj, ap->a_offset, ap->a_count, ap->a_m,
    449  1.11.4.1       chs 			      UFP_NOWAIT|UFP_NOALLOC|UFP_NORDONLY);
    450  1.11.4.1       chs 
    451  1.11.4.2       chs 		return ap->a_m[ap->a_centeridx] == NULL ? EBUSY : 0;
    452  1.11.4.1       chs 	}
    453  1.11.4.1       chs 
    454  1.11.4.1       chs 	/* vnode is VOP_LOCKed, uobj is locked */
    455  1.11.4.1       chs 
    456  1.11.4.1       chs 	error = 0;
    457  1.11.4.1       chs 
    458  1.11.4.1       chs 	/*
    459  1.11.4.2       chs 	 * find our center page and make some simple checks.
    460  1.11.4.1       chs 	 */
    461  1.11.4.1       chs 
    462  1.11.4.2       chs 	origoffset = ap->a_offset + (ap->a_centeridx << PAGE_SHIFT);
    463  1.11.4.2       chs 	pg = NULL;
    464  1.11.4.2       chs 	npages = 1;
    465  1.11.4.2       chs 	uvn_findpages(uobj, origoffset, &npages, &pg, 0);
    466  1.11.4.2       chs 
    467  1.11.4.1       chs 	/*
    468  1.11.4.2       chs 	 * if PGO_OVERWRITE is set, don't bother reading the page.
    469  1.11.4.2       chs 	 * PGO_OVERWRITE also means that the caller guarantees
    470  1.11.4.2       chs 	 * that the page already has backing store allocated.
    471  1.11.4.1       chs 	 */
    472  1.11.4.1       chs 
    473  1.11.4.2       chs 	if (flags & PGO_OVERWRITE) {
    474  1.11.4.2       chs 		UVMHIST_LOG(ubchist, "PGO_OVERWRITE",0,0,0,0);
    475  1.11.4.1       chs 
    476  1.11.4.2       chs 		/* XXX for now, zero the page if we allocated it */
    477  1.11.4.2       chs 		if (pg->flags & PG_FAKE) {
    478  1.11.4.2       chs 			uvm_pagezero(pg);
    479  1.11.4.2       chs 		}
    480  1.11.4.1       chs 
    481  1.11.4.2       chs 		simple_unlock(&uobj->vmobjlock);
    482  1.11.4.3       chs 		pgs[0] = pg;
    483  1.11.4.2       chs 		goto out;
    484  1.11.4.2       chs 	}
    485  1.11.4.1       chs 
    486  1.11.4.1       chs 	/*
    487  1.11.4.1       chs 	 * if the page is already resident, just return it.
    488  1.11.4.1       chs 	 */
    489  1.11.4.1       chs 
    490  1.11.4.1       chs 	if ((pg->flags & PG_FAKE) == 0 &&
    491  1.11.4.2       chs 	    !((ap->a_access_type & VM_PROT_WRITE) &&
    492  1.11.4.2       chs 	      (pg->flags & PG_RDONLY))) {
    493  1.11.4.2       chs 		UVMHIST_LOG(ubchist, "returning cached pg %p", pg,0,0,0);
    494  1.11.4.3       chs 
    495  1.11.4.2       chs 		simple_unlock(&uobj->vmobjlock);
    496  1.11.4.3       chs 		pgs[0] = pg;
    497  1.11.4.3       chs 		goto out;
    498  1.11.4.1       chs 	}
    499  1.11.4.1       chs 
    500  1.11.4.1       chs 	/*
    501  1.11.4.2       chs 	 * the page wasn't resident and we're not overwriting,
    502  1.11.4.2       chs 	 * so we're going to have to do some i/o.
    503  1.11.4.2       chs 	 * expand the fault to cover at least 1 block.
    504  1.11.4.1       chs 	 */
    505  1.11.4.1       chs 
    506  1.11.4.2       chs 	bshift = vp->v_mount->mnt_fs_bshift;
    507  1.11.4.2       chs 	bsize = 1 << bshift;
    508  1.11.4.2       chs 	dev_bshift = vp->v_mount->mnt_dev_bshift;
    509  1.11.4.2       chs 	dev_bsize = 1 << dev_bshift;
    510  1.11.4.1       chs 
    511  1.11.4.2       chs 	startoffset = offset = origoffset & ~(bsize - 1);
    512  1.11.4.2       chs 	cidx = (origoffset - offset) >> PAGE_SHIFT;
    513  1.11.4.2       chs 	npages = max(*ap->a_count + cidx, bsize >> PAGE_SHIFT);
    514  1.11.4.2       chs 
    515  1.11.4.2       chs 	if (npages == 1) {
    516  1.11.4.2       chs 		pgs[0] = pg;
    517  1.11.4.2       chs 	} else {
    518  1.11.4.2       chs 		int n = npages;
    519  1.11.4.2       chs 		memset(pgs, 0, sizeof(pgs));
    520  1.11.4.2       chs 		pgs[cidx] = PGO_DONTCARE;
    521  1.11.4.2       chs 		uvn_findpages(uobj, offset, &n, pgs, 0);
    522  1.11.4.2       chs 		pgs[cidx] = pg;
    523  1.11.4.1       chs 	}
    524  1.11.4.2       chs 	simple_unlock(&uobj->vmobjlock);
    525  1.11.4.1       chs 
    526  1.11.4.1       chs 	/*
    527  1.11.4.2       chs 	 * read the desired page(s).
    528  1.11.4.1       chs 	 */
    529  1.11.4.1       chs 
    530  1.11.4.2       chs 	totalbytes = npages << PAGE_SHIFT;
    531  1.11.4.2       chs 	bytes = min(totalbytes, (vp->v_uvm.u_size - offset + dev_bsize - 1) &
    532  1.11.4.1       chs 		    ~(dev_bsize - 1));
    533  1.11.4.2       chs 	tailbytes = totalbytes - bytes;
    534  1.11.4.2       chs 	skipbytes = 0;
    535  1.11.4.1       chs 
    536  1.11.4.2       chs 	kva = (void *)uvm_pagermapin(pgs, npages, M_WAITOK);
    537  1.11.4.1       chs 
    538  1.11.4.1       chs 	s = splbio();
    539  1.11.4.1       chs 	mbp = pool_get(&bufpool, PR_WAITOK);
    540  1.11.4.1       chs 	splx(s);
    541  1.11.4.1       chs 	mbp->b_bufsize = bytes;
    542  1.11.4.1       chs 	mbp->b_data = (void *)kva;
    543  1.11.4.2       chs 	mbp->b_resid = mbp->b_bcount = bytes;
    544  1.11.4.1       chs 	mbp->b_flags = B_BUSY|B_READ| (flags & PGO_SYNCIO ? 0 : B_CALL);
    545  1.11.4.1       chs 	mbp->b_iodone = uvm_aio_biodone;
    546  1.11.4.1       chs 	mbp->b_vp = vp;
    547  1.11.4.1       chs 
    548  1.11.4.1       chs 	bp = NULL;
    549  1.11.4.1       chs 	for (; bytes > 0; offset += iobytes, bytes -= iobytes) {
    550  1.11.4.2       chs 
    551  1.11.4.2       chs 		/*
    552  1.11.4.2       chs 		 * skip pages which don't need to be read.
    553  1.11.4.2       chs 		 */
    554  1.11.4.2       chs 
    555  1.11.4.2       chs 		pidx = (offset - startoffset) >> PAGE_SHIFT;
    556  1.11.4.2       chs 		while ((pgs[pidx]->flags & PG_FAKE) == 0) {
    557  1.11.4.2       chs 			size_t b;
    558  1.11.4.2       chs 
    559  1.11.4.2       chs 			if (offset & (PAGE_SIZE - 1)) {
    560  1.11.4.2       chs 				panic("genfs_getpages: skipping from middle "
    561  1.11.4.2       chs 				      "of page");
    562  1.11.4.2       chs 			}
    563  1.11.4.2       chs 
    564  1.11.4.2       chs 			b = min(PAGE_SIZE, bytes);
    565  1.11.4.2       chs 			offset += b;
    566  1.11.4.2       chs 			bytes -= b;
    567  1.11.4.2       chs 			skipbytes += b;
    568  1.11.4.2       chs 			pidx++;
    569  1.11.4.2       chs 			if (bytes == 0) {
    570  1.11.4.2       chs 				goto loopdone;
    571  1.11.4.2       chs 			}
    572  1.11.4.2       chs 		}
    573  1.11.4.1       chs 
    574  1.11.4.1       chs 		/*
    575  1.11.4.1       chs 		 * bmap the file to find out the blkno to read from and
    576  1.11.4.1       chs 		 * how much we can read in one i/o.
    577  1.11.4.1       chs 		 */
    578  1.11.4.1       chs 
    579  1.11.4.2       chs 		lbn = offset >> bshift;
    580  1.11.4.1       chs 		error = VOP_BMAP(vp, lbn, NULL, &blkno, &run);
    581  1.11.4.1       chs 		if (error) {
    582  1.11.4.1       chs 			UVMHIST_LOG(ubchist, "VOP_BMAP lbn 0x%x -> %d\n",
    583  1.11.4.1       chs 				    lbn, error,0,0);
    584  1.11.4.3       chs 			goto looperr;
    585  1.11.4.1       chs 		}
    586  1.11.4.1       chs 
    587  1.11.4.2       chs 		/*
    588  1.11.4.2       chs 		 * see how many pages need to be read with this i/o.
    589  1.11.4.2       chs 		 * reduce the i/o size if necessary.
    590  1.11.4.2       chs 		 */
    591  1.11.4.1       chs 
    592  1.11.4.2       chs 		iobytes = min(((lbn + 1 + run) << bshift) - offset, bytes);
    593  1.11.4.2       chs 		if (offset + iobytes > round_page(offset)) {
    594  1.11.4.2       chs 			pcount = 1;
    595  1.11.4.2       chs 			while (pidx + pcount < npages &&
    596  1.11.4.2       chs 			       pgs[pidx + pcount]->flags & PG_FAKE) {
    597  1.11.4.2       chs 				pcount++;
    598  1.11.4.1       chs 			}
    599  1.11.4.2       chs 			iobytes = min(iobytes, (pcount << PAGE_SHIFT) -
    600  1.11.4.2       chs 				      (offset - trunc_page(offset)));
    601  1.11.4.2       chs 		}
    602  1.11.4.1       chs 
    603  1.11.4.2       chs 		/*
    604  1.11.4.2       chs 		 * if this block isn't allocated, zero it instead of reading it.
    605  1.11.4.2       chs 		 */
    606  1.11.4.1       chs 
    607  1.11.4.2       chs 		if (blkno == (daddr_t)-1) {
    608  1.11.4.2       chs 			UVMHIST_LOG(ubchist, "lbn 0x%x -> HOLE", lbn,0,0,0);
    609  1.11.4.1       chs 
    610  1.11.4.2       chs 			sawhole = TRUE;
    611  1.11.4.2       chs 			memset(kva + (offset - startoffset), 0,
    612  1.11.4.2       chs 			       min(1 << bshift, (npages << PAGE_SHIFT) -
    613  1.11.4.2       chs 				   (offset - startoffset)));
    614  1.11.4.1       chs 			continue;
    615  1.11.4.1       chs 		}
    616  1.11.4.1       chs 
    617  1.11.4.1       chs 		/*
    618  1.11.4.1       chs 		 * allocate a sub-buf for this piece of the i/o
    619  1.11.4.1       chs 		 * (or just use mbp if there's only 1 piece),
    620  1.11.4.1       chs 		 * and start it going.
    621  1.11.4.1       chs 		 */
    622  1.11.4.1       chs 
    623  1.11.4.1       chs 		if (bp == NULL && iobytes == bytes) {
    624  1.11.4.1       chs 			bp = mbp;
    625  1.11.4.1       chs 		} else {
    626  1.11.4.1       chs 			s = splbio();
    627  1.11.4.1       chs 			bp = pool_get(&bufpool, PR_WAITOK);
    628  1.11.4.1       chs 			splx(s);
    629  1.11.4.1       chs 			bp->b_data = (void *)(kva + offset - pg->offset);
    630  1.11.4.2       chs 			bp->b_resid = bp->b_bcount = iobytes;
    631  1.11.4.1       chs 			bp->b_flags = B_BUSY|B_READ|B_CALL;
    632  1.11.4.1       chs 			bp->b_iodone = uvm_aio_biodone1;
    633  1.11.4.1       chs 			bp->b_vp = vp;
    634  1.11.4.1       chs 		}
    635  1.11.4.1       chs 		bp->b_lblkno = 0;
    636  1.11.4.1       chs 		bp->b_private = mbp;
    637  1.11.4.1       chs 
    638  1.11.4.1       chs 		/* adjust physical blkno for partial blocks */
    639  1.11.4.1       chs 		bp->b_blkno = blkno + ((offset - (lbn << bshift)) >>
    640  1.11.4.1       chs 				       dev_bshift);
    641  1.11.4.2       chs 
    642  1.11.4.2       chs 		UVMHIST_LOG(ubchist, "bp %p offset 0x%x bcount 0x%x blkno 0x%x",
    643  1.11.4.2       chs 			    bp, (int)offset, (int)iobytes, bp->b_blkno);
    644  1.11.4.1       chs 
    645  1.11.4.1       chs 		VOP_STRATEGY(bp);
    646  1.11.4.1       chs 	}
    647  1.11.4.2       chs loopdone:
    648  1.11.4.2       chs 
    649  1.11.4.2       chs 	if (skipbytes) {
    650  1.11.4.2       chs 		s = splbio();
    651  1.11.4.2       chs 		mbp->b_resid -= skipbytes;
    652  1.11.4.2       chs 		if (mbp->b_resid == 0) {
    653  1.11.4.2       chs 			biodone(mbp);
    654  1.11.4.2       chs 		}
    655  1.11.4.2       chs 		splx(s);
    656  1.11.4.2       chs 	}
    657  1.11.4.1       chs 
    658  1.11.4.1       chs 	/*
    659  1.11.4.1       chs 	 * if EOF is in the middle of this page, zero the part past EOF.
    660  1.11.4.1       chs 	 */
    661  1.11.4.1       chs 
    662  1.11.4.1       chs 	if (tailbytes > 0) {
    663  1.11.4.1       chs 		memset(kva + (offset - origoffset), 0, tailbytes);
    664  1.11.4.1       chs 	}
    665  1.11.4.1       chs 
    666  1.11.4.3       chs looperr:
    667  1.11.4.1       chs 	if ((flags & PGO_SYNCIO) == 0) {
    668  1.11.4.2       chs 		UVMHIST_LOG(ubchist, "returning PEND",0,0,0,0);
    669  1.11.4.2       chs 		return EINPROGRESS;
    670  1.11.4.1       chs 	}
    671  1.11.4.1       chs 	if (bp != NULL) {
    672  1.11.4.1       chs 		error = biowait(mbp);
    673  1.11.4.1       chs 	}
    674  1.11.4.1       chs 	s = splbio();
    675  1.11.4.1       chs 	pool_put(&bufpool, mbp);
    676  1.11.4.1       chs 	splx(s);
    677  1.11.4.2       chs 	uvm_pagermapout((vaddr_t)kva, npages);
    678  1.11.4.2       chs 
    679  1.11.4.2       chs 	/*
    680  1.11.4.2       chs 	 * if this we encountered a hole then we have to do a little more work.
    681  1.11.4.2       chs 	 * for read faults, we must mark the page PG_RDONLY so that future
    682  1.11.4.2       chs 	 * write accesses to the page will fault again.
    683  1.11.4.2       chs 	 * for write faults, we must make sure that the backing store for
    684  1.11.4.2       chs 	 * the page is completely allocated.
    685  1.11.4.2       chs 	 */
    686  1.11.4.2       chs 
    687  1.11.4.2       chs 	if (sawhole) {
    688  1.11.4.2       chs 		if ((ap->a_access_type & VM_PROT_WRITE) == 0) {
    689  1.11.4.2       chs 			pg->flags |= PG_RDONLY;
    690  1.11.4.2       chs 			UVMHIST_LOG(ubchist, "setting PG_RDONLY",
    691  1.11.4.2       chs 				    0,0,0,0);
    692  1.11.4.2       chs 		} else {
    693  1.11.4.2       chs 			/* XXX loop VOP_BALLOC() over the page/block */
    694  1.11.4.2       chs 			error = VOP_BALLOC(vp, offset, bsize, cred, 0, NULL);
    695  1.11.4.2       chs 			if (error) {
    696  1.11.4.2       chs 				UVMHIST_LOG(ubchist, "balloc lbn 0x%x -> %d",
    697  1.11.4.2       chs 					    lbn, error,0,0);
    698  1.11.4.2       chs 				goto out;
    699  1.11.4.2       chs 			}
    700  1.11.4.2       chs 		}
    701  1.11.4.2       chs 	}
    702  1.11.4.2       chs 
    703  1.11.4.2       chs 	/*
    704  1.11.4.2       chs 	 * see if we want to start any readahead.
    705  1.11.4.2       chs 	 * XXX writeme
    706  1.11.4.2       chs 	 */
    707  1.11.4.2       chs 
    708  1.11.4.2       chs 	/*
    709  1.11.4.2       chs 	 * we're almost done!  release the pages...
    710  1.11.4.2       chs 	 * for errors, we free the pages.
    711  1.11.4.2       chs 	 * otherwise we activate them and mark them as valid and clean.
    712  1.11.4.2       chs 	 * also, unbusy all but the center page.
    713  1.11.4.2       chs 	 */
    714  1.11.4.1       chs 
    715  1.11.4.1       chs out:
    716  1.11.4.1       chs 	if (error) {
    717  1.11.4.1       chs 		simple_lock(&uobj->vmobjlock);
    718  1.11.4.2       chs 		for (i = 0; i < npages; i++) {
    719  1.11.4.2       chs 			UVMHIST_LOG(ubchist, "examining pg %p flags 0x%x",
    720  1.11.4.2       chs 				    pgs[i], pgs[i]->flags, 0,0);
    721  1.11.4.2       chs 			if (pgs[i]->flags & PG_FAKE) {
    722  1.11.4.2       chs 				if (pgs[i]->flags & PG_WANTED) {
    723  1.11.4.2       chs 					wakeup(pgs[i]);
    724  1.11.4.2       chs 				}
    725  1.11.4.2       chs 				uvm_pagefree(pgs[i]);
    726  1.11.4.2       chs 			}
    727  1.11.4.1       chs 		}
    728  1.11.4.1       chs 		simple_unlock(&uobj->vmobjlock);
    729  1.11.4.2       chs 		UVMHIST_LOG(ubchist, "returning error %d", error,0,0,0);
    730  1.11.4.2       chs 		return error;
    731  1.11.4.1       chs 	}
    732  1.11.4.2       chs 
    733  1.11.4.2       chs 	UVMHIST_LOG(ubchist, "succeeding, npages %d", npages,0,0,0);
    734  1.11.4.2       chs 	simple_lock(&uobj->vmobjlock);
    735  1.11.4.2       chs 	for (i = 0; i < npages; i++) {
    736  1.11.4.2       chs 		UVMHIST_LOG(ubchist, "examining pg %p flags 0x%x",
    737  1.11.4.2       chs 			    pgs[i], pgs[i]->flags, 0,0);
    738  1.11.4.2       chs 		if (pgs[i]->flags & PG_FAKE) {
    739  1.11.4.2       chs 			UVMHIST_LOG(ubchist, "unfaking pg %p offset 0x%x",
    740  1.11.4.2       chs 				    pgs[i], (int)pgs[i]->offset,0,0);
    741  1.11.4.2       chs 			pgs[i]->flags &= ~(PG_FAKE);
    742  1.11.4.2       chs 			pmap_clear_modify(PMAP_PGARG(pgs[i]));
    743  1.11.4.2       chs 			pmap_clear_reference(PMAP_PGARG(pgs[i]));
    744  1.11.4.2       chs 		}
    745  1.11.4.2       chs 		if (pgs[i] != pg) {
    746  1.11.4.2       chs 			UVMHIST_LOG(ubchist, "unbusy pg %p offset 0x%x",
    747  1.11.4.2       chs 				    pgs[i], (int)pgs[i]->offset,0,0);
    748  1.11.4.2       chs 			/*
    749  1.11.4.2       chs 			KASSERT((pgs[i]->flags & PG_RELEASED) == 0);
    750  1.11.4.2       chs 			*/
    751  1.11.4.2       chs 
    752  1.11.4.2       chs 			if (pgs[i]->flags & PG_WANTED) {
    753  1.11.4.2       chs 				wakeup(pgs[i]);
    754  1.11.4.2       chs 			}
    755  1.11.4.2       chs 			pgs[i]->flags &= ~(PG_WANTED|PG_BUSY);
    756  1.11.4.2       chs 			UVM_PAGE_OWN(pgs[i], NULL);
    757  1.11.4.2       chs 		}
    758  1.11.4.2       chs 	}
    759  1.11.4.2       chs 	simple_unlock(&uobj->vmobjlock);
    760  1.11.4.2       chs 	ap->a_m[ap->a_centeridx] = pg;
    761  1.11.4.2       chs 	return 0;
    762  1.11.4.1       chs }
    763  1.11.4.1       chs 
    764  1.11.4.1       chs /*
    765  1.11.4.1       chs  * generic VM putpages routine.
    766  1.11.4.1       chs  * Write the given range of pages to backing store.
    767  1.11.4.1       chs  */
    768  1.11.4.1       chs int
    769  1.11.4.1       chs genfs_putpages(v)
    770  1.11.4.1       chs 	void *v;
    771  1.11.4.1       chs {
    772  1.11.4.1       chs 	struct vop_putpages_args /* {
    773  1.11.4.1       chs 		struct vnode *a_vp;
    774  1.11.4.1       chs 		struct vm_page **a_m;
    775  1.11.4.1       chs 		int a_count;
    776  1.11.4.1       chs 		int a_sync;
    777  1.11.4.1       chs 		int *a_rtvals;
    778  1.11.4.1       chs 	} */ *ap = v;
    779  1.11.4.1       chs 
    780  1.11.4.1       chs 	int s, error, bshift, dev_bshift, dev_bsize, run;
    781  1.11.4.1       chs 	vaddr_t kva;
    782  1.11.4.1       chs 	off_t offset;
    783  1.11.4.1       chs 	size_t bytes, iobytes;
    784  1.11.4.1       chs 	daddr_t lbn, blkno;
    785  1.11.4.1       chs 	struct vm_page *pg;
    786  1.11.4.1       chs 	struct buf *mbp, *bp;
    787  1.11.4.1       chs 	struct vnode *vp = ap->a_vp;
    788  1.11.4.1       chs 	UVMHIST_FUNC("genfs_putpages"); UVMHIST_CALLED(ubchist);
    789  1.11.4.1       chs 
    790  1.11.4.2       chs 	error = 0;
    791  1.11.4.1       chs 	bshift = vp->v_mount->mnt_fs_bshift;
    792  1.11.4.1       chs 	dev_bshift = vp->v_mount->mnt_dev_bshift;
    793  1.11.4.1       chs 	dev_bsize = 1 << dev_bshift;
    794  1.11.4.1       chs 
    795  1.11.4.1       chs 	pg = ap->a_m[0];
    796  1.11.4.1       chs 	offset = pg->offset;
    797  1.11.4.1       chs 	bytes = min(ap->a_count << PAGE_SHIFT,
    798  1.11.4.1       chs 		    (vp->v_uvm.u_size - offset + dev_bsize - 1) &
    799  1.11.4.1       chs 		    ~(dev_bsize - 1));
    800  1.11.4.1       chs 
    801  1.11.4.2       chs 	kva = uvm_pagermapin(ap->a_m, ap->a_count, M_WAITOK);
    802  1.11.4.2       chs 
    803  1.11.4.1       chs 	s = splbio();
    804  1.11.4.1       chs 	vp->v_numoutput++;
    805  1.11.4.1       chs 	mbp = pool_get(&bufpool, PR_WAITOK);
    806  1.11.4.1       chs 	splx(s);
    807  1.11.4.1       chs 	mbp->b_bufsize = ap->a_count << PAGE_SHIFT;
    808  1.11.4.1       chs 	mbp->b_data = (void *)kva;
    809  1.11.4.2       chs 	mbp->b_resid = mbp->b_bcount = bytes;
    810  1.11.4.1       chs 	mbp->b_flags = B_BUSY|B_WRITE| (ap->a_sync ? 0 : B_CALL) |
    811  1.11.4.1       chs 		(curproc == uvm.pagedaemon_proc ? B_PDAEMON : 0);
    812  1.11.4.1       chs 
    813  1.11.4.1       chs 	mbp->b_iodone = uvm_aio_biodone;
    814  1.11.4.1       chs 	mbp->b_vp = vp;
    815  1.11.4.1       chs 
    816  1.11.4.1       chs 	bp = NULL;
    817  1.11.4.1       chs 	for (; bytes > 0; offset += iobytes, bytes -= iobytes) {
    818  1.11.4.1       chs 		lbn = offset >> bshift;
    819  1.11.4.1       chs 		error = VOP_BMAP(vp, lbn, NULL, &blkno, &run);
    820  1.11.4.1       chs 		if (error) {
    821  1.11.4.2       chs 			UVMHIST_LOG(ubchist, "VOP_BALLOC() -> %d", error,0,0,0);
    822  1.11.4.1       chs 			goto errout;
    823  1.11.4.1       chs 		}
    824  1.11.4.1       chs 
    825  1.11.4.1       chs 		/* this could be ifdef DIAGNOSTIC, but it's really important */
    826  1.11.4.1       chs 		if (blkno == (daddr_t)-1) {
    827  1.11.4.2       chs 			panic("genfs_putpages: no backing store "
    828  1.11.4.2       chs 			      "vp %p off 0x%x lbn 0x%x",
    829  1.11.4.2       chs 			      vp, (int)offset, lbn);
    830  1.11.4.1       chs 		}
    831  1.11.4.1       chs 
    832  1.11.4.1       chs 		/* if it's really one i/o, don't make a second buf */
    833  1.11.4.1       chs 		iobytes = min(((lbn + 1 + run) << bshift) - offset, bytes);
    834  1.11.4.1       chs 		if (bp == NULL && iobytes == bytes) {
    835  1.11.4.1       chs 			bp = mbp;
    836  1.11.4.1       chs 		} else {
    837  1.11.4.1       chs 			s = splbio();
    838  1.11.4.1       chs 			vp->v_numoutput++;
    839  1.11.4.1       chs 			bp = pool_get(&bufpool, PR_WAITOK);
    840  1.11.4.1       chs 			splx(s);
    841  1.11.4.1       chs 			bp->b_data = (char *)kva +
    842  1.11.4.1       chs 				(vsize_t)(offset - pg->offset);
    843  1.11.4.2       chs 			bp->b_resid = bp->b_bcount = iobytes;
    844  1.11.4.1       chs 			bp->b_flags = B_BUSY|B_WRITE|B_CALL;
    845  1.11.4.1       chs 			bp->b_iodone = uvm_aio_biodone1;
    846  1.11.4.1       chs 			bp->b_vp = vp;
    847  1.11.4.1       chs 		}
    848  1.11.4.1       chs 		bp->b_lblkno = 0;
    849  1.11.4.1       chs 		bp->b_private = mbp;
    850  1.11.4.1       chs 
    851  1.11.4.1       chs 		/* adjust physical blkno for partial blocks */
    852  1.11.4.1       chs 		bp->b_blkno = blkno + ((offset - (lbn << bshift)) >>
    853  1.11.4.1       chs 				       dev_bshift);
    854  1.11.4.2       chs 		UVMHIST_LOG(ubchist, "vp %p offset 0x%x bcount 0x%x blkno 0x%x",
    855  1.11.4.2       chs 			    vp, (int)offset, (int)iobytes, bp->b_blkno);
    856  1.11.4.1       chs 
    857  1.11.4.1       chs 		VOP_STRATEGY(bp);
    858  1.11.4.1       chs 	}
    859  1.11.4.1       chs 
    860  1.11.4.1       chs 	if (!ap->a_sync) {
    861  1.11.4.2       chs 		return EINPROGRESS;
    862  1.11.4.1       chs 	}
    863  1.11.4.1       chs 
    864  1.11.4.1       chs errout:
    865  1.11.4.1       chs 	if (bp != NULL) {
    866  1.11.4.1       chs 		error = biowait(mbp);
    867  1.11.4.1       chs 	}
    868  1.11.4.1       chs 	s = splbio();
    869  1.11.4.1       chs 	pool_put(&bufpool, mbp);
    870  1.11.4.1       chs 	splx(s);
    871  1.11.4.1       chs 	uvm_pagermapout(kva, ap->a_count);
    872  1.11.4.1       chs 	UVMHIST_LOG(ubchist, "returning, error %d", error,0,0,0);
    873  1.11.4.1       chs 
    874  1.11.4.2       chs 	return error;
    875       1.1   mycroft }
    876