[BACK]Return to puffs_vnops.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / fs / puffs

Annotation of src/sys/fs/puffs/puffs_vnops.c, Revision 1.38

1.38    ! pooka       1: /*     $NetBSD: puffs_vnops.c,v 1.37 2007/01/21 14:52:20 pooka Exp $   */
1.1       pooka       2:
                      3: /*
                      4:  * Copyright (c) 2005, 2006  Antti Kantee.  All Rights Reserved.
                      5:  *
                      6:  * Development of this software was supported by the
                      7:  * Google Summer of Code program and the Ulla Tuominen Foundation.
                      8:  * The Google SoC project was mentored by Bill Studenmund.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  * 3. The name of the company nor the name of the author may be used to
                     19:  *    endorse or promote products derived from this software without specific
                     20:  *    prior written permission.
                     21:  *
                     22:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
                     23:  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     24:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     25:  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     26:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     27:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     28:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     29:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     30:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     31:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     32:  * SUCH DAMAGE.
                     33:  */
                     34:
                     35: #include <sys/cdefs.h>
1.38    ! pooka      36: __KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.37 2007/01/21 14:52:20 pooka Exp $");
1.1       pooka      37:
                     38: #include <sys/param.h>
                     39: #include <sys/vnode.h>
                     40: #include <sys/mount.h>
                     41: #include <sys/malloc.h>
                     42: #include <sys/namei.h>
                     43:
                     44: #include <fs/puffs/puffs_msgif.h>
                     45: #include <fs/puffs/puffs_sys.h>
                     46:
1.6       pooka      47: #include <miscfs/fifofs/fifo.h>
1.1       pooka      48: #include <miscfs/genfs/genfs.h>
1.5       pooka      49: #include <miscfs/specfs/specdev.h>
                     50:
1.1       pooka      51: int    puffs_lookup(void *);
                     52: int    puffs_create(void *);
                     53: int    puffs_access(void *);
                     54: int    puffs_mknod(void *);
                     55: int    puffs_open(void *);
                     56: int    puffs_close(void *);
                     57: int    puffs_getattr(void *);
                     58: int    puffs_setattr(void *);
                     59: int    puffs_reclaim(void *);
                     60: int    puffs_readdir(void *);
                     61: int    puffs_poll(void *);
                     62: int    puffs_fsync(void *);
                     63: int    puffs_seek(void *);
                     64: int    puffs_remove(void *);
                     65: int    puffs_mkdir(void *);
                     66: int    puffs_rmdir(void *);
                     67: int    puffs_link(void *);
                     68: int    puffs_readlink(void *);
                     69: int    puffs_symlink(void *);
                     70: int    puffs_rename(void *);
                     71: int    puffs_read(void *);
                     72: int    puffs_write(void *);
                     73: int    puffs_fcntl(void *);
                     74: int    puffs_ioctl(void *);
                     75: int    puffs_inactive(void *);
                     76: int    puffs_print(void *);
                     77: int    puffs_pathconf(void *);
                     78: int    puffs_advlock(void *);
1.8       pooka      79: int    puffs_strategy(void *);
                     80: int    puffs_bmap(void *);
1.16      pooka      81: int    puffs_mmap(void *);
1.1       pooka      82:
1.26      pooka      83: int    puffs_spec_read(void *);
                     84: int    puffs_spec_write(void *);
                     85: int    puffs_fifo_read(void *);
                     86: int    puffs_fifo_write(void *);
                     87:
1.17      pooka      88: int    puffs_checkop(void *);
                     89:
1.1       pooka      90:
                     91: /* VOP_LEASE() not included */
                     92:
                     93: int    puffs_generic(void *);
                     94:
                     95: #if 0
                     96: #define puffs_lock genfs_lock
                     97: #define puffs_unlock genfs_unlock
                     98: #define puffs_islocked genfs_islocked
                     99: #else
                    100: int puffs_lock(void *);
                    101: int puffs_unlock(void *);
                    102: int puffs_islocked(void *);
                    103: #endif
                    104:
                    105: int (**puffs_vnodeop_p)(void *);
                    106: const struct vnodeopv_entry_desc puffs_vnodeop_entries[] = {
                    107:        { &vop_default_desc, vn_default_error },
1.17      pooka     108:        { &vop_lookup_desc, puffs_lookup },             /* REAL lookup */
                    109:        { &vop_create_desc, puffs_checkop },            /* create */
                    110:         { &vop_mknod_desc, puffs_checkop },            /* mknod */
                    111:         { &vop_open_desc, puffs_checkop },             /* open */
                    112:         { &vop_close_desc, puffs_checkop },            /* close */
                    113:         { &vop_access_desc, puffs_checkop },           /* access */
                    114:         { &vop_getattr_desc, puffs_checkop },          /* getattr */
                    115:         { &vop_setattr_desc, puffs_checkop },          /* setattr */
                    116:         { &vop_read_desc, puffs_checkop },             /* read */
                    117:         { &vop_write_desc, puffs_checkop },            /* write */
                    118:         { &vop_fcntl_desc, puffs_checkop },            /* fcntl */
                    119:         { &vop_ioctl_desc, puffs_checkop },            /* ioctl */
1.31      pooka     120:         { &vop_fsync_desc, puffs_fsync },              /* REAL fsync */
1.17      pooka     121:         { &vop_seek_desc, puffs_checkop },             /* seek */
                    122:         { &vop_remove_desc, puffs_checkop },           /* remove */
                    123:         { &vop_link_desc, puffs_checkop },             /* link */
                    124:         { &vop_rename_desc, puffs_checkop },           /* rename */
                    125:         { &vop_mkdir_desc, puffs_checkop },            /* mkdir */
                    126:         { &vop_rmdir_desc, puffs_checkop },            /* rmdir */
                    127:         { &vop_symlink_desc, puffs_checkop },          /* symlink */
                    128:         { &vop_readdir_desc, puffs_checkop },          /* readdir */
                    129:         { &vop_readlink_desc, puffs_checkop },         /* readlink */
                    130:         { &vop_getpages_desc, puffs_checkop },         /* getpages */
                    131:         { &vop_putpages_desc, puffs_checkop },         /* putpages */
                    132:         { &vop_pathconf_desc, puffs_checkop },         /* pathconf */
                    133:         { &vop_advlock_desc, puffs_checkop },          /* advlock */
                    134:         { &vop_strategy_desc, puffs_strategy },                /* REAL strategy */
1.34      pooka     135:         { &vop_revoke_desc, genfs_revoke },            /* REAL revoke */
1.17      pooka     136:         { &vop_abortop_desc, genfs_abortop },          /* REAL abortop */
                    137:         { &vop_inactive_desc, puffs_inactive },                /* REAL inactive */
                    138:         { &vop_reclaim_desc, puffs_reclaim },          /* REAL reclaim */
                    139:         { &vop_lock_desc, puffs_lock },                        /* REAL lock */
                    140:         { &vop_unlock_desc, puffs_unlock },            /* REAL unlock */
                    141:         { &vop_bmap_desc, puffs_bmap },                        /* REAL bmap */
                    142:         { &vop_print_desc, puffs_print },              /* REAL print */
                    143:         { &vop_islocked_desc, puffs_islocked },                /* REAL islocked */
                    144:         { &vop_bwrite_desc, genfs_nullop },            /* REAL bwrite */
                    145:         { &vop_mmap_desc, puffs_mmap },                        /* REAL mmap */
1.1       pooka     146:
                    147:         { &vop_poll_desc, genfs_eopnotsupp },          /* poll XXX */
                    148:         { &vop_poll_desc, genfs_eopnotsupp },          /* kqfilter XXX */
                    149:        { NULL, NULL }
                    150: };
                    151: const struct vnodeopv_desc puffs_vnodeop_opv_desc =
                    152:        { &puffs_vnodeop_p, puffs_vnodeop_entries };
                    153:
1.5       pooka     154:
                    155: int (**puffs_specop_p)(void *);
                    156: const struct vnodeopv_entry_desc puffs_specop_entries[] = {
                    157:        { &vop_default_desc, vn_default_error },
                    158:        { &vop_lookup_desc, spec_lookup },              /* lookup, ENOTDIR */
1.6       pooka     159:        { &vop_create_desc, spec_create },              /* genfs_badop */
                    160:        { &vop_mknod_desc, spec_mknod },                /* genfs_badop */
                    161:        { &vop_open_desc, spec_open },                  /* spec_open */
1.26      pooka     162:        { &vop_close_desc, spec_close },                /* spec_close */
                    163:        { &vop_access_desc, puffs_checkop },            /* access */
                    164:        { &vop_getattr_desc, puffs_checkop },           /* getattr */
                    165:        { &vop_setattr_desc, puffs_checkop },           /* setattr */
                    166:        { &vop_read_desc, puffs_spec_read },            /* update, read */
                    167:        { &vop_write_desc, puffs_spec_write },          /* update, write */
1.5       pooka     168:        { &vop_lease_desc, spec_lease_check },          /* genfs_nullop */
                    169:        { &vop_ioctl_desc, spec_ioctl },                /* spec_ioctl */
                    170:        { &vop_fcntl_desc, genfs_fcntl },               /* dummy */
                    171:        { &vop_poll_desc, spec_poll },                  /* spec_poll */
                    172:        { &vop_kqfilter_desc, spec_kqfilter },          /* spec_kqfilter */
                    173:        { &vop_revoke_desc, spec_revoke },              /* genfs_revoke */
                    174:        { &vop_mmap_desc, spec_mmap },                  /* genfs_mmap (dummy) */
1.7       pooka     175:        { &vop_fsync_desc, spec_fsync },                /* vflushbuf */
1.5       pooka     176:        { &vop_seek_desc, spec_seek },                  /* genfs_nullop */
                    177:        { &vop_remove_desc, spec_remove },              /* genfs_badop */
                    178:        { &vop_link_desc, spec_link },                  /* genfs_badop */
                    179:        { &vop_rename_desc, spec_rename },              /* genfs_badop */
                    180:        { &vop_mkdir_desc, spec_mkdir },                /* genfs_badop */
                    181:        { &vop_rmdir_desc, spec_rmdir },                /* genfs_badop */
                    182:        { &vop_symlink_desc, spec_symlink },            /* genfs_badop */
                    183:        { &vop_readdir_desc, spec_readdir },            /* genfs_badop */
                    184:        { &vop_readlink_desc, spec_readlink },          /* genfs_badop */
                    185:        { &vop_abortop_desc, spec_abortop },            /* genfs_badop */
1.26      pooka     186:        { &vop_inactive_desc, puffs_inactive },         /* REAL inactive */
                    187:        { &vop_reclaim_desc, puffs_reclaim },           /* REAL reclaim */
                    188:        { &vop_lock_desc, puffs_lock },                 /* REAL lock */
                    189:        { &vop_unlock_desc, puffs_unlock },             /* REAL unlock */
1.5       pooka     190:        { &vop_bmap_desc, spec_bmap },                  /* dummy */
                    191:        { &vop_strategy_desc, spec_strategy },          /* dev strategy */
1.26      pooka     192:        { &vop_print_desc, puffs_print },               /* REAL print */
                    193:        { &vop_islocked_desc, puffs_islocked },         /* REAL islocked */
1.5       pooka     194:        { &vop_pathconf_desc, spec_pathconf },          /* pathconf */
                    195:        { &vop_advlock_desc, spec_advlock },            /* lf_advlock */
                    196:        { &vop_bwrite_desc, vn_bwrite },                /* bwrite */
                    197:        { &vop_getpages_desc, spec_getpages },          /* genfs_getpages */
                    198:        { &vop_putpages_desc, spec_putpages },          /* genfs_putpages */
                    199: #if 0
                    200:        { &vop_openextattr_desc, _openextattr },        /* openextattr */
                    201:        { &vop_closeextattr_desc, _closeextattr },      /* closeextattr */
                    202:        { &vop_getextattr_desc, _getextattr },          /* getextattr */
                    203:        { &vop_setextattr_desc, _setextattr },          /* setextattr */
                    204:        { &vop_listextattr_desc, _listextattr },        /* listextattr */
                    205:        { &vop_deleteextattr_desc, _deleteextattr },    /* deleteextattr */
                    206: #endif
                    207:        { NULL, NULL }
                    208: };
                    209: const struct vnodeopv_desc puffs_specop_opv_desc =
                    210:        { &puffs_specop_p, puffs_specop_entries };
                    211:
