[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.112

1.112   ! pooka       1: /*     $NetBSD: puffs_vnops.c,v 1.111 2007/10/21 19:43:52 pooka Exp $  */
1.1       pooka       2:
                      3: /*
1.64      pooka       4:  * Copyright (c) 2005, 2006, 2007  Antti Kantee.  All Rights Reserved.
1.1       pooka       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:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
                     20:  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     21:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     22:  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     23:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     24:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     25:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     26:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     27:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     28:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     29:  * SUCH DAMAGE.
                     30:  */
                     31:
                     32: #include <sys/cdefs.h>
1.112   ! pooka      33: __KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.111 2007/10/21 19:43:52 pooka Exp $");
1.1       pooka      34:
                     35: #include <sys/param.h>
1.41      pooka      36: #include <sys/fstrans.h>
                     37: #include <sys/malloc.h>
1.1       pooka      38: #include <sys/mount.h>
                     39: #include <sys/namei.h>
1.41      pooka      40: #include <sys/vnode.h>
1.87      ad         41: #include <sys/proc.h>
                     42:
1.45      pooka      43: #include <uvm/uvm.h>
1.1       pooka      44:
                     45: #include <fs/puffs/puffs_msgif.h>
                     46: #include <fs/puffs/puffs_sys.h>
                     47:
1.6       pooka      48: #include <miscfs/fifofs/fifo.h>
1.1       pooka      49: #include <miscfs/genfs/genfs.h>
1.5       pooka      50: #include <miscfs/specfs/specdev.h>
                     51:
1.1       pooka      52: int    puffs_lookup(void *);
                     53: int    puffs_create(void *);
                     54: int    puffs_access(void *);
                     55: int    puffs_mknod(void *);
                     56: int    puffs_open(void *);
                     57: int    puffs_close(void *);
                     58: int    puffs_getattr(void *);
                     59: int    puffs_setattr(void *);
                     60: int    puffs_reclaim(void *);
                     61: int    puffs_readdir(void *);
                     62: int    puffs_poll(void *);
                     63: int    puffs_fsync(void *);
                     64: int    puffs_seek(void *);
                     65: int    puffs_remove(void *);
                     66: int    puffs_mkdir(void *);
                     67: int    puffs_rmdir(void *);
                     68: int    puffs_link(void *);
                     69: int    puffs_readlink(void *);
                     70: int    puffs_symlink(void *);
                     71: int    puffs_rename(void *);
                     72: int    puffs_read(void *);
                     73: int    puffs_write(void *);
                     74: int    puffs_fcntl(void *);
                     75: int    puffs_ioctl(void *);
                     76: int    puffs_inactive(void *);
                     77: int    puffs_print(void *);
                     78: int    puffs_pathconf(void *);
                     79: int    puffs_advlock(void *);
1.8       pooka      80: int    puffs_strategy(void *);
                     81: int    puffs_bmap(void *);
1.16      pooka      82: int    puffs_mmap(void *);
1.54      pooka      83: int    puffs_getpages(void *);
1.1       pooka      84:
1.26      pooka      85: int    puffs_spec_read(void *);
                     86: int    puffs_spec_write(void *);
                     87: int    puffs_fifo_read(void *);
                     88: int    puffs_fifo_write(void *);
                     89:
1.17      pooka      90: int    puffs_checkop(void *);
                     91:
1.1       pooka      92:
                     93: /* VOP_LEASE() not included */
                     94:
                     95: int    puffs_generic(void *);
                     96:
                     97: #if 0
                     98: #define puffs_lock genfs_lock
                     99: #define puffs_unlock genfs_unlock
                    100: #define puffs_islocked genfs_islocked
                    101: #else
                    102: int puffs_lock(void *);
                    103: int puffs_unlock(void *);
                    104: int puffs_islocked(void *);
                    105: #endif
                    106:
                    107: int (**puffs_vnodeop_p)(void *);
                    108: const struct vnodeopv_entry_desc puffs_vnodeop_entries[] = {
                    109:        { &vop_default_desc, vn_default_error },
1.17      pooka     110:        { &vop_lookup_desc, puffs_lookup },             /* REAL lookup */
                    111:        { &vop_create_desc, puffs_checkop },            /* create */
                    112:         { &vop_mknod_desc, puffs_checkop },            /* mknod */
1.47      pooka     113:         { &vop_open_desc, puffs_open },                        /* REAL open */
1.17      pooka     114:         { &vop_close_desc, puffs_checkop },            /* close */
1.47      pooka     115:         { &vop_access_desc, puffs_access },            /* REAL access */
1.17      pooka     116:         { &vop_getattr_desc, puffs_checkop },          /* getattr */
                    117:         { &vop_setattr_desc, puffs_checkop },          /* setattr */
                    118:         { &vop_read_desc, puffs_checkop },             /* read */
                    119:         { &vop_write_desc, puffs_checkop },            /* write */
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 */
1.47      pooka     131:         { &vop_putpages_desc, genfs_putpages },                /* REAL putpages */
1.17      pooka     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.69      pooka     146:         { &vop_poll_desc, puffs_poll },                        /* REAL poll */
1.1       pooka     147:
1.69      pooka     148:         { &vop_kqfilter_desc, genfs_eopnotsupp },      /* kqfilter XXX */
1.1       pooka     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 */
1.69      pooka     174:        { &vop_mmap_desc, spec_mmap },                  /* spec_mmap */
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.42      pooka     233:        { &vop_fsync_desc, fifo_fsync },                /* genfs_nullop*/
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_seek_desc, puffs_seek },                        /* seek */
                    284:         { &vop_remove_desc, puffs_remove },            /* remove */
                    285:         { &vop_link_desc, puffs_link },                        /* link */
                    286:         { &vop_rename_desc, puffs_rename },            /* rename */
                    287:         { &vop_mkdir_desc, puffs_mkdir },              /* mkdir */
                    288:         { &vop_rmdir_desc, puffs_rmdir },              /* rmdir */
                    289:         { &vop_symlink_desc, puffs_symlink },          /* symlink */
                    290:         { &vop_readdir_desc, puffs_readdir },          /* readdir */
                    291:         { &vop_readlink_desc, puffs_readlink },                /* readlink */
                    292:         { &vop_print_desc, puffs_print },              /* print */
                    293:         { &vop_islocked_desc, puffs_islocked },                /* islocked */
                    294:         { &vop_pathconf_desc, puffs_pathconf },                /* pathconf */
                    295:         { &vop_advlock_desc, puffs_advlock },          /* advlock */
1.54      pooka     296:         { &vop_getpages_desc, puffs_getpages },                /* getpages */
1.17      pooka     297:        { NULL, NULL }
                    298: };
                    299: const struct vnodeopv_desc puffs_msgop_opv_desc =
                    300:        { &puffs_msgop_p, puffs_msgop_entries };
                    301:
1.5       pooka     302:
1.79      pooka     303: #define ERROUT(err)                                                    \
                    304: do {                                                                   \
                    305:        error = err;                                                    \
                    306:        goto out;                                                       \
                    307: } while (/*CONSTCOND*/0)
