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