1.23      pooka     212:
1.6       pooka     213: int (**puffs_fifoop_p)(void *);
                    214: const struct vnodeopv_entry_desc puffs_fifoop_entries[] = {
                    215:        { &vop_default_desc, vn_default_error },
                    216:        { &vop_lookup_desc, fifo_lookup },              /* lookup, ENOTDIR */
                    217:        { &vop_create_desc, fifo_create },              /* genfs_badop */
                    218:        { &vop_mknod_desc, fifo_mknod },                /* genfs_badop */
                    219:        { &vop_open_desc, fifo_open },                  /* open */
1.26      pooka     220:        { &vop_close_desc, fifo_close },                /* close */
                    221:        { &vop_access_desc, puffs_checkop },            /* access */
                    222:        { &vop_getattr_desc, puffs_checkop },           /* getattr */
                    223:        { &vop_setattr_desc, puffs_checkop },           /* setattr */
                    224:        { &vop_read_desc, puffs_fifo_read },            /* read, update */
                    225:        { &vop_write_desc, puffs_fifo_write },          /* write, update */
1.6       pooka     226:        { &vop_lease_desc, fifo_lease_check },          /* genfs_nullop */
                    227:        { &vop_ioctl_desc, fifo_ioctl },                /* ioctl */
                    228:        { &vop_fcntl_desc, genfs_fcntl },               /* dummy */
                    229:        { &vop_poll_desc, fifo_poll },                  /* poll */
                    230:        { &vop_kqfilter_desc, fifo_kqfilter },          /* kqfilter */
                    231:        { &vop_revoke_desc, fifo_revoke },              /* genfs_revoke */
                    232:        { &vop_mmap_desc, fifo_mmap },                  /* genfs_badop */
1.26      pooka     233:        { &vop_fsync_desc, puffs_checkop },             /* fsync */
1.6       pooka     234:        { &vop_seek_desc, fifo_seek },                  /* genfs_badop */
                    235:        { &vop_remove_desc, fifo_remove },              /* genfs_badop */
                    236:        { &vop_link_desc, fifo_link },                  /* genfs_badop */
                    237:        { &vop_rename_desc, fifo_rename },              /* genfs_badop */
                    238:        { &vop_mkdir_desc, fifo_mkdir },                /* genfs_badop */
                    239:        { &vop_rmdir_desc, fifo_rmdir },                /* genfs_badop */
                    240:        { &vop_symlink_desc, fifo_symlink },            /* genfs_badop */
                    241:        { &vop_readdir_desc, fifo_readdir },            /* genfs_badop */
                    242:        { &vop_readlink_desc, fifo_readlink },          /* genfs_badop */
                    243:        { &vop_abortop_desc, fifo_abortop },            /* genfs_badop */
1.26      pooka     244:        { &vop_inactive_desc, puffs_inactive },         /* REAL inactive */
                    245:        { &vop_reclaim_desc, puffs_reclaim },           /* REAL reclaim */
                    246:        { &vop_lock_desc, puffs_lock },                 /* REAL lock */
                    247:        { &vop_unlock_desc, puffs_unlock },             /* REAL unlock */
1.6       pooka     248:        { &vop_bmap_desc, fifo_bmap },                  /* dummy */
                    249:        { &vop_strategy_desc, fifo_strategy },          /* genfs_badop */
1.26      pooka     250:        { &vop_print_desc, puffs_print },               /* REAL print */
                    251:        { &vop_islocked_desc, puffs_islocked },         /* REAL islocked */
1.6       pooka     252:        { &vop_pathconf_desc, fifo_pathconf },          /* pathconf */
                    253:        { &vop_advlock_desc, fifo_advlock },            /* genfs_einval */
                    254:        { &vop_bwrite_desc, vn_bwrite },                /* bwrite */
                    255:        { &vop_putpages_desc, fifo_putpages },          /* genfs_null_putpages*/
                    256: #if 0
                    257:        { &vop_openextattr_desc, _openextattr },        /* openextattr */
                    258:        { &vop_closeextattr_desc, _closeextattr },      /* closeextattr */
                    259:        { &vop_getextattr_desc, _getextattr },          /* getextattr */
                    260:        { &vop_setextattr_desc, _setextattr },          /* setextattr */
                    261:        { &vop_listextattr_desc, _listextattr },        /* listextattr */
                    262:        { &vop_deleteextattr_desc, _deleteextattr },    /* deleteextattr */
                    263: #endif
                    264:        { NULL, NULL }
                    265: };
                    266: const struct vnodeopv_desc puffs_fifoop_opv_desc =
                    267:        { &puffs_fifoop_p, puffs_fifoop_entries };
                    268:
                    269:
1.17      pooka     270: /* "real" vnode operations */
                    271: int (**puffs_msgop_p)(void *);
                    272: const struct vnodeopv_entry_desc puffs_msgop_entries[] = {
                    273:        { &vop_default_desc, vn_default_error },
                    274:        { &vop_create_desc, puffs_create },             /* create */
                    275:         { &vop_mknod_desc, puffs_mknod },              /* mknod */
                    276:         { &vop_open_desc, puffs_open },                        /* open */
                    277:         { &vop_close_desc, puffs_close },              /* close */
                    278:         { &vop_access_desc, puffs_access },            /* access */
                    279:         { &vop_getattr_desc, puffs_getattr },          /* getattr */
                    280:         { &vop_setattr_desc, puffs_setattr },          /* setattr */
                    281:         { &vop_read_desc, puffs_read },                        /* read */
                    282:         { &vop_write_desc, puffs_write },              /* write */
                    283:         { &vop_fcntl_desc, puffs_fcntl },              /* fcntl */
                    284:         { &vop_ioctl_desc, puffs_ioctl },              /* ioctl */
                    285:         { &vop_fsync_desc, puffs_fsync },              /* fsync */
                    286:         { &vop_seek_desc, puffs_seek },                        /* seek */
                    287:         { &vop_remove_desc, puffs_remove },            /* remove */
                    288:         { &vop_link_desc, puffs_link },                        /* link */
                    289:         { &vop_rename_desc, puffs_rename },            /* rename */
                    290:         { &vop_mkdir_desc, puffs_mkdir },              /* mkdir */
                    291:         { &vop_rmdir_desc, puffs_rmdir },              /* rmdir */
                    292:         { &vop_symlink_desc, puffs_symlink },          /* symlink */
                    293:         { &vop_readdir_desc, puffs_readdir },          /* readdir */
                    294:         { &vop_readlink_desc, puffs_readlink },                /* readlink */
                    295:         { &vop_print_desc, puffs_print },              /* print */
                    296:         { &vop_islocked_desc, puffs_islocked },                /* islocked */
                    297:         { &vop_pathconf_desc, puffs_pathconf },                /* pathconf */
                    298:         { &vop_advlock_desc, puffs_advlock },          /* advlock */
                    299:         { &vop_getpages_desc, genfs_getpages },                /* getpages */
                    300:         { &vop_putpages_desc, genfs_putpages },                /* putpages */
                    301:        { NULL, NULL }
                    302: };
                    303: const struct vnodeopv_desc puffs_msgop_opv_desc =
                    304:        { &puffs_msgop_p, puffs_msgop_entries };
                    305:
1.5       pooka     306:
1.1       pooka     307: #define LOCKEDVP(a) (VOP_ISLOCKED(a) ? (a) : NULL)
                    308:
                    309:
1.17      pooka     310: /*
                    311:  * This is a generic vnode operation handler.  It checks if the necessary
                    312:  * operations for the called vnode operation are implemented by userspace
                    313:  * and either returns a dummy return value or proceeds to call the real
                    314:  * vnode operation from puffs_msgop_v.
                    315:  *
                    316:  * XXX: this should described elsewhere and autogenerated, the complexity
                    317:  * of the vnode operations vectors and their interrelationships is also
                    318:  * getting a bit out of hand.  Another problem is that we need this same
                    319:  * information in the fs server code, so keeping the two in sync manually
                    320:  * is not a viable (long term) plan.
                    321:  */
                    322:
                    323: /* not supported, handle locking protocol */
                    324: #define CHECKOP_NOTSUPP(op)                                            \
                    325: case VOP_##op##_DESCOFFSET:                                            \
                    326:        if (pmp->pmp_vnopmask[PUFFS_VN_##op] == 0)                      \
                    327:                return genfs_eopnotsupp(v);                             \
                    328:        break
                    329:
                    330: /* always succeed, no locking */
                    331: #define CHECKOP_SUCCESS(op)                                            \
                    332: case VOP_##op##_DESCOFFSET:                                            \
                    333:        if (pmp->pmp_vnopmask[PUFFS_VN_##op] == 0)                      \
                    334:                return 0;                                               \
                    335:        break
                    336:
                    337: int
                    338: puffs_checkop(void *v)
                    339: {
                    340:        struct vop_generic_args /* {
                    341:                struct vnodeop_desc *a_desc;
                    342:                spooky mystery contents;
                    343:        } */ *ap = v;
                    344:        struct vnodeop_desc *desc = ap->a_desc;
                    345:        struct puffs_mount *pmp;
                    346:        struct vnode *vp;
                    347:        int offset;
                    348:
                    349:        DPRINTF_VERBOSE(("checkop call %s (%d)\n",
                    350:            ap->a_desc->vdesc_name, ap->a_desc->vdesc_offset));
                    351:
                    352:        offset = ap->a_desc->vdesc_vp_offsets[0];
                    353: #ifdef DIAGNOSTIC
                    354:        if (offset == VDESC_NO_OFFSET)
                    355:                panic("puffs_checkop: no vnode, why did you call me?");
                    356: #endif
                    357:        vp = *VOPARG_OFFSETTO(struct vnode **, offset, ap);
                    358:        pmp = MPTOPUFFSMP(vp->v_mount);
                    359:
1.18      pooka     360:        if ((pmp->pmp_flags & PUFFS_KFLAG_ALLOPS) == 0) {
1.17      pooka     361:                switch (desc->vdesc_offset) {
                    362:                        CHECKOP_NOTSUPP(CREATE);
                    363:                        CHECKOP_NOTSUPP(MKNOD);
                    364:                        CHECKOP_NOTSUPP(GETATTR);
                    365:                        CHECKOP_NOTSUPP(SETATTR);
                    366:                        CHECKOP_NOTSUPP(READ);
                    367:                        CHECKOP_NOTSUPP(WRITE);
                    368:                        CHECKOP_NOTSUPP(FCNTL);
                    369:                        CHECKOP_NOTSUPP(IOCTL);
                    370:                        CHECKOP_NOTSUPP(REMOVE);
                    371:                        CHECKOP_NOTSUPP(LINK);
                    372:                        CHECKOP_NOTSUPP(RENAME);
                    373:                        CHECKOP_NOTSUPP(MKDIR);
                    374:                        CHECKOP_NOTSUPP(RMDIR);
                    375:                        CHECKOP_NOTSUPP(SYMLINK);
                    376:                        CHECKOP_NOTSUPP(READDIR);
                    377:                        CHECKOP_NOTSUPP(READLINK);
                    378:                        CHECKOP_NOTSUPP(PRINT);
                    379:                        CHECKOP_NOTSUPP(PATHCONF);
                    380:                        CHECKOP_NOTSUPP(ADVLOCK);
                    381:
                    382:                        CHECKOP_SUCCESS(OPEN);
                    383:                        CHECKOP_SUCCESS(CLOSE);
                    384:                        CHECKOP_SUCCESS(ACCESS);
                    385:                        CHECKOP_SUCCESS(SEEK);
                    386:
1.31      pooka     387:                /* XXXfixme: read w/o write && cache == bad bad bad */
1.17      pooka     388:                case VOP_GETPAGES_DESCOFFSET:
                    389:                        if (!EXISTSOP(pmp, READ))
                    390:                                return genfs_eopnotsupp(v);
                    391:                        break;
                    392:
                    393:                case VOP_PUTPAGES_DESCOFFSET:
                    394:                        if (!EXISTSOP(pmp, WRITE))
                    395:                                return genfs_null_putpages(v);
                    396:                        break;
                    397:
                    398:                default:
                    399:                        panic("puffs_checkop: unhandled vnop %d",
                    400:                            desc->vdesc_offset);
                    401:                }
                    402:        }
                    403:
                    404:        return VOCALL(puffs_msgop_p, ap->a_desc->vdesc_offset, v);
                    405: }
                    406:
                    407:
1.1       pooka     408: int
                    409: puffs_lookup(void *v)
                    410: {
                    411:         struct vop_lookup_args /* {
1.17      pooka     412:                const struct vnodeop_desc *a_desc;
                    413:                struct vnode *a_dvp;
                    414:                struct vnode **a_vpp;
                    415:                struct componentname *a_cnp;
1.1       pooka     416:         } */ *ap = v;
                    417:        struct puffs_mount *pmp;
                    418:        struct componentname *cnp;
                    419:        struct vnode *vp, *dvp;
1.32      pooka     420:        struct puffs_node *dpn;
1.22      chs       421:        int isdot;
1.1       pooka     422:        int error;
                    423:
                    424:        PUFFS_VNREQ(lookup);
                    425:
                    426:        pmp = MPTOPUFFSMP(ap->a_dvp->v_mount);
                    427:        cnp = ap->a_cnp;
                    428:        dvp = ap->a_dvp;
                    429:        *ap->a_vpp = NULL;
                    430:
                    431:        /* first things first: check access */
                    432:        error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, cnp->cn_lwp);
                    433:        if (error)
                    434:                return error;
                    435:
                    436:        isdot = cnp->cn_namelen == 1 && *cnp->cn_nameptr == '.';
                    437:
                    438:        DPRINTF(("puffs_lookup: \"%s\", parent vnode %p, op: %lx\n",
                    439:            cnp->cn_nameptr, dvp, cnp->cn_nameiop));
                    440:
                    441:        /*
                    442:         * Check if someone fed it into the cache
                    443:         */
1.23      pooka     444:        if (PUFFS_DOCACHE(pmp)) {
                    445:                error = cache_lookup(dvp, ap->a_vpp, cnp);
1.30      pooka     446:
1.23      pooka     447:                if (error >= 0)
                    448:                        return error;
                    449:        }
1.1       pooka     450:
                    451:        if (isdot) {
                    452:                vp = ap->a_dvp;
                    453:                vref(vp);
                    454:                *ap->a_vpp = vp;
                    455:                return 0;
                    456:        }
                    457:
                    458:        puffs_makecn(&lookup_arg.pvnr_cn, cnp);
                    459:
                    460:        if (cnp->cn_flags & ISDOTDOT)
                    461:                VOP_UNLOCK(dvp, 0);
                    462:
                    463:        error = puffs_vntouser(pmp, PUFFS_VN_LOOKUP,
                    464:            &lookup_arg, sizeof(lookup_arg), VPTOPNC(dvp), LOCKEDVP(dvp), NULL);
                    465:        DPRINTF(("puffs_lookup: return of the userspace, part %d\n", error));
                    466:
                    467:        /*
1.23      pooka     468:         * In case of error, there is no new vnode to play with, so be
                    469:         * happy with the NULL value given to vpp in the beginning.
                    470:         * Also, check if this really was an error or the target was not
                    471:         * present.  Either treat it as a non-error for CREATE/RENAME or
                    472:         * enter the component into the negative name cache (if desired).
1.1       pooka     473:         */
                    474:        if (error) {
1.10      pooka     475:                if (error == ENOENT) {
1.1       pooka     476:                        if ((cnp->cn_flags & ISLASTCN)
                    477:                            && (cnp->cn_nameiop == CREATE
                    478:                              || cnp->cn_nameiop == RENAME)) {
                    479:                                cnp->cn_flags |= SAVENAME;
                    480:                                error = EJUSTRETURN;
1.23      pooka     481:                        } else {
                    482:                                if ((cnp->cn_flags & MAKEENTRY)
                    483:                                    && PUFFS_DOCACHE(pmp))
                    484:                                        cache_enter(dvp, NULL, cnp);
1.10      pooka     485:                        }
1.1       pooka     486:                }
1.22      chs       487:                goto errout;
1.1       pooka     488:        }
                    489:
1.32      pooka     490:        /*
                    491:         * Check that we don't get our parent node back, that would cause
                    492:         * a pretty obvious deadlock.
                    493:         */
                    494:        dpn = dvp->v_data;
                    495:        if (lookup_arg.pvnr_newnode == dpn->pn_cookie) {
                    496:                error = EINVAL;
                    497:                goto errout;
                    498:        }
                    499:
                    500:        /* XXX: race here */
1.33      pooka     501:        /* XXX2: this check for node existence twice */
1.30      pooka     502:        vp = puffs_pnode2vnode(pmp, lookup_arg.pvnr_newnode, 1);
1.1       pooka     503:        if (!vp) {
                    504:                error = puffs_getvnode(dvp->v_mount,
1.5       pooka     505:                    lookup_arg.pvnr_newnode, lookup_arg.pvnr_vtype,
1.8       pooka     506:                    lookup_arg.pvnr_size, lookup_arg.pvnr_rdev, &vp);
1.1       pooka     507:                if (error) {
1.22      chs       508:                        goto errout;
1.1       pooka     509:                }
                    510:                vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                    511:        }
1.23      pooka     512:        *ap->a_vpp = vp;
1.1       pooka     513:
1.23      pooka     514:        if ((cnp->cn_flags & MAKEENTRY) != 0 && PUFFS_DOCACHE(pmp))
1.1       pooka     515:                cache_enter(dvp, vp, cnp);
                    516:
1.23      pooka     517:  errout:
1.22      chs       518:        if (cnp->cn_flags & ISDOTDOT)
                    519:                vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
                    520:
                    521:        return error;
1.1       pooka     522: }
                    523:
                    524: int
                    525: puffs_create(void *v)
                    526: {
                    527:        struct vop_create_args /* {
                    528:                const struct vnodeop_desc *a_desc;
                    529:                struct vnode *a_dvp;
                    530:                struct vnode **a_vpp;
                    531:                struct componentname *a_cnp;
                    532:                struct vattr *a_vap;
                    533:        } */ *ap = v;
                    534:        int error;
                    535:
                    536:        PUFFS_VNREQ(create);
                    537:
                    538:        puffs_makecn(&create_arg.pvnr_cn, ap->a_cnp);
                    539:        create_arg.pvnr_va = *ap->a_vap;
                    540:
                    541:        error = puffs_vntouser(MPTOPUFFSMP(ap->a_dvp->v_mount), PUFFS_VN_CREATE,
                    542:            &create_arg, sizeof(create_arg), VPTOPNC(ap->a_dvp),
                    543:            ap->a_dvp, NULL);
                    544:        if (error)
1.4       pooka     545:                goto out;
1.1       pooka     546:
1.4       pooka     547:        error = puffs_newnode(ap->a_dvp->v_mount, ap->a_dvp, ap->a_vpp,
1.5       pooka     548:            create_arg.pvnr_newnode, ap->a_cnp, ap->a_vap->va_type, 0);
1.4       pooka     549:
                    550:  out:
                    551:        if (error || (ap->a_cnp->cn_flags & SAVESTART) == 0)
                    552:                PNBUF_PUT(ap->a_cnp->cn_pnbuf);
                    553:        vput(ap->a_dvp);
                    554:        return error;
1.1       pooka     555: }
                    556:
                    557: int
                    558: puffs_mknod(void *v)
                    559: {
                    560:        struct vop_mknod_args /* {
                    561:                const struct vnodeop_desc *a_desc;
                    562:                struct vnode *a_dvp;
                    563:                struct vnode **a_vpp;
                    564:                struct componentname *a_cnp;
                    565:                struct vattr *a_vap;
                    566:        } */ *ap = v;
                    567:        int error;
                    568:
                    569:        PUFFS_VNREQ(mknod);
                    570:
                    571:        puffs_makecn(&mknod_arg.pvnr_cn, ap->a_cnp);
                    572:        mknod_arg.pvnr_va = *ap->a_vap;
                    573:
                    574:        error = puffs_vntouser(MPTOPUFFSMP(ap->a_dvp->v_mount), PUFFS_VN_MKNOD,
                    575:            &mknod_arg, sizeof(mknod_arg), VPTOPNC(ap->a_dvp), ap->a_dvp, NULL);
                    576:        if (error)
1.4       pooka     577:                goto out;
1.1       pooka     578:
1.4       pooka     579:        error = puffs_newnode(ap->a_dvp->v_mount, ap->a_dvp, ap->a_vpp,
1.5       pooka     580:            mknod_arg.pvnr_newnode, ap->a_cnp, ap->a_vap->va_type,
                    581:            ap->a_vap->va_rdev);
1.4       pooka     582:
                    583:  out:
                    584:        if (error || (ap->a_cnp->cn_flags & SAVESTART) == 0)
                    585:                PNBUF_PUT(ap->a_cnp->cn_pnbuf);
                    586:        vput(ap->a_dvp);
                    587:        return error;
1.1       pooka     588: }
                    589:
                    590: int
                    591: puffs_open(void *v)
                    592: {
                    593:        struct vop_open_args /* {
                    594:                const struct vnodeop_desc *a_desc;
                    595:                struct vnode *a_vp;
                    596:                int a_mode;
                    597:                kauth_cred_t a_cred;
                    598:                struct lwp *a_l;
                    599:        } */ *ap = v;
                    600:
                    601:        PUFFS_VNREQ(open);
                    602:
                    603:        open_arg.pvnr_mode = ap->a_mode;
                    604:        puffs_credcvt(&open_arg.pvnr_cred, ap->a_cred);
                    605:        open_arg.pvnr_pid = puffs_lwp2pid(ap->a_l);
                    606:
                    607:        return puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount), PUFFS_VN_OPEN,
                    608:            &open_arg, sizeof(open_arg), VPTOPNC(ap->a_vp), ap->a_vp, NULL);
                    609: }
                    610:
                    611: int
                    612: puffs_close(void *v)
                    613: {
                    614:        struct vop_close_args /* {
                    615:                const struct vnodeop_desc *a_desc;
                    616:                struct vnode *a_vp;
                    617:                int a_fflag;
                    618:                kauth_cred_t a_cred;
                    619:                struct lwp *a_l;
                    620:        } */ *ap = v;
                    621:
                    622:        PUFFS_VNREQ(close);
                    623:
                    624:        close_arg.pvnr_fflag = ap->a_fflag;
                    625:        puffs_credcvt(&close_arg.pvnr_cred, ap->a_cred);
                    626:        close_arg.pvnr_pid = puffs_lwp2pid(ap->a_l);
                    627:
                    628:        return puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount), PUFFS_VN_CLOSE,
                    629:            &close_arg, sizeof(close_arg), VPTOPNC(ap->a_vp), ap->a_vp, NULL);
                    630: }
                    631:
                    632: int
                    633: puffs_access(void *v)
                    634: {
                    635:        struct vop_access_args /* {
                    636:                const struct vnodeop_desc *a_desc;
                    637:                struct vnode *a_vp;
                    638:                int a_mode;
                    639:                kauth_cred_t a_cred;
                    640:                struct lwp *a_l;
                    641:        } */ *ap = v;
                    642:
                    643:        PUFFS_VNREQ(access);
                    644:
                    645:        access_arg.pvnr_mode = ap->a_mode;
                    646:        access_arg.pvnr_pid = puffs_lwp2pid(ap->a_l);
                    647:        puffs_credcvt(&access_arg.pvnr_cred, ap->a_cred);
                    648:
1.8       pooka     649:        return puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount), PUFFS_VN_ACCESS,
1.1       pooka     650:            &access_arg, sizeof(access_arg), VPTOPNC(ap->a_vp), ap->a_vp, NULL);
                    651: }
                    652:
                    653: int
                    654: puffs_getattr(void *v)
                    655: {
                    656:        struct vop_getattr_args /* {
                    657:                const struct vnodeop_desc *a_desc;
                    658:                struct vnode *a_vp;
                    659:                struct vattr *a_vap;
                    660:                kauth_cred_t a_cred;
                    661:                struct lwp *a_l;
                    662:        } */ *ap = v;
1.13      pooka     663:        struct mount *mp;
1.1       pooka     664:        int error;
                    665:
                    666:        PUFFS_VNREQ(getattr);
                    667:
1.13      pooka     668:        mp = ap->a_vp->v_mount;
                    669:
1.1       pooka     670:        vattr_null(&getattr_arg.pvnr_va);
                    671:        puffs_credcvt(&getattr_arg.pvnr_cred, ap->a_cred);
                    672:        getattr_arg.pvnr_pid = puffs_lwp2pid(ap->a_l);
                    673:
                    674:        /*
                    675:         * XXX + XX (dos equis): this can't go through the unlock/lock
                    676:         * cycle, since it can be called from uvn_attach(), which fiddles
                    677:         * around with VXLOCK and therefore breaks vn_lock().  Proper
                    678:         * fix pending.
                    679:         */
                    680:        error = puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount), PUFFS_VN_GETATTR,
                    681:            &getattr_arg, sizeof(getattr_arg), VPTOPNC(ap->a_vp),
                    682:            NULL /* XXXseeabove: should be LOCKEDVP(ap->a_vp) */, NULL);
                    683:        if (error)
                    684:                return error;
                    685:
                    686:        (void)memcpy(ap->a_vap, &getattr_arg.pvnr_va, sizeof(struct vattr));
                    687:
1.13      pooka     688:        /*
                    689:         * fill in information userspace does not have
                    690:         * XXX: but would it be better to do fsid at the generic level?
                    691:         */
                    692:        ap->a_vap->va_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0];
                    693:
1.1       pooka     694:        return 0;
                    695: }
                    696:
                    697: int
                    698: puffs_setattr(void *v)
                    699: {
                    700:        struct vop_getattr_args /* {
                    701:                const struct vnodeop_desc *a_desc;
                    702:                struct vnode *a_vp;
                    703:                struct vattr *a_vap;
                    704:                kauth_cred_t a_cred;
                    705:                struct lwp *a_l;
                    706:        } */ *ap = v;
1.8       pooka     707:        int error;
1.1       pooka     708:
                    709:        PUFFS_VNREQ(setattr);
                    710:
                    711:        (void)memcpy(&setattr_arg.pvnr_va, ap->a_vap, sizeof(struct vattr));
                    712:        puffs_credcvt(&setattr_arg.pvnr_cred, ap->a_cred);
                    713:        setattr_arg.pvnr_pid = puffs_lwp2pid(ap->a_l);
                    714:
1.8       pooka     715:        error = puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount), PUFFS_VN_SETATTR,
1.1       pooka     716:            &setattr_arg, sizeof(setattr_arg), VPTOPNC(ap->a_vp),
                    717:            ap->a_vp, NULL);
1.8       pooka     718:        if (error)
                    719:                return error;
                    720:
                    721:        if (ap->a_vap->va_size != VNOVAL)
                    722:                uvm_vnp_setsize(ap->a_vp, ap->a_vap->va_size);
                    723:
                    724:        return 0;
1.1       pooka     725: }
                    726:
                    727: int
1.3       pooka     728: puffs_inactive(void *v)
                    729: {
                    730:        struct vop_inactive_args /* {
                    731:                const struct vnodeop_desc *a_desc;
                    732:                struct vnode *a_vp;
                    733:                struct lwp *a_l;
                    734:        } */ *ap = v;
1.17      pooka     735:        struct puffs_mount *pmp;
1.3       pooka     736:        struct puffs_node *pnode;
                    737:        int rv, vnrefs;
                    738:
                    739:        PUFFS_VNREQ(inactive);
                    740:
                    741:        /*
                    742:         * XXX: think about this after we really start unlocking
                    743:         * when going to userspace
                    744:         */
                    745:        pnode = ap->a_vp->v_data;
                    746:
1.17      pooka     747:        pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
                    748:
1.3       pooka     749:        inactive_arg.pvnr_pid = puffs_lwp2pid(ap->a_l);
                    750:
1.17      pooka     751:        if (EXISTSOP(pmp, INACTIVE))
                    752:                rv = puffs_vntouser(pmp, PUFFS_VN_INACTIVE,
                    753:                    &inactive_arg, sizeof(inactive_arg), VPTOPNC(ap->a_vp),
                    754:                    ap->a_vp, NULL);
                    755:        else
                    756:                rv = 1; /* see below */
1.3       pooka     757:
                    758:        /* can't trust userspace return value?  simulate safe answer */
                    759:        if (rv)
                    760:                vnrefs = 1;
                    761:        else
                    762:                vnrefs = inactive_arg.pvnr_backendrefs;
                    763:
                    764:        VOP_UNLOCK(ap->a_vp, 0);
                    765:
                    766:        /*
                    767:         * user server thinks it's gone?  then don't be afraid care,
                    768:         * node's life was already all it would ever be
                    769:         */
1.38    ! pooka     770:        if (vnrefs == 0) {
        !           771:                pnode->pn_stat |= PNODE_NOREFS;
1.3       pooka     772:                vrecycle(ap->a_vp, NULL, ap->a_l);
1.38    ! pooka     773:        }
1.3       pooka     774:
                    775:        return 0;
                    776: }
                    777:
1.34      pooka     778: /*
                    779:  * always FAF, we don't really care if the server wants to fail to
                    780:  * reclaim the node or not
                    781:  */
1.3       pooka     782: int
1.1       pooka     783: puffs_reclaim(void *v)
                    784: {
                    785:        struct vop_reclaim_args /* {
                    786:                const struct vnodeop_desc *a_desc;
                    787:                struct vnode *a_vp;
                    788:                struct lwp *a_l;
                    789:        } */ *ap = v;
                    790:        struct puffs_mount *pmp;
1.34      pooka     791:        struct puffs_vnreq_reclaim *reclaim_argp;
1.1       pooka     792:
1.17      pooka     793:        pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
                    794:
1.1       pooka     795:        /*
                    796:         * first things first: check if someone is trying to reclaim the
                    797:         * root vnode.  do not allow that to travel to userspace.
                    798:         * Note that we don't need to take the lock similarly to
                    799:         * puffs_root(), since there is only one of us.
                    800:         */
                    801:        if (ap->a_vp->v_flag & VROOT) {
                    802: #ifdef DIAGNOSTIC
                    803:                simple_lock(&pmp->pmp_lock);
                    804:                if (pmp->pmp_root == NULL)
                    805:                        panic("puffs_reclaim: releasing root vnode (%p) twice",
                    806:                            ap->a_vp);
                    807:                simple_unlock(&pmp->pmp_lock);
                    808: #endif
                    809:                pmp->pmp_root = NULL;
1.34      pooka     810:                goto out;
1.1       pooka     811:        }
                    812:
1.34      pooka     813:        if (!EXISTSOP(pmp, RECLAIM))
                    814:                goto out;
1.1       pooka     815:
1.34      pooka     816:        reclaim_argp = malloc(sizeof(struct puffs_vnreq_reclaim),
                    817:            M_PUFFS, M_WAITOK | M_ZERO);
                    818:        reclaim_argp->pvnr_pid = puffs_lwp2pid(ap->a_l);
                    819:
                    820:        puffs_vntouser_faf(pmp, PUFFS_VN_RECLAIM,
                    821:            reclaim_argp, sizeof(struct puffs_vnreq_reclaim),
                    822:            VPTOPNC(ap->a_vp));
1.1       pooka     823:
1.34      pooka     824:  out:
1.23      pooka     825:        if (PUFFS_DOCACHE(pmp))
                    826:                cache_purge(ap->a_vp);
1.1       pooka     827:        puffs_putvnode(ap->a_vp);
                    828:
                    829:        return 0;
                    830: }
                    831:
                    832: int
                    833: puffs_readdir(void *v)
                    834: {
                    835:        struct vop_readdir_args /* {
                    836:                const struct vnodeop_desc *a_desc;
                    837:                struct vnode *a_vp;
                    838:                struct uio *a_uio;
                    839:                kauth_cred_t a_cred;
                    840:                int *a_eofflag;
                    841:                off_t **a_cookies;
                    842:                int *a_ncookies;
                    843:        } */ *ap = v;
                    844:        struct puffs_vnreq_readdir *readdir_argp;
                    845:        size_t argsize;
                    846:        struct uio *uio = ap->a_uio;
                    847:        size_t howmuch;
                    848:        int error;
                    849:
                    850:        /* worry about these later */
                    851:        if (!(ap->a_cookies == NULL && ap->a_ncookies == NULL))
                    852:                return EOPNOTSUPP;
                    853:
                    854:        argsize = sizeof(struct puffs_vnreq_readdir);
                    855:        readdir_argp = malloc(argsize, M_PUFFS, M_ZERO | M_WAITOK);
                    856:
                    857:        puffs_credcvt(&readdir_argp->pvnr_cred, ap->a_cred);
                    858:        readdir_argp->pvnr_offset = uio->uio_offset;
                    859:        readdir_argp->pvnr_resid = uio->uio_resid;
                    860:
                    861:        error = puffs_vntouser_adjbuf(MPTOPUFFSMP(ap->a_vp->v_mount),
                    862:            PUFFS_VN_READDIR, (void **)&readdir_argp, &argsize,
1.19      pooka     863:            readdir_argp->pvnr_resid, VPTOPNC(ap->a_vp), ap->a_vp, NULL);
1.1       pooka     864:        if (error)
                    865:                goto out;
                    866:
                    867:        /* userspace is cheating? */
                    868:        if (readdir_argp->pvnr_resid > uio->uio_resid) {
                    869:                error = EINVAL;
                    870:                goto out;
                    871:        }
                    872:
                    873:        /* bouncy-wouncy with the directory data */
                    874:        howmuch = uio->uio_resid - readdir_argp->pvnr_resid;
1.29      pooka     875:        /* XXX: we could let userlandia tell its opinion first time 'round */
                    876:        if (howmuch == 0) {
                    877:                *ap->a_eofflag = 1;
                    878:                goto out;
                    879:        }
1.1       pooka     880:        error = uiomove(readdir_argp->pvnr_dent, howmuch, uio);
                    881:        if (error)
                    882:                goto out;
                    883:        uio->uio_offset = readdir_argp->pvnr_offset;
                    884:
                    885:  out:
                    886:        free(readdir_argp, M_PUFFS);
                    887:        return error;
                    888: }
                    889:
                    890: int
                    891: puffs_poll(void *v)
                    892: {
                    893:        struct vop_poll_args /* {
                    894:                const struct vnodeop_desc *a_desc;
                    895:                struct vnode *a_vp;
                    896:                int a_events;
                    897:                struct lwp *a_l;
                    898:        } */ *ap = v;
                    899:
                    900:        PUFFS_VNREQ(poll);
                    901:
                    902:        poll_arg.pvnr_events = ap->a_events;
                    903:        poll_arg.pvnr_pid = puffs_lwp2pid(ap->a_l);
                    904:
                    905:        return puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount), PUFFS_VN_POLL,
                    906:            &poll_arg, sizeof(poll_arg), VPTOPNC(ap->a_vp), NULL, NULL);
                    907: }
                    908:
                    909: int
                    910: puffs_fsync(void *v)
                    911: {
                    912:        struct vop_fsync_args /* {
                    913:                const struct vnodeop_desc *a_desc;
                    914:                struct vnode *a_vp;
                    915:                kauth_cred_t a_cred;
                    916:                int a_flags;
                    917:                off_t a_offlo;
                    918:                off_t a_offhi;
                    919:                struct lwp *a_l;
                    920:        } */ *ap = v;
1.31      pooka     921:        struct puffs_mount *pmp;
1.8       pooka     922:        struct puffs_vnreq_fsync *fsync_argp;
                    923:        struct vnode *vp;
1.38    ! pooka     924:        struct puffs_node *pn;
1.35      pooka     925:        int pflags, error, dofaf;
1.1       pooka     926:
                    927:        PUFFS_VNREQ(fsync);
                    928:
1.8       pooka     929:        vp = ap->a_vp;
1.38    ! pooka     930:        pn = VPTOPP(vp);
1.31      pooka     931:        pmp = MPTOPUFFSMP(vp->v_mount);
1.8       pooka     932:
                    933:        pflags = PGO_CLEANIT;
1.31      pooka     934:        if (ap->a_flags & FSYNC_WAIT)
1.8       pooka     935:                pflags |= PGO_SYNCIO;
                    936:
                    937:        /*
                    938:         * flush pages to avoid being overly dirty
                    939:         */
                    940:        simple_lock(&vp->v_interlock);
                    941:        error = VOP_PUTPAGES(vp, trunc_page(ap->a_offlo),
                    942:            round_page(ap->a_offhi), pflags);
                    943:        if (error)
                    944:                return error;
                    945:
1.31      pooka     946:        /*
                    947:         * HELLO!  We exit already here if the user server does not
1.38    ! pooka     948:         * support fsync OR if we should call fsync for a node which
        !           949:         * has references neither in the kernel or the fs server.
        !           950:         * Otherwise we continue to issue fsync() forward.
1.31      pooka     951:         */
1.38    ! pooka     952:        if (!EXISTSOP(pmp, FSYNC) || (pn->pn_stat & PNODE_NOREFS))
1.31      pooka     953:                return 0;
                    954:
1.35      pooka     955:        dofaf = (ap->a_flags & FSYNC_WAIT) == 0;
                    956:        /*
                    957:         * We abuse VXLOCK to mean "vnode is going to die", so we issue
                    958:         * only FAFs for those.  Otherwise there's a danger of deadlock,
                    959:         * since the execution context here might be the user server
                    960:         * doing some operation on another fs, which in turn caused a
                    961:         * vnode to be reclaimed from the freelist for this fs.
                    962:         */
                    963:        if (dofaf == 0) {
                    964:                simple_lock(&vp->v_interlock);
                    965:                if (vp->v_flag & VXLOCK)
                    966:                        dofaf = 1;
                    967:                simple_unlock(&vp->v_interlock);
                    968:        }
                    969:
                    970:        if (dofaf == 0) {
1.31      pooka     971:                fsync_argp = &fsync_arg;
                    972:        } else {
                    973:                fsync_argp = malloc(sizeof(struct puffs_vnreq_fsync),
                    974:                    M_PUFFS, M_ZERO | M_NOWAIT);
                    975:                if (fsync_argp == NULL)
                    976:                        return ENOMEM;
                    977:        }
                    978:
1.8       pooka     979:        puffs_credcvt(&fsync_argp->pvnr_cred, ap->a_cred);
                    980:        fsync_argp->pvnr_flags = ap->a_flags;
                    981:        fsync_argp->pvnr_offlo = ap->a_offlo;
                    982:        fsync_argp->pvnr_offhi = ap->a_offhi;
                    983:        fsync_argp->pvnr_pid = puffs_lwp2pid(ap->a_l);
1.1       pooka     984:
                    985:        /*
                    986:         * XXX: see comment at puffs_getattr about locking
1.8       pooka     987:         *
                    988:         * If we are not required to wait, do a FAF operation.
                    989:         * Otherwise block here.
1.1       pooka     990:         */
1.35      pooka     991:        if (dofaf == 0) {
1.8       pooka     992:                error =  puffs_vntouser(MPTOPUFFSMP(vp->v_mount),
                    993:                    PUFFS_VN_FSYNC, fsync_argp, sizeof(*fsync_argp),
                    994:                    VPTOPNC(vp), NULL /* XXXshouldbe: vp */, NULL);
                    995:        } else {
                    996:                /* FAF is always "succesful" */
                    997:                error = 0;
                    998:                puffs_vntouser_faf(MPTOPUFFSMP(vp->v_mount),
                    999:                    PUFFS_VN_FSYNC, fsync_argp, sizeof(*fsync_argp),
                   1000:                    VPTOPNC(vp));
                   1001:        }
                   1002:
                   1003:        return error;
1.1       pooka    1004: }
                   1005:
                   1006: int
                   1007: puffs_seek(void *v)
                   1008: {
                   1009:        struct vop_seek_args /* {
                   1010:                const struct vnodeop_desc *a_desc;
                   1011:                struct vnode *a_vp;
                   1012:                off_t a_oldoff;
                   1013:                off_t a_newoff;
                   1014:                kauth_cred_t a_cred;
                   1015:        } */ *ap = v;
                   1016:
                   1017:        PUFFS_VNREQ(seek);
                   1018:
                   1019:        seek_arg.pvnr_oldoff = ap->a_oldoff;
                   1020:        seek_arg.pvnr_newoff = ap->a_newoff;
                   1021:        puffs_credcvt(&seek_arg.pvnr_cred, ap->a_cred);
                   1022:
                   1023:        /*
                   1024:         * XXX: seems like seek is called with an unlocked vp, but
                   1025:         * it can't hurt to play safe
                   1026:         */
                   1027:        return puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount), PUFFS_VN_SEEK,
                   1028:            &seek_arg, sizeof(seek_arg), VPTOPNC(ap->a_vp),
                   1029:            LOCKEDVP(ap->a_vp), NULL);
                   1030: }
                   1031:
                   1032: int
                   1033: puffs_remove(void *v)
                   1034: {
                   1035:        struct vop_remove_args /* {
                   1036:                const struct vnodeop_desc *a_desc;
                   1037:                struct vnode *a_dvp;
                   1038:                struct vnode *a_vp;
                   1039:                struct componentname *a_cnp;
                   1040:        } */ *ap = v;
                   1041:        int error;
                   1042:
                   1043:        PUFFS_VNREQ(remove);
                   1044:
                   1045:        remove_arg.pvnr_cookie_targ = VPTOPNC(ap->a_vp);
                   1046:        puffs_makecn(&remove_arg.pvnr_cn, ap->a_cnp);
                   1047:
                   1048:        error = puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount), PUFFS_VN_REMOVE,
                   1049:            &remove_arg, sizeof(remove_arg), VPTOPNC(ap->a_dvp),
                   1050:            ap->a_dvp, ap->a_vp);
                   1051:
                   1052:        vput(ap->a_vp);