1.1       pooka     308:
1.17      pooka     309: /*
                    310:  * This is a generic vnode operation handler.  It checks if the necessary
                    311:  * operations for the called vnode operation are implemented by userspace
                    312:  * and either returns a dummy return value or proceeds to call the real
                    313:  * vnode operation from puffs_msgop_v.
                    314:  *
                    315:  * XXX: this should described elsewhere and autogenerated, the complexity
                    316:  * of the vnode operations vectors and their interrelationships is also
                    317:  * getting a bit out of hand.  Another problem is that we need this same
                    318:  * information in the fs server code, so keeping the two in sync manually
                    319:  * is not a viable (long term) plan.
                    320:  */
                    321:
                    322: /* not supported, handle locking protocol */
                    323: #define CHECKOP_NOTSUPP(op)                                            \
                    324: case VOP_##op##_DESCOFFSET:                                            \
                    325:        if (pmp->pmp_vnopmask[PUFFS_VN_##op] == 0)                      \
                    326:                return genfs_eopnotsupp(v);                             \
                    327:        break
                    328:
                    329: /* always succeed, no locking */
                    330: #define CHECKOP_SUCCESS(op)                                            \
                    331: case VOP_##op##_DESCOFFSET:                                            \
                    332:        if (pmp->pmp_vnopmask[PUFFS_VN_##op] == 0)                      \
                    333:                return 0;                                               \
                    334:        break
                    335:
                    336: int
                    337: puffs_checkop(void *v)
                    338: {
                    339:        struct vop_generic_args /* {
                    340:                struct vnodeop_desc *a_desc;
                    341:                spooky mystery contents;
                    342:        } */ *ap = v;
                    343:        struct vnodeop_desc *desc = ap->a_desc;
                    344:        struct puffs_mount *pmp;
                    345:        struct vnode *vp;
1.75      pooka     346:        int offset, rv;
1.17      pooka     347:
                    348:        offset = ap->a_desc->vdesc_vp_offsets[0];
                    349: #ifdef DIAGNOSTIC
                    350:        if (offset == VDESC_NO_OFFSET)
                    351:                panic("puffs_checkop: no vnode, why did you call me?");
                    352: #endif
                    353:        vp = *VOPARG_OFFSETTO(struct vnode **, offset, ap);
                    354:        pmp = MPTOPUFFSMP(vp->v_mount);
                    355:
1.75      pooka     356:        DPRINTF_VERBOSE(("checkop call %s (%d), vp %p\n",
                    357:            ap->a_desc->vdesc_name, ap->a_desc->vdesc_offset, vp));
                    358:
1.66      pooka     359:        if (!ALLOPS(pmp)) {
1.17      pooka     360:                switch (desc->vdesc_offset) {
                    361:                        CHECKOP_NOTSUPP(CREATE);
                    362:                        CHECKOP_NOTSUPP(MKNOD);
                    363:                        CHECKOP_NOTSUPP(GETATTR);
                    364:                        CHECKOP_NOTSUPP(SETATTR);
                    365:                        CHECKOP_NOTSUPP(READ);
                    366:                        CHECKOP_NOTSUPP(WRITE);
                    367:                        CHECKOP_NOTSUPP(FCNTL);
                    368:                        CHECKOP_NOTSUPP(IOCTL);
                    369:                        CHECKOP_NOTSUPP(REMOVE);
                    370:                        CHECKOP_NOTSUPP(LINK);
                    371:                        CHECKOP_NOTSUPP(RENAME);
                    372:                        CHECKOP_NOTSUPP(MKDIR);
                    373:                        CHECKOP_NOTSUPP(RMDIR);
                    374:                        CHECKOP_NOTSUPP(SYMLINK);
                    375:                        CHECKOP_NOTSUPP(READDIR);
                    376:                        CHECKOP_NOTSUPP(READLINK);
                    377:                        CHECKOP_NOTSUPP(PRINT);
                    378:                        CHECKOP_NOTSUPP(PATHCONF);
                    379:                        CHECKOP_NOTSUPP(ADVLOCK);
                    380:
1.47      pooka     381:                        CHECKOP_SUCCESS(ACCESS);
1.17      pooka     382:                        CHECKOP_SUCCESS(CLOSE);
                    383:                        CHECKOP_SUCCESS(SEEK);
                    384:
                    385:                case VOP_GETPAGES_DESCOFFSET:
                    386:                        if (!EXISTSOP(pmp, READ))
                    387:                                return genfs_eopnotsupp(v);
                    388:                        break;
                    389:
                    390:                default:
                    391:                        panic("puffs_checkop: unhandled vnop %d",
                    392:                            desc->vdesc_offset);
                    393:                }
                    394:        }
                    395:
1.75      pooka     396:        rv = VOCALL(puffs_msgop_p, ap->a_desc->vdesc_offset, v);
                    397:
                    398:        DPRINTF_VERBOSE(("checkop return %s (%d), vp %p: %d\n",
                    399:            ap->a_desc->vdesc_name, ap->a_desc->vdesc_offset, vp, rv));
                    400:
                    401:        return rv;
1.17      pooka     402: }
                    403:
1.103     pooka     404: static int puffs_callremove(struct puffs_mount *, void *, void *,
                    405:                            struct componentname *);
                    406: static int puffs_callrmdir(struct puffs_mount *, void *, void *,
                    407:                           struct componentname *);
                    408: static void puffs_callinactive(struct puffs_mount *, void *, int, struct lwp *);
                    409: static void puffs_callreclaim(struct puffs_mount *, void *, struct lwp *);
                    410:
                    411: #define PUFFS_ABORT_LOOKUP     1
                    412: #define PUFFS_ABORT_CREATE     2
                    413: #define PUFFS_ABORT_MKNOD      3
                    414: #define PUFFS_ABORT_MKDIR      4
                    415: #define PUFFS_ABORT_SYMLINK    5
                    416:
                    417: /*
                    418:  * Press the pani^Wabort button!  Kernel resource allocation failed.
                    419:  */
                    420: static void
                    421: puffs_abortbutton(struct puffs_mount *pmp, int what,
                    422:        void *dcookie, void *cookie, struct componentname *cnp)
                    423: {
                    424:
                    425:        switch (what) {
                    426:        case PUFFS_ABORT_CREATE:
                    427:        case PUFFS_ABORT_MKNOD:
                    428:        case PUFFS_ABORT_SYMLINK:
                    429:                puffs_callremove(pmp, dcookie, cookie, cnp);
                    430:                break;
                    431:        case PUFFS_ABORT_MKDIR:
                    432:                puffs_callrmdir(pmp, dcookie, cookie, cnp);
                    433:                break;
                    434:        }
                    435:
                    436:        puffs_callinactive(pmp, cookie, 0, cnp->cn_lwp);
                    437:        puffs_callreclaim(pmp, cookie, cnp->cn_lwp);
                    438: }
1.17      pooka     439:
1.1       pooka     440: int
                    441: puffs_lookup(void *v)
                    442: {
                    443:         struct vop_lookup_args /* {
1.17      pooka     444:                const struct vnodeop_desc *a_desc;
                    445:                struct vnode *a_dvp;
                    446:                struct vnode **a_vpp;
                    447:                struct componentname *a_cnp;
1.1       pooka     448:         } */ *ap = v;
1.107     pooka     449:        PUFFS_MSG_VARS(vn, lookup);
1.1       pooka     450:        struct puffs_mount *pmp;
                    451:        struct componentname *cnp;
                    452:        struct vnode *vp, *dvp;
1.32      pooka     453:        struct puffs_node *dpn;
1.22      chs       454:        int isdot;
1.1       pooka     455:        int error;
                    456:
                    457:        pmp = MPTOPUFFSMP(ap->a_dvp->v_mount);
                    458:        cnp = ap->a_cnp;
                    459:        dvp = ap->a_dvp;
                    460:        *ap->a_vpp = NULL;
                    461:
1.97      pooka     462:        /* r/o fs?  we check create later to handle EEXIST */
1.96      pooka     463:        if ((cnp->cn_flags & ISLASTCN)
                    464:            && (dvp->v_mount->mnt_flag & MNT_RDONLY)
1.97      pooka     465:            && (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
1.96      pooka     466:                return EROFS;
                    467:
1.1       pooka     468:        isdot = cnp->cn_namelen == 1 && *cnp->cn_nameptr == '.';
                    469:
1.98      pooka     470:        DPRINTF(("puffs_lookup: \"%s\", parent vnode %p, op: %x\n",
1.1       pooka     471:            cnp->cn_nameptr, dvp, cnp->cn_nameiop));
                    472:
                    473:        /*
                    474:         * Check if someone fed it into the cache
                    475:         */
1.78      pooka     476:        if (PUFFS_USE_NAMECACHE(pmp)) {
1.23      pooka     477:                error = cache_lookup(dvp, ap->a_vpp, cnp);
1.30      pooka     478:
1.23      pooka     479:                if (error >= 0)
                    480:                        return error;
                    481:        }
1.1       pooka     482:
                    483:        if (isdot) {
                    484:                vp = ap->a_dvp;
                    485:                vref(vp);
                    486:                *ap->a_vpp = vp;
                    487:                return 0;
                    488:        }
                    489:
1.107     pooka     490:        PUFFS_MSG_ALLOC(vn, lookup);
                    491:        puffs_makecn(&lookup_msg->pvnr_cn, &lookup_msg->pvnr_cn_cred,
                    492:            &lookup_msg->pvnr_cn_cid, cnp, PUFFS_USE_FULLPNBUF(pmp));
1.1       pooka     493:
                    494:        if (cnp->cn_flags & ISDOTDOT)
                    495:                VOP_UNLOCK(dvp, 0);
                    496:
1.108     pooka     497:        error = puffs_msg_vn(pmp, park_lookup, PUFFS_VN_LOOKUP, 0, dvp, NULL);
1.1       pooka     498:        DPRINTF(("puffs_lookup: return of the userspace, part %d\n", error));
                    499:
                    500:        /*
1.23      pooka     501:         * In case of error, there is no new vnode to play with, so be
                    502:         * happy with the NULL value given to vpp in the beginning.
                    503:         * Also, check if this really was an error or the target was not
                    504:         * present.  Either treat it as a non-error for CREATE/RENAME or
                    505:         * enter the component into the negative name cache (if desired).
1.1       pooka     506:         */
                    507:        if (error) {
1.102     pooka     508:                error = checkerr(pmp, error, __func__);
1.10      pooka     509:                if (error == ENOENT) {
1.97      pooka     510:                        /* don't allow to create files on r/o fs */
                    511:                        if ((dvp->v_mount->mnt_flag & MNT_RDONLY)
                    512:                            && cnp->cn_nameiop == CREATE) {
                    513:                                error = EROFS;
                    514:
                    515:                        /* adjust values if we are creating */
                    516:                        } else if ((cnp->cn_flags & ISLASTCN)
1.1       pooka     517:                            && (cnp->cn_nameiop == CREATE
                    518:                              || cnp->cn_nameiop == RENAME)) {
                    519:                                cnp->cn_flags |= SAVENAME;
                    520:                                error = EJUSTRETURN;
1.97      pooka     521:
                    522:                        /* save negative cache entry */
1.23      pooka     523:                        } else {
                    524:                                if ((cnp->cn_flags & MAKEENTRY)
1.78      pooka     525:                                    && PUFFS_USE_NAMECACHE(pmp))
1.23      pooka     526:                                        cache_enter(dvp, NULL, cnp);
1.10      pooka     527:                        }
1.1       pooka     528:                }
1.80      pooka     529:                goto out;
1.1       pooka     530:        }
                    531:
1.32      pooka     532:        /*
                    533:         * Check that we don't get our parent node back, that would cause
                    534:         * a pretty obvious deadlock.
                    535:         */
                    536:        dpn = dvp->v_data;
1.107     pooka     537:        if (lookup_msg->pvnr_newnode == dpn->pn_cookie) {
                    538:                puffs_msg_errnotify(pmp, PUFFS_ERR_LOOKUP, EINVAL,
                    539:                    "lookup produced parent cookie", lookup_msg->pvnr_newnode);
1.100     pooka     540:                error = EPROTO;
1.80      pooka     541:                goto out;
1.32      pooka     542:        }
                    543:
1.107     pooka     544:        error = puffs_cookie2vnode(pmp, lookup_msg->pvnr_newnode, 1, 1, &vp);
1.101     pooka     545:        if (error == PUFFS_NOSUCHCOOKIE) {
1.1       pooka     546:                error = puffs_getvnode(dvp->v_mount,
1.107     pooka     547:                    lookup_msg->pvnr_newnode, lookup_msg->pvnr_vtype,
                    548:                    lookup_msg->pvnr_size, lookup_msg->pvnr_rdev, &vp);
1.1       pooka     549:                if (error) {
1.103     pooka     550:                        puffs_abortbutton(pmp, PUFFS_ABORT_LOOKUP, VPTOPNC(dvp),
1.107     pooka     551:                            lookup_msg->pvnr_newnode, ap->a_cnp);
1.80      pooka     552:                        goto out;
1.1       pooka     553:                }
                    554:                vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1.101     pooka     555:        } else if (error) {
1.103     pooka     556:                puffs_abortbutton(pmp, PUFFS_ABORT_LOOKUP, VPTOPNC(dvp),
1.107     pooka     557:                    lookup_msg->pvnr_newnode, ap->a_cnp);
1.101     pooka     558:                goto out;
1.1       pooka     559:        }
1.101     pooka     560:
1.23      pooka     561:        *ap->a_vpp = vp;
1.1       pooka     562:
1.78      pooka     563:        if ((cnp->cn_flags & MAKEENTRY) != 0 && PUFFS_USE_NAMECACHE(pmp))
1.1       pooka     564:                cache_enter(dvp, vp, cnp);
                    565:
1.86      pooka     566:        /* XXX */
1.107     pooka     567:        if ((lookup_msg->pvnr_cn.pkcn_flags & REQUIREDIR) == 0)
1.86      pooka     568:                cnp->cn_flags &= ~REQUIREDIR;
1.107     pooka     569:        if (lookup_msg->pvnr_cn.pkcn_consume)
                    570:                cnp->cn_consume = MIN(lookup_msg->pvnr_cn.pkcn_consume,
1.86      pooka     571:                    strlen(cnp->cn_nameptr) - cnp->cn_namelen);
                    572:
1.80      pooka     573:  out:
1.22      chs       574:        if (cnp->cn_flags & ISDOTDOT)
                    575:                vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
1.97      pooka     576:
1.50      pooka     577:        DPRINTF(("puffs_lookup: returning %d %p\n", error, *ap->a_vpp));
1.107     pooka     578:        PUFFS_MSG_RELEASE(lookup);
1.22      chs       579:        return error;
1.1       pooka     580: }
                    581:
                    582: int
                    583: puffs_create(void *v)
                    584: {
                    585:        struct vop_create_args /* {
                    586:                const struct vnodeop_desc *a_desc;
                    587:                struct vnode *a_dvp;
                    588:                struct vnode **a_vpp;
                    589:                struct componentname *a_cnp;
                    590:                struct vattr *a_vap;
                    591:        } */ *ap = v;
1.107     pooka     592:        PUFFS_MSG_VARS(vn, create);
                    593:        struct vnode *dvp = ap->a_dvp;
                    594:        struct componentname *cnp = ap->a_cnp;
                    595:        struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount);
1.1       pooka     596:        int error;
                    597:
1.50      pooka     598:        DPRINTF(("puffs_create: dvp %p, cnp: %s\n",
1.107     pooka     599:            dvp, ap->a_cnp->cn_nameptr));
1.1       pooka     600:
1.107     pooka     601:        PUFFS_MSG_ALLOC(vn, create);
                    602:        puffs_makecn(&create_msg->pvnr_cn, &create_msg->pvnr_cn_cred,
                    603:            &create_msg->pvnr_cn_cid, cnp, PUFFS_USE_FULLPNBUF(pmp));
                    604:        create_msg->pvnr_va = *ap->a_vap;
1.1       pooka     605:
1.107     pooka     606:        error = puffs_msg_vn(pmp, park_create, PUFFS_VN_CREATE, 0, dvp, NULL);
1.102     pooka     607:        error = checkerr(pmp, error, __func__);
1.1       pooka     608:        if (error)
1.4       pooka     609:                goto out;
1.1       pooka     610:
1.107     pooka     611:        error = puffs_newnode(dvp->v_mount, dvp, ap->a_vpp,
                    612:            create_msg->pvnr_newnode, cnp, ap->a_vap->va_type, 0);
1.103     pooka     613:        if (error)
1.107     pooka     614:                puffs_abortbutton(pmp, PUFFS_ABORT_CREATE, VPTOPNC(dvp),
                    615:                    create_msg->pvnr_newnode, cnp);
1.4       pooka     616:
                    617:  out:
1.107     pooka     618:        if (error || (cnp->cn_flags & SAVESTART) == 0)
                    619:                PNBUF_PUT(cnp->cn_pnbuf);
                    620:        vput(dvp);
1.50      pooka     621:
                    622:        DPRINTF(("puffs_create: return %d\n", error));
1.107     pooka     623:        PUFFS_MSG_RELEASE(create);
1.4       pooka     624:        return error;
1.1       pooka     625: }
                    626:
                    627: int
                    628: puffs_mknod(void *v)
                    629: {
                    630:        struct vop_mknod_args /* {
                    631:                const struct vnodeop_desc *a_desc;
                    632:                struct vnode *a_dvp;
                    633:                struct vnode **a_vpp;
                    634:                struct componentname *a_cnp;
                    635:                struct vattr *a_vap;
                    636:        } */ *ap = v;
1.107     pooka     637:        PUFFS_MSG_VARS(vn, mknod);
                    638:        struct vnode *dvp = ap->a_dvp;
                    639:        struct componentname *cnp = ap->a_cnp;
                    640:        struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount);
1.1       pooka     641:        int error;
                    642:
1.107     pooka     643:        PUFFS_MSG_ALLOC(vn, mknod);
                    644:        puffs_makecn(&mknod_msg->pvnr_cn, &mknod_msg->pvnr_cn_cred,
                    645:            &mknod_msg->pvnr_cn_cid, cnp, PUFFS_USE_FULLPNBUF(pmp));
                    646:        mknod_msg->pvnr_va = *ap->a_vap;
1.1       pooka     647:
1.107     pooka     648:        error = puffs_msg_vn(pmp, park_mknod, PUFFS_VN_MKNOD, 0, dvp, NULL);
1.102     pooka     649:        error = checkerr(pmp, error, __func__);
1.1       pooka     650:        if (error)
1.4       pooka     651:                goto out;
1.1       pooka     652:
1.107     pooka     653:        error = puffs_newnode(dvp->v_mount, dvp, ap->a_vpp,
                    654:            mknod_msg->pvnr_newnode, cnp, ap->a_vap->va_type,
1.5       pooka     655:            ap->a_vap->va_rdev);
1.103     pooka     656:        if (error)
1.107     pooka     657:                puffs_abortbutton(pmp, PUFFS_ABORT_MKNOD, VPTOPNC(dvp),
                    658:                    mknod_msg->pvnr_newnode, cnp);
1.4       pooka     659:
                    660:  out:
1.107     pooka     661:        PUFFS_MSG_RELEASE(mknod);
                    662:        if (error || (cnp->cn_flags & SAVESTART) == 0)
                    663:                PNBUF_PUT(cnp->cn_pnbuf);
                    664:        vput(dvp);
1.4       pooka     665:        return error;
1.1       pooka     666: }
                    667:
                    668: int
                    669: puffs_open(void *v)
                    670: {
                    671:        struct vop_open_args /* {
                    672:                const struct vnodeop_desc *a_desc;
                    673:                struct vnode *a_vp;
                    674:                int a_mode;
                    675:                kauth_cred_t a_cred;
                    676:                struct lwp *a_l;
                    677:        } */ *ap = v;
1.107     pooka     678:        PUFFS_MSG_VARS(vn, open);
1.47      pooka     679:        struct vnode *vp = ap->a_vp;
                    680:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
                    681:        int mode = ap->a_mode;
1.79      pooka     682:        int error;
1.1       pooka     683:
1.50      pooka     684:        DPRINTF(("puffs_open: vp %p, mode 0x%x\n", vp, mode));
1.1       pooka     685:
1.79      pooka     686:        if (vp->v_type == VREG && mode & FWRITE && !EXISTSOP(pmp, WRITE))
                    687:                ERROUT(EROFS);
1.47      pooka     688:
1.79      pooka     689:        if (!EXISTSOP(pmp, OPEN))
                    690:                ERROUT(0);
1.47      pooka     691:
1.107     pooka     692:        PUFFS_MSG_ALLOC(vn, open);
                    693:        open_msg->pvnr_mode = mode;
                    694:        puffs_credcvt(&open_msg->pvnr_cred, ap->a_cred);
                    695:        puffs_cidcvt(&open_msg->pvnr_cid, ap->a_l);
1.1       pooka     696:
1.107     pooka     697:        error = puffs_msg_vn(pmp, park_open, PUFFS_VN_OPEN, 0, vp, NULL);
1.102     pooka     698:        error = checkerr(pmp, error, __func__);
1.50      pooka     699:
                    700:  out:
1.79      pooka     701:        DPRINTF(("puffs_open: returning %d\n", error));
1.107     pooka     702:        PUFFS_MSG_RELEASE(open);
1.79      pooka     703:        return error;
1.1       pooka     704: }
                    705:
                    706: int
                    707: puffs_close(void *v)
                    708: {
                    709:        struct vop_close_args /* {
                    710:                const struct vnodeop_desc *a_desc;
                    711:                struct vnode *a_vp;
                    712:                int a_fflag;
                    713:                kauth_cred_t a_cred;
                    714:                struct lwp *a_l;
                    715:        } */ *ap = v;
1.107     pooka     716:        PUFFS_MSG_VARS(vn, close);
                    717:        struct vnode *vp = ap->a_vp;
                    718:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.1       pooka     719:
1.107     pooka     720:        PUFFS_MSG_ALLOC(vn, close);
                    721:        puffs_msg_setfaf(park_close);
                    722:        close_msg->pvnr_fflag = ap->a_fflag;
                    723:        puffs_credcvt(&close_msg->pvnr_cred, ap->a_cred);
                    724:        puffs_cidcvt(&close_msg->pvnr_cid, ap->a_l);
1.1       pooka     725:
1.107     pooka     726:        puffs_msg_vn(pmp, park_close, PUFFS_VN_CLOSE, 0, vp, NULL);
1.1       pooka     727:
1.107     pooka     728:        PUFFS_MSG_RELEASE(close);
1.63      pooka     729:        return 0;
1.1       pooka     730: }
                    731:
                    732: int
                    733: puffs_access(void *v)
                    734: {
                    735:        struct vop_access_args /* {
                    736:                const struct vnodeop_desc *a_desc;
                    737:                struct vnode *a_vp;
                    738:                int a_mode;
                    739:                kauth_cred_t a_cred;
                    740:                struct lwp *a_l;
                    741:        } */ *ap = v;
1.107     pooka     742:        PUFFS_MSG_VARS(vn, access);
1.47      pooka     743:        struct vnode *vp = ap->a_vp;
                    744:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
                    745:        int mode = ap->a_mode;
1.102     pooka     746:        int error;
1.1       pooka     747:
1.96      pooka     748:        if (mode & VWRITE) {
                    749:                switch (vp->v_type) {
                    750:                case VDIR:
                    751:                case VLNK:
                    752:                case VREG:
                    753:                        if ((vp->v_mount->mnt_flag & MNT_RDONLY)
                    754:                            || !EXISTSOP(pmp, WRITE))
                    755:                                return EROFS;
                    756:                        break;
                    757:                default:
                    758:                        break;
                    759:                }
                    760:        }
1.47      pooka     761:
                    762:        if (!EXISTSOP(pmp, ACCESS))
                    763:                return 0;
                    764:
1.107     pooka     765:        PUFFS_MSG_ALLOC(vn, access);
                    766:        access_msg->pvnr_mode = ap->a_mode;
                    767:        puffs_credcvt(&access_msg->pvnr_cred, ap->a_cred);
                    768:        puffs_cidcvt(&access_msg->pvnr_cid, ap->a_l);
                    769:
                    770:        error = puffs_msg_vn(pmp, park_access, PUFFS_VN_ACCESS, 0, vp, NULL);
                    771:        error = checkerr(pmp, error, __func__);
                    772:        PUFFS_MSG_RELEASE(access);
1.1       pooka     773:
1.107     pooka     774:        return error;
1.1       pooka     775: }
                    776:
                    777: int
                    778: puffs_getattr(void *v)
                    779: {
                    780:        struct vop_getattr_args /* {
                    781:                const struct vnodeop_desc *a_desc;
                    782:                struct vnode *a_vp;
                    783:                struct vattr *a_vap;
                    784:                kauth_cred_t a_cred;
                    785:                struct lwp *a_l;
                    786:        } */ *ap = v;
1.107     pooka     787:        PUFFS_MSG_VARS(vn, getattr);
                    788:        struct vnode *vp = ap->a_vp;
                    789:        struct mount *mp = vp->v_mount;
                    790:        struct puffs_mount *pmp = MPTOPUFFSMP(mp);
1.67      pooka     791:        struct vattr *vap, *rvap;
1.54      pooka     792:        struct puffs_node *pn;
1.107     pooka     793:        int error = 0;
1.1       pooka     794:
1.54      pooka     795:        vap = ap->a_vap;
1.13      pooka     796:
1.107     pooka     797:        PUFFS_MSG_ALLOC(vn, getattr);
                    798:        vattr_null(&getattr_msg->pvnr_va);
                    799:        puffs_credcvt(&getattr_msg->pvnr_cred, ap->a_cred);
                    800:        puffs_cidcvt(&getattr_msg->pvnr_cid, ap->a_l);
1.1       pooka     801:
1.107     pooka     802:        error = puffs_msg_vn(pmp, park_getattr, PUFFS_VN_GETATTR, 0, vp, NULL);
1.102     pooka     803:        error = checkerr(pmp, error, __func__);
1.1       pooka     804:        if (error)
1.107     pooka     805:                goto out;
1.1       pooka     806:
1.107     pooka     807:        rvap = &getattr_msg->pvnr_va;
1.67      pooka     808:        /*
                    809:         * Don't listen to the file server regarding special device
                    810:         * size info, the file server doesn't know anything about them.
                    811:         */
                    812:        if (vp->v_type == VBLK || vp->v_type == VCHR)
                    813:                rvap->va_size = vp->v_size;
                    814:
                    815:        /* Ditto for blocksize (ufs comment: this doesn't belong here) */
                    816:        if (vp->v_type == VBLK)
                    817:                rvap->va_blocksize = BLKDEV_IOSIZE;
                    818:        else if (vp->v_type == VCHR)
                    819:                rvap->va_blocksize = MAXBSIZE;
                    820:
                    821:        (void) memcpy(vap, rvap, sizeof(struct vattr));
1.54      pooka     822:        vap->va_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0];
1.1       pooka     823:
1.54      pooka     824:        pn = VPTOPP(vp);
                    825:        if (pn->pn_stat & PNODE_METACACHE_ATIME)
                    826:                vap->va_atime = pn->pn_mc_atime;
                    827:        if (pn->pn_stat & PNODE_METACACHE_CTIME)
                    828:                vap->va_ctime = pn->pn_mc_ctime;
                    829:        if (pn->pn_stat & PNODE_METACACHE_MTIME)
                    830:                vap->va_mtime = pn->pn_mc_mtime;
                    831:        if (pn->pn_stat & PNODE_METACACHE_SIZE) {
                    832:                vap->va_size = pn->pn_mc_size;
                    833:        } else {
1.67      pooka     834:                if (rvap->va_size != VNOVAL
1.90      pooka     835:                    && vp->v_type != VBLK && vp->v_type != VCHR) {
1.67      pooka     836:                        uvm_vnp_setsize(vp, rvap->va_size);
1.90      pooka     837:                        pn->pn_serversize = rvap->va_size;
                    838:                }
1.54      pooka     839:        }
1.13      pooka     840:
1.107     pooka     841:  out:
                    842:        PUFFS_MSG_RELEASE(getattr);
                    843:        return error;
1.1       pooka     844: }
                    845:
1.90      pooka     846: static int
                    847: puffs_dosetattr(struct vnode *vp, struct vattr *vap, kauth_cred_t cred,
                    848:        struct lwp *l, int chsize)
1.1       pooka     849: {
1.107     pooka     850:        PUFFS_MSG_VARS(vn, setattr);
                    851:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.90      pooka     852:        struct puffs_node *pn = vp->v_data;
1.8       pooka     853:        int error;
1.1       pooka     854:
1.96      pooka     855:        if ((vp->v_mount->mnt_flag & MNT_RDONLY) &&
                    856:            (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL
                    857:            || vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL
                    858:            || vap->va_mode != (mode_t)VNOVAL))
                    859:                return EROFS;
                    860:
                    861:        if ((vp->v_mount->mnt_flag & MNT_RDONLY)
                    862:            && vp->v_type == VREG && vap->va_size != VNOVAL)
                    863:                return EROFS;
                    864:
1.65      pooka     865:        /*
                    866:         * Flush metacache first.  If we are called with some explicit
                    867:         * parameters, treat them as information overriding metacache
                    868:         * information.
                    869:         */
                    870:        if (pn->pn_stat & PNODE_METACACHE_MASK) {
                    871:                if ((pn->pn_stat & PNODE_METACACHE_ATIME)
                    872:                    && vap->va_atime.tv_sec == VNOVAL)
                    873:                        vap->va_atime = pn->pn_mc_atime;
                    874:                if ((pn->pn_stat & PNODE_METACACHE_CTIME)
                    875:                    && vap->va_ctime.tv_sec == VNOVAL)
                    876:                        vap->va_ctime = pn->pn_mc_ctime;
                    877:                if ((pn->pn_stat & PNODE_METACACHE_MTIME)
                    878:                    && vap->va_mtime.tv_sec == VNOVAL)
                    879:                        vap->va_mtime = pn->pn_mc_mtime;
                    880:                if ((pn->pn_stat & PNODE_METACACHE_SIZE)
                    881:                    && vap->va_size == VNOVAL)
                    882:                        vap->va_size = pn->pn_mc_size;
                    883:
                    884:                pn->pn_stat &= ~PNODE_METACACHE_MASK;
                    885:        }
                    886:
1.107     pooka     887:        PUFFS_MSG_ALLOC(vn, setattr);
                    888:        (void)memcpy(&setattr_msg->pvnr_va, vap, sizeof(struct vattr));
                    889:        puffs_credcvt(&setattr_msg->pvnr_cred, cred);
                    890:        puffs_cidcvt(&setattr_msg->pvnr_cid, l);
                    891:
                    892:        error = puffs_msg_vn(pmp, park_setattr, PUFFS_VN_SETATTR, 0, vp, NULL);
                    893:        PUFFS_MSG_RELEASE(setattr);
1.1       pooka     894:
1.106     pooka     895:        error = checkerr(pmp, error, __func__);
1.8       pooka     896:        if (error)
                    897:                return error;
                    898:
1.90      pooka     899:        if (vap->va_size != VNOVAL) {
                    900:                pn->pn_serversize = vap->va_size;
                    901:                if (chsize)
                    902:                        uvm_vnp_setsize(vp, vap->va_size);
                    903:        }
1.8       pooka     904:
                    905:        return 0;
1.1       pooka     906: }
                    907:
                    908: int
1.90      pooka     909: puffs_setattr(void *v)
                    910: {
                    911:        struct vop_getattr_args /* {
                    912:                const struct vnodeop_desc *a_desc;
                    913:                struct vnode *a_vp;
                    914:                struct vattr *a_vap;
                    915:                kauth_cred_t a_cred;
                    916:                struct lwp *a_l;
                    917:        } */ *ap = v;
                    918:
                    919:        return puffs_dosetattr(ap->a_vp, ap->a_vap, ap->a_cred, ap->a_l, 1);
                    920: }
                    921:
1.107     pooka     922: static __inline int
                    923: doinact(struct puffs_mount *pmp, int iaflag)
1.3       pooka     924: {
                    925:
1.17      pooka     926:        if (EXISTSOP(pmp, INACTIVE))
1.66      pooka     927:                if (pmp->pmp_flags & PUFFS_KFLAG_IAONDEMAND)
1.103     pooka     928:                        if (iaflag || ALLOPS(pmp))
1.107     pooka     929:                                return 1;
1.66      pooka     930:                        else
1.107     pooka     931:                                return 0;
1.66      pooka     932:                else
1.107     pooka     933:                        return 1;
1.66      pooka     934:        else
1.107     pooka     935:                return 0;
                    936: }
                    937:
                    938: static void
                    939: puffs_callinactive(struct puffs_mount *pmp, void *cookie, int iaflag,
                    940:        struct lwp *l)
                    941: {
                    942:        PUFFS_MSG_VARS(vn, inactive);
                    943:
                    944:        if (doinact(pmp, iaflag)) {
                    945:                struct puffs_req *preq;
1.66      pooka     946:
1.107     pooka     947:                PUFFS_MSG_ALLOC(vn, inactive);
                    948:                puffs_cidcvt(&inactive_msg->pvnr_cid, l);
                    949:                preq = (struct puffs_req *)inactive_msg;
                    950:                preq->preq_cookie = cookie;
                    951:                preq->preq_opclass = PUFFSOP_VN;
                    952:                preq->preq_optype = PUFFS_VN_INACTIVE;
                    953:
                    954:                puffs_msg_raw(pmp, park_inactive);
                    955:                PUFFS_MSG_RELEASE(inactive);
                    956:        }
1.103     pooka     957: }
                    958:
1.107     pooka     959: /* XXX: callinactive can't setback */
1.103     pooka     960: int
                    961: puffs_inactive(void *v)
                    962: {
                    963:        struct vop_inactive_args /* {
                    964:                const struct vnodeop_desc *a_desc;
                    965:                struct vnode *a_vp;
                    966:                struct lwp *a_l;
                    967:        } */ *ap = v;
1.107     pooka     968:        PUFFS_MSG_VARS(vn, inactive);
1.103     pooka     969:        struct vnode *vp = ap->a_vp;
1.107     pooka     970:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.103     pooka     971:        struct puffs_node *pnode;
                    972:
                    973:        pnode = vp->v_data;
                    974:
1.107     pooka     975:        if (doinact(pmp, pnode->pn_stat & PNODE_DOINACT)) {
                    976:                PUFFS_MSG_ALLOC(vn, inactive);
                    977:                puffs_cidcvt(&inactive_msg->pvnr_cid, ap->a_l);
                    978:                puffs_msg_vn(pmp, park_inactive, PUFFS_VN_INACTIVE, 0, vp,NULL);
                    979:                PUFFS_MSG_RELEASE(inactive);
                    980:        }
1.66      pooka     981:        pnode->pn_stat &= ~PNODE_DOINACT;
1.3       pooka     982:
1.107     pooka     983:        VOP_UNLOCK(vp, 0);
1.3       pooka     984:
                    985:        /*
1.85      pooka     986:         * file server thinks it's gone?  then don't be afraid care,
1.3       pooka     987:         * node's life was already all it would ever be
                    988:         */
1.85      pooka     989:        if (pnode->pn_stat & PNODE_NOREFS) {
1.72      pooka     990:                pnode->pn_stat |= PNODE_DYING;
1.107     pooka     991:                vrecycle(vp, NULL, ap->a_l);
1.38      pooka     992:        }
1.3       pooka     993:
                    994:        return 0;
                    995: }
                    996:
1.103     pooka     997: static void
                    998: puffs_callreclaim(struct puffs_mount *pmp, void *cookie, struct lwp *l)
                    999: {
1.107     pooka    1000:        PUFFS_MSG_VARS(vn, reclaim);
                   1001:        struct puffs_req *preq;
1.103     pooka    1002:
                   1003:        if (!EXISTSOP(pmp, RECLAIM))
                   1004:                return;
                   1005:
1.107     pooka    1006:        PUFFS_MSG_ALLOC(vn, reclaim);
                   1007:        puffs_msg_setfaf(park_reclaim);
                   1008:        puffs_cidcvt(&reclaim_msg->pvnr_cid, l);
                   1009:
                   1010:        preq = (struct puffs_req *)reclaim_msg;
                   1011:        preq->preq_cookie = cookie;
                   1012:        preq->preq_opclass = PUFFSOP_VN;
                   1013:        preq->preq_optype = PUFFS_VN_RECLAIM;
1.103     pooka    1014:
1.107     pooka    1015:        puffs_msg_raw(pmp, park_reclaim);
                   1016:        PUFFS_MSG_RELEASE(reclaim);
1.103     pooka    1017: }
                   1018:
1.34      pooka    1019: /*
                   1020:  * always FAF, we don't really care if the server wants to fail to
                   1021:  * reclaim the node or not
                   1022:  */
1.3       pooka    1023: int
1.1       pooka    1024: puffs_reclaim(void *v)
                   1025: {
                   1026:        struct vop_reclaim_args /* {
                   1027:                const struct vnodeop_desc *a_desc;
                   1028:                struct vnode *a_vp;
                   1029:                struct lwp *a_l;
                   1030:        } */ *ap = v;
1.103     pooka    1031:        struct vnode *vp = ap->a_vp;
                   1032:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.17      pooka    1033:
1.1       pooka    1034:        /*
                   1035:         * first things first: check if someone is trying to reclaim the
                   1036:         * root vnode.  do not allow that to travel to userspace.
                   1037:         * Note that we don't need to take the lock similarly to
                   1038:         * puffs_root(), since there is only one of us.
                   1039:         */
1.105     ad       1040:        if (vp->v_vflag & VV_ROOT) {
1.55      pooka    1041:                mutex_enter(&pmp->pmp_lock);
1.39      pooka    1042:                KASSERT(pmp->pmp_root != NULL);
                   1043:                pmp->pmp_root = NULL;
1.55      pooka    1044:                mutex_exit(&pmp->pmp_lock);
1.34      pooka    1045:                goto out;
1.1       pooka    1046:        }
                   1047:
1.103     pooka    1048:        puffs_callreclaim(MPTOPUFFSMP(vp->v_mount), VPTOPNC(vp), ap->a_l);
1.1       pooka    1049:
1.34      pooka    1050:  out:
1.78      pooka    1051:        if (PUFFS_USE_NAMECACHE(pmp))
1.103     pooka    1052:                cache_purge(vp);
                   1053:        puffs_putvnode(vp);
1.1       pooka    1054:
                   1055:        return 0;
                   1056: }
                   1057:
1.60      pooka    1058: #define CSIZE sizeof(**ap->a_cookies)
1.1       pooka    1059: int
                   1060: puffs_readdir(void *v)
                   1061: {
                   1062:        struct vop_readdir_args /* {
                   1063:                const struct vnodeop_desc *a_desc;
                   1064:                struct vnode *a_vp;
                   1065:                struct uio *a_uio;
                   1066:                kauth_cred_t a_cred;
                   1067:                int *a_eofflag;
                   1068:                off_t **a_cookies;
                   1069:                int *a_ncookies;
                   1070:        } */ *ap = v;
1.107     pooka    1071:        PUFFS_MSG_VARS(vn, readdir);
1.102     pooka    1072:        struct vnode *vp = ap->a_vp;
1.107     pooka    1073:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.61      pooka    1074:        size_t argsize, tomove, cookiemem, cookiesmax;
1.1       pooka    1075:        struct uio *uio = ap->a_uio;
1.89      pooka    1076:        size_t howmuch, resid;
1.1       pooka    1077:        int error;
                   1078:
1.89      pooka    1079:        /*
                   1080:         * ok, so we need: resid + cookiemem = maxreq
                   1081:         * => resid + cookiesize * (resid/minsize) = maxreq
                   1082:         * => resid + cookiesize/minsize * resid = maxreq
                   1083:         * => (cookiesize/minsize + 1) * resid = maxreq
                   1084:         * => resid = maxreq / (cookiesize/minsize + 1)
                   1085:         *
                   1086:         * Since cookiesize <= minsize and we're not very big on floats,
                   1087:         * we approximate that to be 1.  Therefore:
                   1088:         *
                   1089:         * resid = maxreq / 2;
                   1090:         *
                   1091:         * Well, at least we didn't have to use differential equations
                   1092:         * or the Gram-Schmidt process.
                   1093:         *
                   1094:         * (yes, I'm very afraid of this)
                   1095:         */
                   1096:        KASSERT(CSIZE <= _DIRENT_MINSIZE((struct dirent *)0));
                   1097:
1.58      pooka    1098:        if (ap->a_cookies) {
                   1099:                KASSERT(ap->a_ncookies != NULL);
1.59      pooka    1100:                if (pmp->pmp_args.pa_fhsize == 0)
1.58      pooka    1101:                        return EOPNOTSUPP;
1.89      pooka    1102:                resid = PUFFS_TOMOVE(uio->uio_resid, pmp) / 2;
                   1103:                cookiesmax = resid/_DIRENT_MINSIZE((struct dirent *)0);
1.58      pooka    1104:                cookiemem = ALIGN(cookiesmax*CSIZE); /* play safe */
                   1105:        } else {
1.89      pooka    1106:                resid = PUFFS_TOMOVE(uio->uio_resid, pmp);
1.58      pooka    1107:                cookiesmax = 0;
                   1108:                cookiemem = 0;
                   1109:        }
1.1       pooka    1110:
1.107     pooka    1111:        argsize = sizeof(struct puffs_vnmsg_readdir);
1.89      pooka    1112:        tomove = resid + cookiemem;
1.107     pooka    1113:        puffs_msgmem_alloc(argsize + tomove, &park_readdir,
                   1114:            (void **)&readdir_msg, 1);
1.1       pooka    1115:
1.107     pooka    1116:        puffs_credcvt(&readdir_msg->pvnr_cred, ap->a_cred);
                   1117:        readdir_msg->pvnr_offset = uio->uio_offset;
                   1118:        readdir_msg->pvnr_resid = resid;
                   1119:        readdir_msg->pvnr_ncookies = cookiesmax;
                   1120:        readdir_msg->pvnr_eofflag = 0;
                   1121:        readdir_msg->pvnr_dentoff = cookiemem;
1.1       pooka    1122:
1.107     pooka    1123:        error = puffs_msg_vn(pmp, park_readdir, PUFFS_VN_READDIR,
1.110     pooka    1124:            tomove, vp, NULL);
1.102     pooka    1125:        error = checkerr(pmp, error, __func__);
1.1       pooka    1126:        if (error)
                   1127:                goto out;
                   1128:
                   1129:        /* userspace is cheating? */
1.107     pooka    1130:        if (readdir_msg->pvnr_resid > resid) {
                   1131:                puffs_msg_errnotify(pmp, PUFFS_ERR_READDIR, E2BIG,
1.102     pooka    1132:                    "resid grew", VPTOPNC(vp));
                   1133:                ERROUT(EPROTO);
                   1134:        }
1.107     pooka    1135:        if (readdir_msg->pvnr_ncookies > cookiesmax) {
                   1136:                puffs_msg_errnotify(pmp, PUFFS_ERR_READDIR, E2BIG,
1.102     pooka    1137:                    "too many cookies", VPTOPNC(vp));
1.100     pooka    1138:                ERROUT(EPROTO);
                   1139:        }
1.1       pooka    1140:
1.58      pooka    1141:        /* check eof */
1.107     pooka    1142:        if (readdir_msg->pvnr_eofflag)
1.58      pooka    1143:                *ap->a_eofflag = 1;
                   1144:
1.1       pooka    1145:        /* bouncy-wouncy with the directory data */
1.107     pooka    1146:        howmuch = resid - readdir_msg->pvnr_resid;
1.58      pooka    1147:
                   1148:        /* force eof if no data was returned (getcwd() needs this) */
1.29      pooka    1149:        if (howmuch == 0) {
                   1150:                *ap->a_eofflag = 1;
                   1151:                goto out;
                   1152:        }
1.58      pooka    1153:
1.107     pooka    1154:        error = uiomove(readdir_msg->pvnr_data + cookiemem, howmuch, uio);
1.1       pooka    1155:        if (error)
                   1156:                goto out;
1.58      pooka    1157:
                   1158:        /* provide cookies to caller if so desired */
                   1159:        if (ap->a_cookies) {
1.107     pooka    1160:                *ap->a_cookies = malloc(readdir_msg->pvnr_ncookies*CSIZE,
1.58      pooka    1161:                    M_TEMP, M_WAITOK);
1.107     pooka    1162:                *ap->a_ncookies = readdir_msg->pvnr_ncookies;
                   1163:                memcpy(*ap->a_cookies, readdir_msg->pvnr_data,
1.58      pooka    1164:                    *ap->a_ncookies*CSIZE);
                   1165:        }
                   1166:
                   1167:        /* next readdir starts here */
1.107     pooka    1168:        uio->uio_offset = readdir_msg->pvnr_offset;
1.1       pooka    1169:
                   1170:  out:
1.107     pooka    1171:        puffs_msgmem_release(park_readdir);
1.1       pooka    1172:        return error;
                   1173: }
1.58      pooka    1174: #undef CSIZE
1.1       pooka    1175:
1.69      pooka    1176: /*
                   1177:  * poll works by consuming the bitmask in pn_revents.  If there are
                   1178:  * events available, poll returns immediately.  If not, it issues a
                   1179:  * poll to userspace, selrecords itself and returns with no available
                   1180:  * events.  When the file server returns, it executes puffs_parkdone_poll(),
                   1181:  * where available events are added to the bitmask.  selnotify() is
                   1182:  * then also executed by that function causing us to enter here again
                   1183:  * and hopefully find the missing bits (unless someone got them first,
                   1184:  * in which case it starts all over again).
                   1185:  */
1.1       pooka    1186: int
                   1187: puffs_poll(void *v)
                   1188: {
                   1189:        struct vop_poll_args /* {
                   1190:                const struct vnodeop_desc *a_desc;
                   1191:                struct vnode *a_vp;
                   1192:                int a_events;
                   1193:                struct lwp *a_l;
                   1194:        } */ *ap = v;
1.107     pooka    1195:        PUFFS_MSG_VARS(vn, poll);
1.69      pooka    1196:        struct vnode *vp = ap->a_vp;
                   1197:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
                   1198:        struct puffs_node *pn = vp->v_data;
                   1199:        int events;
1.1       pooka    1200:
1.69      pooka    1201:        if (EXISTSOP(pmp, POLL)) {
                   1202:                mutex_enter(&pn->pn_mtx);
                   1203:                events = pn->pn_revents & ap->a_events;
                   1204:                if (events & ap->a_events) {
                   1205:                        pn->pn_revents &= ~ap->a_events;
                   1206:                        mutex_exit(&pn->pn_mtx);
1.1       pooka    1207:
1.69      pooka    1208:                        return events;
                   1209:                } else {
                   1210:                        puffs_referencenode(pn);
                   1211:                        mutex_exit(&pn->pn_mtx);
                   1212:
1.107     pooka    1213:                        PUFFS_MSG_ALLOC(vn, poll);
                   1214:                        poll_msg->pvnr_events = ap->a_events;
                   1215:                        puffs_cidcvt(&poll_msg->pvnr_cid, ap->a_l);
1.69      pooka    1216:
1.70      pooka    1217:                        selrecord(ap->a_l, &pn->pn_sel);
1.107     pooka    1218:                        puffs_msg_vncall(pmp, park_poll, PUFFS_VN_POLL, 0,
                   1219:                            puffs_parkdone_poll, pn, vp);
                   1220:                        PUFFS_MSG_RELEASE(poll);
1.1       pooka    1221:
1.69      pooka    1222:                        return 0;
                   1223:                }
                   1224:        } else {
                   1225:                return genfs_poll(v);
                   1226:        }
1.1       pooka    1227: }
                   1228:
                   1229: int
                   1230: puffs_fsync(void *v)
                   1231: {
                   1232:        struct vop_fsync_args /* {
                   1233:                const struct vnodeop_desc *a_desc;
                   1234:                struct vnode *a_vp;
                   1235:                kauth_cred_t a_cred;
                   1236:                int a_flags;
                   1237:                off_t a_offlo;
                   1238:                off_t a_offhi;
                   1239:                struct lwp *a_l;
                   1240:        } */ *ap = v;
1.107     pooka    1241:        PUFFS_MSG_VARS(vn, fsync);
                   1242:        struct vnode *vp = ap->a_vp;
                   1243:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
                   1244:        struct puffs_node *pn;
1.54      pooka    1245:        struct vattr va;
1.35      pooka    1246:        int pflags, error, dofaf;
1.1       pooka    1247:
1.38      pooka    1248:        pn = VPTOPP(vp);
1.8       pooka    1249:
1.65      pooka    1250:        /* flush out information from our metacache, see vop_setattr */
1.72      pooka    1251:        if (pn->pn_stat & PNODE_METACACHE_MASK
                   1252:            && (pn->pn_stat & PNODE_DYING) == 0) {
1.54      pooka    1253:                vattr_null(&va);
                   1254:                error = VOP_SETATTR(vp, &va, FSCRED, NULL);
                   1255:                if (error)
                   1256:                        return error;
                   1257:        }
1.8       pooka    1258:
                   1259:        /*
                   1260:         * flush pages to avoid being overly dirty
                   1261:         */
1.54      pooka    1262:        pflags = PGO_CLEANIT;
                   1263:        if (ap->a_flags & FSYNC_WAIT)
                   1264:                pflags |= PGO_SYNCIO;
1.8       pooka    1265:        simple_lock(&vp->v_interlock);
                   1266:        error = VOP_PUTPAGES(vp, trunc_page(ap->a_offlo),
                   1267:            round_page(ap->a_offhi), pflags);
                   1268:        if (error)
                   1269:                return error;
                   1270:
1.31      pooka    1271:        /*
                   1272:         * HELLO!  We exit already here if the user server does not
1.38      pooka    1273:         * support fsync OR if we should call fsync for a node which
                   1274:         * has references neither in the kernel or the fs server.
                   1275:         * Otherwise we continue to issue fsync() forward.
1.31      pooka    1276:         */
1.72      pooka    1277:        if (!EXISTSOP(pmp, FSYNC) || (pn->pn_stat & PNODE_DYING))
1.31      pooka    1278:                return 0;
                   1279:
1.41      pooka    1280:        dofaf = (ap->a_flags & FSYNC_WAIT) == 0 || ap->a_flags == FSYNC_LAZY;
1.35      pooka    1281:        /*
                   1282:         * We abuse VXLOCK to mean "vnode is going to die", so we issue
                   1283:         * only FAFs for those.  Otherwise there's a danger of deadlock,
                   1284:         * since the execution context here might be the user server
                   1285:         * doing some operation on another fs, which in turn caused a
                   1286:         * vnode to be reclaimed from the freelist for this fs.
                   1287:         */
                   1288:        if (dofaf == 0) {
                   1289:                simple_lock(&vp->v_interlock);
1.105     ad       1290:                if (vp->v_iflag & VI_XLOCK)
1.35      pooka    1291:                        dofaf = 1;
                   1292:                simple_unlock(&vp->v_interlock);
                   1293:        }
                   1294:
1.107     pooka    1295:        PUFFS_MSG_ALLOC(vn, fsync);
                   1296:        if (dofaf)
                   1297:                puffs_msg_setfaf(park_fsync);
                   1298:
                   1299:        puffs_credcvt(&fsync_msg->pvnr_cred, ap->a_cred);
                   1300:        fsync_msg->pvnr_flags = ap->a_flags;
                   1301:        fsync_msg->pvnr_offlo = ap->a_offlo;
                   1302:        fsync_msg->pvnr_offhi = ap->a_offhi;
                   1303:        puffs_cidcvt(&fsync_msg->pvnr_cid, ap->a_l);
1.31      pooka    1304:
1.107     pooka    1305:        error = puffs_msg_vn(pmp, park_fsync, PUFFS_VN_FSYNC, 0, vp, NULL);
                   1306:        PUFFS_MSG_RELEASE(fsync);
1.1       pooka    1307:
1.107     pooka    1308:        error = checkerr(pmp, error, __func__);
1.8       pooka    1309:
                   1310:        return error;
1.1       pooka    1311: }
                   1312:
                   1313: int
                   1314: puffs_seek(void *v)
                   1315: {
                   1316:        struct vop_seek_args /* {
                   1317:                const struct vnodeop_desc *a_desc;
                   1318:                struct vnode *a_vp;
                   1319:                off_t a_oldoff;
                   1320:                off_t a_newoff;
                   1321:                kauth_cred_t a_cred;
                   1322:        } */ *ap = v;
1.107     pooka    1323:        PUFFS_MSG_VARS(vn, seek);
1.102     pooka    1324:        struct vnode *vp = ap->a_vp;
1.106     pooka    1325:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.102     pooka    1326:        int error;
1.1       pooka    1327:
1.107     pooka    1328:        PUFFS_MSG_ALLOC(vn, seek);
                   1329:        seek_msg->pvnr_oldoff = ap->a_oldoff;
                   1330:        seek_msg->pvnr_newoff = ap->a_newoff;
                   1331:        puffs_credcvt(&seek_msg->pvnr_cred, ap->a_cred);
1.1       pooka    1332:
1.107     pooka    1333:        error = puffs_msg_vn(pmp, park_seek, PUFFS_VN_SEEK, 0, vp, NULL);
                   1334:        PUFFS_MSG_RELEASE(seek);
1.106     pooka    1335:        return checkerr(pmp, error, __func__);
1.1       pooka    1336: }
                   1337:
1.103     pooka    1338: static int
                   1339: puffs_callremove(struct puffs_mount *pmp, void *dcookie, void *cookie,
                   1340:        struct componentname *cnp)
                   1341: {
1.107     pooka    1342:        PUFFS_MSG_VARS(vn, remove);
                   1343:        struct puffs_req *preq;
1.103     pooka    1344:        int error;
                   1345:
1.107     pooka    1346:        PUFFS_MSG_ALLOC(vn, remove);
                   1347:        remove_msg->pvnr_cookie_targ = cookie;
                   1348:        puffs_makecn(&remove_msg->pvnr_cn, &remove_msg->pvnr_cn_cred,
                   1349:            &remove_msg->pvnr_cn_cid, cnp, PUFFS_USE_FULLPNBUF(pmp));
                   1350:
                   1351:        /* XXX: uh, this is wrong because we don't get setbacks with raw */
                   1352:        preq = (struct puffs_req *)remove_msg;
                   1353:        preq->preq_cookie = dcookie;
                   1354:        preq->preq_opclass = PUFFSOP_VN;
                   1355:        preq->preq_optype = PUFFS_VN_REMOVE;
1.103     pooka    1356:
1.107     pooka    1357:        error = puffs_msg_raw(pmp, park_remove);
                   1358:        PUFFS_MSG_RELEASE(remove);
1.103     pooka    1359:
                   1360:        return checkerr(pmp, error, __func__);
                   1361: }
                   1362:
1.107     pooka    1363: /*
                   1364:  * XXX: can't use callremove now because can't catch setbacks with
                   1365:  * it due to lack of a vnode argument.
                   1366:  */
1.1       pooka    1367: int
                   1368: puffs_remove(void *v)
                   1369: {
                   1370:        struct vop_remove_args /* {
                   1371:                const struct vnodeop_desc *a_desc;
                   1372:                struct vnode *a_dvp;
                   1373:                struct vnode *a_vp;
                   1374:                struct componentname *a_cnp;
                   1375:        } */ *ap = v;
1.107     pooka    1376:        PUFFS_MSG_VARS(vn, remove);
1.103     pooka    1377:        struct vnode *dvp = ap->a_dvp;
                   1378:        struct vnode *vp = ap->a_vp;
                   1379:        struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount);
1.107     pooka    1380:        struct componentname *cnp = ap->a_cnp;
1.1       pooka    1381:        int error;
                   1382:
1.107     pooka    1383:        PUFFS_MSG_ALLOC(vn, remove);
                   1384:        remove_msg->pvnr_cookie_targ = VPTOPNC(vp);
                   1385:        puffs_makecn(&remove_msg->pvnr_cn, &remove_msg->pvnr_cn_cred,
                   1386:            &remove_msg->pvnr_cn_cid, cnp, PUFFS_USE_FULLPNBUF(pmp));
1.1       pooka    1387:
1.107     pooka    1388:        error = puffs_msg_vn(pmp, park_remove, PUFFS_VN_REMOVE, 0, dvp, vp);
                   1389:        PUFFS_MSG_RELEASE(remove);
                   1390:
                   1391:        error = checkerr(pmp, error, __func__);
1.103     pooka    1392:        vput(vp);
                   1393:        if (dvp == vp)
                   1394:                vrele(dvp);
1.25      pooka    1395:        else
1.103     pooka    1396:                vput(dvp);
1.1       pooka    1397:
                   1398:        return error;
                   1399: }
                   1400:
                   1401: int
                   1402: puffs_mkdir(void *v)
                   1403: {
                   1404:        struct vop_mkdir_args /* {
                   1405:                const struct vnodeop_desc *a_desc;
                   1406:                struct vnode *a_dvp;
                   1407:                struct vnode **a_vpp;
                   1408:                struct componentname *a_cnp;
                   1409:                struct vattr *a_vap;
                   1410:        } */ *ap = v;
1.107     pooka    1411:        PUFFS_MSG_VARS(vn, mkdir);
                   1412:        struct vnode *dvp = ap->a_dvp;
                   1413:        struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount);
1.111     pooka    1414:        struct componentname *cnp = ap->a_cnp;
1.1       pooka    1415:        int error;
                   1416:
1.107     pooka    1417:        PUFFS_MSG_ALLOC(vn, mkdir);
                   1418:        puffs_makecn(&mkdir_msg->pvnr_cn, &mkdir_msg->pvnr_cn_cred,
1.111     pooka    1419:            &mkdir_msg->pvnr_cn_cid, cnp, PUFFS_USE_FULLPNBUF(pmp));
1.107     pooka    1420:        mkdir_msg->pvnr_va = *ap->a_vap;
1.1       pooka    1421:
1.107     pooka    1422:        error = puffs_msg_vn(pmp, park_mkdir, PUFFS_VN_MKDIR, 0, dvp, NULL);
1.102     pooka    1423:        error = checkerr(pmp, error, __func__);
1.1       pooka    1424:        if (error)
1.4       pooka    1425:                goto out;
1.1       pooka    1426:
1.107     pooka    1427:        error = puffs_newnode(dvp->v_mount, dvp, ap->a_vpp,
1.111     pooka    1428:            mkdir_msg->pvnr_newnode, cnp, VDIR, 0);
1.103     pooka    1429:        if (error)
                   1430:                puffs_abortbutton(pmp, PUFFS_ABORT_MKDIR, VPTOPNC(ap->a_dvp),
1.111     pooka    1431:                    mkdir_msg->pvnr_newnode, cnp);
1.4       pooka    1432:
                   1433:  out:
1.107     pooka    1434:        PUFFS_MSG_RELEASE(mkdir);
1.111     pooka    1435:        if (error || (cnp->cn_flags & SAVESTART) == 0)
                   1436:                PNBUF_PUT(cnp->cn_pnbuf);
1.4       pooka    1437:        vput(ap->a_dvp);
                   1438:        return error;
1.1       pooka    1439: }
                   1440:
1.103     pooka    1441: static int
                   1442: puffs_callrmdir(struct puffs_mount *pmp, void *dcookie, void *cookie,
                   1443:        struct componentname *cnp)
                   1444: {
1.107     pooka    1445:        PUFFS_MSG_VARS(vn, rmdir);
                   1446:        struct puffs_req *preq;
1.103     pooka    1447:        int error;
                   1448:
1.107     pooka    1449:        PUFFS_MSG_ALLOC(vn, rmdir);
                   1450:        rmdir_msg->pvnr_cookie_targ = cookie;
                   1451:        puffs_makecn(&rmdir_msg->pvnr_cn, &rmdir_msg->pvnr_cn_cred,
                   1452:            &rmdir_msg->pvnr_cn_cid, cnp, PUFFS_USE_FULLPNBUF(pmp));
                   1453:
                   1454:        /* XXX: uh, this is wrong because we don't get setbacks with raw */
                   1455:        preq = (struct puffs_req *)rmdir_msg;
                   1456:        preq->preq_cookie = dcookie;
                   1457:        preq->preq_opclass = PUFFSOP_VN;
                   1458:        preq->preq_optype = PUFFS_VN_RMDIR;
1.103     pooka    1459:
1.107     pooka    1460:        error = puffs_msg_raw(pmp, park_rmdir);
                   1461:        PUFFS_MSG_RELEASE(rmdir);
1.103     pooka    1462:
                   1463:        return checkerr(pmp, error, __func__);
                   1464: }
                   1465:
1.1       pooka    1466: int
                   1467: puffs_rmdir(void *v)
                   1468: {
                   1469:        struct vop_rmdir_args /* {
                   1470:                const struct vnodeop_desc *a_desc;
                   1471:                struct vnode *a_dvp;
                   1472:                struct vnode *a_vp;
                   1473:                struct componentname *a_cnp;
                   1474:        } */ *ap = v;
1.107     pooka    1475:        PUFFS_MSG_VARS(vn, rmdir);
1.103     pooka    1476:        struct vnode *dvp = ap->a_dvp;
                   1477:        struct vnode *vp = ap->a_vp;
                   1478:        struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount);
1.107     pooka    1479:        struct componentname *cnp = ap->a_cnp;
1.1       pooka    1480:        int error;
                   1481:
1.107     pooka    1482:        PUFFS_MSG_ALLOC(vn, rmdir);
                   1483:        rmdir_msg->pvnr_cookie_targ = VPTOPNC(vp);
                   1484:        puffs_makecn(&rmdir_msg->pvnr_cn, &rmdir_msg->pvnr_cn_cred,
                   1485:            &rmdir_msg->pvnr_cn_cid, cnp, PUFFS_USE_FULLPNBUF(pmp));
                   1486:
                   1487:        error = puffs_msg_vn(pmp, park_rmdir, PUFFS_VN_RMDIR, 0, dvp, vp);
                   1488:        PUFFS_MSG_RELEASE(rmdir);
1.1       pooka    1489:
1.23      pooka    1490:        /* XXX: some call cache_purge() *for both vnodes* here, investigate */
1.103     pooka    1491:        vput(dvp);
                   1492:        vput(vp);
1.1       pooka    1493:
                   1494:        return error;
                   1495: }
                   1496:
                   1497: int
                   1498: puffs_link(void *v)
                   1499: {
                   1500:        struct vop_link_args /* {
                   1501:                const struct vnodeop_desc *a_desc;
                   1502:                struct vnode *a_dvp;
                   1503:                struct vnode *a_vp;
                   1504:                struct componentname *a_cnp;
                   1505:        } */ *ap = v;
1.107     pooka    1506:        PUFFS_MSG_VARS(vn, link);
                   1507:        struct vnode *dvp = ap->a_dvp;
                   1508:        struct vnode *vp = ap->a_vp;
                   1509:        struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount);
