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

1.212   ! manu        1: /*     $NetBSD: puffs_vnops.c,v 1.211 2017/05/26 14:21:01 riastradh 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.212   ! manu       33: __KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.211 2017/05/26 14:21:01 riastradh 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) {
1.198     manu      911:                /*
                    912:                 * Flush cache:
                    913:                 * - we do not want to discard cached write by direct write
                    914:                 * - read cache is now useless and should be freed
                    915:                 */
1.212   ! manu      916:                mutex_enter(&pn->pn_sizemtx);
1.198     manu      917:                flushvncache(vp, 0, 0, true);
1.212   ! manu      918:                mutex_exit(&pn->pn_sizemtx);
        !           919:
1.183     manu      920:                if (mode & FREAD)
                    921:                        pn->pn_stat |= PNODE_RDIRECT;
                    922:                if (mode & FWRITE)
                    923:                        pn->pn_stat |= PNODE_WDIRECT;
                    924:        }
1.50      pooka     925:  out:
1.79      pooka     926:        DPRINTF(("puffs_open: returning %d\n", error));
1.107     pooka     927:        PUFFS_MSG_RELEASE(open);
1.79      pooka     928:        return error;
1.1       pooka     929: }
                    930:
                    931: int
1.123     pooka     932: puffs_vnop_close(void *v)
1.1       pooka     933: {
                    934:        struct vop_close_args /* {
                    935:                const struct vnodeop_desc *a_desc;
                    936:                struct vnode *a_vp;
                    937:                int a_fflag;
                    938:                kauth_cred_t a_cred;
                    939:        } */ *ap = v;
1.107     pooka     940:        PUFFS_MSG_VARS(vn, close);
                    941:        struct vnode *vp = ap->a_vp;
                    942:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.1       pooka     943:
1.107     pooka     944:        PUFFS_MSG_ALLOC(vn, close);
                    945:        puffs_msg_setfaf(park_close);
                    946:        close_msg->pvnr_fflag = ap->a_fflag;
                    947:        puffs_credcvt(&close_msg->pvnr_cred, ap->a_cred);
1.114     pooka     948:        puffs_msg_setinfo(park_close, PUFFSOP_VN,
                    949:            PUFFS_VN_CLOSE, VPTOPNC(vp));
1.1       pooka     950:
1.114     pooka     951:        puffs_msg_enqueue(pmp, park_close);
1.107     pooka     952:        PUFFS_MSG_RELEASE(close);
1.63      pooka     953:        return 0;
1.1       pooka     954: }
                    955:
                    956: int
1.123     pooka     957: puffs_vnop_access(void *v)
1.1       pooka     958: {
                    959:        struct vop_access_args /* {
                    960:                const struct vnodeop_desc *a_desc;
                    961:                struct vnode *a_vp;
                    962:                int a_mode;
                    963:                kauth_cred_t a_cred;
                    964:        } */ *ap = v;
1.107     pooka     965:        PUFFS_MSG_VARS(vn, access);
1.47      pooka     966:        struct vnode *vp = ap->a_vp;
                    967:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
                    968:        int mode = ap->a_mode;
1.102     pooka     969:        int error;
1.1       pooka     970:
1.96      pooka     971:        if (mode & VWRITE) {
                    972:                switch (vp->v_type) {
                    973:                case VDIR:
                    974:                case VLNK:
                    975:                case VREG:
                    976:                        if ((vp->v_mount->mnt_flag & MNT_RDONLY)
                    977:                            || !EXISTSOP(pmp, WRITE))
                    978:                                return EROFS;
                    979:                        break;
                    980:                default:
                    981:                        break;
                    982:                }
                    983:        }
1.47      pooka     984:
                    985:        if (!EXISTSOP(pmp, ACCESS))
                    986:                return 0;
                    987:
1.107     pooka     988:        PUFFS_MSG_ALLOC(vn, access);
                    989:        access_msg->pvnr_mode = ap->a_mode;
                    990:        puffs_credcvt(&access_msg->pvnr_cred, ap->a_cred);
1.114     pooka     991:        puffs_msg_setinfo(park_access, PUFFSOP_VN,
                    992:            PUFFS_VN_ACCESS, VPTOPNC(vp));
1.107     pooka     993:
1.114     pooka     994:        PUFFS_MSG_ENQUEUEWAIT2(pmp, park_access, vp->v_data, NULL, error);
1.107     pooka     995:        error = checkerr(pmp, error, __func__);
                    996:        PUFFS_MSG_RELEASE(access);
1.1       pooka     997:
1.107     pooka     998:        return error;
1.1       pooka     999: }
                   1000:
1.165     manu     1001: static void
                   1002: update_va(struct vnode *vp, struct vattr *vap, struct vattr *rvap,
1.166     manu     1003:          struct timespec *va_ttl, struct timespec *cn_ttl, int flags)
1.165     manu     1004: {
                   1005:        struct puffs_node *pn = VPTOPP(vp);
1.200     manu     1006:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
                   1007:        int use_metacache;
1.165     manu     1008:
1.167     manu     1009:        if (TTL_VALID(cn_ttl)) {
1.165     manu     1010:                pn->pn_cn_timeout = TTL_TO_TIMEOUT(cn_ttl);
1.167     manu     1011:                pn->pn_cn_grace = MAX(pn->pn_cn_timeout, pn->pn_cn_grace);
                   1012:        }
1.165     manu     1013:
                   1014:        /*
                   1015:         * Don't listen to the file server regarding special device
                   1016:         * size info, the file server doesn't know anything about them.
                   1017:         */
                   1018:        if (vp->v_type == VBLK || vp->v_type == VCHR)
                   1019:                rvap->va_size = vp->v_size;
                   1020:
                   1021:        /* Ditto for blocksize (ufs comment: this doesn't belong here) */
                   1022:        if (vp->v_type == VBLK)
                   1023:                rvap->va_blocksize = BLKDEV_IOSIZE;
                   1024:        else if (vp->v_type == VCHR)
                   1025:                rvap->va_blocksize = MAXBSIZE;
                   1026:
                   1027:        if (vap != NULL) {
                   1028:                (void) memcpy(vap, rvap, sizeof(struct vattr));
                   1029:                vap->va_fsid = vp->v_mount->mnt_stat.f_fsidx.__fsid_val[0];
                   1030:
1.200     manu     1031:                if (PUFFS_USE_METAFLUSH(pmp)) {
                   1032:                        if (pn->pn_stat & PNODE_METACACHE_ATIME)
                   1033:                                vap->va_atime = pn->pn_mc_atime;
                   1034:                        if (pn->pn_stat & PNODE_METACACHE_CTIME)
                   1035:                                vap->va_ctime = pn->pn_mc_ctime;
                   1036:                        if (pn->pn_stat & PNODE_METACACHE_MTIME)
                   1037:                                vap->va_mtime = pn->pn_mc_mtime;
                   1038:                        if (pn->pn_stat & PNODE_METACACHE_SIZE)
                   1039:                                vap->va_size = pn->pn_mc_size;
                   1040:                }
1.165     manu     1041:        }
                   1042:
1.200     manu     1043:        use_metacache = PUFFS_USE_METAFLUSH(pmp) &&
                   1044:                        (pn->pn_stat & PNODE_METACACHE_SIZE);
                   1045:        if (!use_metacache && (flags & SETATTR_CHSIZE)) {
1.165     manu     1046:                if (rvap->va_size != VNOVAL
                   1047:                    && vp->v_type != VBLK && vp->v_type != VCHR) {
                   1048:                        uvm_vnp_setsize(vp, rvap->va_size);
                   1049:                        pn->pn_serversize = rvap->va_size;
                   1050:                }
                   1051:        }
                   1052:
1.166     manu     1053:        if ((va_ttl != NULL) && TTL_VALID(va_ttl)) {
1.165     manu     1054:                if (pn->pn_va_cache == NULL)
                   1055:                        pn->pn_va_cache = pool_get(&puffs_vapool, PR_WAITOK);
                   1056:
                   1057:                (void)memcpy(pn->pn_va_cache, rvap, sizeof(*rvap));
                   1058:
                   1059:                pn->pn_va_timeout = TTL_TO_TIMEOUT(va_ttl);
                   1060:        }
                   1061: }
                   1062:
1.174     manu     1063: static void
                   1064: update_parent(struct vnode *vp, struct vnode *dvp)
                   1065: {
                   1066:        struct puffs_node *pn = VPTOPP(vp);
                   1067:
                   1068:        if (pn->pn_parent != NULL) {
                   1069:                KASSERT(pn->pn_parent != dvp);
                   1070:                vrele(pn->pn_parent);
                   1071:        }
                   1072:
                   1073:        vref(dvp);
                   1074:        pn->pn_parent = dvp;
                   1075: }
                   1076:
1.1       pooka    1077: int
1.123     pooka    1078: puffs_vnop_getattr(void *v)
1.1       pooka    1079: {
                   1080:        struct vop_getattr_args /* {
                   1081:                const struct vnodeop_desc *a_desc;
                   1082:                struct vnode *a_vp;
                   1083:                struct vattr *a_vap;
                   1084:                kauth_cred_t a_cred;
                   1085:        } */ *ap = v;
1.107     pooka    1086:        PUFFS_MSG_VARS(vn, getattr);
                   1087:        struct vnode *vp = ap->a_vp;
                   1088:        struct mount *mp = vp->v_mount;
                   1089:        struct puffs_mount *pmp = MPTOPUFFSMP(mp);
1.67      pooka    1090:        struct vattr *vap, *rvap;
1.142     pooka    1091:        struct puffs_node *pn = VPTOPP(vp);
1.165     manu     1092:        struct timespec *va_ttl = NULL;
1.107     pooka    1093:        int error = 0;
1.1       pooka    1094:
1.155     manu     1095:        /*
                   1096:         * A lock is required so that we do not race with
                   1097:         * setattr, write and fsync when changing vp->v_size.
                   1098:         * This is critical, since setting a stall smaler value
                   1099:         * triggers a file truncate in uvm_vnp_setsize(), which
                   1100:         * most of the time means data corruption (a chunk of
                   1101:         * data is replaced by zeroes). This can be removed if
                   1102:         * we decide one day that VOP_GETATTR must operate on
                   1103:         * a locked vnode.
1.161     hannken  1104:         *
                   1105:         * XXX Should be useless now that VOP_GETATTR has been
                   1106:         *     fixed to always require a shared lock at least.
1.155     manu     1107:         */
                   1108:        mutex_enter(&pn->pn_sizemtx);
                   1109:
1.142     pooka    1110:        REFPN(pn);
1.54      pooka    1111:        vap = ap->a_vap;
1.13      pooka    1112:
1.165     manu     1113:        if (PUFFS_USE_FS_TTL(pmp)) {
1.166     manu     1114:                if (!TIMED_OUT(pn->pn_va_timeout)) {
                   1115:                        update_va(vp, vap, pn->pn_va_cache,
                   1116:                                  NULL, NULL, SETATTR_CHSIZE);
1.165     manu     1117:                        goto out2;
                   1118:                }
                   1119:        }
                   1120:
1.107     pooka    1121:        PUFFS_MSG_ALLOC(vn, getattr);
                   1122:        vattr_null(&getattr_msg->pvnr_va);
                   1123:        puffs_credcvt(&getattr_msg->pvnr_cred, ap->a_cred);
1.114     pooka    1124:        puffs_msg_setinfo(park_getattr, PUFFSOP_VN,
                   1125:            PUFFS_VN_GETATTR, VPTOPNC(vp));
1.1       pooka    1126:
1.114     pooka    1127:        PUFFS_MSG_ENQUEUEWAIT2(pmp, park_getattr, vp->v_data, NULL, error);
1.102     pooka    1128:        error = checkerr(pmp, error, __func__);
1.1       pooka    1129:        if (error)
1.107     pooka    1130:                goto out;
1.1       pooka    1131:
1.107     pooka    1132:        rvap = &getattr_msg->pvnr_va;
1.67      pooka    1133:
1.165     manu     1134:        if (PUFFS_USE_FS_TTL(pmp))
                   1135:                va_ttl = &getattr_msg->pvnr_va_ttl;
1.67      pooka    1136:
1.166     manu     1137:        update_va(vp, vap, rvap, va_ttl, NULL, SETATTR_CHSIZE);
1.1       pooka    1138:
1.165     manu     1139:  out:
                   1140:        PUFFS_MSG_RELEASE(getattr);
1.13      pooka    1141:
1.165     manu     1142:  out2:
1.142     pooka    1143:        puffs_releasenode(pn);
1.155     manu     1144:
                   1145:        mutex_exit(&pn->pn_sizemtx);
                   1146:
1.107     pooka    1147:        return error;
1.1       pooka    1148: }
                   1149:
1.188     manu     1150: static void
                   1151: zerofill_lastpage(struct vnode *vp, voff_t off)
                   1152: {
                   1153:
                   1154:        if (trunc_page(off) == off)
                   1155:                return;
1.190     manu     1156:
                   1157:        if (vp->v_writecount == 0)
                   1158:                return;
1.188     manu     1159:
1.207     christos 1160:        vsize_t len = round_page(off) - off;
                   1161:        ubc_zerorange(&vp->v_uobj, off, len, UBC_WRITE|UBC_UNMAP_FLAG(vp));
1.188     manu     1162: }
                   1163:
1.90      pooka    1164: static int
1.141     pooka    1165: dosetattr(struct vnode *vp, struct vattr *vap, kauth_cred_t cred, int flags)
1.1       pooka    1166: {
1.107     pooka    1167:        PUFFS_MSG_VARS(vn, setattr);
                   1168:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.90      pooka    1169:        struct puffs_node *pn = vp->v_data;
1.190     manu     1170:        vsize_t oldsize = vp->v_size;
1.141     pooka    1171:        int error = 0;
1.1       pooka    1172:
1.155     manu     1173:        KASSERT(!(flags & SETATTR_CHSIZE) || mutex_owned(&pn->pn_sizemtx));
                   1174:
1.96      pooka    1175:        if ((vp->v_mount->mnt_flag & MNT_RDONLY) &&
                   1176:            (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL
                   1177:            || vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL
                   1178:            || vap->va_mode != (mode_t)VNOVAL))
                   1179:                return EROFS;
                   1180:
                   1181:        if ((vp->v_mount->mnt_flag & MNT_RDONLY)
                   1182:            && vp->v_type == VREG && vap->va_size != VNOVAL)
                   1183:                return EROFS;
                   1184:
1.65      pooka    1185:        /*
                   1186:         * Flush metacache first.  If we are called with some explicit
                   1187:         * parameters, treat them as information overriding metacache
                   1188:         * information.
                   1189:         */
1.200     manu     1190:        if (PUFFS_USE_METAFLUSH(pmp) && pn->pn_stat & PNODE_METACACHE_MASK) {
1.65      pooka    1191:                if ((pn->pn_stat & PNODE_METACACHE_ATIME)
                   1192:                    && vap->va_atime.tv_sec == VNOVAL)
                   1193:                        vap->va_atime = pn->pn_mc_atime;
                   1194:                if ((pn->pn_stat & PNODE_METACACHE_CTIME)
                   1195:                    && vap->va_ctime.tv_sec == VNOVAL)
                   1196:                        vap->va_ctime = pn->pn_mc_ctime;
                   1197:                if ((pn->pn_stat & PNODE_METACACHE_MTIME)
                   1198:                    && vap->va_mtime.tv_sec == VNOVAL)
                   1199:                        vap->va_mtime = pn->pn_mc_mtime;
                   1200:                if ((pn->pn_stat & PNODE_METACACHE_SIZE)
                   1201:                    && vap->va_size == VNOVAL)
                   1202:                        vap->va_size = pn->pn_mc_size;
                   1203:
                   1204:                pn->pn_stat &= ~PNODE_METACACHE_MASK;
                   1205:        }
                   1206:
1.165     manu     1207:        /*
                   1208:         * Flush attribute cache so that another thread do
                   1209:         * not get a stale value during the operation.
                   1210:         */
                   1211:        if (PUFFS_USE_FS_TTL(pmp))
                   1212:                pn->pn_va_timeout = 0;
                   1213:
1.107     pooka    1214:        PUFFS_MSG_ALLOC(vn, setattr);
                   1215:        (void)memcpy(&setattr_msg->pvnr_va, vap, sizeof(struct vattr));
                   1216:        puffs_credcvt(&setattr_msg->pvnr_cred, cred);
1.114     pooka    1217:        puffs_msg_setinfo(park_setattr, PUFFSOP_VN,
                   1218:            PUFFS_VN_SETATTR, VPTOPNC(vp));
1.141     pooka    1219:        if (flags & SETATTR_ASYNC)
                   1220:                puffs_msg_setfaf(park_setattr);
1.107     pooka    1221:
1.141     pooka    1222:        puffs_msg_enqueue(pmp, park_setattr);
1.200     manu     1223:        if ((flags & SETATTR_ASYNC) == 0) {
1.141     pooka    1224:                error = puffs_msg_wait2(pmp, park_setattr, vp->v_data, NULL);
1.165     manu     1225:
1.200     manu     1226:                if ((error == 0) && PUFFS_USE_FS_TTL(pmp)) {
                   1227:                        struct timespec *va_ttl = &setattr_msg->pvnr_va_ttl;
                   1228:                        struct vattr *rvap = &setattr_msg->pvnr_va;
1.165     manu     1229:
1.200     manu     1230:                        update_va(vp, NULL, rvap, va_ttl, NULL, flags);
                   1231:                }
1.165     manu     1232:        }
                   1233:
1.107     pooka    1234:        PUFFS_MSG_RELEASE(setattr);
1.141     pooka    1235:        if ((flags & SETATTR_ASYNC) == 0) {
                   1236:                error = checkerr(pmp, error, __func__);
                   1237:                if (error)
                   1238:                        return error;
                   1239:        } else {
                   1240:                error = 0;
                   1241:        }
1.8       pooka    1242:
1.90      pooka    1243:        if (vap->va_size != VNOVAL) {
1.190     manu     1244:                /*
                   1245:                 * If we truncated the file, make sure the data beyond
                   1246:                 * EOF in last page does not remain in cache, otherwise
                   1247:                 * if the file is later truncated to a larger size (creating
                   1248:                 * a hole), that area will not return zeroes as it
                   1249:                 * should.
                   1250:                 */
                   1251:                if ((flags & SETATTR_CHSIZE) && PUFFS_USE_PAGECACHE(pmp) &&
                   1252:                    (vap->va_size < oldsize))
                   1253:                        zerofill_lastpage(vp, vap->va_size);
                   1254:
1.90      pooka    1255:                pn->pn_serversize = vap->va_size;
1.141     pooka    1256:                if (flags & SETATTR_CHSIZE)
1.90      pooka    1257:                        uvm_vnp_setsize(vp, vap->va_size);
1.208     hannken  1258:                puffs_updatenode(pn, PUFFS_UPDATECTIME | PUFFS_UPDATEMTIME, 0);
1.90      pooka    1259:        }
1.8       pooka    1260:
                   1261:        return 0;
1.1       pooka    1262: }
                   1263:
                   1264: int