1.25      pooka    1053:        if (ap->a_dvp == ap->a_vp)
                   1054:                vrele(ap->a_dvp);
                   1055:        else
                   1056:                vput(ap->a_dvp);
1.1       pooka    1057:
                   1058:        return error;
                   1059: }
                   1060:
                   1061: int
                   1062: puffs_mkdir(void *v)
                   1063: {
                   1064:        struct vop_mkdir_args /* {
                   1065:                const struct vnodeop_desc *a_desc;
                   1066:                struct vnode *a_dvp;
                   1067:                struct vnode **a_vpp;
                   1068:                struct componentname *a_cnp;
                   1069:                struct vattr *a_vap;
                   1070:        } */ *ap = v;
                   1071:        int error;
                   1072:
                   1073:        PUFFS_VNREQ(mkdir);
                   1074:
                   1075:        puffs_makecn(&mkdir_arg.pvnr_cn, ap->a_cnp);
                   1076:        mkdir_arg.pvnr_va = *ap->a_vap;
                   1077:
                   1078:        /* XXX: wouldn't need to relock dvp, but that's life */
                   1079:        error = puffs_vntouser(MPTOPUFFSMP(ap->a_dvp->v_mount), PUFFS_VN_MKDIR,
                   1080:            &mkdir_arg, sizeof(mkdir_arg), VPTOPNC(ap->a_dvp), ap->a_dvp, NULL);
                   1081:        if (error)
1.4       pooka    1082:                goto out;
1.1       pooka    1083:
1.4       pooka    1084:        error = puffs_newnode(ap->a_dvp->v_mount, ap->a_dvp, ap->a_vpp,
1.5       pooka    1085:            mkdir_arg.pvnr_newnode, ap->a_cnp, VDIR, 0);
1.4       pooka    1086:
                   1087:  out:
                   1088:        if (error || (ap->a_cnp->cn_flags & SAVESTART) == 0)
                   1089:                PNBUF_PUT(ap->a_cnp->cn_pnbuf);
                   1090:        vput(ap->a_dvp);
                   1091:        return error;
1.1       pooka    1092: }
                   1093:
                   1094: int
                   1095: puffs_rmdir(void *v)
                   1096: {
                   1097:        struct vop_rmdir_args /* {
                   1098:                const struct vnodeop_desc *a_desc;
                   1099:                struct vnode *a_dvp;
                   1100:                struct vnode *a_vp;
                   1101:                struct componentname *a_cnp;
                   1102:        } */ *ap = v;
                   1103:        int error;
                   1104:
                   1105:        PUFFS_VNREQ(rmdir);
                   1106:
                   1107:        rmdir_arg.pvnr_cookie_targ = VPTOPNC(ap->a_vp);
                   1108:        puffs_makecn(&rmdir_arg.pvnr_cn, ap->a_cnp);
                   1109:
                   1110:        error = puffs_vntouser(MPTOPUFFSMP(ap->a_dvp->v_mount), PUFFS_VN_RMDIR,
                   1111:            &rmdir_arg, sizeof(rmdir_arg), VPTOPNC(ap->a_dvp),
                   1112:            ap->a_dvp, ap->a_vp);
                   1113:
1.23      pooka    1114:        /* XXX: some call cache_purge() *for both vnodes* here, investigate */
                   1115:
1.1       pooka    1116:        vput(ap->a_dvp);
                   1117:        vput(ap->a_vp);
                   1118:
                   1119:        return error;
                   1120: }
                   1121:
                   1122: int
                   1123: puffs_link(void *v)
                   1124: {
                   1125:        struct vop_link_args /* {
                   1126:                const struct vnodeop_desc *a_desc;
                   1127:                struct vnode *a_dvp;
                   1128:                struct vnode *a_vp;
                   1129:                struct componentname *a_cnp;
                   1130:        } */ *ap = v;
                   1131:        int error;
                   1132:
                   1133:        PUFFS_VNREQ(link);
                   1134:
                   1135:        link_arg.pvnr_cookie_targ = VPTOPNC(ap->a_vp);
                   1136:        puffs_makecn(&link_arg.pvnr_cn, ap->a_cnp);
                   1137:
                   1138:        error = puffs_vntouser(MPTOPUFFSMP(ap->a_dvp->v_mount), PUFFS_VN_LINK,
                   1139:            &link_arg, sizeof(link_arg), VPTOPNC(ap->a_dvp), ap->a_dvp, NULL);
                   1140:
                   1141:        vput(ap->a_dvp);
                   1142:
                   1143:        return error;
                   1144: }
                   1145:
                   1146: int
                   1147: puffs_symlink(void *v)
                   1148: {
                   1149:        struct vop_symlink_args /* {
                   1150:                const struct vnodeop_desc *a_desc;
                   1151:                struct vnode *a_dvp;
                   1152:                struct vnode **a_vpp;
                   1153:                struct componentname *a_cnp;
                   1154:                struct vattr *a_vap;
                   1155:                char *a_target;
                   1156:        } */ *ap = v;
                   1157:        int error;
                   1158:
                   1159:        PUFFS_VNREQ(symlink); /* XXX: large structure */
                   1160:
                   1161:        *ap->a_vpp = NULL;
                   1162:
                   1163:        puffs_makecn(&symlink_arg.pvnr_cn, ap->a_cnp);
                   1164:        symlink_arg.pvnr_va = *ap->a_vap;
                   1165:        (void)strlcpy(symlink_arg.pvnr_link, ap->a_target,
                   1166:            sizeof(symlink_arg.pvnr_link));
                   1167:
                   1168:        /* XXX: don't need to relock parent */
                   1169:        error =  puffs_vntouser(MPTOPUFFSMP(ap->a_dvp->v_mount),
                   1170:            PUFFS_VN_SYMLINK, &symlink_arg, sizeof(symlink_arg),
                   1171:            VPTOPNC(ap->a_dvp), ap->a_dvp, NULL);
                   1172:        if (error)
1.4       pooka    1173:                goto out;
1.1       pooka    1174:
1.4       pooka    1175:        error = puffs_newnode(ap->a_dvp->v_mount, ap->a_dvp, ap->a_vpp,
1.5       pooka    1176:            symlink_arg.pvnr_newnode, ap->a_cnp, VLNK, 0);
1.4       pooka    1177:
                   1178:  out:
                   1179:        if (error || (ap->a_cnp->cn_flags & SAVESTART) == 0)
                   1180:                PNBUF_PUT(ap->a_cnp->cn_pnbuf);
                   1181:        vput(ap->a_dvp);
                   1182:        return error;
1.1       pooka    1183: }
                   1184:
                   1185: int
                   1186: puffs_readlink(void *v)
                   1187: {
                   1188:        struct vop_readlink_args /* {
                   1189:                const struct vnodeop_desc *a_desc;
                   1190:                struct vnode *a_vp;
                   1191:                struct uio *a_uio;
                   1192:                kauth_cred_t a_cred;
                   1193:        } */ *ap = v;
                   1194:        int error;
                   1195:
                   1196:        PUFFS_VNREQ(readlink);
                   1197:
                   1198:        puffs_credcvt(&readlink_arg.pvnr_cred, ap->a_cred);
                   1199:        readlink_arg.pvnr_linklen = sizeof(readlink_arg.pvnr_link);
                   1200:
                   1201:        error = puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount),
                   1202:            PUFFS_VN_READLINK, &readlink_arg, sizeof(readlink_arg),
                   1203:            VPTOPNC(ap->a_vp), ap->a_vp, NULL);
                   1204:        if (error)
                   1205:                return error;
                   1206:
                   1207:        readlink_arg.pvnr_link[readlink_arg.pvnr_linklen] = '\0';
                   1208:        return uiomove(&readlink_arg.pvnr_link, readlink_arg.pvnr_linklen,
                   1209:            ap->a_uio);
                   1210: }
                   1211:
                   1212: /* XXXXXXX: think about locking & userspace op delocking... */
                   1213: int
                   1214: puffs_rename(void *v)
                   1215: {
                   1216:        struct vop_rename_args /* {
                   1217:                const struct vnodeop_desc *a_desc;
                   1218:                struct vnode *a_fdvp;
                   1219:                struct vnode *a_fvp;
                   1220:                struct componentname *a_fcnp;
                   1221:                struct vnode *a_tdvp;
                   1222:                struct vnode *a_tvp;
                   1223:                struct componentname *a_tcnp;
                   1224:        } */ *ap = v;
                   1225:        int error;
                   1226:
                   1227:        PUFFS_VNREQ(rename);
                   1228:
                   1229:        if (ap->a_fvp->v_mount != ap->a_tdvp->v_mount) {
                   1230:                error = EXDEV;
                   1231:                goto out;
                   1232:        }
                   1233:
                   1234:        rename_arg.pvnr_cookie_src = VPTOPNC(ap->a_fvp);
                   1235:        rename_arg.pvnr_cookie_targdir = VPTOPNC(ap->a_tdvp);
                   1236:        if (ap->a_tvp)
                   1237:                rename_arg.pvnr_cookie_targ = VPTOPNC(ap->a_tvp);
                   1238:        else
                   1239:                rename_arg.pvnr_cookie_targ = NULL;
                   1240:        puffs_makecn(&rename_arg.pvnr_cn_src, ap->a_fcnp);
                   1241:        puffs_makecn(&rename_arg.pvnr_cn_targ, ap->a_tcnp);
                   1242:
                   1243:        error = puffs_vntouser(MPTOPUFFSMP(ap->a_fdvp->v_mount),
                   1244:            PUFFS_VN_RENAME, &rename_arg, sizeof(rename_arg),
                   1245:            VPTOPNC(ap->a_fdvp), NULL, NULL);
                   1246:
                   1247:  out:
                   1248:        if (ap->a_tvp != NULL)
                   1249:                vput(ap->a_tvp);
1.28      pooka    1250:        if (ap->a_tdvp == ap->a_tvp)
                   1251:                vrele(ap->a_tdvp);
                   1252:        else
                   1253:                vput(ap->a_tdvp);
1.1       pooka    1254:
                   1255:        vrele(ap->a_fdvp);
                   1256:        vrele(ap->a_fvp);
                   1257:
                   1258:        return error;
                   1259: }
                   1260:
                   1261: int
                   1262: puffs_read(void *v)
                   1263: {
                   1264:        struct vop_read_args /* {
                   1265:                const struct vnodeop_desc *a_desc;
                   1266:                struct vnode *a_vp;
                   1267:                struct uio *a_uio;
                   1268:                int a_ioflag;
                   1269:                kauth_cred_t a_cred;
                   1270:        } */ *ap = v;
                   1271:        struct puffs_vnreq_read *read_argp;
                   1272:        struct puffs_mount *pmp;
1.8       pooka    1273:        struct vnode *vp;
1.1       pooka    1274:        struct uio *uio;
1.8       pooka    1275:        void *win;
1.1       pooka    1276:        size_t tomove, argsize;
1.8       pooka    1277:        vsize_t bytelen;
1.11      pooka    1278:        int error, ubcflags;
1.1       pooka    1279:
                   1280:        uio = ap->a_uio;
1.8       pooka    1281:        vp = ap->a_vp;
                   1282:        read_argp = NULL;
                   1283:        error = 0;
1.11      pooka    1284:        pmp = MPTOPUFFSMP(vp->v_mount);
1.1       pooka    1285:
1.8       pooka    1286:        /* std sanity */
                   1287:        if (uio->uio_resid == 0)
                   1288:                return 0;
                   1289:        if (uio->uio_offset < 0)
                   1290:                return EINVAL;
1.1       pooka    1291:
1.23      pooka    1292:        if (vp->v_type == VREG && PUFFS_DOCACHE(pmp)) {
1.8       pooka    1293:                const int advice = IO_ADV_DECODE(ap->a_ioflag);
1.1       pooka    1294:
1.12      pooka    1295:                ubcflags = 0;
1.15      pooka    1296:                if (UBC_WANT_UNMAP(vp))
1.12      pooka    1297:                        ubcflags = UBC_UNMAP;
                   1298:
1.8       pooka    1299:                while (uio->uio_resid > 0) {
                   1300:                        bytelen = MIN(uio->uio_resid,
                   1301:                            vp->v_size - uio->uio_offset);
                   1302:                        if (bytelen == 0)
                   1303:                                break;
                   1304:
                   1305:                        win = ubc_alloc(&vp->v_uobj, uio->uio_offset,
                   1306:                            &bytelen, advice, UBC_READ);
                   1307:                        error = uiomove(win, bytelen, uio);
1.11      pooka    1308:                        ubc_release(win, ubcflags);
1.8       pooka    1309:                        if (error)
                   1310:                                break;
1.1       pooka    1311:                }
                   1312:
1.8       pooka    1313:                if ((vp->v_mount->mnt_flag & MNT_NOATIME) == 0)
                   1314:                        puffs_updatenode(vp, PUFFS_UPDATEATIME);
                   1315:        } else {
1.1       pooka    1316:                /*
1.15      pooka    1317:                 * in case it's not a regular file or we're operating
                   1318:                 * uncached, do read in the old-fashioned style,
                   1319:                 * i.e. explicit read operations
1.1       pooka    1320:                 */
                   1321:
                   1322:                tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
1.8       pooka    1323:                argsize = sizeof(struct puffs_vnreq_read);
                   1324:                read_argp = malloc(argsize, M_PUFFS, M_WAITOK | M_ZERO);
                   1325:
                   1326:                error = 0;
                   1327:                while (uio->uio_resid > 0) {
                   1328:                        read_argp->pvnr_ioflag = ap->a_ioflag;
                   1329:                        read_argp->pvnr_resid = tomove;
                   1330:                        read_argp->pvnr_offset = uio->uio_offset;
                   1331:                        puffs_credcvt(&read_argp->pvnr_cred, ap->a_cred);
                   1332:
                   1333:                        argsize = sizeof(struct puffs_vnreq_read);
                   1334:                        error = puffs_vntouser_adjbuf(pmp, PUFFS_VN_READ,
                   1335:                            (void **)&read_argp, &argsize,
1.19      pooka    1336:                            read_argp->pvnr_resid, VPTOPNC(ap->a_vp),
1.8       pooka    1337:                            ap->a_vp, NULL);
                   1338:                        if (error)
                   1339:                                break;
                   1340:
                   1341:                        if (read_argp->pvnr_resid > tomove) {
                   1342:                                error = EINVAL;
                   1343:                                break;
                   1344:                        }
                   1345:
                   1346:                        error = uiomove(read_argp->pvnr_data,
                   1347:                            tomove - read_argp->pvnr_resid, uio);
                   1348:
                   1349:                        /*
                   1350:                         * in case the file is out of juice, resid from
                   1351:                         * userspace is != 0.  and the error-case is
                   1352:                         * quite obvious
                   1353:                         */
                   1354:                        if (error || read_argp->pvnr_resid)
                   1355:                                break;
                   1356:
                   1357:                        tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
                   1358:                }
1.1       pooka    1359:        }
                   1360:
1.8       pooka    1361:        if (read_argp)
                   1362:                free(read_argp, M_PUFFS);
1.1       pooka    1363:        return error;
                   1364: }
                   1365:
                   1366: int
                   1367: puffs_write(void *v)
                   1368: {
                   1369:        struct vop_write_args /* {
                   1370:                const struct vnodeop_desc *a_desc;
                   1371:                struct vnode *a_vp;
                   1372:                struct uio *a_uio;
                   1373:                int a_ioflag;
                   1374:                kauth_cred_t a_cred;
                   1375:        } */ *ap = v;
                   1376:        struct puffs_vnreq_write *write_argp;
                   1377:        struct puffs_mount *pmp;
                   1378:        struct uio *uio;
1.8       pooka    1379:        struct vnode *vp;
                   1380:        void *win;
1.1       pooka    1381:        size_t tomove, argsize;
1.8       pooka    1382:        off_t oldoff, newoff, origoff;
                   1383:        vsize_t bytelen;
1.15      pooka    1384:        int error, uflags;
1.11      pooka    1385:        int async, ubcflags;
1.1       pooka    1386:
1.8       pooka    1387:        vp = ap->a_vp;
1.1       pooka    1388:        uio = ap->a_uio;
1.8       pooka    1389:        async = vp->v_mount->mnt_flag & MNT_ASYNC;
                   1390:        error = uflags = 0;
                   1391:        write_argp = NULL;
1.11      pooka    1392:        pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
                   1393:
1.23      pooka    1394:        if (vp->v_type == VREG && PUFFS_DOCACHE(pmp)) {
1.12      pooka    1395:                ubcflags = 0;
1.15      pooka    1396:                if (UBC_WANT_UNMAP(vp))
1.12      pooka    1397:                        ubcflags = UBC_UNMAP;
                   1398:
1.8       pooka    1399:                /*
                   1400:                 * userspace *should* be allowed to control this,
                   1401:                 * but with UBC it's a bit unclear how to handle it
                   1402:                 */
                   1403:                if (ap->a_ioflag & IO_APPEND)
                   1404:                        uio->uio_offset = vp->v_size;
1.1       pooka    1405:
1.8       pooka    1406:                origoff = uio->uio_offset;
                   1407:                while (uio->uio_resid > 0) {
                   1408:                        uflags |= PUFFS_UPDATECTIME;
                   1409:                        uflags |= PUFFS_UPDATEMTIME;
                   1410:                        oldoff = uio->uio_offset;
                   1411:                        bytelen = uio->uio_resid;
                   1412:
                   1413:                        win = ubc_alloc(&vp->v_uobj, oldoff, &bytelen,
                   1414:                            UVM_ADV_NORMAL, UBC_WRITE);
                   1415:                        error = uiomove(win, bytelen, uio);
                   1416:
                   1417:                        /*
                   1418:                         * did we grow the file?
                   1419:                         * XXX: should probably ask userspace to extend
                   1420:                         * it's idea of the *first* before growing it
                   1421:                         * here.  Or we need some mechanism to "rollback"
                   1422:                         * in case putpages fails.
                   1423:                         */
                   1424:                        newoff = oldoff + bytelen;
                   1425:                        if (vp->v_size < newoff) {
                   1426:                                uflags |= PUFFS_UPDATESIZE;
                   1427:                                uvm_vnp_setsize(vp, newoff);
                   1428:
                   1429:                                /*
                   1430:                                 * in case we couldn't copy data to the
                   1431:                                 * window, zero it out so that we don't
                   1432:                                 * have any random leftovers in there.
                   1433:                                 */
                   1434:                                if (error)
                   1435:                                        memset(win, 0, bytelen);
                   1436:                        }
1.1       pooka    1437:
1.11      pooka    1438:                        ubc_release(win, ubcflags);
1.8       pooka    1439:                        if (error)
                   1440:                                break;
                   1441:
                   1442:                        /* ok, I really need to admit: why's this? */
                   1443:                        if (!async && oldoff >> 16 != uio->uio_offset >> 16) {
                   1444:                                simple_lock(&vp->v_interlock);
                   1445:                                error = VOP_PUTPAGES(vp, oldoff & ~0xffff,
                   1446:                                    uio->uio_offset & ~0xffff, PGO_CLEANIT);
                   1447:                                if (error)
                   1448:                                        break;
                   1449:                        }
1.1       pooka    1450:                }
1.8       pooka    1451:
1.15      pooka    1452:                if (error == 0 && ap->a_ioflag & IO_SYNC) {
1.8       pooka    1453:                        simple_lock(&vp->v_interlock);
                   1454:                        error = VOP_PUTPAGES(vp, trunc_page(origoff),
1.15      pooka    1455:                            round_page(uio->uio_offset),
                   1456:                            PGO_CLEANIT | PGO_SYNCIO);
1.1       pooka    1457:                }
                   1458:
1.8       pooka    1459:                puffs_updatenode(vp, uflags);
                   1460:        } else {
1.19      pooka    1461:                /* tomove is non-increasing */
1.1       pooka    1462:                tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
1.8       pooka    1463:                argsize = sizeof(struct puffs_vnreq_write) + tomove;
                   1464:                write_argp = malloc(argsize, M_PUFFS, M_WAITOK | M_ZERO);
                   1465:
                   1466:                while (uio->uio_resid > 0) {
                   1467:                        write_argp->pvnr_ioflag = ap->a_ioflag;
                   1468:                        write_argp->pvnr_resid = tomove;
                   1469:                        write_argp->pvnr_offset = uio->uio_offset;
                   1470:                        puffs_credcvt(&write_argp->pvnr_cred, ap->a_cred);
                   1471:                        error = uiomove(write_argp->pvnr_data, tomove, uio);
                   1472:                        if (error)
                   1473:                                break;
                   1474:
                   1475:                        error = puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount),
                   1476:                            PUFFS_VN_WRITE, write_argp, argsize,
                   1477:                            VPTOPNC(ap->a_vp), ap->a_vp, NULL);
                   1478:                        if (error) {
                   1479:                                /* restore uiomove */
                   1480:                                uio->uio_resid += tomove;
                   1481:                                uio->uio_offset -= tomove;
                   1482:                                break;
                   1483:                        }
                   1484:                        if (write_argp->pvnr_resid > tomove) {
                   1485:                                /*
                   1486:                                 * XXX: correct file size is a mystery,
                   1487:                                 * we can only guess
                   1488:                                 */
                   1489:                                error = EINVAL;
                   1490:                                break;
                   1491:                        }
                   1492:
                   1493:                        /* adjust file size */
1.20      pooka    1494:                        if (vp->v_size < uio->uio_offset)
                   1495:                                uvm_vnp_setsize(vp, uio->uio_offset);
1.8       pooka    1496:
                   1497:                        /* didn't move everything?  bad userspace.  bail */
                   1498:                        if (write_argp->pvnr_resid != 0) {
                   1499:                                uio->uio_resid += write_argp->pvnr_resid;
                   1500:                                uio->uio_offset -= write_argp->pvnr_resid;
                   1501:                                error = EIO;
                   1502:                                break;
                   1503:                        }
                   1504:
                   1505:                        tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
                   1506:                }