1.111     pooka    1510:        struct componentname *cnp = ap->a_cnp;
1.1       pooka    1511:        int error;
                   1512:
1.107     pooka    1513:        PUFFS_MSG_ALLOC(vn, link);
                   1514:        link_msg->pvnr_cookie_targ = VPTOPNC(vp);
                   1515:        puffs_makecn(&link_msg->pvnr_cn, &link_msg->pvnr_cn_cred,
1.111     pooka    1516:            &link_msg->pvnr_cn_cid, cnp, PUFFS_USE_FULLPNBUF(pmp));
1.1       pooka    1517:
1.107     pooka    1518:        error = puffs_msg_vn(pmp, park_link, PUFFS_VN_LINK, 0, dvp, NULL);
                   1519:        PUFFS_MSG_RELEASE(link);
1.1       pooka    1520:
1.102     pooka    1521:        error = checkerr(pmp, error, __func__);
1.1       pooka    1522:
1.54      pooka    1523:        /*
                   1524:         * XXX: stay in touch with the cache.  I don't like this, but
                   1525:         * don't have a better solution either.  See also puffs_rename().
                   1526:         */
                   1527:        if (error == 0)
1.107     pooka    1528:                puffs_updatenode(vp, PUFFS_UPDATECTIME);
1.54      pooka    1529:
1.111     pooka    1530:        PNBUF_PUT(cnp->cn_pnbuf);
1.107     pooka    1531:        vput(dvp);
1.1       pooka    1532:
                   1533:        return error;
                   1534: }
                   1535:
                   1536: int
                   1537: puffs_symlink(void *v)
                   1538: {
                   1539:        struct vop_symlink_args /* {
                   1540:                const struct vnodeop_desc *a_desc;
                   1541:                struct vnode *a_dvp;
                   1542:                struct vnode **a_vpp;
                   1543:                struct componentname *a_cnp;
                   1544:                struct vattr *a_vap;
                   1545:                char *a_target;
                   1546:        } */ *ap = v;
1.107     pooka    1547:        PUFFS_MSG_VARS(vn, symlink);
                   1548:        struct vnode *dvp = ap->a_dvp;
                   1549:        struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount);