1.123     pooka    1265: puffs_vnop_setattr(void *v)
1.90      pooka    1266: {
                   1267:        struct vop_getattr_args /* {
                   1268:                const struct vnodeop_desc *a_desc;
                   1269:                struct vnode *a_vp;
                   1270:                struct vattr *a_vap;
                   1271:                kauth_cred_t a_cred;
                   1272:        } */ *ap = v;
1.155     manu     1273:        struct puffs_node *pn = ap->a_vp->v_data;
                   1274:        int error;
1.90      pooka    1275:
1.155     manu     1276:        mutex_enter(&pn->pn_sizemtx);
                   1277:        error = dosetattr(ap->a_vp, ap->a_vap, ap->a_cred, SETATTR_CHSIZE);
                   1278:        mutex_exit(&pn->pn_sizemtx);
                   1279:
                   1280:        return error;
1.90      pooka    1281: }
                   1282:
1.107     pooka    1283: static __inline int
                   1284: doinact(struct puffs_mount *pmp, int iaflag)
1.3       pooka    1285: {
                   1286:
1.17      pooka    1287:        if (EXISTSOP(pmp, INACTIVE))
1.66      pooka    1288:                if (pmp->pmp_flags & PUFFS_KFLAG_IAONDEMAND)
1.103     pooka    1289:                        if (iaflag || ALLOPS(pmp))
1.107     pooka    1290:                                return 1;
1.66      pooka    1291:                        else
1.107     pooka    1292:                                return 0;
1.66      pooka    1293:                else
1.107     pooka    1294:                        return 1;
1.66      pooka    1295:        else
1.107     pooka    1296:                return 0;
                   1297: }
                   1298:
                   1299: static void
1.127     pooka    1300: callinactive(struct puffs_mount *pmp, puffs_cookie_t ck, int iaflag)
1.107     pooka    1301: {
                   1302:        PUFFS_MSG_VARS(vn, inactive);
                   1303:
                   1304:        if (doinact(pmp, iaflag)) {
                   1305:                PUFFS_MSG_ALLOC(vn, inactive);
1.114     pooka    1306:                puffs_msg_setinfo(park_inactive, PUFFSOP_VN,
1.127     pooka    1307:                    PUFFS_VN_INACTIVE, ck);
1.177     christos 1308:                PUFFS_MSG_ENQUEUEWAIT_NOERROR(pmp, park_inactive);
1.107     pooka    1309:                PUFFS_MSG_RELEASE(inactive);
                   1310:        }
1.103     pooka    1311: }
                   1312:
1.107     pooka    1313: /* XXX: callinactive can't setback */
1.103     pooka    1314: int
1.123     pooka    1315: puffs_vnop_inactive(void *v)
1.103     pooka    1316: {
1.209     riastrad 1317:        struct vop_inactive_v2_args /* {
1.103     pooka    1318:                const struct vnodeop_desc *a_desc;
                   1319:                struct vnode *a_vp;
                   1320:        } */ *ap = v;
1.107     pooka    1321:        PUFFS_MSG_VARS(vn, inactive);
1.103     pooka    1322:        struct vnode *vp = ap->a_vp;
1.107     pooka    1323:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.103     pooka    1324:        struct puffs_node *pnode;
1.167     manu     1325:        bool recycle = false;
1.103     pooka    1326:
1.197     manu     1327:        /*
                   1328:         * When puffs_cookie2vnode() misses an entry, vcache_get()
                   1329:         * creates a new node (puffs_vfsop_loadvnode being called to
                   1330:         * initialize the PUFFS part), then it discovers it is VNON,
                   1331:         * and tries to vrele() it. This leads us there, while the
                   1332:         * cookie was stall and the node likely already reclaimed.
                   1333:         */
                   1334:        if (vp->v_type == VNON) {
                   1335:                return 0;
                   1336:        }
                   1337:
1.103     pooka    1338:        pnode = vp->v_data;
1.155     manu     1339:        mutex_enter(&pnode->pn_sizemtx);
1.103     pooka    1340:
1.107     pooka    1341:        if (doinact(pmp, pnode->pn_stat & PNODE_DOINACT)) {
1.141     pooka    1342:                flushvncache(vp, 0, 0, false);
1.107     pooka    1343:                PUFFS_MSG_ALLOC(vn, inactive);
1.114     pooka    1344:                puffs_msg_setinfo(park_inactive, PUFFSOP_VN,
                   1345:                    PUFFS_VN_INACTIVE, VPTOPNC(vp));
1.177     christos 1346:                PUFFS_MSG_ENQUEUEWAIT2_NOERROR(pmp, park_inactive, vp->v_data,
                   1347:                    NULL);
1.107     pooka    1348:                PUFFS_MSG_RELEASE(inactive);
                   1349:        }
1.66      pooka    1350:        pnode->pn_stat &= ~PNODE_DOINACT;
1.3       pooka    1351:
                   1352:        /*
1.85      pooka    1353:         * file server thinks it's gone?  then don't be afraid care,
1.3       pooka    1354:         * node's life was already all it would ever be
                   1355:         */
1.137     pooka    1356:        if (pnode->pn_stat & PNODE_NOREFS) {
                   1357:                pnode->pn_stat |= PNODE_DYING;
1.167     manu     1358:                recycle = true;
                   1359:        }
                   1360:
                   1361:        /*
                   1362:         * Handle node TTL.
                   1363:         * If grace has already timed out, make it reclaimed.
                   1364:         * Otherwise, we queue its expiration by sop thread, so
                   1365:         * that it does not remain for ages in the freelist,
                   1366:         * holding memory in userspace, while we will have
                   1367:         * to look it up again anyway.
                   1368:         */
                   1369:        if (PUFFS_USE_FS_TTL(pmp) && !(vp->v_vflag & VV_ROOT) && !recycle) {
                   1370:                bool incache = !TIMED_OUT(pnode->pn_cn_timeout);
                   1371:                bool ingrace = !TIMED_OUT(pnode->pn_cn_grace);
                   1372:                bool reclaimqueued = pnode->pn_stat & PNODE_SOPEXP;
                   1373:
                   1374:                if (!incache && !ingrace && !reclaimqueued) {
                   1375:                        pnode->pn_stat |= PNODE_DYING;
                   1376:                        recycle = true;
                   1377:                }
                   1378:
                   1379:                if (!recycle && !reclaimqueued) {
                   1380:                        struct puffs_sopreq *psopr;
                   1381:                        int at = MAX(pnode->pn_cn_grace, pnode->pn_cn_timeout);
                   1382:
                   1383:                        KASSERT(curlwp != uvm.pagedaemon_lwp);
                   1384:                        psopr = kmem_alloc(sizeof(*psopr), KM_SLEEP);
                   1385:                        psopr->psopr_ck = VPTOPNC(pnode->pn_vp);
                   1386:                        psopr->psopr_sopreq = PUFFS_SOPREQ_EXPIRE;
                   1387:                        psopr->psopr_at = at;
                   1388:
                   1389:                        mutex_enter(&pmp->pmp_sopmtx);
                   1390:
                   1391:                        /*
                   1392:                         * If thread has disapeared, just give up. The
                   1393:                         * fs is being unmounted and the node will be
                   1394:                         * be reclaimed anyway.
                   1395:                         *
                   1396:                         * Otherwise, we queue the request but do not
                   1397:                         * immediatly signal the thread, as the node
                   1398:                         * has not been expired yet.
                   1399:                         */
                   1400:                        if (pmp->pmp_sopthrcount == 0) {
                   1401:                                kmem_free(psopr, sizeof(*psopr));
                   1402:                        } else {
1.171     manu     1403:                                TAILQ_INSERT_TAIL(&pmp->pmp_sopnodereqs,
1.204     msaitoh  1404:                                    psopr, psopr_entries);
1.167     manu     1405:                                pnode->pn_stat |= PNODE_SOPEXP;
                   1406:                        }
                   1407:
                   1408:                        mutex_exit(&pmp->pmp_sopmtx);
                   1409:                }
1.137     pooka    1410:        }
1.124     ad       1411:
1.198     manu     1412:        /*
                   1413:         * Wipe direct I/O flags
                   1414:         */
                   1415:        pnode->pn_stat &= ~(PNODE_RDIRECT|PNODE_WDIRECT);
                   1416:
1.167     manu     1417:        *ap->a_recycle = recycle;
                   1418:
1.155     manu     1419:        mutex_exit(&pnode->pn_sizemtx);
1.3       pooka    1420:
                   1421:        return 0;
                   1422: }
                   1423:
1.103     pooka    1424: static void
1.167     manu     1425: callreclaim(struct puffs_mount *pmp, puffs_cookie_t ck, int nlookup)
1.103     pooka    1426: {
1.107     pooka    1427:        PUFFS_MSG_VARS(vn, reclaim);
1.103     pooka    1428:
                   1429:        if (!EXISTSOP(pmp, RECLAIM))
                   1430:                return;
                   1431:
1.107     pooka    1432:        PUFFS_MSG_ALLOC(vn, reclaim);
1.167     manu     1433:        reclaim_msg->pvnr_nlookup = nlookup;
1.107     pooka    1434:        puffs_msg_setfaf(park_reclaim);
1.127     pooka    1435:        puffs_msg_setinfo(park_reclaim, PUFFSOP_VN, PUFFS_VN_RECLAIM, ck);
1.107     pooka    1436:
1.114     pooka    1437:        puffs_msg_enqueue(pmp, park_reclaim);
1.107     pooka    1438:        PUFFS_MSG_RELEASE(reclaim);
1.167     manu     1439:        return;
1.103     pooka    1440: }
                   1441:
1.34      pooka    1442: /*
                   1443:  * always FAF, we don't really care if the server wants to fail to
                   1444:  * reclaim the node or not
                   1445:  */
1.3       pooka    1446: int
1.123     pooka    1447: puffs_vnop_reclaim(void *v)
1.1       pooka    1448: {
1.211     riastrad 1449:        struct vop_reclaim_v2_args /* {
1.1       pooka    1450:                const struct vnodeop_desc *a_desc;
                   1451:                struct vnode *a_vp;
                   1452:        } */ *ap = v;
1.103     pooka    1453:        struct vnode *vp = ap->a_vp;
                   1454:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.134     pooka    1455:        bool notifyserver = true;
1.17      pooka    1456:
1.211     riastrad 1457:        VOP_UNLOCK(vp);
                   1458:
1.1       pooka    1459:        /*
                   1460:         * first things first: check if someone is trying to reclaim the
                   1461:         * root vnode.  do not allow that to travel to userspace.
                   1462:         * Note that we don't need to take the lock similarly to
                   1463:         * puffs_root(), since there is only one of us.
                   1464:         */
1.105     ad       1465:        if (vp->v_vflag & VV_ROOT) {
1.55      pooka    1466:                mutex_enter(&pmp->pmp_lock);
1.39      pooka    1467:                KASSERT(pmp->pmp_root != NULL);
                   1468:                pmp->pmp_root = NULL;
1.55      pooka    1469:                mutex_exit(&pmp->pmp_lock);
1.134     pooka    1470:                notifyserver = false;
1.1       pooka    1471:        }
                   1472:
1.134     pooka    1473:        /*
                   1474:         * purge info from kernel before issueing FAF, since we
                   1475:         * don't really know when we'll get around to it after
                   1476:         * that and someone might race us into node creation
                   1477:         */
                   1478:        mutex_enter(&pmp->pmp_lock);
1.167     manu     1479:        if (PUFFS_USE_NAMECACHE(pmp))
                   1480:                cache_purge(vp);
1.134     pooka    1481:        mutex_exit(&pmp->pmp_lock);
                   1482:
1.167     manu     1483:        if (notifyserver) {
                   1484:                int nlookup = VPTOPP(vp)->pn_nlookup;
                   1485:
                   1486:                callreclaim(MPTOPUFFSMP(vp->v_mount), VPTOPNC(vp), nlookup);
                   1487:        }
1.134     pooka    1488:
1.174     manu     1489:        if (PUFFS_USE_DOTDOTCACHE(pmp)) {
                   1490:                if (__predict_true(VPTOPP(vp)->pn_parent != NULL))
                   1491:                        vrele(VPTOPP(vp)->pn_parent);
                   1492:                else
1.187     hannken  1493:                        KASSERT(vp->v_type == VNON || (vp->v_vflag & VV_ROOT));
1.174     manu     1494:        }
                   1495:
1.103     pooka    1496:        puffs_putvnode(vp);
1.1       pooka    1497:
                   1498:        return 0;
                   1499: }
                   1500:
1.60      pooka    1501: #define CSIZE sizeof(**ap->a_cookies)
1.1       pooka    1502: int
1.123     pooka    1503: puffs_vnop_readdir(void *v)
1.1       pooka    1504: {
                   1505:        struct vop_readdir_args /* {
                   1506:                const struct vnodeop_desc *a_desc;
                   1507:                struct vnode *a_vp;
                   1508:                struct uio *a_uio;
                   1509:                kauth_cred_t a_cred;
                   1510:                int *a_eofflag;
                   1511:                off_t **a_cookies;
                   1512:                int *a_ncookies;
                   1513:        } */ *ap = v;
1.107     pooka    1514:        PUFFS_MSG_VARS(vn, readdir);
1.102     pooka    1515:        struct vnode *vp = ap->a_vp;
1.107     pooka    1516:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.61      pooka    1517:        size_t argsize, tomove, cookiemem, cookiesmax;
1.1       pooka    1518:        struct uio *uio = ap->a_uio;
1.89      pooka    1519:        size_t howmuch, resid;
1.1       pooka    1520:        int error;
                   1521:
1.89      pooka    1522:        /*
                   1523:         * ok, so we need: resid + cookiemem = maxreq
                   1524:         * => resid + cookiesize * (resid/minsize) = maxreq
                   1525:         * => resid + cookiesize/minsize * resid = maxreq
                   1526:         * => (cookiesize/minsize + 1) * resid = maxreq
                   1527:         * => resid = maxreq / (cookiesize/minsize + 1)
                   1528:         *
                   1529:         * Since cookiesize <= minsize and we're not very big on floats,
                   1530:         * we approximate that to be 1.  Therefore:
                   1531:         *
                   1532:         * resid = maxreq / 2;
                   1533:         *
                   1534:         * Well, at least we didn't have to use differential equations
                   1535:         * or the Gram-Schmidt process.
                   1536:         *
                   1537:         * (yes, I'm very afraid of this)
                   1538:         */
                   1539:        KASSERT(CSIZE <= _DIRENT_MINSIZE((struct dirent *)0));
                   1540:
1.58      pooka    1541:        if (ap->a_cookies) {
                   1542:                KASSERT(ap->a_ncookies != NULL);
1.59      pooka    1543:                if (pmp->pmp_args.pa_fhsize == 0)
1.58      pooka    1544:                        return EOPNOTSUPP;
1.89      pooka    1545:                resid = PUFFS_TOMOVE(uio->uio_resid, pmp) / 2;
                   1546:                cookiesmax = resid/_DIRENT_MINSIZE((struct dirent *)0);
1.58      pooka    1547:                cookiemem = ALIGN(cookiesmax*CSIZE); /* play safe */
                   1548:        } else {
1.89      pooka    1549:                resid = PUFFS_TOMOVE(uio->uio_resid, pmp);
1.58      pooka    1550:                cookiesmax = 0;
                   1551:                cookiemem = 0;
                   1552:        }
1.1       pooka    1553:
1.107     pooka    1554:        argsize = sizeof(struct puffs_vnmsg_readdir);
1.89      pooka    1555:        tomove = resid + cookiemem;
1.107     pooka    1556:        puffs_msgmem_alloc(argsize + tomove, &park_readdir,
1.125     pooka    1557:            (void *)&readdir_msg, 1);
1.1       pooka    1558:
1.107     pooka    1559:        puffs_credcvt(&readdir_msg->pvnr_cred, ap->a_cred);
                   1560:        readdir_msg->pvnr_offset = uio->uio_offset;
                   1561:        readdir_msg->pvnr_resid = resid;
                   1562:        readdir_msg->pvnr_ncookies = cookiesmax;
                   1563:        readdir_msg->pvnr_eofflag = 0;
                   1564:        readdir_msg->pvnr_dentoff = cookiemem;
1.114     pooka    1565:        puffs_msg_setinfo(park_readdir, PUFFSOP_VN,
                   1566:            PUFFS_VN_READDIR, VPTOPNC(vp));
                   1567:        puffs_msg_setdelta(park_readdir, tomove);
1.1       pooka    1568:
1.114     pooka    1569:        PUFFS_MSG_ENQUEUEWAIT2(pmp, park_readdir, vp->v_data, NULL, error);
1.102     pooka    1570:        error = checkerr(pmp, error, __func__);
1.1       pooka    1571:        if (error)
                   1572:                goto out;
                   1573:
                   1574:        /* userspace is cheating? */
1.107     pooka    1575:        if (readdir_msg->pvnr_resid > resid) {
1.114     pooka    1576:                puffs_senderr(pmp, PUFFS_ERR_READDIR, E2BIG,
1.102     pooka    1577:                    "resid grew", VPTOPNC(vp));
                   1578:                ERROUT(EPROTO);
                   1579:        }
1.107     pooka    1580:        if (readdir_msg->pvnr_ncookies > cookiesmax) {
1.114     pooka    1581:                puffs_senderr(pmp, PUFFS_ERR_READDIR, E2BIG,
1.102     pooka    1582:                    "too many cookies", VPTOPNC(vp));
1.100     pooka    1583:                ERROUT(EPROTO);
                   1584:        }
1.1       pooka    1585:
1.58      pooka    1586:        /* check eof */
1.107     pooka    1587:        if (readdir_msg->pvnr_eofflag)
1.58      pooka    1588:                *ap->a_eofflag = 1;
                   1589:
1.1       pooka    1590:        /* bouncy-wouncy with the directory data */
1.107     pooka    1591:        howmuch = resid - readdir_msg->pvnr_resid;
1.58      pooka    1592:
                   1593:        /* force eof if no data was returned (getcwd() needs this) */
1.29      pooka    1594:        if (howmuch == 0) {
                   1595:                *ap->a_eofflag = 1;
                   1596:                goto out;
                   1597:        }
1.58      pooka    1598:
1.107     pooka    1599:        error = uiomove(readdir_msg->pvnr_data + cookiemem, howmuch, uio);
1.1       pooka    1600:        if (error)
                   1601:                goto out;
1.58      pooka    1602:
                   1603:        /* provide cookies to caller if so desired */
                   1604:        if (ap->a_cookies) {
1.159     manu     1605:                KASSERT(curlwp != uvm.pagedaemon_lwp);
1.107     pooka    1606:                *ap->a_cookies = malloc(readdir_msg->pvnr_ncookies*CSIZE,
1.58      pooka    1607:                    M_TEMP, M_WAITOK);
1.107     pooka    1608:                *ap->a_ncookies = readdir_msg->pvnr_ncookies;
                   1609:                memcpy(*ap->a_cookies, readdir_msg->pvnr_data,
1.58      pooka    1610:                    *ap->a_ncookies*CSIZE);
                   1611:        }
                   1612:
                   1613:        /* next readdir starts here */
1.107     pooka    1614:        uio->uio_offset = readdir_msg->pvnr_offset;
1.1       pooka    1615:
                   1616:  out:
1.107     pooka    1617:        puffs_msgmem_release(park_readdir);
1.1       pooka    1618:        return error;
                   1619: }
1.58      pooka    1620: #undef CSIZE
1.1       pooka    1621:
1.69      pooka    1622: /*
                   1623:  * poll works by consuming the bitmask in pn_revents.  If there are
                   1624:  * events available, poll returns immediately.  If not, it issues a
                   1625:  * poll to userspace, selrecords itself and returns with no available
                   1626:  * events.  When the file server returns, it executes puffs_parkdone_poll(),
                   1627:  * where available events are added to the bitmask.  selnotify() is
                   1628:  * then also executed by that function causing us to enter here again
                   1629:  * and hopefully find the missing bits (unless someone got them first,
                   1630:  * in which case it starts all over again).
                   1631:  */
1.1       pooka    1632: int
1.123     pooka    1633: puffs_vnop_poll(void *v)
1.1       pooka    1634: {
                   1635:        struct vop_poll_args /* {
                   1636:                const struct vnodeop_desc *a_desc;
                   1637:                struct vnode *a_vp;
                   1638:                int a_events;
1.129     christos 1639:        } */ *ap = v;
1.107     pooka    1640:        PUFFS_MSG_VARS(vn, poll);
1.69      pooka    1641:        struct vnode *vp = ap->a_vp;
                   1642:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
                   1643:        struct puffs_node *pn = vp->v_data;
1.177     christos 1644:        int events;
1.1       pooka    1645:
1.69      pooka    1646:        if (EXISTSOP(pmp, POLL)) {
                   1647:                mutex_enter(&pn->pn_mtx);
                   1648:                events = pn->pn_revents & ap->a_events;
                   1649:                if (events & ap->a_events) {
                   1650:                        pn->pn_revents &= ~ap->a_events;
                   1651:                        mutex_exit(&pn->pn_mtx);
1.1       pooka    1652:
1.69      pooka    1653:                        return events;
                   1654:                } else {
                   1655:                        puffs_referencenode(pn);
                   1656:                        mutex_exit(&pn->pn_mtx);
                   1657:
1.107     pooka    1658:                        PUFFS_MSG_ALLOC(vn, poll);
                   1659:                        poll_msg->pvnr_events = ap->a_events;
1.114     pooka    1660:                        puffs_msg_setinfo(park_poll, PUFFSOP_VN,
                   1661:                            PUFFS_VN_POLL, VPTOPNC(vp));
                   1662:                        puffs_msg_setcall(park_poll, puffs_parkdone_poll, pn);
1.120     pooka    1663:                        selrecord(curlwp, &pn->pn_sel);
1.69      pooka    1664:
1.177     christos 1665:                        PUFFS_MSG_ENQUEUEWAIT2_NOERROR(pmp, park_poll,
                   1666:                            vp->v_data, NULL);
1.107     pooka    1667:                        PUFFS_MSG_RELEASE(poll);
1.1       pooka    1668:
1.69      pooka    1669:                        return 0;
                   1670:                }
                   1671:        } else {
                   1672:                return genfs_poll(v);
                   1673:        }
1.1       pooka    1674: }
                   1675:
1.141     pooka    1676: static int
                   1677: flushvncache(struct vnode *vp, off_t offlo, off_t offhi, bool wait)
1.1       pooka    1678: {
1.141     pooka    1679:        struct puffs_node *pn = VPTOPP(vp);
1.54      pooka    1680:        struct vattr va;
1.141     pooka    1681:        int pflags, error;
1.8       pooka    1682:
1.65      pooka    1683:        /* flush out information from our metacache, see vop_setattr */
1.137     pooka    1684:        if (pn->pn_stat & PNODE_METACACHE_MASK
                   1685:            && (pn->pn_stat & PNODE_DYING) == 0) {
1.54      pooka    1686:                vattr_null(&va);
1.141     pooka    1687:                error = dosetattr(vp, &va, FSCRED,
                   1688:                    SETATTR_CHSIZE | (wait ? 0 : SETATTR_ASYNC));
1.54      pooka    1689:                if (error)
                   1690:                        return error;
                   1691:        }
1.8       pooka    1692:
                   1693:        /*
                   1694:         * flush pages to avoid being overly dirty
                   1695:         */
1.54      pooka    1696:        pflags = PGO_CLEANIT;
1.141     pooka    1697:        if (wait)
1.54      pooka    1698:                pflags |= PGO_SYNCIO;
1.165     manu     1699:
1.153     rmind    1700:        mutex_enter(vp->v_interlock);
1.141     pooka    1701:        return VOP_PUTPAGES(vp, trunc_page(offlo), round_page(offhi), pflags);
                   1702: }
                   1703:
                   1704: int
                   1705: puffs_vnop_fsync(void *v)
                   1706: {
                   1707:        struct vop_fsync_args /* {
                   1708:                const struct vnodeop_desc *a_desc;
                   1709:                struct vnode *a_vp;
                   1710:                kauth_cred_t a_cred;
                   1711:                int a_flags;
                   1712:                off_t a_offlo;
                   1713:                off_t a_offhi;
                   1714:        } */ *ap = v;
                   1715:        PUFFS_MSG_VARS(vn, fsync);
1.163     martin   1716:        struct vnode *vp;
                   1717:        struct puffs_node *pn;
                   1718:        struct puffs_mount *pmp;
1.141     pooka    1719:        int error, dofaf;
                   1720:
1.163     martin   1721:        vp = ap->a_vp;
                   1722:        KASSERT(vp != NULL);
                   1723:        pn = VPTOPP(vp);
                   1724:        KASSERT(pn != NULL);
                   1725:        pmp = MPTOPUFFSMP(vp->v_mount);
1.156     manu     1726:        if (ap->a_flags & FSYNC_WAIT) {
                   1727:                mutex_enter(&pn->pn_sizemtx);
                   1728:        } else {
                   1729:                if (mutex_tryenter(&pn->pn_sizemtx) == 0)
                   1730:                        return EDEADLK;
                   1731:        }
                   1732:
1.141     pooka    1733:        error = flushvncache(vp, ap->a_offlo, ap->a_offhi,
                   1734:            (ap->a_flags & FSYNC_WAIT) == FSYNC_WAIT);
1.8       pooka    1735:        if (error)
1.155     manu     1736:                goto out;
1.8       pooka    1737:
1.31      pooka    1738:        /*
                   1739:         * HELLO!  We exit already here if the user server does not
1.38      pooka    1740:         * support fsync OR if we should call fsync for a node which
                   1741:         * has references neither in the kernel or the fs server.
                   1742:         * Otherwise we continue to issue fsync() forward.
1.31      pooka    1743:         */
1.155     manu     1744:        error = 0;
1.137     pooka    1745:        if (!EXISTSOP(pmp, FSYNC) || (pn->pn_stat & PNODE_DYING))
1.155     manu     1746:                goto out;
1.31      pooka    1747:
1.41      pooka    1748:        dofaf = (ap->a_flags & FSYNC_WAIT) == 0 || ap->a_flags == FSYNC_LAZY;
1.35      pooka    1749:        /*
                   1750:         * We abuse VXLOCK to mean "vnode is going to die", so we issue
                   1751:         * only FAFs for those.  Otherwise there's a danger of deadlock,
                   1752:         * since the execution context here might be the user server
                   1753:         * doing some operation on another fs, which in turn caused a
                   1754:         * vnode to be reclaimed from the freelist for this fs.
                   1755:         */
                   1756:        if (dofaf == 0) {
1.153     rmind    1757:                mutex_enter(vp->v_interlock);
1.181     hannken  1758:                if (vdead_check(vp, VDEAD_NOWAIT) != 0)
1.35      pooka    1759:                        dofaf = 1;
1.153     rmind    1760:                mutex_exit(vp->v_interlock);
1.35      pooka    1761:        }
                   1762:
1.107     pooka    1763:        PUFFS_MSG_ALLOC(vn, fsync);
                   1764:        if (dofaf)
                   1765:                puffs_msg_setfaf(park_fsync);
                   1766:
                   1767:        puffs_credcvt(&fsync_msg->pvnr_cred, ap->a_cred);
                   1768:        fsync_msg->pvnr_flags = ap->a_flags;
                   1769:        fsync_msg->pvnr_offlo = ap->a_offlo;
                   1770:        fsync_msg->pvnr_offhi = ap->a_offhi;
1.114     pooka    1771:        puffs_msg_setinfo(park_fsync, PUFFSOP_VN,
                   1772:            PUFFS_VN_FSYNC, VPTOPNC(vp));
1.31      pooka    1773:
1.114     pooka    1774:        PUFFS_MSG_ENQUEUEWAIT2(pmp, park_fsync, vp->v_data, NULL, error);
1.107     pooka    1775:        PUFFS_MSG_RELEASE(fsync);
1.1       pooka    1776:
1.107     pooka    1777:        error = checkerr(pmp, error, __func__);
1.8       pooka    1778:
1.155     manu     1779: out:
                   1780:        mutex_exit(&pn->pn_sizemtx);
1.8       pooka    1781:        return error;
1.1       pooka    1782: }
                   1783:
                   1784: int
1.123     pooka    1785: puffs_vnop_seek(void *v)
1.1       pooka    1786: {
                   1787:        struct vop_seek_args /* {
                   1788:                const struct vnodeop_desc *a_desc;
                   1789:                struct vnode *a_vp;
                   1790:                off_t a_oldoff;
                   1791:                off_t a_newoff;
                   1792:                kauth_cred_t a_cred;
                   1793:        } */ *ap = v;
1.107     pooka    1794:        PUFFS_MSG_VARS(vn, seek);
1.102     pooka    1795:        struct vnode *vp = ap->a_vp;
1.106     pooka    1796:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.102     pooka    1797:        int error;
1.1       pooka    1798:
1.107     pooka    1799:        PUFFS_MSG_ALLOC(vn, seek);
                   1800:        seek_msg->pvnr_oldoff = ap->a_oldoff;
                   1801:        seek_msg->pvnr_newoff = ap->a_newoff;
                   1802:        puffs_credcvt(&seek_msg->pvnr_cred, ap->a_cred);
1.114     pooka    1803:        puffs_msg_setinfo(park_seek, PUFFSOP_VN,
                   1804:            PUFFS_VN_SEEK, VPTOPNC(vp));
1.1       pooka    1805:
1.114     pooka    1806:        PUFFS_MSG_ENQUEUEWAIT2(pmp, park_seek, vp->v_data, NULL, error);
1.107     pooka    1807:        PUFFS_MSG_RELEASE(seek);
1.106     pooka    1808:        return checkerr(pmp, error, __func__);
1.1       pooka    1809: }
                   1810:
1.103     pooka    1811: static int
1.127     pooka    1812: callremove(struct puffs_mount *pmp, puffs_cookie_t dck, puffs_cookie_t ck,
1.103     pooka    1813:        struct componentname *cnp)
                   1814: {
1.107     pooka    1815:        PUFFS_MSG_VARS(vn, remove);
1.103     pooka    1816:        int error;
                   1817:
1.107     pooka    1818:        PUFFS_MSG_ALLOC(vn, remove);
1.127     pooka    1819:        remove_msg->pvnr_cookie_targ = ck;
1.107     pooka    1820:        puffs_makecn(&remove_msg->pvnr_cn, &remove_msg->pvnr_cn_cred,
1.122     pooka    1821:            cnp, PUFFS_USE_FULLPNBUF(pmp));
1.127     pooka    1822:        puffs_msg_setinfo(park_remove, PUFFSOP_VN, PUFFS_VN_REMOVE, dck);
1.107     pooka    1823:
1.114     pooka    1824:        PUFFS_MSG_ENQUEUEWAIT(pmp, park_remove, error);
1.107     pooka    1825:        PUFFS_MSG_RELEASE(remove);
1.103     pooka    1826:
                   1827:        return checkerr(pmp, error, __func__);
                   1828: }
                   1829:
