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

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

CVSweb <webmaster@jp.NetBSD.org>