1.1       pooka    1550:        int error;
                   1551:
                   1552:        *ap->a_vpp = NULL;
                   1553:
1.107     pooka    1554:        PUFFS_MSG_ALLOC(vn, symlink);
                   1555:        puffs_makecn(&symlink_msg->pvnr_cn, &symlink_msg->pvnr_cn_cred,
                   1556:                &symlink_msg->pvnr_cn_cid, ap->a_cnp, PUFFS_USE_FULLPNBUF(pmp));
                   1557:        symlink_msg->pvnr_va = *ap->a_vap;
                   1558:        (void)strlcpy(symlink_msg->pvnr_link, ap->a_target,
                   1559:            sizeof(symlink_msg->pvnr_link));
1.1       pooka    1560:
1.107     pooka    1561:        error =  puffs_msg_vn(pmp, park_symlink, PUFFS_VN_SYMLINK, 0, dvp,NULL);
1.102     pooka    1562:        error = checkerr(pmp, error, __func__);
1.1       pooka    1563:        if (error)
1.4       pooka    1564:                goto out;
1.1       pooka    1565:
1.4       pooka    1566:        error = puffs_newnode(ap->a_dvp->v_mount, ap->a_dvp, ap->a_vpp,
1.107     pooka    1567:            symlink_msg->pvnr_newnode, ap->a_cnp, VLNK, 0);
1.103     pooka    1568:        if (error)
                   1569:                puffs_abortbutton(pmp, PUFFS_ABORT_SYMLINK, VPTOPNC(ap->a_dvp),
1.107     pooka    1570:                    symlink_msg->pvnr_newnode, ap->a_cnp);
1.4       pooka    1571:
                   1572:  out:
1.107     pooka    1573:        PUFFS_MSG_RELEASE(symlink);
1.4       pooka    1574:        if (error || (ap->a_cnp->cn_flags & SAVESTART) == 0)
                   1575:                PNBUF_PUT(ap->a_cnp->cn_pnbuf);
                   1576:        vput(ap->a_dvp);
1.81      pooka    1577:
1.4       pooka    1578:        return error;
1.1       pooka    1579: }
                   1580:
                   1581: int
                   1582: puffs_readlink(void *v)
                   1583: {
                   1584:        struct vop_readlink_args /* {
                   1585:                const struct vnodeop_desc *a_desc;
                   1586:                struct vnode *a_vp;
                   1587:                struct uio *a_uio;
                   1588:                kauth_cred_t a_cred;
                   1589:        } */ *ap = v;
1.107     pooka    1590:        PUFFS_MSG_VARS(vn, readlink);
                   1591:        struct vnode *vp = ap->a_vp;
1.100     pooka    1592:        struct puffs_mount *pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
1.51      pooka    1593:        size_t linklen;
1.1       pooka    1594:        int error;
                   1595:
1.107     pooka    1596:        PUFFS_MSG_ALLOC(vn, readlink);
                   1597:        puffs_credcvt(&readlink_msg->pvnr_cred, ap->a_cred);
                   1598:        linklen = sizeof(readlink_msg->pvnr_link);
                   1599:        readlink_msg->pvnr_linklen = linklen;
1.1       pooka    1600:
1.107     pooka    1601:        error = puffs_msg_vn(pmp, park_readlink, PUFFS_VN_READLINK, 0, vp,NULL);
1.102     pooka    1602:        error = checkerr(pmp, error, __func__);
1.1       pooka    1603:        if (error)
1.107     pooka    1604:                goto out;
1.1       pooka    1605:
1.51      pooka    1606:        /* bad bad user file server */
1.107     pooka    1607:        if (readlink_msg->pvnr_linklen > linklen) {
                   1608:                puffs_msg_errnotify(pmp, PUFFS_ERR_READLINK, E2BIG,
1.102     pooka    1609:                    "linklen too big", VPTOPNC(ap->a_vp));
1.107     pooka    1610:                error = EPROTO;
                   1611:                goto out;
1.100     pooka    1612:        }
1.51      pooka    1613:
1.107     pooka    1614:        error = uiomove(&readlink_msg->pvnr_link, readlink_msg->pvnr_linklen,
1.1       pooka    1615:            ap->a_uio);
1.107     pooka    1616:  out:
                   1617:        PUFFS_MSG_RELEASE(readlink);
                   1618:        return error;
1.1       pooka    1619: }
                   1620:
                   1621: int
                   1622: puffs_rename(void *v)
                   1623: {
                   1624:        struct vop_rename_args /* {
                   1625:                const struct vnodeop_desc *a_desc;
                   1626:                struct vnode *a_fdvp;
                   1627:                struct vnode *a_fvp;
                   1628:                struct componentname *a_fcnp;
                   1629:                struct vnode *a_tdvp;
                   1630:                struct vnode *a_tvp;
                   1631:                struct componentname *a_tcnp;
                   1632:        } */ *ap = v;
1.107     pooka    1633:        PUFFS_MSG_VARS(vn, rename);
1.83      pooka    1634:        struct puffs_mount *pmp = MPTOPUFFSMP(ap->a_fdvp->v_mount);
1.1       pooka    1635:        int error;
                   1636:
1.79      pooka    1637:        if (ap->a_fvp->v_mount != ap->a_tdvp->v_mount)
                   1638:                ERROUT(EXDEV);
1.1       pooka    1639:
1.107     pooka    1640:        PUFFS_MSG_ALLOC(vn, rename);
                   1641:        rename_msg->pvnr_cookie_src = VPTOPNC(ap->a_fvp);
                   1642:        rename_msg->pvnr_cookie_targdir = VPTOPNC(ap->a_tdvp);
1.1       pooka    1643:        if (ap->a_tvp)
1.107     pooka    1644:                rename_msg->pvnr_cookie_targ = VPTOPNC(ap->a_tvp);
1.1       pooka    1645:        else
1.107     pooka    1646:                rename_msg->pvnr_cookie_targ = NULL;
                   1647:        puffs_makecn(&rename_msg->pvnr_cn_src,
                   1648:            &rename_msg->pvnr_cn_src_cred, &rename_msg->pvnr_cn_src_cid,
1.83      pooka    1649:            ap->a_fcnp, PUFFS_USE_FULLPNBUF(pmp));
1.107     pooka    1650:        puffs_makecn(&rename_msg->pvnr_cn_targ,
                   1651:            &rename_msg->pvnr_cn_targ_cred, &rename_msg->pvnr_cn_targ_cid,
1.83      pooka    1652:            ap->a_tcnp, PUFFS_USE_FULLPNBUF(pmp));
1.1       pooka    1653:
1.107     pooka    1654:        error = puffs_msg_vn(pmp, park_rename, PUFFS_VN_RENAME,
                   1655:            0, ap->a_fdvp, NULL); /* XXX: missing vnodes */
1.102     pooka    1656:        error = checkerr(pmp, error, __func__);
1.1       pooka    1657:
1.54      pooka    1658:        /*
                   1659:         * XXX: stay in touch with the cache.  I don't like this, but
                   1660:         * don't have a better solution either.  See also puffs_link().
                   1661:         */
                   1662:        if (error == 0)
                   1663:                puffs_updatenode(ap->a_fvp, PUFFS_UPDATECTIME);
                   1664:
1.1       pooka    1665:  out:
1.107     pooka    1666:        PUFFS_MSG_RELEASE(rename);
1.1       pooka    1667:        if (ap->a_tvp != NULL)
                   1668:                vput(ap->a_tvp);
1.28      pooka    1669:        if (ap->a_tdvp == ap->a_tvp)
                   1670:                vrele(ap->a_tdvp);
                   1671:        else
                   1672:                vput(ap->a_tdvp);
1.1       pooka    1673:
                   1674:        vrele(ap->a_fdvp);
                   1675:        vrele(ap->a_fvp);
                   1676:
                   1677:        return error;
                   1678: }
                   1679:
1.79      pooka    1680: #define RWARGS(cont, iofl, move, offset, creds)                                \
                   1681:        (cont)->pvnr_ioflag = (iofl);                                   \
                   1682:        (cont)->pvnr_resid = (move);                                    \
                   1683:        (cont)->pvnr_offset = (offset);                                 \
                   1684:        puffs_credcvt(&(cont)->pvnr_cred, creds)
                   1685:
1.1       pooka    1686: int
                   1687: puffs_read(void *v)
                   1688: {
                   1689:        struct vop_read_args /* {
                   1690:                const struct vnodeop_desc *a_desc;
                   1691:                struct vnode *a_vp;
                   1692:                struct uio *a_uio;
                   1693:                int a_ioflag;
                   1694:                kauth_cred_t a_cred;
                   1695:        } */ *ap = v;
1.107     pooka    1696:        PUFFS_MSG_VARS(vn, read);
                   1697:        struct vnode *vp = ap->a_vp;
                   1698:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
                   1699:        struct uio *uio = ap->a_uio;
1.8       pooka    1700:        void *win;
1.1       pooka    1701:        size_t tomove, argsize;
1.8       pooka    1702:        vsize_t bytelen;
1.11      pooka    1703:        int error, ubcflags;
1.1       pooka    1704:
1.107     pooka    1705:        read_msg = NULL;
1.8       pooka    1706:        error = 0;
1.1       pooka    1707:
1.8       pooka    1708:        /* std sanity */
                   1709:        if (uio->uio_resid == 0)
                   1710:                return 0;
                   1711:        if (uio->uio_offset < 0)
                   1712:                return EINVAL;
1.1       pooka    1713:
1.78      pooka    1714:        if (vp->v_type == VREG && PUFFS_USE_PAGECACHE(pmp)) {
1.8       pooka    1715:                const int advice = IO_ADV_DECODE(ap->a_ioflag);
1.1       pooka    1716:
1.12      pooka    1717:                ubcflags = 0;
1.15      pooka    1718:                if (UBC_WANT_UNMAP(vp))
1.12      pooka    1719:                        ubcflags = UBC_UNMAP;
                   1720:
1.8       pooka    1721:                while (uio->uio_resid > 0) {
                   1722:                        bytelen = MIN(uio->uio_resid,
                   1723:                            vp->v_size - uio->uio_offset);
                   1724:                        if (bytelen == 0)
                   1725:                                break;
                   1726:
                   1727:                        win = ubc_alloc(&vp->v_uobj, uio->uio_offset,
                   1728:                            &bytelen, advice, UBC_READ);
                   1729:                        error = uiomove(win, bytelen, uio);
1.11      pooka    1730:                        ubc_release(win, ubcflags);
1.8       pooka    1731:                        if (error)
                   1732:                                break;
1.1       pooka    1733:                }
                   1734:
1.8       pooka    1735:                if ((vp->v_mount->mnt_flag & MNT_NOATIME) == 0)
                   1736:                        puffs_updatenode(vp, PUFFS_UPDATEATIME);
                   1737:        } else {
1.1       pooka    1738:                /*
1.15      pooka    1739:                 * in case it's not a regular file or we're operating
                   1740:                 * uncached, do read in the old-fashioned style,
                   1741:                 * i.e. explicit read operations
1.1       pooka    1742:                 */
                   1743:
                   1744:                tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
1.107     pooka    1745:                argsize = sizeof(struct puffs_vnmsg_read);
                   1746:                puffs_msgmem_alloc(argsize + tomove, &park_read,
                   1747:                    (void **)&read_msg, 1);
1.8       pooka    1748:
                   1749:                error = 0;
                   1750:                while (uio->uio_resid > 0) {
1.79      pooka    1751:                        tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
1.107     pooka    1752:                        RWARGS(read_msg, ap->a_ioflag, tomove,
1.79      pooka    1753:                            uio->uio_offset, ap->a_cred);
1.8       pooka    1754:
1.107     pooka    1755:                        error = puffs_msg_vn(pmp, park_read, PUFFS_VN_READ,
1.110     pooka    1756:                            tomove, vp, NULL);
1.102     pooka    1757:                        error = checkerr(pmp, error, __func__);
1.8       pooka    1758:                        if (error)
                   1759:                                break;
                   1760:
1.107     pooka    1761:                        if (read_msg->pvnr_resid > tomove) {
                   1762:                                puffs_msg_errnotify(pmp, PUFFS_ERR_READ,
1.102     pooka    1763:                                    E2BIG, "resid grew", VPTOPNC(ap->a_vp));
1.100     pooka    1764:                                error = EPROTO;
1.8       pooka    1765:                                break;
                   1766:                        }
                   1767:
1.107     pooka    1768:                        error = uiomove(read_msg->pvnr_data,
                   1769:                            tomove - read_msg->pvnr_resid, uio);
1.8       pooka    1770:
                   1771:                        /*
                   1772:                         * in case the file is out of juice, resid from
                   1773:                         * userspace is != 0.  and the error-case is
                   1774:                         * quite obvious
                   1775:                         */
1.107     pooka    1776:                        if (error || read_msg->pvnr_resid)
1.8       pooka    1777:                                break;
                   1778:                }
1.107     pooka    1779:
                   1780:                puffs_msgmem_release(park_read);
1.1       pooka    1781:        }
                   1782:
                   1783:        return error;
                   1784: }
                   1785:
1.79      pooka    1786: /*
                   1787:  * XXX: in case of a failure, this leaves uio in a bad state.
                   1788:  * We could theoretically copy the uio and iovecs and "replay"
                   1789:  * them the right amount after the userspace trip, but don't
                   1790:  * bother for now.
                   1791:  */
1.1       pooka    1792: int
                   1793: puffs_write(void *v)
                   1794: {
                   1795:        struct vop_write_args /* {
                   1796:                const struct vnodeop_desc *a_desc;
                   1797:                struct vnode *a_vp;
                   1798:                struct uio *a_uio;
                   1799:                int a_ioflag;
                   1800:                kauth_cred_t a_cred;
1.73      yamt     1801:        } */ *ap = v;
1.107     pooka    1802:        PUFFS_MSG_VARS(vn, write);
                   1803:        struct vnode *vp = ap->a_vp;
                   1804:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
                   1805:        struct uio *uio = ap->a_uio;
1.1       pooka    1806:        size_t tomove, argsize;
1.8       pooka    1807:        off_t oldoff, newoff, origoff;
                   1808:        vsize_t bytelen;
1.15      pooka    1809:        int error, uflags;
1.50      pooka    1810:        int ubcflags;
1.1       pooka    1811:
1.8       pooka    1812:        error = uflags = 0;
1.107     pooka    1813:        write_msg = NULL;
1.11      pooka    1814:
1.78      pooka    1815:        if (vp->v_type == VREG && PUFFS_USE_PAGECACHE(pmp)) {
1.74      yamt     1816:                ubcflags = UBC_WRITE | UBC_PARTIALOK;
1.15      pooka    1817:                if (UBC_WANT_UNMAP(vp))
1.95      pooka    1818:                        ubcflags |= UBC_UNMAP;
1.12      pooka    1819:
1.8       pooka    1820:                /*
                   1821:                 * userspace *should* be allowed to control this,
                   1822:                 * but with UBC it's a bit unclear how to handle it
                   1823:                 */
                   1824:                if (ap->a_ioflag & IO_APPEND)
                   1825:                        uio->uio_offset = vp->v_size;
1.1       pooka    1826:
1.8       pooka    1827:                origoff = uio->uio_offset;
                   1828:                while (uio->uio_resid > 0) {
                   1829:                        uflags |= PUFFS_UPDATECTIME;
                   1830:                        uflags |= PUFFS_UPDATEMTIME;
                   1831:                        oldoff = uio->uio_offset;
                   1832:                        bytelen = uio->uio_resid;
                   1833:
1.74      yamt     1834:                        newoff = oldoff + bytelen;
                   1835:                        if (vp->v_size < newoff) {
                   1836:                                uvm_vnp_setwritesize(vp, newoff);
                   1837:                        }
                   1838:                        error = ubc_uiomove(&vp->v_uobj, uio, bytelen,
1.93      yamt     1839:                            UVM_ADV_RANDOM, ubcflags);
1.8       pooka    1840:
                   1841:                        /*
1.74      yamt     1842:                         * In case of a ubc_uiomove() error,
1.64      pooka    1843:                         * opt to not extend the file at all and
                   1844:                         * return an error.  Otherwise, if we attempt
                   1845:                         * to clear the memory we couldn't fault to,
                   1846:                         * we might generate a kernel page fault.
1.8       pooka    1847:                         */
1.74      yamt     1848:                        if (vp->v_size < newoff) {
                   1849:                                if (error == 0) {
                   1850:                                        uflags |= PUFFS_UPDATESIZE;
                   1851:                                        uvm_vnp_setsize(vp, newoff);
                   1852:                                } else {
                   1853:                                        uvm_vnp_setwritesize(vp, vp->v_size);
                   1854:                                }
1.8       pooka    1855:                        }
                   1856:                        if (error)
                   1857:                                break;
                   1858:
1.50      pooka    1859:                        /*
                   1860:                         * If we're writing large files, flush to file server
                   1861:                         * every 64k.  Otherwise we can very easily exhaust
                   1862:                         * kernel and user memory, as the file server cannot
                   1863:                         * really keep up with our writing speed.
                   1864:                         *
                   1865:                         * Note: this does *NOT* honor MNT_ASYNC, because
                   1866:                         * that gives userland too much say in the kernel.
                   1867:                         */
                   1868:                        if (oldoff >> 16 != uio->uio_offset >> 16) {
1.8       pooka    1869:                                simple_lock(&vp->v_interlock);
                   1870:                                error = VOP_PUTPAGES(vp, oldoff & ~0xffff,
1.50      pooka    1871:                                    uio->uio_offset & ~0xffff,
                   1872:                                    PGO_CLEANIT | PGO_SYNCIO);
1.8       pooka    1873:                                if (error)
                   1874:                                        break;
                   1875:                        }
1.1       pooka    1876:                }
1.8       pooka    1877:
1.62      pooka    1878:                /* synchronous I/O? */
1.15      pooka    1879:                if (error == 0 && ap->a_ioflag & IO_SYNC) {
1.8       pooka    1880:                        simple_lock(&vp->v_interlock);
                   1881:                        error = VOP_PUTPAGES(vp, trunc_page(origoff),
1.15      pooka    1882:                            round_page(uio->uio_offset),
                   1883:                            PGO_CLEANIT | PGO_SYNCIO);
1.62      pooka    1884:
1.97      pooka    1885:                /* write through page cache? */
1.62      pooka    1886:                } else if (error == 0 && pmp->pmp_flags & PUFFS_KFLAG_WTCACHE) {
                   1887:                        simple_lock(&vp->v_interlock);
                   1888:                        error = VOP_PUTPAGES(vp, trunc_page(origoff),
                   1889:                            round_page(uio->uio_offset), PGO_CLEANIT);
1.1       pooka    1890:                }
                   1891:
1.8       pooka    1892:                puffs_updatenode(vp, uflags);
                   1893:        } else {
1.19      pooka    1894:                /* tomove is non-increasing */
1.1       pooka    1895:                tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
1.107     pooka    1896:                argsize = sizeof(struct puffs_vnmsg_write) + tomove;
                   1897:                puffs_msgmem_alloc(argsize, &park_write, (void **)&write_msg,1);
1.8       pooka    1898:
                   1899:                while (uio->uio_resid > 0) {
1.79      pooka    1900:                        /* move data to buffer */
                   1901:                        tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
1.107     pooka    1902:                        RWARGS(write_msg, ap->a_ioflag, tomove,
1.79      pooka    1903:                            uio->uio_offset, ap->a_cred);
1.107     pooka    1904:                        error = uiomove(write_msg->pvnr_data, tomove, uio);
1.8       pooka    1905:                        if (error)
                   1906:                                break;
                   1907:
1.79      pooka    1908:                        /* move buffer to userspace */
1.107     pooka    1909:                        error = puffs_msg_vn(pmp, park_write, PUFFS_VN_WRITE,
                   1910:                            0, vp, NULL);
1.102     pooka    1911:                        error = checkerr(pmp, error, __func__);
1.79      pooka    1912:                        if (error)
1.8       pooka    1913:                                break;
1.79      pooka    1914:
1.107     pooka    1915:                        if (write_msg->pvnr_resid > tomove) {
                   1916:                                puffs_msg_errnotify(pmp, PUFFS_ERR_WRITE,
1.102     pooka    1917:                                    E2BIG, "resid grew", VPTOPNC(ap->a_vp));
1.100     pooka    1918:                                error = EPROTO;
1.8       pooka    1919:                                break;
                   1920:                        }
                   1921:
                   1922:                        /* adjust file size */
1.20      pooka    1923:                        if (vp->v_size < uio->uio_offset)
                   1924:                                uvm_vnp_setsize(vp, uio->uio_offset);
1.8       pooka    1925:
                   1926:                        /* didn't move everything?  bad userspace.  bail */
1.107     pooka    1927:                        if (write_msg->pvnr_resid != 0) {
1.8       pooka    1928:                                error = EIO;
                   1929:                                break;
                   1930:                        }
                   1931:                }
1.107     pooka    1932:                puffs_msgmem_release(park_write);
1.1       pooka    1933:        }
                   1934:
                   1935:        return error;
                   1936: }
                   1937:
                   1938: int
                   1939: puffs_print(void *v)
                   1940: {
                   1941:        struct vop_print_args /* {
                   1942:                struct vnode *a_vp;
                   1943:        } */ *ap = v;
1.107     pooka    1944:        PUFFS_MSG_VARS(vn, print);
1.1       pooka    1945:        struct vnode *vp = ap->a_vp;
1.107     pooka    1946:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.2       pooka    1947:        struct puffs_node *pn = vp->v_data;
1.1       pooka    1948:
                   1949:        /* kernel portion */
1.2       pooka    1950:        printf("tag VT_PUFFS, vnode %p, puffs node: %p,\n"
                   1951:            "    userspace cookie: %p\n", vp, pn, pn->pn_cookie);
1.6       pooka    1952:        if (vp->v_type == VFIFO)
                   1953:                fifo_printinfo(vp);
1.1       pooka    1954:        lockmgr_printinfo(&vp->v_lock);
                   1955:
                   1956:        /* userspace portion */
1.107     pooka    1957:        if (EXISTSOP(pmp, PRINT)) {
                   1958:                PUFFS_MSG_ALLOC(vn, print);
                   1959:                puffs_msg_vn(pmp, park_print, PUFFS_VN_PRINT, 0, vp, NULL);
                   1960:                PUFFS_MSG_RELEASE(print);
                   1961:        }
1.17      pooka    1962:
                   1963:        return 0;
1.1       pooka    1964: }
                   1965:
                   1966: int
                   1967: puffs_pathconf(void *v)
                   1968: {
                   1969:        struct vop_pathconf_args /* {
                   1970:                const struct vnodeop_desc *a_desc;
                   1971:                struct vnode *a_vp;
                   1972:                int a_name;
                   1973:                register_t *a_retval;
                   1974:        } */ *ap = v;
1.107     pooka    1975:        PUFFS_MSG_VARS(vn, pathconf);
1.102     pooka    1976:        struct vnode *vp = ap->a_vp;
                   1977:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.1       pooka    1978:        int error;
                   1979:
1.107     pooka    1980:        PUFFS_MSG_ALLOC(vn, pathconf);
                   1981:        pathconf_msg->pvnr_name = ap->a_name;
                   1982:        error = puffs_msg_vn(pmp, park_pathconf, PUFFS_VN_PATHCONF, 0, vp,NULL);
1.102     pooka    1983:        error = checkerr(pmp, error, __func__);
1.107     pooka    1984:        if (!error)
                   1985:                *ap->a_retval = pathconf_msg->pvnr_retval;
                   1986:        PUFFS_MSG_RELEASE(pathconf);
1.1       pooka    1987:
1.107     pooka    1988:        return error;
1.1       pooka    1989: }
                   1990:
                   1991: int
                   1992: puffs_advlock(void *v)
                   1993: {
                   1994:        struct vop_advlock_args /* {
                   1995:                const struct vnodeop_desc *a_desc;
                   1996:                struct vnode *a_vp;
                   1997:                void *a_id;
                   1998:                int a_op;
                   1999:                struct flock *a_fl;
                   2000:                int a_flags;
                   2001:        } */ *ap = v;
1.107     pooka    2002:        PUFFS_MSG_VARS(vn, advlock);
1.102     pooka    2003:        struct vnode *vp = ap->a_vp;
                   2004:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.1       pooka    2005:        int error;
                   2006:
1.107     pooka    2007:        PUFFS_MSG_ALLOC(vn, advlock);
                   2008:        error = copyin(ap->a_fl, &advlock_msg->pvnr_fl, sizeof(struct flock));
                   2009:        if (error)
                   2010:                goto out;
                   2011:        advlock_msg->pvnr_id = ap->a_id;
                   2012:        advlock_msg->pvnr_op = ap->a_op;
                   2013:        advlock_msg->pvnr_flags = ap->a_flags;
1.1       pooka    2014:
1.107     pooka    2015:        error = puffs_msg_vn(pmp, park_advlock, PUFFS_VN_ADVLOCK, 0, vp, NULL);
                   2016:        error = checkerr(pmp, error, __func__);
1.1       pooka    2017:
1.107     pooka    2018:  out:
                   2019:        PUFFS_MSG_RELEASE(advlock);
                   2020:        return error;
1.1       pooka    2021: }
1.79      pooka    2022:
                   2023: #define BIOASYNC(bp) (bp->b_flags & B_ASYNC)
                   2024: #define BIOREAD(bp) (bp->b_flags & B_READ)
                   2025: #define BIOWRITE(bp) ((bp->b_flags & B_READ) == 0)
                   2026:
1.8       pooka    2027: /*
                   2028:  * This maps itself to PUFFS_VN_READ/WRITE for data transfer.
                   2029:  */
                   2030: int
                   2031: puffs_strategy(void *v)
                   2032: {
                   2033:        struct vop_strategy_args /* {
                   2034:                const struct vnodeop_desc *a_desc;
                   2035:                struct vnode *a_vp;
                   2036:                struct buf *a_bp;
                   2037:        } */ *ap = v;
1.107     pooka    2038:        PUFFS_MSG_VARS(vn, rw);
1.35      pooka    2039:        struct vnode *vp = ap->a_vp;
1.107     pooka    2040:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.38      pooka    2041:        struct puffs_node *pn;
1.8       pooka    2042:        struct buf *bp;
                   2043:        size_t argsize;
1.14      pooka    2044:        size_t tomove, moved;
1.79      pooka    2045:        int error, dofaf;
1.8       pooka    2046:
1.35      pooka    2047:        pmp = MPTOPUFFSMP(vp->v_mount);
1.8       pooka    2048:        bp = ap->a_bp;
1.36      pooka    2049:        error = 0;
1.79      pooka    2050:        dofaf = 0;
1.38      pooka    2051:        pn = VPTOPP(vp);
1.107     pooka    2052:        park_rw = NULL; /* explicit */
1.38      pooka    2053:
1.79      pooka    2054:        if ((BIOREAD(bp) && !EXISTSOP(pmp, READ))
                   2055:            || (BIOWRITE(bp) && !EXISTSOP(pmp, WRITE)))
                   2056:                ERROUT(EOPNOTSUPP);
1.8       pooka    2057:
1.38      pooka    2058:        /*
                   2059:         * Short-circuit optimization: don't flush buffer in between
                   2060:         * VOP_INACTIVE and VOP_RECLAIM in case the node has no references.
                   2061:         */
1.72      pooka    2062:        if (pn->pn_stat & PNODE_DYING) {
1.79      pooka    2063:                KASSERT(BIOWRITE(bp));
1.38      pooka    2064:                bp->b_resid = 0;
                   2065:                goto out;
                   2066:        }
1.17      pooka    2067:
1.8       pooka    2068: #ifdef DIAGNOSTIC
1.107     pooka    2069:        if (bp->b_bcount > pmp->pmp_msg_maxsize - PUFFS_MSGSTRUCT_MAX)
1.46      pooka    2070:                panic("puffs_strategy: wildly inappropriate buf bcount %d",
                   2071:                    bp->b_bcount);
1.8       pooka    2072: #endif
                   2073:
1.35      pooka    2074:        /*
1.41      pooka    2075:         * See explanation for the necessity of a FAF in puffs_fsync.
                   2076:         *
                   2077:         * Also, do FAF in case we're suspending.
                   2078:         * See puffs_vfsops.c:pageflush()
1.35      pooka    2079:         */
1.79      pooka    2080:        if (BIOWRITE(bp)) {
1.35      pooka    2081:                simple_lock(&vp->v_interlock);
1.105     ad       2082:                if (vp->v_iflag & VI_XLOCK)
1.79      pooka    2083:                        dofaf = 1;
1.41      pooka    2084:                if (pn->pn_stat & PNODE_SUSPEND)
1.79      pooka    2085:                        dofaf = 1;
1.35      pooka    2086:                simple_unlock(&vp->v_interlock);
                   2087:        }
                   2088:
1.79      pooka    2089:        if (BIOASYNC(bp))
                   2090:                dofaf = 1;
1.45      pooka    2091:
                   2092: #ifdef DIAGNOSTIC
1.88      ad       2093:        if (curlwp == uvm.pagedaemon_lwp)
1.79      pooka    2094:                KASSERT(dofaf);
1.45      pooka    2095: #endif
                   2096:
1.79      pooka    2097:        /* allocate transport structure */
1.53      pooka    2098:        tomove = PUFFS_TOMOVE(bp->b_bcount, pmp);
1.107     pooka    2099:        argsize = sizeof(struct puffs_vnmsg_rw);
                   2100:        error = puffs_msgmem_alloc(argsize + tomove, &park_rw,
                   2101:            (void **)&rw_msg, dofaf ? 0 : 1);
                   2102:        if (error)
                   2103:                goto out;
                   2104:        RWARGS(rw_msg, 0, tomove, bp->b_blkno << DEV_BSHIFT, FSCRED);
1.79      pooka    2105:
                   2106:        /* 2x2 cases: read/write, faf/nofaf */
                   2107:        if (BIOREAD(bp)) {
                   2108:                if (dofaf) {
1.107     pooka    2109:                        puffs_msg_vncall(pmp, park_rw, PUFFS_VN_READ, 0,
                   2110:                            puffs_parkdone_asyncbioread, bp, vp);
1.79      pooka    2111:                } else {
1.107     pooka    2112:                        error = puffs_msg_vn(pmp, park_rw, PUFFS_VN_READ,
1.110     pooka    2113:                            tomove, vp, NULL);
1.102     pooka    2114:                        error = checkerr(pmp, error, __func__);
1.79      pooka    2115:                        if (error)
                   2116:                                goto out;
1.53      pooka    2117:
1.107     pooka    2118:                        if (rw_msg->pvnr_resid > tomove) {
                   2119:                                puffs_msg_errnotify(pmp, PUFFS_ERR_READ,
1.102     pooka    2120:                                    E2BIG, "resid grew", VPTOPNC(vp));
1.100     pooka    2121:                                ERROUT(EPROTO);
                   2122:                        }
1.14      pooka    2123:
1.107     pooka    2124:                        moved = tomove - rw_msg->pvnr_resid;
1.8       pooka    2125:
1.107     pooka    2126:                        (void)memcpy(bp->b_data, rw_msg->pvnr_data, moved);
1.79      pooka    2127:                        bp->b_resid = bp->b_bcount - moved;
1.14      pooka    2128:                }
1.8       pooka    2129:        } else {
1.54      pooka    2130:                /*
                   2131:                 * make pages read-only before we write them if we want
                   2132:                 * write caching info
                   2133:                 */
                   2134:                if (PUFFS_WCACHEINFO(pmp)) {
                   2135:                        struct uvm_object *uobj = &vp->v_uobj;
                   2136:                        int npages = (bp->b_bcount + PAGE_SIZE-1) >> PAGE_SHIFT;
                   2137:                        struct vm_page *vmp;
                   2138:                        int i;
                   2139:
                   2140:                        for (i = 0; i < npages; i++) {
                   2141:                                vmp= uvm_pageratop((vaddr_t)bp->b_data
                   2142:                                    + (i << PAGE_SHIFT));
                   2143:                                DPRINTF(("puffs_strategy: write-protecting "
                   2144:                                    "vp %p page %p, offset %" PRId64"\n",
                   2145:                                    vp, vmp, vmp->offset));
                   2146:                                simple_lock(&uobj->vmobjlock);
                   2147:                                vmp->flags |= PG_RDONLY;
                   2148:                                pmap_page_protect(vmp, VM_PROT_READ);
                   2149:                                simple_unlock(&uobj->vmobjlock);
                   2150:                        }
                   2151:                }
                   2152:
1.107     pooka    2153:                (void)memcpy(&rw_msg->pvnr_data, bp->b_data, tomove);
                   2154:                if (dofaf)
                   2155:                        puffs_msg_setfaf(park_rw);
                   2156:                error = puffs_msg_vn(pmp, park_rw, PUFFS_VN_WRITE, 0, vp, NULL);
                   2157:
1.112   ! pooka    2158:                /*
        !          2159:                 * XXXXXXXX: wrong, but kernel can't survive strategy
        !          2160:                 * failure currently.  Here, have one more X: X.
        !          2161:                 */
        !          2162:                if (error != ENOMEM)
        !          2163:                        error = 0;
        !          2164:
        !          2165:                error = checkerr(pmp, error, __func__);
        !          2166:                if (error)
        !          2167:                        goto out;
        !          2168:
        !          2169:                if (rw_msg->pvnr_resid > tomove) {
        !          2170:                        puffs_msg_errnotify(pmp, PUFFS_ERR_WRITE,
        !          2171:                            E2BIG, "resid grew", VPTOPNC(vp));
        !          2172:                        ERROUT(EPROTO);
        !          2173:                }
1.8       pooka    2174:
1.112   ! pooka    2175:                /*
        !          2176:                 * FAF moved everything.  Frankly, we don't
        !          2177:                 * really have a choice.
        !          2178:                 */
        !          2179:                if (dofaf && error == 0)
        !          2180:                        moved = tomove;
        !          2181:                else
1.107     pooka    2182:                        moved = tomove - rw_msg->pvnr_resid;
1.9       pooka    2183:
1.112   ! pooka    2184:                bp->b_resid = bp->b_bcount - moved;
        !          2185:                if (bp->b_resid != 0) {
        !          2186:                        ERROUT(EIO);
1.14      pooka    2187:                }
1.8       pooka    2188:        }
                   2189:
                   2190:  out:
1.107     pooka    2191:        if (park_rw)
                   2192:                puffs_msgmem_release(park_rw);
1.14      pooka    2193:
1.94      ad       2194:        if (error)
1.40      pooka    2195:                bp->b_error = error;
                   2196:
1.79      pooka    2197:        if (error || !(BIOREAD(bp) && BIOASYNC(bp)))
1.53      pooka    2198:                biodone(bp);
1.79      pooka    2199:
1.8       pooka    2200:        return error;
                   2201: }
1.1       pooka    2202:
1.21      pooka    2203: int
                   2204: puffs_mmap(void *v)
                   2205: {
                   2206:        struct vop_mmap_args /* {
                   2207:                const struct vnodeop_desc *a_desc;
                   2208:                struct vnode *a_vp;
1.92      pooka    2209:                vm_prot_t a_prot;
1.21      pooka    2210:                kauth_cred_t a_cred;
                   2211:                struct lwp *a_l;
                   2212:        } */ *ap = v;
1.107     pooka    2213:        PUFFS_MSG_VARS(vn, mmap);
                   2214:        struct vnode *vp = ap->a_vp;
                   2215:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.21      pooka    2216:        int error;
                   2217:
1.78      pooka    2218:        if (!PUFFS_USE_PAGECACHE(pmp))
1.21      pooka    2219:                return genfs_eopnotsupp(v);
                   2220:
                   2221:        if (EXISTSOP(pmp, MMAP)) {
1.107     pooka    2222:                PUFFS_MSG_ALLOC(vn, mmap);
                   2223:                mmap_msg->pvnr_prot = ap->a_prot;
                   2224:                puffs_credcvt(&mmap_msg->pvnr_cred, ap->a_cred);
                   2225:                puffs_cidcvt(&mmap_msg->pvnr_cid, ap->a_l);
                   2226:
                   2227:                error = puffs_msg_vn(pmp, park_mmap, PUFFS_VN_MMAP,
                   2228:                    0, vp, NULL);
1.102     pooka    2229:                error = checkerr(pmp, error, __func__);
1.107     pooka    2230:                PUFFS_MSG_RELEASE(mmap);
1.21      pooka    2231:        } else {
                   2232:                error = genfs_mmap(v);
                   2233:        }
                   2234:
                   2235:        return error;
                   2236: }
                   2237:
                   2238:
1.1       pooka    2239: /*
                   2240:  * The rest don't get a free trip to userspace and back, they
                   2241:  * have to stay within the kernel.
                   2242:  */
                   2243:
                   2244: /*
1.8       pooka    2245:  * bmap doesn't really make any sense for puffs, so just 1:1 map it.
                   2246:  * well, maybe somehow, somewhere, some day ....
                   2247:  */
                   2248: int
                   2249: puffs_bmap(void *v)
                   2250: {
                   2251:        struct vop_bmap_args /* {
                   2252:                const struct vnodeop_desc *a_desc;
                   2253:                struct vnode *a_vp;
                   2254:                daddr_t a_bn;
                   2255:                struct vnode **a_vpp;
                   2256:                daddr_t *a_bnp;
                   2257:                int *a_runp;
                   2258:        } */ *ap = v;
                   2259:        struct puffs_mount *pmp;
                   2260:
                   2261:        pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
                   2262:
                   2263:        if (ap->a_vpp)
                   2264:                *ap->a_vpp = ap->a_vp;
                   2265:        if (ap->a_bnp)
                   2266:                *ap->a_bnp = ap->a_bn;
                   2267:        if (ap->a_runp)
1.55      pooka    2268:                *ap->a_runp
1.107     pooka    2269:                    = (PUFFS_TOMOVE(pmp->pmp_msg_maxsize, pmp)>>DEV_BSHIFT) - 1;
1.8       pooka    2270:
                   2271:        return 0;
                   2272: }
                   2273:
1.54      pooka    2274: /*
                   2275:  * Handle getpages faults in puffs.  We let genfs_getpages() do most
                   2276:  * of the dirty work, but we come in this route to do accounting tasks.
                   2277:  * If the user server has specified functions for cache notifications
                   2278:  * about reads and/or writes, we record which type of operation we got,
                   2279:  * for which page range, and proceed to issue a FAF notification to the
                   2280:  * server about it.
                   2281:  */
                   2282: int
                   2283: puffs_getpages(void *v)
                   2284: {
                   2285:        struct vop_getpages_args /* {
                   2286:                const struct vnodeop_desc *a_desc;
                   2287:                struct vnode *a_vp;
                   2288:                voff_t a_offset;
                   2289:                struct vm_page **a_m;
                   2290:                int *a_count;
                   2291:                int a_centeridx;
                   2292:                vm_prot_t a_access_type;
                   2293:                int a_advice;
                   2294:                int a_flags;
                   2295:        } */ *ap = v;
                   2296:        struct puffs_mount *pmp;
1.90      pooka    2297:        struct puffs_node *pn;
1.54      pooka    2298:        struct vnode *vp;
                   2299:        struct vm_page **pgs;
                   2300:        struct puffs_cacheinfo *pcinfo = NULL;
                   2301:        struct puffs_cacherun *pcrun;
1.55      pooka    2302:        void *parkmem = NULL;
1.54      pooka    2303:        size_t runsizes;
                   2304:        int i, npages, si, streakon;
                   2305:        int error, locked, write;
                   2306:
                   2307:        pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
                   2308:        npages = *ap->a_count;
                   2309:        pgs = ap->a_m;
                   2310:        vp = ap->a_vp;
1.90      pooka    2311:        pn = vp->v_data;
1.54      pooka    2312:        locked = (ap->a_flags & PGO_LOCKED) != 0;
                   2313:        write = (ap->a_access_type & VM_PROT_WRITE) != 0;
                   2314:
                   2315:        /* ccg xnaht - gets Wuninitialized wrong */
                   2316:        pcrun = NULL;
                   2317:        runsizes = 0;
                   2318:
1.90      pooka    2319:        /*
                   2320:         * Check that we aren't trying to fault in pages which our file
                   2321:         * server doesn't know about.  This happens if we extend a file by
                   2322:         * skipping some pages and later try to fault in pages which
                   2323:         * are between pn_serversize and vp_size.  This check optimizes
                   2324:         * away the common case where a file is being extended.
                   2325:         */
                   2326:        if (ap->a_offset >= pn->pn_serversize && ap->a_offset < vp->v_size) {
                   2327:                struct vattr va;
                   2328:
                   2329:                /* try again later when we can block */
                   2330:                if (locked)
                   2331:                        ERROUT(EBUSY);
                   2332:
                   2333:                simple_unlock(&vp->v_interlock);
                   2334:                vattr_null(&va);
                   2335:                va.va_size = vp->v_size;
1.91      pooka    2336:                error = puffs_dosetattr(vp, &va, FSCRED, NULL, 0);
1.90      pooka    2337:                if (error)
                   2338:                        ERROUT(error);
                   2339:                simple_lock(&vp->v_interlock);
                   2340:        }
                   2341:
1.54      pooka    2342:        if (write && PUFFS_WCACHEINFO(pmp)) {
1.107     pooka    2343: #ifdef notnowjohn
1.54      pooka    2344:                /* allocate worst-case memory */
                   2345:                runsizes = ((npages / 2) + 1) * sizeof(struct puffs_cacherun);
                   2346:                pcinfo = malloc(sizeof(struct puffs_cacheinfo) + runsizes,
                   2347:                    M_PUFFS, M_ZERO | locked ? M_NOWAIT : M_WAITOK);
                   2348:
                   2349:                /*
                   2350:                 * can't block if we're locked and can't mess up caching
                   2351:                 * information for fs server.  so come back later, please
                   2352:                 */
1.79      pooka    2353:                if (pcinfo == NULL)
                   2354:                        ERROUT(ENOMEM);
1.54      pooka    2355:
1.57      pooka    2356:                parkmem = puffs_park_alloc(locked == 0);
1.79      pooka    2357:                if (parkmem == NULL)
                   2358:                        ERROUT(ENOMEM);
1.54      pooka    2359:
                   2360:                pcrun = pcinfo->pcache_runs;
1.107     pooka    2361: #else
                   2362:                (void)parkmem;
                   2363: #endif
1.54      pooka    2364:        }
                   2365:
                   2366:        error = genfs_getpages(v);
                   2367:        if (error)
                   2368:                goto out;
                   2369:
                   2370:        if (PUFFS_WCACHEINFO(pmp) == 0)
                   2371:                goto out;
                   2372:
                   2373:        /*
                   2374:         * Let's see whose fault it was and inform the user server of
                   2375:         * possibly read/written pages.  Map pages from read faults
                   2376:         * strictly read-only, since otherwise we might miss info on
                   2377:         * when the page is actually write-faulted to.
                   2378:         */
                   2379:        if (!locked)
                   2380:                simple_lock(&vp->v_uobj.vmobjlock);
                   2381:        for (i = 0, si = 0, streakon = 0; i < npages; i++) {
                   2382:                if (pgs[i] == NULL || pgs[i] == PGO_DONTCARE) {
                   2383:                        if (streakon && write) {
                   2384:                                streakon = 0;
                   2385:                                pcrun[si].pcache_runend
                   2386:                                    = trunc_page(pgs[i]->offset) + PAGE_MASK;
                   2387:                                si++;
                   2388:                        }
                   2389:                        continue;
                   2390:                }
                   2391:                if (streakon == 0 && write) {
                   2392:                        streakon = 1;
                   2393:                        pcrun[si].pcache_runstart = pgs[i]->offset;
                   2394:                }
                   2395:
                   2396:                if (!write)
                   2397:                        pgs[i]->flags |= PG_RDONLY;
                   2398:        }
                   2399:        /* was the last page part of our streak? */
                   2400:        if (streakon) {
                   2401:                pcrun[si].pcache_runend
                   2402:                    = trunc_page(pgs[i-1]->offset) + PAGE_MASK;
                   2403:                si++;
                   2404:        }
                   2405:        if (!locked)
                   2406:                simple_unlock(&vp->v_uobj.vmobjlock);
                   2407:
                   2408:        KASSERT(si <= (npages / 2) + 1);
                   2409:
1.107     pooka    2410: #ifdef notnowjohn
1.54      pooka    2411:        /* send results to userspace */
                   2412:        if (write)
1.55      pooka    2413:                puffs_cacheop(pmp, parkmem, pcinfo,
1.54      pooka    2414:                    sizeof(struct puffs_cacheinfo) + runsizes, VPTOPNC(vp));
1.107     pooka    2415: #endif
1.54      pooka    2416:
                   2417:  out:
                   2418:        if (error) {
                   2419:                if (pcinfo != NULL)
                   2420:                        free(pcinfo, M_PUFFS);
1.107     pooka    2421: #ifdef notnowjohn
1.55      pooka    2422:                if (parkmem != NULL)
1.57      pooka    2423:                        puffs_park_release(parkmem, 1);
1.107     pooka    2424: #endif
1.54      pooka    2425:        }
                   2426:
                   2427:        return error;
                   2428: }
1.41      pooka    2429:
1.1       pooka    2430: int
                   2431: puffs_lock(void *v)
                   2432: {
                   2433:        struct vop_lock_args /* {
                   2434:                struct vnode *a_vp;
                   2435:                int a_flags;
                   2436:        } */ *ap = v;
                   2437:        struct vnode *vp = ap->a_vp;
1.41      pooka    2438:        struct mount *mp = vp->v_mount;
1.1       pooka    2439:
                   2440: #if 0
                   2441:        DPRINTF(("puffs_lock: lock %p, args 0x%x\n", vp, ap->a_flags));
                   2442: #endif
                   2443:
1.41      pooka    2444:        /*
                   2445:         * XXX: this avoids deadlocking when we're suspending.
                   2446:         * e.g. some ops holding the vnode lock might be blocked for
                   2447:         * the vfs transaction lock so we'd deadlock.
                   2448:         *
                   2449:         * Now once again this is skating on the thin ice of modern life,
                   2450:         * since we are breaking the consistency guarantee provided
                   2451:         * _to the user server_ by vnode locking.  Hopefully this will
                   2452:         * get fixed soon enough by getting rid of the dependency on
                   2453:         * vnode locks alltogether.
                   2454:         */
1.43      hannken  2455:        if (fstrans_is_owner(mp) && fstrans_getstate(mp) == FSTRANS_SUSPENDING){
1.41      pooka    2456:                if (ap->a_flags & LK_INTERLOCK)
                   2457:                        simple_unlock(&vp->v_interlock);
                   2458:                return 0;
                   2459:        }
                   2460:
1.1       pooka    2461:        return lockmgr(&vp->v_lock, ap->a_flags, &vp->v_interlock);
                   2462: }
                   2463:
                   2464: int
                   2465: puffs_unlock(void *v)
                   2466: {
                   2467:        struct vop_unlock_args /* {
                   2468:                struct vnode *a_vp;
                   2469:                int a_flags;
                   2470:        } */ *ap = v;
                   2471:        struct vnode *vp = ap->a_vp;
1.41      pooka    2472:        struct mount *mp = vp->v_mount;
1.1       pooka    2473:
                   2474: #if 0
                   2475:        DPRINTF(("puffs_unlock: lock %p, args 0x%x\n", vp, ap->a_flags));
                   2476: #endif
                   2477:
1.41      pooka    2478:        /* XXX: see puffs_lock() */
1.43      hannken  2479:        if (fstrans_is_owner(mp) && fstrans_getstate(mp) == FSTRANS_SUSPENDING){
1.41      pooka    2480:                if (ap->a_flags & LK_INTERLOCK)
                   2481:                        simple_unlock(&vp->v_interlock);
                   2482:                return 0;
                   2483:        }
                   2484:
1.1       pooka    2485:        return lockmgr(&vp->v_lock, ap->a_flags | LK_RELEASE, &vp->v_interlock);
                   2486: }
                   2487:
                   2488: int
                   2489: puffs_islocked(void *v)
                   2490: {
                   2491:        struct vop_islocked_args *ap = v;
                   2492:        int rv;
                   2493:
                   2494:        rv = lockstatus(&ap->a_vp->v_lock);
                   2495:        return rv;
                   2496: }
                   2497:
                   2498: int
                   2499: puffs_generic(void *v)
                   2500: {
                   2501:        struct vop_generic_args *ap = v;
                   2502:
                   2503:        (void)ap;
                   2504:        DPRINTF(("puffs_generic: ap->a_desc = %s\n", ap->a_desc->vdesc_name));
                   2505:
                   2506:        return EOPNOTSUPP;
                   2507: }
1.26      pooka    2508:
                   2509:
                   2510: /*
1.31      pooka    2511:  * spec & fifo.  These call the miscfs spec and fifo vectors, but issue
1.26      pooka    2512:  * FAF update information for the puffs node first.
                   2513:  */
                   2514: int
                   2515: puffs_spec_read(void *v)
                   2516: {
                   2517:        struct vop_read_args /* {
                   2518:                const struct vnodeop_desc *a_desc;
                   2519:                struct vnode *a_vp;
                   2520:                struct uio *a_uio;
                   2521:                int a_ioflag;
                   2522:                kauth_cred_t a_cred;
                   2523:        } */ *ap = v;
                   2524:
                   2525:        puffs_updatenode(ap->a_vp, PUFFS_UPDATEATIME);
                   2526:        return VOCALL(spec_vnodeop_p, VOFFSET(vop_read), v);
                   2527: }
                   2528:
                   2529: int
                   2530: puffs_spec_write(void *v)
                   2531: {
                   2532:        struct vop_write_args /* {
                   2533:                const struct vnodeop_desc *a_desc;
                   2534:                struct vnode *a_vp;
                   2535:                struct uio *a_uio;
                   2536:                int a_ioflag;
                   2537:                kauth_cred_t a_cred;
                   2538:        } */ *ap = v;
                   2539:
                   2540:        puffs_updatenode(ap->a_vp, PUFFS_UPDATEMTIME);
                   2541:        return VOCALL(spec_vnodeop_p, VOFFSET(vop_write), v);
                   2542: }
                   2543:
                   2544: int
                   2545: puffs_fifo_read(void *v)
                   2546: {
                   2547:        struct vop_read_args /* {
                   2548:                const struct vnodeop_desc *a_desc;
                   2549:                struct vnode *a_vp;
                   2550:                struct uio *a_uio;
                   2551:                int a_ioflag;
                   2552:                kauth_cred_t a_cred;
                   2553:        } */ *ap = v;
                   2554:
                   2555:        puffs_updatenode(ap->a_vp, PUFFS_UPDATEATIME);
                   2556:        return VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), v);
                   2557: }
                   2558:
                   2559: int
                   2560: puffs_fifo_write(void *v)
                   2561: {
                   2562:        struct vop_write_args /* {
                   2563:                const struct vnodeop_desc *a_desc;
                   2564:                struct vnode *a_vp;
                   2565:                struct uio *a_uio;
                   2566:                int a_ioflag;
                   2567:                kauth_cred_t a_cred;
                   2568:        } */ *ap = v;
                   2569:
                   2570:        puffs_updatenode(ap->a_vp, PUFFS_UPDATEMTIME);
                   2571:        return VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), v);
                   2572: }

CVSweb <webmaster@jp.NetBSD.org>