1.107     pooka    1830: /*
                   1831:  * XXX: can't use callremove now because can't catch setbacks with
1.116     pooka    1832:  * it due to lack of a pnode argument.
1.107     pooka    1833:  */
1.1       pooka    1834: int
1.123     pooka    1835: puffs_vnop_remove(void *v)
1.1       pooka    1836: {
1.210     riastrad 1837:        struct vop_remove_v2_args /* {
1.1       pooka    1838:                const struct vnodeop_desc *a_desc;
                   1839:                struct vnode *a_dvp;
                   1840:                struct vnode *a_vp;
                   1841:                struct componentname *a_cnp;
                   1842:        } */ *ap = v;
1.107     pooka    1843:        PUFFS_MSG_VARS(vn, remove);
1.103     pooka    1844:        struct vnode *dvp = ap->a_dvp;
                   1845:        struct vnode *vp = ap->a_vp;
1.116     pooka    1846:        struct puffs_node *dpn = VPTOPP(dvp);
                   1847:        struct puffs_node *pn = VPTOPP(vp);
1.107     pooka    1848:        struct componentname *cnp = ap->a_cnp;
1.116     pooka    1849:        struct mount *mp = dvp->v_mount;
                   1850:        struct puffs_mount *pmp = MPTOPUFFSMP(mp);
1.1       pooka    1851:        int error;
                   1852:
1.107     pooka    1853:        PUFFS_MSG_ALLOC(vn, remove);
                   1854:        remove_msg->pvnr_cookie_targ = VPTOPNC(vp);
                   1855:        puffs_makecn(&remove_msg->pvnr_cn, &remove_msg->pvnr_cn_cred,
1.122     pooka    1856:            cnp, PUFFS_USE_FULLPNBUF(pmp));
1.114     pooka    1857:        puffs_msg_setinfo(park_remove, PUFFSOP_VN,
                   1858:            PUFFS_VN_REMOVE, VPTOPNC(dvp));
1.1       pooka    1859:
1.116     pooka    1860:        puffs_msg_enqueue(pmp, park_remove);
1.210     riastrad 1861:        vref(dvp);              /* hang onto caller's reference at end */
                   1862:        REFPN(dpn);
1.116     pooka    1863:        if (dvp == vp)
                   1864:                REFPN(pn);
                   1865:        else
                   1866:                REFPN_AND_UNLOCKVP(vp, pn);
                   1867:        error = puffs_msg_wait2(pmp, park_remove, dpn, pn);
                   1868:
1.107     pooka    1869:        PUFFS_MSG_RELEASE(remove);
                   1870:
1.185     manu     1871:        puffs_updatenode(VPTOPP(dvp), PUFFS_UPDATECTIME|PUFFS_UPDATEMTIME, 0);
                   1872:
1.116     pooka    1873:        RELEPN_AND_VP(dvp, dpn);
                   1874:        RELEPN_AND_VP(vp, pn);
                   1875:
1.107     pooka    1876:        error = checkerr(pmp, error, __func__);
1.1       pooka    1877:        return error;
                   1878: }
                   1879:
                   1880: int
1.123     pooka    1881: puffs_vnop_mkdir(void *v)
1.1       pooka    1882: {
1.179     hannken  1883:        struct vop_mkdir_v3_args /* {
1.1       pooka    1884:                const struct vnodeop_desc *a_desc;
                   1885:                struct vnode *a_dvp;
                   1886:                struct vnode **a_vpp;
                   1887:                struct componentname *a_cnp;
                   1888:                struct vattr *a_vap;
                   1889:        } */ *ap = v;
1.107     pooka    1890:        PUFFS_MSG_VARS(vn, mkdir);
                   1891:        struct vnode *dvp = ap->a_dvp;
1.116     pooka    1892:        struct puffs_node *dpn = VPTOPP(dvp);
1.111     pooka    1893:        struct componentname *cnp = ap->a_cnp;
1.116     pooka    1894:        struct mount *mp = dvp->v_mount;
                   1895:        struct puffs_mount *pmp = MPTOPUFFSMP(mp);
1.1       pooka    1896:        int error;
                   1897:
1.107     pooka    1898:        PUFFS_MSG_ALLOC(vn, mkdir);
                   1899:        puffs_makecn(&mkdir_msg->pvnr_cn, &mkdir_msg->pvnr_cn_cred,
1.122     pooka    1900:            cnp, PUFFS_USE_FULLPNBUF(pmp));
1.107     pooka    1901:        mkdir_msg->pvnr_va = *ap->a_vap;
1.114     pooka    1902:        puffs_msg_setinfo(park_mkdir, PUFFSOP_VN,
                   1903:            PUFFS_VN_MKDIR, VPTOPNC(dvp));
1.1       pooka    1904:
1.134     pooka    1905:        PUFFS_MSG_ENQUEUEWAIT2(pmp, park_mkdir, dvp->v_data, NULL, error);
1.116     pooka    1906:
1.102     pooka    1907:        error = checkerr(pmp, error, __func__);
1.1       pooka    1908:        if (error)
1.4       pooka    1909:                goto out;
1.1       pooka    1910:
1.116     pooka    1911:        error = puffs_newnode(mp, dvp, ap->a_vpp,
1.111     pooka    1912:            mkdir_msg->pvnr_newnode, cnp, VDIR, 0);
1.165     manu     1913:        if (error) {
1.116     pooka    1914:                puffs_abortbutton(pmp, PUFFS_ABORT_MKDIR, dpn->pn_cookie,
1.111     pooka    1915:                    mkdir_msg->pvnr_newnode, cnp);
1.165     manu     1916:                goto out;
                   1917:        }
                   1918:
                   1919:        if (PUFFS_USE_FS_TTL(pmp)) {
                   1920:                struct timespec *va_ttl = &mkdir_msg->pvnr_va_ttl;
                   1921:                struct timespec *cn_ttl = &mkdir_msg->pvnr_cn_ttl;
                   1922:                struct vattr *rvap = &mkdir_msg->pvnr_va;
                   1923:
1.166     manu     1924:                update_va(*ap->a_vpp, NULL, rvap,
                   1925:                          va_ttl, cn_ttl, SETATTR_CHSIZE);
1.165     manu     1926:        }
1.4       pooka    1927:
1.173     manu     1928:        VPTOPP(*ap->a_vpp)->pn_nlookup++;
                   1929:
1.174     manu     1930:        if (PUFFS_USE_DOTDOTCACHE(pmp) &&
                   1931:            (VPTOPP(*ap->a_vpp)->pn_parent != dvp))
                   1932:                update_parent(*ap->a_vpp, dvp);
                   1933:
1.4       pooka    1934:  out:
1.107     pooka    1935:        PUFFS_MSG_RELEASE(mkdir);
1.4       pooka    1936:        return error;
1.1       pooka    1937: }
                   1938:
1.103     pooka    1939: static int
1.127     pooka    1940: callrmdir(struct puffs_mount *pmp, puffs_cookie_t dck, puffs_cookie_t ck,
1.103     pooka    1941:        struct componentname *cnp)
                   1942: {
1.107     pooka    1943:        PUFFS_MSG_VARS(vn, rmdir);
1.103     pooka    1944:        int error;
                   1945:
1.107     pooka    1946:        PUFFS_MSG_ALLOC(vn, rmdir);
1.127     pooka    1947:        rmdir_msg->pvnr_cookie_targ = ck;
1.107     pooka    1948:        puffs_makecn(&rmdir_msg->pvnr_cn, &rmdir_msg->pvnr_cn_cred,
1.122     pooka    1949:            cnp, PUFFS_USE_FULLPNBUF(pmp));
1.127     pooka    1950:        puffs_msg_setinfo(park_rmdir, PUFFSOP_VN, PUFFS_VN_RMDIR, dck);
1.107     pooka    1951:
1.114     pooka    1952:        PUFFS_MSG_ENQUEUEWAIT(pmp, park_rmdir, error);
1.107     pooka    1953:        PUFFS_MSG_RELEASE(rmdir);
1.103     pooka    1954:
                   1955:        return checkerr(pmp, error, __func__);
                   1956: }
                   1957:
1.1       pooka    1958: int
1.123     pooka    1959: puffs_vnop_rmdir(void *v)
1.1       pooka    1960: {
1.210     riastrad 1961:        struct vop_rmdir_v2_args /* {
1.1       pooka    1962:                const struct vnodeop_desc *a_desc;
                   1963:                struct vnode *a_dvp;
                   1964:                struct vnode *a_vp;
                   1965:                struct componentname *a_cnp;
                   1966:        } */ *ap = v;
1.107     pooka    1967:        PUFFS_MSG_VARS(vn, rmdir);
1.103     pooka    1968:        struct vnode *dvp = ap->a_dvp;
                   1969:        struct vnode *vp = ap->a_vp;
1.116     pooka    1970:        struct puffs_node *dpn = VPTOPP(dvp);
                   1971:        struct puffs_node *pn = VPTOPP(vp);
1.103     pooka    1972:        struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount);
1.107     pooka    1973:        struct componentname *cnp = ap->a_cnp;
1.1       pooka    1974:        int error;
                   1975:
1.107     pooka    1976:        PUFFS_MSG_ALLOC(vn, rmdir);
                   1977:        rmdir_msg->pvnr_cookie_targ = VPTOPNC(vp);
                   1978:        puffs_makecn(&rmdir_msg->pvnr_cn, &rmdir_msg->pvnr_cn_cred,
1.122     pooka    1979:            cnp, PUFFS_USE_FULLPNBUF(pmp));
1.114     pooka    1980:        puffs_msg_setinfo(park_rmdir, PUFFSOP_VN,
                   1981:            PUFFS_VN_RMDIR, VPTOPNC(dvp));
1.107     pooka    1982:
1.116     pooka    1983:        puffs_msg_enqueue(pmp, park_rmdir);
1.210     riastrad 1984:        vref(dvp);              /* hang onto caller's reference at end */
                   1985:        KASSERTMSG((dvp != vp), "rmdir .");
                   1986:        REFPN(dpn);
1.116     pooka    1987:        REFPN_AND_UNLOCKVP(vp, pn);
                   1988:        error = puffs_msg_wait2(pmp, park_rmdir, dpn, pn);
                   1989:
1.107     pooka    1990:        PUFFS_MSG_RELEASE(rmdir);
1.1       pooka    1991:
1.185     manu     1992:        puffs_updatenode(VPTOPP(dvp), PUFFS_UPDATECTIME|PUFFS_UPDATEMTIME, 0);
                   1993:
1.23      pooka    1994:        /* XXX: some call cache_purge() *for both vnodes* here, investigate */
1.116     pooka    1995:        RELEPN_AND_VP(dvp, dpn);
                   1996:        RELEPN_AND_VP(vp, pn);
1.1       pooka    1997:
                   1998:        return error;
                   1999: }
                   2000:
                   2001: int
1.123     pooka    2002: puffs_vnop_link(void *v)
1.1       pooka    2003: {
1.203     riastrad 2004:        struct vop_link_v2_args /* {
1.1       pooka    2005:                const struct vnodeop_desc *a_desc;
                   2006:                struct vnode *a_dvp;
                   2007:                struct vnode *a_vp;
                   2008:                struct componentname *a_cnp;
1.129     christos 2009:        } */ *ap = v;
1.107     pooka    2010:        PUFFS_MSG_VARS(vn, link);
                   2011:        struct vnode *dvp = ap->a_dvp;
                   2012:        struct vnode *vp = ap->a_vp;
1.116     pooka    2013:        struct puffs_node *dpn = VPTOPP(dvp);
                   2014:        struct puffs_node *pn = VPTOPP(vp);
1.107     pooka    2015:        struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount);
1.111     pooka    2016:        struct componentname *cnp = ap->a_cnp;
1.1       pooka    2017:        int error;
                   2018:
1.107     pooka    2019:        PUFFS_MSG_ALLOC(vn, link);
                   2020:        link_msg->pvnr_cookie_targ = VPTOPNC(vp);
                   2021:        puffs_makecn(&link_msg->pvnr_cn, &link_msg->pvnr_cn_cred,
1.122     pooka    2022:            cnp, PUFFS_USE_FULLPNBUF(pmp));
1.114     pooka    2023:        puffs_msg_setinfo(park_link, PUFFSOP_VN,
                   2024:            PUFFS_VN_LINK, VPTOPNC(dvp));
1.1       pooka    2025:
1.116     pooka    2026:        puffs_msg_enqueue(pmp, park_link);
                   2027:        error = puffs_msg_wait2(pmp, park_link, dpn, pn);
                   2028:
1.107     pooka    2029:        PUFFS_MSG_RELEASE(link);
1.1       pooka    2030:
1.102     pooka    2031:        error = checkerr(pmp, error, __func__);
1.1       pooka    2032:
1.54      pooka    2033:        /*
                   2034:         * XXX: stay in touch with the cache.  I don't like this, but
                   2035:         * don't have a better solution either.  See also puffs_rename().
                   2036:         */
1.185     manu     2037:        if (error == 0) {
1.117     pooka    2038:                puffs_updatenode(pn, PUFFS_UPDATECTIME, 0);
1.185     manu     2039:                puffs_updatenode(VPTOPP(dvp),
                   2040:                                 PUFFS_UPDATECTIME|PUFFS_UPDATEMTIME, 0);
                   2041:        }
1.54      pooka    2042:
1.1       pooka    2043:        return error;
                   2044: }
                   2045:
                   2046: int
1.123     pooka    2047: puffs_vnop_symlink(void *v)
1.1       pooka    2048: {
1.179     hannken  2049:        struct vop_symlink_v3_args /* {
1.1       pooka    2050:                const struct vnodeop_desc *a_desc;
                   2051:                struct vnode *a_dvp;
                   2052:                struct vnode **a_vpp;
                   2053:                struct componentname *a_cnp;
                   2054:                struct vattr *a_vap;
                   2055:                char *a_target;
1.129     christos 2056:        } */ *ap = v;
1.107     pooka    2057:        PUFFS_MSG_VARS(vn, symlink);
                   2058:        struct vnode *dvp = ap->a_dvp;
1.116     pooka    2059:        struct puffs_node *dpn = VPTOPP(dvp);
                   2060:        struct mount *mp = dvp->v_mount;
1.107     pooka    2061:        struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount);
1.116     pooka    2062:        struct componentname *cnp = ap->a_cnp;
1.1       pooka    2063:        int error;
                   2064:
                   2065:        *ap->a_vpp = NULL;
                   2066:
1.107     pooka    2067:        PUFFS_MSG_ALLOC(vn, symlink);
                   2068:        puffs_makecn(&symlink_msg->pvnr_cn, &symlink_msg->pvnr_cn_cred,
1.122     pooka    2069:                cnp, PUFFS_USE_FULLPNBUF(pmp));
1.107     pooka    2070:        symlink_msg->pvnr_va = *ap->a_vap;
                   2071:        (void)strlcpy(symlink_msg->pvnr_link, ap->a_target,
                   2072:            sizeof(symlink_msg->pvnr_link));
1.114     pooka    2073:        puffs_msg_setinfo(park_symlink, PUFFSOP_VN,
                   2074:            PUFFS_VN_SYMLINK, VPTOPNC(dvp));
1.1       pooka    2075:
1.134     pooka    2076:        PUFFS_MSG_ENQUEUEWAIT2(pmp, park_symlink, dvp->v_data, NULL, error);
1.116     pooka    2077:
1.102     pooka    2078:        error = checkerr(pmp, error, __func__);
1.1       pooka    2079:        if (error)
1.4       pooka    2080:                goto out;
1.1       pooka    2081:
1.116     pooka    2082:        error = puffs_newnode(mp, dvp, ap->a_vpp,
                   2083:            symlink_msg->pvnr_newnode, cnp, VLNK, 0);
1.165     manu     2084:        if (error) {
1.116     pooka    2085:                puffs_abortbutton(pmp, PUFFS_ABORT_SYMLINK, dpn->pn_cookie,
                   2086:                    symlink_msg->pvnr_newnode, cnp);
1.165     manu     2087:                goto out;
                   2088:        }
                   2089:
                   2090:        if (PUFFS_USE_FS_TTL(pmp)) {
                   2091:                struct timespec *va_ttl = &symlink_msg->pvnr_va_ttl;
                   2092:                struct timespec *cn_ttl = &symlink_msg->pvnr_cn_ttl;
                   2093:                struct vattr *rvap = &symlink_msg->pvnr_va;
                   2094:
1.166     manu     2095:                update_va(*ap->a_vpp, NULL, rvap,
                   2096:                          va_ttl, cn_ttl, SETATTR_CHSIZE);
1.165     manu     2097:        }
1.4       pooka    2098:
1.173     manu     2099:        VPTOPP(*ap->a_vpp)->pn_nlookup++;
                   2100:
1.174     manu     2101:        if (PUFFS_USE_DOTDOTCACHE(pmp) &&
                   2102:            (VPTOPP(*ap->a_vpp)->pn_parent != dvp))
                   2103:                update_parent(*ap->a_vpp, dvp);
                   2104:
1.4       pooka    2105:  out:
1.107     pooka    2106:        PUFFS_MSG_RELEASE(symlink);
1.81      pooka    2107:
1.4       pooka    2108:        return error;
1.1       pooka    2109: }
                   2110:
                   2111: int