1.1       pooka    1507:        }
                   1508:
1.8       pooka    1509:        if (write_argp)
                   1510:                free(write_argp, M_PUFFS);
1.1       pooka    1511:        return error;
                   1512: }
                   1513:
                   1514: static int     puffs_fcnioctl(struct vop_ioctl_args * /*XXX*/, int);
                   1515:
                   1516: #define FCNIOCTL_ARG_MAX 1<<16
                   1517: int
                   1518: puffs_fcnioctl(struct vop_ioctl_args *ap, int puffsop)
                   1519: {
1.24      pooka    1520:
                   1521:        /* currently not supported */
                   1522:        return EOPNOTSUPP;
                   1523: #if 0
1.1       pooka    1524:        /* struct vop_ioctl_args {
                   1525:                const struct vnodeop_desc *a_desc;
                   1526:                struct vnode *a_vp;
                   1527:                u_long a_command;
                   1528:                void *a_data;
                   1529:                int a_fflag;
                   1530:                kauth_cred_t a_cred;
                   1531:                struct lwp *a_l;
                   1532:        } *ap = v; */
                   1533:        struct puffs_mount *pmp;
                   1534:        struct puffs_sizepark pspark;
                   1535:        void *kernbuf;
                   1536:        size_t copylen;
                   1537:        int error;
                   1538:
                   1539:        PUFFS_VNREQ(fcnioctl);
                   1540:
                   1541:        /*
                   1542:         * Since this op gives the filesystem (almost) complete control on
                   1543:         * how much it is allowed to copy from the calling process
                   1544:         * address space, do not enable it by default, since it would
                   1545:         * be a whopping security hole.
                   1546:         */
                   1547:        pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
1.18      pooka    1548:        if ((pmp->pmp_flags & PUFFS_KFLAG_ALLOWCTL) == 0)
1.1       pooka    1549:                return EINVAL; /* only shoe that fits */
                   1550:
                   1551:        /* fill in sizereq and store it */
                   1552:        pspark.pkso_reqid = puffs_getreqid(pmp);
                   1553:        pspark.pkso_reqtype = PUFFS_SIZEOPREQ_BUF_IN;
                   1554:        pspark.pkso_copybuf = ap->a_data;
                   1555:        pspark.pkso_bufsize = FCNIOCTL_ARG_MAX;
                   1556:        TAILQ_INSERT_TAIL(&pmp->pmp_req_sizepark, &pspark, pkso_entries);
                   1557:
                   1558:        /* then fill in actual request and shoot it off */
                   1559:        fcnioctl_arg.pvnr_command = ap->a_command;
                   1560:        fcnioctl_arg.pvnr_fflag = ap->a_fflag;
                   1561:        puffs_credcvt(&fcnioctl_arg.pvnr_cred, ap->a_cred);
                   1562:        fcnioctl_arg.pvnr_pid = puffs_lwp2pid(ap->a_l);
                   1563:
                   1564:        error = puffs_vntouser_req(MPTOPUFFSMP(ap->a_vp->v_mount), puffsop,
                   1565:            &fcnioctl_arg, sizeof(fcnioctl_arg), VPTOPNC(ap->a_vp),
                   1566:            pspark.pkso_reqid, NULL, NULL);
                   1567:
                   1568:        /* if we don't need to copy data, we're done */
                   1569:        if (error || !fcnioctl_arg.pvnr_copyback)
                   1570:                return error;
                   1571:
                   1572:        copylen = MIN(FCNIOCTL_ARG_MAX, fcnioctl_arg.pvnr_datalen);
                   1573:        kernbuf = malloc(copylen, M_PUFFS, M_WAITOK);
                   1574:        error = copyin(fcnioctl_arg.pvnr_data, kernbuf, copylen);
                   1575:        if (error)
                   1576:                goto out;
                   1577:        error = copyout(kernbuf, ap->a_data, copylen);
                   1578:
                   1579:  out:
                   1580:        free(kernbuf, M_PUFFS);
                   1581:        return error;
1.24      pooka    1582: #endif
1.1       pooka    1583: }
                   1584:
                   1585: int
                   1586: puffs_ioctl(void *v)
                   1587: {
                   1588:
                   1589:        return puffs_fcnioctl(v, PUFFS_VN_IOCTL);
                   1590: }
                   1591:
                   1592: int
                   1593: puffs_fcntl(void *v)
                   1594: {
                   1595:
                   1596:        return puffs_fcnioctl(v, PUFFS_VN_FCNTL);
                   1597: }
                   1598:
                   1599: int
                   1600: puffs_print(void *v)
                   1601: {
                   1602:        struct vop_print_args /* {
                   1603:                struct vnode *a_vp;
                   1604:        } */ *ap = v;
1.17      pooka    1605:        struct puffs_mount *pmp;
1.1       pooka    1606:        struct vnode *vp = ap->a_vp;
1.2       pooka    1607:        struct puffs_node *pn = vp->v_data;
1.1       pooka    1608:
                   1609:        PUFFS_VNREQ(print);
                   1610:
1.17      pooka    1611:        pmp = MPTOPUFFSMP(vp->v_mount);
                   1612:
1.1       pooka    1613:        /* kernel portion */
1.2       pooka    1614:        printf("tag VT_PUFFS, vnode %p, puffs node: %p,\n"
                   1615:            "    userspace cookie: %p\n", vp, pn, pn->pn_cookie);
1.6       pooka    1616:        if (vp->v_type == VFIFO)
                   1617:                fifo_printinfo(vp);
1.1       pooka    1618:        lockmgr_printinfo(&vp->v_lock);
                   1619:
                   1620:        /* userspace portion */
1.17      pooka    1621:        if (EXISTSOP(pmp, PRINT))
                   1622:                puffs_vntouser(pmp, PUFFS_VN_PRINT,
                   1623:                    &print_arg, sizeof(print_arg), VPTOPNC(ap->a_vp),
                   1624:                    LOCKEDVP(ap->a_vp), NULL);
                   1625:
                   1626:        return 0;
1.1       pooka    1627: }
                   1628:
                   1629: int
                   1630: puffs_pathconf(void *v)
                   1631: {
                   1632:        struct vop_pathconf_args /* {
                   1633:                const struct vnodeop_desc *a_desc;
                   1634:                struct vnode *a_vp;
                   1635:                int a_name;
                   1636:                register_t *a_retval;
                   1637:        } */ *ap = v;
                   1638:        int error;
                   1639:
                   1640:        PUFFS_VNREQ(pathconf);
                   1641:
                   1642:        pathconf_arg.pvnr_name = ap->a_name;
                   1643:
                   1644:        error = puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount),
                   1645:            PUFFS_VN_PATHCONF, &pathconf_arg, sizeof(pathconf_arg),
                   1646:            VPTOPNC(ap->a_vp), ap->a_vp, NULL);
                   1647:        if (error)
                   1648:                return error;
                   1649:
                   1650:        *ap->a_retval = pathconf_arg.pvnr_retval;
                   1651:
                   1652:        return 0;
                   1653: }
                   1654:
                   1655: int
                   1656: puffs_advlock(void *v)
                   1657: {
                   1658:        struct vop_advlock_args /* {
                   1659:                const struct vnodeop_desc *a_desc;
                   1660:                struct vnode *a_vp;
                   1661:                void *a_id;
                   1662:                int a_op;
                   1663:                struct flock *a_fl;
                   1664:                int a_flags;
                   1665:        } */ *ap = v;
                   1666:        int error;
                   1667:
                   1668:        PUFFS_VNREQ(advlock);
                   1669:
                   1670:        error = copyin(ap->a_fl, &advlock_arg.pvnr_fl, sizeof(struct flock));
                   1671:        if (error)
                   1672:                return error;
                   1673:        advlock_arg.pvnr_id = ap->a_id;
                   1674:        advlock_arg.pvnr_op = ap->a_op;
                   1675:        advlock_arg.pvnr_flags = ap->a_flags;
                   1676:
                   1677:        return puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount), PUFFS_VN_ADVLOCK,
                   1678:            &advlock_arg, sizeof(advlock_arg), VPTOPNC(ap->a_vp), NULL, NULL);
                   1679: }
