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