1.123     pooka    2112: puffs_vnop_readlink(void *v)
1.1       pooka    2113: {
                   2114:        struct vop_readlink_args /* {
                   2115:                const struct vnodeop_desc *a_desc;
                   2116:                struct vnode *a_vp;
                   2117:                struct uio *a_uio;
                   2118:                kauth_cred_t a_cred;
                   2119:        } */ *ap = v;
1.107     pooka    2120:        PUFFS_MSG_VARS(vn, readlink);
                   2121:        struct vnode *vp = ap->a_vp;
1.100     pooka    2122:        struct puffs_mount *pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
1.51      pooka    2123:        size_t linklen;
1.1       pooka    2124:        int error;
                   2125:
1.107     pooka    2126:        PUFFS_MSG_ALLOC(vn, readlink);
                   2127:        puffs_credcvt(&readlink_msg->pvnr_cred, ap->a_cred);
                   2128:        linklen = sizeof(readlink_msg->pvnr_link);
                   2129:        readlink_msg->pvnr_linklen = linklen;
1.114     pooka    2130:        puffs_msg_setinfo(park_readlink, PUFFSOP_VN,
                   2131:            PUFFS_VN_READLINK, VPTOPNC(vp));
1.1       pooka    2132:
1.114     pooka    2133:        PUFFS_MSG_ENQUEUEWAIT2(pmp, park_readlink, vp->v_data, NULL, error);
1.102     pooka    2134:        error = checkerr(pmp, error, __func__);
1.1       pooka    2135:        if (error)
1.107     pooka    2136:                goto out;
1.1       pooka    2137:
1.51      pooka    2138:        /* bad bad user file server */
1.107     pooka    2139:        if (readlink_msg->pvnr_linklen > linklen) {
1.114     pooka    2140:                puffs_senderr(pmp, PUFFS_ERR_READLINK, E2BIG,
1.102     pooka    2141:                    "linklen too big", VPTOPNC(ap->a_vp));
1.107     pooka    2142:                error = EPROTO;
                   2143:                goto out;
1.100     pooka    2144:        }
1.51      pooka    2145:
1.107     pooka    2146:        error = uiomove(&readlink_msg->pvnr_link, readlink_msg->pvnr_linklen,
1.1       pooka    2147:            ap->a_uio);
1.107     pooka    2148:  out:
                   2149:        PUFFS_MSG_RELEASE(readlink);
                   2150:        return error;
1.1       pooka    2151: }
                   2152:
                   2153: int
1.123     pooka    2154: puffs_vnop_rename(void *v)
1.1       pooka    2155: {
                   2156:        struct vop_rename_args /* {
                   2157:                const struct vnodeop_desc *a_desc;
                   2158:                struct vnode *a_fdvp;
                   2159:                struct vnode *a_fvp;
                   2160:                struct componentname *a_fcnp;
                   2161:                struct vnode *a_tdvp;
                   2162:                struct vnode *a_tvp;
                   2163:                struct componentname *a_tcnp;
1.129     christos 2164:        } */ *ap = v;
1.107     pooka    2165:        PUFFS_MSG_VARS(vn, rename);
1.140     pooka    2166:        struct vnode *fdvp = ap->a_fdvp, *fvp = ap->a_fvp;
                   2167:        struct vnode *tdvp = ap->a_tdvp, *tvp = ap->a_tvp;
1.117     pooka    2168:        struct puffs_node *fpn = ap->a_fvp->v_data;
1.114     pooka    2169:        struct puffs_mount *pmp = MPTOPUFFSMP(fdvp->v_mount);
1.1       pooka    2170:        int error;
1.140     pooka    2171:        bool doabort = true;
1.1       pooka    2172:
1.140     pooka    2173:        if ((fvp->v_mount != tdvp->v_mount) ||
                   2174:            (tvp && (fvp->v_mount != tvp->v_mount))) {
1.79      pooka    2175:                ERROUT(EXDEV);
1.140     pooka    2176:        }
1.1       pooka    2177:
1.107     pooka    2178:        PUFFS_MSG_ALLOC(vn, rename);
1.140     pooka    2179:        rename_msg->pvnr_cookie_src = VPTOPNC(fvp);
                   2180:        rename_msg->pvnr_cookie_targdir = VPTOPNC(tdvp);
                   2181:        if (tvp)
                   2182:                rename_msg->pvnr_cookie_targ = VPTOPNC(tvp);
1.1       pooka    2183:        else
1.107     pooka    2184:                rename_msg->pvnr_cookie_targ = NULL;
1.122     pooka    2185:        puffs_makecn(&rename_msg->pvnr_cn_src, &rename_msg->pvnr_cn_src_cred,
1.83      pooka    2186:            ap->a_fcnp, PUFFS_USE_FULLPNBUF(pmp));
1.122     pooka    2187:        puffs_makecn(&rename_msg->pvnr_cn_targ, &rename_msg->pvnr_cn_targ_cred,
1.83      pooka    2188:            ap->a_tcnp, PUFFS_USE_FULLPNBUF(pmp));
1.114     pooka    2189:        puffs_msg_setinfo(park_rename, PUFFSOP_VN,
                   2190:            PUFFS_VN_RENAME, VPTOPNC(fdvp));
1.1       pooka    2191:
1.114     pooka    2192:        PUFFS_MSG_ENQUEUEWAIT2(pmp, park_rename, fdvp->v_data, NULL, error);
1.140     pooka    2193:        doabort = false;
                   2194:        PUFFS_MSG_RELEASE(rename);
1.102     pooka    2195:        error = checkerr(pmp, error, __func__);
1.1       pooka    2196:
1.54      pooka    2197:        /*
                   2198:         * XXX: stay in touch with the cache.  I don't like this, but
                   2199:         * don't have a better solution either.  See also puffs_link().
                   2200:         */
1.174     manu     2201:        if (error == 0) {
1.117     pooka    2202:                puffs_updatenode(fpn, PUFFS_UPDATECTIME, 0);
1.185     manu     2203:                puffs_updatenode(VPTOPP(fdvp),
                   2204:                                 PUFFS_UPDATECTIME|PUFFS_UPDATEMTIME, 0);
                   2205:                if (fdvp != tdvp)
                   2206:                        puffs_updatenode(VPTOPP(tdvp),
                   2207:                                         PUFFS_UPDATECTIME|PUFFS_UPDATEMTIME,
                   2208:                                         0);
1.54      pooka    2209:
1.174     manu     2210:                if (PUFFS_USE_DOTDOTCACHE(pmp) &&
                   2211:                    (VPTOPP(fvp)->pn_parent != tdvp))
                   2212:                        update_parent(fvp, tdvp);
                   2213:        }
                   2214:
                   2215:
1.1       pooka    2216:  out:
1.140     pooka    2217:        if (doabort)
                   2218:                VOP_ABORTOP(tdvp, ap->a_tcnp);
                   2219:        if (tvp != NULL)
                   2220:                vput(tvp);
                   2221:        if (tdvp == tvp)
                   2222:                vrele(tdvp);
1.28      pooka    2223:        else
1.140     pooka    2224:                vput(tdvp);
1.1       pooka    2225:
1.140     pooka    2226:        if (doabort)
                   2227:                VOP_ABORTOP(fdvp, ap->a_fcnp);
                   2228:        vrele(fdvp);
                   2229:        vrele(fvp);
1.1       pooka    2230:
                   2231:        return error;
                   2232: }
                   2233:
1.79      pooka    2234: #define RWARGS(cont, iofl, move, offset, creds)                                \
                   2235:        (cont)->pvnr_ioflag = (iofl);                                   \
                   2236:        (cont)->pvnr_resid = (move);                                    \
                   2237:        (cont)->pvnr_offset = (offset);                                 \
                   2238:        puffs_credcvt(&(cont)->pvnr_cred, creds)
                   2239:
1.1       pooka    2240: int
1.123     pooka    2241: puffs_vnop_read(void *v)
1.1       pooka    2242: {
                   2243:        struct vop_read_args /* {
                   2244:                const struct vnodeop_desc *a_desc;
                   2245:                struct vnode *a_vp;
                   2246:                struct uio *a_uio;
                   2247:                int a_ioflag;
                   2248:                kauth_cred_t a_cred;
                   2249:        } */ *ap = v;
1.107     pooka    2250:        PUFFS_MSG_VARS(vn, read);
                   2251:        struct vnode *vp = ap->a_vp;
1.183     manu     2252:        struct puffs_node *pn = VPTOPP(vp);
1.107     pooka    2253:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
                   2254:        struct uio *uio = ap->a_uio;
1.1       pooka    2255:        size_t tomove, argsize;
1.8       pooka    2256:        vsize_t bytelen;
1.131     pooka    2257:        int error;
1.1       pooka    2258:
1.107     pooka    2259:        read_msg = NULL;
1.8       pooka    2260:        error = 0;
1.1       pooka    2261:
1.8       pooka    2262:        /* std sanity */
                   2263:        if (uio->uio_resid == 0)
                   2264:                return 0;
                   2265:        if (uio->uio_offset < 0)
1.186     manu     2266:                return EFBIG;
1.1       pooka    2267:
1.199     manu     2268:        /*
                   2269:         * On the case of reading empty files and (vp->v_size != 0) below:
                   2270:         * some filesystems (hint: FUSE and distributed filesystems) still
                   2271:         * expect to get the READ in order to update atime. Reading through
                   2272:         * the case filters empty files, therefore we prefer to bypass the
                   2273:         * cache here.
                   2274:         */
1.183     manu     2275:        if (vp->v_type == VREG &&
                   2276:            PUFFS_USE_PAGECACHE(pmp) &&
1.199     manu     2277:            !(pn->pn_stat & PNODE_RDIRECT) &&
                   2278:            (vp->v_size != 0)) {
1.8       pooka    2279:                const int advice = IO_ADV_DECODE(ap->a_ioflag);
1.1       pooka    2280:
1.8       pooka    2281:                while (uio->uio_resid > 0) {
1.164     jakllsch 2282:                        if (vp->v_size <= uio->uio_offset) {
                   2283:                                break;
                   2284:                        }
1.8       pooka    2285:                        bytelen = MIN(uio->uio_resid,
                   2286:                            vp->v_size - uio->uio_offset);
                   2287:                        if (bytelen == 0)
                   2288:                                break;
                   2289:
1.131     pooka    2290:                        error = ubc_uiomove(&vp->v_uobj, uio, bytelen, advice,
                   2291:                            UBC_READ | UBC_PARTIALOK | UBC_UNMAP_FLAG(vp));
1.8       pooka    2292:                        if (error)
                   2293:                                break;
1.1       pooka    2294:                }
                   2295:
1.8       pooka    2296:                if ((vp->v_mount->mnt_flag & MNT_NOATIME) == 0)
1.117     pooka    2297:                        puffs_updatenode(VPTOPP(vp), PUFFS_UPDATEATIME, 0);
1.8       pooka    2298:        } else {
1.1       pooka    2299:                /*
1.15      pooka    2300:                 * in case it's not a regular file or we're operating
                   2301:                 * uncached, do read in the old-fashioned style,
                   2302:                 * i.e. explicit read operations
1.1       pooka    2303:                 */
                   2304:
                   2305:                tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
1.107     pooka    2306:                argsize = sizeof(struct puffs_vnmsg_read);
                   2307:                puffs_msgmem_alloc(argsize + tomove, &park_read,
1.125     pooka    2308:                    (void *)&read_msg, 1);
1.8       pooka    2309:
                   2310:                error = 0;
                   2311:                while (uio->uio_resid > 0) {
1.79      pooka    2312:                        tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
1.113     pooka    2313:                        memset(read_msg, 0, argsize); /* XXX: touser KASSERT */
1.107     pooka    2314:                        RWARGS(read_msg, ap->a_ioflag, tomove,
1.79      pooka    2315:                            uio->uio_offset, ap->a_cred);
1.114     pooka    2316:                        puffs_msg_setinfo(park_read, PUFFSOP_VN,
                   2317:                            PUFFS_VN_READ, VPTOPNC(vp));
                   2318:                        puffs_msg_setdelta(park_read, tomove);
1.8       pooka    2319:
1.114     pooka    2320:                        PUFFS_MSG_ENQUEUEWAIT2(pmp, park_read, vp->v_data,
                   2321:                            NULL, error);
1.102     pooka    2322:                        error = checkerr(pmp, error, __func__);
1.8       pooka    2323:                        if (error)
                   2324:                                break;
                   2325:
1.107     pooka    2326:                        if (read_msg->pvnr_resid > tomove) {
1.114     pooka    2327:                                puffs_senderr(pmp, PUFFS_ERR_READ,
1.102     pooka    2328:                                    E2BIG, "resid grew", VPTOPNC(ap->a_vp));
1.100     pooka    2329:                                error = EPROTO;
1.8       pooka    2330:                                break;
                   2331:                        }
                   2332:
1.107     pooka    2333:                        error = uiomove(read_msg->pvnr_data,
                   2334:                            tomove - read_msg->pvnr_resid, uio);
1.8       pooka    2335:
                   2336:                        /*
                   2337:                         * in case the file is out of juice, resid from
                   2338:                         * userspace is != 0.  and the error-case is
                   2339:                         * quite obvious
                   2340:                         */
1.107     pooka    2341:                        if (error || read_msg->pvnr_resid)
1.8       pooka    2342:                                break;
                   2343:                }
1.107     pooka    2344:
                   2345:                puffs_msgmem_release(park_read);
1.1       pooka    2346:        }
                   2347:
                   2348:        return error;
                   2349: }
                   2350:
1.79      pooka    2351: /*
                   2352:  * XXX: in case of a failure, this leaves uio in a bad state.
                   2353:  * We could theoretically copy the uio and iovecs and "replay"
                   2354:  * them the right amount after the userspace trip, but don't
                   2355:  * bother for now.
                   2356:  */