1.8       pooka    1680: /*
                   1681:  * This maps itself to PUFFS_VN_READ/WRITE for data transfer.
                   1682:  */
                   1683: int
                   1684: puffs_strategy(void *v)
                   1685: {
                   1686:        struct vop_strategy_args /* {
                   1687:                const struct vnodeop_desc *a_desc;
                   1688:                struct vnode *a_vp;
                   1689:                struct buf *a_bp;
                   1690:        } */ *ap = v;
                   1691:        struct puffs_mount *pmp;
1.35      pooka    1692:        struct vnode *vp = ap->a_vp;
1.38    ! pooka    1693:        struct puffs_node *pn;
1.14      pooka    1694:        struct puffs_vnreq_read *read_argp = NULL;
                   1695:        struct puffs_vnreq_write *write_argp = NULL;
1.8       pooka    1696:        struct buf *bp;
                   1697:        size_t argsize;
1.14      pooka    1698:        size_t tomove, moved;
1.35      pooka    1699:        int error, dowritefaf;
1.8       pooka    1700:
1.35      pooka    1701:        pmp = MPTOPUFFSMP(vp->v_mount);
1.8       pooka    1702:        bp = ap->a_bp;
1.36      pooka    1703:        error = 0;
                   1704:        dowritefaf = 0;
1.38    ! pooka    1705:        pn = VPTOPP(vp);
        !          1706:
        !          1707:        if (((bp->b_flags & B_READ) && !EXISTSOP(pmp, READ))
        !          1708:            || (((bp->b_flags & B_READ) == 0) && !EXISTSOP(pmp, WRITE))) {
        !          1709:                error = EOPNOTSUPP;
        !          1710:                goto out;
        !          1711:        }
1.8       pooka    1712:
1.38    ! pooka    1713:        /*
        !          1714:         * Short-circuit optimization: don't flush buffer in between
        !          1715:         * VOP_INACTIVE and VOP_RECLAIM in case the node has no references.
        !          1716:         */
        !          1717:        if (pn->pn_stat & PNODE_NOREFS) {
        !          1718:                bp->b_resid = 0;
        !          1719:                goto out;
        !          1720:        }
1.17      pooka    1721:
1.8       pooka    1722: #ifdef DIAGNOSTIC
1.14      pooka    1723:        if (bp->b_resid > pmp->pmp_req_maxsize - PUFFS_REQSTRUCT_MAX)
                   1724:                panic("puffs_strategy: wildly inappropriate buf resid %d",
                   1725:                    bp->b_resid);
1.8       pooka    1726: #endif
                   1727:
1.35      pooka    1728:        /*
                   1729:         * See explanation for the necessity of a FAF in puffs_fsync
                   1730:         *
                   1731:         * XXgoddamnX: B_WRITE is a "pseudo flag"
                   1732:         */
                   1733:        if ((bp->b_flags & B_READ) == 0) {
                   1734:                simple_lock(&vp->v_interlock);
                   1735:                if (vp->v_flag & VXLOCK)
                   1736:                        dowritefaf = 1;
                   1737:                simple_unlock(&vp->v_interlock);
                   1738:        }
                   1739:
1.8       pooka    1740:        if (bp->b_flags & B_READ) {
                   1741:                argsize = sizeof(struct puffs_vnreq_read);
1.14      pooka    1742:                read_argp = malloc(argsize, M_PUFFS, M_NOWAIT | M_ZERO);
                   1743:                if (read_argp == NULL) {
                   1744:                        error = ENOMEM;
                   1745:                        goto out;
                   1746:                }
                   1747:
                   1748:                tomove = PUFFS_TOMOVE(bp->b_resid, pmp);
                   1749:
1.8       pooka    1750:                read_argp->pvnr_ioflag = 0;
1.14      pooka    1751:                read_argp->pvnr_resid = tomove;
1.8       pooka    1752:                read_argp->pvnr_offset = bp->b_blkno << DEV_BSHIFT;
1.14      pooka    1753:                puffs_credcvt(&read_argp->pvnr_cred, FSCRED);
1.8       pooka    1754:
                   1755:                error = puffs_vntouser_adjbuf(pmp, PUFFS_VN_READ,
1.35      pooka    1756:                    (void **)&read_argp, &argsize, read_argp->pvnr_resid,
                   1757:                    VPTOPNC(vp), LOCKEDVP(vp), NULL);
1.8       pooka    1758:
                   1759:                if (error)
1.14      pooka    1760:                        goto out;
1.8       pooka    1761:
1.14      pooka    1762:                if (read_argp->pvnr_resid > tomove) {
                   1763:                        error = EINVAL;
                   1764:                        goto out;
                   1765:                }
                   1766:
                   1767:                moved = tomove - read_argp->pvnr_resid;
                   1768:
                   1769:                (void)memcpy(bp->b_data, read_argp->pvnr_data, moved);
                   1770:                bp->b_resid -= moved;
1.8       pooka    1771:        } else {
                   1772:                argsize = sizeof(struct puffs_vnreq_write) + bp->b_bcount;
1.14      pooka    1773:                write_argp = malloc(argsize, M_PUFFS, M_NOWAIT | M_ZERO);
                   1774:                if (write_argp == NULL) {
                   1775:                        error = ENOMEM;
                   1776:                        goto out;
                   1777:                }
                   1778:
                   1779:                tomove = PUFFS_TOMOVE(bp->b_resid, pmp);
                   1780:
1.8       pooka    1781:                write_argp->pvnr_ioflag = 0;
1.14      pooka    1782:                write_argp->pvnr_resid = tomove;
1.8       pooka    1783:                write_argp->pvnr_offset = bp->b_blkno << DEV_BSHIFT;
1.14      pooka    1784:                puffs_credcvt(&write_argp->pvnr_cred, FSCRED);
                   1785:
                   1786:                (void)memcpy(&write_argp->pvnr_data, bp->b_data, tomove);
1.8       pooka    1787:
1.35      pooka    1788:                if (dowritefaf) {
                   1789:                        /*
                   1790:                         * assume FAF moves everything.  frankly, we don't
                   1791:                         * really have a choice.
                   1792:                         */
                   1793:                        puffs_vntouser_faf(MPTOPUFFSMP(vp->v_mount),
                   1794:                            PUFFS_VN_WRITE, write_argp, argsize, VPTOPNC(vp));
                   1795:                        bp->b_resid -= tomove;
                   1796:                } else {
                   1797:                        error = puffs_vntouser(MPTOPUFFSMP(vp->v_mount),
                   1798:                            PUFFS_VN_WRITE, write_argp, argsize, VPTOPNC(vp),
                   1799:                            vp, NULL);
                   1800:                        if (error)
                   1801:                                goto out;
1.8       pooka    1802:
1.35      pooka    1803:                        moved = tomove - write_argp->pvnr_resid;
                   1804:                        if (write_argp->pvnr_resid > tomove) {
                   1805:                                error = EINVAL;
                   1806:                                goto out;
                   1807:                        }
1.9       pooka    1808:
1.35      pooka    1809:                        bp->b_resid -= moved;
                   1810:                        if (write_argp->pvnr_resid != 0)
                   1811:                                error = EIO;
1.14      pooka    1812:                }
1.8       pooka    1813:        }
                   1814:
                   1815:  out:
1.14      pooka    1816:        if (read_argp)
                   1817:                free(read_argp, M_PUFFS);
1.35      pooka    1818:        if (write_argp && !dowritefaf)
1.14      pooka    1819:                free(write_argp, M_PUFFS);
                   1820:
1.38    ! pooka    1821:        biodone(bp);
1.8       pooka    1822:        return error;
                   1823: }
