[BACK]Return to ffs_vnops.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / ufs / ffs

Annotation of src/sys/ufs/ffs/ffs_vnops.c, Revision 1.16.2.3

1.16.2.3! chs         1: /*     $NetBSD: ffs_vnops.c,v 1.16.2.2 1998/11/16 08:25:38 chs Exp $   */
1.3       cgd         2:
1.1       mycroft     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:  *
1.12      fvdl       35:  *     @(#)ffs_vnops.c 8.15 (Berkeley) 5/14/95
1.1       mycroft    36:  */
1.11      mrg        37:
1.13      scottr     38: #if defined(_KERNEL) && !defined(_LKM)
1.11      mrg        39: #include "opt_uvm.h"
1.16.2.3! chs        40: #include "opt_uvmhist.h"
1.13      scottr     41: #endif
1.1       mycroft    42:
                     43: #include <sys/param.h>
                     44: #include <sys/systm.h>
                     45: #include <sys/resourcevar.h>
                     46: #include <sys/kernel.h>
                     47: #include <sys/file.h>
                     48: #include <sys/stat.h>
                     49: #include <sys/buf.h>
                     50: #include <sys/proc.h>
                     51: #include <sys/conf.h>
                     52: #include <sys/mount.h>
                     53: #include <sys/vnode.h>
                     54: #include <sys/malloc.h>
1.16      thorpej    55: #include <sys/pool.h>
1.6       christos   56: #include <sys/signalvar.h>
1.1       mycroft    57:
                     58: #include <vm/vm.h>
1.10      mrg        59:
                     60: #if defined(UVM)
                     61: #include <uvm/uvm_extern.h>
                     62: #endif
1.1       mycroft    63:
1.8       mycroft    64: #include <miscfs/fifofs/fifo.h>
                     65: #include <miscfs/genfs/genfs.h>
1.1       mycroft    66: #include <miscfs/specfs/specdev.h>
                     67:
                     68: #include <ufs/ufs/quota.h>
                     69: #include <ufs/ufs/inode.h>
                     70: #include <ufs/ufs/dir.h>
                     71: #include <ufs/ufs/ufs_extern.h>
1.2       mycroft    72: #include <ufs/ufs/ufsmount.h>
1.1       mycroft    73:
                     74: #include <ufs/ffs/fs.h>
                     75: #include <ufs/ffs/ffs_extern.h>
                     76:
                     77: /* Global vfs data structures for ufs. */
1.6       christos   78: int (**ffs_vnodeop_p) __P((void *));
1.1       mycroft    79: struct vnodeopv_entry_desc ffs_vnodeop_entries[] = {
                     80:        { &vop_default_desc, vn_default_error },
                     81:        { &vop_lookup_desc, ufs_lookup },               /* lookup */
                     82:        { &vop_create_desc, ufs_create },               /* create */
1.5       mycroft    83:        { &vop_whiteout_desc, ufs_whiteout },           /* whiteout */
1.1       mycroft    84:        { &vop_mknod_desc, ufs_mknod },                 /* mknod */
                     85:        { &vop_open_desc, ufs_open },                   /* open */
                     86:        { &vop_close_desc, ufs_close },                 /* close */
                     87:        { &vop_access_desc, ufs_access },               /* access */
                     88:        { &vop_getattr_desc, ufs_getattr },             /* getattr */
                     89:        { &vop_setattr_desc, ufs_setattr },             /* setattr */
                     90:        { &vop_read_desc, ffs_read },                   /* read */
                     91:        { &vop_write_desc, ffs_write },                 /* write */
1.4       mycroft    92:        { &vop_lease_desc, ufs_lease_check },           /* lease */
1.1       mycroft    93:        { &vop_ioctl_desc, ufs_ioctl },                 /* ioctl */
1.9       mycroft    94:        { &vop_poll_desc, ufs_poll },                   /* poll */
1.12      fvdl       95:        { &vop_revoke_desc, ufs_revoke },               /* revoke */
1.1       mycroft    96:        { &vop_mmap_desc, ufs_mmap },                   /* mmap */
                     97:        { &vop_fsync_desc, ffs_fsync },                 /* fsync */
                     98:        { &vop_seek_desc, ufs_seek },                   /* seek */
                     99:        { &vop_remove_desc, ufs_remove },               /* remove */
                    100:        { &vop_link_desc, ufs_link },                   /* link */
                    101:        { &vop_rename_desc, ufs_rename },               /* rename */
                    102:        { &vop_mkdir_desc, ufs_mkdir },                 /* mkdir */
                    103:        { &vop_rmdir_desc, ufs_rmdir },                 /* rmdir */
                    104:        { &vop_symlink_desc, ufs_symlink },             /* symlink */
                    105:        { &vop_readdir_desc, ufs_readdir },             /* readdir */
                    106:        { &vop_readlink_desc, ufs_readlink },           /* readlink */
                    107:        { &vop_abortop_desc, ufs_abortop },             /* abortop */
                    108:        { &vop_inactive_desc, ufs_inactive },           /* inactive */
                    109:        { &vop_reclaim_desc, ffs_reclaim },             /* reclaim */
                    110:        { &vop_lock_desc, ufs_lock },                   /* lock */
                    111:        { &vop_unlock_desc, ufs_unlock },               /* unlock */
                    112:        { &vop_bmap_desc, ufs_bmap },                   /* bmap */
                    113:        { &vop_strategy_desc, ufs_strategy },           /* strategy */
                    114:        { &vop_print_desc, ufs_print },                 /* print */
                    115:        { &vop_islocked_desc, ufs_islocked },           /* islocked */
                    116:        { &vop_pathconf_desc, ufs_pathconf },           /* pathconf */
                    117:        { &vop_advlock_desc, ufs_advlock },             /* advlock */
                    118:        { &vop_blkatoff_desc, ffs_blkatoff },           /* blkatoff */
                    119:        { &vop_valloc_desc, ffs_valloc },               /* valloc */
                    120:        { &vop_reallocblks_desc, ffs_reallocblks },     /* reallocblks */
                    121:        { &vop_vfree_desc, ffs_vfree },                 /* vfree */
                    122:        { &vop_truncate_desc, ffs_truncate },           /* truncate */
                    123:        { &vop_update_desc, ffs_update },               /* update */
1.8       mycroft   124:        { &vop_bwrite_desc, vn_bwrite },                /* bwrite */
1.16.2.1  chs       125: #ifdef UBC
                    126:        { &vop_getpages_desc, ffs_getpages },           /* getpages */
                    127:        { &vop_putpages_desc, ffs_putpages },           /* putpages */
                    128: #endif
                    129:        { NULL, NULL }
1.1       mycroft   130: };
                    131: struct vnodeopv_desc ffs_vnodeop_opv_desc =
                    132:        { &ffs_vnodeop_p, ffs_vnodeop_entries };
                    133:
1.6       christos  134: int (**ffs_specop_p) __P((void *));
1.1       mycroft   135: struct vnodeopv_entry_desc ffs_specop_entries[] = {
                    136:        { &vop_default_desc, vn_default_error },
                    137:        { &vop_lookup_desc, spec_lookup },              /* lookup */
                    138:        { &vop_create_desc, spec_create },              /* create */
                    139:        { &vop_mknod_desc, spec_mknod },                /* mknod */
                    140:        { &vop_open_desc, spec_open },                  /* open */
                    141:        { &vop_close_desc, ufsspec_close },             /* close */
                    142:        { &vop_access_desc, ufs_access },               /* access */
                    143:        { &vop_getattr_desc, ufs_getattr },             /* getattr */
                    144:        { &vop_setattr_desc, ufs_setattr },             /* setattr */
                    145:        { &vop_read_desc, ufsspec_read },               /* read */
                    146:        { &vop_write_desc, ufsspec_write },             /* write */
1.4       mycroft   147:        { &vop_lease_desc, spec_lease_check },          /* lease */
1.1       mycroft   148:        { &vop_ioctl_desc, spec_ioctl },                /* ioctl */
1.9       mycroft   149:        { &vop_poll_desc, spec_poll },                  /* poll */
1.12      fvdl      150:        { &vop_revoke_desc, spec_revoke },              /* revoke */
1.1       mycroft   151:        { &vop_mmap_desc, spec_mmap },                  /* mmap */
                    152:        { &vop_fsync_desc, ffs_fsync },                 /* fsync */
                    153:        { &vop_seek_desc, spec_seek },                  /* seek */
                    154:        { &vop_remove_desc, spec_remove },              /* remove */
                    155:        { &vop_link_desc, spec_link },                  /* link */
                    156:        { &vop_rename_desc, spec_rename },              /* rename */
                    157:        { &vop_mkdir_desc, spec_mkdir },                /* mkdir */
                    158:        { &vop_rmdir_desc, spec_rmdir },                /* rmdir */
                    159:        { &vop_symlink_desc, spec_symlink },            /* symlink */
                    160:        { &vop_readdir_desc, spec_readdir },            /* readdir */
                    161:        { &vop_readlink_desc, spec_readlink },          /* readlink */
                    162:        { &vop_abortop_desc, spec_abortop },            /* abortop */
                    163:        { &vop_inactive_desc, ufs_inactive },           /* inactive */
                    164:        { &vop_reclaim_desc, ffs_reclaim },             /* reclaim */
                    165:        { &vop_lock_desc, ufs_lock },                   /* lock */
                    166:        { &vop_unlock_desc, ufs_unlock },               /* unlock */
                    167:        { &vop_bmap_desc, spec_bmap },                  /* bmap */
                    168:        { &vop_strategy_desc, spec_strategy },          /* strategy */
                    169:        { &vop_print_desc, ufs_print },                 /* print */
                    170:        { &vop_islocked_desc, ufs_islocked },           /* islocked */
                    171:        { &vop_pathconf_desc, spec_pathconf },          /* pathconf */
                    172:        { &vop_advlock_desc, spec_advlock },            /* advlock */
                    173:        { &vop_blkatoff_desc, spec_blkatoff },          /* blkatoff */
                    174:        { &vop_valloc_desc, spec_valloc },              /* valloc */
                    175:        { &vop_reallocblks_desc, spec_reallocblks },    /* reallocblks */
                    176:        { &vop_vfree_desc, ffs_vfree },                 /* vfree */
                    177:        { &vop_truncate_desc, spec_truncate },          /* truncate */
                    178:        { &vop_update_desc, ffs_update },               /* update */
1.8       mycroft   179:        { &vop_bwrite_desc, vn_bwrite },                /* bwrite */
1.6       christos  180:        { (struct vnodeop_desc*)NULL, (int(*) __P((void *)))NULL }
1.1       mycroft   181: };
                    182: struct vnodeopv_desc ffs_specop_opv_desc =
                    183:        { &ffs_specop_p, ffs_specop_entries };
                    184:
1.6       christos  185: int (**ffs_fifoop_p) __P((void *));
1.1       mycroft   186: struct vnodeopv_entry_desc ffs_fifoop_entries[] = {
                    187:        { &vop_default_desc, vn_default_error },
                    188:        { &vop_lookup_desc, fifo_lookup },              /* lookup */
                    189:        { &vop_create_desc, fifo_create },              /* create */
                    190:        { &vop_mknod_desc, fifo_mknod },                /* mknod */
                    191:        { &vop_open_desc, fifo_open },                  /* open */
                    192:        { &vop_close_desc, ufsfifo_close },             /* close */
                    193:        { &vop_access_desc, ufs_access },               /* access */
                    194:        { &vop_getattr_desc, ufs_getattr },             /* getattr */
                    195:        { &vop_setattr_desc, ufs_setattr },             /* setattr */
                    196:        { &vop_read_desc, ufsfifo_read },               /* read */
                    197:        { &vop_write_desc, ufsfifo_write },             /* write */
1.4       mycroft   198:        { &vop_lease_desc, fifo_lease_check },          /* lease */
1.1       mycroft   199:        { &vop_ioctl_desc, fifo_ioctl },                /* ioctl */
1.9       mycroft   200:        { &vop_poll_desc, fifo_poll },                  /* poll */
1.12      fvdl      201:        { &vop_revoke_desc, fifo_revoke },              /* revoke */
1.1       mycroft   202:        { &vop_mmap_desc, fifo_mmap },                  /* mmap */
                    203:        { &vop_fsync_desc, ffs_fsync },                 /* fsync */
                    204:        { &vop_seek_desc, fifo_seek },                  /* seek */
                    205:        { &vop_remove_desc, fifo_remove },              /* remove */
                    206:        { &vop_link_desc, fifo_link },                  /* link */
                    207:        { &vop_rename_desc, fifo_rename },              /* rename */
                    208:        { &vop_mkdir_desc, fifo_mkdir },                /* mkdir */
                    209:        { &vop_rmdir_desc, fifo_rmdir },                /* rmdir */
                    210:        { &vop_symlink_desc, fifo_symlink },            /* symlink */
                    211:        { &vop_readdir_desc, fifo_readdir },            /* readdir */
                    212:        { &vop_readlink_desc, fifo_readlink },          /* readlink */
                    213:        { &vop_abortop_desc, fifo_abortop },            /* abortop */
                    214:        { &vop_inactive_desc, ufs_inactive },           /* inactive */
                    215:        { &vop_reclaim_desc, ffs_reclaim },             /* reclaim */
                    216:        { &vop_lock_desc, ufs_lock },                   /* lock */
                    217:        { &vop_unlock_desc, ufs_unlock },               /* unlock */
                    218:        { &vop_bmap_desc, fifo_bmap },                  /* bmap */
                    219:        { &vop_strategy_desc, fifo_strategy },          /* strategy */
                    220:        { &vop_print_desc, ufs_print },                 /* print */
                    221:        { &vop_islocked_desc, ufs_islocked },           /* islocked */
                    222:        { &vop_pathconf_desc, fifo_pathconf },          /* pathconf */
                    223:        { &vop_advlock_desc, fifo_advlock },            /* advlock */
                    224:        { &vop_blkatoff_desc, fifo_blkatoff },          /* blkatoff */
                    225:        { &vop_valloc_desc, fifo_valloc },              /* valloc */
                    226:        { &vop_reallocblks_desc, fifo_reallocblks },    /* reallocblks */
                    227:        { &vop_vfree_desc, ffs_vfree },                 /* vfree */
                    228:        { &vop_truncate_desc, fifo_truncate },          /* truncate */
                    229:        { &vop_update_desc, ffs_update },               /* update */
1.8       mycroft   230:        { &vop_bwrite_desc, vn_bwrite },                /* bwrite */
1.6       christos  231:        { (struct vnodeop_desc*)NULL, (int(*) __P((void *)))NULL }
1.1       mycroft   232: };
                    233: struct vnodeopv_desc ffs_fifoop_opv_desc =
                    234:        { &ffs_fifoop_p, ffs_fifoop_entries };
                    235:
                    236: int doclusterread = 1;
                    237: int doclusterwrite = 1;
                    238:
                    239: #include <ufs/ufs/ufs_readwrite.c>
                    240:
                    241: /*
                    242:  * Reclaim an inode so that it can be used for other purposes.
                    243:  */
                    244: int
1.6       christos  245: ffs_reclaim(v)
                    246:        void *v;
                    247: {
1.1       mycroft   248:        struct vop_reclaim_args /* {
                    249:                struct vnode *a_vp;
1.12      fvdl      250:                struct proc *a_p;
1.6       christos  251:        } */ *ap = v;
1.1       mycroft   252:        register struct vnode *vp = ap->a_vp;
                    253:        int error;
                    254:
1.12      fvdl      255:        if ((error = ufs_reclaim(vp, ap->a_p)) != 0)
1.1       mycroft   256:                return (error);
1.16.2.1  chs       257:
1.16      thorpej   258:        /*
                    259:         * XXX MFS ends up here, too, to free an inode.  Should we create
                    260:         * XXX a separate pool for MFS inodes?
                    261:         */
                    262:        pool_put(&ffs_inode_pool, vp->v_data);
1.1       mycroft   263:        vp->v_data = NULL;
                    264:        return (0);
                    265: }
1.16.2.1  chs       266:
                    267: #ifdef UBC
                    268: #include <uvm/uvm.h>
                    269:
                    270: int
                    271: ffs_getpages(v)
                    272:        void *v;
                    273: {
                    274:        struct vop_getpages_args /* {
                    275:                struct vnode *a_vp;
                    276:                vaddr_t a_offset;
                    277:                vm_page_t *a_m;
                    278:                int *a_count;
                    279:                int a_centeridx;
                    280:                vm_prot_t a_access_type;
                    281:                int a_advice;
                    282:                int a_flags;
                    283:        } */ *ap = v;
                    284:
1.16.2.3! chs       285:        int i, error, npages;
1.16.2.1  chs       286:        vm_page_t m;
                    287:        vaddr_t kva;
                    288:        struct buf tmpbuf, *bp;
                    289:        struct vnode *vp = ap->a_vp;
                    290:        struct uvm_object *uobj = &vp->v_uvm.u_obj;
                    291:        struct inode *ip = VTOI(vp);
                    292:        struct fs *fs = ip->i_fs;
                    293:        UVMHIST_FUNC("ffs_getpages"); UVMHIST_CALLED(ubchist);
                    294:
1.16.2.3! chs       295: #ifdef DIAGNOSTIC
        !           296:        if (ap->a_centeridx < 0 || ap->a_centeridx > *ap->a_count) {
        !           297:                panic("ffs_getpages: centeridx %d out of range",
        !           298:                      ap->a_centeridx);
        !           299:        }
        !           300: #endif
        !           301:
1.16.2.1  chs       302:        if (ap->a_flags & PGO_LOCKED) {
1.16.2.3! chs       303:                uvn_findpages(uobj, ap->a_offset, ap->a_count, ap->a_m,
        !           304:                              UFP_NOWAIT|UFP_NOALLOC);
        !           305:
        !           306:                /* XXX PGO_ALLPAGES? */
        !           307:                return ap->a_m[ap->a_centeridx] == NULL ?
        !           308:                        VM_PAGER_UNLOCK : VM_PAGER_OK;
1.16.2.1  chs       309:        }
                    310:
                    311:        /* vnode is VOP_LOCKed, uobj is locked */
                    312:
1.16.2.3! chs       313:        /*
        !           314:         * XXX
        !           315:         * first see if center page already exists.
        !           316:         * this is needed because ubc_fault() doesn't
        !           317:         * do a PGO_LOCKED call first.
        !           318:         * if the page exists, return it.
        !           319:         */
1.16.2.1  chs       320:
1.16.2.3! chs       321:        npages = 1;
        !           322:        uvn_findpages(uobj, ap->a_offset + (ap->a_centeridx << PAGE_SHIFT),
        !           323:                      &npages, &ap->a_m[ap->a_centeridx], UFP_NOALLOC);
        !           324:        if (npages == 1) {
        !           325:                simple_unlock(&uobj->vmobjlock);
        !           326:                return VM_PAGER_OK;
1.16.2.1  chs       327:        }
                    328:
1.16.2.3! chs       329:        npages = 1;
        !           330:        uvn_findpages(uobj, ap->a_offset, &npages, ap->a_m, 0);
1.16.2.1  chs       331:        m = ap->a_m[ap->a_centeridx];
                    332:
                    333:        simple_unlock(&uobj->vmobjlock);
                    334:
                    335:        if ((m->flags & PG_FAKE) == 0) {
                    336:                UVMHIST_LOG(ubchist, "page was valid",0,0,0,0);
1.16.2.3! chs       337:                return VM_PAGER_OK;
1.16.2.1  chs       338:        }
                    339:
                    340:        bp = &tmpbuf;
                    341:        bzero(bp, sizeof *bp);
                    342:
                    343:        bp->b_lblkno = lblkno(fs, m->offset);
1.16.2.3! chs       344:        if (m->blkno == 0) {
        !           345:                error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL);
        !           346:                if (error) {
1.16.2.1  chs       347: UVMHIST_LOG(ubchist, "VOP_BMAP error %d", error,0,0,0);
1.16.2.3! chs       348:                        return (error);
        !           349:                }
1.16.2.1  chs       350: UVMHIST_LOG(ubchist, "VOP_BMAP gave 0x%x", bp->b_blkno,0,0,0);
1.16.2.3! chs       351:                if (bp->b_blkno == (daddr_t)-1) {
        !           352:
        !           353:                        /*
        !           354:                         * XXX pre-allocate blocks here someday?
        !           355:                         * ... only for write accesses.
        !           356:                         * for read accesses we can skip the block allocation
        !           357:                         * if we can arrange to be called again
        !           358:                         * when a subsequent write access occurs.
        !           359:                         * needs support in uvm_fault().
        !           360:                         */
        !           361:                        uvm_pagezero(m);
        !           362:                        m->flags &= ~(PG_FAKE);
        !           363:                        pmap_clear_modify(PMAP_PGARG(m));
        !           364:                        pmap_clear_reference(PMAP_PGARG(m));
        !           365:                        return VM_PAGER_OK;
        !           366:                }
1.16.2.1  chs       367:        }
                    368:
                    369:        /* adjust physical blkno for partial blocks */
                    370:        bp->b_blkno += (m->offset - lblktosize(fs, bp->b_lblkno)) >> DEV_BSHIFT;
                    371:        m->blkno = bp->b_blkno;
                    372:
1.16.2.3! chs       373: UVMHIST_LOG(ubchist, "vp %p lblkno 0x%x blkno 0x%x",
        !           374:            vp, bp->b_lblkno, bp->b_blkno, 0);
        !           375:
        !           376:        /*
        !           377:         * don't bother reading the pages if we're just going to
        !           378:         * overwrite them.
        !           379:         */
        !           380:        if (ap->a_flags & PGO_OVERWRITE) {
        !           381:                for (i = 0; i < *ap->a_count; i++) {
        !           382:
        !           383:                        /* XXX for now, zero the pages */
        !           384:                        if (ap->a_m[i]->flags & PG_FAKE) {
        !           385:                                uvm_pagezero(ap->a_m[i]);
        !           386:                                ap->a_m[i]->flags &= ~(PG_FAKE);
        !           387:                        }
        !           388:                }
        !           389:                return VM_PAGER_OK;
        !           390:        }
        !           391:
        !           392:        kva = uvm_pagermapin(ap->a_m, *ap->a_count, NULL, M_WAITOK);
        !           393:        if (kva == 0) {
        !           394:                /* XXX unbusy pages */
        !           395:                return VM_PAGER_AGAIN;
        !           396:        }
        !           397:
        !           398:        bp->b_bufsize = PAGE_SIZE;
        !           399:        bp->b_data = (void *)kva;
        !           400:        bp->b_bcount = bp->b_lblkno < 0 ? bp->b_bufsize :
        !           401:                min(bp->b_bufsize,
        !           402:                    fragroundup(fs, vp->v_uvm.u_size - m->offset));
        !           403:        bp->b_vp = vp;
        !           404:        bp->b_flags = B_BUSY|B_READ;
        !           405:
        !           406: UVMHIST_LOG(ubchist, "bp %p vp %p blkno 0x%x", bp, vp, bp->b_lblkno, 0);
1.16.2.1  chs       407:
                    408:        VOP_STRATEGY(bp);
                    409:        error = biowait(bp);
                    410:
                    411: UVMHIST_LOG(ubchist, "error %d", error,0,0,0);
                    412:
                    413:        uvm_pagermapout(kva, *ap->a_count);
                    414:
                    415:        if (error) {
                    416:                simple_lock(&uobj->vmobjlock);
                    417:                if (m->flags & PG_WANTED)
1.16.2.3! chs       418:                        wakeup(m);
1.16.2.1  chs       419:                m->flags &= ~(PG_WANTED|PG_BUSY);
                    420:                UVM_PAGE_OWN(m, NULL);
                    421:                uvm_lock_pageq();
                    422:                uvm_pagefree(m);
                    423:                uvm_unlock_pageq();
                    424:                simple_unlock(&uobj->vmobjlock);
                    425:        } else {
1.16.2.3! chs       426:                m->flags &= ~(PG_FAKE);
1.16.2.1  chs       427:                pmap_clear_modify(PMAP_PGARG(m));
                    428:        }
                    429:
1.16.2.3! chs       430:        return error ? VM_PAGER_ERROR : VM_PAGER_OK;
1.16.2.1  chs       431: }
                    432:
                    433: /*
                    434:  * Vnode op for VM putpages.
                    435:  */
                    436: int
                    437: ffs_putpages(v)
                    438:        void *v;
                    439: {
                    440:        struct vop_putpages_args /* {
                    441:                struct vnode *a_vp;
1.16.2.3! chs       442:                struct vm_page **a_m;
1.16.2.1  chs       443:                int a_count;
                    444:                int a_sync;
                    445:                int *a_rtvals;
                    446:        } */ *ap = v;
                    447:
1.16.2.3! chs       448:        int s, error;
        !           449:        vaddr_t kva, offset;
        !           450:        struct vm_page *pg;
1.16.2.1  chs       451:        struct buf tmpbuf, *bp;
                    452:        struct vnode *vp = ap->a_vp;
                    453:        struct inode *ip = VTOI(vp);
                    454:        struct fs *fs = ip->i_fs;
                    455:        struct ucred *cred = curproc->p_ucred;  /* XXX curproc */
                    456:        UVMHIST_FUNC("ffs_putpages"); UVMHIST_CALLED(ubchist);
                    457:
1.16.2.3! chs       458:        pg = ap->a_m[0];
        !           459:
        !           460: #ifdef DIAGNOSTIC
        !           461:        if (ap->a_count > 1) {
        !           462:                int i;
        !           463:
        !           464:                for (i = 1; i < ap->a_count; i++) {
        !           465:                        if (ap->a_m[i]->blkno !=
        !           466:                            pg->blkno + i * (PAGE_SIZE >> DEV_BSHIFT)) {
        !           467:                                panic("ffs_putpages: pg %p %p not clusterable",
        !           468:                                      pg, ap->a_m[i]);
        !           469:                        }
        !           470:                }
1.16.2.2  chs       471:        }
1.16.2.3! chs       472: #endif
1.16.2.1  chs       473:
                    474:        kva = uvm_pagermapin(ap->a_m, ap->a_count, NULL, M_WAITOK);
1.16.2.2  chs       475:        if (kva == 0) {
1.16.2.3! chs       476:                return VM_PAGER_AGAIN;
1.16.2.1  chs       477:        }
                    478:
1.16.2.3! chs       479:        if (ap->a_sync) {
        !           480:                bp = &tmpbuf;
        !           481:                bzero(bp, sizeof *bp);
        !           482:        }
        !           483:        else {
        !           484:                struct uvm_aiobuf *abp = pool_get(uvm_aiobuf_pool, PR_WAITOK);
        !           485:                abp->aio.aiodone = uvm_aio_aiodone;
        !           486:                abp->aio.kva = kva;
        !           487:                abp->aio.npages = ap->a_count;
        !           488:                abp->aio.pd_ptr = abp;
        !           489:                bp = &abp->buf;
        !           490:                bzero(bp, sizeof *bp);
        !           491:                bp->b_flags = B_CALL|B_ASYNC;
        !           492:                bp->b_iodone = uvm_aio_biodone;
        !           493:        }
1.16.2.1  chs       494:
1.16.2.3! chs       495:        offset = pg->offset;
        !           496:        bp->b_bufsize = ap->a_count << PAGE_SHIFT;
1.16.2.1  chs       497:        bp->b_data = (void *)kva;
1.16.2.3! chs       498:        bp->b_lblkno = lblkno(fs, offset);
        !           499:        bp->b_bcount = min(bp->b_bufsize,
        !           500:                           fragroundup(fs, vp->v_uvm.u_size - offset));
        !           501:        bp->b_flags |= B_BUSY|B_WRITE;
1.16.2.1  chs       502:        bp->b_vp = vp;
                    503:
                    504:        /*
                    505:         * if the blkno wasn't set in the page, do a bmap to find it.
1.16.2.3! chs       506:         * this should only happen if the block is unallocated.
1.16.2.1  chs       507:         * we'll always want to set the page's blkno if it's allocated
                    508:         * to help prevent memory deadlocks.  we probably even want to
1.16.2.3! chs       509:         * allocate blocks in VOP_GETPAGES() for this same reason.
1.16.2.1  chs       510:         *
                    511:         * once we switch to doing that, the page should always have a blkno.
                    512:         * but for now, we'll handle allocating blocks here too.
1.16.2.3! chs       513:         *
        !           514:         * XXX this doesn't handle blocksizes smaller than PAGE_SIZE.
1.16.2.1  chs       515:         */
                    516:
1.16.2.3! chs       517:        bp->b_blkno = pg->blkno;
1.16.2.1  chs       518:        if (bp->b_blkno == 0) {
1.16.2.3! chs       519:                int bsize;
        !           520:
        !           521: #ifdef DEBUG
1.16.2.1  chs       522:                error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL);
                    523:                if (error) {
1.16.2.3! chs       524:                        goto out;
1.16.2.1  chs       525:                }
1.16.2.3! chs       526:                if (bp->b_blkno != (daddr_t)-1) {
        !           527:                        panic("ffs_putpage: page %p has blkno 0, not %d\n",
        !           528:                              pg, bp->b_blkno);
        !           529:                }
        !           530: #endif
        !           531:                bsize = blksize(fs, ip, lblkno(fs, offset));
        !           532:                error = ffs_balloc(ip, bp->b_lblkno, bsize, cred, NULL,
        !           533:                                   &bp->b_blkno, 0, NULL);
1.16.2.1  chs       534:                if (error) {
1.16.2.3! chs       535:                        UVMHIST_LOG(ubchist, "ffs_balloc -> %d", error, 0,0,0);
        !           536:                        goto out;
1.16.2.1  chs       537:                }
                    538:
                    539:                /* adjust physical blkno for partial blocks */
1.16.2.3! chs       540:                bp->b_blkno += ((offset - lblktosize(fs, bp->b_lblkno))
1.16.2.1  chs       541:                                >> DEV_BSHIFT);
1.16.2.3! chs       542:                pg->blkno = bp->b_blkno;
1.16.2.1  chs       543:        }
                    544:
1.16.2.3! chs       545:        UVMHIST_LOG(ubchist, "pg %p vp %p lblkno 0x%x blkno 0x%x",
        !           546:                    pg, vp, bp->b_lblkno, bp->b_blkno);
1.16.2.1  chs       547:
1.16.2.3! chs       548:        s = splbio();
1.16.2.1  chs       549:        vp->v_numoutput++;
1.16.2.3! chs       550:        splx(s);
1.16.2.1  chs       551:
                    552:        VOP_STRATEGY(bp);
1.16.2.3! chs       553:        if (!ap->a_sync) {
        !           554:                return VM_PAGER_PEND;
        !           555:        }
1.16.2.1  chs       556:
                    557:        error = biowait(bp);
                    558:
1.16.2.3! chs       559: out:
1.16.2.1  chs       560: UVMHIST_LOG(ubchist, "error %d", error,0,0,0);
                    561:        uvm_pagermapout(kva, ap->a_count);
                    562:
1.16.2.3! chs       563:        return error ? VM_PAGER_ERROR : VM_PAGER_OK;
1.16.2.1  chs       564: }
                    565: #endif

CVSweb <webmaster@jp.NetBSD.org>