1/* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Rick Macklem at The University of Guelph. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95
| 1/* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Rick Macklem at The University of Guelph. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95
|
37 * $Id: nfs_vnops.c,v 1.91 1998/05/31 01:03:07 peter Exp $
| 37 * $Id: nfs_vnops.c,v 1.92 1998/05/31 17:27:55 peter Exp $
|
38 */ 39 40 41/* 42 * vnode op calls for Sun NFS version 2 and 3 43 */ 44 45#include "opt_inet.h" 46 47#include <sys/param.h> 48#include <sys/kernel.h> 49#include <sys/systm.h> 50#include <sys/resourcevar.h> 51#include <sys/proc.h> 52#include <sys/mount.h> 53#include <sys/buf.h> 54#include <sys/malloc.h> 55#include <sys/mbuf.h> 56#include <sys/namei.h> 57#include <sys/socket.h> 58#include <sys/vnode.h> 59#include <sys/dirent.h> 60#include <sys/fcntl.h> 61#include <sys/lockf.h> 62 63#include <vm/vm.h> 64#include <vm/vm_extern.h> 65#include <vm/vm_zone.h> 66 67#include <miscfs/fifofs/fifo.h> 68#include <miscfs/specfs/specdev.h> 69 70#include <nfs/rpcv2.h> 71#include <nfs/nfsproto.h> 72#include <nfs/nfs.h> 73#include <nfs/nfsnode.h> 74#include <nfs/nfsmount.h> 75#include <nfs/xdr_subs.h> 76#include <nfs/nfsm_subs.h> 77#include <nfs/nqnfs.h> 78 79#include <net/if.h> 80#include <netinet/in.h> 81#include <netinet/in_var.h> 82 83/* Defs */ 84#define TRUE 1 85#define FALSE 0 86 87/* 88 * Ifdef for FreeBSD-current merged buffer cache. It is unfortunate that these 89 * calls are not in getblk() and brelse() so that they would not be necessary 90 * here. 91 */ 92#ifndef B_VMIO 93#define vfs_busy_pages(bp, f) 94#endif 95 96static int nfsspec_read __P((struct vop_read_args *)); 97static int nfsspec_write __P((struct vop_write_args *)); 98static int nfsfifo_read __P((struct vop_read_args *)); 99static int nfsfifo_write __P((struct vop_write_args *)); 100static int nfsspec_close __P((struct vop_close_args *)); 101static int nfsfifo_close __P((struct vop_close_args *)); 102#define nfs_poll vop_nopoll 103static int nfs_flush __P((struct vnode *,struct ucred *,int,struct proc *,int)); 104static int nfs_setattrrpc __P((struct vnode *,struct vattr *,struct ucred *,struct proc *)); 105static int nfs_lookup __P((struct vop_lookup_args *)); 106static int nfs_create __P((struct vop_create_args *)); 107static int nfs_mknod __P((struct vop_mknod_args *)); 108static int nfs_open __P((struct vop_open_args *)); 109static int nfs_close __P((struct vop_close_args *)); 110static int nfs_access __P((struct vop_access_args *)); 111static int nfs_getattr __P((struct vop_getattr_args *)); 112static int nfs_setattr __P((struct vop_setattr_args *)); 113static int nfs_read __P((struct vop_read_args *)); 114static int nfs_mmap __P((struct vop_mmap_args *)); 115static int nfs_fsync __P((struct vop_fsync_args *)); 116static int nfs_remove __P((struct vop_remove_args *)); 117static int nfs_link __P((struct vop_link_args *)); 118static int nfs_rename __P((struct vop_rename_args *)); 119static int nfs_mkdir __P((struct vop_mkdir_args *)); 120static int nfs_rmdir __P((struct vop_rmdir_args *)); 121static int nfs_symlink __P((struct vop_symlink_args *)); 122static int nfs_readdir __P((struct vop_readdir_args *)); 123static int nfs_bmap __P((struct vop_bmap_args *)); 124static int nfs_strategy __P((struct vop_strategy_args *));
| 38 */ 39 40 41/* 42 * vnode op calls for Sun NFS version 2 and 3 43 */ 44 45#include "opt_inet.h" 46 47#include <sys/param.h> 48#include <sys/kernel.h> 49#include <sys/systm.h> 50#include <sys/resourcevar.h> 51#include <sys/proc.h> 52#include <sys/mount.h> 53#include <sys/buf.h> 54#include <sys/malloc.h> 55#include <sys/mbuf.h> 56#include <sys/namei.h> 57#include <sys/socket.h> 58#include <sys/vnode.h> 59#include <sys/dirent.h> 60#include <sys/fcntl.h> 61#include <sys/lockf.h> 62 63#include <vm/vm.h> 64#include <vm/vm_extern.h> 65#include <vm/vm_zone.h> 66 67#include <miscfs/fifofs/fifo.h> 68#include <miscfs/specfs/specdev.h> 69 70#include <nfs/rpcv2.h> 71#include <nfs/nfsproto.h> 72#include <nfs/nfs.h> 73#include <nfs/nfsnode.h> 74#include <nfs/nfsmount.h> 75#include <nfs/xdr_subs.h> 76#include <nfs/nfsm_subs.h> 77#include <nfs/nqnfs.h> 78 79#include <net/if.h> 80#include <netinet/in.h> 81#include <netinet/in_var.h> 82 83/* Defs */ 84#define TRUE 1 85#define FALSE 0 86 87/* 88 * Ifdef for FreeBSD-current merged buffer cache. It is unfortunate that these 89 * calls are not in getblk() and brelse() so that they would not be necessary 90 * here. 91 */ 92#ifndef B_VMIO 93#define vfs_busy_pages(bp, f) 94#endif 95 96static int nfsspec_read __P((struct vop_read_args *)); 97static int nfsspec_write __P((struct vop_write_args *)); 98static int nfsfifo_read __P((struct vop_read_args *)); 99static int nfsfifo_write __P((struct vop_write_args *)); 100static int nfsspec_close __P((struct vop_close_args *)); 101static int nfsfifo_close __P((struct vop_close_args *)); 102#define nfs_poll vop_nopoll 103static int nfs_flush __P((struct vnode *,struct ucred *,int,struct proc *,int)); 104static int nfs_setattrrpc __P((struct vnode *,struct vattr *,struct ucred *,struct proc *)); 105static int nfs_lookup __P((struct vop_lookup_args *)); 106static int nfs_create __P((struct vop_create_args *)); 107static int nfs_mknod __P((struct vop_mknod_args *)); 108static int nfs_open __P((struct vop_open_args *)); 109static int nfs_close __P((struct vop_close_args *)); 110static int nfs_access __P((struct vop_access_args *)); 111static int nfs_getattr __P((struct vop_getattr_args *)); 112static int nfs_setattr __P((struct vop_setattr_args *)); 113static int nfs_read __P((struct vop_read_args *)); 114static int nfs_mmap __P((struct vop_mmap_args *)); 115static int nfs_fsync __P((struct vop_fsync_args *)); 116static int nfs_remove __P((struct vop_remove_args *)); 117static int nfs_link __P((struct vop_link_args *)); 118static int nfs_rename __P((struct vop_rename_args *)); 119static int nfs_mkdir __P((struct vop_mkdir_args *)); 120static int nfs_rmdir __P((struct vop_rmdir_args *)); 121static int nfs_symlink __P((struct vop_symlink_args *)); 122static int nfs_readdir __P((struct vop_readdir_args *)); 123static int nfs_bmap __P((struct vop_bmap_args *)); 124static int nfs_strategy __P((struct vop_strategy_args *));
|
125static int nfs_lookitup __P((struct vnode *,char *,int,struct ucred *,struct proc *,struct nfsnode **));
| 125static int nfs_lookitup __P((struct vnode *, const char *, int, 126 struct ucred *, struct proc *, struct nfsnode **));
|
126static int nfs_sillyrename __P((struct vnode *,struct vnode *,struct componentname *)); 127static int nfsspec_access __P((struct vop_access_args *)); 128static int nfs_readlink __P((struct vop_readlink_args *)); 129static int nfs_print __P((struct vop_print_args *)); 130static int nfs_advlock __P((struct vop_advlock_args *)); 131static int nfs_bwrite __P((struct vop_bwrite_args *)); 132/* 133 * Global vfs data structures for nfs 134 */ 135vop_t **nfsv2_vnodeop_p; 136static struct vnodeopv_entry_desc nfsv2_vnodeop_entries[] = { 137 { &vop_default_desc, (vop_t *) vop_defaultop }, 138 { &vop_abortop_desc, (vop_t *) nfs_abortop }, 139 { &vop_access_desc, (vop_t *) nfs_access }, 140 { &vop_advlock_desc, (vop_t *) nfs_advlock }, 141 { &vop_bmap_desc, (vop_t *) nfs_bmap }, 142 { &vop_bwrite_desc, (vop_t *) nfs_bwrite }, 143 { &vop_close_desc, (vop_t *) nfs_close }, 144 { &vop_create_desc, (vop_t *) nfs_create }, 145 { &vop_fsync_desc, (vop_t *) nfs_fsync }, 146 { &vop_getattr_desc, (vop_t *) nfs_getattr }, 147 { &vop_getpages_desc, (vop_t *) nfs_getpages }, 148 { &vop_putpages_desc, (vop_t *) nfs_putpages }, 149 { &vop_inactive_desc, (vop_t *) nfs_inactive }, 150 { &vop_lease_desc, (vop_t *) vop_null }, 151 { &vop_link_desc, (vop_t *) nfs_link }, 152 { &vop_lock_desc, (vop_t *) vop_sharedlock }, 153 { &vop_lookup_desc, (vop_t *) nfs_lookup }, 154 { &vop_mkdir_desc, (vop_t *) nfs_mkdir }, 155 { &vop_mknod_desc, (vop_t *) nfs_mknod }, 156 { &vop_mmap_desc, (vop_t *) nfs_mmap }, 157 { &vop_open_desc, (vop_t *) nfs_open }, 158 { &vop_poll_desc, (vop_t *) nfs_poll }, 159 { &vop_print_desc, (vop_t *) nfs_print }, 160 { &vop_read_desc, (vop_t *) nfs_read }, 161 { &vop_readdir_desc, (vop_t *) nfs_readdir }, 162 { &vop_readlink_desc, (vop_t *) nfs_readlink }, 163 { &vop_reclaim_desc, (vop_t *) nfs_reclaim }, 164 { &vop_remove_desc, (vop_t *) nfs_remove }, 165 { &vop_rename_desc, (vop_t *) nfs_rename }, 166 { &vop_rmdir_desc, (vop_t *) nfs_rmdir }, 167 { &vop_setattr_desc, (vop_t *) nfs_setattr }, 168 { &vop_strategy_desc, (vop_t *) nfs_strategy }, 169 { &vop_symlink_desc, (vop_t *) nfs_symlink }, 170 { &vop_write_desc, (vop_t *) nfs_write }, 171 { NULL, NULL } 172}; 173static struct vnodeopv_desc nfsv2_vnodeop_opv_desc = 174 { &nfsv2_vnodeop_p, nfsv2_vnodeop_entries }; 175VNODEOP_SET(nfsv2_vnodeop_opv_desc); 176 177/* 178 * Special device vnode ops 179 */ 180vop_t **spec_nfsv2nodeop_p; 181static struct vnodeopv_entry_desc nfsv2_specop_entries[] = { 182 { &vop_default_desc, (vop_t *) spec_vnoperate }, 183 { &vop_access_desc, (vop_t *) nfsspec_access }, 184 { &vop_close_desc, (vop_t *) nfsspec_close }, 185 { &vop_fsync_desc, (vop_t *) nfs_fsync }, 186 { &vop_getattr_desc, (vop_t *) nfs_getattr }, 187 { &vop_inactive_desc, (vop_t *) nfs_inactive }, 188 { &vop_lock_desc, (vop_t *) vop_sharedlock }, 189 { &vop_print_desc, (vop_t *) nfs_print }, 190 { &vop_read_desc, (vop_t *) nfsspec_read }, 191 { &vop_reclaim_desc, (vop_t *) nfs_reclaim }, 192 { &vop_setattr_desc, (vop_t *) nfs_setattr }, 193 { &vop_write_desc, (vop_t *) nfsspec_write }, 194 { NULL, NULL } 195}; 196static struct vnodeopv_desc spec_nfsv2nodeop_opv_desc = 197 { &spec_nfsv2nodeop_p, nfsv2_specop_entries }; 198VNODEOP_SET(spec_nfsv2nodeop_opv_desc); 199 200vop_t **fifo_nfsv2nodeop_p; 201static struct vnodeopv_entry_desc nfsv2_fifoop_entries[] = { 202 { &vop_default_desc, (vop_t *) fifo_vnoperate }, 203 { &vop_access_desc, (vop_t *) nfsspec_access }, 204 { &vop_close_desc, (vop_t *) nfsfifo_close }, 205 { &vop_fsync_desc, (vop_t *) nfs_fsync }, 206 { &vop_getattr_desc, (vop_t *) nfs_getattr }, 207 { &vop_inactive_desc, (vop_t *) nfs_inactive }, 208 { &vop_lock_desc, (vop_t *) vop_sharedlock }, 209 { &vop_print_desc, (vop_t *) nfs_print }, 210 { &vop_read_desc, (vop_t *) nfsfifo_read }, 211 { &vop_reclaim_desc, (vop_t *) nfs_reclaim }, 212 { &vop_setattr_desc, (vop_t *) nfs_setattr }, 213 { &vop_write_desc, (vop_t *) nfsfifo_write }, 214 { NULL, NULL } 215}; 216static struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc = 217 { &fifo_nfsv2nodeop_p, nfsv2_fifoop_entries }; 218VNODEOP_SET(fifo_nfsv2nodeop_opv_desc); 219 220static int nfs_commit __P((struct vnode *vp, u_quad_t offset, int cnt, 221 struct ucred *cred, struct proc *procp)); 222static int nfs_mknodrpc __P((struct vnode *dvp, struct vnode **vpp, 223 struct componentname *cnp, 224 struct vattr *vap));
| 127static int nfs_sillyrename __P((struct vnode *,struct vnode *,struct componentname *)); 128static int nfsspec_access __P((struct vop_access_args *)); 129static int nfs_readlink __P((struct vop_readlink_args *)); 130static int nfs_print __P((struct vop_print_args *)); 131static int nfs_advlock __P((struct vop_advlock_args *)); 132static int nfs_bwrite __P((struct vop_bwrite_args *)); 133/* 134 * Global vfs data structures for nfs 135 */ 136vop_t **nfsv2_vnodeop_p; 137static struct vnodeopv_entry_desc nfsv2_vnodeop_entries[] = { 138 { &vop_default_desc, (vop_t *) vop_defaultop }, 139 { &vop_abortop_desc, (vop_t *) nfs_abortop }, 140 { &vop_access_desc, (vop_t *) nfs_access }, 141 { &vop_advlock_desc, (vop_t *) nfs_advlock }, 142 { &vop_bmap_desc, (vop_t *) nfs_bmap }, 143 { &vop_bwrite_desc, (vop_t *) nfs_bwrite }, 144 { &vop_close_desc, (vop_t *) nfs_close }, 145 { &vop_create_desc, (vop_t *) nfs_create }, 146 { &vop_fsync_desc, (vop_t *) nfs_fsync }, 147 { &vop_getattr_desc, (vop_t *) nfs_getattr }, 148 { &vop_getpages_desc, (vop_t *) nfs_getpages }, 149 { &vop_putpages_desc, (vop_t *) nfs_putpages }, 150 { &vop_inactive_desc, (vop_t *) nfs_inactive }, 151 { &vop_lease_desc, (vop_t *) vop_null }, 152 { &vop_link_desc, (vop_t *) nfs_link }, 153 { &vop_lock_desc, (vop_t *) vop_sharedlock }, 154 { &vop_lookup_desc, (vop_t *) nfs_lookup }, 155 { &vop_mkdir_desc, (vop_t *) nfs_mkdir }, 156 { &vop_mknod_desc, (vop_t *) nfs_mknod }, 157 { &vop_mmap_desc, (vop_t *) nfs_mmap }, 158 { &vop_open_desc, (vop_t *) nfs_open }, 159 { &vop_poll_desc, (vop_t *) nfs_poll }, 160 { &vop_print_desc, (vop_t *) nfs_print }, 161 { &vop_read_desc, (vop_t *) nfs_read }, 162 { &vop_readdir_desc, (vop_t *) nfs_readdir }, 163 { &vop_readlink_desc, (vop_t *) nfs_readlink }, 164 { &vop_reclaim_desc, (vop_t *) nfs_reclaim }, 165 { &vop_remove_desc, (vop_t *) nfs_remove }, 166 { &vop_rename_desc, (vop_t *) nfs_rename }, 167 { &vop_rmdir_desc, (vop_t *) nfs_rmdir }, 168 { &vop_setattr_desc, (vop_t *) nfs_setattr }, 169 { &vop_strategy_desc, (vop_t *) nfs_strategy }, 170 { &vop_symlink_desc, (vop_t *) nfs_symlink }, 171 { &vop_write_desc, (vop_t *) nfs_write }, 172 { NULL, NULL } 173}; 174static struct vnodeopv_desc nfsv2_vnodeop_opv_desc = 175 { &nfsv2_vnodeop_p, nfsv2_vnodeop_entries }; 176VNODEOP_SET(nfsv2_vnodeop_opv_desc); 177 178/* 179 * Special device vnode ops 180 */ 181vop_t **spec_nfsv2nodeop_p; 182static struct vnodeopv_entry_desc nfsv2_specop_entries[] = { 183 { &vop_default_desc, (vop_t *) spec_vnoperate }, 184 { &vop_access_desc, (vop_t *) nfsspec_access }, 185 { &vop_close_desc, (vop_t *) nfsspec_close }, 186 { &vop_fsync_desc, (vop_t *) nfs_fsync }, 187 { &vop_getattr_desc, (vop_t *) nfs_getattr }, 188 { &vop_inactive_desc, (vop_t *) nfs_inactive }, 189 { &vop_lock_desc, (vop_t *) vop_sharedlock }, 190 { &vop_print_desc, (vop_t *) nfs_print }, 191 { &vop_read_desc, (vop_t *) nfsspec_read }, 192 { &vop_reclaim_desc, (vop_t *) nfs_reclaim }, 193 { &vop_setattr_desc, (vop_t *) nfs_setattr }, 194 { &vop_write_desc, (vop_t *) nfsspec_write }, 195 { NULL, NULL } 196}; 197static struct vnodeopv_desc spec_nfsv2nodeop_opv_desc = 198 { &spec_nfsv2nodeop_p, nfsv2_specop_entries }; 199VNODEOP_SET(spec_nfsv2nodeop_opv_desc); 200 201vop_t **fifo_nfsv2nodeop_p; 202static struct vnodeopv_entry_desc nfsv2_fifoop_entries[] = { 203 { &vop_default_desc, (vop_t *) fifo_vnoperate }, 204 { &vop_access_desc, (vop_t *) nfsspec_access }, 205 { &vop_close_desc, (vop_t *) nfsfifo_close }, 206 { &vop_fsync_desc, (vop_t *) nfs_fsync }, 207 { &vop_getattr_desc, (vop_t *) nfs_getattr }, 208 { &vop_inactive_desc, (vop_t *) nfs_inactive }, 209 { &vop_lock_desc, (vop_t *) vop_sharedlock }, 210 { &vop_print_desc, (vop_t *) nfs_print }, 211 { &vop_read_desc, (vop_t *) nfsfifo_read }, 212 { &vop_reclaim_desc, (vop_t *) nfs_reclaim }, 213 { &vop_setattr_desc, (vop_t *) nfs_setattr }, 214 { &vop_write_desc, (vop_t *) nfsfifo_write }, 215 { NULL, NULL } 216}; 217static struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc = 218 { &fifo_nfsv2nodeop_p, nfsv2_fifoop_entries }; 219VNODEOP_SET(fifo_nfsv2nodeop_opv_desc); 220 221static int nfs_commit __P((struct vnode *vp, u_quad_t offset, int cnt, 222 struct ucred *cred, struct proc *procp)); 223static int nfs_mknodrpc __P((struct vnode *dvp, struct vnode **vpp, 224 struct componentname *cnp, 225 struct vattr *vap));
|
225static int nfs_removerpc __P((struct vnode *dvp, char *name, int namelen,
| 226static int nfs_removerpc __P((struct vnode *dvp, const char *name, 227 int namelen,
|
226 struct ucred *cred, struct proc *proc));
| 228 struct ucred *cred, struct proc *proc));
|
227static int nfs_renamerpc __P((struct vnode *fdvp, char *fnameptr,
| 229static int nfs_renamerpc __P((struct vnode *fdvp, const char *fnameptr,
|
228 int fnamelen, struct vnode *tdvp,
| 230 int fnamelen, struct vnode *tdvp,
|
229 char *tnameptr, int tnamelen,
| 231 const char *tnameptr, int tnamelen,
|
230 struct ucred *cred, struct proc *proc)); 231static int nfs_renameit __P((struct vnode *sdvp, 232 struct componentname *scnp, 233 struct sillyrename *sp)); 234 235/* 236 * Global variables 237 */ 238extern u_long nfs_true, nfs_false; 239extern struct nfsstats nfsstats; 240extern nfstype nfsv3_type[9]; 241struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON]; 242struct nfsmount *nfs_iodmount[NFS_MAXASYNCDAEMON]; 243int nfs_numasync = 0; 244#define DIRHDSIZ (sizeof (struct dirent) - (MAXNAMLEN + 1)) 245 246/* 247 * nfs access vnode op. 248 * For nfs version 2, just return ok. File accesses may fail later. 249 * For nfs version 3, use the access rpc to check accessibility. If file modes 250 * are changed on the server, accesses might still fail later. 251 */ 252static int 253nfs_access(ap) 254 struct vop_access_args /* { 255 struct vnode *a_vp; 256 int a_mode; 257 struct ucred *a_cred; 258 struct proc *a_p; 259 } */ *ap; 260{ 261 register struct vnode *vp = ap->a_vp; 262 register u_long *tl; 263 register caddr_t cp; 264 register int t1, t2; 265 caddr_t bpos, dpos, cp2; 266 int error = 0, attrflag; 267 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 268 u_long mode, rmode; 269 int v3 = NFS_ISV3(vp); 270 271 /* 272 * Disallow write attempts on filesystems mounted read-only; 273 * unless the file is a socket, fifo, or a block or character 274 * device resident on the filesystem. 275 */ 276 if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) { 277 switch (vp->v_type) { 278 case VREG: 279 case VDIR: 280 case VLNK: 281 return (EROFS); 282 default: 283 break; 284 } 285 } 286 /* 287 * For nfs v3, do an access rpc, otherwise you are stuck emulating 288 * ufs_access() locally using the vattr. This may not be correct, 289 * since the server may apply other access criteria such as 290 * client uid-->server uid mapping that we do not know about, but 291 * this is better than just returning anything that is lying about 292 * in the cache. 293 */ 294 if (v3) { 295 nfsstats.rpccnt[NFSPROC_ACCESS]++; 296 nfsm_reqhead(vp, NFSPROC_ACCESS, NFSX_FH(v3) + NFSX_UNSIGNED); 297 nfsm_fhtom(vp, v3); 298 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 299 if (ap->a_mode & VREAD) 300 mode = NFSV3ACCESS_READ; 301 else 302 mode = 0; 303 if (vp->v_type != VDIR) { 304 if (ap->a_mode & VWRITE) 305 mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND); 306 if (ap->a_mode & VEXEC) 307 mode |= NFSV3ACCESS_EXECUTE; 308 } else { 309 if (ap->a_mode & VWRITE) 310 mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND | 311 NFSV3ACCESS_DELETE); 312 if (ap->a_mode & VEXEC) 313 mode |= NFSV3ACCESS_LOOKUP; 314 } 315 *tl = txdr_unsigned(mode); 316 nfsm_request(vp, NFSPROC_ACCESS, ap->a_p, ap->a_cred); 317 nfsm_postop_attr(vp, attrflag); 318 if (!error) { 319 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 320 rmode = fxdr_unsigned(u_long, *tl); 321 /* 322 * The NFS V3 spec does not clarify whether or not 323 * the returned access bits can be a superset of 324 * the ones requested, so... 325 */ 326 if ((rmode & mode) != mode) 327 error = EACCES; 328 } 329 nfsm_reqdone; 330 return (error); 331 } else { 332 if (error = nfsspec_access(ap)) 333 return (error); 334 335 /* 336 * Attempt to prevent a mapped root from accessing a file 337 * which it shouldn't. We try to read a byte from the file 338 * if the user is root and the file is not zero length. 339 * After calling nfsspec_access, we should have the correct 340 * file size cached. 341 */ 342 if (ap->a_cred->cr_uid == 0 && (ap->a_mode & VREAD) 343 && VTONFS(vp)->n_size > 0) { 344 struct iovec aiov; 345 struct uio auio; 346 char buf[1]; 347 348 aiov.iov_base = buf; 349 aiov.iov_len = 1; 350 auio.uio_iov = &aiov; 351 auio.uio_iovcnt = 1; 352 auio.uio_offset = 0; 353 auio.uio_resid = 1; 354 auio.uio_segflg = UIO_SYSSPACE; 355 auio.uio_rw = UIO_READ; 356 auio.uio_procp = ap->a_p; 357 358 if (vp->v_type == VREG) 359 error = nfs_readrpc(vp, &auio, ap->a_cred); 360 else if (vp->v_type == VDIR) { 361 char* bp; 362 bp = malloc(NFS_DIRBLKSIZ, M_TEMP, M_WAITOK); 363 aiov.iov_base = bp; 364 aiov.iov_len = auio.uio_resid = NFS_DIRBLKSIZ; 365 error = nfs_readdirrpc(vp, &auio, ap->a_cred); 366 free(bp, M_TEMP); 367 } else if (vp->v_type = VLNK) 368 error = nfs_readlinkrpc(vp, &auio, ap->a_cred); 369 else 370 error = EACCES; 371 } 372 return (error); 373 } 374} 375 376/* 377 * nfs open vnode op 378 * Check to see if the type is ok 379 * and that deletion is not in progress. 380 * For paged in text files, you will need to flush the page cache 381 * if consistency is lost. 382 */ 383/* ARGSUSED */ 384static int 385nfs_open(ap) 386 struct vop_open_args /* { 387 struct vnode *a_vp; 388 int a_mode; 389 struct ucred *a_cred; 390 struct proc *a_p; 391 } */ *ap; 392{ 393 register struct vnode *vp = ap->a_vp; 394 struct nfsnode *np = VTONFS(vp); 395 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 396 struct vattr vattr; 397 int error; 398 399 if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) { 400 printf("open eacces vtyp=%d\n",vp->v_type); 401 return (EACCES); 402 } 403 /* 404 * Get a valid lease. If cached data is stale, flush it. 405 */ 406 if (nmp->nm_flag & NFSMNT_NQNFS) { 407 if (NQNFS_CKINVALID(vp, np, ND_READ)) { 408 do { 409 error = nqnfs_getlease(vp, ND_READ, ap->a_cred, 410 ap->a_p); 411 } while (error == NQNFS_EXPIRED); 412 if (error) 413 return (error); 414 if (np->n_lrev != np->n_brev || 415 (np->n_flag & NQNFSNONCACHE)) { 416 if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, 417 ap->a_p, 1)) == EINTR) 418 return (error); 419 np->n_brev = np->n_lrev; 420 } 421 } 422 } else { 423 if (np->n_flag & NMODIFIED) { 424 if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, 425 ap->a_p, 1)) == EINTR) 426 return (error); 427 np->n_attrstamp = 0; 428 if (vp->v_type == VDIR) 429 np->n_direofoffset = 0; 430 error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p); 431 if (error) 432 return (error); 433 np->n_mtime = vattr.va_mtime.tv_sec; 434 } else { 435 error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p); 436 if (error) 437 return (error); 438 if (np->n_mtime != vattr.va_mtime.tv_sec) { 439 if (vp->v_type == VDIR) 440 np->n_direofoffset = 0; 441 if ((error = nfs_vinvalbuf(vp, V_SAVE, 442 ap->a_cred, ap->a_p, 1)) == EINTR) 443 return (error); 444 np->n_mtime = vattr.va_mtime.tv_sec; 445 } 446 } 447 } 448 if ((nmp->nm_flag & NFSMNT_NQNFS) == 0) 449 np->n_attrstamp = 0; /* For Open/Close consistency */ 450 return (0); 451} 452 453/* 454 * nfs close vnode op 455 * What an NFS client should do upon close after writing is a debatable issue. 456 * Most NFS clients push delayed writes to the server upon close, basically for 457 * two reasons: 458 * 1 - So that any write errors may be reported back to the client process 459 * doing the close system call. By far the two most likely errors are 460 * NFSERR_NOSPC and NFSERR_DQUOT to indicate space allocation failure. 461 * 2 - To put a worst case upper bound on cache inconsistency between 462 * multiple clients for the file. 463 * There is also a consistency problem for Version 2 of the protocol w.r.t. 464 * not being able to tell if other clients are writing a file concurrently, 465 * since there is no way of knowing if the changed modify time in the reply 466 * is only due to the write for this client. 467 * (NFS Version 3 provides weak cache consistency data in the reply that 468 * should be sufficient to detect and handle this case.) 469 * 470 * The current code does the following: 471 * for NFS Version 2 - play it safe and flush/invalidate all dirty buffers 472 * for NFS Version 3 - flush dirty buffers to the server but don't invalidate 473 * or commit them (this satisfies 1 and 2 except for the 474 * case where the server crashes after this close but 475 * before the commit RPC, which is felt to be "good 476 * enough". Changing the last argument to nfs_flush() to 477 * a 1 would force a commit operation, if it is felt a 478 * commit is necessary now. 479 * for NQNFS - do nothing now, since 2 is dealt with via leases and 480 * 1 should be dealt with via an fsync() system call for 481 * cases where write errors are important. 482 */ 483/* ARGSUSED */ 484static int 485nfs_close(ap) 486 struct vop_close_args /* { 487 struct vnodeop_desc *a_desc; 488 struct vnode *a_vp; 489 int a_fflag; 490 struct ucred *a_cred; 491 struct proc *a_p; 492 } */ *ap; 493{ 494 register struct vnode *vp = ap->a_vp; 495 register struct nfsnode *np = VTONFS(vp); 496 int error = 0; 497 498 if (vp->v_type == VREG) { 499 if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) == 0 && 500 (np->n_flag & NMODIFIED)) { 501 if (NFS_ISV3(vp)) { 502 error = nfs_flush(vp, ap->a_cred, MNT_WAIT, ap->a_p, 0); 503 np->n_flag &= ~NMODIFIED; 504 } else 505 error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 1); 506 np->n_attrstamp = 0; 507 } 508 if (np->n_flag & NWRITEERR) { 509 np->n_flag &= ~NWRITEERR; 510 error = np->n_error; 511 } 512 } 513 return (error); 514} 515 516/* 517 * nfs getattr call from vfs. 518 */ 519static int 520nfs_getattr(ap) 521 struct vop_getattr_args /* { 522 struct vnode *a_vp; 523 struct vattr *a_vap; 524 struct ucred *a_cred; 525 struct proc *a_p; 526 } */ *ap; 527{ 528 register struct vnode *vp = ap->a_vp; 529 register struct nfsnode *np = VTONFS(vp); 530 register caddr_t cp; 531 register u_long *tl; 532 register int t1, t2; 533 caddr_t bpos, dpos; 534 int error = 0; 535 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 536 int v3 = NFS_ISV3(vp); 537 538 /* 539 * Update local times for special files. 540 */ 541 if (np->n_flag & (NACC | NUPD)) 542 np->n_flag |= NCHG; 543 /* 544 * First look in the cache. 545 */ 546 if (nfs_getattrcache(vp, ap->a_vap) == 0) 547 return (0); 548 nfsstats.rpccnt[NFSPROC_GETATTR]++; 549 nfsm_reqhead(vp, NFSPROC_GETATTR, NFSX_FH(v3)); 550 nfsm_fhtom(vp, v3); 551 nfsm_request(vp, NFSPROC_GETATTR, ap->a_p, ap->a_cred); 552 if (!error) { 553 nfsm_loadattr(vp, ap->a_vap); 554 } 555 nfsm_reqdone; 556 return (error); 557} 558 559/* 560 * nfs setattr call. 561 */ 562static int 563nfs_setattr(ap) 564 struct vop_setattr_args /* { 565 struct vnodeop_desc *a_desc; 566 struct vnode *a_vp; 567 struct vattr *a_vap; 568 struct ucred *a_cred; 569 struct proc *a_p; 570 } */ *ap; 571{ 572 register struct vnode *vp = ap->a_vp; 573 register struct nfsnode *np = VTONFS(vp); 574 register struct vattr *vap = ap->a_vap; 575 int error = 0; 576 u_quad_t tsize; 577 578#ifndef nolint 579 tsize = (u_quad_t)0; 580#endif 581 /* 582 * Disallow write attempts if the filesystem is mounted read-only. 583 */ 584 if ((vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL || 585 vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || 586 vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) && 587 (vp->v_mount->mnt_flag & MNT_RDONLY)) 588 return (EROFS); 589 if (vap->va_size != VNOVAL) { 590 switch (vp->v_type) { 591 case VDIR: 592 return (EISDIR); 593 case VCHR: 594 case VBLK: 595 case VSOCK: 596 case VFIFO: 597 if (vap->va_mtime.tv_sec == VNOVAL && 598 vap->va_atime.tv_sec == VNOVAL && 599 vap->va_mode == (u_short)VNOVAL && 600 vap->va_uid == (uid_t)VNOVAL && 601 vap->va_gid == (gid_t)VNOVAL) 602 return (0); 603 vap->va_size = VNOVAL; 604 break; 605 default: 606 /* 607 * Disallow write attempts if the filesystem is 608 * mounted read-only. 609 */ 610 if (vp->v_mount->mnt_flag & MNT_RDONLY) 611 return (EROFS); 612 if (np->n_flag & NMODIFIED) { 613 if (vap->va_size == 0) 614 error = nfs_vinvalbuf(vp, 0, 615 ap->a_cred, ap->a_p, 1); 616 else 617 error = nfs_vinvalbuf(vp, V_SAVE, 618 ap->a_cred, ap->a_p, 1); 619 if (error) 620 return (error); 621 } 622 tsize = np->n_size; 623 np->n_size = np->n_vattr.va_size = vap->va_size; 624 vnode_pager_setsize(vp, (u_long)np->n_size); 625 }; 626 } else if ((vap->va_mtime.tv_sec != VNOVAL || 627 vap->va_atime.tv_sec != VNOVAL) && (np->n_flag & NMODIFIED) && 628 vp->v_type == VREG && 629 (error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, 630 ap->a_p, 1)) == EINTR) 631 return (error); 632 error = nfs_setattrrpc(vp, vap, ap->a_cred, ap->a_p); 633 if (error && vap->va_size != VNOVAL) { 634 np->n_size = np->n_vattr.va_size = tsize; 635 vnode_pager_setsize(vp, (u_long)np->n_size); 636 } 637 return (error); 638} 639 640/* 641 * Do an nfs setattr rpc. 642 */ 643static int 644nfs_setattrrpc(vp, vap, cred, procp) 645 register struct vnode *vp; 646 register struct vattr *vap; 647 struct ucred *cred; 648 struct proc *procp; 649{ 650 register struct nfsv2_sattr *sp; 651 register caddr_t cp; 652 register long t1, t2; 653 caddr_t bpos, dpos, cp2; 654 u_long *tl; 655 int error = 0, wccflag = NFSV3_WCCRATTR; 656 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 657 int v3 = NFS_ISV3(vp); 658 659 nfsstats.rpccnt[NFSPROC_SETATTR]++; 660 nfsm_reqhead(vp, NFSPROC_SETATTR, NFSX_FH(v3) + NFSX_SATTR(v3)); 661 nfsm_fhtom(vp, v3); 662 if (v3) { 663 if (vap->va_mode != (u_short)VNOVAL) { 664 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 665 *tl++ = nfs_true; 666 *tl = txdr_unsigned(vap->va_mode); 667 } else { 668 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 669 *tl = nfs_false; 670 } 671 if (vap->va_uid != (uid_t)VNOVAL) { 672 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 673 *tl++ = nfs_true; 674 *tl = txdr_unsigned(vap->va_uid); 675 } else { 676 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 677 *tl = nfs_false; 678 } 679 if (vap->va_gid != (gid_t)VNOVAL) { 680 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 681 *tl++ = nfs_true; 682 *tl = txdr_unsigned(vap->va_gid); 683 } else { 684 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 685 *tl = nfs_false; 686 } 687 if (vap->va_size != VNOVAL) { 688 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED); 689 *tl++ = nfs_true; 690 txdr_hyper(&vap->va_size, tl); 691 } else { 692 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 693 *tl = nfs_false; 694 } 695 if (vap->va_atime.tv_sec != VNOVAL) { 696 if (vap->va_atime.tv_sec != time_second) { 697 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED); 698 *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); 699 txdr_nfsv3time(&vap->va_atime, tl); 700 } else { 701 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 702 *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); 703 } 704 } else { 705 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 706 *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); 707 } 708 if (vap->va_mtime.tv_sec != VNOVAL) { 709 if (vap->va_mtime.tv_sec != time_second) { 710 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED); 711 *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); 712 txdr_nfsv3time(&vap->va_mtime, tl); 713 } else { 714 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 715 *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); 716 } 717 } else { 718 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 719 *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); 720 } 721 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 722 *tl = nfs_false; 723 } else { 724 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 725 if (vap->va_mode == (u_short)VNOVAL) 726 sp->sa_mode = VNOVAL; 727 else 728 sp->sa_mode = vtonfsv2_mode(vp->v_type, vap->va_mode); 729 if (vap->va_uid == (uid_t)VNOVAL) 730 sp->sa_uid = VNOVAL; 731 else 732 sp->sa_uid = txdr_unsigned(vap->va_uid); 733 if (vap->va_gid == (gid_t)VNOVAL) 734 sp->sa_gid = VNOVAL; 735 else 736 sp->sa_gid = txdr_unsigned(vap->va_gid); 737 sp->sa_size = txdr_unsigned(vap->va_size); 738 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 739 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 740 } 741 nfsm_request(vp, NFSPROC_SETATTR, procp, cred); 742 if (v3) { 743 nfsm_wcc_data(vp, wccflag); 744 } else 745 nfsm_loadattr(vp, (struct vattr *)0); 746 nfsm_reqdone; 747 return (error); 748} 749 750/* 751 * nfs lookup call, one step at a time... 752 * First look in cache 753 * If not found, unlock the directory nfsnode and do the rpc 754 */ 755static int 756nfs_lookup(ap) 757 struct vop_lookup_args /* { 758 struct vnodeop_desc *a_desc; 759 struct vnode *a_dvp; 760 struct vnode **a_vpp; 761 struct componentname *a_cnp; 762 } */ *ap; 763{ 764 struct componentname *cnp = ap->a_cnp; 765 struct vnode *dvp = ap->a_dvp; 766 struct vnode **vpp = ap->a_vpp; 767 int flags = cnp->cn_flags; 768 struct vnode *newvp; 769 u_long *tl; 770 caddr_t cp; 771 long t1, t2; 772 struct nfsmount *nmp; 773 caddr_t bpos, dpos, cp2; 774 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 775 long len; 776 nfsfh_t *fhp; 777 struct nfsnode *np; 778 int lockparent, wantparent, error = 0, attrflag, fhsize; 779 int v3 = NFS_ISV3(dvp); 780 struct proc *p = cnp->cn_proc; 781 782 *vpp = NULLVP; 783 if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) && 784 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) 785 return (EROFS); 786 if (dvp->v_type != VDIR) 787 return (ENOTDIR); 788 lockparent = flags & LOCKPARENT; 789 wantparent = flags & (LOCKPARENT|WANTPARENT); 790 nmp = VFSTONFS(dvp->v_mount); 791 np = VTONFS(dvp); 792 if ((error = cache_lookup(dvp, vpp, cnp)) && error != ENOENT) { 793 struct vattr vattr; 794 int vpid; 795 796 if (error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, p)) { 797 *vpp = NULLVP; 798 return (error); 799 } 800 801 newvp = *vpp; 802 vpid = newvp->v_id; 803 /* 804 * See the comment starting `Step through' in ufs/ufs_lookup.c 805 * for an explanation of the locking protocol 806 */ 807 if (dvp == newvp) { 808 VREF(newvp); 809 error = 0; 810 } else if (flags & ISDOTDOT) { 811 VOP_UNLOCK(dvp, 0, p); 812 error = vget(newvp, LK_EXCLUSIVE, p); 813 if (!error && lockparent && (flags & ISLASTCN)) 814 error = vn_lock(dvp, LK_EXCLUSIVE, p); 815 } else { 816 error = vget(newvp, LK_EXCLUSIVE, p); 817 if (!lockparent || error || !(flags & ISLASTCN)) 818 VOP_UNLOCK(dvp, 0, p); 819 } 820 if (!error) { 821 if (vpid == newvp->v_id) { 822 if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, p) 823 && vattr.va_ctime.tv_sec == VTONFS(newvp)->n_ctime) { 824 nfsstats.lookupcache_hits++; 825 if (cnp->cn_nameiop != LOOKUP && 826 (flags & ISLASTCN)) 827 cnp->cn_flags |= SAVENAME; 828 return (0); 829 } 830 cache_purge(newvp); 831 } 832 vput(newvp); 833 if (lockparent && dvp != newvp && (flags & ISLASTCN)) 834 VOP_UNLOCK(dvp, 0, p); 835 } 836 error = vn_lock(dvp, LK_EXCLUSIVE, p); 837 *vpp = NULLVP; 838 if (error) 839 return (error); 840 } 841 error = 0; 842 newvp = NULLVP; 843 nfsstats.lookupcache_misses++; 844 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 845 len = cnp->cn_namelen; 846 nfsm_reqhead(dvp, NFSPROC_LOOKUP, 847 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len)); 848 nfsm_fhtom(dvp, v3); 849 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); 850 nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred); 851 if (error) { 852 nfsm_postop_attr(dvp, attrflag); 853 m_freem(mrep); 854 goto nfsmout; 855 } 856 nfsm_getfh(fhp, fhsize, v3); 857 858 /* 859 * Handle RENAME case... 860 */ 861 if (cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)) { 862 if (NFS_CMPFH(np, fhp, fhsize)) { 863 m_freem(mrep); 864 return (EISDIR); 865 } 866 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np); 867 if (error) { 868 m_freem(mrep); 869 return (error); 870 } 871 newvp = NFSTOV(np); 872 if (v3) { 873 nfsm_postop_attr(newvp, attrflag); 874 nfsm_postop_attr(dvp, attrflag); 875 } else 876 nfsm_loadattr(newvp, (struct vattr *)0); 877 *vpp = newvp; 878 m_freem(mrep); 879 cnp->cn_flags |= SAVENAME; 880 if (!lockparent) 881 VOP_UNLOCK(dvp, 0, p); 882 return (0); 883 } 884 885 if (flags & ISDOTDOT) { 886 VOP_UNLOCK(dvp, 0, p); 887 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np); 888 if (error) { 889 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p); 890 return (error); 891 } 892 newvp = NFSTOV(np); 893 if (lockparent && (flags & ISLASTCN) && 894 (error = vn_lock(dvp, LK_EXCLUSIVE, p))) { 895 vput(newvp); 896 return (error); 897 } 898 } else if (NFS_CMPFH(np, fhp, fhsize)) { 899 VREF(dvp); 900 newvp = dvp; 901 } else { 902 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np); 903 if (error) { 904 m_freem(mrep); 905 return (error); 906 } 907 if (!lockparent || !(flags & ISLASTCN)) 908 VOP_UNLOCK(dvp, 0, p); 909 newvp = NFSTOV(np); 910 } 911 if (v3) { 912 nfsm_postop_attr(newvp, attrflag); 913 nfsm_postop_attr(dvp, attrflag); 914 } else 915 nfsm_loadattr(newvp, (struct vattr *)0); 916 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) 917 cnp->cn_flags |= SAVENAME; 918 if ((cnp->cn_flags & MAKEENTRY) && 919 (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) { 920 np->n_ctime = np->n_vattr.va_ctime.tv_sec; 921 cache_enter(dvp, newvp, cnp); 922 } 923 *vpp = newvp; 924 nfsm_reqdone; 925 if (error) { 926 if (newvp != NULLVP) { 927 vrele(newvp); 928 *vpp = NULLVP; 929 } 930 if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) && 931 (flags & ISLASTCN) && error == ENOENT) { 932 if (!lockparent) 933 VOP_UNLOCK(dvp, 0, p); 934 if (dvp->v_mount->mnt_flag & MNT_RDONLY) 935 error = EROFS; 936 else 937 error = EJUSTRETURN; 938 } 939 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) 940 cnp->cn_flags |= SAVENAME; 941 } 942 return (error); 943} 944 945/* 946 * nfs read call. 947 * Just call nfs_bioread() to do the work. 948 */ 949static int 950nfs_read(ap) 951 struct vop_read_args /* { 952 struct vnode *a_vp; 953 struct uio *a_uio; 954 int a_ioflag; 955 struct ucred *a_cred; 956 } */ *ap; 957{ 958 register struct vnode *vp = ap->a_vp; 959 960 if (vp->v_type != VREG) 961 return (EPERM); 962 return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred, 0)); 963} 964 965/* 966 * nfs readlink call 967 */ 968static int 969nfs_readlink(ap) 970 struct vop_readlink_args /* { 971 struct vnode *a_vp; 972 struct uio *a_uio; 973 struct ucred *a_cred; 974 } */ *ap; 975{ 976 register struct vnode *vp = ap->a_vp; 977 978 if (vp->v_type != VLNK) 979 return (EPERM); 980 return (nfs_bioread(vp, ap->a_uio, 0, ap->a_cred, 0)); 981} 982 983/* 984 * Do a readlink rpc. 985 * Called by nfs_doio() from below the buffer cache. 986 */ 987int 988nfs_readlinkrpc(vp, uiop, cred) 989 register struct vnode *vp; 990 struct uio *uiop; 991 struct ucred *cred; 992{ 993 register u_long *tl; 994 register caddr_t cp; 995 register long t1, t2; 996 caddr_t bpos, dpos, cp2; 997 int error = 0, len, attrflag; 998 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 999 int v3 = NFS_ISV3(vp); 1000 1001 nfsstats.rpccnt[NFSPROC_READLINK]++; 1002 nfsm_reqhead(vp, NFSPROC_READLINK, NFSX_FH(v3)); 1003 nfsm_fhtom(vp, v3); 1004 nfsm_request(vp, NFSPROC_READLINK, uiop->uio_procp, cred); 1005 if (v3) 1006 nfsm_postop_attr(vp, attrflag); 1007 if (!error) { 1008 nfsm_strsiz(len, NFS_MAXPATHLEN); 1009 nfsm_mtouio(uiop, len); 1010 } 1011 nfsm_reqdone; 1012 return (error); 1013} 1014 1015/* 1016 * nfs read rpc call 1017 * Ditto above 1018 */ 1019int 1020nfs_readrpc(vp, uiop, cred) 1021 register struct vnode *vp; 1022 struct uio *uiop; 1023 struct ucred *cred; 1024{ 1025 register u_long *tl; 1026 register caddr_t cp; 1027 register long t1, t2; 1028 caddr_t bpos, dpos, cp2; 1029 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1030 struct nfsmount *nmp; 1031 int error = 0, len, retlen, tsiz, eof, attrflag; 1032 int v3 = NFS_ISV3(vp); 1033 1034#ifndef nolint 1035 eof = 0; 1036#endif 1037 nmp = VFSTONFS(vp->v_mount); 1038 tsiz = uiop->uio_resid; 1039 if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize) 1040 return (EFBIG); 1041 while (tsiz > 0) { 1042 nfsstats.rpccnt[NFSPROC_READ]++; 1043 len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz; 1044 nfsm_reqhead(vp, NFSPROC_READ, NFSX_FH(v3) + NFSX_UNSIGNED * 3); 1045 nfsm_fhtom(vp, v3); 1046 nfsm_build(tl, u_long *, NFSX_UNSIGNED * 3); 1047 if (v3) { 1048 txdr_hyper(&uiop->uio_offset, tl); 1049 *(tl + 2) = txdr_unsigned(len); 1050 } else { 1051 *tl++ = txdr_unsigned(uiop->uio_offset); 1052 *tl++ = txdr_unsigned(len); 1053 *tl = 0; 1054 } 1055 nfsm_request(vp, NFSPROC_READ, uiop->uio_procp, cred); 1056 if (v3) { 1057 nfsm_postop_attr(vp, attrflag); 1058 if (error) { 1059 m_freem(mrep); 1060 goto nfsmout; 1061 } 1062 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 1063 eof = fxdr_unsigned(int, *(tl + 1)); 1064 } else 1065 nfsm_loadattr(vp, (struct vattr *)0); 1066 nfsm_strsiz(retlen, nmp->nm_rsize); 1067 nfsm_mtouio(uiop, retlen); 1068 m_freem(mrep); 1069 tsiz -= retlen; 1070 if (v3) { 1071 if (eof || retlen == 0) 1072 tsiz = 0; 1073 } else if (retlen < len) 1074 tsiz = 0; 1075 } 1076nfsmout: 1077 return (error); 1078} 1079 1080/* 1081 * nfs write call 1082 */ 1083int 1084nfs_writerpc(vp, uiop, cred, iomode, must_commit) 1085 register struct vnode *vp; 1086 register struct uio *uiop; 1087 struct ucred *cred; 1088 int *iomode, *must_commit; 1089{ 1090 register u_long *tl; 1091 register caddr_t cp; 1092 register int t1, t2, backup; 1093 caddr_t bpos, dpos, cp2; 1094 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1095 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 1096 int error = 0, len, tsiz, wccflag = NFSV3_WCCRATTR, rlen, commit; 1097 int v3 = NFS_ISV3(vp), committed = NFSV3WRITE_FILESYNC; 1098 1099#ifndef DIAGNOSTIC 1100 if (uiop->uio_iovcnt != 1) 1101 panic("nfs: writerpc iovcnt > 1"); 1102#endif 1103 *must_commit = 0; 1104 tsiz = uiop->uio_resid; 1105 if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize) 1106 return (EFBIG); 1107 while (tsiz > 0) { 1108 nfsstats.rpccnt[NFSPROC_WRITE]++; 1109 len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz; 1110 nfsm_reqhead(vp, NFSPROC_WRITE, 1111 NFSX_FH(v3) + 5 * NFSX_UNSIGNED + nfsm_rndup(len)); 1112 nfsm_fhtom(vp, v3); 1113 if (v3) { 1114 nfsm_build(tl, u_long *, 5 * NFSX_UNSIGNED); 1115 txdr_hyper(&uiop->uio_offset, tl); 1116 tl += 2; 1117 *tl++ = txdr_unsigned(len); 1118 *tl++ = txdr_unsigned(*iomode); 1119 } else { 1120 nfsm_build(tl, u_long *, 4 * NFSX_UNSIGNED); 1121 *++tl = txdr_unsigned(uiop->uio_offset); 1122 tl += 2; 1123 } 1124 *tl = txdr_unsigned(len); 1125 nfsm_uiotom(uiop, len); 1126 nfsm_request(vp, NFSPROC_WRITE, uiop->uio_procp, cred); 1127 if (v3) { 1128 wccflag = NFSV3_WCCCHK; 1129 nfsm_wcc_data(vp, wccflag); 1130 if (!error) { 1131 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED + 1132 NFSX_V3WRITEVERF); 1133 rlen = fxdr_unsigned(int, *tl++); 1134 if (rlen == 0) { 1135 error = NFSERR_IO; 1136 break; 1137 } else if (rlen < len) { 1138 backup = len - rlen; 1139 uiop->uio_iov->iov_base -= backup; 1140 uiop->uio_iov->iov_len += backup; 1141 uiop->uio_offset -= backup; 1142 uiop->uio_resid += backup; 1143 len = rlen; 1144 } 1145 commit = fxdr_unsigned(int, *tl++); 1146 1147 /* 1148 * Return the lowest committment level 1149 * obtained by any of the RPCs. 1150 */ 1151 if (committed == NFSV3WRITE_FILESYNC) 1152 committed = commit; 1153 else if (committed == NFSV3WRITE_DATASYNC && 1154 commit == NFSV3WRITE_UNSTABLE) 1155 committed = commit; 1156 if ((nmp->nm_state & NFSSTA_HASWRITEVERF) == 0){ 1157 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf, 1158 NFSX_V3WRITEVERF); 1159 nmp->nm_state |= NFSSTA_HASWRITEVERF; 1160 } else if (bcmp((caddr_t)tl, 1161 (caddr_t)nmp->nm_verf, NFSX_V3WRITEVERF)) { 1162 *must_commit = 1; 1163 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf, 1164 NFSX_V3WRITEVERF); 1165 } 1166 } 1167 } else 1168 nfsm_loadattr(vp, (struct vattr *)0); 1169 if (wccflag) 1170 VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime.tv_sec; 1171 m_freem(mrep); 1172 tsiz -= len; 1173 } 1174nfsmout: 1175 if (vp->v_mount->mnt_flag & MNT_ASYNC) 1176 committed = NFSV3WRITE_FILESYNC; 1177 *iomode = committed; 1178 if (error) 1179 uiop->uio_resid = tsiz; 1180 return (error); 1181} 1182 1183/* 1184 * nfs mknod rpc 1185 * For NFS v2 this is a kludge. Use a create rpc but with the IFMT bits of the 1186 * mode set to specify the file type and the size field for rdev. 1187 */ 1188static int 1189nfs_mknodrpc(dvp, vpp, cnp, vap) 1190 register struct vnode *dvp; 1191 register struct vnode **vpp; 1192 register struct componentname *cnp; 1193 register struct vattr *vap; 1194{ 1195 register struct nfsv2_sattr *sp; 1196 register struct nfsv3_sattr *sp3; 1197 register u_long *tl; 1198 register caddr_t cp; 1199 register long t1, t2; 1200 struct vnode *newvp = (struct vnode *)0; 1201 struct nfsnode *np = (struct nfsnode *)0; 1202 struct vattr vattr; 1203 char *cp2; 1204 caddr_t bpos, dpos; 1205 int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0; 1206 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1207 u_long rdev; 1208 int v3 = NFS_ISV3(dvp); 1209 1210 if (vap->va_type == VCHR || vap->va_type == VBLK) 1211 rdev = txdr_unsigned(vap->va_rdev); 1212 else if (vap->va_type == VFIFO || vap->va_type == VSOCK) 1213 rdev = 0xffffffff; 1214 else { 1215 VOP_ABORTOP(dvp, cnp); 1216 return (EOPNOTSUPP); 1217 } 1218 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 1219 VOP_ABORTOP(dvp, cnp); 1220 return (error); 1221 } 1222 nfsstats.rpccnt[NFSPROC_MKNOD]++; 1223 nfsm_reqhead(dvp, NFSPROC_MKNOD, NFSX_FH(v3) + 4 * NFSX_UNSIGNED + 1224 + nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3)); 1225 nfsm_fhtom(dvp, v3); 1226 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1227 if (v3) { 1228 nfsm_build(tl, u_long *, NFSX_UNSIGNED + NFSX_V3SRVSATTR); 1229 *tl++ = vtonfsv3_type(vap->va_type); 1230 sp3 = (struct nfsv3_sattr *)tl; 1231 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, vattr.va_gid); 1232 if (vap->va_type == VCHR || vap->va_type == VBLK) { 1233 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 1234 *tl++ = txdr_unsigned(major(vap->va_rdev)); 1235 *tl = txdr_unsigned(minor(vap->va_rdev)); 1236 } 1237 } else { 1238 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1239 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode); 1240 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1241 sp->sa_gid = txdr_unsigned(vattr.va_gid); 1242 sp->sa_size = rdev; 1243 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1244 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1245 } 1246 nfsm_request(dvp, NFSPROC_MKNOD, cnp->cn_proc, cnp->cn_cred); 1247 if (!error) { 1248 nfsm_mtofh(dvp, newvp, v3, gotvp); 1249 if (!gotvp) { 1250 if (newvp) { 1251 vput(newvp); 1252 newvp = (struct vnode *)0; 1253 } 1254 error = nfs_lookitup(dvp, cnp->cn_nameptr, 1255 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc, &np); 1256 if (!error) 1257 newvp = NFSTOV(np); 1258 } 1259 } 1260 if (v3) 1261 nfsm_wcc_data(dvp, wccflag); 1262 nfsm_reqdone; 1263 if (error) { 1264 if (newvp) 1265 vput(newvp); 1266 } else { 1267 if (cnp->cn_flags & MAKEENTRY) 1268 cache_enter(dvp, newvp, cnp); 1269 *vpp = newvp; 1270 } 1271 zfree(namei_zone, cnp->cn_pnbuf); 1272 VTONFS(dvp)->n_flag |= NMODIFIED; 1273 if (!wccflag) 1274 VTONFS(dvp)->n_attrstamp = 0; 1275 return (error); 1276} 1277 1278/* 1279 * nfs mknod vop 1280 * just call nfs_mknodrpc() to do the work. 1281 */ 1282/* ARGSUSED */ 1283static int 1284nfs_mknod(ap) 1285 struct vop_mknod_args /* { 1286 struct vnode *a_dvp; 1287 struct vnode **a_vpp; 1288 struct componentname *a_cnp; 1289 struct vattr *a_vap; 1290 } */ *ap; 1291{ 1292 struct vnode *newvp; 1293 int error; 1294 1295 error = nfs_mknodrpc(ap->a_dvp, &newvp, ap->a_cnp, ap->a_vap); 1296 if (!error) 1297 vput(newvp); 1298 return (error); 1299} 1300 1301static u_long create_verf; 1302/* 1303 * nfs file create call 1304 */ 1305static int 1306nfs_create(ap) 1307 struct vop_create_args /* { 1308 struct vnode *a_dvp; 1309 struct vnode **a_vpp; 1310 struct componentname *a_cnp; 1311 struct vattr *a_vap; 1312 } */ *ap; 1313{ 1314 register struct vnode *dvp = ap->a_dvp; 1315 register struct vattr *vap = ap->a_vap; 1316 register struct componentname *cnp = ap->a_cnp; 1317 register struct nfsv2_sattr *sp; 1318 register struct nfsv3_sattr *sp3; 1319 register u_long *tl; 1320 register caddr_t cp; 1321 register long t1, t2; 1322 struct nfsnode *np = (struct nfsnode *)0; 1323 struct vnode *newvp = (struct vnode *)0; 1324 caddr_t bpos, dpos, cp2; 1325 int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0, fmode = 0; 1326 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1327 struct vattr vattr; 1328 int v3 = NFS_ISV3(dvp); 1329 1330 /* 1331 * Oops, not for me.. 1332 */ 1333 if (vap->va_type == VSOCK) 1334 return (nfs_mknodrpc(dvp, ap->a_vpp, cnp, vap)); 1335 1336 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 1337 VOP_ABORTOP(dvp, cnp); 1338 return (error); 1339 } 1340 if (vap->va_vaflags & VA_EXCLUSIVE) 1341 fmode |= O_EXCL; 1342again: 1343 nfsstats.rpccnt[NFSPROC_CREATE]++; 1344 nfsm_reqhead(dvp, NFSPROC_CREATE, NFSX_FH(v3) + 2 * NFSX_UNSIGNED + 1345 nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3)); 1346 nfsm_fhtom(dvp, v3); 1347 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1348 if (v3) { 1349 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 1350 if (fmode & O_EXCL) { 1351 *tl = txdr_unsigned(NFSV3CREATE_EXCLUSIVE); 1352 nfsm_build(tl, u_long *, NFSX_V3CREATEVERF); 1353#ifdef INET 1354 if (!TAILQ_EMPTY(&in_ifaddrhead)) 1355 *tl++ = IA_SIN(in_ifaddrhead.tqh_first)->sin_addr.s_addr; 1356 else 1357#endif 1358 *tl++ = create_verf; 1359 *tl = ++create_verf; 1360 } else { 1361 *tl = txdr_unsigned(NFSV3CREATE_UNCHECKED); 1362 nfsm_build(tl, u_long *, NFSX_V3SRVSATTR); 1363 sp3 = (struct nfsv3_sattr *)tl; 1364 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, vattr.va_gid); 1365 } 1366 } else { 1367 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1368 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode); 1369 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1370 sp->sa_gid = txdr_unsigned(vattr.va_gid); 1371 sp->sa_size = 0; 1372 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1373 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1374 } 1375 nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred); 1376 if (!error) { 1377 nfsm_mtofh(dvp, newvp, v3, gotvp); 1378 if (!gotvp) { 1379 if (newvp) { 1380 vput(newvp); 1381 newvp = (struct vnode *)0; 1382 } 1383 error = nfs_lookitup(dvp, cnp->cn_nameptr, 1384 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc, &np); 1385 if (!error) 1386 newvp = NFSTOV(np); 1387 } 1388 } 1389 if (v3) 1390 nfsm_wcc_data(dvp, wccflag); 1391 nfsm_reqdone; 1392 if (error) { 1393 if (v3 && (fmode & O_EXCL) && error == NFSERR_NOTSUPP) { 1394 fmode &= ~O_EXCL; 1395 goto again; 1396 } 1397 if (newvp) 1398 vput(newvp); 1399 } else if (v3 && (fmode & O_EXCL)) 1400 error = nfs_setattrrpc(newvp, vap, cnp->cn_cred, cnp->cn_proc); 1401 if (!error) { 1402 if (cnp->cn_flags & MAKEENTRY) 1403 cache_enter(dvp, newvp, cnp); 1404 *ap->a_vpp = newvp; 1405 } 1406 zfree(namei_zone, cnp->cn_pnbuf); 1407 VTONFS(dvp)->n_flag |= NMODIFIED; 1408 if (!wccflag) 1409 VTONFS(dvp)->n_attrstamp = 0; 1410 return (error); 1411} 1412 1413/* 1414 * nfs file remove call 1415 * To try and make nfs semantics closer to ufs semantics, a file that has 1416 * other processes using the vnode is renamed instead of removed and then 1417 * removed later on the last close. 1418 * - If v_usecount > 1 1419 * If a rename is not already in the works 1420 * call nfs_sillyrename() to set it up 1421 * else 1422 * do the remove rpc 1423 */ 1424static int 1425nfs_remove(ap) 1426 struct vop_remove_args /* { 1427 struct vnodeop_desc *a_desc; 1428 struct vnode * a_dvp; 1429 struct vnode * a_vp; 1430 struct componentname * a_cnp; 1431 } */ *ap; 1432{ 1433 register struct vnode *vp = ap->a_vp; 1434 register struct vnode *dvp = ap->a_dvp; 1435 register struct componentname *cnp = ap->a_cnp; 1436 register struct nfsnode *np = VTONFS(vp); 1437 int error = 0; 1438 struct vattr vattr; 1439 1440#ifndef DIAGNOSTIC 1441 if ((cnp->cn_flags & HASBUF) == 0) 1442 panic("nfs_remove: no name"); 1443 if (vp->v_usecount < 1) 1444 panic("nfs_remove: bad v_usecount"); 1445#endif 1446 if (vp->v_usecount == 1 || (np->n_sillyrename && 1447 VOP_GETATTR(vp, &vattr, cnp->cn_cred, cnp->cn_proc) == 0 && 1448 vattr.va_nlink > 1)) { 1449 /* 1450 * Purge the name cache so that the chance of a lookup for 1451 * the name succeeding while the remove is in progress is 1452 * minimized. Without node locking it can still happen, such 1453 * that an I/O op returns ESTALE, but since you get this if 1454 * another host removes the file.. 1455 */ 1456 cache_purge(vp); 1457 /* 1458 * throw away biocache buffers, mainly to avoid 1459 * unnecessary delayed writes later. 1460 */ 1461 error = nfs_vinvalbuf(vp, 0, cnp->cn_cred, cnp->cn_proc, 1); 1462 /* Do the rpc */ 1463 if (error != EINTR) 1464 error = nfs_removerpc(dvp, cnp->cn_nameptr, 1465 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc); 1466 /* 1467 * Kludge City: If the first reply to the remove rpc is lost.. 1468 * the reply to the retransmitted request will be ENOENT 1469 * since the file was in fact removed 1470 * Therefore, we cheat and return success. 1471 */ 1472 if (error == ENOENT) 1473 error = 0; 1474 } else if (!np->n_sillyrename) 1475 error = nfs_sillyrename(dvp, vp, cnp); 1476 zfree(namei_zone, cnp->cn_pnbuf); 1477 np->n_attrstamp = 0; 1478 return (error); 1479} 1480 1481/* 1482 * nfs file remove rpc called from nfs_inactive 1483 */ 1484int 1485nfs_removeit(sp) 1486 register struct sillyrename *sp; 1487{ 1488 1489 return (nfs_removerpc(sp->s_dvp, sp->s_name, sp->s_namlen, sp->s_cred, 1490 (struct proc *)0)); 1491} 1492 1493/* 1494 * Nfs remove rpc, called from nfs_remove() and nfs_removeit(). 1495 */ 1496static int 1497nfs_removerpc(dvp, name, namelen, cred, proc) 1498 register struct vnode *dvp;
| 232 struct ucred *cred, struct proc *proc)); 233static int nfs_renameit __P((struct vnode *sdvp, 234 struct componentname *scnp, 235 struct sillyrename *sp)); 236 237/* 238 * Global variables 239 */ 240extern u_long nfs_true, nfs_false; 241extern struct nfsstats nfsstats; 242extern nfstype nfsv3_type[9]; 243struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON]; 244struct nfsmount *nfs_iodmount[NFS_MAXASYNCDAEMON]; 245int nfs_numasync = 0; 246#define DIRHDSIZ (sizeof (struct dirent) - (MAXNAMLEN + 1)) 247 248/* 249 * nfs access vnode op. 250 * For nfs version 2, just return ok. File accesses may fail later. 251 * For nfs version 3, use the access rpc to check accessibility. If file modes 252 * are changed on the server, accesses might still fail later. 253 */ 254static int 255nfs_access(ap) 256 struct vop_access_args /* { 257 struct vnode *a_vp; 258 int a_mode; 259 struct ucred *a_cred; 260 struct proc *a_p; 261 } */ *ap; 262{ 263 register struct vnode *vp = ap->a_vp; 264 register u_long *tl; 265 register caddr_t cp; 266 register int t1, t2; 267 caddr_t bpos, dpos, cp2; 268 int error = 0, attrflag; 269 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 270 u_long mode, rmode; 271 int v3 = NFS_ISV3(vp); 272 273 /* 274 * Disallow write attempts on filesystems mounted read-only; 275 * unless the file is a socket, fifo, or a block or character 276 * device resident on the filesystem. 277 */ 278 if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) { 279 switch (vp->v_type) { 280 case VREG: 281 case VDIR: 282 case VLNK: 283 return (EROFS); 284 default: 285 break; 286 } 287 } 288 /* 289 * For nfs v3, do an access rpc, otherwise you are stuck emulating 290 * ufs_access() locally using the vattr. This may not be correct, 291 * since the server may apply other access criteria such as 292 * client uid-->server uid mapping that we do not know about, but 293 * this is better than just returning anything that is lying about 294 * in the cache. 295 */ 296 if (v3) { 297 nfsstats.rpccnt[NFSPROC_ACCESS]++; 298 nfsm_reqhead(vp, NFSPROC_ACCESS, NFSX_FH(v3) + NFSX_UNSIGNED); 299 nfsm_fhtom(vp, v3); 300 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 301 if (ap->a_mode & VREAD) 302 mode = NFSV3ACCESS_READ; 303 else 304 mode = 0; 305 if (vp->v_type != VDIR) { 306 if (ap->a_mode & VWRITE) 307 mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND); 308 if (ap->a_mode & VEXEC) 309 mode |= NFSV3ACCESS_EXECUTE; 310 } else { 311 if (ap->a_mode & VWRITE) 312 mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND | 313 NFSV3ACCESS_DELETE); 314 if (ap->a_mode & VEXEC) 315 mode |= NFSV3ACCESS_LOOKUP; 316 } 317 *tl = txdr_unsigned(mode); 318 nfsm_request(vp, NFSPROC_ACCESS, ap->a_p, ap->a_cred); 319 nfsm_postop_attr(vp, attrflag); 320 if (!error) { 321 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 322 rmode = fxdr_unsigned(u_long, *tl); 323 /* 324 * The NFS V3 spec does not clarify whether or not 325 * the returned access bits can be a superset of 326 * the ones requested, so... 327 */ 328 if ((rmode & mode) != mode) 329 error = EACCES; 330 } 331 nfsm_reqdone; 332 return (error); 333 } else { 334 if (error = nfsspec_access(ap)) 335 return (error); 336 337 /* 338 * Attempt to prevent a mapped root from accessing a file 339 * which it shouldn't. We try to read a byte from the file 340 * if the user is root and the file is not zero length. 341 * After calling nfsspec_access, we should have the correct 342 * file size cached. 343 */ 344 if (ap->a_cred->cr_uid == 0 && (ap->a_mode & VREAD) 345 && VTONFS(vp)->n_size > 0) { 346 struct iovec aiov; 347 struct uio auio; 348 char buf[1]; 349 350 aiov.iov_base = buf; 351 aiov.iov_len = 1; 352 auio.uio_iov = &aiov; 353 auio.uio_iovcnt = 1; 354 auio.uio_offset = 0; 355 auio.uio_resid = 1; 356 auio.uio_segflg = UIO_SYSSPACE; 357 auio.uio_rw = UIO_READ; 358 auio.uio_procp = ap->a_p; 359 360 if (vp->v_type == VREG) 361 error = nfs_readrpc(vp, &auio, ap->a_cred); 362 else if (vp->v_type == VDIR) { 363 char* bp; 364 bp = malloc(NFS_DIRBLKSIZ, M_TEMP, M_WAITOK); 365 aiov.iov_base = bp; 366 aiov.iov_len = auio.uio_resid = NFS_DIRBLKSIZ; 367 error = nfs_readdirrpc(vp, &auio, ap->a_cred); 368 free(bp, M_TEMP); 369 } else if (vp->v_type = VLNK) 370 error = nfs_readlinkrpc(vp, &auio, ap->a_cred); 371 else 372 error = EACCES; 373 } 374 return (error); 375 } 376} 377 378/* 379 * nfs open vnode op 380 * Check to see if the type is ok 381 * and that deletion is not in progress. 382 * For paged in text files, you will need to flush the page cache 383 * if consistency is lost. 384 */ 385/* ARGSUSED */ 386static int 387nfs_open(ap) 388 struct vop_open_args /* { 389 struct vnode *a_vp; 390 int a_mode; 391 struct ucred *a_cred; 392 struct proc *a_p; 393 } */ *ap; 394{ 395 register struct vnode *vp = ap->a_vp; 396 struct nfsnode *np = VTONFS(vp); 397 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 398 struct vattr vattr; 399 int error; 400 401 if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) { 402 printf("open eacces vtyp=%d\n",vp->v_type); 403 return (EACCES); 404 } 405 /* 406 * Get a valid lease. If cached data is stale, flush it. 407 */ 408 if (nmp->nm_flag & NFSMNT_NQNFS) { 409 if (NQNFS_CKINVALID(vp, np, ND_READ)) { 410 do { 411 error = nqnfs_getlease(vp, ND_READ, ap->a_cred, 412 ap->a_p); 413 } while (error == NQNFS_EXPIRED); 414 if (error) 415 return (error); 416 if (np->n_lrev != np->n_brev || 417 (np->n_flag & NQNFSNONCACHE)) { 418 if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, 419 ap->a_p, 1)) == EINTR) 420 return (error); 421 np->n_brev = np->n_lrev; 422 } 423 } 424 } else { 425 if (np->n_flag & NMODIFIED) { 426 if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, 427 ap->a_p, 1)) == EINTR) 428 return (error); 429 np->n_attrstamp = 0; 430 if (vp->v_type == VDIR) 431 np->n_direofoffset = 0; 432 error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p); 433 if (error) 434 return (error); 435 np->n_mtime = vattr.va_mtime.tv_sec; 436 } else { 437 error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p); 438 if (error) 439 return (error); 440 if (np->n_mtime != vattr.va_mtime.tv_sec) { 441 if (vp->v_type == VDIR) 442 np->n_direofoffset = 0; 443 if ((error = nfs_vinvalbuf(vp, V_SAVE, 444 ap->a_cred, ap->a_p, 1)) == EINTR) 445 return (error); 446 np->n_mtime = vattr.va_mtime.tv_sec; 447 } 448 } 449 } 450 if ((nmp->nm_flag & NFSMNT_NQNFS) == 0) 451 np->n_attrstamp = 0; /* For Open/Close consistency */ 452 return (0); 453} 454 455/* 456 * nfs close vnode op 457 * What an NFS client should do upon close after writing is a debatable issue. 458 * Most NFS clients push delayed writes to the server upon close, basically for 459 * two reasons: 460 * 1 - So that any write errors may be reported back to the client process 461 * doing the close system call. By far the two most likely errors are 462 * NFSERR_NOSPC and NFSERR_DQUOT to indicate space allocation failure. 463 * 2 - To put a worst case upper bound on cache inconsistency between 464 * multiple clients for the file. 465 * There is also a consistency problem for Version 2 of the protocol w.r.t. 466 * not being able to tell if other clients are writing a file concurrently, 467 * since there is no way of knowing if the changed modify time in the reply 468 * is only due to the write for this client. 469 * (NFS Version 3 provides weak cache consistency data in the reply that 470 * should be sufficient to detect and handle this case.) 471 * 472 * The current code does the following: 473 * for NFS Version 2 - play it safe and flush/invalidate all dirty buffers 474 * for NFS Version 3 - flush dirty buffers to the server but don't invalidate 475 * or commit them (this satisfies 1 and 2 except for the 476 * case where the server crashes after this close but 477 * before the commit RPC, which is felt to be "good 478 * enough". Changing the last argument to nfs_flush() to 479 * a 1 would force a commit operation, if it is felt a 480 * commit is necessary now. 481 * for NQNFS - do nothing now, since 2 is dealt with via leases and 482 * 1 should be dealt with via an fsync() system call for 483 * cases where write errors are important. 484 */ 485/* ARGSUSED */ 486static int 487nfs_close(ap) 488 struct vop_close_args /* { 489 struct vnodeop_desc *a_desc; 490 struct vnode *a_vp; 491 int a_fflag; 492 struct ucred *a_cred; 493 struct proc *a_p; 494 } */ *ap; 495{ 496 register struct vnode *vp = ap->a_vp; 497 register struct nfsnode *np = VTONFS(vp); 498 int error = 0; 499 500 if (vp->v_type == VREG) { 501 if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) == 0 && 502 (np->n_flag & NMODIFIED)) { 503 if (NFS_ISV3(vp)) { 504 error = nfs_flush(vp, ap->a_cred, MNT_WAIT, ap->a_p, 0); 505 np->n_flag &= ~NMODIFIED; 506 } else 507 error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 1); 508 np->n_attrstamp = 0; 509 } 510 if (np->n_flag & NWRITEERR) { 511 np->n_flag &= ~NWRITEERR; 512 error = np->n_error; 513 } 514 } 515 return (error); 516} 517 518/* 519 * nfs getattr call from vfs. 520 */ 521static int 522nfs_getattr(ap) 523 struct vop_getattr_args /* { 524 struct vnode *a_vp; 525 struct vattr *a_vap; 526 struct ucred *a_cred; 527 struct proc *a_p; 528 } */ *ap; 529{ 530 register struct vnode *vp = ap->a_vp; 531 register struct nfsnode *np = VTONFS(vp); 532 register caddr_t cp; 533 register u_long *tl; 534 register int t1, t2; 535 caddr_t bpos, dpos; 536 int error = 0; 537 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 538 int v3 = NFS_ISV3(vp); 539 540 /* 541 * Update local times for special files. 542 */ 543 if (np->n_flag & (NACC | NUPD)) 544 np->n_flag |= NCHG; 545 /* 546 * First look in the cache. 547 */ 548 if (nfs_getattrcache(vp, ap->a_vap) == 0) 549 return (0); 550 nfsstats.rpccnt[NFSPROC_GETATTR]++; 551 nfsm_reqhead(vp, NFSPROC_GETATTR, NFSX_FH(v3)); 552 nfsm_fhtom(vp, v3); 553 nfsm_request(vp, NFSPROC_GETATTR, ap->a_p, ap->a_cred); 554 if (!error) { 555 nfsm_loadattr(vp, ap->a_vap); 556 } 557 nfsm_reqdone; 558 return (error); 559} 560 561/* 562 * nfs setattr call. 563 */ 564static int 565nfs_setattr(ap) 566 struct vop_setattr_args /* { 567 struct vnodeop_desc *a_desc; 568 struct vnode *a_vp; 569 struct vattr *a_vap; 570 struct ucred *a_cred; 571 struct proc *a_p; 572 } */ *ap; 573{ 574 register struct vnode *vp = ap->a_vp; 575 register struct nfsnode *np = VTONFS(vp); 576 register struct vattr *vap = ap->a_vap; 577 int error = 0; 578 u_quad_t tsize; 579 580#ifndef nolint 581 tsize = (u_quad_t)0; 582#endif 583 /* 584 * Disallow write attempts if the filesystem is mounted read-only. 585 */ 586 if ((vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL || 587 vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || 588 vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) && 589 (vp->v_mount->mnt_flag & MNT_RDONLY)) 590 return (EROFS); 591 if (vap->va_size != VNOVAL) { 592 switch (vp->v_type) { 593 case VDIR: 594 return (EISDIR); 595 case VCHR: 596 case VBLK: 597 case VSOCK: 598 case VFIFO: 599 if (vap->va_mtime.tv_sec == VNOVAL && 600 vap->va_atime.tv_sec == VNOVAL && 601 vap->va_mode == (u_short)VNOVAL && 602 vap->va_uid == (uid_t)VNOVAL && 603 vap->va_gid == (gid_t)VNOVAL) 604 return (0); 605 vap->va_size = VNOVAL; 606 break; 607 default: 608 /* 609 * Disallow write attempts if the filesystem is 610 * mounted read-only. 611 */ 612 if (vp->v_mount->mnt_flag & MNT_RDONLY) 613 return (EROFS); 614 if (np->n_flag & NMODIFIED) { 615 if (vap->va_size == 0) 616 error = nfs_vinvalbuf(vp, 0, 617 ap->a_cred, ap->a_p, 1); 618 else 619 error = nfs_vinvalbuf(vp, V_SAVE, 620 ap->a_cred, ap->a_p, 1); 621 if (error) 622 return (error); 623 } 624 tsize = np->n_size; 625 np->n_size = np->n_vattr.va_size = vap->va_size; 626 vnode_pager_setsize(vp, (u_long)np->n_size); 627 }; 628 } else if ((vap->va_mtime.tv_sec != VNOVAL || 629 vap->va_atime.tv_sec != VNOVAL) && (np->n_flag & NMODIFIED) && 630 vp->v_type == VREG && 631 (error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, 632 ap->a_p, 1)) == EINTR) 633 return (error); 634 error = nfs_setattrrpc(vp, vap, ap->a_cred, ap->a_p); 635 if (error && vap->va_size != VNOVAL) { 636 np->n_size = np->n_vattr.va_size = tsize; 637 vnode_pager_setsize(vp, (u_long)np->n_size); 638 } 639 return (error); 640} 641 642/* 643 * Do an nfs setattr rpc. 644 */ 645static int 646nfs_setattrrpc(vp, vap, cred, procp) 647 register struct vnode *vp; 648 register struct vattr *vap; 649 struct ucred *cred; 650 struct proc *procp; 651{ 652 register struct nfsv2_sattr *sp; 653 register caddr_t cp; 654 register long t1, t2; 655 caddr_t bpos, dpos, cp2; 656 u_long *tl; 657 int error = 0, wccflag = NFSV3_WCCRATTR; 658 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 659 int v3 = NFS_ISV3(vp); 660 661 nfsstats.rpccnt[NFSPROC_SETATTR]++; 662 nfsm_reqhead(vp, NFSPROC_SETATTR, NFSX_FH(v3) + NFSX_SATTR(v3)); 663 nfsm_fhtom(vp, v3); 664 if (v3) { 665 if (vap->va_mode != (u_short)VNOVAL) { 666 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 667 *tl++ = nfs_true; 668 *tl = txdr_unsigned(vap->va_mode); 669 } else { 670 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 671 *tl = nfs_false; 672 } 673 if (vap->va_uid != (uid_t)VNOVAL) { 674 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 675 *tl++ = nfs_true; 676 *tl = txdr_unsigned(vap->va_uid); 677 } else { 678 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 679 *tl = nfs_false; 680 } 681 if (vap->va_gid != (gid_t)VNOVAL) { 682 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 683 *tl++ = nfs_true; 684 *tl = txdr_unsigned(vap->va_gid); 685 } else { 686 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 687 *tl = nfs_false; 688 } 689 if (vap->va_size != VNOVAL) { 690 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED); 691 *tl++ = nfs_true; 692 txdr_hyper(&vap->va_size, tl); 693 } else { 694 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 695 *tl = nfs_false; 696 } 697 if (vap->va_atime.tv_sec != VNOVAL) { 698 if (vap->va_atime.tv_sec != time_second) { 699 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED); 700 *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); 701 txdr_nfsv3time(&vap->va_atime, tl); 702 } else { 703 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 704 *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); 705 } 706 } else { 707 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 708 *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); 709 } 710 if (vap->va_mtime.tv_sec != VNOVAL) { 711 if (vap->va_mtime.tv_sec != time_second) { 712 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED); 713 *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); 714 txdr_nfsv3time(&vap->va_mtime, tl); 715 } else { 716 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 717 *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); 718 } 719 } else { 720 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 721 *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); 722 } 723 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 724 *tl = nfs_false; 725 } else { 726 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 727 if (vap->va_mode == (u_short)VNOVAL) 728 sp->sa_mode = VNOVAL; 729 else 730 sp->sa_mode = vtonfsv2_mode(vp->v_type, vap->va_mode); 731 if (vap->va_uid == (uid_t)VNOVAL) 732 sp->sa_uid = VNOVAL; 733 else 734 sp->sa_uid = txdr_unsigned(vap->va_uid); 735 if (vap->va_gid == (gid_t)VNOVAL) 736 sp->sa_gid = VNOVAL; 737 else 738 sp->sa_gid = txdr_unsigned(vap->va_gid); 739 sp->sa_size = txdr_unsigned(vap->va_size); 740 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 741 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 742 } 743 nfsm_request(vp, NFSPROC_SETATTR, procp, cred); 744 if (v3) { 745 nfsm_wcc_data(vp, wccflag); 746 } else 747 nfsm_loadattr(vp, (struct vattr *)0); 748 nfsm_reqdone; 749 return (error); 750} 751 752/* 753 * nfs lookup call, one step at a time... 754 * First look in cache 755 * If not found, unlock the directory nfsnode and do the rpc 756 */ 757static int 758nfs_lookup(ap) 759 struct vop_lookup_args /* { 760 struct vnodeop_desc *a_desc; 761 struct vnode *a_dvp; 762 struct vnode **a_vpp; 763 struct componentname *a_cnp; 764 } */ *ap; 765{ 766 struct componentname *cnp = ap->a_cnp; 767 struct vnode *dvp = ap->a_dvp; 768 struct vnode **vpp = ap->a_vpp; 769 int flags = cnp->cn_flags; 770 struct vnode *newvp; 771 u_long *tl; 772 caddr_t cp; 773 long t1, t2; 774 struct nfsmount *nmp; 775 caddr_t bpos, dpos, cp2; 776 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 777 long len; 778 nfsfh_t *fhp; 779 struct nfsnode *np; 780 int lockparent, wantparent, error = 0, attrflag, fhsize; 781 int v3 = NFS_ISV3(dvp); 782 struct proc *p = cnp->cn_proc; 783 784 *vpp = NULLVP; 785 if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) && 786 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) 787 return (EROFS); 788 if (dvp->v_type != VDIR) 789 return (ENOTDIR); 790 lockparent = flags & LOCKPARENT; 791 wantparent = flags & (LOCKPARENT|WANTPARENT); 792 nmp = VFSTONFS(dvp->v_mount); 793 np = VTONFS(dvp); 794 if ((error = cache_lookup(dvp, vpp, cnp)) && error != ENOENT) { 795 struct vattr vattr; 796 int vpid; 797 798 if (error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, p)) { 799 *vpp = NULLVP; 800 return (error); 801 } 802 803 newvp = *vpp; 804 vpid = newvp->v_id; 805 /* 806 * See the comment starting `Step through' in ufs/ufs_lookup.c 807 * for an explanation of the locking protocol 808 */ 809 if (dvp == newvp) { 810 VREF(newvp); 811 error = 0; 812 } else if (flags & ISDOTDOT) { 813 VOP_UNLOCK(dvp, 0, p); 814 error = vget(newvp, LK_EXCLUSIVE, p); 815 if (!error && lockparent && (flags & ISLASTCN)) 816 error = vn_lock(dvp, LK_EXCLUSIVE, p); 817 } else { 818 error = vget(newvp, LK_EXCLUSIVE, p); 819 if (!lockparent || error || !(flags & ISLASTCN)) 820 VOP_UNLOCK(dvp, 0, p); 821 } 822 if (!error) { 823 if (vpid == newvp->v_id) { 824 if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, p) 825 && vattr.va_ctime.tv_sec == VTONFS(newvp)->n_ctime) { 826 nfsstats.lookupcache_hits++; 827 if (cnp->cn_nameiop != LOOKUP && 828 (flags & ISLASTCN)) 829 cnp->cn_flags |= SAVENAME; 830 return (0); 831 } 832 cache_purge(newvp); 833 } 834 vput(newvp); 835 if (lockparent && dvp != newvp && (flags & ISLASTCN)) 836 VOP_UNLOCK(dvp, 0, p); 837 } 838 error = vn_lock(dvp, LK_EXCLUSIVE, p); 839 *vpp = NULLVP; 840 if (error) 841 return (error); 842 } 843 error = 0; 844 newvp = NULLVP; 845 nfsstats.lookupcache_misses++; 846 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 847 len = cnp->cn_namelen; 848 nfsm_reqhead(dvp, NFSPROC_LOOKUP, 849 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len)); 850 nfsm_fhtom(dvp, v3); 851 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); 852 nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred); 853 if (error) { 854 nfsm_postop_attr(dvp, attrflag); 855 m_freem(mrep); 856 goto nfsmout; 857 } 858 nfsm_getfh(fhp, fhsize, v3); 859 860 /* 861 * Handle RENAME case... 862 */ 863 if (cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)) { 864 if (NFS_CMPFH(np, fhp, fhsize)) { 865 m_freem(mrep); 866 return (EISDIR); 867 } 868 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np); 869 if (error) { 870 m_freem(mrep); 871 return (error); 872 } 873 newvp = NFSTOV(np); 874 if (v3) { 875 nfsm_postop_attr(newvp, attrflag); 876 nfsm_postop_attr(dvp, attrflag); 877 } else 878 nfsm_loadattr(newvp, (struct vattr *)0); 879 *vpp = newvp; 880 m_freem(mrep); 881 cnp->cn_flags |= SAVENAME; 882 if (!lockparent) 883 VOP_UNLOCK(dvp, 0, p); 884 return (0); 885 } 886 887 if (flags & ISDOTDOT) { 888 VOP_UNLOCK(dvp, 0, p); 889 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np); 890 if (error) { 891 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p); 892 return (error); 893 } 894 newvp = NFSTOV(np); 895 if (lockparent && (flags & ISLASTCN) && 896 (error = vn_lock(dvp, LK_EXCLUSIVE, p))) { 897 vput(newvp); 898 return (error); 899 } 900 } else if (NFS_CMPFH(np, fhp, fhsize)) { 901 VREF(dvp); 902 newvp = dvp; 903 } else { 904 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np); 905 if (error) { 906 m_freem(mrep); 907 return (error); 908 } 909 if (!lockparent || !(flags & ISLASTCN)) 910 VOP_UNLOCK(dvp, 0, p); 911 newvp = NFSTOV(np); 912 } 913 if (v3) { 914 nfsm_postop_attr(newvp, attrflag); 915 nfsm_postop_attr(dvp, attrflag); 916 } else 917 nfsm_loadattr(newvp, (struct vattr *)0); 918 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) 919 cnp->cn_flags |= SAVENAME; 920 if ((cnp->cn_flags & MAKEENTRY) && 921 (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) { 922 np->n_ctime = np->n_vattr.va_ctime.tv_sec; 923 cache_enter(dvp, newvp, cnp); 924 } 925 *vpp = newvp; 926 nfsm_reqdone; 927 if (error) { 928 if (newvp != NULLVP) { 929 vrele(newvp); 930 *vpp = NULLVP; 931 } 932 if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) && 933 (flags & ISLASTCN) && error == ENOENT) { 934 if (!lockparent) 935 VOP_UNLOCK(dvp, 0, p); 936 if (dvp->v_mount->mnt_flag & MNT_RDONLY) 937 error = EROFS; 938 else 939 error = EJUSTRETURN; 940 } 941 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) 942 cnp->cn_flags |= SAVENAME; 943 } 944 return (error); 945} 946 947/* 948 * nfs read call. 949 * Just call nfs_bioread() to do the work. 950 */ 951static int 952nfs_read(ap) 953 struct vop_read_args /* { 954 struct vnode *a_vp; 955 struct uio *a_uio; 956 int a_ioflag; 957 struct ucred *a_cred; 958 } */ *ap; 959{ 960 register struct vnode *vp = ap->a_vp; 961 962 if (vp->v_type != VREG) 963 return (EPERM); 964 return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred, 0)); 965} 966 967/* 968 * nfs readlink call 969 */ 970static int 971nfs_readlink(ap) 972 struct vop_readlink_args /* { 973 struct vnode *a_vp; 974 struct uio *a_uio; 975 struct ucred *a_cred; 976 } */ *ap; 977{ 978 register struct vnode *vp = ap->a_vp; 979 980 if (vp->v_type != VLNK) 981 return (EPERM); 982 return (nfs_bioread(vp, ap->a_uio, 0, ap->a_cred, 0)); 983} 984 985/* 986 * Do a readlink rpc. 987 * Called by nfs_doio() from below the buffer cache. 988 */ 989int 990nfs_readlinkrpc(vp, uiop, cred) 991 register struct vnode *vp; 992 struct uio *uiop; 993 struct ucred *cred; 994{ 995 register u_long *tl; 996 register caddr_t cp; 997 register long t1, t2; 998 caddr_t bpos, dpos, cp2; 999 int error = 0, len, attrflag; 1000 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1001 int v3 = NFS_ISV3(vp); 1002 1003 nfsstats.rpccnt[NFSPROC_READLINK]++; 1004 nfsm_reqhead(vp, NFSPROC_READLINK, NFSX_FH(v3)); 1005 nfsm_fhtom(vp, v3); 1006 nfsm_request(vp, NFSPROC_READLINK, uiop->uio_procp, cred); 1007 if (v3) 1008 nfsm_postop_attr(vp, attrflag); 1009 if (!error) { 1010 nfsm_strsiz(len, NFS_MAXPATHLEN); 1011 nfsm_mtouio(uiop, len); 1012 } 1013 nfsm_reqdone; 1014 return (error); 1015} 1016 1017/* 1018 * nfs read rpc call 1019 * Ditto above 1020 */ 1021int 1022nfs_readrpc(vp, uiop, cred) 1023 register struct vnode *vp; 1024 struct uio *uiop; 1025 struct ucred *cred; 1026{ 1027 register u_long *tl; 1028 register caddr_t cp; 1029 register long t1, t2; 1030 caddr_t bpos, dpos, cp2; 1031 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1032 struct nfsmount *nmp; 1033 int error = 0, len, retlen, tsiz, eof, attrflag; 1034 int v3 = NFS_ISV3(vp); 1035 1036#ifndef nolint 1037 eof = 0; 1038#endif 1039 nmp = VFSTONFS(vp->v_mount); 1040 tsiz = uiop->uio_resid; 1041 if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize) 1042 return (EFBIG); 1043 while (tsiz > 0) { 1044 nfsstats.rpccnt[NFSPROC_READ]++; 1045 len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz; 1046 nfsm_reqhead(vp, NFSPROC_READ, NFSX_FH(v3) + NFSX_UNSIGNED * 3); 1047 nfsm_fhtom(vp, v3); 1048 nfsm_build(tl, u_long *, NFSX_UNSIGNED * 3); 1049 if (v3) { 1050 txdr_hyper(&uiop->uio_offset, tl); 1051 *(tl + 2) = txdr_unsigned(len); 1052 } else { 1053 *tl++ = txdr_unsigned(uiop->uio_offset); 1054 *tl++ = txdr_unsigned(len); 1055 *tl = 0; 1056 } 1057 nfsm_request(vp, NFSPROC_READ, uiop->uio_procp, cred); 1058 if (v3) { 1059 nfsm_postop_attr(vp, attrflag); 1060 if (error) { 1061 m_freem(mrep); 1062 goto nfsmout; 1063 } 1064 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 1065 eof = fxdr_unsigned(int, *(tl + 1)); 1066 } else 1067 nfsm_loadattr(vp, (struct vattr *)0); 1068 nfsm_strsiz(retlen, nmp->nm_rsize); 1069 nfsm_mtouio(uiop, retlen); 1070 m_freem(mrep); 1071 tsiz -= retlen; 1072 if (v3) { 1073 if (eof || retlen == 0) 1074 tsiz = 0; 1075 } else if (retlen < len) 1076 tsiz = 0; 1077 } 1078nfsmout: 1079 return (error); 1080} 1081 1082/* 1083 * nfs write call 1084 */ 1085int 1086nfs_writerpc(vp, uiop, cred, iomode, must_commit) 1087 register struct vnode *vp; 1088 register struct uio *uiop; 1089 struct ucred *cred; 1090 int *iomode, *must_commit; 1091{ 1092 register u_long *tl; 1093 register caddr_t cp; 1094 register int t1, t2, backup; 1095 caddr_t bpos, dpos, cp2; 1096 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1097 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 1098 int error = 0, len, tsiz, wccflag = NFSV3_WCCRATTR, rlen, commit; 1099 int v3 = NFS_ISV3(vp), committed = NFSV3WRITE_FILESYNC; 1100 1101#ifndef DIAGNOSTIC 1102 if (uiop->uio_iovcnt != 1) 1103 panic("nfs: writerpc iovcnt > 1"); 1104#endif 1105 *must_commit = 0; 1106 tsiz = uiop->uio_resid; 1107 if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize) 1108 return (EFBIG); 1109 while (tsiz > 0) { 1110 nfsstats.rpccnt[NFSPROC_WRITE]++; 1111 len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz; 1112 nfsm_reqhead(vp, NFSPROC_WRITE, 1113 NFSX_FH(v3) + 5 * NFSX_UNSIGNED + nfsm_rndup(len)); 1114 nfsm_fhtom(vp, v3); 1115 if (v3) { 1116 nfsm_build(tl, u_long *, 5 * NFSX_UNSIGNED); 1117 txdr_hyper(&uiop->uio_offset, tl); 1118 tl += 2; 1119 *tl++ = txdr_unsigned(len); 1120 *tl++ = txdr_unsigned(*iomode); 1121 } else { 1122 nfsm_build(tl, u_long *, 4 * NFSX_UNSIGNED); 1123 *++tl = txdr_unsigned(uiop->uio_offset); 1124 tl += 2; 1125 } 1126 *tl = txdr_unsigned(len); 1127 nfsm_uiotom(uiop, len); 1128 nfsm_request(vp, NFSPROC_WRITE, uiop->uio_procp, cred); 1129 if (v3) { 1130 wccflag = NFSV3_WCCCHK; 1131 nfsm_wcc_data(vp, wccflag); 1132 if (!error) { 1133 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED + 1134 NFSX_V3WRITEVERF); 1135 rlen = fxdr_unsigned(int, *tl++); 1136 if (rlen == 0) { 1137 error = NFSERR_IO; 1138 break; 1139 } else if (rlen < len) { 1140 backup = len - rlen; 1141 uiop->uio_iov->iov_base -= backup; 1142 uiop->uio_iov->iov_len += backup; 1143 uiop->uio_offset -= backup; 1144 uiop->uio_resid += backup; 1145 len = rlen; 1146 } 1147 commit = fxdr_unsigned(int, *tl++); 1148 1149 /* 1150 * Return the lowest committment level 1151 * obtained by any of the RPCs. 1152 */ 1153 if (committed == NFSV3WRITE_FILESYNC) 1154 committed = commit; 1155 else if (committed == NFSV3WRITE_DATASYNC && 1156 commit == NFSV3WRITE_UNSTABLE) 1157 committed = commit; 1158 if ((nmp->nm_state & NFSSTA_HASWRITEVERF) == 0){ 1159 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf, 1160 NFSX_V3WRITEVERF); 1161 nmp->nm_state |= NFSSTA_HASWRITEVERF; 1162 } else if (bcmp((caddr_t)tl, 1163 (caddr_t)nmp->nm_verf, NFSX_V3WRITEVERF)) { 1164 *must_commit = 1; 1165 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf, 1166 NFSX_V3WRITEVERF); 1167 } 1168 } 1169 } else 1170 nfsm_loadattr(vp, (struct vattr *)0); 1171 if (wccflag) 1172 VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime.tv_sec; 1173 m_freem(mrep); 1174 tsiz -= len; 1175 } 1176nfsmout: 1177 if (vp->v_mount->mnt_flag & MNT_ASYNC) 1178 committed = NFSV3WRITE_FILESYNC; 1179 *iomode = committed; 1180 if (error) 1181 uiop->uio_resid = tsiz; 1182 return (error); 1183} 1184 1185/* 1186 * nfs mknod rpc 1187 * For NFS v2 this is a kludge. Use a create rpc but with the IFMT bits of the 1188 * mode set to specify the file type and the size field for rdev. 1189 */ 1190static int 1191nfs_mknodrpc(dvp, vpp, cnp, vap) 1192 register struct vnode *dvp; 1193 register struct vnode **vpp; 1194 register struct componentname *cnp; 1195 register struct vattr *vap; 1196{ 1197 register struct nfsv2_sattr *sp; 1198 register struct nfsv3_sattr *sp3; 1199 register u_long *tl; 1200 register caddr_t cp; 1201 register long t1, t2; 1202 struct vnode *newvp = (struct vnode *)0; 1203 struct nfsnode *np = (struct nfsnode *)0; 1204 struct vattr vattr; 1205 char *cp2; 1206 caddr_t bpos, dpos; 1207 int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0; 1208 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1209 u_long rdev; 1210 int v3 = NFS_ISV3(dvp); 1211 1212 if (vap->va_type == VCHR || vap->va_type == VBLK) 1213 rdev = txdr_unsigned(vap->va_rdev); 1214 else if (vap->va_type == VFIFO || vap->va_type == VSOCK) 1215 rdev = 0xffffffff; 1216 else { 1217 VOP_ABORTOP(dvp, cnp); 1218 return (EOPNOTSUPP); 1219 } 1220 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 1221 VOP_ABORTOP(dvp, cnp); 1222 return (error); 1223 } 1224 nfsstats.rpccnt[NFSPROC_MKNOD]++; 1225 nfsm_reqhead(dvp, NFSPROC_MKNOD, NFSX_FH(v3) + 4 * NFSX_UNSIGNED + 1226 + nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3)); 1227 nfsm_fhtom(dvp, v3); 1228 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1229 if (v3) { 1230 nfsm_build(tl, u_long *, NFSX_UNSIGNED + NFSX_V3SRVSATTR); 1231 *tl++ = vtonfsv3_type(vap->va_type); 1232 sp3 = (struct nfsv3_sattr *)tl; 1233 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, vattr.va_gid); 1234 if (vap->va_type == VCHR || vap->va_type == VBLK) { 1235 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 1236 *tl++ = txdr_unsigned(major(vap->va_rdev)); 1237 *tl = txdr_unsigned(minor(vap->va_rdev)); 1238 } 1239 } else { 1240 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1241 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode); 1242 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1243 sp->sa_gid = txdr_unsigned(vattr.va_gid); 1244 sp->sa_size = rdev; 1245 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1246 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1247 } 1248 nfsm_request(dvp, NFSPROC_MKNOD, cnp->cn_proc, cnp->cn_cred); 1249 if (!error) { 1250 nfsm_mtofh(dvp, newvp, v3, gotvp); 1251 if (!gotvp) { 1252 if (newvp) { 1253 vput(newvp); 1254 newvp = (struct vnode *)0; 1255 } 1256 error = nfs_lookitup(dvp, cnp->cn_nameptr, 1257 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc, &np); 1258 if (!error) 1259 newvp = NFSTOV(np); 1260 } 1261 } 1262 if (v3) 1263 nfsm_wcc_data(dvp, wccflag); 1264 nfsm_reqdone; 1265 if (error) { 1266 if (newvp) 1267 vput(newvp); 1268 } else { 1269 if (cnp->cn_flags & MAKEENTRY) 1270 cache_enter(dvp, newvp, cnp); 1271 *vpp = newvp; 1272 } 1273 zfree(namei_zone, cnp->cn_pnbuf); 1274 VTONFS(dvp)->n_flag |= NMODIFIED; 1275 if (!wccflag) 1276 VTONFS(dvp)->n_attrstamp = 0; 1277 return (error); 1278} 1279 1280/* 1281 * nfs mknod vop 1282 * just call nfs_mknodrpc() to do the work. 1283 */ 1284/* ARGSUSED */ 1285static int 1286nfs_mknod(ap) 1287 struct vop_mknod_args /* { 1288 struct vnode *a_dvp; 1289 struct vnode **a_vpp; 1290 struct componentname *a_cnp; 1291 struct vattr *a_vap; 1292 } */ *ap; 1293{ 1294 struct vnode *newvp; 1295 int error; 1296 1297 error = nfs_mknodrpc(ap->a_dvp, &newvp, ap->a_cnp, ap->a_vap); 1298 if (!error) 1299 vput(newvp); 1300 return (error); 1301} 1302 1303static u_long create_verf; 1304/* 1305 * nfs file create call 1306 */ 1307static int 1308nfs_create(ap) 1309 struct vop_create_args /* { 1310 struct vnode *a_dvp; 1311 struct vnode **a_vpp; 1312 struct componentname *a_cnp; 1313 struct vattr *a_vap; 1314 } */ *ap; 1315{ 1316 register struct vnode *dvp = ap->a_dvp; 1317 register struct vattr *vap = ap->a_vap; 1318 register struct componentname *cnp = ap->a_cnp; 1319 register struct nfsv2_sattr *sp; 1320 register struct nfsv3_sattr *sp3; 1321 register u_long *tl; 1322 register caddr_t cp; 1323 register long t1, t2; 1324 struct nfsnode *np = (struct nfsnode *)0; 1325 struct vnode *newvp = (struct vnode *)0; 1326 caddr_t bpos, dpos, cp2; 1327 int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0, fmode = 0; 1328 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1329 struct vattr vattr; 1330 int v3 = NFS_ISV3(dvp); 1331 1332 /* 1333 * Oops, not for me.. 1334 */ 1335 if (vap->va_type == VSOCK) 1336 return (nfs_mknodrpc(dvp, ap->a_vpp, cnp, vap)); 1337 1338 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 1339 VOP_ABORTOP(dvp, cnp); 1340 return (error); 1341 } 1342 if (vap->va_vaflags & VA_EXCLUSIVE) 1343 fmode |= O_EXCL; 1344again: 1345 nfsstats.rpccnt[NFSPROC_CREATE]++; 1346 nfsm_reqhead(dvp, NFSPROC_CREATE, NFSX_FH(v3) + 2 * NFSX_UNSIGNED + 1347 nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3)); 1348 nfsm_fhtom(dvp, v3); 1349 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1350 if (v3) { 1351 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 1352 if (fmode & O_EXCL) { 1353 *tl = txdr_unsigned(NFSV3CREATE_EXCLUSIVE); 1354 nfsm_build(tl, u_long *, NFSX_V3CREATEVERF); 1355#ifdef INET 1356 if (!TAILQ_EMPTY(&in_ifaddrhead)) 1357 *tl++ = IA_SIN(in_ifaddrhead.tqh_first)->sin_addr.s_addr; 1358 else 1359#endif 1360 *tl++ = create_verf; 1361 *tl = ++create_verf; 1362 } else { 1363 *tl = txdr_unsigned(NFSV3CREATE_UNCHECKED); 1364 nfsm_build(tl, u_long *, NFSX_V3SRVSATTR); 1365 sp3 = (struct nfsv3_sattr *)tl; 1366 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, vattr.va_gid); 1367 } 1368 } else { 1369 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1370 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode); 1371 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1372 sp->sa_gid = txdr_unsigned(vattr.va_gid); 1373 sp->sa_size = 0; 1374 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1375 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1376 } 1377 nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred); 1378 if (!error) { 1379 nfsm_mtofh(dvp, newvp, v3, gotvp); 1380 if (!gotvp) { 1381 if (newvp) { 1382 vput(newvp); 1383 newvp = (struct vnode *)0; 1384 } 1385 error = nfs_lookitup(dvp, cnp->cn_nameptr, 1386 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc, &np); 1387 if (!error) 1388 newvp = NFSTOV(np); 1389 } 1390 } 1391 if (v3) 1392 nfsm_wcc_data(dvp, wccflag); 1393 nfsm_reqdone; 1394 if (error) { 1395 if (v3 && (fmode & O_EXCL) && error == NFSERR_NOTSUPP) { 1396 fmode &= ~O_EXCL; 1397 goto again; 1398 } 1399 if (newvp) 1400 vput(newvp); 1401 } else if (v3 && (fmode & O_EXCL)) 1402 error = nfs_setattrrpc(newvp, vap, cnp->cn_cred, cnp->cn_proc); 1403 if (!error) { 1404 if (cnp->cn_flags & MAKEENTRY) 1405 cache_enter(dvp, newvp, cnp); 1406 *ap->a_vpp = newvp; 1407 } 1408 zfree(namei_zone, cnp->cn_pnbuf); 1409 VTONFS(dvp)->n_flag |= NMODIFIED; 1410 if (!wccflag) 1411 VTONFS(dvp)->n_attrstamp = 0; 1412 return (error); 1413} 1414 1415/* 1416 * nfs file remove call 1417 * To try and make nfs semantics closer to ufs semantics, a file that has 1418 * other processes using the vnode is renamed instead of removed and then 1419 * removed later on the last close. 1420 * - If v_usecount > 1 1421 * If a rename is not already in the works 1422 * call nfs_sillyrename() to set it up 1423 * else 1424 * do the remove rpc 1425 */ 1426static int 1427nfs_remove(ap) 1428 struct vop_remove_args /* { 1429 struct vnodeop_desc *a_desc; 1430 struct vnode * a_dvp; 1431 struct vnode * a_vp; 1432 struct componentname * a_cnp; 1433 } */ *ap; 1434{ 1435 register struct vnode *vp = ap->a_vp; 1436 register struct vnode *dvp = ap->a_dvp; 1437 register struct componentname *cnp = ap->a_cnp; 1438 register struct nfsnode *np = VTONFS(vp); 1439 int error = 0; 1440 struct vattr vattr; 1441 1442#ifndef DIAGNOSTIC 1443 if ((cnp->cn_flags & HASBUF) == 0) 1444 panic("nfs_remove: no name"); 1445 if (vp->v_usecount < 1) 1446 panic("nfs_remove: bad v_usecount"); 1447#endif 1448 if (vp->v_usecount == 1 || (np->n_sillyrename && 1449 VOP_GETATTR(vp, &vattr, cnp->cn_cred, cnp->cn_proc) == 0 && 1450 vattr.va_nlink > 1)) { 1451 /* 1452 * Purge the name cache so that the chance of a lookup for 1453 * the name succeeding while the remove is in progress is 1454 * minimized. Without node locking it can still happen, such 1455 * that an I/O op returns ESTALE, but since you get this if 1456 * another host removes the file.. 1457 */ 1458 cache_purge(vp); 1459 /* 1460 * throw away biocache buffers, mainly to avoid 1461 * unnecessary delayed writes later. 1462 */ 1463 error = nfs_vinvalbuf(vp, 0, cnp->cn_cred, cnp->cn_proc, 1); 1464 /* Do the rpc */ 1465 if (error != EINTR) 1466 error = nfs_removerpc(dvp, cnp->cn_nameptr, 1467 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc); 1468 /* 1469 * Kludge City: If the first reply to the remove rpc is lost.. 1470 * the reply to the retransmitted request will be ENOENT 1471 * since the file was in fact removed 1472 * Therefore, we cheat and return success. 1473 */ 1474 if (error == ENOENT) 1475 error = 0; 1476 } else if (!np->n_sillyrename) 1477 error = nfs_sillyrename(dvp, vp, cnp); 1478 zfree(namei_zone, cnp->cn_pnbuf); 1479 np->n_attrstamp = 0; 1480 return (error); 1481} 1482 1483/* 1484 * nfs file remove rpc called from nfs_inactive 1485 */ 1486int 1487nfs_removeit(sp) 1488 register struct sillyrename *sp; 1489{ 1490 1491 return (nfs_removerpc(sp->s_dvp, sp->s_name, sp->s_namlen, sp->s_cred, 1492 (struct proc *)0)); 1493} 1494 1495/* 1496 * Nfs remove rpc, called from nfs_remove() and nfs_removeit(). 1497 */ 1498static int 1499nfs_removerpc(dvp, name, namelen, cred, proc) 1500 register struct vnode *dvp;
|
1499 char *name;
| 1501 const char *name;
|
1500 int namelen; 1501 struct ucred *cred; 1502 struct proc *proc; 1503{ 1504 register u_long *tl; 1505 register caddr_t cp; 1506 register long t1, t2; 1507 caddr_t bpos, dpos, cp2; 1508 int error = 0, wccflag = NFSV3_WCCRATTR; 1509 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1510 int v3 = NFS_ISV3(dvp); 1511 1512 nfsstats.rpccnt[NFSPROC_REMOVE]++; 1513 nfsm_reqhead(dvp, NFSPROC_REMOVE, 1514 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(namelen)); 1515 nfsm_fhtom(dvp, v3); 1516 nfsm_strtom(name, namelen, NFS_MAXNAMLEN); 1517 nfsm_request(dvp, NFSPROC_REMOVE, proc, cred); 1518 if (v3) 1519 nfsm_wcc_data(dvp, wccflag); 1520 nfsm_reqdone; 1521 VTONFS(dvp)->n_flag |= NMODIFIED; 1522 if (!wccflag) 1523 VTONFS(dvp)->n_attrstamp = 0; 1524 return (error); 1525} 1526 1527/* 1528 * nfs file rename call 1529 */ 1530static int 1531nfs_rename(ap) 1532 struct vop_rename_args /* { 1533 struct vnode *a_fdvp; 1534 struct vnode *a_fvp; 1535 struct componentname *a_fcnp; 1536 struct vnode *a_tdvp; 1537 struct vnode *a_tvp; 1538 struct componentname *a_tcnp; 1539 } */ *ap; 1540{ 1541 register struct vnode *fvp = ap->a_fvp; 1542 register struct vnode *tvp = ap->a_tvp; 1543 register struct vnode *fdvp = ap->a_fdvp; 1544 register struct vnode *tdvp = ap->a_tdvp; 1545 register struct componentname *tcnp = ap->a_tcnp; 1546 register struct componentname *fcnp = ap->a_fcnp; 1547 int error; 1548 1549#ifndef DIAGNOSTIC 1550 if ((tcnp->cn_flags & HASBUF) == 0 || 1551 (fcnp->cn_flags & HASBUF) == 0) 1552 panic("nfs_rename: no name"); 1553#endif 1554 /* Check for cross-device rename */ 1555 if ((fvp->v_mount != tdvp->v_mount) || 1556 (tvp && (fvp->v_mount != tvp->v_mount))) { 1557 error = EXDEV; 1558 goto out; 1559 } 1560 1561 /* 1562 * If the tvp exists and is in use, sillyrename it before doing the 1563 * rename of the new file over it. 1564 * XXX Can't sillyrename a directory. 1565 */ 1566 if (tvp && tvp->v_usecount > 1 && !VTONFS(tvp)->n_sillyrename && 1567 tvp->v_type != VDIR && !nfs_sillyrename(tdvp, tvp, tcnp)) { 1568 vput(tvp); 1569 tvp = NULL; 1570 } 1571 1572 error = nfs_renamerpc(fdvp, fcnp->cn_nameptr, fcnp->cn_namelen, 1573 tdvp, tcnp->cn_nameptr, tcnp->cn_namelen, tcnp->cn_cred, 1574 tcnp->cn_proc); 1575 1576 if (fvp->v_type == VDIR) { 1577 if (tvp != NULL && tvp->v_type == VDIR) 1578 cache_purge(tdvp); 1579 cache_purge(fdvp); 1580 } 1581out: 1582 if (tdvp == tvp) 1583 vrele(tdvp); 1584 else 1585 vput(tdvp); 1586 if (tvp) 1587 vput(tvp); 1588 vrele(fdvp); 1589 vrele(fvp); 1590 /* 1591 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry. 1592 */ 1593 if (error == ENOENT) 1594 error = 0; 1595 return (error); 1596} 1597 1598/* 1599 * nfs file rename rpc called from nfs_remove() above 1600 */ 1601static int 1602nfs_renameit(sdvp, scnp, sp) 1603 struct vnode *sdvp; 1604 struct componentname *scnp; 1605 register struct sillyrename *sp; 1606{ 1607 return (nfs_renamerpc(sdvp, scnp->cn_nameptr, scnp->cn_namelen, 1608 sdvp, sp->s_name, sp->s_namlen, scnp->cn_cred, scnp->cn_proc)); 1609} 1610 1611/* 1612 * Do an nfs rename rpc. Called from nfs_rename() and nfs_renameit(). 1613 */ 1614static int 1615nfs_renamerpc(fdvp, fnameptr, fnamelen, tdvp, tnameptr, tnamelen, cred, proc) 1616 register struct vnode *fdvp;
| 1502 int namelen; 1503 struct ucred *cred; 1504 struct proc *proc; 1505{ 1506 register u_long *tl; 1507 register caddr_t cp; 1508 register long t1, t2; 1509 caddr_t bpos, dpos, cp2; 1510 int error = 0, wccflag = NFSV3_WCCRATTR; 1511 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1512 int v3 = NFS_ISV3(dvp); 1513 1514 nfsstats.rpccnt[NFSPROC_REMOVE]++; 1515 nfsm_reqhead(dvp, NFSPROC_REMOVE, 1516 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(namelen)); 1517 nfsm_fhtom(dvp, v3); 1518 nfsm_strtom(name, namelen, NFS_MAXNAMLEN); 1519 nfsm_request(dvp, NFSPROC_REMOVE, proc, cred); 1520 if (v3) 1521 nfsm_wcc_data(dvp, wccflag); 1522 nfsm_reqdone; 1523 VTONFS(dvp)->n_flag |= NMODIFIED; 1524 if (!wccflag) 1525 VTONFS(dvp)->n_attrstamp = 0; 1526 return (error); 1527} 1528 1529/* 1530 * nfs file rename call 1531 */ 1532static int 1533nfs_rename(ap) 1534 struct vop_rename_args /* { 1535 struct vnode *a_fdvp; 1536 struct vnode *a_fvp; 1537 struct componentname *a_fcnp; 1538 struct vnode *a_tdvp; 1539 struct vnode *a_tvp; 1540 struct componentname *a_tcnp; 1541 } */ *ap; 1542{ 1543 register struct vnode *fvp = ap->a_fvp; 1544 register struct vnode *tvp = ap->a_tvp; 1545 register struct vnode *fdvp = ap->a_fdvp; 1546 register struct vnode *tdvp = ap->a_tdvp; 1547 register struct componentname *tcnp = ap->a_tcnp; 1548 register struct componentname *fcnp = ap->a_fcnp; 1549 int error; 1550 1551#ifndef DIAGNOSTIC 1552 if ((tcnp->cn_flags & HASBUF) == 0 || 1553 (fcnp->cn_flags & HASBUF) == 0) 1554 panic("nfs_rename: no name"); 1555#endif 1556 /* Check for cross-device rename */ 1557 if ((fvp->v_mount != tdvp->v_mount) || 1558 (tvp && (fvp->v_mount != tvp->v_mount))) { 1559 error = EXDEV; 1560 goto out; 1561 } 1562 1563 /* 1564 * If the tvp exists and is in use, sillyrename it before doing the 1565 * rename of the new file over it. 1566 * XXX Can't sillyrename a directory. 1567 */ 1568 if (tvp && tvp->v_usecount > 1 && !VTONFS(tvp)->n_sillyrename && 1569 tvp->v_type != VDIR && !nfs_sillyrename(tdvp, tvp, tcnp)) { 1570 vput(tvp); 1571 tvp = NULL; 1572 } 1573 1574 error = nfs_renamerpc(fdvp, fcnp->cn_nameptr, fcnp->cn_namelen, 1575 tdvp, tcnp->cn_nameptr, tcnp->cn_namelen, tcnp->cn_cred, 1576 tcnp->cn_proc); 1577 1578 if (fvp->v_type == VDIR) { 1579 if (tvp != NULL && tvp->v_type == VDIR) 1580 cache_purge(tdvp); 1581 cache_purge(fdvp); 1582 } 1583out: 1584 if (tdvp == tvp) 1585 vrele(tdvp); 1586 else 1587 vput(tdvp); 1588 if (tvp) 1589 vput(tvp); 1590 vrele(fdvp); 1591 vrele(fvp); 1592 /* 1593 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry. 1594 */ 1595 if (error == ENOENT) 1596 error = 0; 1597 return (error); 1598} 1599 1600/* 1601 * nfs file rename rpc called from nfs_remove() above 1602 */ 1603static int 1604nfs_renameit(sdvp, scnp, sp) 1605 struct vnode *sdvp; 1606 struct componentname *scnp; 1607 register struct sillyrename *sp; 1608{ 1609 return (nfs_renamerpc(sdvp, scnp->cn_nameptr, scnp->cn_namelen, 1610 sdvp, sp->s_name, sp->s_namlen, scnp->cn_cred, scnp->cn_proc)); 1611} 1612 1613/* 1614 * Do an nfs rename rpc. Called from nfs_rename() and nfs_renameit(). 1615 */ 1616static int 1617nfs_renamerpc(fdvp, fnameptr, fnamelen, tdvp, tnameptr, tnamelen, cred, proc) 1618 register struct vnode *fdvp;
|
1617 char *fnameptr;
| 1619 const char *fnameptr;
|
1618 int fnamelen; 1619 register struct vnode *tdvp;
| 1620 int fnamelen; 1621 register struct vnode *tdvp;
|
1620 char *tnameptr;
| 1622 const char *tnameptr;
|
1621 int tnamelen; 1622 struct ucred *cred; 1623 struct proc *proc; 1624{ 1625 register u_long *tl; 1626 register caddr_t cp; 1627 register long t1, t2; 1628 caddr_t bpos, dpos, cp2; 1629 int error = 0, fwccflag = NFSV3_WCCRATTR, twccflag = NFSV3_WCCRATTR; 1630 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1631 int v3 = NFS_ISV3(fdvp); 1632 1633 nfsstats.rpccnt[NFSPROC_RENAME]++; 1634 nfsm_reqhead(fdvp, NFSPROC_RENAME, 1635 (NFSX_FH(v3) + NFSX_UNSIGNED)*2 + nfsm_rndup(fnamelen) + 1636 nfsm_rndup(tnamelen)); 1637 nfsm_fhtom(fdvp, v3); 1638 nfsm_strtom(fnameptr, fnamelen, NFS_MAXNAMLEN); 1639 nfsm_fhtom(tdvp, v3); 1640 nfsm_strtom(tnameptr, tnamelen, NFS_MAXNAMLEN); 1641 nfsm_request(fdvp, NFSPROC_RENAME, proc, cred); 1642 if (v3) { 1643 nfsm_wcc_data(fdvp, fwccflag); 1644 nfsm_wcc_data(tdvp, twccflag); 1645 } 1646 nfsm_reqdone; 1647 VTONFS(fdvp)->n_flag |= NMODIFIED; 1648 VTONFS(tdvp)->n_flag |= NMODIFIED; 1649 if (!fwccflag) 1650 VTONFS(fdvp)->n_attrstamp = 0; 1651 if (!twccflag) 1652 VTONFS(tdvp)->n_attrstamp = 0; 1653 return (error); 1654} 1655 1656/* 1657 * nfs hard link create call 1658 */ 1659static int 1660nfs_link(ap) 1661 struct vop_link_args /* { 1662 struct vnode *a_tdvp; 1663 struct vnode *a_vp; 1664 struct componentname *a_cnp; 1665 } */ *ap; 1666{ 1667 register struct vnode *vp = ap->a_vp; 1668 register struct vnode *tdvp = ap->a_tdvp; 1669 register struct componentname *cnp = ap->a_cnp; 1670 register u_long *tl; 1671 register caddr_t cp; 1672 register long t1, t2; 1673 caddr_t bpos, dpos, cp2; 1674 int error = 0, wccflag = NFSV3_WCCRATTR, attrflag = 0; 1675 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1676 int v3 = NFS_ISV3(vp); 1677 1678 if (vp->v_mount != tdvp->v_mount) { 1679 VOP_ABORTOP(tdvp, cnp); 1680 return (EXDEV); 1681 } 1682 1683 /* 1684 * Push all writes to the server, so that the attribute cache 1685 * doesn't get "out of sync" with the server. 1686 * XXX There should be a better way! 1687 */ 1688 VOP_FSYNC(vp, cnp->cn_cred, MNT_WAIT, cnp->cn_proc); 1689 1690 nfsstats.rpccnt[NFSPROC_LINK]++; 1691 nfsm_reqhead(vp, NFSPROC_LINK, 1692 NFSX_FH(v3)*2 + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen)); 1693 nfsm_fhtom(vp, v3); 1694 nfsm_fhtom(tdvp, v3); 1695 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1696 nfsm_request(vp, NFSPROC_LINK, cnp->cn_proc, cnp->cn_cred); 1697 if (v3) { 1698 nfsm_postop_attr(vp, attrflag); 1699 nfsm_wcc_data(tdvp, wccflag); 1700 } 1701 nfsm_reqdone; 1702 zfree(namei_zone, cnp->cn_pnbuf); 1703 VTONFS(tdvp)->n_flag |= NMODIFIED; 1704 if (!attrflag) 1705 VTONFS(vp)->n_attrstamp = 0; 1706 if (!wccflag) 1707 VTONFS(tdvp)->n_attrstamp = 0; 1708 /* 1709 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry. 1710 */ 1711 if (error == EEXIST) 1712 error = 0; 1713 return (error); 1714} 1715 1716/* 1717 * nfs symbolic link create call 1718 */ 1719static int 1720nfs_symlink(ap) 1721 struct vop_symlink_args /* { 1722 struct vnode *a_dvp; 1723 struct vnode **a_vpp; 1724 struct componentname *a_cnp; 1725 struct vattr *a_vap; 1726 char *a_target; 1727 } */ *ap; 1728{ 1729 register struct vnode *dvp = ap->a_dvp; 1730 register struct vattr *vap = ap->a_vap; 1731 register struct componentname *cnp = ap->a_cnp; 1732 register struct nfsv2_sattr *sp; 1733 register struct nfsv3_sattr *sp3; 1734 register u_long *tl; 1735 register caddr_t cp; 1736 register long t1, t2; 1737 caddr_t bpos, dpos, cp2; 1738 int slen, error = 0, wccflag = NFSV3_WCCRATTR, gotvp; 1739 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1740 struct vnode *newvp = (struct vnode *)0; 1741 int v3 = NFS_ISV3(dvp); 1742 1743 nfsstats.rpccnt[NFSPROC_SYMLINK]++; 1744 slen = strlen(ap->a_target); 1745 nfsm_reqhead(dvp, NFSPROC_SYMLINK, NFSX_FH(v3) + 2*NFSX_UNSIGNED + 1746 nfsm_rndup(cnp->cn_namelen) + nfsm_rndup(slen) + NFSX_SATTR(v3)); 1747 nfsm_fhtom(dvp, v3); 1748 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1749 if (v3) { 1750 nfsm_build(sp3, struct nfsv3_sattr *, NFSX_V3SRVSATTR); 1751 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, 1752 cnp->cn_cred->cr_gid); 1753 } 1754 nfsm_strtom(ap->a_target, slen, NFS_MAXPATHLEN); 1755 if (!v3) { 1756 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1757 sp->sa_mode = vtonfsv2_mode(VLNK, vap->va_mode); 1758 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1759 sp->sa_gid = txdr_unsigned(cnp->cn_cred->cr_gid); 1760 sp->sa_size = -1; 1761 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1762 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1763 } 1764 nfsm_request(dvp, NFSPROC_SYMLINK, cnp->cn_proc, cnp->cn_cred); 1765 if (v3) { 1766 if (!error) 1767 nfsm_mtofh(dvp, newvp, v3, gotvp); 1768 nfsm_wcc_data(dvp, wccflag); 1769 } 1770 nfsm_reqdone; 1771 if (newvp) 1772 vput(newvp); 1773 zfree(namei_zone, cnp->cn_pnbuf); 1774 VTONFS(dvp)->n_flag |= NMODIFIED; 1775 if (!wccflag) 1776 VTONFS(dvp)->n_attrstamp = 0; 1777 /* 1778 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry. 1779 */ 1780 if (error == EEXIST) 1781 error = 0; 1782 return (error); 1783} 1784 1785/* 1786 * nfs make dir call 1787 */ 1788static int 1789nfs_mkdir(ap) 1790 struct vop_mkdir_args /* { 1791 struct vnode *a_dvp; 1792 struct vnode **a_vpp; 1793 struct componentname *a_cnp; 1794 struct vattr *a_vap; 1795 } */ *ap; 1796{ 1797 register struct vnode *dvp = ap->a_dvp; 1798 register struct vattr *vap = ap->a_vap; 1799 register struct componentname *cnp = ap->a_cnp; 1800 register struct nfsv2_sattr *sp; 1801 register struct nfsv3_sattr *sp3; 1802 register u_long *tl; 1803 register caddr_t cp; 1804 register long t1, t2; 1805 register int len; 1806 struct nfsnode *np = (struct nfsnode *)0; 1807 struct vnode *newvp = (struct vnode *)0; 1808 caddr_t bpos, dpos, cp2; 1809 int error = 0, wccflag = NFSV3_WCCRATTR; 1810 int gotvp = 0; 1811 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1812 struct vattr vattr; 1813 int v3 = NFS_ISV3(dvp); 1814 1815 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 1816 VOP_ABORTOP(dvp, cnp); 1817 return (error); 1818 } 1819 len = cnp->cn_namelen; 1820 nfsstats.rpccnt[NFSPROC_MKDIR]++; 1821 nfsm_reqhead(dvp, NFSPROC_MKDIR, 1822 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len) + NFSX_SATTR(v3)); 1823 nfsm_fhtom(dvp, v3); 1824 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); 1825 if (v3) { 1826 nfsm_build(sp3, struct nfsv3_sattr *, NFSX_V3SRVSATTR); 1827 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, vattr.va_gid); 1828 } else { 1829 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1830 sp->sa_mode = vtonfsv2_mode(VDIR, vap->va_mode); 1831 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1832 sp->sa_gid = txdr_unsigned(vattr.va_gid); 1833 sp->sa_size = -1; 1834 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1835 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1836 } 1837 nfsm_request(dvp, NFSPROC_MKDIR, cnp->cn_proc, cnp->cn_cred); 1838 if (!error) 1839 nfsm_mtofh(dvp, newvp, v3, gotvp); 1840 if (v3) 1841 nfsm_wcc_data(dvp, wccflag); 1842 nfsm_reqdone; 1843 VTONFS(dvp)->n_flag |= NMODIFIED; 1844 if (!wccflag) 1845 VTONFS(dvp)->n_attrstamp = 0; 1846 /* 1847 * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry 1848 * if we can succeed in looking up the directory. 1849 */ 1850 if (error == EEXIST || (!error && !gotvp)) { 1851 if (newvp) { 1852 vrele(newvp); 1853 newvp = (struct vnode *)0; 1854 } 1855 error = nfs_lookitup(dvp, cnp->cn_nameptr, len, cnp->cn_cred, 1856 cnp->cn_proc, &np); 1857 if (!error) { 1858 newvp = NFSTOV(np); 1859 if (newvp->v_type != VDIR) 1860 error = EEXIST; 1861 } 1862 } 1863 if (error) { 1864 if (newvp) 1865 vrele(newvp); 1866 } else 1867 *ap->a_vpp = newvp; 1868 zfree(namei_zone, cnp->cn_pnbuf); 1869 return (error); 1870} 1871 1872/* 1873 * nfs remove directory call 1874 */ 1875static int 1876nfs_rmdir(ap) 1877 struct vop_rmdir_args /* { 1878 struct vnode *a_dvp; 1879 struct vnode *a_vp; 1880 struct componentname *a_cnp; 1881 } */ *ap; 1882{ 1883 register struct vnode *vp = ap->a_vp; 1884 register struct vnode *dvp = ap->a_dvp; 1885 register struct componentname *cnp = ap->a_cnp; 1886 register u_long *tl; 1887 register caddr_t cp; 1888 register long t1, t2; 1889 caddr_t bpos, dpos, cp2; 1890 int error = 0, wccflag = NFSV3_WCCRATTR; 1891 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1892 int v3 = NFS_ISV3(dvp); 1893 1894 nfsstats.rpccnt[NFSPROC_RMDIR]++; 1895 nfsm_reqhead(dvp, NFSPROC_RMDIR, 1896 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen)); 1897 nfsm_fhtom(dvp, v3); 1898 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1899 nfsm_request(dvp, NFSPROC_RMDIR, cnp->cn_proc, cnp->cn_cred); 1900 if (v3) 1901 nfsm_wcc_data(dvp, wccflag); 1902 nfsm_reqdone; 1903 zfree(namei_zone, cnp->cn_pnbuf); 1904 VTONFS(dvp)->n_flag |= NMODIFIED; 1905 if (!wccflag) 1906 VTONFS(dvp)->n_attrstamp = 0; 1907 cache_purge(dvp); 1908 cache_purge(vp); 1909 /* 1910 * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry. 1911 */ 1912 if (error == ENOENT) 1913 error = 0; 1914 return (error); 1915} 1916 1917/* 1918 * nfs readdir call 1919 */ 1920static int 1921nfs_readdir(ap) 1922 struct vop_readdir_args /* { 1923 struct vnode *a_vp; 1924 struct uio *a_uio; 1925 struct ucred *a_cred; 1926 } */ *ap; 1927{ 1928 register struct vnode *vp = ap->a_vp; 1929 register struct nfsnode *np = VTONFS(vp); 1930 register struct uio *uio = ap->a_uio; 1931 int tresid, error; 1932 struct vattr vattr; 1933 1934 if (vp->v_type != VDIR) 1935 return (EPERM); 1936 /* 1937 * First, check for hit on the EOF offset cache 1938 */ 1939 if (np->n_direofoffset > 0 && uio->uio_offset >= np->n_direofoffset && 1940 (np->n_flag & NMODIFIED) == 0) { 1941 if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) { 1942 if (NQNFS_CKCACHABLE(vp, ND_READ)) { 1943 nfsstats.direofcache_hits++; 1944 return (0); 1945 } 1946 } else if (VOP_GETATTR(vp, &vattr, ap->a_cred, uio->uio_procp) == 0 && 1947 np->n_mtime == vattr.va_mtime.tv_sec) { 1948 nfsstats.direofcache_hits++; 1949 return (0); 1950 } 1951 } 1952 1953 /* 1954 * Call nfs_bioread() to do the real work. 1955 */ 1956 tresid = uio->uio_resid; 1957 error = nfs_bioread(vp, uio, 0, ap->a_cred, 0); 1958 1959 if (!error && uio->uio_resid == tresid) 1960 nfsstats.direofcache_misses++; 1961 return (error); 1962} 1963 1964/* 1965 * Readdir rpc call. 1966 * Called from below the buffer cache by nfs_doio(). 1967 */ 1968int 1969nfs_readdirrpc(vp, uiop, cred) 1970 struct vnode *vp; 1971 register struct uio *uiop; 1972 struct ucred *cred; 1973 1974{ 1975 register int len, left; 1976 register struct dirent *dp; 1977 register u_long *tl; 1978 register caddr_t cp; 1979 register long t1, t2; 1980 register nfsuint64 *cookiep; 1981 caddr_t bpos, dpos, cp2; 1982 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1983 nfsuint64 cookie; 1984 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 1985 struct nfsnode *dnp = VTONFS(vp); 1986 u_quad_t fileno; 1987 int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1; 1988 int attrflag; 1989 int v3 = NFS_ISV3(vp); 1990 1991#ifndef nolint 1992 dp = (struct dirent *)0; 1993#endif 1994#ifndef DIAGNOSTIC 1995 if (uiop->uio_iovcnt != 1 || (uiop->uio_offset & (NFS_DIRBLKSIZ - 1)) || 1996 (uiop->uio_resid & (NFS_DIRBLKSIZ - 1))) 1997 panic("nfs readdirrpc bad uio"); 1998#endif 1999 2000 /* 2001 * If there is no cookie, assume directory was stale. 2002 */ 2003 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 0); 2004 if (cookiep) 2005 cookie = *cookiep; 2006 else 2007 return (NFSERR_BAD_COOKIE); 2008 /* 2009 * Loop around doing readdir rpc's of size nm_readdirsize 2010 * truncated to a multiple of DIRBLKSIZ. 2011 * The stopping criteria is EOF or buffer full. 2012 */ 2013 while (more_dirs && bigenough) { 2014 nfsstats.rpccnt[NFSPROC_READDIR]++; 2015 nfsm_reqhead(vp, NFSPROC_READDIR, NFSX_FH(v3) + 2016 NFSX_READDIR(v3)); 2017 nfsm_fhtom(vp, v3); 2018 if (v3) { 2019 nfsm_build(tl, u_long *, 5 * NFSX_UNSIGNED); 2020 *tl++ = cookie.nfsuquad[0]; 2021 *tl++ = cookie.nfsuquad[1]; 2022 *tl++ = dnp->n_cookieverf.nfsuquad[0]; 2023 *tl++ = dnp->n_cookieverf.nfsuquad[1]; 2024 } else { 2025 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 2026 *tl++ = cookie.nfsuquad[0]; 2027 } 2028 *tl = txdr_unsigned(nmp->nm_readdirsize); 2029 nfsm_request(vp, NFSPROC_READDIR, uiop->uio_procp, cred); 2030 if (v3) { 2031 nfsm_postop_attr(vp, attrflag); 2032 if (!error) { 2033 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 2034 dnp->n_cookieverf.nfsuquad[0] = *tl++; 2035 dnp->n_cookieverf.nfsuquad[1] = *tl; 2036 } else { 2037 m_freem(mrep); 2038 goto nfsmout; 2039 } 2040 } 2041 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2042 more_dirs = fxdr_unsigned(int, *tl); 2043 2044 /* loop thru the dir entries, doctoring them to 4bsd form */ 2045 while (more_dirs && bigenough) { 2046 if (v3) { 2047 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2048 fxdr_hyper(tl, &fileno); 2049 len = fxdr_unsigned(int, *(tl + 2)); 2050 } else { 2051 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 2052 fileno = fxdr_unsigned(u_quad_t, *tl++); 2053 len = fxdr_unsigned(int, *tl); 2054 } 2055 if (len <= 0 || len > NFS_MAXNAMLEN) { 2056 error = EBADRPC; 2057 m_freem(mrep); 2058 goto nfsmout; 2059 } 2060 tlen = nfsm_rndup(len); 2061 if (tlen == len) 2062 tlen += 4; /* To ensure null termination */ 2063 left = DIRBLKSIZ - blksiz; 2064 if ((tlen + DIRHDSIZ) > left) { 2065 dp->d_reclen += left; 2066 uiop->uio_iov->iov_base += left; 2067 uiop->uio_iov->iov_len -= left; 2068 uiop->uio_offset += left; 2069 uiop->uio_resid -= left; 2070 blksiz = 0; 2071 } 2072 if ((tlen + DIRHDSIZ) > uiop->uio_resid) 2073 bigenough = 0; 2074 if (bigenough) { 2075 dp = (struct dirent *)uiop->uio_iov->iov_base; 2076 dp->d_fileno = (int)fileno; 2077 dp->d_namlen = len; 2078 dp->d_reclen = tlen + DIRHDSIZ; 2079 dp->d_type = DT_UNKNOWN; 2080 blksiz += dp->d_reclen; 2081 if (blksiz == DIRBLKSIZ) 2082 blksiz = 0; 2083 uiop->uio_offset += DIRHDSIZ; 2084 uiop->uio_resid -= DIRHDSIZ; 2085 uiop->uio_iov->iov_base += DIRHDSIZ; 2086 uiop->uio_iov->iov_len -= DIRHDSIZ; 2087 nfsm_mtouio(uiop, len); 2088 cp = uiop->uio_iov->iov_base; 2089 tlen -= len; 2090 *cp = '\0'; /* null terminate */ 2091 uiop->uio_iov->iov_base += tlen; 2092 uiop->uio_iov->iov_len -= tlen; 2093 uiop->uio_offset += tlen; 2094 uiop->uio_resid -= tlen; 2095 } else 2096 nfsm_adv(nfsm_rndup(len)); 2097 if (v3) { 2098 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2099 } else { 2100 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 2101 } 2102 if (bigenough) { 2103 cookie.nfsuquad[0] = *tl++; 2104 if (v3) 2105 cookie.nfsuquad[1] = *tl++; 2106 } else if (v3) 2107 tl += 2; 2108 else 2109 tl++; 2110 more_dirs = fxdr_unsigned(int, *tl); 2111 } 2112 /* 2113 * If at end of rpc data, get the eof boolean 2114 */ 2115 if (!more_dirs) { 2116 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2117 more_dirs = (fxdr_unsigned(int, *tl) == 0); 2118 } 2119 m_freem(mrep); 2120 } 2121 /* 2122 * Fill last record, iff any, out to a multiple of DIRBLKSIZ 2123 * by increasing d_reclen for the last record. 2124 */ 2125 if (blksiz > 0) { 2126 left = DIRBLKSIZ - blksiz; 2127 dp->d_reclen += left; 2128 uiop->uio_iov->iov_base += left; 2129 uiop->uio_iov->iov_len -= left; 2130 uiop->uio_offset += left; 2131 uiop->uio_resid -= left; 2132 } 2133 2134 /* 2135 * We are now either at the end of the directory or have filled the 2136 * block. 2137 */ 2138 if (bigenough) 2139 dnp->n_direofoffset = uiop->uio_offset; 2140 else { 2141 if (uiop->uio_resid > 0) 2142 printf("EEK! readdirrpc resid > 0\n"); 2143 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 1); 2144 *cookiep = cookie; 2145 } 2146nfsmout: 2147 return (error); 2148} 2149 2150/* 2151 * NFS V3 readdir plus RPC. Used in place of nfs_readdirrpc(). 2152 */ 2153int 2154nfs_readdirplusrpc(vp, uiop, cred) 2155 struct vnode *vp; 2156 register struct uio *uiop; 2157 struct ucred *cred; 2158{ 2159 register int len, left; 2160 register struct dirent *dp; 2161 register u_long *tl; 2162 register caddr_t cp; 2163 register long t1, t2; 2164 register struct vnode *newvp; 2165 register nfsuint64 *cookiep; 2166 caddr_t bpos, dpos, cp2, dpossav1, dpossav2; 2167 struct mbuf *mreq, *mrep, *md, *mb, *mb2, *mdsav1, *mdsav2; 2168 struct nameidata nami, *ndp = &nami; 2169 struct componentname *cnp = &ndp->ni_cnd; 2170 nfsuint64 cookie; 2171 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2172 struct nfsnode *dnp = VTONFS(vp), *np; 2173 nfsfh_t *fhp; 2174 u_quad_t fileno; 2175 int error = 0, tlen, more_dirs = 1, blksiz = 0, doit, bigenough = 1, i; 2176 int attrflag, fhsize; 2177 2178#ifndef nolint 2179 dp = (struct dirent *)0; 2180#endif 2181#ifndef DIAGNOSTIC 2182 if (uiop->uio_iovcnt != 1 || (uiop->uio_offset & (DIRBLKSIZ - 1)) || 2183 (uiop->uio_resid & (DIRBLKSIZ - 1))) 2184 panic("nfs readdirplusrpc bad uio"); 2185#endif 2186 ndp->ni_dvp = vp; 2187 newvp = NULLVP; 2188 2189 /* 2190 * If there is no cookie, assume directory was stale. 2191 */ 2192 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 0); 2193 if (cookiep) 2194 cookie = *cookiep; 2195 else 2196 return (NFSERR_BAD_COOKIE); 2197 /* 2198 * Loop around doing readdir rpc's of size nm_readdirsize 2199 * truncated to a multiple of DIRBLKSIZ. 2200 * The stopping criteria is EOF or buffer full. 2201 */ 2202 while (more_dirs && bigenough) { 2203 nfsstats.rpccnt[NFSPROC_READDIRPLUS]++; 2204 nfsm_reqhead(vp, NFSPROC_READDIRPLUS, 2205 NFSX_FH(1) + 6 * NFSX_UNSIGNED); 2206 nfsm_fhtom(vp, 1); 2207 nfsm_build(tl, u_long *, 6 * NFSX_UNSIGNED); 2208 *tl++ = cookie.nfsuquad[0]; 2209 *tl++ = cookie.nfsuquad[1]; 2210 *tl++ = dnp->n_cookieverf.nfsuquad[0]; 2211 *tl++ = dnp->n_cookieverf.nfsuquad[1]; 2212 *tl++ = txdr_unsigned(nmp->nm_readdirsize); 2213 *tl = txdr_unsigned(nmp->nm_rsize); 2214 nfsm_request(vp, NFSPROC_READDIRPLUS, uiop->uio_procp, cred); 2215 nfsm_postop_attr(vp, attrflag); 2216 if (error) { 2217 m_freem(mrep); 2218 goto nfsmout; 2219 } 2220 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2221 dnp->n_cookieverf.nfsuquad[0] = *tl++; 2222 dnp->n_cookieverf.nfsuquad[1] = *tl++; 2223 more_dirs = fxdr_unsigned(int, *tl); 2224 2225 /* loop thru the dir entries, doctoring them to 4bsd form */ 2226 while (more_dirs && bigenough) { 2227 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2228 fxdr_hyper(tl, &fileno); 2229 len = fxdr_unsigned(int, *(tl + 2)); 2230 if (len <= 0 || len > NFS_MAXNAMLEN) { 2231 error = EBADRPC; 2232 m_freem(mrep); 2233 goto nfsmout; 2234 } 2235 tlen = nfsm_rndup(len); 2236 if (tlen == len) 2237 tlen += 4; /* To ensure null termination*/ 2238 left = DIRBLKSIZ - blksiz; 2239 if ((tlen + DIRHDSIZ) > left) { 2240 dp->d_reclen += left; 2241 uiop->uio_iov->iov_base += left; 2242 uiop->uio_iov->iov_len -= left; 2243 uiop->uio_offset += left; 2244 uiop->uio_resid -= left; 2245 blksiz = 0; 2246 } 2247 if ((tlen + DIRHDSIZ) > uiop->uio_resid) 2248 bigenough = 0; 2249 if (bigenough) { 2250 dp = (struct dirent *)uiop->uio_iov->iov_base; 2251 dp->d_fileno = (int)fileno; 2252 dp->d_namlen = len; 2253 dp->d_reclen = tlen + DIRHDSIZ; 2254 dp->d_type = DT_UNKNOWN; 2255 blksiz += dp->d_reclen; 2256 if (blksiz == DIRBLKSIZ) 2257 blksiz = 0; 2258 uiop->uio_offset += DIRHDSIZ; 2259 uiop->uio_resid -= DIRHDSIZ; 2260 uiop->uio_iov->iov_base += DIRHDSIZ; 2261 uiop->uio_iov->iov_len -= DIRHDSIZ; 2262 cnp->cn_nameptr = uiop->uio_iov->iov_base; 2263 cnp->cn_namelen = len; 2264 nfsm_mtouio(uiop, len); 2265 cp = uiop->uio_iov->iov_base; 2266 tlen -= len; 2267 *cp = '\0'; 2268 uiop->uio_iov->iov_base += tlen; 2269 uiop->uio_iov->iov_len -= tlen; 2270 uiop->uio_offset += tlen; 2271 uiop->uio_resid -= tlen; 2272 } else 2273 nfsm_adv(nfsm_rndup(len)); 2274 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2275 if (bigenough) { 2276 cookie.nfsuquad[0] = *tl++; 2277 cookie.nfsuquad[1] = *tl++; 2278 } else 2279 tl += 2; 2280 2281 /* 2282 * Since the attributes are before the file handle 2283 * (sigh), we must skip over the attributes and then 2284 * come back and get them. 2285 */ 2286 attrflag = fxdr_unsigned(int, *tl); 2287 if (attrflag) { 2288 dpossav1 = dpos; 2289 mdsav1 = md; 2290 nfsm_adv(NFSX_V3FATTR); 2291 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2292 doit = fxdr_unsigned(int, *tl); 2293 if (doit) { 2294 nfsm_getfh(fhp, fhsize, 1); 2295 if (NFS_CMPFH(dnp, fhp, fhsize)) { 2296 VREF(vp); 2297 newvp = vp; 2298 np = dnp; 2299 } else { 2300 error = nfs_nget(vp->v_mount, fhp, 2301 fhsize, &np); 2302 if (error) 2303 doit = 0; 2304 else 2305 newvp = NFSTOV(np); 2306 } 2307 } 2308 if (doit) { 2309 dpossav2 = dpos; 2310 dpos = dpossav1; 2311 mdsav2 = md; 2312 md = mdsav1; 2313 nfsm_loadattr(newvp, (struct vattr *)0); 2314 dpos = dpossav2; 2315 md = mdsav2; 2316 dp->d_type = 2317 IFTODT(VTTOIF(np->n_vattr.va_type)); 2318 ndp->ni_vp = newvp; 2319 cnp->cn_hash = 0; 2320 for (cp = cnp->cn_nameptr, i = 1; i <= len; 2321 i++, cp++) 2322 cnp->cn_hash += (unsigned char)*cp * i; 2323 cache_enter(ndp->ni_dvp, ndp->ni_vp, cnp); 2324 } 2325 } else { 2326 /* Just skip over the file handle */ 2327 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2328 i = fxdr_unsigned(int, *tl); 2329 nfsm_adv(nfsm_rndup(i)); 2330 } 2331 if (newvp != NULLVP) { 2332 vrele(newvp); 2333 newvp = NULLVP; 2334 } 2335 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2336 more_dirs = fxdr_unsigned(int, *tl); 2337 } 2338 /* 2339 * If at end of rpc data, get the eof boolean 2340 */ 2341 if (!more_dirs) { 2342 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2343 more_dirs = (fxdr_unsigned(int, *tl) == 0); 2344 } 2345 m_freem(mrep); 2346 } 2347 /* 2348 * Fill last record, iff any, out to a multiple of NFS_DIRBLKSIZ 2349 * by increasing d_reclen for the last record. 2350 */ 2351 if (blksiz > 0) { 2352 left = DIRBLKSIZ - blksiz; 2353 dp->d_reclen += left; 2354 uiop->uio_iov->iov_base += left; 2355 uiop->uio_iov->iov_len -= left; 2356 uiop->uio_offset += left; 2357 uiop->uio_resid -= left; 2358 } 2359 2360 /* 2361 * We are now either at the end of the directory or have filled the 2362 * block. 2363 */ 2364 if (bigenough) 2365 dnp->n_direofoffset = uiop->uio_offset; 2366 else { 2367 if (uiop->uio_resid > 0) 2368 printf("EEK! readdirplusrpc resid > 0\n"); 2369 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 1); 2370 *cookiep = cookie; 2371 } 2372nfsmout: 2373 if (newvp != NULLVP) { 2374 if (newvp == vp) 2375 vrele(newvp); 2376 else 2377 vput(newvp); 2378 newvp = NULLVP; 2379 } 2380 return (error); 2381} 2382 2383/* 2384 * Silly rename. To make the NFS filesystem that is stateless look a little 2385 * more like the "ufs" a remove of an active vnode is translated to a rename 2386 * to a funny looking filename that is removed by nfs_inactive on the 2387 * nfsnode. There is the potential for another process on a different client 2388 * to create the same funny name between the nfs_lookitup() fails and the 2389 * nfs_rename() completes, but... 2390 */ 2391static int 2392nfs_sillyrename(dvp, vp, cnp) 2393 struct vnode *dvp, *vp; 2394 struct componentname *cnp; 2395{ 2396 register struct sillyrename *sp; 2397 struct nfsnode *np; 2398 int error; 2399 short pid; 2400 2401 cache_purge(dvp); 2402 np = VTONFS(vp); 2403#ifndef DIAGNOSTIC 2404 if (vp->v_type == VDIR) 2405 panic("nfs: sillyrename dir"); 2406#endif 2407 MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename), 2408 M_NFSREQ, M_WAITOK); 2409 sp->s_cred = crdup(cnp->cn_cred); 2410 sp->s_dvp = dvp; 2411 VREF(dvp); 2412 2413 /* Fudge together a funny name */ 2414 pid = cnp->cn_proc->p_pid; 2415 sp->s_namlen = sprintf(sp->s_name, ".nfsA%04x4.4", pid); 2416 2417 /* Try lookitups until we get one that isn't there */ 2418 while (nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred, 2419 cnp->cn_proc, (struct nfsnode **)0) == 0) { 2420 sp->s_name[4]++; 2421 if (sp->s_name[4] > 'z') { 2422 error = EINVAL; 2423 goto bad; 2424 } 2425 } 2426 error = nfs_renameit(dvp, cnp, sp); 2427 if (error) 2428 goto bad; 2429 error = nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred, 2430 cnp->cn_proc, &np); 2431 np->n_sillyrename = sp; 2432 return (0); 2433bad: 2434 vrele(sp->s_dvp); 2435 crfree(sp->s_cred); 2436 free((caddr_t)sp, M_NFSREQ); 2437 return (error); 2438} 2439 2440/* 2441 * Look up a file name and optionally either update the file handle or 2442 * allocate an nfsnode, depending on the value of npp. 2443 * npp == NULL --> just do the lookup 2444 * *npp == NULL --> allocate a new nfsnode and make sure attributes are 2445 * handled too 2446 * *npp != NULL --> update the file handle in the vnode 2447 */ 2448static int 2449nfs_lookitup(dvp, name, len, cred, procp, npp) 2450 register struct vnode *dvp;
| 1623 int tnamelen; 1624 struct ucred *cred; 1625 struct proc *proc; 1626{ 1627 register u_long *tl; 1628 register caddr_t cp; 1629 register long t1, t2; 1630 caddr_t bpos, dpos, cp2; 1631 int error = 0, fwccflag = NFSV3_WCCRATTR, twccflag = NFSV3_WCCRATTR; 1632 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1633 int v3 = NFS_ISV3(fdvp); 1634 1635 nfsstats.rpccnt[NFSPROC_RENAME]++; 1636 nfsm_reqhead(fdvp, NFSPROC_RENAME, 1637 (NFSX_FH(v3) + NFSX_UNSIGNED)*2 + nfsm_rndup(fnamelen) + 1638 nfsm_rndup(tnamelen)); 1639 nfsm_fhtom(fdvp, v3); 1640 nfsm_strtom(fnameptr, fnamelen, NFS_MAXNAMLEN); 1641 nfsm_fhtom(tdvp, v3); 1642 nfsm_strtom(tnameptr, tnamelen, NFS_MAXNAMLEN); 1643 nfsm_request(fdvp, NFSPROC_RENAME, proc, cred); 1644 if (v3) { 1645 nfsm_wcc_data(fdvp, fwccflag); 1646 nfsm_wcc_data(tdvp, twccflag); 1647 } 1648 nfsm_reqdone; 1649 VTONFS(fdvp)->n_flag |= NMODIFIED; 1650 VTONFS(tdvp)->n_flag |= NMODIFIED; 1651 if (!fwccflag) 1652 VTONFS(fdvp)->n_attrstamp = 0; 1653 if (!twccflag) 1654 VTONFS(tdvp)->n_attrstamp = 0; 1655 return (error); 1656} 1657 1658/* 1659 * nfs hard link create call 1660 */ 1661static int 1662nfs_link(ap) 1663 struct vop_link_args /* { 1664 struct vnode *a_tdvp; 1665 struct vnode *a_vp; 1666 struct componentname *a_cnp; 1667 } */ *ap; 1668{ 1669 register struct vnode *vp = ap->a_vp; 1670 register struct vnode *tdvp = ap->a_tdvp; 1671 register struct componentname *cnp = ap->a_cnp; 1672 register u_long *tl; 1673 register caddr_t cp; 1674 register long t1, t2; 1675 caddr_t bpos, dpos, cp2; 1676 int error = 0, wccflag = NFSV3_WCCRATTR, attrflag = 0; 1677 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1678 int v3 = NFS_ISV3(vp); 1679 1680 if (vp->v_mount != tdvp->v_mount) { 1681 VOP_ABORTOP(tdvp, cnp); 1682 return (EXDEV); 1683 } 1684 1685 /* 1686 * Push all writes to the server, so that the attribute cache 1687 * doesn't get "out of sync" with the server. 1688 * XXX There should be a better way! 1689 */ 1690 VOP_FSYNC(vp, cnp->cn_cred, MNT_WAIT, cnp->cn_proc); 1691 1692 nfsstats.rpccnt[NFSPROC_LINK]++; 1693 nfsm_reqhead(vp, NFSPROC_LINK, 1694 NFSX_FH(v3)*2 + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen)); 1695 nfsm_fhtom(vp, v3); 1696 nfsm_fhtom(tdvp, v3); 1697 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1698 nfsm_request(vp, NFSPROC_LINK, cnp->cn_proc, cnp->cn_cred); 1699 if (v3) { 1700 nfsm_postop_attr(vp, attrflag); 1701 nfsm_wcc_data(tdvp, wccflag); 1702 } 1703 nfsm_reqdone; 1704 zfree(namei_zone, cnp->cn_pnbuf); 1705 VTONFS(tdvp)->n_flag |= NMODIFIED; 1706 if (!attrflag) 1707 VTONFS(vp)->n_attrstamp = 0; 1708 if (!wccflag) 1709 VTONFS(tdvp)->n_attrstamp = 0; 1710 /* 1711 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry. 1712 */ 1713 if (error == EEXIST) 1714 error = 0; 1715 return (error); 1716} 1717 1718/* 1719 * nfs symbolic link create call 1720 */ 1721static int 1722nfs_symlink(ap) 1723 struct vop_symlink_args /* { 1724 struct vnode *a_dvp; 1725 struct vnode **a_vpp; 1726 struct componentname *a_cnp; 1727 struct vattr *a_vap; 1728 char *a_target; 1729 } */ *ap; 1730{ 1731 register struct vnode *dvp = ap->a_dvp; 1732 register struct vattr *vap = ap->a_vap; 1733 register struct componentname *cnp = ap->a_cnp; 1734 register struct nfsv2_sattr *sp; 1735 register struct nfsv3_sattr *sp3; 1736 register u_long *tl; 1737 register caddr_t cp; 1738 register long t1, t2; 1739 caddr_t bpos, dpos, cp2; 1740 int slen, error = 0, wccflag = NFSV3_WCCRATTR, gotvp; 1741 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1742 struct vnode *newvp = (struct vnode *)0; 1743 int v3 = NFS_ISV3(dvp); 1744 1745 nfsstats.rpccnt[NFSPROC_SYMLINK]++; 1746 slen = strlen(ap->a_target); 1747 nfsm_reqhead(dvp, NFSPROC_SYMLINK, NFSX_FH(v3) + 2*NFSX_UNSIGNED + 1748 nfsm_rndup(cnp->cn_namelen) + nfsm_rndup(slen) + NFSX_SATTR(v3)); 1749 nfsm_fhtom(dvp, v3); 1750 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1751 if (v3) { 1752 nfsm_build(sp3, struct nfsv3_sattr *, NFSX_V3SRVSATTR); 1753 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, 1754 cnp->cn_cred->cr_gid); 1755 } 1756 nfsm_strtom(ap->a_target, slen, NFS_MAXPATHLEN); 1757 if (!v3) { 1758 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1759 sp->sa_mode = vtonfsv2_mode(VLNK, vap->va_mode); 1760 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1761 sp->sa_gid = txdr_unsigned(cnp->cn_cred->cr_gid); 1762 sp->sa_size = -1; 1763 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1764 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1765 } 1766 nfsm_request(dvp, NFSPROC_SYMLINK, cnp->cn_proc, cnp->cn_cred); 1767 if (v3) { 1768 if (!error) 1769 nfsm_mtofh(dvp, newvp, v3, gotvp); 1770 nfsm_wcc_data(dvp, wccflag); 1771 } 1772 nfsm_reqdone; 1773 if (newvp) 1774 vput(newvp); 1775 zfree(namei_zone, cnp->cn_pnbuf); 1776 VTONFS(dvp)->n_flag |= NMODIFIED; 1777 if (!wccflag) 1778 VTONFS(dvp)->n_attrstamp = 0; 1779 /* 1780 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry. 1781 */ 1782 if (error == EEXIST) 1783 error = 0; 1784 return (error); 1785} 1786 1787/* 1788 * nfs make dir call 1789 */ 1790static int 1791nfs_mkdir(ap) 1792 struct vop_mkdir_args /* { 1793 struct vnode *a_dvp; 1794 struct vnode **a_vpp; 1795 struct componentname *a_cnp; 1796 struct vattr *a_vap; 1797 } */ *ap; 1798{ 1799 register struct vnode *dvp = ap->a_dvp; 1800 register struct vattr *vap = ap->a_vap; 1801 register struct componentname *cnp = ap->a_cnp; 1802 register struct nfsv2_sattr *sp; 1803 register struct nfsv3_sattr *sp3; 1804 register u_long *tl; 1805 register caddr_t cp; 1806 register long t1, t2; 1807 register int len; 1808 struct nfsnode *np = (struct nfsnode *)0; 1809 struct vnode *newvp = (struct vnode *)0; 1810 caddr_t bpos, dpos, cp2; 1811 int error = 0, wccflag = NFSV3_WCCRATTR; 1812 int gotvp = 0; 1813 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1814 struct vattr vattr; 1815 int v3 = NFS_ISV3(dvp); 1816 1817 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 1818 VOP_ABORTOP(dvp, cnp); 1819 return (error); 1820 } 1821 len = cnp->cn_namelen; 1822 nfsstats.rpccnt[NFSPROC_MKDIR]++; 1823 nfsm_reqhead(dvp, NFSPROC_MKDIR, 1824 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len) + NFSX_SATTR(v3)); 1825 nfsm_fhtom(dvp, v3); 1826 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); 1827 if (v3) { 1828 nfsm_build(sp3, struct nfsv3_sattr *, NFSX_V3SRVSATTR); 1829 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, vattr.va_gid); 1830 } else { 1831 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1832 sp->sa_mode = vtonfsv2_mode(VDIR, vap->va_mode); 1833 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1834 sp->sa_gid = txdr_unsigned(vattr.va_gid); 1835 sp->sa_size = -1; 1836 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1837 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1838 } 1839 nfsm_request(dvp, NFSPROC_MKDIR, cnp->cn_proc, cnp->cn_cred); 1840 if (!error) 1841 nfsm_mtofh(dvp, newvp, v3, gotvp); 1842 if (v3) 1843 nfsm_wcc_data(dvp, wccflag); 1844 nfsm_reqdone; 1845 VTONFS(dvp)->n_flag |= NMODIFIED; 1846 if (!wccflag) 1847 VTONFS(dvp)->n_attrstamp = 0; 1848 /* 1849 * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry 1850 * if we can succeed in looking up the directory. 1851 */ 1852 if (error == EEXIST || (!error && !gotvp)) { 1853 if (newvp) { 1854 vrele(newvp); 1855 newvp = (struct vnode *)0; 1856 } 1857 error = nfs_lookitup(dvp, cnp->cn_nameptr, len, cnp->cn_cred, 1858 cnp->cn_proc, &np); 1859 if (!error) { 1860 newvp = NFSTOV(np); 1861 if (newvp->v_type != VDIR) 1862 error = EEXIST; 1863 } 1864 } 1865 if (error) { 1866 if (newvp) 1867 vrele(newvp); 1868 } else 1869 *ap->a_vpp = newvp; 1870 zfree(namei_zone, cnp->cn_pnbuf); 1871 return (error); 1872} 1873 1874/* 1875 * nfs remove directory call 1876 */ 1877static int 1878nfs_rmdir(ap) 1879 struct vop_rmdir_args /* { 1880 struct vnode *a_dvp; 1881 struct vnode *a_vp; 1882 struct componentname *a_cnp; 1883 } */ *ap; 1884{ 1885 register struct vnode *vp = ap->a_vp; 1886 register struct vnode *dvp = ap->a_dvp; 1887 register struct componentname *cnp = ap->a_cnp; 1888 register u_long *tl; 1889 register caddr_t cp; 1890 register long t1, t2; 1891 caddr_t bpos, dpos, cp2; 1892 int error = 0, wccflag = NFSV3_WCCRATTR; 1893 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1894 int v3 = NFS_ISV3(dvp); 1895 1896 nfsstats.rpccnt[NFSPROC_RMDIR]++; 1897 nfsm_reqhead(dvp, NFSPROC_RMDIR, 1898 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen)); 1899 nfsm_fhtom(dvp, v3); 1900 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1901 nfsm_request(dvp, NFSPROC_RMDIR, cnp->cn_proc, cnp->cn_cred); 1902 if (v3) 1903 nfsm_wcc_data(dvp, wccflag); 1904 nfsm_reqdone; 1905 zfree(namei_zone, cnp->cn_pnbuf); 1906 VTONFS(dvp)->n_flag |= NMODIFIED; 1907 if (!wccflag) 1908 VTONFS(dvp)->n_attrstamp = 0; 1909 cache_purge(dvp); 1910 cache_purge(vp); 1911 /* 1912 * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry. 1913 */ 1914 if (error == ENOENT) 1915 error = 0; 1916 return (error); 1917} 1918 1919/* 1920 * nfs readdir call 1921 */ 1922static int 1923nfs_readdir(ap) 1924 struct vop_readdir_args /* { 1925 struct vnode *a_vp; 1926 struct uio *a_uio; 1927 struct ucred *a_cred; 1928 } */ *ap; 1929{ 1930 register struct vnode *vp = ap->a_vp; 1931 register struct nfsnode *np = VTONFS(vp); 1932 register struct uio *uio = ap->a_uio; 1933 int tresid, error; 1934 struct vattr vattr; 1935 1936 if (vp->v_type != VDIR) 1937 return (EPERM); 1938 /* 1939 * First, check for hit on the EOF offset cache 1940 */ 1941 if (np->n_direofoffset > 0 && uio->uio_offset >= np->n_direofoffset && 1942 (np->n_flag & NMODIFIED) == 0) { 1943 if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) { 1944 if (NQNFS_CKCACHABLE(vp, ND_READ)) { 1945 nfsstats.direofcache_hits++; 1946 return (0); 1947 } 1948 } else if (VOP_GETATTR(vp, &vattr, ap->a_cred, uio->uio_procp) == 0 && 1949 np->n_mtime == vattr.va_mtime.tv_sec) { 1950 nfsstats.direofcache_hits++; 1951 return (0); 1952 } 1953 } 1954 1955 /* 1956 * Call nfs_bioread() to do the real work. 1957 */ 1958 tresid = uio->uio_resid; 1959 error = nfs_bioread(vp, uio, 0, ap->a_cred, 0); 1960 1961 if (!error && uio->uio_resid == tresid) 1962 nfsstats.direofcache_misses++; 1963 return (error); 1964} 1965 1966/* 1967 * Readdir rpc call. 1968 * Called from below the buffer cache by nfs_doio(). 1969 */ 1970int 1971nfs_readdirrpc(vp, uiop, cred) 1972 struct vnode *vp; 1973 register struct uio *uiop; 1974 struct ucred *cred; 1975 1976{ 1977 register int len, left; 1978 register struct dirent *dp; 1979 register u_long *tl; 1980 register caddr_t cp; 1981 register long t1, t2; 1982 register nfsuint64 *cookiep; 1983 caddr_t bpos, dpos, cp2; 1984 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1985 nfsuint64 cookie; 1986 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 1987 struct nfsnode *dnp = VTONFS(vp); 1988 u_quad_t fileno; 1989 int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1; 1990 int attrflag; 1991 int v3 = NFS_ISV3(vp); 1992 1993#ifndef nolint 1994 dp = (struct dirent *)0; 1995#endif 1996#ifndef DIAGNOSTIC 1997 if (uiop->uio_iovcnt != 1 || (uiop->uio_offset & (NFS_DIRBLKSIZ - 1)) || 1998 (uiop->uio_resid & (NFS_DIRBLKSIZ - 1))) 1999 panic("nfs readdirrpc bad uio"); 2000#endif 2001 2002 /* 2003 * If there is no cookie, assume directory was stale. 2004 */ 2005 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 0); 2006 if (cookiep) 2007 cookie = *cookiep; 2008 else 2009 return (NFSERR_BAD_COOKIE); 2010 /* 2011 * Loop around doing readdir rpc's of size nm_readdirsize 2012 * truncated to a multiple of DIRBLKSIZ. 2013 * The stopping criteria is EOF or buffer full. 2014 */ 2015 while (more_dirs && bigenough) { 2016 nfsstats.rpccnt[NFSPROC_READDIR]++; 2017 nfsm_reqhead(vp, NFSPROC_READDIR, NFSX_FH(v3) + 2018 NFSX_READDIR(v3)); 2019 nfsm_fhtom(vp, v3); 2020 if (v3) { 2021 nfsm_build(tl, u_long *, 5 * NFSX_UNSIGNED); 2022 *tl++ = cookie.nfsuquad[0]; 2023 *tl++ = cookie.nfsuquad[1]; 2024 *tl++ = dnp->n_cookieverf.nfsuquad[0]; 2025 *tl++ = dnp->n_cookieverf.nfsuquad[1]; 2026 } else { 2027 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 2028 *tl++ = cookie.nfsuquad[0]; 2029 } 2030 *tl = txdr_unsigned(nmp->nm_readdirsize); 2031 nfsm_request(vp, NFSPROC_READDIR, uiop->uio_procp, cred); 2032 if (v3) { 2033 nfsm_postop_attr(vp, attrflag); 2034 if (!error) { 2035 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 2036 dnp->n_cookieverf.nfsuquad[0] = *tl++; 2037 dnp->n_cookieverf.nfsuquad[1] = *tl; 2038 } else { 2039 m_freem(mrep); 2040 goto nfsmout; 2041 } 2042 } 2043 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2044 more_dirs = fxdr_unsigned(int, *tl); 2045 2046 /* loop thru the dir entries, doctoring them to 4bsd form */ 2047 while (more_dirs && bigenough) { 2048 if (v3) { 2049 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2050 fxdr_hyper(tl, &fileno); 2051 len = fxdr_unsigned(int, *(tl + 2)); 2052 } else { 2053 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 2054 fileno = fxdr_unsigned(u_quad_t, *tl++); 2055 len = fxdr_unsigned(int, *tl); 2056 } 2057 if (len <= 0 || len > NFS_MAXNAMLEN) { 2058 error = EBADRPC; 2059 m_freem(mrep); 2060 goto nfsmout; 2061 } 2062 tlen = nfsm_rndup(len); 2063 if (tlen == len) 2064 tlen += 4; /* To ensure null termination */ 2065 left = DIRBLKSIZ - blksiz; 2066 if ((tlen + DIRHDSIZ) > left) { 2067 dp->d_reclen += left; 2068 uiop->uio_iov->iov_base += left; 2069 uiop->uio_iov->iov_len -= left; 2070 uiop->uio_offset += left; 2071 uiop->uio_resid -= left; 2072 blksiz = 0; 2073 } 2074 if ((tlen + DIRHDSIZ) > uiop->uio_resid) 2075 bigenough = 0; 2076 if (bigenough) { 2077 dp = (struct dirent *)uiop->uio_iov->iov_base; 2078 dp->d_fileno = (int)fileno; 2079 dp->d_namlen = len; 2080 dp->d_reclen = tlen + DIRHDSIZ; 2081 dp->d_type = DT_UNKNOWN; 2082 blksiz += dp->d_reclen; 2083 if (blksiz == DIRBLKSIZ) 2084 blksiz = 0; 2085 uiop->uio_offset += DIRHDSIZ; 2086 uiop->uio_resid -= DIRHDSIZ; 2087 uiop->uio_iov->iov_base += DIRHDSIZ; 2088 uiop->uio_iov->iov_len -= DIRHDSIZ; 2089 nfsm_mtouio(uiop, len); 2090 cp = uiop->uio_iov->iov_base; 2091 tlen -= len; 2092 *cp = '\0'; /* null terminate */ 2093 uiop->uio_iov->iov_base += tlen; 2094 uiop->uio_iov->iov_len -= tlen; 2095 uiop->uio_offset += tlen; 2096 uiop->uio_resid -= tlen; 2097 } else 2098 nfsm_adv(nfsm_rndup(len)); 2099 if (v3) { 2100 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2101 } else { 2102 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 2103 } 2104 if (bigenough) { 2105 cookie.nfsuquad[0] = *tl++; 2106 if (v3) 2107 cookie.nfsuquad[1] = *tl++; 2108 } else if (v3) 2109 tl += 2; 2110 else 2111 tl++; 2112 more_dirs = fxdr_unsigned(int, *tl); 2113 } 2114 /* 2115 * If at end of rpc data, get the eof boolean 2116 */ 2117 if (!more_dirs) { 2118 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2119 more_dirs = (fxdr_unsigned(int, *tl) == 0); 2120 } 2121 m_freem(mrep); 2122 } 2123 /* 2124 * Fill last record, iff any, out to a multiple of DIRBLKSIZ 2125 * by increasing d_reclen for the last record. 2126 */ 2127 if (blksiz > 0) { 2128 left = DIRBLKSIZ - blksiz; 2129 dp->d_reclen += left; 2130 uiop->uio_iov->iov_base += left; 2131 uiop->uio_iov->iov_len -= left; 2132 uiop->uio_offset += left; 2133 uiop->uio_resid -= left; 2134 } 2135 2136 /* 2137 * We are now either at the end of the directory or have filled the 2138 * block. 2139 */ 2140 if (bigenough) 2141 dnp->n_direofoffset = uiop->uio_offset; 2142 else { 2143 if (uiop->uio_resid > 0) 2144 printf("EEK! readdirrpc resid > 0\n"); 2145 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 1); 2146 *cookiep = cookie; 2147 } 2148nfsmout: 2149 return (error); 2150} 2151 2152/* 2153 * NFS V3 readdir plus RPC. Used in place of nfs_readdirrpc(). 2154 */ 2155int 2156nfs_readdirplusrpc(vp, uiop, cred) 2157 struct vnode *vp; 2158 register struct uio *uiop; 2159 struct ucred *cred; 2160{ 2161 register int len, left; 2162 register struct dirent *dp; 2163 register u_long *tl; 2164 register caddr_t cp; 2165 register long t1, t2; 2166 register struct vnode *newvp; 2167 register nfsuint64 *cookiep; 2168 caddr_t bpos, dpos, cp2, dpossav1, dpossav2; 2169 struct mbuf *mreq, *mrep, *md, *mb, *mb2, *mdsav1, *mdsav2; 2170 struct nameidata nami, *ndp = &nami; 2171 struct componentname *cnp = &ndp->ni_cnd; 2172 nfsuint64 cookie; 2173 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2174 struct nfsnode *dnp = VTONFS(vp), *np; 2175 nfsfh_t *fhp; 2176 u_quad_t fileno; 2177 int error = 0, tlen, more_dirs = 1, blksiz = 0, doit, bigenough = 1, i; 2178 int attrflag, fhsize; 2179 2180#ifndef nolint 2181 dp = (struct dirent *)0; 2182#endif 2183#ifndef DIAGNOSTIC 2184 if (uiop->uio_iovcnt != 1 || (uiop->uio_offset & (DIRBLKSIZ - 1)) || 2185 (uiop->uio_resid & (DIRBLKSIZ - 1))) 2186 panic("nfs readdirplusrpc bad uio"); 2187#endif 2188 ndp->ni_dvp = vp; 2189 newvp = NULLVP; 2190 2191 /* 2192 * If there is no cookie, assume directory was stale. 2193 */ 2194 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 0); 2195 if (cookiep) 2196 cookie = *cookiep; 2197 else 2198 return (NFSERR_BAD_COOKIE); 2199 /* 2200 * Loop around doing readdir rpc's of size nm_readdirsize 2201 * truncated to a multiple of DIRBLKSIZ. 2202 * The stopping criteria is EOF or buffer full. 2203 */ 2204 while (more_dirs && bigenough) { 2205 nfsstats.rpccnt[NFSPROC_READDIRPLUS]++; 2206 nfsm_reqhead(vp, NFSPROC_READDIRPLUS, 2207 NFSX_FH(1) + 6 * NFSX_UNSIGNED); 2208 nfsm_fhtom(vp, 1); 2209 nfsm_build(tl, u_long *, 6 * NFSX_UNSIGNED); 2210 *tl++ = cookie.nfsuquad[0]; 2211 *tl++ = cookie.nfsuquad[1]; 2212 *tl++ = dnp->n_cookieverf.nfsuquad[0]; 2213 *tl++ = dnp->n_cookieverf.nfsuquad[1]; 2214 *tl++ = txdr_unsigned(nmp->nm_readdirsize); 2215 *tl = txdr_unsigned(nmp->nm_rsize); 2216 nfsm_request(vp, NFSPROC_READDIRPLUS, uiop->uio_procp, cred); 2217 nfsm_postop_attr(vp, attrflag); 2218 if (error) { 2219 m_freem(mrep); 2220 goto nfsmout; 2221 } 2222 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2223 dnp->n_cookieverf.nfsuquad[0] = *tl++; 2224 dnp->n_cookieverf.nfsuquad[1] = *tl++; 2225 more_dirs = fxdr_unsigned(int, *tl); 2226 2227 /* loop thru the dir entries, doctoring them to 4bsd form */ 2228 while (more_dirs && bigenough) { 2229 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2230 fxdr_hyper(tl, &fileno); 2231 len = fxdr_unsigned(int, *(tl + 2)); 2232 if (len <= 0 || len > NFS_MAXNAMLEN) { 2233 error = EBADRPC; 2234 m_freem(mrep); 2235 goto nfsmout; 2236 } 2237 tlen = nfsm_rndup(len); 2238 if (tlen == len) 2239 tlen += 4; /* To ensure null termination*/ 2240 left = DIRBLKSIZ - blksiz; 2241 if ((tlen + DIRHDSIZ) > left) { 2242 dp->d_reclen += left; 2243 uiop->uio_iov->iov_base += left; 2244 uiop->uio_iov->iov_len -= left; 2245 uiop->uio_offset += left; 2246 uiop->uio_resid -= left; 2247 blksiz = 0; 2248 } 2249 if ((tlen + DIRHDSIZ) > uiop->uio_resid) 2250 bigenough = 0; 2251 if (bigenough) { 2252 dp = (struct dirent *)uiop->uio_iov->iov_base; 2253 dp->d_fileno = (int)fileno; 2254 dp->d_namlen = len; 2255 dp->d_reclen = tlen + DIRHDSIZ; 2256 dp->d_type = DT_UNKNOWN; 2257 blksiz += dp->d_reclen; 2258 if (blksiz == DIRBLKSIZ) 2259 blksiz = 0; 2260 uiop->uio_offset += DIRHDSIZ; 2261 uiop->uio_resid -= DIRHDSIZ; 2262 uiop->uio_iov->iov_base += DIRHDSIZ; 2263 uiop->uio_iov->iov_len -= DIRHDSIZ; 2264 cnp->cn_nameptr = uiop->uio_iov->iov_base; 2265 cnp->cn_namelen = len; 2266 nfsm_mtouio(uiop, len); 2267 cp = uiop->uio_iov->iov_base; 2268 tlen -= len; 2269 *cp = '\0'; 2270 uiop->uio_iov->iov_base += tlen; 2271 uiop->uio_iov->iov_len -= tlen; 2272 uiop->uio_offset += tlen; 2273 uiop->uio_resid -= tlen; 2274 } else 2275 nfsm_adv(nfsm_rndup(len)); 2276 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2277 if (bigenough) { 2278 cookie.nfsuquad[0] = *tl++; 2279 cookie.nfsuquad[1] = *tl++; 2280 } else 2281 tl += 2; 2282 2283 /* 2284 * Since the attributes are before the file handle 2285 * (sigh), we must skip over the attributes and then 2286 * come back and get them. 2287 */ 2288 attrflag = fxdr_unsigned(int, *tl); 2289 if (attrflag) { 2290 dpossav1 = dpos; 2291 mdsav1 = md; 2292 nfsm_adv(NFSX_V3FATTR); 2293 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2294 doit = fxdr_unsigned(int, *tl); 2295 if (doit) { 2296 nfsm_getfh(fhp, fhsize, 1); 2297 if (NFS_CMPFH(dnp, fhp, fhsize)) { 2298 VREF(vp); 2299 newvp = vp; 2300 np = dnp; 2301 } else { 2302 error = nfs_nget(vp->v_mount, fhp, 2303 fhsize, &np); 2304 if (error) 2305 doit = 0; 2306 else 2307 newvp = NFSTOV(np); 2308 } 2309 } 2310 if (doit) { 2311 dpossav2 = dpos; 2312 dpos = dpossav1; 2313 mdsav2 = md; 2314 md = mdsav1; 2315 nfsm_loadattr(newvp, (struct vattr *)0); 2316 dpos = dpossav2; 2317 md = mdsav2; 2318 dp->d_type = 2319 IFTODT(VTTOIF(np->n_vattr.va_type)); 2320 ndp->ni_vp = newvp; 2321 cnp->cn_hash = 0; 2322 for (cp = cnp->cn_nameptr, i = 1; i <= len; 2323 i++, cp++) 2324 cnp->cn_hash += (unsigned char)*cp * i; 2325 cache_enter(ndp->ni_dvp, ndp->ni_vp, cnp); 2326 } 2327 } else { 2328 /* Just skip over the file handle */ 2329 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2330 i = fxdr_unsigned(int, *tl); 2331 nfsm_adv(nfsm_rndup(i)); 2332 } 2333 if (newvp != NULLVP) { 2334 vrele(newvp); 2335 newvp = NULLVP; 2336 } 2337 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2338 more_dirs = fxdr_unsigned(int, *tl); 2339 } 2340 /* 2341 * If at end of rpc data, get the eof boolean 2342 */ 2343 if (!more_dirs) { 2344 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2345 more_dirs = (fxdr_unsigned(int, *tl) == 0); 2346 } 2347 m_freem(mrep); 2348 } 2349 /* 2350 * Fill last record, iff any, out to a multiple of NFS_DIRBLKSIZ 2351 * by increasing d_reclen for the last record. 2352 */ 2353 if (blksiz > 0) { 2354 left = DIRBLKSIZ - blksiz; 2355 dp->d_reclen += left; 2356 uiop->uio_iov->iov_base += left; 2357 uiop->uio_iov->iov_len -= left; 2358 uiop->uio_offset += left; 2359 uiop->uio_resid -= left; 2360 } 2361 2362 /* 2363 * We are now either at the end of the directory or have filled the 2364 * block. 2365 */ 2366 if (bigenough) 2367 dnp->n_direofoffset = uiop->uio_offset; 2368 else { 2369 if (uiop->uio_resid > 0) 2370 printf("EEK! readdirplusrpc resid > 0\n"); 2371 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 1); 2372 *cookiep = cookie; 2373 } 2374nfsmout: 2375 if (newvp != NULLVP) { 2376 if (newvp == vp) 2377 vrele(newvp); 2378 else 2379 vput(newvp); 2380 newvp = NULLVP; 2381 } 2382 return (error); 2383} 2384 2385/* 2386 * Silly rename. To make the NFS filesystem that is stateless look a little 2387 * more like the "ufs" a remove of an active vnode is translated to a rename 2388 * to a funny looking filename that is removed by nfs_inactive on the 2389 * nfsnode. There is the potential for another process on a different client 2390 * to create the same funny name between the nfs_lookitup() fails and the 2391 * nfs_rename() completes, but... 2392 */ 2393static int 2394nfs_sillyrename(dvp, vp, cnp) 2395 struct vnode *dvp, *vp; 2396 struct componentname *cnp; 2397{ 2398 register struct sillyrename *sp; 2399 struct nfsnode *np; 2400 int error; 2401 short pid; 2402 2403 cache_purge(dvp); 2404 np = VTONFS(vp); 2405#ifndef DIAGNOSTIC 2406 if (vp->v_type == VDIR) 2407 panic("nfs: sillyrename dir"); 2408#endif 2409 MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename), 2410 M_NFSREQ, M_WAITOK); 2411 sp->s_cred = crdup(cnp->cn_cred); 2412 sp->s_dvp = dvp; 2413 VREF(dvp); 2414 2415 /* Fudge together a funny name */ 2416 pid = cnp->cn_proc->p_pid; 2417 sp->s_namlen = sprintf(sp->s_name, ".nfsA%04x4.4", pid); 2418 2419 /* Try lookitups until we get one that isn't there */ 2420 while (nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred, 2421 cnp->cn_proc, (struct nfsnode **)0) == 0) { 2422 sp->s_name[4]++; 2423 if (sp->s_name[4] > 'z') { 2424 error = EINVAL; 2425 goto bad; 2426 } 2427 } 2428 error = nfs_renameit(dvp, cnp, sp); 2429 if (error) 2430 goto bad; 2431 error = nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred, 2432 cnp->cn_proc, &np); 2433 np->n_sillyrename = sp; 2434 return (0); 2435bad: 2436 vrele(sp->s_dvp); 2437 crfree(sp->s_cred); 2438 free((caddr_t)sp, M_NFSREQ); 2439 return (error); 2440} 2441 2442/* 2443 * Look up a file name and optionally either update the file handle or 2444 * allocate an nfsnode, depending on the value of npp. 2445 * npp == NULL --> just do the lookup 2446 * *npp == NULL --> allocate a new nfsnode and make sure attributes are 2447 * handled too 2448 * *npp != NULL --> update the file handle in the vnode 2449 */ 2450static int 2451nfs_lookitup(dvp, name, len, cred, procp, npp) 2452 register struct vnode *dvp;
|
2451 char *name;
| 2453 const char *name;
|
2452 int len; 2453 struct ucred *cred; 2454 struct proc *procp; 2455 struct nfsnode **npp; 2456{ 2457 register u_long *tl; 2458 register caddr_t cp; 2459 register long t1, t2; 2460 struct vnode *newvp = (struct vnode *)0; 2461 struct nfsnode *np, *dnp = VTONFS(dvp); 2462 caddr_t bpos, dpos, cp2; 2463 int error = 0, fhlen, attrflag; 2464 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 2465 nfsfh_t *nfhp; 2466 int v3 = NFS_ISV3(dvp); 2467 2468 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 2469 nfsm_reqhead(dvp, NFSPROC_LOOKUP, 2470 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len)); 2471 nfsm_fhtom(dvp, v3); 2472 nfsm_strtom(name, len, NFS_MAXNAMLEN); 2473 nfsm_request(dvp, NFSPROC_LOOKUP, procp, cred); 2474 if (npp && !error) { 2475 nfsm_getfh(nfhp, fhlen, v3); 2476 if (*npp) { 2477 np = *npp; 2478 if (np->n_fhsize > NFS_SMALLFH && fhlen <= NFS_SMALLFH) { 2479 free((caddr_t)np->n_fhp, M_NFSBIGFH); 2480 np->n_fhp = &np->n_fh; 2481 } else if (np->n_fhsize <= NFS_SMALLFH && fhlen>NFS_SMALLFH) 2482 np->n_fhp =(nfsfh_t *)malloc(fhlen,M_NFSBIGFH,M_WAITOK); 2483 bcopy((caddr_t)nfhp, (caddr_t)np->n_fhp, fhlen); 2484 np->n_fhsize = fhlen; 2485 newvp = NFSTOV(np); 2486 } else if (NFS_CMPFH(dnp, nfhp, fhlen)) { 2487 VREF(dvp); 2488 newvp = dvp; 2489 } else { 2490 error = nfs_nget(dvp->v_mount, nfhp, fhlen, &np); 2491 if (error) { 2492 m_freem(mrep); 2493 return (error); 2494 } 2495 newvp = NFSTOV(np); 2496 } 2497 if (v3) { 2498 nfsm_postop_attr(newvp, attrflag); 2499 if (!attrflag && *npp == NULL) { 2500 m_freem(mrep); 2501 if (newvp == dvp) 2502 vrele(newvp); 2503 else 2504 vput(newvp); 2505 return (ENOENT); 2506 } 2507 } else 2508 nfsm_loadattr(newvp, (struct vattr *)0); 2509 } 2510 nfsm_reqdone; 2511 if (npp && *npp == NULL) { 2512 if (error) { 2513 if (newvp) 2514 if (newvp == dvp) 2515 vrele(newvp); 2516 else 2517 vput(newvp); 2518 } else 2519 *npp = np; 2520 } 2521 return (error); 2522} 2523 2524/* 2525 * Nfs Version 3 commit rpc 2526 */ 2527static int 2528nfs_commit(vp, offset, cnt, cred, procp) 2529 register struct vnode *vp; 2530 u_quad_t offset; 2531 int cnt; 2532 struct ucred *cred; 2533 struct proc *procp; 2534{ 2535 register caddr_t cp; 2536 register u_long *tl; 2537 register int t1, t2; 2538 register struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2539 caddr_t bpos, dpos, cp2; 2540 int error = 0, wccflag = NFSV3_WCCRATTR; 2541 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 2542 2543 if ((nmp->nm_state & NFSSTA_HASWRITEVERF) == 0) 2544 return (0); 2545 nfsstats.rpccnt[NFSPROC_COMMIT]++; 2546 nfsm_reqhead(vp, NFSPROC_COMMIT, NFSX_FH(1)); 2547 nfsm_fhtom(vp, 1); 2548 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED); 2549 txdr_hyper(&offset, tl); 2550 tl += 2; 2551 *tl = txdr_unsigned(cnt); 2552 nfsm_request(vp, NFSPROC_COMMIT, procp, cred); 2553 nfsm_wcc_data(vp, wccflag); 2554 if (!error) { 2555 nfsm_dissect(tl, u_long *, NFSX_V3WRITEVERF); 2556 if (bcmp((caddr_t)nmp->nm_verf, (caddr_t)tl, 2557 NFSX_V3WRITEVERF)) { 2558 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf, 2559 NFSX_V3WRITEVERF); 2560 error = NFSERR_STALEWRITEVERF; 2561 } 2562 } 2563 nfsm_reqdone; 2564 return (error); 2565} 2566 2567/* 2568 * Kludge City.. 2569 * - make nfs_bmap() essentially a no-op that does no translation 2570 * - do nfs_strategy() by doing I/O with nfs_readrpc/nfs_writerpc 2571 * (Maybe I could use the process's page mapping, but I was concerned that 2572 * Kernel Write might not be enabled and also figured copyout() would do 2573 * a lot more work than bcopy() and also it currently happens in the 2574 * context of the swapper process (2). 2575 */ 2576static int 2577nfs_bmap(ap) 2578 struct vop_bmap_args /* { 2579 struct vnode *a_vp; 2580 daddr_t a_bn; 2581 struct vnode **a_vpp; 2582 daddr_t *a_bnp; 2583 int *a_runp; 2584 int *a_runb; 2585 } */ *ap; 2586{ 2587 register struct vnode *vp = ap->a_vp; 2588 2589 if (ap->a_vpp != NULL) 2590 *ap->a_vpp = vp; 2591 if (ap->a_bnp != NULL) 2592 *ap->a_bnp = ap->a_bn * btodb(vp->v_mount->mnt_stat.f_iosize); 2593 if (ap->a_runp != NULL) 2594 *ap->a_runp = 0; 2595 if (ap->a_runb != NULL) 2596 *ap->a_runb = 0; 2597 return (0); 2598} 2599 2600/* 2601 * Strategy routine. 2602 * For async requests when nfsiod(s) are running, queue the request by 2603 * calling nfs_asyncio(), otherwise just all nfs_doio() to do the 2604 * request. 2605 */ 2606static int 2607nfs_strategy(ap) 2608 struct vop_strategy_args *ap; 2609{ 2610 register struct buf *bp = ap->a_bp; 2611 struct ucred *cr; 2612 struct proc *p; 2613 int error = 0; 2614 2615 if (bp->b_flags & B_PHYS) 2616 panic("nfs physio"); 2617 if (bp->b_flags & B_ASYNC) 2618 p = (struct proc *)0; 2619 else 2620 p = curproc; /* XXX */ 2621 if (bp->b_flags & B_READ) 2622 cr = bp->b_rcred; 2623 else 2624 cr = bp->b_wcred; 2625 /* 2626 * If the op is asynchronous and an i/o daemon is waiting 2627 * queue the request, wake it up and wait for completion 2628 * otherwise just do it ourselves. 2629 */ 2630 if ((bp->b_flags & B_ASYNC) == 0 || 2631 nfs_asyncio(bp, NOCRED)) 2632 error = nfs_doio(bp, cr, p); 2633 return (error); 2634} 2635 2636/* 2637 * Mmap a file 2638 * 2639 * NB Currently unsupported. 2640 */ 2641/* ARGSUSED */ 2642static int 2643nfs_mmap(ap) 2644 struct vop_mmap_args /* { 2645 struct vnode *a_vp; 2646 int a_fflags; 2647 struct ucred *a_cred; 2648 struct proc *a_p; 2649 } */ *ap; 2650{ 2651 2652 return (EINVAL); 2653} 2654 2655/* 2656 * fsync vnode op. Just call nfs_flush() with commit == 1. 2657 */ 2658/* ARGSUSED */ 2659static int 2660nfs_fsync(ap) 2661 struct vop_fsync_args /* { 2662 struct vnodeop_desc *a_desc; 2663 struct vnode * a_vp; 2664 struct ucred * a_cred; 2665 int a_waitfor; 2666 struct proc * a_p; 2667 } */ *ap; 2668{ 2669 2670 return (nfs_flush(ap->a_vp, ap->a_cred, ap->a_waitfor, ap->a_p, 1)); 2671} 2672 2673/* 2674 * Flush all the blocks associated with a vnode. 2675 * Walk through the buffer pool and push any dirty pages 2676 * associated with the vnode. 2677 */ 2678static int 2679nfs_flush(vp, cred, waitfor, p, commit) 2680 register struct vnode *vp; 2681 struct ucred *cred; 2682 int waitfor; 2683 struct proc *p; 2684 int commit; 2685{ 2686 register struct nfsnode *np = VTONFS(vp); 2687 register struct buf *bp; 2688 register int i; 2689 struct buf *nbp; 2690 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2691 int s, error = 0, slptimeo = 0, slpflag = 0, retv, bvecpos; 2692 int passone = 1; 2693 u_quad_t off, endoff, toff; 2694 struct ucred* wcred = NULL; 2695 struct buf **bvec = NULL; 2696#ifndef NFS_COMMITBVECSIZ 2697#define NFS_COMMITBVECSIZ 20 2698#endif 2699 struct buf *bvec_on_stack[NFS_COMMITBVECSIZ]; 2700 int bvecsize = 0, bveccount; 2701 2702 if (nmp->nm_flag & NFSMNT_INT) 2703 slpflag = PCATCH; 2704 if (!commit) 2705 passone = 0; 2706 /* 2707 * A b_flags == (B_DELWRI | B_NEEDCOMMIT) block has been written to the 2708 * server, but nas not been committed to stable storage on the server 2709 * yet. On the first pass, the byte range is worked out and the commit 2710 * rpc is done. On the second pass, nfs_writebp() is called to do the 2711 * job. 2712 */ 2713again: 2714 off = (u_quad_t)-1; 2715 endoff = 0; 2716 bvecpos = 0; 2717 if (NFS_ISV3(vp) && commit) { 2718 s = splbio(); 2719 /* 2720 * Count up how many buffers waiting for a commit. 2721 */ 2722 bveccount = 0; 2723 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { 2724 nbp = bp->b_vnbufs.le_next; 2725 if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT)) 2726 == (B_DELWRI | B_NEEDCOMMIT)) 2727 bveccount++; 2728 } 2729 /* 2730 * Allocate space to remember the list of bufs to commit. It is 2731 * important to use M_NOWAIT here to avoid a race with nfs_write. 2732 * If we can't get memory (for whatever reason), we will end up 2733 * committing the buffers one-by-one in the loop below. 2734 */ 2735 if (bveccount > NFS_COMMITBVECSIZ) { 2736 if (bvec != NULL && bvec != bvec_on_stack) 2737 free(bvec, M_TEMP); 2738 bvec = (struct buf **) 2739 malloc(bveccount * sizeof(struct buf *), 2740 M_TEMP, M_NOWAIT); 2741 if (bvec == NULL) { 2742 bvec = bvec_on_stack; 2743 bvecsize = NFS_COMMITBVECSIZ; 2744 } else 2745 bvecsize = bveccount; 2746 } else { 2747 bvec = bvec_on_stack; 2748 bvecsize = NFS_COMMITBVECSIZ; 2749 } 2750 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { 2751 nbp = bp->b_vnbufs.le_next; 2752 if (bvecpos >= bvecsize) 2753 break; 2754 if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT)) 2755 != (B_DELWRI | B_NEEDCOMMIT)) 2756 continue; 2757 bremfree(bp); 2758 /* 2759 * Work out if all buffers are using the same cred 2760 * so we can deal with them all with one commit. 2761 */ 2762 if (wcred == NULL) 2763 wcred = bp->b_wcred; 2764 else if (wcred != bp->b_wcred) 2765 wcred = NOCRED; 2766 bp->b_flags |= (B_BUSY | B_WRITEINPROG); 2767 vfs_busy_pages(bp, 1); 2768 /* 2769 * A list of these buffers is kept so that the 2770 * second loop knows which buffers have actually 2771 * been committed. This is necessary, since there 2772 * may be a race between the commit rpc and new 2773 * uncommitted writes on the file. 2774 */ 2775 bvec[bvecpos++] = bp; 2776 toff = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + 2777 bp->b_dirtyoff; 2778 if (toff < off) 2779 off = toff; 2780 toff += (u_quad_t)(bp->b_dirtyend - bp->b_dirtyoff); 2781 if (toff > endoff) 2782 endoff = toff; 2783 } 2784 splx(s); 2785 } 2786 if (bvecpos > 0) { 2787 /* 2788 * Commit data on the server, as required. 2789 * If all bufs are using the same wcred, then use that with 2790 * one call for all of them, otherwise commit each one 2791 * separately. 2792 */ 2793 if (wcred != NOCRED) 2794 retv = nfs_commit(vp, off, (int)(endoff - off), 2795 wcred, p); 2796 else { 2797 retv = 0; 2798 for (i = 0; i < bvecpos; i++) { 2799 off_t off, size; 2800 bp = bvec[i]; 2801 off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + 2802 bp->b_dirtyoff; 2803 size = (u_quad_t)(bp->b_dirtyend 2804 - bp->b_dirtyoff); 2805 retv = nfs_commit(vp, off, (int)size, 2806 bp->b_wcred, p); 2807 if (retv) break; 2808 } 2809 } 2810 2811 if (retv == NFSERR_STALEWRITEVERF) 2812 nfs_clearcommit(vp->v_mount); 2813 /* 2814 * Now, either mark the blocks I/O done or mark the 2815 * blocks dirty, depending on whether the commit 2816 * succeeded. 2817 */ 2818 for (i = 0; i < bvecpos; i++) { 2819 bp = bvec[i]; 2820 bp->b_flags &= ~(B_NEEDCOMMIT | B_WRITEINPROG); 2821 if (retv) { 2822 vfs_unbusy_pages(bp); 2823 brelse(bp); 2824 } else { 2825 vp->v_numoutput++; 2826 bp->b_flags |= B_ASYNC; 2827 if (bp->b_flags & B_DELWRI) { 2828 --numdirtybuffers; 2829 if (needsbuffer) { 2830 vfs_bio_need_satisfy(); 2831 } 2832 } 2833 s = splbio(); /* XXX check this positionning */ 2834 bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI); 2835 bp->b_dirtyoff = bp->b_dirtyend = 0; 2836 reassignbuf(bp, vp); 2837 splx(s); 2838 biodone(bp); 2839 } 2840 } 2841 } 2842 2843 /* 2844 * Start/do any write(s) that are required. 2845 */ 2846loop: 2847 s = splbio(); 2848 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { 2849 nbp = bp->b_vnbufs.le_next; 2850 if (bp->b_flags & B_BUSY) { 2851 if (waitfor != MNT_WAIT || passone) 2852 continue; 2853 bp->b_flags |= B_WANTED; 2854 error = tsleep((caddr_t)bp, slpflag | (PRIBIO + 1), 2855 "nfsfsync", slptimeo); 2856 splx(s); 2857 if (error) { 2858 if (nfs_sigintr(nmp, (struct nfsreq *)0, p)) { 2859 error = EINTR; 2860 goto done; 2861 } 2862 if (slpflag == PCATCH) { 2863 slpflag = 0; 2864 slptimeo = 2 * hz; 2865 } 2866 } 2867 goto loop; 2868 } 2869 if ((bp->b_flags & B_DELWRI) == 0) 2870 panic("nfs_fsync: not dirty"); 2871 if ((passone || !commit) && (bp->b_flags & B_NEEDCOMMIT)) 2872 continue; 2873 bremfree(bp); 2874 if (passone || !commit) 2875 bp->b_flags |= (B_BUSY|B_ASYNC); 2876 else 2877 bp->b_flags |= (B_BUSY|B_ASYNC|B_WRITEINPROG|B_NEEDCOMMIT); 2878 splx(s); 2879 VOP_BWRITE(bp); 2880 goto loop; 2881 } 2882 splx(s); 2883 if (passone) { 2884 passone = 0; 2885 goto again; 2886 } 2887 if (waitfor == MNT_WAIT) { 2888 while (vp->v_numoutput) { 2889 vp->v_flag |= VBWAIT; 2890 error = tsleep((caddr_t)&vp->v_numoutput, 2891 slpflag | (PRIBIO + 1), "nfsfsync", slptimeo); 2892 if (error) { 2893 if (nfs_sigintr(nmp, (struct nfsreq *)0, p)) { 2894 error = EINTR; 2895 goto done; 2896 } 2897 if (slpflag == PCATCH) { 2898 slpflag = 0; 2899 slptimeo = 2 * hz; 2900 } 2901 } 2902 } 2903 if (vp->v_dirtyblkhd.lh_first && commit) { 2904 goto loop; 2905 } 2906 } 2907 if (np->n_flag & NWRITEERR) { 2908 error = np->n_error; 2909 np->n_flag &= ~NWRITEERR; 2910 } 2911done: 2912 if (bvec != NULL && bvec != bvec_on_stack) 2913 free(bvec, M_TEMP); 2914 return (error); 2915} 2916 2917/* 2918 * NFS advisory byte-level locks. 2919 * Currently unsupported. 2920 */ 2921static int 2922nfs_advlock(ap) 2923 struct vop_advlock_args /* { 2924 struct vnode *a_vp; 2925 caddr_t a_id; 2926 int a_op; 2927 struct flock *a_fl; 2928 int a_flags; 2929 } */ *ap; 2930{ 2931 register struct nfsnode *np = VTONFS(ap->a_vp); 2932 2933 /* 2934 * The following kludge is to allow diskless support to work 2935 * until a real NFS lockd is implemented. Basically, just pretend 2936 * that this is a local lock. 2937 */ 2938 return (lf_advlock(ap, &(np->n_lockf), np->n_size)); 2939} 2940 2941/* 2942 * Print out the contents of an nfsnode. 2943 */ 2944static int 2945nfs_print(ap) 2946 struct vop_print_args /* { 2947 struct vnode *a_vp; 2948 } */ *ap; 2949{ 2950 register struct vnode *vp = ap->a_vp; 2951 register struct nfsnode *np = VTONFS(vp); 2952 2953 printf("tag VT_NFS, fileid %ld fsid 0x%lx", 2954 np->n_vattr.va_fileid, np->n_vattr.va_fsid); 2955 if (vp->v_type == VFIFO) 2956 fifo_printinfo(vp); 2957 printf("\n"); 2958 return (0); 2959} 2960 2961/* 2962 * Just call nfs_writebp() with the force argument set to 1. 2963 */ 2964static int 2965nfs_bwrite(ap) 2966 struct vop_bwrite_args /* { 2967 struct vnode *a_bp; 2968 } */ *ap; 2969{ 2970 2971 return (nfs_writebp(ap->a_bp, 1)); 2972} 2973 2974/* 2975 * This is a clone of vn_bwrite(), except that B_WRITEINPROG isn't set unless 2976 * the force flag is one and it also handles the B_NEEDCOMMIT flag. 2977 */ 2978int 2979nfs_writebp(bp, force) 2980 register struct buf *bp; 2981 int force; 2982{ 2983 int s; 2984 register int oldflags = bp->b_flags, retv = 1; 2985 off_t off; 2986 2987 if(!(bp->b_flags & B_BUSY)) 2988 panic("bwrite: buffer is not busy???"); 2989 2990 if (bp->b_flags & B_INVAL) 2991 bp->b_flags |= B_INVAL | B_NOCACHE; 2992 2993 if (bp->b_flags & B_DELWRI) { 2994 --numdirtybuffers; 2995 if (needsbuffer) 2996 vfs_bio_need_satisfy(); 2997 } 2998 s = splbio(); /* XXX check if needed */ 2999 bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI); 3000 3001 if ((oldflags & (B_ASYNC|B_DELWRI)) == (B_ASYNC|B_DELWRI)) { 3002 reassignbuf(bp, bp->b_vp); 3003 } 3004 3005 bp->b_vp->v_numoutput++; 3006 curproc->p_stats->p_ru.ru_oublock++; 3007 splx(s); 3008 3009 /* 3010 * If B_NEEDCOMMIT is set, a commit rpc may do the trick. If not 3011 * an actual write will have to be scheduled via. VOP_STRATEGY(). 3012 * If B_WRITEINPROG is already set, then push it with a write anyhow. 3013 */ 3014 vfs_busy_pages(bp, 1); 3015 if ((oldflags & (B_NEEDCOMMIT | B_WRITEINPROG)) == B_NEEDCOMMIT) { 3016 off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + bp->b_dirtyoff; 3017 bp->b_flags |= B_WRITEINPROG; 3018 retv = nfs_commit(bp->b_vp, off, bp->b_dirtyend-bp->b_dirtyoff, 3019 bp->b_wcred, bp->b_proc); 3020 bp->b_flags &= ~B_WRITEINPROG; 3021 if (!retv) { 3022 bp->b_dirtyoff = bp->b_dirtyend = 0; 3023 bp->b_flags &= ~B_NEEDCOMMIT; 3024 biodone(bp); 3025 } else if (retv == NFSERR_STALEWRITEVERF) 3026 nfs_clearcommit(bp->b_vp->v_mount); 3027 } 3028 if (retv) { 3029 if (force) 3030 bp->b_flags |= B_WRITEINPROG; 3031 VOP_STRATEGY(bp); 3032 } 3033 3034 if( (oldflags & B_ASYNC) == 0) { 3035 int rtval = biowait(bp); 3036 3037 if (oldflags & B_DELWRI) { 3038 s = splbio(); 3039 reassignbuf(bp, bp->b_vp); 3040 splx(s); 3041 } 3042 3043 brelse(bp); 3044 return (rtval); 3045 } 3046 3047 return (0); 3048} 3049 3050/* 3051 * nfs special file access vnode op. 3052 * Essentially just get vattr and then imitate iaccess() since the device is 3053 * local to the client. 3054 */ 3055static int 3056nfsspec_access(ap) 3057 struct vop_access_args /* { 3058 struct vnode *a_vp; 3059 int a_mode; 3060 struct ucred *a_cred; 3061 struct proc *a_p; 3062 } */ *ap; 3063{ 3064 register struct vattr *vap; 3065 register gid_t *gp; 3066 register struct ucred *cred = ap->a_cred; 3067 struct vnode *vp = ap->a_vp; 3068 mode_t mode = ap->a_mode; 3069 struct vattr vattr; 3070 register int i; 3071 int error; 3072 3073 /* 3074 * Disallow write attempts on filesystems mounted read-only; 3075 * unless the file is a socket, fifo, or a block or character 3076 * device resident on the filesystem. 3077 */ 3078 if ((mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) { 3079 switch (vp->v_type) { 3080 case VREG: 3081 case VDIR: 3082 case VLNK: 3083 return (EROFS); 3084 default: 3085 break; 3086 } 3087 } 3088 /* 3089 * If you're the super-user, 3090 * you always get access. 3091 */ 3092 if (cred->cr_uid == 0) 3093 return (0); 3094 vap = &vattr; 3095 error = VOP_GETATTR(vp, vap, cred, ap->a_p); 3096 if (error) 3097 return (error); 3098 /* 3099 * Access check is based on only one of owner, group, public. 3100 * If not owner, then check group. If not a member of the 3101 * group, then check public access. 3102 */ 3103 if (cred->cr_uid != vap->va_uid) { 3104 mode >>= 3; 3105 gp = cred->cr_groups; 3106 for (i = 0; i < cred->cr_ngroups; i++, gp++) 3107 if (vap->va_gid == *gp) 3108 goto found; 3109 mode >>= 3; 3110found: 3111 ; 3112 } 3113 error = (vap->va_mode & mode) == mode ? 0 : EACCES; 3114 return (error); 3115} 3116 3117/* 3118 * Read wrapper for special devices. 3119 */ 3120static int 3121nfsspec_read(ap) 3122 struct vop_read_args /* { 3123 struct vnode *a_vp; 3124 struct uio *a_uio; 3125 int a_ioflag; 3126 struct ucred *a_cred; 3127 } */ *ap; 3128{ 3129 register struct nfsnode *np = VTONFS(ap->a_vp); 3130 3131 /* 3132 * Set access flag. 3133 */ 3134 np->n_flag |= NACC; 3135 getnanotime(&np->n_atim); 3136 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap)); 3137} 3138 3139/* 3140 * Write wrapper for special devices. 3141 */ 3142static int 3143nfsspec_write(ap) 3144 struct vop_write_args /* { 3145 struct vnode *a_vp; 3146 struct uio *a_uio; 3147 int a_ioflag; 3148 struct ucred *a_cred; 3149 } */ *ap; 3150{ 3151 register struct nfsnode *np = VTONFS(ap->a_vp); 3152 3153 /* 3154 * Set update flag. 3155 */ 3156 np->n_flag |= NUPD; 3157 getnanotime(&np->n_mtim); 3158 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap)); 3159} 3160 3161/* 3162 * Close wrapper for special devices. 3163 * 3164 * Update the times on the nfsnode then do device close. 3165 */ 3166static int 3167nfsspec_close(ap) 3168 struct vop_close_args /* { 3169 struct vnode *a_vp; 3170 int a_fflag; 3171 struct ucred *a_cred; 3172 struct proc *a_p; 3173 } */ *ap; 3174{ 3175 register struct vnode *vp = ap->a_vp; 3176 register struct nfsnode *np = VTONFS(vp); 3177 struct vattr vattr; 3178 3179 if (np->n_flag & (NACC | NUPD)) { 3180 np->n_flag |= NCHG; 3181 if (vp->v_usecount == 1 && 3182 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 3183 VATTR_NULL(&vattr); 3184 if (np->n_flag & NACC) 3185 vattr.va_atime = np->n_atim; 3186 if (np->n_flag & NUPD) 3187 vattr.va_mtime = np->n_mtim; 3188 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p); 3189 } 3190 } 3191 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap)); 3192} 3193 3194/* 3195 * Read wrapper for fifos. 3196 */ 3197static int 3198nfsfifo_read(ap) 3199 struct vop_read_args /* { 3200 struct vnode *a_vp; 3201 struct uio *a_uio; 3202 int a_ioflag; 3203 struct ucred *a_cred; 3204 } */ *ap; 3205{ 3206 register struct nfsnode *np = VTONFS(ap->a_vp); 3207 3208 /* 3209 * Set access flag. 3210 */ 3211 np->n_flag |= NACC; 3212 getnanotime(&np->n_atim); 3213 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap)); 3214} 3215 3216/* 3217 * Write wrapper for fifos. 3218 */ 3219static int 3220nfsfifo_write(ap) 3221 struct vop_write_args /* { 3222 struct vnode *a_vp; 3223 struct uio *a_uio; 3224 int a_ioflag; 3225 struct ucred *a_cred; 3226 } */ *ap; 3227{ 3228 register struct nfsnode *np = VTONFS(ap->a_vp); 3229 3230 /* 3231 * Set update flag. 3232 */ 3233 np->n_flag |= NUPD; 3234 getnanotime(&np->n_mtim); 3235 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap)); 3236} 3237 3238/* 3239 * Close wrapper for fifos. 3240 * 3241 * Update the times on the nfsnode then do fifo close. 3242 */ 3243static int 3244nfsfifo_close(ap) 3245 struct vop_close_args /* { 3246 struct vnode *a_vp; 3247 int a_fflag; 3248 struct ucred *a_cred; 3249 struct proc *a_p; 3250 } */ *ap; 3251{ 3252 register struct vnode *vp = ap->a_vp; 3253 register struct nfsnode *np = VTONFS(vp); 3254 struct vattr vattr; 3255 struct timespec ts; 3256 3257 if (np->n_flag & (NACC | NUPD)) { 3258 getnanotime(&ts); 3259 if (np->n_flag & NACC) 3260 np->n_atim = ts; 3261 if (np->n_flag & NUPD) 3262 np->n_mtim = ts; 3263 np->n_flag |= NCHG; 3264 if (vp->v_usecount == 1 && 3265 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 3266 VATTR_NULL(&vattr); 3267 if (np->n_flag & NACC) 3268 vattr.va_atime = np->n_atim; 3269 if (np->n_flag & NUPD) 3270 vattr.va_mtime = np->n_mtim; 3271 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p); 3272 } 3273 } 3274 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap)); 3275}
| 2454 int len; 2455 struct ucred *cred; 2456 struct proc *procp; 2457 struct nfsnode **npp; 2458{ 2459 register u_long *tl; 2460 register caddr_t cp; 2461 register long t1, t2; 2462 struct vnode *newvp = (struct vnode *)0; 2463 struct nfsnode *np, *dnp = VTONFS(dvp); 2464 caddr_t bpos, dpos, cp2; 2465 int error = 0, fhlen, attrflag; 2466 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 2467 nfsfh_t *nfhp; 2468 int v3 = NFS_ISV3(dvp); 2469 2470 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 2471 nfsm_reqhead(dvp, NFSPROC_LOOKUP, 2472 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len)); 2473 nfsm_fhtom(dvp, v3); 2474 nfsm_strtom(name, len, NFS_MAXNAMLEN); 2475 nfsm_request(dvp, NFSPROC_LOOKUP, procp, cred); 2476 if (npp && !error) { 2477 nfsm_getfh(nfhp, fhlen, v3); 2478 if (*npp) { 2479 np = *npp; 2480 if (np->n_fhsize > NFS_SMALLFH && fhlen <= NFS_SMALLFH) { 2481 free((caddr_t)np->n_fhp, M_NFSBIGFH); 2482 np->n_fhp = &np->n_fh; 2483 } else if (np->n_fhsize <= NFS_SMALLFH && fhlen>NFS_SMALLFH) 2484 np->n_fhp =(nfsfh_t *)malloc(fhlen,M_NFSBIGFH,M_WAITOK); 2485 bcopy((caddr_t)nfhp, (caddr_t)np->n_fhp, fhlen); 2486 np->n_fhsize = fhlen; 2487 newvp = NFSTOV(np); 2488 } else if (NFS_CMPFH(dnp, nfhp, fhlen)) { 2489 VREF(dvp); 2490 newvp = dvp; 2491 } else { 2492 error = nfs_nget(dvp->v_mount, nfhp, fhlen, &np); 2493 if (error) { 2494 m_freem(mrep); 2495 return (error); 2496 } 2497 newvp = NFSTOV(np); 2498 } 2499 if (v3) { 2500 nfsm_postop_attr(newvp, attrflag); 2501 if (!attrflag && *npp == NULL) { 2502 m_freem(mrep); 2503 if (newvp == dvp) 2504 vrele(newvp); 2505 else 2506 vput(newvp); 2507 return (ENOENT); 2508 } 2509 } else 2510 nfsm_loadattr(newvp, (struct vattr *)0); 2511 } 2512 nfsm_reqdone; 2513 if (npp && *npp == NULL) { 2514 if (error) { 2515 if (newvp) 2516 if (newvp == dvp) 2517 vrele(newvp); 2518 else 2519 vput(newvp); 2520 } else 2521 *npp = np; 2522 } 2523 return (error); 2524} 2525 2526/* 2527 * Nfs Version 3 commit rpc 2528 */ 2529static int 2530nfs_commit(vp, offset, cnt, cred, procp) 2531 register struct vnode *vp; 2532 u_quad_t offset; 2533 int cnt; 2534 struct ucred *cred; 2535 struct proc *procp; 2536{ 2537 register caddr_t cp; 2538 register u_long *tl; 2539 register int t1, t2; 2540 register struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2541 caddr_t bpos, dpos, cp2; 2542 int error = 0, wccflag = NFSV3_WCCRATTR; 2543 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 2544 2545 if ((nmp->nm_state & NFSSTA_HASWRITEVERF) == 0) 2546 return (0); 2547 nfsstats.rpccnt[NFSPROC_COMMIT]++; 2548 nfsm_reqhead(vp, NFSPROC_COMMIT, NFSX_FH(1)); 2549 nfsm_fhtom(vp, 1); 2550 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED); 2551 txdr_hyper(&offset, tl); 2552 tl += 2; 2553 *tl = txdr_unsigned(cnt); 2554 nfsm_request(vp, NFSPROC_COMMIT, procp, cred); 2555 nfsm_wcc_data(vp, wccflag); 2556 if (!error) { 2557 nfsm_dissect(tl, u_long *, NFSX_V3WRITEVERF); 2558 if (bcmp((caddr_t)nmp->nm_verf, (caddr_t)tl, 2559 NFSX_V3WRITEVERF)) { 2560 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf, 2561 NFSX_V3WRITEVERF); 2562 error = NFSERR_STALEWRITEVERF; 2563 } 2564 } 2565 nfsm_reqdone; 2566 return (error); 2567} 2568 2569/* 2570 * Kludge City.. 2571 * - make nfs_bmap() essentially a no-op that does no translation 2572 * - do nfs_strategy() by doing I/O with nfs_readrpc/nfs_writerpc 2573 * (Maybe I could use the process's page mapping, but I was concerned that 2574 * Kernel Write might not be enabled and also figured copyout() would do 2575 * a lot more work than bcopy() and also it currently happens in the 2576 * context of the swapper process (2). 2577 */ 2578static int 2579nfs_bmap(ap) 2580 struct vop_bmap_args /* { 2581 struct vnode *a_vp; 2582 daddr_t a_bn; 2583 struct vnode **a_vpp; 2584 daddr_t *a_bnp; 2585 int *a_runp; 2586 int *a_runb; 2587 } */ *ap; 2588{ 2589 register struct vnode *vp = ap->a_vp; 2590 2591 if (ap->a_vpp != NULL) 2592 *ap->a_vpp = vp; 2593 if (ap->a_bnp != NULL) 2594 *ap->a_bnp = ap->a_bn * btodb(vp->v_mount->mnt_stat.f_iosize); 2595 if (ap->a_runp != NULL) 2596 *ap->a_runp = 0; 2597 if (ap->a_runb != NULL) 2598 *ap->a_runb = 0; 2599 return (0); 2600} 2601 2602/* 2603 * Strategy routine. 2604 * For async requests when nfsiod(s) are running, queue the request by 2605 * calling nfs_asyncio(), otherwise just all nfs_doio() to do the 2606 * request. 2607 */ 2608static int 2609nfs_strategy(ap) 2610 struct vop_strategy_args *ap; 2611{ 2612 register struct buf *bp = ap->a_bp; 2613 struct ucred *cr; 2614 struct proc *p; 2615 int error = 0; 2616 2617 if (bp->b_flags & B_PHYS) 2618 panic("nfs physio"); 2619 if (bp->b_flags & B_ASYNC) 2620 p = (struct proc *)0; 2621 else 2622 p = curproc; /* XXX */ 2623 if (bp->b_flags & B_READ) 2624 cr = bp->b_rcred; 2625 else 2626 cr = bp->b_wcred; 2627 /* 2628 * If the op is asynchronous and an i/o daemon is waiting 2629 * queue the request, wake it up and wait for completion 2630 * otherwise just do it ourselves. 2631 */ 2632 if ((bp->b_flags & B_ASYNC) == 0 || 2633 nfs_asyncio(bp, NOCRED)) 2634 error = nfs_doio(bp, cr, p); 2635 return (error); 2636} 2637 2638/* 2639 * Mmap a file 2640 * 2641 * NB Currently unsupported. 2642 */ 2643/* ARGSUSED */ 2644static int 2645nfs_mmap(ap) 2646 struct vop_mmap_args /* { 2647 struct vnode *a_vp; 2648 int a_fflags; 2649 struct ucred *a_cred; 2650 struct proc *a_p; 2651 } */ *ap; 2652{ 2653 2654 return (EINVAL); 2655} 2656 2657/* 2658 * fsync vnode op. Just call nfs_flush() with commit == 1. 2659 */ 2660/* ARGSUSED */ 2661static int 2662nfs_fsync(ap) 2663 struct vop_fsync_args /* { 2664 struct vnodeop_desc *a_desc; 2665 struct vnode * a_vp; 2666 struct ucred * a_cred; 2667 int a_waitfor; 2668 struct proc * a_p; 2669 } */ *ap; 2670{ 2671 2672 return (nfs_flush(ap->a_vp, ap->a_cred, ap->a_waitfor, ap->a_p, 1)); 2673} 2674 2675/* 2676 * Flush all the blocks associated with a vnode. 2677 * Walk through the buffer pool and push any dirty pages 2678 * associated with the vnode. 2679 */ 2680static int 2681nfs_flush(vp, cred, waitfor, p, commit) 2682 register struct vnode *vp; 2683 struct ucred *cred; 2684 int waitfor; 2685 struct proc *p; 2686 int commit; 2687{ 2688 register struct nfsnode *np = VTONFS(vp); 2689 register struct buf *bp; 2690 register int i; 2691 struct buf *nbp; 2692 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2693 int s, error = 0, slptimeo = 0, slpflag = 0, retv, bvecpos; 2694 int passone = 1; 2695 u_quad_t off, endoff, toff; 2696 struct ucred* wcred = NULL; 2697 struct buf **bvec = NULL; 2698#ifndef NFS_COMMITBVECSIZ 2699#define NFS_COMMITBVECSIZ 20 2700#endif 2701 struct buf *bvec_on_stack[NFS_COMMITBVECSIZ]; 2702 int bvecsize = 0, bveccount; 2703 2704 if (nmp->nm_flag & NFSMNT_INT) 2705 slpflag = PCATCH; 2706 if (!commit) 2707 passone = 0; 2708 /* 2709 * A b_flags == (B_DELWRI | B_NEEDCOMMIT) block has been written to the 2710 * server, but nas not been committed to stable storage on the server 2711 * yet. On the first pass, the byte range is worked out and the commit 2712 * rpc is done. On the second pass, nfs_writebp() is called to do the 2713 * job. 2714 */ 2715again: 2716 off = (u_quad_t)-1; 2717 endoff = 0; 2718 bvecpos = 0; 2719 if (NFS_ISV3(vp) && commit) { 2720 s = splbio(); 2721 /* 2722 * Count up how many buffers waiting for a commit. 2723 */ 2724 bveccount = 0; 2725 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { 2726 nbp = bp->b_vnbufs.le_next; 2727 if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT)) 2728 == (B_DELWRI | B_NEEDCOMMIT)) 2729 bveccount++; 2730 } 2731 /* 2732 * Allocate space to remember the list of bufs to commit. It is 2733 * important to use M_NOWAIT here to avoid a race with nfs_write. 2734 * If we can't get memory (for whatever reason), we will end up 2735 * committing the buffers one-by-one in the loop below. 2736 */ 2737 if (bveccount > NFS_COMMITBVECSIZ) { 2738 if (bvec != NULL && bvec != bvec_on_stack) 2739 free(bvec, M_TEMP); 2740 bvec = (struct buf **) 2741 malloc(bveccount * sizeof(struct buf *), 2742 M_TEMP, M_NOWAIT); 2743 if (bvec == NULL) { 2744 bvec = bvec_on_stack; 2745 bvecsize = NFS_COMMITBVECSIZ; 2746 } else 2747 bvecsize = bveccount; 2748 } else { 2749 bvec = bvec_on_stack; 2750 bvecsize = NFS_COMMITBVECSIZ; 2751 } 2752 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { 2753 nbp = bp->b_vnbufs.le_next; 2754 if (bvecpos >= bvecsize) 2755 break; 2756 if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT)) 2757 != (B_DELWRI | B_NEEDCOMMIT)) 2758 continue; 2759 bremfree(bp); 2760 /* 2761 * Work out if all buffers are using the same cred 2762 * so we can deal with them all with one commit. 2763 */ 2764 if (wcred == NULL) 2765 wcred = bp->b_wcred; 2766 else if (wcred != bp->b_wcred) 2767 wcred = NOCRED; 2768 bp->b_flags |= (B_BUSY | B_WRITEINPROG); 2769 vfs_busy_pages(bp, 1); 2770 /* 2771 * A list of these buffers is kept so that the 2772 * second loop knows which buffers have actually 2773 * been committed. This is necessary, since there 2774 * may be a race between the commit rpc and new 2775 * uncommitted writes on the file. 2776 */ 2777 bvec[bvecpos++] = bp; 2778 toff = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + 2779 bp->b_dirtyoff; 2780 if (toff < off) 2781 off = toff; 2782 toff += (u_quad_t)(bp->b_dirtyend - bp->b_dirtyoff); 2783 if (toff > endoff) 2784 endoff = toff; 2785 } 2786 splx(s); 2787 } 2788 if (bvecpos > 0) { 2789 /* 2790 * Commit data on the server, as required. 2791 * If all bufs are using the same wcred, then use that with 2792 * one call for all of them, otherwise commit each one 2793 * separately. 2794 */ 2795 if (wcred != NOCRED) 2796 retv = nfs_commit(vp, off, (int)(endoff - off), 2797 wcred, p); 2798 else { 2799 retv = 0; 2800 for (i = 0; i < bvecpos; i++) { 2801 off_t off, size; 2802 bp = bvec[i]; 2803 off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + 2804 bp->b_dirtyoff; 2805 size = (u_quad_t)(bp->b_dirtyend 2806 - bp->b_dirtyoff); 2807 retv = nfs_commit(vp, off, (int)size, 2808 bp->b_wcred, p); 2809 if (retv) break; 2810 } 2811 } 2812 2813 if (retv == NFSERR_STALEWRITEVERF) 2814 nfs_clearcommit(vp->v_mount); 2815 /* 2816 * Now, either mark the blocks I/O done or mark the 2817 * blocks dirty, depending on whether the commit 2818 * succeeded. 2819 */ 2820 for (i = 0; i < bvecpos; i++) { 2821 bp = bvec[i]; 2822 bp->b_flags &= ~(B_NEEDCOMMIT | B_WRITEINPROG); 2823 if (retv) { 2824 vfs_unbusy_pages(bp); 2825 brelse(bp); 2826 } else { 2827 vp->v_numoutput++; 2828 bp->b_flags |= B_ASYNC; 2829 if (bp->b_flags & B_DELWRI) { 2830 --numdirtybuffers; 2831 if (needsbuffer) { 2832 vfs_bio_need_satisfy(); 2833 } 2834 } 2835 s = splbio(); /* XXX check this positionning */ 2836 bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI); 2837 bp->b_dirtyoff = bp->b_dirtyend = 0; 2838 reassignbuf(bp, vp); 2839 splx(s); 2840 biodone(bp); 2841 } 2842 } 2843 } 2844 2845 /* 2846 * Start/do any write(s) that are required. 2847 */ 2848loop: 2849 s = splbio(); 2850 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { 2851 nbp = bp->b_vnbufs.le_next; 2852 if (bp->b_flags & B_BUSY) { 2853 if (waitfor != MNT_WAIT || passone) 2854 continue; 2855 bp->b_flags |= B_WANTED; 2856 error = tsleep((caddr_t)bp, slpflag | (PRIBIO + 1), 2857 "nfsfsync", slptimeo); 2858 splx(s); 2859 if (error) { 2860 if (nfs_sigintr(nmp, (struct nfsreq *)0, p)) { 2861 error = EINTR; 2862 goto done; 2863 } 2864 if (slpflag == PCATCH) { 2865 slpflag = 0; 2866 slptimeo = 2 * hz; 2867 } 2868 } 2869 goto loop; 2870 } 2871 if ((bp->b_flags & B_DELWRI) == 0) 2872 panic("nfs_fsync: not dirty"); 2873 if ((passone || !commit) && (bp->b_flags & B_NEEDCOMMIT)) 2874 continue; 2875 bremfree(bp); 2876 if (passone || !commit) 2877 bp->b_flags |= (B_BUSY|B_ASYNC); 2878 else 2879 bp->b_flags |= (B_BUSY|B_ASYNC|B_WRITEINPROG|B_NEEDCOMMIT); 2880 splx(s); 2881 VOP_BWRITE(bp); 2882 goto loop; 2883 } 2884 splx(s); 2885 if (passone) { 2886 passone = 0; 2887 goto again; 2888 } 2889 if (waitfor == MNT_WAIT) { 2890 while (vp->v_numoutput) { 2891 vp->v_flag |= VBWAIT; 2892 error = tsleep((caddr_t)&vp->v_numoutput, 2893 slpflag | (PRIBIO + 1), "nfsfsync", slptimeo); 2894 if (error) { 2895 if (nfs_sigintr(nmp, (struct nfsreq *)0, p)) { 2896 error = EINTR; 2897 goto done; 2898 } 2899 if (slpflag == PCATCH) { 2900 slpflag = 0; 2901 slptimeo = 2 * hz; 2902 } 2903 } 2904 } 2905 if (vp->v_dirtyblkhd.lh_first && commit) { 2906 goto loop; 2907 } 2908 } 2909 if (np->n_flag & NWRITEERR) { 2910 error = np->n_error; 2911 np->n_flag &= ~NWRITEERR; 2912 } 2913done: 2914 if (bvec != NULL && bvec != bvec_on_stack) 2915 free(bvec, M_TEMP); 2916 return (error); 2917} 2918 2919/* 2920 * NFS advisory byte-level locks. 2921 * Currently unsupported. 2922 */ 2923static int 2924nfs_advlock(ap) 2925 struct vop_advlock_args /* { 2926 struct vnode *a_vp; 2927 caddr_t a_id; 2928 int a_op; 2929 struct flock *a_fl; 2930 int a_flags; 2931 } */ *ap; 2932{ 2933 register struct nfsnode *np = VTONFS(ap->a_vp); 2934 2935 /* 2936 * The following kludge is to allow diskless support to work 2937 * until a real NFS lockd is implemented. Basically, just pretend 2938 * that this is a local lock. 2939 */ 2940 return (lf_advlock(ap, &(np->n_lockf), np->n_size)); 2941} 2942 2943/* 2944 * Print out the contents of an nfsnode. 2945 */ 2946static int 2947nfs_print(ap) 2948 struct vop_print_args /* { 2949 struct vnode *a_vp; 2950 } */ *ap; 2951{ 2952 register struct vnode *vp = ap->a_vp; 2953 register struct nfsnode *np = VTONFS(vp); 2954 2955 printf("tag VT_NFS, fileid %ld fsid 0x%lx", 2956 np->n_vattr.va_fileid, np->n_vattr.va_fsid); 2957 if (vp->v_type == VFIFO) 2958 fifo_printinfo(vp); 2959 printf("\n"); 2960 return (0); 2961} 2962 2963/* 2964 * Just call nfs_writebp() with the force argument set to 1. 2965 */ 2966static int 2967nfs_bwrite(ap) 2968 struct vop_bwrite_args /* { 2969 struct vnode *a_bp; 2970 } */ *ap; 2971{ 2972 2973 return (nfs_writebp(ap->a_bp, 1)); 2974} 2975 2976/* 2977 * This is a clone of vn_bwrite(), except that B_WRITEINPROG isn't set unless 2978 * the force flag is one and it also handles the B_NEEDCOMMIT flag. 2979 */ 2980int 2981nfs_writebp(bp, force) 2982 register struct buf *bp; 2983 int force; 2984{ 2985 int s; 2986 register int oldflags = bp->b_flags, retv = 1; 2987 off_t off; 2988 2989 if(!(bp->b_flags & B_BUSY)) 2990 panic("bwrite: buffer is not busy???"); 2991 2992 if (bp->b_flags & B_INVAL) 2993 bp->b_flags |= B_INVAL | B_NOCACHE; 2994 2995 if (bp->b_flags & B_DELWRI) { 2996 --numdirtybuffers; 2997 if (needsbuffer) 2998 vfs_bio_need_satisfy(); 2999 } 3000 s = splbio(); /* XXX check if needed */ 3001 bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI); 3002 3003 if ((oldflags & (B_ASYNC|B_DELWRI)) == (B_ASYNC|B_DELWRI)) { 3004 reassignbuf(bp, bp->b_vp); 3005 } 3006 3007 bp->b_vp->v_numoutput++; 3008 curproc->p_stats->p_ru.ru_oublock++; 3009 splx(s); 3010 3011 /* 3012 * If B_NEEDCOMMIT is set, a commit rpc may do the trick. If not 3013 * an actual write will have to be scheduled via. VOP_STRATEGY(). 3014 * If B_WRITEINPROG is already set, then push it with a write anyhow. 3015 */ 3016 vfs_busy_pages(bp, 1); 3017 if ((oldflags & (B_NEEDCOMMIT | B_WRITEINPROG)) == B_NEEDCOMMIT) { 3018 off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + bp->b_dirtyoff; 3019 bp->b_flags |= B_WRITEINPROG; 3020 retv = nfs_commit(bp->b_vp, off, bp->b_dirtyend-bp->b_dirtyoff, 3021 bp->b_wcred, bp->b_proc); 3022 bp->b_flags &= ~B_WRITEINPROG; 3023 if (!retv) { 3024 bp->b_dirtyoff = bp->b_dirtyend = 0; 3025 bp->b_flags &= ~B_NEEDCOMMIT; 3026 biodone(bp); 3027 } else if (retv == NFSERR_STALEWRITEVERF) 3028 nfs_clearcommit(bp->b_vp->v_mount); 3029 } 3030 if (retv) { 3031 if (force) 3032 bp->b_flags |= B_WRITEINPROG; 3033 VOP_STRATEGY(bp); 3034 } 3035 3036 if( (oldflags & B_ASYNC) == 0) { 3037 int rtval = biowait(bp); 3038 3039 if (oldflags & B_DELWRI) { 3040 s = splbio(); 3041 reassignbuf(bp, bp->b_vp); 3042 splx(s); 3043 } 3044 3045 brelse(bp); 3046 return (rtval); 3047 } 3048 3049 return (0); 3050} 3051 3052/* 3053 * nfs special file access vnode op. 3054 * Essentially just get vattr and then imitate iaccess() since the device is 3055 * local to the client. 3056 */ 3057static int 3058nfsspec_access(ap) 3059 struct vop_access_args /* { 3060 struct vnode *a_vp; 3061 int a_mode; 3062 struct ucred *a_cred; 3063 struct proc *a_p; 3064 } */ *ap; 3065{ 3066 register struct vattr *vap; 3067 register gid_t *gp; 3068 register struct ucred *cred = ap->a_cred; 3069 struct vnode *vp = ap->a_vp; 3070 mode_t mode = ap->a_mode; 3071 struct vattr vattr; 3072 register int i; 3073 int error; 3074 3075 /* 3076 * Disallow write attempts on filesystems mounted read-only; 3077 * unless the file is a socket, fifo, or a block or character 3078 * device resident on the filesystem. 3079 */ 3080 if ((mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) { 3081 switch (vp->v_type) { 3082 case VREG: 3083 case VDIR: 3084 case VLNK: 3085 return (EROFS); 3086 default: 3087 break; 3088 } 3089 } 3090 /* 3091 * If you're the super-user, 3092 * you always get access. 3093 */ 3094 if (cred->cr_uid == 0) 3095 return (0); 3096 vap = &vattr; 3097 error = VOP_GETATTR(vp, vap, cred, ap->a_p); 3098 if (error) 3099 return (error); 3100 /* 3101 * Access check is based on only one of owner, group, public. 3102 * If not owner, then check group. If not a member of the 3103 * group, then check public access. 3104 */ 3105 if (cred->cr_uid != vap->va_uid) { 3106 mode >>= 3; 3107 gp = cred->cr_groups; 3108 for (i = 0; i < cred->cr_ngroups; i++, gp++) 3109 if (vap->va_gid == *gp) 3110 goto found; 3111 mode >>= 3; 3112found: 3113 ; 3114 } 3115 error = (vap->va_mode & mode) == mode ? 0 : EACCES; 3116 return (error); 3117} 3118 3119/* 3120 * Read wrapper for special devices. 3121 */ 3122static int 3123nfsspec_read(ap) 3124 struct vop_read_args /* { 3125 struct vnode *a_vp; 3126 struct uio *a_uio; 3127 int a_ioflag; 3128 struct ucred *a_cred; 3129 } */ *ap; 3130{ 3131 register struct nfsnode *np = VTONFS(ap->a_vp); 3132 3133 /* 3134 * Set access flag. 3135 */ 3136 np->n_flag |= NACC; 3137 getnanotime(&np->n_atim); 3138 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap)); 3139} 3140 3141/* 3142 * Write wrapper for special devices. 3143 */ 3144static int 3145nfsspec_write(ap) 3146 struct vop_write_args /* { 3147 struct vnode *a_vp; 3148 struct uio *a_uio; 3149 int a_ioflag; 3150 struct ucred *a_cred; 3151 } */ *ap; 3152{ 3153 register struct nfsnode *np = VTONFS(ap->a_vp); 3154 3155 /* 3156 * Set update flag. 3157 */ 3158 np->n_flag |= NUPD; 3159 getnanotime(&np->n_mtim); 3160 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap)); 3161} 3162 3163/* 3164 * Close wrapper for special devices. 3165 * 3166 * Update the times on the nfsnode then do device close. 3167 */ 3168static int 3169nfsspec_close(ap) 3170 struct vop_close_args /* { 3171 struct vnode *a_vp; 3172 int a_fflag; 3173 struct ucred *a_cred; 3174 struct proc *a_p; 3175 } */ *ap; 3176{ 3177 register struct vnode *vp = ap->a_vp; 3178 register struct nfsnode *np = VTONFS(vp); 3179 struct vattr vattr; 3180 3181 if (np->n_flag & (NACC | NUPD)) { 3182 np->n_flag |= NCHG; 3183 if (vp->v_usecount == 1 && 3184 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 3185 VATTR_NULL(&vattr); 3186 if (np->n_flag & NACC) 3187 vattr.va_atime = np->n_atim; 3188 if (np->n_flag & NUPD) 3189 vattr.va_mtime = np->n_mtim; 3190 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p); 3191 } 3192 } 3193 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap)); 3194} 3195 3196/* 3197 * Read wrapper for fifos. 3198 */ 3199static int 3200nfsfifo_read(ap) 3201 struct vop_read_args /* { 3202 struct vnode *a_vp; 3203 struct uio *a_uio; 3204 int a_ioflag; 3205 struct ucred *a_cred; 3206 } */ *ap; 3207{ 3208 register struct nfsnode *np = VTONFS(ap->a_vp); 3209 3210 /* 3211 * Set access flag. 3212 */ 3213 np->n_flag |= NACC; 3214 getnanotime(&np->n_atim); 3215 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap)); 3216} 3217 3218/* 3219 * Write wrapper for fifos. 3220 */ 3221static int 3222nfsfifo_write(ap) 3223 struct vop_write_args /* { 3224 struct vnode *a_vp; 3225 struct uio *a_uio; 3226 int a_ioflag; 3227 struct ucred *a_cred; 3228 } */ *ap; 3229{ 3230 register struct nfsnode *np = VTONFS(ap->a_vp); 3231 3232 /* 3233 * Set update flag. 3234 */ 3235 np->n_flag |= NUPD; 3236 getnanotime(&np->n_mtim); 3237 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap)); 3238} 3239 3240/* 3241 * Close wrapper for fifos. 3242 * 3243 * Update the times on the nfsnode then do fifo close. 3244 */ 3245static int 3246nfsfifo_close(ap) 3247 struct vop_close_args /* { 3248 struct vnode *a_vp; 3249 int a_fflag; 3250 struct ucred *a_cred; 3251 struct proc *a_p; 3252 } */ *ap; 3253{ 3254 register struct vnode *vp = ap->a_vp; 3255 register struct nfsnode *np = VTONFS(vp); 3256 struct vattr vattr; 3257 struct timespec ts; 3258 3259 if (np->n_flag & (NACC | NUPD)) { 3260 getnanotime(&ts); 3261 if (np->n_flag & NACC) 3262 np->n_atim = ts; 3263 if (np->n_flag & NUPD) 3264 np->n_mtim = ts; 3265 np->n_flag |= NCHG; 3266 if (vp->v_usecount == 1 && 3267 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 3268 VATTR_NULL(&vattr); 3269 if (np->n_flag & NACC) 3270 vattr.va_atime = np->n_atim; 3271 if (np->n_flag & NUPD) 3272 vattr.va_mtime = np->n_mtim; 3273 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p); 3274 } 3275 } 3276 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap)); 3277}
|