1.1       pooka    2357: int
1.123     pooka    2358: puffs_vnop_write(void *v)
1.1       pooka    2359: {
                   2360:        struct vop_write_args /* {
                   2361:                const struct vnodeop_desc *a_desc;
                   2362:                struct vnode *a_vp;
                   2363:                struct uio *a_uio;
                   2364:                int a_ioflag;
                   2365:                kauth_cred_t a_cred;
1.73      yamt     2366:        } */ *ap = v;
1.107     pooka    2367:        PUFFS_MSG_VARS(vn, write);
                   2368:        struct vnode *vp = ap->a_vp;
1.155     manu     2369:        struct puffs_node *pn = VPTOPP(vp);
1.107     pooka    2370:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
                   2371:        struct uio *uio = ap->a_uio;
1.1       pooka    2372:        size_t tomove, argsize;
1.8       pooka    2373:        off_t oldoff, newoff, origoff;
                   2374:        vsize_t bytelen;
1.15      pooka    2375:        int error, uflags;
1.50      pooka    2376:        int ubcflags;
1.1       pooka    2377:
1.8       pooka    2378:        error = uflags = 0;
1.107     pooka    2379:        write_msg = NULL;
1.11      pooka    2380:
1.186     manu     2381:        /* std sanity */
                   2382:        if (uio->uio_resid == 0)
                   2383:                return 0;
                   2384:        if (uio->uio_offset < 0)
                   2385:                return EFBIG;
                   2386:
1.155     manu     2387:        mutex_enter(&pn->pn_sizemtx);
                   2388:
1.198     manu     2389:        /*
                   2390:         * userspace *should* be allowed to control this,
                   2391:         * but with UBC it's a bit unclear how to handle it
                   2392:         */
                   2393:        if (ap->a_ioflag & IO_APPEND)
                   2394:                uio->uio_offset = vp->v_size;
                   2395:
                   2396:        origoff = uio->uio_offset;
                   2397:
1.183     manu     2398:        if (vp->v_type == VREG &&
                   2399:            PUFFS_USE_PAGECACHE(pmp) &&
                   2400:            !(pn->pn_stat & PNODE_WDIRECT)) {
1.131     pooka    2401:                ubcflags = UBC_WRITE | UBC_PARTIALOK | UBC_UNMAP_FLAG(vp);
1.12      pooka    2402:
1.8       pooka    2403:                while (uio->uio_resid > 0) {
                   2404:                        oldoff = uio->uio_offset;
                   2405:                        bytelen = uio->uio_resid;
                   2406:
1.74      yamt     2407:                        newoff = oldoff + bytelen;
                   2408:                        if (vp->v_size < newoff) {
                   2409:                                uvm_vnp_setwritesize(vp, newoff);
                   2410:                        }
                   2411:                        error = ubc_uiomove(&vp->v_uobj, uio, bytelen,
1.93      yamt     2412:                            UVM_ADV_RANDOM, ubcflags);
1.8       pooka    2413:
                   2414:                        /*
1.74      yamt     2415:                         * In case of a ubc_uiomove() error,
1.64      pooka    2416:                         * opt to not extend the file at all and
                   2417:                         * return an error.  Otherwise, if we attempt
                   2418:                         * to clear the memory we couldn't fault to,
                   2419:                         * we might generate a kernel page fault.
1.8       pooka    2420:                         */
1.74      yamt     2421:                        if (vp->v_size < newoff) {
                   2422:                                if (error == 0) {
                   2423:                                        uflags |= PUFFS_UPDATESIZE;
                   2424:                                        uvm_vnp_setsize(vp, newoff);
                   2425:                                } else {
                   2426:                                        uvm_vnp_setwritesize(vp, vp->v_size);
                   2427:                                }
1.8       pooka    2428:                        }
                   2429:                        if (error)
                   2430:                                break;
                   2431:
1.50      pooka    2432:                        /*
                   2433:                         * If we're writing large files, flush to file server
                   2434:                         * every 64k.  Otherwise we can very easily exhaust
                   2435:                         * kernel and user memory, as the file server cannot
                   2436:                         * really keep up with our writing speed.
                   2437:                         *
                   2438:                         * Note: this does *NOT* honor MNT_ASYNC, because
                   2439:                         * that gives userland too much say in the kernel.
                   2440:                         */
                   2441:                        if (oldoff >> 16 != uio->uio_offset >> 16) {
1.153     rmind    2442:                                mutex_enter(vp->v_interlock);
1.8       pooka    2443:                                error = VOP_PUTPAGES(vp, oldoff & ~0xffff,
1.50      pooka    2444:                                    uio->uio_offset & ~0xffff,
                   2445:                                    PGO_CLEANIT | PGO_SYNCIO);
1.8       pooka    2446:                                if (error)
                   2447:                                        break;
                   2448:                        }
1.1       pooka    2449:                }
1.8       pooka    2450:
1.62      pooka    2451:                /* synchronous I/O? */
1.15      pooka    2452:                if (error == 0 && ap->a_ioflag & IO_SYNC) {
1.153     rmind    2453:                        mutex_enter(vp->v_interlock);
1.8       pooka    2454:                        error = VOP_PUTPAGES(vp, trunc_page(origoff),
1.15      pooka    2455:                            round_page(uio->uio_offset),
                   2456:                            PGO_CLEANIT | PGO_SYNCIO);
1.62      pooka    2457:
1.97      pooka    2458:                /* write through page cache? */
1.62      pooka    2459:                } else if (error == 0 && pmp->pmp_flags & PUFFS_KFLAG_WTCACHE) {
1.153     rmind    2460:                        mutex_enter(vp->v_interlock);
1.62      pooka    2461:                        error = VOP_PUTPAGES(vp, trunc_page(origoff),
                   2462:                            round_page(uio->uio_offset), PGO_CLEANIT);
1.1       pooka    2463:                }
1.8       pooka    2464:        } else {
1.19      pooka    2465:                /* tomove is non-increasing */
1.1       pooka    2466:                tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
1.107     pooka    2467:                argsize = sizeof(struct puffs_vnmsg_write) + tomove;
1.125     pooka    2468:                puffs_msgmem_alloc(argsize, &park_write, (void *)&write_msg,1);
1.8       pooka    2469:
                   2470:                while (uio->uio_resid > 0) {
1.79      pooka    2471:                        /* move data to buffer */
                   2472:                        tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
1.113     pooka    2473:                        memset(write_msg, 0, argsize); /* XXX: touser KASSERT */
1.107     pooka    2474:                        RWARGS(write_msg, ap->a_ioflag, tomove,
1.79      pooka    2475:                            uio->uio_offset, ap->a_cred);
1.107     pooka    2476:                        error = uiomove(write_msg->pvnr_data, tomove, uio);
1.8       pooka    2477:                        if (error)
                   2478:                                break;
                   2479:
1.79      pooka    2480:                        /* move buffer to userspace */
1.114     pooka    2481:                        puffs_msg_setinfo(park_write, PUFFSOP_VN,
                   2482:                            PUFFS_VN_WRITE, VPTOPNC(vp));
                   2483:                        PUFFS_MSG_ENQUEUEWAIT2(pmp, park_write, vp->v_data,
                   2484:                            NULL, error);
1.102     pooka    2485:                        error = checkerr(pmp, error, __func__);
1.79      pooka    2486:                        if (error)
1.8       pooka    2487:                                break;
1.79      pooka    2488:
1.107     pooka    2489:                        if (write_msg->pvnr_resid > tomove) {
1.114     pooka    2490:                                puffs_senderr(pmp, PUFFS_ERR_WRITE,
1.102     pooka    2491:                                    E2BIG, "resid grew", VPTOPNC(ap->a_vp));
1.100     pooka    2492:                                error = EPROTO;
1.8       pooka    2493:                                break;
                   2494:                        }
                   2495:
                   2496:                        /* adjust file size */
1.186     manu     2497:                        if (vp->v_size < uio->uio_offset) {
                   2498:                                uflags |= PUFFS_UPDATESIZE;
1.20      pooka    2499:                                uvm_vnp_setsize(vp, uio->uio_offset);
1.186     manu     2500:                        }
1.8       pooka    2501:
                   2502:                        /* didn't move everything?  bad userspace.  bail */
1.107     pooka    2503:                        if (write_msg->pvnr_resid != 0) {
1.8       pooka    2504:                                error = EIO;
                   2505:                                break;
                   2506:                        }
                   2507:                }
1.107     pooka    2508:                puffs_msgmem_release(park_write);
1.198     manu     2509:
                   2510:                /*
                   2511:                 * Direct I/O on write but not on read: we must
                   2512:                 * invlidate the written pages so that we read
                   2513:                 * the written data and not the stalled cache.
                   2514:                 */
                   2515:                if ((error == 0) &&
                   2516:                    (vp->v_type == VREG) && PUFFS_USE_PAGECACHE(pmp) &&
                   2517:                    (pn->pn_stat & PNODE_WDIRECT) &&
                   2518:                    !(pn->pn_stat & PNODE_RDIRECT)) {
                   2519:                        voff_t off_lo = trunc_page(origoff);
                   2520:                        voff_t off_hi = round_page(uio->uio_offset);
                   2521:
                   2522:                        mutex_enter(vp->v_uobj.vmobjlock);
                   2523:                        error = VOP_PUTPAGES(vp, off_lo, off_hi, PGO_FREE);
                   2524:                }
1.1       pooka    2525:        }
                   2526:
1.186     manu     2527:        if (vp->v_mount->mnt_flag & MNT_RELATIME)
                   2528:                uflags |= PUFFS_UPDATEATIME;
                   2529:        uflags |= PUFFS_UPDATECTIME;
                   2530:        uflags |= PUFFS_UPDATEMTIME;
                   2531:        puffs_updatenode(VPTOPP(vp), uflags, vp->v_size);
                   2532:
1.201     manu     2533:        /*
                   2534:         * If we do not use meta flush, we need to update the
                   2535:         * filesystem now, otherwise we will get a stale value
                   2536:         * on the next GETATTR
                   2537:         */
                   2538:        if (!PUFFS_USE_METAFLUSH(pmp) && (uflags & PUFFS_UPDATESIZE)) {
                   2539:                struct vattr va;
                   2540:                int ret;
                   2541:
                   2542:                vattr_null(&va);
                   2543:                va.va_size = vp->v_size;
                   2544:                ret = dosetattr(vp, &va, FSCRED, 0);
                   2545:                if (ret) {
1.202     christos 2546:                        DPRINTF(("dosetattr set size to %jd failed: %d\n",
                   2547:                            (intmax_t)vp->v_size, ret));
1.201     manu     2548:                }
                   2549:        }
1.155     manu     2550:        mutex_exit(&pn->pn_sizemtx);
1.1       pooka    2551:        return error;
                   2552: }
                   2553:
                   2554: int
1.196     manu     2555: puffs_vnop_fallocate(void *v)
                   2556: {
                   2557:        struct vop_fallocate_args /* {
                   2558:                const struct vnodeop_desc *a_desc;
                   2559:                struct vnode *a_vp;
                   2560:                off_t a_pos;
                   2561:                off_t a_len;
                   2562:        } */ *ap = v;
                   2563:        struct vnode *vp = ap->a_vp;
                   2564:        struct puffs_node *pn = VPTOPP(vp);
                   2565:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
                   2566:        PUFFS_MSG_VARS(vn, fallocate);
                   2567:        int error;
                   2568:
                   2569:        mutex_enter(&pn->pn_sizemtx);
                   2570:
                   2571:        PUFFS_MSG_ALLOC(vn, fallocate);
                   2572:        fallocate_msg->pvnr_off = ap->a_pos;
                   2573:        fallocate_msg->pvnr_len = ap->a_len;
                   2574:        puffs_msg_setinfo(park_fallocate, PUFFSOP_VN,
                   2575:            PUFFS_VN_FALLOCATE, VPTOPNC(vp));
                   2576:
                   2577:        PUFFS_MSG_ENQUEUEWAIT2(pmp, park_fallocate, vp->v_data, NULL, error);
                   2578:        error = checkerr(pmp, error, __func__);
                   2579:        PUFFS_MSG_RELEASE(fallocate);
                   2580:
                   2581:        switch (error) {
                   2582:        case 0:
                   2583:                break;
                   2584:        case EAGAIN:
                   2585:                error = EIO;
                   2586:                /* FALLTHROUGH */
                   2587:        default:
                   2588:                goto out;
                   2589:        }
                   2590:
                   2591:        if (ap->a_pos + ap->a_len > vp->v_size) {
                   2592:                uvm_vnp_setsize(vp, ap->a_pos + ap->a_len);
                   2593:                puffs_updatenode(pn, PUFFS_UPDATESIZE, vp->v_size);
                   2594:        }
                   2595: out:
                   2596:        mutex_exit(&pn->pn_sizemtx);
                   2597:
                   2598:        return error;
                   2599: }
                   2600:
                   2601: int
                   2602: puffs_vnop_fdiscard(void *v)
                   2603: {
                   2604:        struct vop_fdiscard_args /* {
                   2605:                const struct vnodeop_desc *a_desc;
                   2606:                struct vnode *a_vp;
                   2607:                off_t a_pos;
                   2608:                off_t a_len;
                   2609:        } */ *ap = v;
                   2610:        struct vnode *vp = ap->a_vp;
                   2611:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
                   2612:        PUFFS_MSG_VARS(vn, fdiscard);
                   2613:        int error;
                   2614:
                   2615:        PUFFS_MSG_ALLOC(vn, fdiscard);
                   2616:        fdiscard_msg->pvnr_off = ap->a_pos;
                   2617:        fdiscard_msg->pvnr_len = ap->a_len;
                   2618:        puffs_msg_setinfo(park_fdiscard, PUFFSOP_VN,
                   2619:            PUFFS_VN_FALLOCATE, VPTOPNC(vp));
                   2620:
                   2621:        PUFFS_MSG_ENQUEUEWAIT2(pmp, park_fdiscard, vp->v_data, NULL, error);
                   2622:        error = checkerr(pmp, error, __func__);
                   2623:        PUFFS_MSG_RELEASE(fdiscard);
                   2624:
                   2625:        return error;
                   2626: }
                   2627:
                   2628: int
1.123     pooka    2629: puffs_vnop_print(void *v)
1.1       pooka    2630: {
                   2631:        struct vop_print_args /* {
                   2632:                struct vnode *a_vp;
                   2633:        } */ *ap = v;
1.107     pooka    2634:        PUFFS_MSG_VARS(vn, print);
1.1       pooka    2635:        struct vnode *vp = ap->a_vp;
1.107     pooka    2636:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.2       pooka    2637:        struct puffs_node *pn = vp->v_data;
1.1       pooka    2638:
                   2639:        /* kernel portion */
1.144     pooka    2640:        printf("tag VT_PUFFS, vnode %p, puffs node: %p,\n"
                   2641:            "\tuserspace cookie: %p", vp, pn, pn->pn_cookie);
1.6       pooka    2642:        if (vp->v_type == VFIFO)
1.144     pooka    2643:                VOCALL(fifo_vnodeop_p, VOFFSET(vop_print), v);
1.143     pooka    2644:        printf("\n");
1.1       pooka    2645:
                   2646:        /* userspace portion */
1.107     pooka    2647:        if (EXISTSOP(pmp, PRINT)) {
                   2648:                PUFFS_MSG_ALLOC(vn, print);
1.114     pooka    2649:                puffs_msg_setinfo(park_print, PUFFSOP_VN,
                   2650:                    PUFFS_VN_PRINT, VPTOPNC(vp));
1.177     christos 2651:                PUFFS_MSG_ENQUEUEWAIT2_NOERROR(pmp, park_print, vp->v_data,
                   2652:                    NULL);
1.107     pooka    2653:                PUFFS_MSG_RELEASE(print);
                   2654:        }
1.17      pooka    2655:
                   2656:        return 0;
1.1       pooka    2657: }
                   2658:
                   2659: int
1.123     pooka    2660: puffs_vnop_pathconf(void *v)
1.1       pooka    2661: {
                   2662:        struct vop_pathconf_args /* {
                   2663:                const struct vnodeop_desc *a_desc;
                   2664:                struct vnode *a_vp;
                   2665:                int a_name;
                   2666:                register_t *a_retval;
                   2667:        } */ *ap = v;
1.107     pooka    2668:        PUFFS_MSG_VARS(vn, pathconf);
1.102     pooka    2669:        struct vnode *vp = ap->a_vp;
                   2670:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.1       pooka    2671:        int error;
                   2672:
1.107     pooka    2673:        PUFFS_MSG_ALLOC(vn, pathconf);
                   2674:        pathconf_msg->pvnr_name = ap->a_name;
1.114     pooka    2675:        puffs_msg_setinfo(park_pathconf, PUFFSOP_VN,
                   2676:            PUFFS_VN_PATHCONF, VPTOPNC(vp));
                   2677:        PUFFS_MSG_ENQUEUEWAIT2(pmp, park_pathconf, vp->v_data, NULL, error);
1.102     pooka    2678:        error = checkerr(pmp, error, __func__);
1.107     pooka    2679:        if (!error)
                   2680:                *ap->a_retval = pathconf_msg->pvnr_retval;
                   2681:        PUFFS_MSG_RELEASE(pathconf);
1.1       pooka    2682:
1.107     pooka    2683:        return error;
1.1       pooka    2684: }
                   2685:
                   2686: int
1.123     pooka    2687: puffs_vnop_advlock(void *v)
1.1       pooka    2688: {
                   2689:        struct vop_advlock_args /* {
                   2690:                const struct vnodeop_desc *a_desc;
                   2691:                struct vnode *a_vp;
                   2692:                void *a_id;
                   2693:                int a_op;
                   2694:                struct flock *a_fl;
                   2695:                int a_flags;
                   2696:        } */ *ap = v;
1.151     manu     2697:        PUFFS_MSG_VARS(vn, advlock);
1.102     pooka    2698:        struct vnode *vp = ap->a_vp;
1.150     kefren   2699:        struct puffs_node *pn = VPTOPP(vp);
1.151     manu     2700:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
                   2701:        int error;
                   2702:
                   2703:        if (!EXISTSOP(pmp, ADVLOCK))
1.204     msaitoh  2704:                return lf_advlock(ap, &pn->pn_lockf, vp->v_size);
1.151     manu     2705:
                   2706:        PUFFS_MSG_ALLOC(vn, advlock);
                   2707:        (void)memcpy(&advlock_msg->pvnr_fl, ap->a_fl,
                   2708:                     sizeof(advlock_msg->pvnr_fl));
                   2709:        advlock_msg->pvnr_id = ap->a_id;
                   2710:        advlock_msg->pvnr_op = ap->a_op;
                   2711:        advlock_msg->pvnr_flags = ap->a_flags;
                   2712:        puffs_msg_setinfo(park_advlock, PUFFSOP_VN,
                   2713:            PUFFS_VN_ADVLOCK, VPTOPNC(vp));
                   2714:        PUFFS_MSG_ENQUEUEWAIT2(pmp, park_advlock, vp->v_data, NULL, error);
                   2715:        error = checkerr(pmp, error, __func__);
                   2716:        PUFFS_MSG_RELEASE(advlock);
1.1       pooka    2717:
1.151     manu     2718:        return error;
1.1       pooka    2719: }
1.79      pooka    2720:
1.136     pooka    2721: int
                   2722: puffs_vnop_abortop(void *v)
                   2723: {
                   2724:        struct vop_abortop_args /* {
                   2725:                struct vnode *a_dvp;
                   2726:                struct componentname *a_cnp;
                   2727:        }; */ *ap = v;
                   2728:        PUFFS_MSG_VARS(vn, abortop);
                   2729:        struct vnode *dvp = ap->a_dvp;
                   2730:        struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount);
                   2731:        struct componentname *cnp = ap->a_cnp;
                   2732:
                   2733:        if (EXISTSOP(pmp, ABORTOP)) {
                   2734:                PUFFS_MSG_ALLOC(vn, abortop);
                   2735:                puffs_makecn(&abortop_msg->pvnr_cn, &abortop_msg->pvnr_cn_cred,
                   2736:                    cnp, PUFFS_USE_FULLPNBUF(pmp));
1.139     pooka    2737:                puffs_msg_setfaf(park_abortop);
1.136     pooka    2738:                puffs_msg_setinfo(park_abortop, PUFFSOP_VN,
                   2739:                    PUFFS_VN_ABORTOP, VPTOPNC(dvp));
                   2740:
1.139     pooka    2741:                puffs_msg_enqueue(pmp, park_abortop);
1.136     pooka    2742:                PUFFS_MSG_RELEASE(abortop);
                   2743:        }
                   2744:
                   2745:        return genfs_abortop(v);
                   2746: }
                   2747:
1.79      pooka    2748: #define BIOASYNC(bp) (bp->b_flags & B_ASYNC)
                   2749:
1.8       pooka    2750: /*
                   2751:  * This maps itself to PUFFS_VN_READ/WRITE for data transfer.
                   2752:  */
                   2753: int
