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

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

CVSweb <webmaster@jp.NetBSD.org>