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

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

CVSweb <webmaster@jp.NetBSD.org>