1.1       pooka    1824:
1.21      pooka    1825: int
                   1826: puffs_mmap(void *v)
                   1827: {
                   1828:        struct vop_mmap_args /* {
                   1829:                const struct vnodeop_desc *a_desc;
                   1830:                struct vnode *a_vp;
                   1831:                int a_fflags;
                   1832:                kauth_cred_t a_cred;
                   1833:                struct lwp *a_l;
                   1834:        } */ *ap = v;
                   1835:        struct puffs_mount *pmp;
                   1836:        int error;
                   1837:
                   1838:        PUFFS_VNREQ(mmap);
                   1839:
                   1840:        pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
                   1841:
1.23      pooka    1842:        if (!PUFFS_DOCACHE(pmp))
1.21      pooka    1843:                return genfs_eopnotsupp(v);
                   1844:
                   1845:        if (EXISTSOP(pmp, MMAP)) {
                   1846:                mmap_arg.pvnr_fflags = ap->a_fflags;
                   1847:                puffs_credcvt(&mmap_arg.pvnr_cred, ap->a_cred);
                   1848:                mmap_arg.pvnr_pid = puffs_lwp2pid(ap->a_l);
                   1849:
                   1850:                error = puffs_vntouser(pmp, PUFFS_VN_MMAP,
                   1851:                    &mmap_arg, sizeof(mmap_arg),
                   1852:                    VPTOPNC(ap->a_vp), NULL, NULL);
                   1853:        } else {
                   1854:                error = genfs_mmap(v);
                   1855:        }
                   1856:
                   1857:        return error;
                   1858: }
                   1859:
                   1860:
1.1       pooka    1861: /*
                   1862:  * The rest don't get a free trip to userspace and back, they
                   1863:  * have to stay within the kernel.
                   1864:  */
                   1865:
                   1866: /*
1.8       pooka    1867:  * bmap doesn't really make any sense for puffs, so just 1:1 map it.
                   1868:  * well, maybe somehow, somewhere, some day ....
                   1869:  */
                   1870: int
                   1871: puffs_bmap(void *v)
                   1872: {
                   1873:        struct vop_bmap_args /* {
                   1874:                const struct vnodeop_desc *a_desc;
                   1875:                struct vnode *a_vp;
                   1876:                daddr_t a_bn;
                   1877:                struct vnode **a_vpp;
                   1878:                daddr_t *a_bnp;
                   1879:                int *a_runp;
                   1880:        } */ *ap = v;
                   1881:        struct puffs_mount *pmp;
                   1882:
                   1883:        pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
                   1884:
                   1885:        if (ap->a_vpp)
                   1886:                *ap->a_vpp = ap->a_vp;
                   1887:        if (ap->a_bnp)
                   1888:                *ap->a_bnp = ap->a_bn;
                   1889:        if (ap->a_runp)
                   1890:                *ap->a_runp = pmp->pmp_req_maxsize - PUFFS_REQSTRUCT_MAX;
                   1891:
                   1892:        return 0;
                   1893: }
                   1894:
                   1895: /*
1.1       pooka    1896:  * moreXXX: yes, todo
                   1897:  */
                   1898: int
                   1899: puffs_lock(void *v)
                   1900: {
                   1901:        struct vop_lock_args /* {
                   1902:                struct vnode *a_vp;
                   1903:                int a_flags;
                   1904:        } */ *ap = v;
                   1905:        struct vnode *vp = ap->a_vp;
                   1906:
                   1907: #if 0
                   1908:        DPRINTF(("puffs_lock: lock %p, args 0x%x\n", vp, ap->a_flags));
                   1909: #endif
                   1910:
                   1911:        return lockmgr(&vp->v_lock, ap->a_flags, &vp->v_interlock);
                   1912: }
                   1913:
                   1914: int
                   1915: puffs_unlock(void *v)
                   1916: {
                   1917:        struct vop_unlock_args /* {
                   1918:                struct vnode *a_vp;
                   1919:                int a_flags;
                   1920:        } */ *ap = v;
                   1921:        struct vnode *vp = ap->a_vp;
                   1922:
                   1923: #if 0
                   1924:        DPRINTF(("puffs_unlock: lock %p, args 0x%x\n", vp, ap->a_flags));
                   1925: #endif
                   1926:
                   1927:        return lockmgr(&vp->v_lock, ap->a_flags | LK_RELEASE, &vp->v_interlock);
                   1928: }
                   1929:
                   1930: int
                   1931: puffs_islocked(void *v)
                   1932: {
                   1933:        struct vop_islocked_args *ap = v;
                   1934:        int rv;
                   1935:
                   1936:        rv = lockstatus(&ap->a_vp->v_lock);
                   1937:        return rv;
                   1938: }
                   1939:
                   1940: int
                   1941: puffs_generic(void *v)
                   1942: {
                   1943:        struct vop_generic_args *ap = v;
                   1944:
                   1945:        (void)ap;
                   1946:        DPRINTF(("puffs_generic: ap->a_desc = %s\n", ap->a_desc->vdesc_name));
                   1947:
                   1948:        return EOPNOTSUPP;
                   1949: }
1.26      pooka    1950:
                   1951:
                   1952: /*
1.31      pooka    1953:  * spec & fifo.  These call the miscfs spec and fifo vectors, but issue
1.26      pooka    1954:  * FAF update information for the puffs node first.
                   1955:  */
                   1956: int
                   1957: puffs_spec_read(void *v)
                   1958: {
                   1959:        struct vop_read_args /* {
                   1960:                const struct vnodeop_desc *a_desc;
                   1961:                struct vnode *a_vp;
                   1962:                struct uio *a_uio;
                   1963:                int a_ioflag;
                   1964:                kauth_cred_t a_cred;
                   1965:        } */ *ap = v;
                   1966:
                   1967:        puffs_updatenode(ap->a_vp, PUFFS_UPDATEATIME);
                   1968:        return VOCALL(spec_vnodeop_p, VOFFSET(vop_read), v);
                   1969: }
                   1970:
                   1971: int
                   1972: puffs_spec_write(void *v)
                   1973: {
                   1974:        struct vop_write_args /* {
                   1975:                const struct vnodeop_desc *a_desc;
                   1976:                struct vnode *a_vp;
                   1977:                struct uio *a_uio;
                   1978:                int a_ioflag;
                   1979:                kauth_cred_t a_cred;
                   1980:        } */ *ap = v;
                   1981:
                   1982:        puffs_updatenode(ap->a_vp, PUFFS_UPDATEMTIME);
                   1983:        return VOCALL(spec_vnodeop_p, VOFFSET(vop_write), v);
                   1984: }
                   1985:
                   1986: int
                   1987: puffs_fifo_read(void *v)
                   1988: {
                   1989:        struct vop_read_args /* {
                   1990:                const struct vnodeop_desc *a_desc;
                   1991:                struct vnode *a_vp;
                   1992:                struct uio *a_uio;
                   1993:                int a_ioflag;
                   1994:                kauth_cred_t a_cred;
                   1995:        } */ *ap = v;
                   1996:
                   1997:        puffs_updatenode(ap->a_vp, PUFFS_UPDATEATIME);
                   1998:        return VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), v);
                   1999: }
                   2000:
                   2001: int
                   2002: puffs_fifo_write(void *v)
                   2003: {
                   2004:        struct vop_write_args /* {
                   2005:                const struct vnodeop_desc *a_desc;
                   2006:                struct vnode *a_vp;
                   2007:                struct uio *a_uio;
                   2008:                int a_ioflag;
                   2009:                kauth_cred_t a_cred;
                   2010:        } */ *ap = v;
                   2011:
                   2012:        puffs_updatenode(ap->a_vp, PUFFS_UPDATEMTIME);
                   2013:        return VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), v);
                   2014: }

CVSweb <webmaster@jp.NetBSD.org>