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

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

CVSweb <webmaster@jp.NetBSD.org>