1.123     pooka    2754: puffs_vnop_strategy(void *v)
1.8       pooka    2755: {
                   2756:        struct vop_strategy_args /* {
                   2757:                const struct vnodeop_desc *a_desc;
                   2758:                struct vnode *a_vp;
                   2759:                struct buf *a_bp;
                   2760:        } */ *ap = v;
1.107     pooka    2761:        PUFFS_MSG_VARS(vn, rw);
1.35      pooka    2762:        struct vnode *vp = ap->a_vp;
1.107     pooka    2763:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.38      pooka    2764:        struct puffs_node *pn;
1.8       pooka    2765:        struct buf *bp;
                   2766:        size_t argsize;
1.14      pooka    2767:        size_t tomove, moved;
1.159     manu     2768:        int error, dofaf, cansleep, dobiodone;
1.8       pooka    2769:
1.35      pooka    2770:        pmp = MPTOPUFFSMP(vp->v_mount);
1.8       pooka    2771:        bp = ap->a_bp;
1.36      pooka    2772:        error = 0;
1.79      pooka    2773:        dofaf = 0;
1.159     manu     2774:        cansleep = 0;
1.38      pooka    2775:        pn = VPTOPP(vp);
1.107     pooka    2776:        park_rw = NULL; /* explicit */
1.115     pooka    2777:        dobiodone = 1;
1.38      pooka    2778:
1.119     pooka    2779:        if ((BUF_ISREAD(bp) && !EXISTSOP(pmp, READ))
                   2780:            || (BUF_ISWRITE(bp) && !EXISTSOP(pmp, WRITE)))
1.79      pooka    2781:                ERROUT(EOPNOTSUPP);
1.8       pooka    2782:
1.137     pooka    2783:        /*
                   2784:         * Short-circuit optimization: don't flush buffer in between
                   2785:         * VOP_INACTIVE and VOP_RECLAIM in case the node has no references.
                   2786:         */
                   2787:        if (pn->pn_stat & PNODE_DYING) {
                   2788:                KASSERT(BUF_ISWRITE(bp));
                   2789:                bp->b_resid = 0;
                   2790:                goto out;
                   2791:        }
                   2792:
1.8       pooka    2793: #ifdef DIAGNOSTIC
1.107     pooka    2794:        if (bp->b_bcount > pmp->pmp_msg_maxsize - PUFFS_MSGSTRUCT_MAX)
1.46      pooka    2795:                panic("puffs_strategy: wildly inappropriate buf bcount %d",
                   2796:                    bp->b_bcount);
1.8       pooka    2797: #endif
                   2798:
1.35      pooka    2799:        /*
1.41      pooka    2800:         * See explanation for the necessity of a FAF in puffs_fsync.
                   2801:         *
                   2802:         * Also, do FAF in case we're suspending.
                   2803:         * See puffs_vfsops.c:pageflush()
1.35      pooka    2804:         */
1.119     pooka    2805:        if (BUF_ISWRITE(bp)) {
1.153     rmind    2806:                mutex_enter(vp->v_interlock);
1.181     hannken  2807:                if (vdead_check(vp, VDEAD_NOWAIT) != 0)
1.79      pooka    2808:                        dofaf = 1;
1.138     pooka    2809:                if (pn->pn_stat & PNODE_FAF)
1.79      pooka    2810:                        dofaf = 1;
1.153     rmind    2811:                mutex_exit(vp->v_interlock);
1.35      pooka    2812:        }
                   2813:
1.159     manu     2814:        cansleep = (curlwp == uvm.pagedaemon_lwp || dofaf) ? 0 : 1;
                   2815:
1.160     manu     2816:        KASSERT(curlwp != uvm.pagedaemon_lwp || dofaf || BIOASYNC(bp));
1.45      pooka    2817:
1.79      pooka    2818:        /* allocate transport structure */
1.53      pooka    2819:        tomove = PUFFS_TOMOVE(bp->b_bcount, pmp);
1.107     pooka    2820:        argsize = sizeof(struct puffs_vnmsg_rw);
                   2821:        error = puffs_msgmem_alloc(argsize + tomove, &park_rw,
1.159     manu     2822:            (void *)&rw_msg, cansleep);
1.107     pooka    2823:        if (error)
                   2824:                goto out;
                   2825:        RWARGS(rw_msg, 0, tomove, bp->b_blkno << DEV_BSHIFT, FSCRED);
1.79      pooka    2826:
                   2827:        /* 2x2 cases: read/write, faf/nofaf */
1.119     pooka    2828:        if (BUF_ISREAD(bp)) {
1.114     pooka    2829:                puffs_msg_setinfo(park_rw, PUFFSOP_VN,
                   2830:                    PUFFS_VN_READ, VPTOPNC(vp));
                   2831:                puffs_msg_setdelta(park_rw, tomove);
1.115     pooka    2832:                if (BIOASYNC(bp)) {
1.114     pooka    2833:                        puffs_msg_setcall(park_rw,
                   2834:                            puffs_parkdone_asyncbioread, bp);
                   2835:                        puffs_msg_enqueue(pmp, park_rw);
1.115     pooka    2836:                        dobiodone = 0;
1.79      pooka    2837:                } else {
1.114     pooka    2838:                        PUFFS_MSG_ENQUEUEWAIT2(pmp, park_rw, vp->v_data,
                   2839:                            NULL, error);
1.102     pooka    2840:                        error = checkerr(pmp, error, __func__);
1.79      pooka    2841:                        if (error)
                   2842:                                goto out;
1.53      pooka    2843:
1.107     pooka    2844:                        if (rw_msg->pvnr_resid > tomove) {
1.114     pooka    2845:                                puffs_senderr(pmp, PUFFS_ERR_READ,
1.102     pooka    2846:                                    E2BIG, "resid grew", VPTOPNC(vp));
1.100     pooka    2847:                                ERROUT(EPROTO);
                   2848:                        }
1.14      pooka    2849:
1.107     pooka    2850:                        moved = tomove - rw_msg->pvnr_resid;
1.8       pooka    2851:
1.107     pooka    2852:                        (void)memcpy(bp->b_data, rw_msg->pvnr_data, moved);
1.79      pooka    2853:                        bp->b_resid = bp->b_bcount - moved;
1.14      pooka    2854:                }
1.8       pooka    2855:        } else {
1.114     pooka    2856:                puffs_msg_setinfo(park_rw, PUFFSOP_VN,
                   2857:                    PUFFS_VN_WRITE, VPTOPNC(vp));
1.54      pooka    2858:                /*
                   2859:                 * make pages read-only before we write them if we want
                   2860:                 * write caching info
                   2861:                 */
                   2862:                if (PUFFS_WCACHEINFO(pmp)) {
                   2863:                        struct uvm_object *uobj = &vp->v_uobj;
                   2864:                        int npages = (bp->b_bcount + PAGE_SIZE-1) >> PAGE_SHIFT;
                   2865:                        struct vm_page *vmp;
                   2866:                        int i;
                   2867:
                   2868:                        for (i = 0; i < npages; i++) {
                   2869:                                vmp= uvm_pageratop((vaddr_t)bp->b_data
                   2870:                                    + (i << PAGE_SHIFT));
                   2871:                                DPRINTF(("puffs_strategy: write-protecting "
                   2872:                                    "vp %p page %p, offset %" PRId64"\n",
                   2873:                                    vp, vmp, vmp->offset));
1.153     rmind    2874:                                mutex_enter(uobj->vmobjlock);
1.54      pooka    2875:                                vmp->flags |= PG_RDONLY;
                   2876:                                pmap_page_protect(vmp, VM_PROT_READ);
1.153     rmind    2877:                                mutex_exit(uobj->vmobjlock);
1.54      pooka    2878:                        }
                   2879:                }
                   2880:
1.107     pooka    2881:                (void)memcpy(&rw_msg->pvnr_data, bp->b_data, tomove);
1.115     pooka    2882:                if (dofaf) {
1.107     pooka    2883:                        puffs_msg_setfaf(park_rw);
1.115     pooka    2884:                } else if (BIOASYNC(bp)) {
                   2885:                        puffs_msg_setcall(park_rw,
                   2886:                            puffs_parkdone_asyncbiowrite, bp);
                   2887:                        dobiodone = 0;
                   2888:                }
                   2889:
1.114     pooka    2890:                PUFFS_MSG_ENQUEUEWAIT2(pmp, park_rw, vp->v_data, NULL, error);
1.107     pooka    2891:
1.115     pooka    2892:                if (dobiodone == 0)
                   2893:                        goto out;
                   2894:
1.112     pooka    2895:                error = checkerr(pmp, error, __func__);
                   2896:                if (error)
                   2897:                        goto out;
                   2898:
                   2899:                if (rw_msg->pvnr_resid > tomove) {
1.114     pooka    2900:                        puffs_senderr(pmp, PUFFS_ERR_WRITE,
1.112     pooka    2901:                            E2BIG, "resid grew", VPTOPNC(vp));
                   2902:                        ERROUT(EPROTO);
                   2903:                }
1.8       pooka    2904:
1.112     pooka    2905:                /*
                   2906:                 * FAF moved everything.  Frankly, we don't
                   2907:                 * really have a choice.
                   2908:                 */
                   2909:                if (dofaf && error == 0)
                   2910:                        moved = tomove;
                   2911:                else
1.107     pooka    2912:                        moved = tomove - rw_msg->pvnr_resid;
1.9       pooka    2913:
1.112     pooka    2914:                bp->b_resid = bp->b_bcount - moved;
                   2915:                if (bp->b_resid != 0) {
                   2916:                        ERROUT(EIO);
1.14      pooka    2917:                }
1.8       pooka    2918:        }
                   2919:
                   2920:  out:
1.107     pooka    2921:        if (park_rw)
                   2922:                puffs_msgmem_release(park_rw);
1.14      pooka    2923:
1.94      ad       2924:        if (error)
1.40      pooka    2925:                bp->b_error = error;
                   2926:
1.115     pooka    2927:        if (error || dobiodone)
1.53      pooka    2928:                biodone(bp);
1.79      pooka    2929:
1.8       pooka    2930:        return error;
                   2931: }
1.1       pooka    2932:
1.21      pooka    2933: int
1.123     pooka    2934: puffs_vnop_mmap(void *v)
1.21      pooka    2935: {
                   2936:        struct vop_mmap_args /* {
                   2937:                const struct vnodeop_desc *a_desc;
                   2938:                struct vnode *a_vp;
1.92      pooka    2939:                vm_prot_t a_prot;
1.21      pooka    2940:                kauth_cred_t a_cred;
                   2941:        } */ *ap = v;
1.107     pooka    2942:        PUFFS_MSG_VARS(vn, mmap);
                   2943:        struct vnode *vp = ap->a_vp;
                   2944:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.21      pooka    2945:        int error;
                   2946:
1.78      pooka    2947:        if (!PUFFS_USE_PAGECACHE(pmp))
1.21      pooka    2948:                return genfs_eopnotsupp(v);
                   2949:
                   2950:        if (EXISTSOP(pmp, MMAP)) {
1.107     pooka    2951:                PUFFS_MSG_ALLOC(vn, mmap);
                   2952:                mmap_msg->pvnr_prot = ap->a_prot;
                   2953:                puffs_credcvt(&mmap_msg->pvnr_cred, ap->a_cred);
1.114     pooka    2954:                puffs_msg_setinfo(park_mmap, PUFFSOP_VN,
                   2955:                    PUFFS_VN_MMAP, VPTOPNC(vp));
1.107     pooka    2956:
1.114     pooka    2957:                PUFFS_MSG_ENQUEUEWAIT2(pmp, park_mmap, vp->v_data, NULL, error);
1.102     pooka    2958:                error = checkerr(pmp, error, __func__);
1.107     pooka    2959:                PUFFS_MSG_RELEASE(mmap);
1.21      pooka    2960:        } else {
                   2961:                error = genfs_mmap(v);
                   2962:        }
                   2963:
                   2964:        return error;
                   2965: }
                   2966:
                   2967:
1.1       pooka    2968: /*
                   2969:  * The rest don't get a free trip to userspace and back, they
                   2970:  * have to stay within the kernel.
                   2971:  */
                   2972:
                   2973: /*
1.8       pooka    2974:  * bmap doesn't really make any sense for puffs, so just 1:1 map it.
                   2975:  * well, maybe somehow, somewhere, some day ....
                   2976:  */
                   2977: int
1.123     pooka    2978: puffs_vnop_bmap(void *v)
1.8       pooka    2979: {
                   2980:        struct vop_bmap_args /* {
                   2981:                const struct vnodeop_desc *a_desc;
                   2982:                struct vnode *a_vp;
                   2983:                daddr_t a_bn;
                   2984:                struct vnode **a_vpp;
                   2985:                daddr_t *a_bnp;
                   2986:                int *a_runp;
                   2987:        } */ *ap = v;
                   2988:        struct puffs_mount *pmp;
                   2989:
                   2990:        pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
                   2991:
                   2992:        if (ap->a_vpp)
                   2993:                *ap->a_vpp = ap->a_vp;
                   2994:        if (ap->a_bnp)
                   2995:                *ap->a_bnp = ap->a_bn;
                   2996:        if (ap->a_runp)
1.55      pooka    2997:                *ap->a_runp
1.107     pooka    2998:                    = (PUFFS_TOMOVE(pmp->pmp_msg_maxsize, pmp)>>DEV_BSHIFT) - 1;
1.8       pooka    2999:
                   3000:        return 0;
                   3001: }
                   3002:
1.54      pooka    3003: /*
                   3004:  * Handle getpages faults in puffs.  We let genfs_getpages() do most
                   3005:  * of the dirty work, but we come in this route to do accounting tasks.
                   3006:  * If the user server has specified functions for cache notifications
                   3007:  * about reads and/or writes, we record which type of operation we got,
                   3008:  * for which page range, and proceed to issue a FAF notification to the
                   3009:  * server about it.
                   3010:  */
                   3011: int
1.123     pooka    3012: puffs_vnop_getpages(void *v)
1.54      pooka    3013: {
                   3014:        struct vop_getpages_args /* {
                   3015:                const struct vnodeop_desc *a_desc;
                   3016:                struct vnode *a_vp;
                   3017:                voff_t a_offset;
                   3018:                struct vm_page **a_m;
                   3019:                int *a_count;
                   3020:                int a_centeridx;
                   3021:                vm_prot_t a_access_type;
                   3022:                int a_advice;
                   3023:                int a_flags;
                   3024:        } */ *ap = v;
                   3025:        struct puffs_mount *pmp;
1.90      pooka    3026:        struct puffs_node *pn;
1.54      pooka    3027:        struct vnode *vp;
                   3028:        struct vm_page **pgs;
                   3029:        struct puffs_cacheinfo *pcinfo = NULL;
                   3030:        struct puffs_cacherun *pcrun;
1.55      pooka    3031:        void *parkmem = NULL;
1.54      pooka    3032:        size_t runsizes;
                   3033:        int i, npages, si, streakon;
                   3034:        int error, locked, write;
                   3035:
                   3036:        pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
                   3037:        npages = *ap->a_count;
                   3038:        pgs = ap->a_m;
                   3039:        vp = ap->a_vp;
1.90      pooka    3040:        pn = vp->v_data;
1.54      pooka    3041:        locked = (ap->a_flags & PGO_LOCKED) != 0;
                   3042:        write = (ap->a_access_type & VM_PROT_WRITE) != 0;
                   3043:
                   3044:        /* ccg xnaht - gets Wuninitialized wrong */
                   3045:        pcrun = NULL;
                   3046:        runsizes = 0;
                   3047:
1.90      pooka    3048:        /*
                   3049:         * Check that we aren't trying to fault in pages which our file
                   3050:         * server doesn't know about.  This happens if we extend a file by
                   3051:         * skipping some pages and later try to fault in pages which
                   3052:         * are between pn_serversize and vp_size.  This check optimizes
                   3053:         * away the common case where a file is being extended.
                   3054:         */
                   3055:        if (ap->a_offset >= pn->pn_serversize && ap->a_offset < vp->v_size) {
                   3056:                struct vattr va;
                   3057:
                   3058:                /* try again later when we can block */
                   3059:                if (locked)
                   3060:                        ERROUT(EBUSY);
                   3061:
1.153     rmind    3062:                mutex_exit(vp->v_interlock);
1.90      pooka    3063:                vattr_null(&va);
                   3064:                va.va_size = vp->v_size;
1.123     pooka    3065:                error = dosetattr(vp, &va, FSCRED, 0);
1.90      pooka    3066:                if (error)
                   3067:                        ERROUT(error);
1.153     rmind    3068:                mutex_enter(vp->v_interlock);
1.90      pooka    3069:        }
                   3070:
1.54      pooka    3071:        if (write && PUFFS_WCACHEINFO(pmp)) {
1.107     pooka    3072: #ifdef notnowjohn
1.54      pooka    3073:                /* allocate worst-case memory */
                   3074:                runsizes = ((npages / 2) + 1) * sizeof(struct puffs_cacherun);
1.160     manu     3075:                KASSERT(curlwp != uvm.pagedaemon_lwp || locked);
1.132     tsutsui  3076:                pcinfo = kmem_zalloc(sizeof(struct puffs_cacheinfo) + runsize,
1.118     pooka    3077:                    locked ? KM_NOSLEEP : KM_SLEEP);
1.54      pooka    3078:
                   3079:                /*
                   3080:                 * can't block if we're locked and can't mess up caching
                   3081:                 * information for fs server.  so come back later, please
                   3082:                 */
1.79      pooka    3083:                if (pcinfo == NULL)
                   3084:                        ERROUT(ENOMEM);
1.54      pooka    3085:
1.57      pooka    3086:                parkmem = puffs_park_alloc(locked == 0);
1.79      pooka    3087:                if (parkmem == NULL)
                   3088:                        ERROUT(ENOMEM);
1.54      pooka    3089:
                   3090:                pcrun = pcinfo->pcache_runs;
1.107     pooka    3091: #else
                   3092:                (void)parkmem;
                   3093: #endif
1.54      pooka    3094:        }
                   3095:
                   3096:        error = genfs_getpages(v);
                   3097:        if (error)
                   3098:                goto out;
                   3099:
                   3100:        if (PUFFS_WCACHEINFO(pmp) == 0)
                   3101:                goto out;
                   3102:
                   3103:        /*
                   3104:         * Let's see whose fault it was and inform the user server of
                   3105:         * possibly read/written pages.  Map pages from read faults
                   3106:         * strictly read-only, since otherwise we might miss info on
                   3107:         * when the page is actually write-faulted to.
                   3108:         */
                   3109:        if (!locked)
1.153     rmind    3110:                mutex_enter(vp->v_uobj.vmobjlock);
1.54      pooka    3111:        for (i = 0, si = 0, streakon = 0; i < npages; i++) {
                   3112:                if (pgs[i] == NULL || pgs[i] == PGO_DONTCARE) {
                   3113:                        if (streakon && write) {
                   3114:                                streakon = 0;
                   3115:                                pcrun[si].pcache_runend
                   3116:                                    = trunc_page(pgs[i]->offset) + PAGE_MASK;
                   3117:                                si++;
                   3118:                        }
                   3119:                        continue;
                   3120:                }
                   3121:                if (streakon == 0 && write) {
                   3122:                        streakon = 1;
                   3123:                        pcrun[si].pcache_runstart = pgs[i]->offset;
                   3124:                }
                   3125:
                   3126:                if (!write)
                   3127:                        pgs[i]->flags |= PG_RDONLY;
                   3128:        }
                   3129:        /* was the last page part of our streak? */
                   3130:        if (streakon) {
                   3131:                pcrun[si].pcache_runend
                   3132:                    = trunc_page(pgs[i-1]->offset) + PAGE_MASK;
                   3133:                si++;
                   3134:        }
                   3135:        if (!locked)
1.153     rmind    3136:                mutex_exit(vp->v_uobj.vmobjlock);
1.54      pooka    3137:
                   3138:        KASSERT(si <= (npages / 2) + 1);
                   3139:
1.107     pooka    3140: #ifdef notnowjohn
1.54      pooka    3141:        /* send results to userspace */
                   3142:        if (write)
1.55      pooka    3143:                puffs_cacheop(pmp, parkmem, pcinfo,
1.54      pooka    3144:                    sizeof(struct puffs_cacheinfo) + runsizes, VPTOPNC(vp));
1.107     pooka    3145: #endif
1.54      pooka    3146:
                   3147:  out:
                   3148:        if (error) {
                   3149:                if (pcinfo != NULL)
1.118     pooka    3150:                        kmem_free(pcinfo,
                   3151:                            sizeof(struct puffs_cacheinfo) + runsizes);
1.107     pooka    3152: #ifdef notnowjohn
1.55      pooka    3153:                if (parkmem != NULL)
1.57      pooka    3154:                        puffs_park_release(parkmem, 1);
1.107     pooka    3155: #endif
1.54      pooka    3156:        }
                   3157:
                   3158:        return error;
                   3159: }
1.41      pooka    3160:
1.26      pooka    3161: /*
1.145     pooka    3162:  * Extended attribute support.
                   3163:  */
                   3164:
                   3165: int
                   3166: puffs_vnop_getextattr(void *v)
                   3167: {
                   3168:        struct vop_getextattr_args /*
                   3169:                struct vnode *a_vp;
                   3170:                int a_attrnamespace;
                   3171:                const char *a_name;
                   3172:                struct uio *a_uio;
                   3173:                size_t *a_size;
                   3174:                kauth_cred_t a_cred;
                   3175:        }; */ *ap = v;
                   3176:        PUFFS_MSG_VARS(vn, getextattr);
                   3177:        struct vnode *vp = ap->a_vp;
                   3178:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
                   3179:        int attrnamespace = ap->a_attrnamespace;
                   3180:        const char *name = ap->a_name;
                   3181:        struct uio *uio = ap->a_uio;
                   3182:        size_t *sizep = ap->a_size;
                   3183:        size_t tomove, resid;
                   3184:        int error;
                   3185:
                   3186:        if (uio)
                   3187:                resid = uio->uio_resid;
                   3188:        else
                   3189:                resid = 0;
                   3190:
                   3191:        tomove = PUFFS_TOMOVE(resid, pmp);
                   3192:        if (tomove != resid) {
                   3193:                error = E2BIG;
                   3194:                goto out;
                   3195:        }
                   3196:
                   3197:        puffs_msgmem_alloc(sizeof(struct puffs_vnmsg_getextattr) + tomove,
                   3198:            &park_getextattr, (void *)&getextattr_msg, 1);
                   3199:
                   3200:        getextattr_msg->pvnr_attrnamespace = attrnamespace;
                   3201:        strlcpy(getextattr_msg->pvnr_attrname, name,
                   3202:            sizeof(getextattr_msg->pvnr_attrname));
                   3203:        puffs_credcvt(&getextattr_msg->pvnr_cred, ap->a_cred);
                   3204:        if (sizep)
                   3205:                getextattr_msg->pvnr_datasize = 1;
                   3206:        getextattr_msg->pvnr_resid = tomove;
                   3207:
                   3208:        puffs_msg_setinfo(park_getextattr,
                   3209:            PUFFSOP_VN, PUFFS_VN_GETEXTATTR, VPTOPNC(vp));
                   3210:        puffs_msg_setdelta(park_getextattr, tomove);
                   3211:        PUFFS_MSG_ENQUEUEWAIT2(pmp, park_getextattr, vp->v_data, NULL, error);
                   3212:
                   3213:        error = checkerr(pmp, error, __func__);
                   3214:        if (error)
                   3215:                goto out;
                   3216:
                   3217:        resid = getextattr_msg->pvnr_resid;
                   3218:        if (resid > tomove) {
                   3219:                puffs_senderr(pmp, PUFFS_ERR_GETEXTATTR, E2BIG,
                   3220:                    "resid grew", VPTOPNC(vp));
                   3221:                error = EPROTO;
                   3222:                goto out;
                   3223:        }
                   3224:
                   3225:        if (sizep)
                   3226:                *sizep = getextattr_msg->pvnr_datasize;
                   3227:        if (uio)
                   3228:                error = uiomove(getextattr_msg->pvnr_data, tomove - resid, uio);
                   3229:
                   3230:  out:
                   3231:        PUFFS_MSG_RELEASE(getextattr);
                   3232:        return error;
                   3233: }
                   3234:
                   3235: int
                   3236: puffs_vnop_setextattr(void *v)
                   3237: {
                   3238:        struct vop_setextattr_args /* {
                   3239:                struct vnode *a_vp;
                   3240:                int a_attrnamespace;
                   3241:                const char *a_name;
                   3242:                struct uio *a_uio;
                   3243:                kauth_cred_t a_cred;
                   3244:        }; */ *ap = v;
                   3245:        PUFFS_MSG_VARS(vn, setextattr);
                   3246:        struct vnode *vp = ap->a_vp;
                   3247:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
                   3248:        int attrnamespace = ap->a_attrnamespace;
                   3249:        const char *name = ap->a_name;
                   3250:        struct uio *uio = ap->a_uio;
                   3251:        size_t tomove, resid;
                   3252:        int error;
                   3253:
                   3254:        if (uio)
                   3255:                resid = uio->uio_resid;
                   3256:        else
                   3257:                resid = 0;
                   3258:
                   3259:        tomove = PUFFS_TOMOVE(resid, pmp);
                   3260:        if (tomove != resid) {
                   3261:                error = E2BIG;
                   3262:                goto out;
                   3263:        }
                   3264:
                   3265:        puffs_msgmem_alloc(sizeof(struct puffs_vnmsg_setextattr) + tomove,
                   3266:            &park_setextattr, (void *)&setextattr_msg, 1);
                   3267:
                   3268:        setextattr_msg->pvnr_attrnamespace = attrnamespace;
                   3269:        strlcpy(setextattr_msg->pvnr_attrname, name,
                   3270:            sizeof(setextattr_msg->pvnr_attrname));
                   3271:        puffs_credcvt(&setextattr_msg->pvnr_cred, ap->a_cred);
                   3272:        setextattr_msg->pvnr_resid = tomove;
                   3273:
                   3274:        if (uio) {
                   3275:                error = uiomove(setextattr_msg->pvnr_data, tomove, uio);
                   3276:                if (error)
                   3277:                        goto out;
                   3278:        }
                   3279:
                   3280:        puffs_msg_setinfo(park_setextattr,
                   3281:            PUFFSOP_VN, PUFFS_VN_SETEXTATTR, VPTOPNC(vp));
                   3282:        PUFFS_MSG_ENQUEUEWAIT2(pmp, park_setextattr, vp->v_data, NULL, error);
                   3283:
                   3284:        error = checkerr(pmp, error, __func__);
                   3285:        if (error)
                   3286:                goto out;
                   3287:
                   3288:        if (setextattr_msg->pvnr_resid != 0)
                   3289:                error = EIO;
                   3290:
                   3291:  out:
                   3292:        PUFFS_MSG_RELEASE(setextattr);
                   3293:
                   3294:        return error;
                   3295: }
                   3296:
                   3297: int
                   3298: puffs_vnop_listextattr(void *v)
                   3299: {
                   3300:        struct vop_listextattr_args /* {
                   3301:                struct vnode *a_vp;
                   3302:                int a_attrnamespace;
                   3303:                struct uio *a_uio;
                   3304:                size_t *a_size;
1.154     manu     3305:                int a_flag,
1.145     pooka    3306:                kauth_cred_t a_cred;
                   3307:        }; */ *ap = v;
                   3308:        PUFFS_MSG_VARS(vn, listextattr);
                   3309:        struct vnode *vp = ap->a_vp;
                   3310:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
                   3311:        int attrnamespace = ap->a_attrnamespace;
                   3312:        struct uio *uio = ap->a_uio;
                   3313:        size_t *sizep = ap->a_size;
1.154     manu     3314:        int flag = ap->a_flag;
1.145     pooka    3315:        size_t tomove, resid;
                   3316:        int error;
                   3317:
                   3318:        if (uio)
                   3319:                resid = uio->uio_resid;
                   3320:        else
                   3321:                resid = 0;
                   3322:
                   3323:        tomove = PUFFS_TOMOVE(resid, pmp);
                   3324:        if (tomove != resid) {
                   3325:                error = E2BIG;
                   3326:                goto out;
                   3327:        }
                   3328:
                   3329:        puffs_msgmem_alloc(sizeof(struct puffs_vnmsg_listextattr) + tomove,
                   3330:            &park_listextattr, (void *)&listextattr_msg, 1);
                   3331:
                   3332:        listextattr_msg->pvnr_attrnamespace = attrnamespace;
1.154     manu     3333:        listextattr_msg->pvnr_flag = flag;
1.145     pooka    3334:        puffs_credcvt(&listextattr_msg->pvnr_cred, ap->a_cred);
                   3335:        listextattr_msg->pvnr_resid = tomove;
                   3336:        if (sizep)
                   3337:                listextattr_msg->pvnr_datasize = 1;
                   3338:
                   3339:        puffs_msg_setinfo(park_listextattr,
                   3340:            PUFFSOP_VN, PUFFS_VN_LISTEXTATTR, VPTOPNC(vp));
                   3341:        puffs_msg_setdelta(park_listextattr, tomove);
                   3342:        PUFFS_MSG_ENQUEUEWAIT2(pmp, park_listextattr, vp->v_data, NULL, error);
                   3343:
                   3344:        error = checkerr(pmp, error, __func__);
                   3345:        if (error)
                   3346:                goto out;
                   3347:
                   3348:        resid = listextattr_msg->pvnr_resid;
                   3349:        if (resid > tomove) {
                   3350:                puffs_senderr(pmp, PUFFS_ERR_LISTEXTATTR, E2BIG,
                   3351:                    "resid grew", VPTOPNC(vp));
                   3352:                error = EPROTO;
                   3353:                goto out;
                   3354:        }
                   3355:
                   3356:        if (sizep)
                   3357:                *sizep = listextattr_msg->pvnr_datasize;
                   3358:        if (uio)
                   3359:                error = uiomove(listextattr_msg->pvnr_data, tomove-resid, uio);
                   3360:
                   3361:  out:
                   3362:        PUFFS_MSG_RELEASE(listextattr);
                   3363:        return error;
                   3364: }
                   3365:
                   3366: int
                   3367: puffs_vnop_deleteextattr(void *v)
                   3368: {
                   3369:        struct vop_deleteextattr_args /* {
                   3370:                struct vnode *a_vp;
                   3371:                int a_attrnamespace;
                   3372:                const char *a_name;
                   3373:                kauth_cred_t a_cred;
                   3374:        }; */ *ap = v;
                   3375:        PUFFS_MSG_VARS(vn, deleteextattr);
                   3376:        struct vnode *vp = ap->a_vp;
                   3377:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
                   3378:        int attrnamespace = ap->a_attrnamespace;
                   3379:        const char *name = ap->a_name;
                   3380:        int error;
                   3381:
                   3382:        PUFFS_MSG_ALLOC(vn, deleteextattr);
                   3383:        deleteextattr_msg->pvnr_attrnamespace = attrnamespace;
                   3384:        strlcpy(deleteextattr_msg->pvnr_attrname, name,
                   3385:            sizeof(deleteextattr_msg->pvnr_attrname));
                   3386:        puffs_credcvt(&deleteextattr_msg->pvnr_cred, ap->a_cred);
                   3387:
                   3388:        puffs_msg_setinfo(park_deleteextattr,
                   3389:            PUFFSOP_VN, PUFFS_VN_DELETEEXTATTR, VPTOPNC(vp));
                   3390:        PUFFS_MSG_ENQUEUEWAIT2(pmp, park_deleteextattr,
                   3391:            vp->v_data, NULL, error);
                   3392:
                   3393:        error = checkerr(pmp, error, __func__);
                   3394:
                   3395:        PUFFS_MSG_RELEASE(deleteextattr);
                   3396:        return error;
                   3397: }
                   3398:
                   3399: /*
1.31      pooka    3400:  * spec & fifo.  These call the miscfs spec and fifo vectors, but issue
1.26      pooka    3401:  * FAF update information for the puffs node first.
                   3402:  */
                   3403: int
1.123     pooka    3404: puffs_vnop_spec_read(void *v)
1.26      pooka    3405: {
                   3406:        struct vop_read_args /* {
                   3407:                const struct vnodeop_desc *a_desc;
                   3408:                struct vnode *a_vp;
                   3409:                struct uio *a_uio;
                   3410:                int a_ioflag;
                   3411:                kauth_cred_t a_cred;
                   3412:        } */ *ap = v;
                   3413:
1.117     pooka    3414:        puffs_updatenode(VPTOPP(ap->a_vp), PUFFS_UPDATEATIME, 0);
1.26      pooka    3415:        return VOCALL(spec_vnodeop_p, VOFFSET(vop_read), v);
                   3416: }
                   3417:
                   3418: int
1.123     pooka    3419: puffs_vnop_spec_write(void *v)
1.26      pooka    3420: {
                   3421:        struct vop_write_args /* {
                   3422:                const struct vnodeop_desc *a_desc;
                   3423:                struct vnode *a_vp;
                   3424:                struct uio *a_uio;
                   3425:                int a_ioflag;
                   3426:                kauth_cred_t a_cred;
1.129     christos 3427:        } */ *ap = v;
1.26      pooka    3428:
1.117     pooka    3429:        puffs_updatenode(VPTOPP(ap->a_vp), PUFFS_UPDATEMTIME, 0);
1.26      pooka    3430:        return VOCALL(spec_vnodeop_p, VOFFSET(vop_write), v);
                   3431: }
                   3432:
                   3433: int
1.123     pooka    3434: puffs_vnop_fifo_read(void *v)
1.26      pooka    3435: {
                   3436:        struct vop_read_args /* {
                   3437:                const struct vnodeop_desc *a_desc;
                   3438:                struct vnode *a_vp;
                   3439:                struct uio *a_uio;
                   3440:                int a_ioflag;
                   3441:                kauth_cred_t a_cred;
                   3442:        } */ *ap = v;
                   3443:
1.117     pooka    3444:        puffs_updatenode(VPTOPP(ap->a_vp), PUFFS_UPDATEATIME, 0);
1.26      pooka    3445:        return VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), v);
                   3446: }
                   3447:
                   3448: int
1.123     pooka    3449: puffs_vnop_fifo_write(void *v)
1.26      pooka    3450: {
                   3451:        struct vop_write_args /* {
                   3452:                const struct vnodeop_desc *a_desc;
                   3453:                struct vnode *a_vp;
                   3454:                struct uio *a_uio;
                   3455:                int a_ioflag;
                   3456:                kauth_cred_t a_cred;
1.129     christos 3457:        } */ *ap = v;
1.26      pooka    3458:
1.117     pooka    3459:        puffs_updatenode(VPTOPP(ap->a_vp), PUFFS_UPDATEMTIME, 0);
1.26      pooka    3460:        return VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), v);
                   3461: }

CVSweb <webmaster@jp.NetBSD.org>