Make everything compile with -Wtraditional. Make it easier to distribute
[unix-history] / sys / nfs / nfs_vnops.c
CommitLineData
15637ed4
RG
1/*
2 * Copyright (c) 1989 The Regents of the University of California.
3 * 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 *
a8599e88 36 * From: @(#)nfs_vnops.c 7.60 (Berkeley) 5/24/91
fde1aeb2 37 * $Id: nfs_vnops.c,v 1.5 1993/11/25 01:36:55 wollman Exp $
15637ed4
RG
38 */
39
40/*
41 * vnode op calls for sun nfs version 2
42 */
43
44#include "param.h"
45#include "proc.h"
46#include "kernel.h"
47#include "systm.h"
48#include "mount.h"
49#include "buf.h"
50#include "malloc.h"
51#include "mbuf.h"
52#include "conf.h"
53#include "namei.h"
54#include "vnode.h"
55#include "specdev.h"
56#include "fifo.h"
57
58#include "../ufs/quota.h"
59#include "../ufs/inode.h"
60#include "../ufs/dir.h"
61
62#include "nfsv2.h"
63#include "nfs.h"
64#include "nfsnode.h"
65#include "nfsmount.h"
66#include "xdr_subs.h"
67#include "nfsm_subs.h"
68#include "nfsiom.h"
69
70/* Defs */
71#define TRUE 1
72#define FALSE 0
73
74/*
75 * Global vfs data structures for nfs
76 */
77struct vnodeops nfsv2_vnodeops = {
78 nfs_lookup, /* lookup */
79 nfs_create, /* create */
80 nfs_mknod, /* mknod */
81 nfs_open, /* open */
82 nfs_close, /* close */
83 nfs_access, /* access */
84 nfs_getattr, /* getattr */
85 nfs_setattr, /* setattr */
86 nfs_read, /* read */
87 nfs_write, /* write */
88 nfs_ioctl, /* ioctl */
89 nfs_select, /* select */
90 nfs_mmap, /* mmap */
91 nfs_fsync, /* fsync */
92 nfs_seek, /* seek */
93 nfs_remove, /* remove */
94 nfs_link, /* link */
95 nfs_rename, /* rename */
96 nfs_mkdir, /* mkdir */
97 nfs_rmdir, /* rmdir */
98 nfs_symlink, /* symlink */
99 nfs_readdir, /* readdir */
100 nfs_readlink, /* readlink */
101 nfs_abortop, /* abortop */
102 nfs_inactive, /* inactive */
103 nfs_reclaim, /* reclaim */
104 nfs_lock, /* lock */
105 nfs_unlock, /* unlock */
106 nfs_bmap, /* bmap */
107 nfs_strategy, /* strategy */
108 nfs_print, /* print */
109 nfs_islocked, /* islocked */
110 nfs_advlock, /* advlock */
111};
112
113/*
114 * Special device vnode ops
115 */
116struct vnodeops spec_nfsv2nodeops = {
117 spec_lookup, /* lookup */
118 spec_create, /* create */
119 spec_mknod, /* mknod */
120 spec_open, /* open */
121 spec_close, /* close */
122 nfs_access, /* access */
123 nfs_getattr, /* getattr */
124 nfs_setattr, /* setattr */
125 spec_read, /* read */
126 spec_write, /* write */
127 spec_ioctl, /* ioctl */
128 spec_select, /* select */
129 spec_mmap, /* mmap */
130 spec_fsync, /* fsync */
131 spec_seek, /* seek */
132 spec_remove, /* remove */
133 spec_link, /* link */
134 spec_rename, /* rename */
135 spec_mkdir, /* mkdir */
136 spec_rmdir, /* rmdir */
137 spec_symlink, /* symlink */
138 spec_readdir, /* readdir */
139 spec_readlink, /* readlink */
140 spec_abortop, /* abortop */
141 nfs_inactive, /* inactive */
142 nfs_reclaim, /* reclaim */
143 nfs_lock, /* lock */
144 nfs_unlock, /* unlock */
145 spec_bmap, /* bmap */
146 spec_strategy, /* strategy */
147 nfs_print, /* print */
148 nfs_islocked, /* islocked */
149 spec_advlock, /* advlock */
150};
151
152#ifdef FIFO
153struct vnodeops fifo_nfsv2nodeops = {
154 fifo_lookup, /* lookup */
155 fifo_create, /* create */
156 fifo_mknod, /* mknod */
157 fifo_open, /* open */
158 fifo_close, /* close */
159 nfs_access, /* access */
160 nfs_getattr, /* getattr */
161 nfs_setattr, /* setattr */
162 fifo_read, /* read */
163 fifo_write, /* write */
164 fifo_ioctl, /* ioctl */
165 fifo_select, /* select */
166 fifo_mmap, /* mmap */
167 fifo_fsync, /* fsync */
168 fifo_seek, /* seek */
169 fifo_remove, /* remove */
170 fifo_link, /* link */
171 fifo_rename, /* rename */
172 fifo_mkdir, /* mkdir */
173 fifo_rmdir, /* rmdir */
174 fifo_symlink, /* symlink */
175 fifo_readdir, /* readdir */
176 fifo_readlink, /* readlink */
177 fifo_abortop, /* abortop */
178 nfs_inactive, /* inactive */
179 nfs_reclaim, /* reclaim */
180 nfs_lock, /* lock */
181 nfs_unlock, /* unlock */
182 fifo_bmap, /* bmap */
183 fifo_badop, /* strategy */
184 nfs_print, /* print */
185 nfs_islocked, /* islocked */
186 fifo_advlock, /* advlock */
187};
188#endif /* FIFO */
189
190/*
191 * Global vars
192 */
193extern u_long nfs_procids[NFS_NPROCS];
194extern u_long nfs_prog, nfs_vers;
195extern char nfsiobuf[MAXPHYS+NBPG];
196struct buf nfs_bqueue; /* Queue head for nfsiod's */
197struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
198int nfs_numasync = 0;
199
200/*
201 * nfs null call from vfs.
202 */
a8599e88 203int
15637ed4
RG
204nfs_null(vp, cred, p)
205 struct vnode *vp;
206 struct ucred *cred;
207 struct proc *p;
208{
209 caddr_t bpos, dpos;
210 u_long xid;
211 int error = 0;
212 struct mbuf *mreq, *mrep, *md, *mb;
213
214 nfsm_reqhead(nfs_procids[NFSPROC_NULL], cred, 0);
215 nfsm_request(vp, NFSPROC_NULL, p, 0);
216 nfsm_reqdone;
217 return (error);
218}
219
220/*
221 * nfs access vnode op.
222 * Essentially just get vattr and then imitate iaccess()
223 */
a8599e88 224int
15637ed4
RG
225nfs_access(vp, mode, cred, p)
226 struct vnode *vp;
227 int mode;
228 register struct ucred *cred;
229 struct proc *p;
230{
231 register struct vattr *vap;
232 register gid_t *gp;
233 struct vattr vattr;
234 register int i;
235 int error;
236
237 /*
238 * If you're the super-user,
239 * you always get access.
240 */
241 if (cred->cr_uid == 0)
242 return (0);
243 vap = &vattr;
244 if (error = nfs_dogetattr(vp, vap, cred, 0, p))
245 return (error);
246 /*
247 * Access check is based on only one of owner, group, public.
248 * If not owner, then check group. If not a member of the
249 * group, then check public access.
250 */
251 if (cred->cr_uid != vap->va_uid) {
252 mode >>= 3;
253 gp = cred->cr_groups;
254 for (i = 0; i < cred->cr_ngroups; i++, gp++)
255 if (vap->va_gid == *gp)
256 goto found;
257 mode >>= 3;
258found:
259 ;
260 }
261 if ((vap->va_mode & mode) == mode)
262 return (0);
263 return (EACCES);
264}
265
266/*
267 * nfs open vnode op
268 * Just check to see if the type is ok
269 */
270/* ARGSUSED */
a8599e88 271int
15637ed4
RG
272nfs_open(vp, mode, cred, p)
273 struct vnode *vp;
274 int mode;
275 struct ucred *cred;
276 struct proc *p;
277{
278 register enum vtype vtyp;
279
280 vtyp = vp->v_type;
281 if (vtyp == VREG || vtyp == VDIR || vtyp == VLNK)
282 return (0);
283 else
284 return (EACCES);
285}
286
287/*
288 * nfs close vnode op
289 * For reg files, invalidate any buffer cache entries.
290 */
291/* ARGSUSED */
a8599e88 292int
15637ed4
RG
293nfs_close(vp, fflags, cred, p)
294 register struct vnode *vp;
295 int fflags;
296 struct ucred *cred;
297 struct proc *p;
298{
299 register struct nfsnode *np = VTONFS(vp);
300 int error = 0;
301
302 if (vp->v_type == VREG && (np->n_flag & NMODIFIED)) {
303 nfs_lock(vp);
304 np->n_flag &= ~NMODIFIED;
305 vinvalbuf(vp, TRUE);
306 np->n_attrstamp = 0;
307 if (np->n_flag & NWRITEERR) {
308 np->n_flag &= ~NWRITEERR;
309 error = np->n_error;
310 }
311 nfs_unlock(vp);
312 }
313 return (error);
314}
315
316/*
317 * nfs getattr call from vfs.
318 */
a8599e88 319int
15637ed4
RG
320nfs_getattr(vp, vap, cred, p)
321 register struct vnode *vp;
322 struct vattr *vap;
323 struct ucred *cred;
324 struct proc *p;
325{
326 return (nfs_dogetattr(vp, vap, cred, 0, p));
327}
328
a8599e88 329int
15637ed4
RG
330nfs_dogetattr(vp, vap, cred, tryhard, p)
331 register struct vnode *vp;
332 struct vattr *vap;
333 struct ucred *cred;
334 int tryhard;
335 struct proc *p;
336{
337 register caddr_t cp;
338 register long t1;
339 caddr_t bpos, dpos;
340 u_long xid;
341 int error = 0;
342 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
343
344 /* First look in the cache.. */
345 if (nfs_getattrcache(vp, vap) == 0)
346 return (0);
347 nfsstats.rpccnt[NFSPROC_GETATTR]++;
348 nfsm_reqhead(nfs_procids[NFSPROC_GETATTR], cred, NFSX_FH);
349 nfsm_fhtom(vp);
350 nfsm_request(vp, NFSPROC_GETATTR, p, tryhard);
351 nfsm_loadattr(vp, vap);
352 nfsm_reqdone;
353 return (error);
354}
355
356/*
357 * nfs setattr call.
358 */
a8599e88 359int
15637ed4
RG
360nfs_setattr(vp, vap, cred, p)
361 register struct vnode *vp;
362 register struct vattr *vap;
363 struct ucred *cred;
364 struct proc *p;
365{
366 register struct nfsv2_sattr *sp;
367 register caddr_t cp;
368 register long t1;
369 caddr_t bpos, dpos;
370 u_long xid;
371 int error = 0;
372 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
373 struct nfsnode *np;
374
375 nfsstats.rpccnt[NFSPROC_SETATTR]++;
376 nfsm_reqhead(nfs_procids[NFSPROC_SETATTR], cred, NFSX_FH+NFSX_SATTR);
377 nfsm_fhtom(vp);
378 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
379 if (vap->va_mode == 0xffff)
380 sp->sa_mode = VNOVAL;
381 else
382 sp->sa_mode = vtonfs_mode(vp->v_type, vap->va_mode);
383 if (vap->va_uid == 0xffff)
384 sp->sa_uid = VNOVAL;
385 else
386 sp->sa_uid = txdr_unsigned(vap->va_uid);
387 if (vap->va_gid == 0xffff)
388 sp->sa_gid = VNOVAL;
389 else
390 sp->sa_gid = txdr_unsigned(vap->va_gid);
391 sp->sa_size = txdr_unsigned(vap->va_size);
392 sp->sa_atime.tv_sec = txdr_unsigned(vap->va_atime.tv_sec);
393 sp->sa_atime.tv_usec = txdr_unsigned(vap->va_flags);
394 txdr_time(&vap->va_mtime, &sp->sa_mtime);
395 if (vap->va_size != VNOVAL || vap->va_mtime.tv_sec != VNOVAL ||
396 vap->va_atime.tv_sec != VNOVAL) {
397 np = VTONFS(vp);
398 if (np->n_flag & NMODIFIED) {
399 np->n_flag &= ~NMODIFIED;
400 if (vap->va_size == 0)
401 vinvalbuf(vp, FALSE);
402 else
403 vinvalbuf(vp, TRUE);
404 np->n_attrstamp = 0;
405 }
406 }
407 nfsm_request(vp, NFSPROC_SETATTR, p, 1);
408 nfsm_loadattr(vp, (struct vattr *)0);
409 /* should we fill in any vap fields ?? */
410 nfsm_reqdone;
411 return (error);
412}
413
414/*
415 * nfs lookup call, one step at a time...
416 * First look in cache
417 * If not found, unlock the directory nfsnode and do the rpc
418 */
a8599e88 419int
15637ed4
RG
420nfs_lookup(vp, ndp, p)
421 register struct vnode *vp;
422 register struct nameidata *ndp;
423 struct proc *p;
424{
425 register struct vnode *vdp;
426 register u_long *tl;
427 register caddr_t cp;
428 register long t1, t2;
429 caddr_t bpos, dpos, cp2;
430 u_long xid;
431 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
432 struct vnode *newvp;
433 long len;
434 nfsv2fh_t *fhp;
435 struct nfsnode *np;
436 int lockparent, wantparent, flag, error = 0;
437
438 ndp->ni_dvp = vp;
439 ndp->ni_vp = NULL;
440 if (vp->v_type != VDIR)
441 return (ENOTDIR);
442 lockparent = ndp->ni_nameiop & LOCKPARENT;
443 flag = ndp->ni_nameiop & OPMASK;
444 wantparent = ndp->ni_nameiop & (LOCKPARENT|WANTPARENT);
445 if ((error = cache_lookup(ndp)) && error != ENOENT) {
446 struct vattr vattr;
447 int vpid;
448
449 vdp = ndp->ni_vp;
450 vpid = vdp->v_id;
451 /*
452 * See the comment starting `Step through' in ufs/ufs_lookup.c
453 * for an explanation of the locking protocol
454 */
455 if (vp == vdp) {
456 VREF(vdp);
457 error = 0;
458 } else if (ndp->ni_isdotdot) {
459 nfs_unlock(vp);
460 error = vget(vdp);
461 if (!error && lockparent && *ndp->ni_next == '\0')
462 nfs_lock(vp);
463 } else {
464 error = vget(vdp);
465 if (!lockparent || error || *ndp->ni_next != '\0')
466 nfs_unlock(vp);
467 }
468 if (!error) {
469 if (vpid == vdp->v_id) {
470 if (!nfs_dogetattr(vdp, &vattr, ndp->ni_cred, 0, p)&&
471 vattr.va_ctime.tv_sec == VTONFS(vdp)->n_ctime) {
472 nfsstats.lookupcache_hits++;
473 if (flag != LOOKUP && *ndp->ni_next == 0)
474 ndp->ni_nameiop |= SAVENAME;
475 return (0);
476 }
477 cache_purge(vdp);
478 }
479 nfs_nput(vdp);
480 if (lockparent && vdp != vp && *ndp->ni_next == '\0')
481 nfs_unlock(vp);
482 }
483 ndp->ni_vp = NULLVP;
484 } else
485 nfs_unlock(vp);
486 error = 0;
487 nfsstats.lookupcache_misses++;
488 nfsstats.rpccnt[NFSPROC_LOOKUP]++;
489 len = ndp->ni_namelen;
490 nfsm_reqhead(nfs_procids[NFSPROC_LOOKUP], ndp->ni_cred, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len));
491 nfsm_fhtom(vp);
492 nfsm_strtom(ndp->ni_ptr, len, NFS_MAXNAMLEN);
493 nfsm_request(vp, NFSPROC_LOOKUP, p, 0);
494nfsmout:
495 if (error) {
496 if (lockparent || (flag != CREATE && flag != RENAME) ||
497 *ndp->ni_next != 0)
498 nfs_lock(vp);
499 if (flag != LOOKUP && *ndp->ni_next == 0)
500 ndp->ni_nameiop |= SAVENAME;
501 return (error);
502 }
503 nfsm_disect(fhp,nfsv2fh_t *,NFSX_FH);
504
505 /*
506 * Handle DELETE and RENAME cases...
507 */
508 if (flag == DELETE && *ndp->ni_next == 0) {
509 if (!bcmp(VTONFS(vp)->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) {
510 VREF(vp);
511 newvp = vp;
512 np = VTONFS(vp);
513 } else {
514 if (error = nfs_nget(vp->v_mount, fhp, &np)) {
515 nfs_lock(vp);
516 m_freem(mrep);
517 return (error);
518 }
519 newvp = NFSTOV(np);
520 }
521 if (error =
522 nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) {
523 nfs_lock(vp);
524 if (newvp != vp)
525 nfs_nput(newvp);
526 else
527 vrele(vp);
528 m_freem(mrep);
529 return (error);
530 }
531 ndp->ni_vp = newvp;
532 if (lockparent || vp == newvp)
533 nfs_lock(vp);
534 m_freem(mrep);
535 ndp->ni_nameiop |= SAVENAME;
536 return (0);
537 }
538
539 if (flag == RENAME && wantparent && *ndp->ni_next == 0) {
540 if (!bcmp(VTONFS(vp)->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) {
541 nfs_lock(vp);
542 m_freem(mrep);
543 return (EISDIR);
544 }
545 if (error = nfs_nget(vp->v_mount, fhp, &np)) {
546 nfs_lock(vp);
547 m_freem(mrep);
548 return (error);
549 }
550 newvp = NFSTOV(np);
551 if (error =
552 nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) {
553 nfs_lock(vp);
554 nfs_nput(newvp);
555 m_freem(mrep);
556 return (error);
557 }
558 ndp->ni_vp = newvp;
559 if (lockparent)
560 nfs_lock(vp);
561 m_freem(mrep);
562 ndp->ni_nameiop |= SAVENAME;
563 return (0);
564 }
565
566 if (!bcmp(VTONFS(vp)->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) {
567 VREF(vp);
568 newvp = vp;
569 np = VTONFS(vp);
570 } else if (ndp->ni_isdotdot) {
571 if (error = nfs_nget(vp->v_mount, fhp, &np)) {
572 nfs_lock(vp);
573 m_freem(mrep);
574 return (error);
575 }
576 newvp = NFSTOV(np);
577 } else {
578 if (error = nfs_nget(vp->v_mount, fhp, &np)) {
579 nfs_lock(vp);
580 m_freem(mrep);
581 return (error);
582 }
583 newvp = NFSTOV(np);
584 }
585 if (error = nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) {
586 nfs_lock(vp);
587 if (newvp != vp)
588 nfs_nput(newvp);
589 else
590 vrele(vp);
591 m_freem(mrep);
592 return (error);
593 }
594 m_freem(mrep);
595
596 if (vp == newvp || (lockparent && *ndp->ni_next == '\0'))
597 nfs_lock(vp);
598 ndp->ni_vp = newvp;
599 if (flag != LOOKUP && *ndp->ni_next == 0)
600 ndp->ni_nameiop |= SAVENAME;
601 if (error == 0 && ndp->ni_makeentry) {
602 np->n_ctime = np->n_vattr.va_ctime.tv_sec;
603 cache_enter(ndp);
604 }
605 return (error);
606}
607
608/*
609 * nfs read call.
610 * Just call nfs_bioread() to do the work.
611 */
a8599e88 612int
15637ed4
RG
613nfs_read(vp, uiop, ioflag, cred)
614 register struct vnode *vp;
615 struct uio *uiop;
616 int ioflag;
617 struct ucred *cred;
618{
619 if (vp->v_type != VREG)
620 return (EPERM);
621 return (nfs_bioread(vp, uiop, ioflag, cred));
622}
623
624/*
625 * nfs readlink call
626 */
a8599e88 627int
15637ed4
RG
628nfs_readlink(vp, uiop, cred)
629 struct vnode *vp;
630 struct uio *uiop;
631 struct ucred *cred;
632{
633 if (vp->v_type != VLNK)
634 return (EPERM);
635 return (nfs_bioread(vp, uiop, 0, cred));
636}
637
638/*
639 * Do a readlink rpc.
640 * Called by nfs_doio() from below the buffer cache.
641 */
a8599e88 642int
15637ed4
RG
643nfs_readlinkrpc(vp, uiop, cred)
644 register struct vnode *vp;
645 struct uio *uiop;
646 struct ucred *cred;
647{
648 register u_long *tl;
649 register caddr_t cp;
650 register long t1;
651 caddr_t bpos, dpos, cp2;
652 u_long xid;
653 int error = 0;
654 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
655 long len;
656
657 nfsstats.rpccnt[NFSPROC_READLINK]++;
658 nfsm_reqhead(nfs_procids[NFSPROC_READLINK], cred, NFSX_FH);
659 nfsm_fhtom(vp);
660 nfsm_request(vp, NFSPROC_READLINK, uiop->uio_procp, 0);
661 nfsm_strsiz(len, NFS_MAXPATHLEN);
662 nfsm_mtouio(uiop, len);
663 nfsm_reqdone;
664 return (error);
665}
666
667/*
668 * nfs read rpc call
669 * Ditto above
670 */
a8599e88 671int
15637ed4
RG
672nfs_readrpc(vp, uiop, cred)
673 register struct vnode *vp;
674 struct uio *uiop;
675 struct ucred *cred;
676{
677 register u_long *tl;
678 register caddr_t cp;
679 register long t1;
680 caddr_t bpos, dpos, cp2;
681 u_long xid;
682 int error = 0;
683 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
684 struct nfsmount *nmp;
685 long len, retlen, tsiz;
686
687 nmp = VFSTONFS(vp->v_mount);
688 tsiz = uiop->uio_resid;
689 while (tsiz > 0) {
690 nfsstats.rpccnt[NFSPROC_READ]++;
691 len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz;
692 nfsm_reqhead(nfs_procids[NFSPROC_READ], cred, NFSX_FH+NFSX_UNSIGNED*3);
693 nfsm_fhtom(vp);
694 nfsm_build(tl, u_long *, NFSX_UNSIGNED*3);
695 *tl++ = txdr_unsigned(uiop->uio_offset);
696 *tl++ = txdr_unsigned(len);
697 *tl = 0;
698 nfsm_request(vp, NFSPROC_READ, uiop->uio_procp, 1);
699 nfsm_loadattr(vp, (struct vattr *)0);
700 nfsm_strsiz(retlen, nmp->nm_rsize);
701 nfsm_mtouio(uiop, retlen);
702 m_freem(mrep);
703 if (retlen < len)
704 tsiz = 0;
705 else
706 tsiz -= len;
707 }
708nfsmout:
709 return (error);
710}
711
712/*
713 * nfs write call
714 */
a8599e88 715int
15637ed4
RG
716nfs_writerpc(vp, uiop, cred)
717 register struct vnode *vp;
718 struct uio *uiop;
719 struct ucred *cred;
720{
721 register u_long *tl;
722 register caddr_t cp;
723 register long t1;
724 caddr_t bpos, dpos;
725 u_long xid;
726 int error = 0;
727 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
728 struct nfsmount *nmp;
729 long len, tsiz;
730
731 nmp = VFSTONFS(vp->v_mount);
732 tsiz = uiop->uio_resid;
733 while (tsiz > 0) {
734 nfsstats.rpccnt[NFSPROC_WRITE]++;
735 len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz;
736 nfsm_reqhead(nfs_procids[NFSPROC_WRITE], cred,
737 NFSX_FH+NFSX_UNSIGNED*4);
738 nfsm_fhtom(vp);
739 nfsm_build(tl, u_long *, NFSX_UNSIGNED*4);
740 *(tl+1) = txdr_unsigned(uiop->uio_offset);
741 *(tl+3) = txdr_unsigned(len);
742 nfsm_uiotom(uiop, len);
743 nfsm_request(vp, NFSPROC_WRITE, uiop->uio_procp, 1);
744 nfsm_loadattr(vp, (struct vattr *)0);
745 m_freem(mrep);
746 tsiz -= len;
747 }
748nfsmout:
749 return (error);
750}
751
752/*
753 * nfs mknod call
754 * This is a kludge. Use a create rpc but with the IFMT bits of the mode
755 * set to specify the file type and the size field for rdev.
756 */
757/* ARGSUSED */
a8599e88 758int
15637ed4
RG
759nfs_mknod(ndp, vap, cred, p)
760 struct nameidata *ndp;
761 struct ucred *cred;
762 register struct vattr *vap;
763 struct proc *p;
764{
765 register struct nfsv2_sattr *sp;
766 register u_long *tl;
767 register caddr_t cp;
768 register long t1, t2;
769 caddr_t bpos, dpos;
770 u_long xid;
771 int error = 0;
772 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
773 u_long rdev;
774
775 if (vap->va_type == VCHR || vap->va_type == VBLK)
776 rdev = txdr_unsigned(vap->va_rdev);
777#ifdef FIFO
778 else if (vap->va_type == VFIFO)
fde1aeb2 779 rdev = 0xffffffffUL;
15637ed4
RG
780#endif /* FIFO */
781 else {
782 VOP_ABORTOP(ndp);
783 vput(ndp->ni_dvp);
784 return (EOPNOTSUPP);
785 }
786 nfsstats.rpccnt[NFSPROC_CREATE]++;
787 nfsm_reqhead(nfs_procids[NFSPROC_CREATE], ndp->ni_cred,
788 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_namelen)+NFSX_SATTR);
789 nfsm_fhtom(ndp->ni_dvp);
790 nfsm_strtom(ndp->ni_ptr, ndp->ni_namelen, NFS_MAXNAMLEN);
791 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
792 sp->sa_mode = vtonfs_mode(vap->va_type, vap->va_mode);
793 sp->sa_uid = txdr_unsigned(ndp->ni_cred->cr_uid);
794 sp->sa_gid = txdr_unsigned(ndp->ni_cred->cr_gid);
795 sp->sa_size = rdev;
796 /* or should these be VNOVAL ?? */
797 txdr_time(&vap->va_atime, &sp->sa_atime);
798 txdr_time(&vap->va_mtime, &sp->sa_mtime);
799 nfsm_request(ndp->ni_dvp, NFSPROC_CREATE, p, 1);
800 nfsm_reqdone;
801 FREE(ndp->ni_pnbuf, M_NAMEI);
802 VTONFS(ndp->ni_dvp)->n_flag |= NMODIFIED;
803 nfs_nput(ndp->ni_dvp);
804 return (error);
805}
806
807/*
808 * nfs file create call
809 */
a8599e88 810int
15637ed4
RG
811nfs_create(ndp, vap, p)
812 register struct nameidata *ndp;
813 register struct vattr *vap;
814 struct proc *p;
815{
816 register struct nfsv2_sattr *sp;
817 register u_long *tl;
818 register caddr_t cp;
819 register long t1, t2;
820 caddr_t bpos, dpos, cp2;
821 u_long xid;
822 int error = 0;
823 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
824
825 nfsstats.rpccnt[NFSPROC_CREATE]++;
826 nfsm_reqhead(nfs_procids[NFSPROC_CREATE], ndp->ni_cred,
827 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_namelen)+NFSX_SATTR);
828 nfsm_fhtom(ndp->ni_dvp);
829 nfsm_strtom(ndp->ni_ptr, ndp->ni_namelen, NFS_MAXNAMLEN);
830 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
831 sp->sa_mode = vtonfs_mode(vap->va_type, vap->va_mode);
832 sp->sa_uid = txdr_unsigned(ndp->ni_cred->cr_uid);
833 sp->sa_gid = txdr_unsigned(ndp->ni_cred->cr_gid);
834 sp->sa_size = txdr_unsigned(0);
835 /* or should these be VNOVAL ?? */
836 txdr_time(&vap->va_atime, &sp->sa_atime);
837 txdr_time(&vap->va_mtime, &sp->sa_mtime);
838 nfsm_request(ndp->ni_dvp, NFSPROC_CREATE, p, 1);
839 nfsm_mtofh(ndp->ni_dvp, ndp->ni_vp);
840 nfsm_reqdone;
841 FREE(ndp->ni_pnbuf, M_NAMEI);
842 VTONFS(ndp->ni_dvp)->n_flag |= NMODIFIED;
843 nfs_nput(ndp->ni_dvp);
844 return (error);
845}
846
847/*
848 * nfs file remove call
849 * To try and make nfs semantics closer to ufs semantics, a file that has
850 * other processes using the vnode is renamed instead of removed and then
851 * removed later on the last close.
852 * - If v_usecount > 1
853 * If a rename is not already in the works
854 * call nfs_sillyrename() to set it up
855 * else
856 * do the remove rpc
857 */
a8599e88 858int
15637ed4
RG
859nfs_remove(ndp, p)
860 register struct nameidata *ndp;
861 struct proc *p;
862{
863 register struct vnode *vp = ndp->ni_vp;
864 register struct nfsnode *np = VTONFS(ndp->ni_vp);
865 register u_long *tl;
866 register caddr_t cp;
867 register long t1, t2;
868 caddr_t bpos, dpos;
869 u_long xid;
870 int error = 0;
871 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
872
873 if (vp->v_usecount > 1) {
874 if (!np->n_sillyrename)
875 error = nfs_sillyrename(ndp, p);
876 } else {
877 nfsstats.rpccnt[NFSPROC_REMOVE]++;
878 nfsm_reqhead(nfs_procids[NFSPROC_REMOVE], ndp->ni_cred,
879 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_namelen));
880 nfsm_fhtom(ndp->ni_dvp);
881 nfsm_strtom(ndp->ni_ptr, ndp->ni_namelen, NFS_MAXNAMLEN);
882 nfsm_request(ndp->ni_dvp, NFSPROC_REMOVE, p, 1);
883 nfsm_reqdone;
884 FREE(ndp->ni_pnbuf, M_NAMEI);
885 VTONFS(ndp->ni_dvp)->n_flag |= NMODIFIED;
886 /*
887 * Kludge City: If the first reply to the remove rpc is lost..
888 * the reply to the retransmitted request will be ENOENT
889 * since the file was in fact removed
890 * Therefore, we cheat and return success.
891 */
892 if (error == ENOENT)
893 error = 0;
894 }
895 np->n_attrstamp = 0;
896 if (ndp->ni_dvp == vp)
897 vrele(vp);
898 else
899 nfs_nput(ndp->ni_dvp);
900 nfs_nput(vp);
901 return (error);
902}
903
904/*
905 * nfs file remove rpc called from nfs_inactive
906 */
a8599e88 907int
15637ed4
RG
908nfs_removeit(sp, p)
909 register struct sillyrename *sp;
910 struct proc *p;
911{
912 register u_long *tl;
913 register caddr_t cp;
914 register long t1, t2;
915 caddr_t bpos, dpos;
916 u_long xid;
917 int error = 0;
918 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
919
920 nfsstats.rpccnt[NFSPROC_REMOVE]++;
921 nfsm_reqhead(nfs_procids[NFSPROC_REMOVE], sp->s_cred,
922 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(sp->s_namlen));
923 nfsm_fhtom(sp->s_dvp);
924 nfsm_strtom(sp->s_name, sp->s_namlen, NFS_MAXNAMLEN);
925 nfsm_request(sp->s_dvp, NFSPROC_REMOVE, p, 1);
926 nfsm_reqdone;
927 VTONFS(sp->s_dvp)->n_flag |= NMODIFIED;
928 return (error);
929}
930
931/*
932 * nfs file rename call
933 */
a8599e88 934int
15637ed4
RG
935nfs_rename(sndp, tndp, p)
936 register struct nameidata *sndp, *tndp;
937 struct proc *p;
938{
939 register u_long *tl;
940 register caddr_t cp;
941 register long t1, t2;
942 caddr_t bpos, dpos;
943 u_long xid;
944 int error = 0;
945 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
946
947 nfsstats.rpccnt[NFSPROC_RENAME]++;
948 nfsm_reqhead(nfs_procids[NFSPROC_RENAME], tndp->ni_cred,
949 (NFSX_FH+NFSX_UNSIGNED)*2+nfsm_rndup(sndp->ni_namelen) +
950 nfsm_rndup(tndp->ni_namelen)); /* or sndp->ni_cred?*/
951 nfsm_fhtom(sndp->ni_dvp);
952 nfsm_strtom(sndp->ni_ptr, sndp->ni_namelen, NFS_MAXNAMLEN);
953 nfsm_fhtom(tndp->ni_dvp);
954 nfsm_strtom(tndp->ni_ptr, tndp->ni_namelen, NFS_MAXNAMLEN);
955 nfsm_request(sndp->ni_dvp, NFSPROC_RENAME, p, 1);
956 nfsm_reqdone;
957 VTONFS(sndp->ni_dvp)->n_flag |= NMODIFIED;
958 VTONFS(tndp->ni_dvp)->n_flag |= NMODIFIED;
959 if (sndp->ni_vp->v_type == VDIR) {
960 if (tndp->ni_vp != NULL && tndp->ni_vp->v_type == VDIR)
961 cache_purge(tndp->ni_dvp);
962 cache_purge(sndp->ni_dvp);
963 }
964 if (tndp->ni_dvp == tndp->ni_vp)
965 vrele(tndp->ni_dvp);
966 else
967 vput(tndp->ni_dvp);
968 if (tndp->ni_vp)
969 vput(tndp->ni_vp);
970 vrele(sndp->ni_dvp);
971 vrele(sndp->ni_vp);
972 /*
973 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry.
974 */
975 if (error == ENOENT)
976 error = 0;
977 return (error);
978}
979
980/*
981 * nfs file rename rpc called from nfs_remove() above
982 */
a8599e88 983int
15637ed4
RG
984nfs_renameit(sndp, sp, p)
985 register struct nameidata *sndp;
986 register struct sillyrename *sp;
987 struct proc *p;
988{
989 register u_long *tl;
990 register caddr_t cp;
991 register long t1, t2;
992 caddr_t bpos, dpos;
993 u_long xid;
994 int error = 0;
995 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
996
997 nfsstats.rpccnt[NFSPROC_RENAME]++;
998 nfsm_reqhead(nfs_procids[NFSPROC_RENAME], sp->s_cred,
999 (NFSX_FH+NFSX_UNSIGNED)*2+nfsm_rndup(sndp->ni_namelen) +
1000 nfsm_rndup(sp->s_namlen)); /* or sndp->ni_cred?*/
1001 nfsm_fhtom(sndp->ni_dvp);
1002 nfsm_strtom(sndp->ni_ptr, sndp->ni_namelen, NFS_MAXNAMLEN);
1003 nfsm_fhtom(sp->s_dvp);
1004 nfsm_strtom(sp->s_name, sp->s_namlen, NFS_MAXNAMLEN);
1005 nfsm_request(sndp->ni_dvp, NFSPROC_RENAME, p, 1);
1006 nfsm_reqdone;
1007 FREE(sndp->ni_pnbuf, M_NAMEI);
1008 VTONFS(sndp->ni_dvp)->n_flag |= NMODIFIED;
1009 VTONFS(sp->s_dvp)->n_flag |= NMODIFIED;
1010 return (error);
1011}
1012
1013/*
1014 * nfs hard link create call
1015 */
a8599e88 1016int
15637ed4
RG
1017nfs_link(vp, ndp, p)
1018 register struct vnode *vp;
1019 register struct nameidata *ndp;
1020 struct proc *p;
1021{
1022 register u_long *tl;
1023 register caddr_t cp;
1024 register long t1, t2;
1025 caddr_t bpos, dpos;
1026 u_long xid;
1027 int error = 0;
1028 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1029
1030 if (ndp->ni_dvp != vp)
1031 nfs_lock(vp);
1032 nfsstats.rpccnt[NFSPROC_LINK]++;
1033 nfsm_reqhead(nfs_procids[NFSPROC_LINK], ndp->ni_cred,
1034 NFSX_FH*2+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_namelen));
1035 nfsm_fhtom(vp);
1036 nfsm_fhtom(ndp->ni_dvp);
1037 nfsm_strtom(ndp->ni_ptr, ndp->ni_namelen, NFS_MAXNAMLEN);
1038 nfsm_request(vp, NFSPROC_LINK, p, 1);
1039 nfsm_reqdone;
1040 FREE(ndp->ni_pnbuf, M_NAMEI);
1041 VTONFS(vp)->n_attrstamp = 0;
1042 VTONFS(ndp->ni_dvp)->n_flag |= NMODIFIED;
1043 if (ndp->ni_dvp != vp)
1044 nfs_unlock(vp);
1045 nfs_nput(ndp->ni_dvp);
1046 /*
1047 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
1048 */
1049 if (error == EEXIST)
1050 error = 0;
1051 return (error);
1052}
1053
1054/*
1055 * nfs symbolic link create call
1056 */
a8599e88 1057int
15637ed4
RG
1058nfs_symlink(ndp, vap, nm, p)
1059 struct nameidata *ndp;
1060 struct vattr *vap;
1061 char *nm; /* is this the path ?? */
1062 struct proc *p;
1063{
1064 register struct nfsv2_sattr *sp;
1065 register u_long *tl;
1066 register caddr_t cp;
1067 register long t1, t2;
1068 caddr_t bpos, dpos;
1069 u_long xid;
1070 int error = 0;
1071 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1072
1073 nfsstats.rpccnt[NFSPROC_SYMLINK]++;
1074 nfsm_reqhead(nfs_procids[NFSPROC_SYMLINK], ndp->ni_cred,
1075 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_namelen)+NFSX_UNSIGNED);
1076 nfsm_fhtom(ndp->ni_dvp);
1077 nfsm_strtom(ndp->ni_ptr, ndp->ni_namelen, NFS_MAXNAMLEN);
1078 nfsm_strtom(nm, strlen(nm), NFS_MAXPATHLEN);
1079 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
1080 sp->sa_mode = vtonfs_mode(VLNK, vap->va_mode);
1081 sp->sa_uid = txdr_unsigned(ndp->ni_cred->cr_uid);
1082 sp->sa_gid = txdr_unsigned(ndp->ni_cred->cr_gid);
1083 sp->sa_size = txdr_unsigned(VNOVAL);
1084 txdr_time(&vap->va_atime, &sp->sa_atime); /* or VNOVAL ?? */
1085 txdr_time(&vap->va_mtime, &sp->sa_mtime); /* or VNOVAL ?? */
1086 nfsm_request(ndp->ni_dvp, NFSPROC_SYMLINK, p, 1);
1087 nfsm_reqdone;
1088 FREE(ndp->ni_pnbuf, M_NAMEI);
1089 VTONFS(ndp->ni_dvp)->n_flag |= NMODIFIED;
1090 nfs_nput(ndp->ni_dvp);
1091 /*
1092 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
1093 */
1094 if (error == EEXIST)
1095 error = 0;
1096 return (error);
1097}
1098
1099/*
1100 * nfs make dir call
1101 */
a8599e88 1102int
15637ed4
RG
1103nfs_mkdir(ndp, vap, p)
1104 register struct nameidata *ndp;
1105 struct vattr *vap;
1106 struct proc *p;
1107{
1108 register struct nfsv2_sattr *sp;
1109 register u_long *tl;
1110 register caddr_t cp;
1111 register long t1, t2;
1112 register int len;
1113 caddr_t bpos, dpos, cp2;
1114 u_long xid;
1115 int error = 0, firsttry = 1;
1116 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1117
1118 len = ndp->ni_namelen;
1119 nfsstats.rpccnt[NFSPROC_MKDIR]++;
1120 nfsm_reqhead(nfs_procids[NFSPROC_MKDIR], ndp->ni_cred,
1121 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len)+NFSX_SATTR);
1122 nfsm_fhtom(ndp->ni_dvp);
1123 nfsm_strtom(ndp->ni_ptr, len, NFS_MAXNAMLEN);
1124 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
1125 sp->sa_mode = vtonfs_mode(VDIR, vap->va_mode);
1126 sp->sa_uid = txdr_unsigned(ndp->ni_cred->cr_uid);
1127 sp->sa_gid = txdr_unsigned(ndp->ni_cred->cr_gid);
1128 sp->sa_size = txdr_unsigned(VNOVAL);
1129 txdr_time(&vap->va_atime, &sp->sa_atime); /* or VNOVAL ?? */
1130 txdr_time(&vap->va_mtime, &sp->sa_mtime); /* or VNOVAL ?? */
1131 nfsm_request(ndp->ni_dvp, NFSPROC_MKDIR, p, 1);
1132 nfsm_mtofh(ndp->ni_dvp, ndp->ni_vp);
1133 nfsm_reqdone;
1134 VTONFS(ndp->ni_dvp)->n_flag |= NMODIFIED;
1135 /*
1136 * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry
1137 * if we can succeed in looking up the directory.
1138 * "firsttry" is necessary since the macros may "goto nfsmout" which
1139 * is above the if on errors. (Ugh)
1140 */
1141 if (error == EEXIST && firsttry) {
1142 firsttry = 0;
1143 error = 0;
1144 nfsstats.rpccnt[NFSPROC_LOOKUP]++;
1145 ndp->ni_vp = NULL;
1146 nfsm_reqhead(nfs_procids[NFSPROC_LOOKUP], ndp->ni_cred,
1147 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len));
1148 nfsm_fhtom(ndp->ni_dvp);
1149 nfsm_strtom(ndp->ni_ptr, len, NFS_MAXNAMLEN);
1150 nfsm_request(ndp->ni_dvp, NFSPROC_LOOKUP, p, 1);
1151 nfsm_mtofh(ndp->ni_dvp, ndp->ni_vp);
1152 if (ndp->ni_vp->v_type != VDIR) {
1153 vput(ndp->ni_vp);
1154 error = EEXIST;
1155 }
1156 m_freem(mrep);
1157 }
1158 FREE(ndp->ni_pnbuf, M_NAMEI);
1159 nfs_nput(ndp->ni_dvp);
1160 return (error);
1161}
1162
1163/*
1164 * nfs remove directory call
1165 */
a8599e88 1166int
15637ed4
RG
1167nfs_rmdir(ndp, p)
1168 register struct nameidata *ndp;
1169 struct proc *p;
1170{
1171 register u_long *tl;
1172 register caddr_t cp;
1173 register long t1, t2;
1174 caddr_t bpos, dpos;
1175 u_long xid;
1176 int error = 0;
1177 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1178
1179 if (ndp->ni_dvp == ndp->ni_vp) {
1180 vrele(ndp->ni_dvp);
1181 nfs_nput(ndp->ni_dvp);
1182 return (EINVAL);
1183 }
1184 nfsstats.rpccnt[NFSPROC_RMDIR]++;
1185 nfsm_reqhead(nfs_procids[NFSPROC_RMDIR], ndp->ni_cred,
1186 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_namelen));
1187 nfsm_fhtom(ndp->ni_dvp);
1188 nfsm_strtom(ndp->ni_ptr, ndp->ni_namelen, NFS_MAXNAMLEN);
1189 nfsm_request(ndp->ni_dvp, NFSPROC_RMDIR, p, 1);
1190 nfsm_reqdone;
1191 FREE(ndp->ni_pnbuf, M_NAMEI);
1192 VTONFS(ndp->ni_dvp)->n_flag |= NMODIFIED;
1193 cache_purge(ndp->ni_dvp);
1194 cache_purge(ndp->ni_vp);
1195 nfs_nput(ndp->ni_vp);
1196 nfs_nput(ndp->ni_dvp);
1197 /*
1198 * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry.
1199 */
1200 if (error == ENOENT)
1201 error = 0;
1202 return (error);
1203}
1204
1205/*
1206 * nfs readdir call
1207 * Although cookie is defined as opaque, I translate it to/from net byte
1208 * order so that it looks more sensible. This appears consistent with the
1209 * Ultrix implementation of NFS.
1210 */
a8599e88 1211int
15637ed4
RG
1212nfs_readdir(vp, uiop, cred, eofflagp)
1213 register struct vnode *vp;
1214 struct uio *uiop;
1215 struct ucred *cred;
1216 int *eofflagp;
1217{
1218 register struct nfsnode *np = VTONFS(vp);
1219 int tresid, error;
1220 struct vattr vattr;
1221
1222 if (vp->v_type != VDIR)
1223 return (EPERM);
1224 /*
1225 * First, check for hit on the EOF offset cache
1226 */
1227 if (uiop->uio_offset != 0 && uiop->uio_offset == np->n_direofoffset &&
1228 (np->n_flag & NMODIFIED) == 0 &&
1229 nfs_dogetattr(vp, &vattr, cred, 0, uiop->uio_procp) == 0 &&
1230 np->n_mtime == vattr.va_mtime.tv_sec) {
1231 *eofflagp = 1;
1232 nfsstats.direofcache_hits++;
1233 return (0);
1234 }
1235
1236 /*
1237 * Call nfs_bioread() to do the real work.
1238 */
1239 tresid = uiop->uio_resid;
1240 error = nfs_bioread(vp, uiop, 0, cred);
1241
1242 if (!error && uiop->uio_resid == tresid) {
1243 *eofflagp = 1;
1244 nfsstats.direofcache_misses++;
1245 } else
1246 *eofflagp = 0;
1247 return (error);
1248}
1249
1250/*
1251 * Readdir rpc call.
1252 * Called from below the buffer cache by nfs_doio().
1253 */
a8599e88 1254int
15637ed4
RG
1255nfs_readdirrpc(vp, uiop, cred)
1256 register struct vnode *vp;
1257 struct uio *uiop;
1258 struct ucred *cred;
1259{
1260 register long len;
4c45483e 1261 register struct direct *dp = 0;
15637ed4
RG
1262 register u_long *tl;
1263 register caddr_t cp;
1264 register long t1;
4c45483e 1265 long tlen, lastlen = 0;
15637ed4
RG
1266 caddr_t bpos, dpos, cp2;
1267 u_long xid;
1268 int error = 0;
1269 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1270 struct mbuf *md2;
1271 caddr_t dpos2;
1272 int siz;
1273 int more_dirs = 1;
4c45483e
GW
1274 off_t off, savoff = 0;
1275 struct direct *savdp = 0;
15637ed4
RG
1276 struct nfsmount *nmp;
1277 struct nfsnode *np = VTONFS(vp);
1278 long tresid;
1279
1280 nmp = VFSTONFS(vp->v_mount);
1281 tresid = uiop->uio_resid;
1282 /*
1283 * Loop around doing readdir rpc's of size uio_resid or nm_rsize,
1284 * whichever is smaller, truncated to a multiple of NFS_DIRBLKSIZ.
1285 * The stopping criteria is EOF or buffer full.
1286 */
1287 while (more_dirs && uiop->uio_resid >= NFS_DIRBLKSIZ) {
1288 nfsstats.rpccnt[NFSPROC_READDIR]++;
1289 nfsm_reqhead(nfs_procids[NFSPROC_READDIR], cred, xid);
1290 nfsm_fhtom(vp);
1291 nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
1292 *tl++ = txdr_unsigned(uiop->uio_offset);
1293 *tl = txdr_unsigned(((uiop->uio_resid > nmp->nm_rsize) ?
1294 nmp->nm_rsize : uiop->uio_resid) & ~(NFS_DIRBLKSIZ-1));
1295 nfsm_request(vp, NFSPROC_READDIR, uiop->uio_procp, 0);
1296 siz = 0;
1297 nfsm_disect(tl, u_long *, NFSX_UNSIGNED);
1298 more_dirs = fxdr_unsigned(int, *tl);
1299
1300 /* Save the position so that we can do nfsm_mtouio() later */
1301 dpos2 = dpos;
1302 md2 = md;
1303
1304 /* loop thru the dir entries, doctoring them to 4bsd form */
1305 off = uiop->uio_offset;
1306#ifdef lint
1307 dp = (struct direct *)0;
1308#endif /* lint */
1309 while (more_dirs && siz < uiop->uio_resid) {
1310 savoff = off; /* Hold onto offset and dp */
1311 savdp = dp;
1312 nfsm_disecton(tl, u_long *, 2*NFSX_UNSIGNED);
1313 dp = (struct direct *)tl;
1314 dp->d_ino = fxdr_unsigned(u_long, *tl++);
1315 len = fxdr_unsigned(int, *tl);
1316 if (len <= 0 || len > NFS_MAXNAMLEN) {
1317 error = EBADRPC;
1318 m_freem(mrep);
1319 goto nfsmout;
1320 }
1321 dp->d_namlen = (u_short)len;
1322 nfsm_adv(len); /* Point past name */
1323 tlen = nfsm_rndup(len);
1324 /*
1325 * This should not be necessary, but some servers have
1326 * broken XDR such that these bytes are not null filled.
1327 */
1328 if (tlen != len) {
1329 *dpos = '\0'; /* Null-terminate */
1330 nfsm_adv(tlen - len);
1331 len = tlen;
1332 }
1333 nfsm_disecton(tl, u_long *, 2*NFSX_UNSIGNED);
1334 off = fxdr_unsigned(off_t, *tl);
1335 *tl++ = 0; /* Ensures null termination of name */
1336 more_dirs = fxdr_unsigned(int, *tl);
1337 dp->d_reclen = len+4*NFSX_UNSIGNED;
1338 siz += dp->d_reclen;
1339 }
1340 /*
1341 * If at end of rpc data, get the eof boolean
1342 */
1343 if (!more_dirs) {
1344 nfsm_disecton(tl, u_long *, NFSX_UNSIGNED);
1345 more_dirs = (fxdr_unsigned(int, *tl) == 0);
1346
1347 /*
1348 * If at EOF, cache directory offset
1349 */
1350 if (!more_dirs)
1351 np->n_direofoffset = off;
1352 }
1353 /*
1354 * If there is too much to fit in the data buffer, use savoff and
1355 * savdp to trim off the last record.
1356 * --> we are not at eof
1357 */
1358 if (siz > uiop->uio_resid) {
1359 off = savoff;
1360 siz -= dp->d_reclen;
1361 dp = savdp;
1362 more_dirs = 0; /* Paranoia */
1363 }
1364 if (siz > 0) {
1365 lastlen = dp->d_reclen;
1366 md = md2;
1367 dpos = dpos2;
1368 nfsm_mtouio(uiop, siz);
1369 uiop->uio_offset = off;
1370 } else
1371 more_dirs = 0; /* Ugh, never happens, but in case.. */
1372 m_freem(mrep);
1373 }
1374 /*
1375 * Fill last record, iff any, out to a multiple of NFS_DIRBLKSIZ
1376 * by increasing d_reclen for the last record.
1377 */
1378 if (uiop->uio_resid < tresid) {
1379 len = uiop->uio_resid & (NFS_DIRBLKSIZ - 1);
1380 if (len > 0) {
1381 dp = (struct direct *)
1382 (uiop->uio_iov->iov_base - lastlen);
1383 dp->d_reclen += len;
1384 uiop->uio_iov->iov_base += len;
1385 uiop->uio_iov->iov_len -= len;
1386 uiop->uio_resid -= len;
1387 }
1388 }
1389nfsmout:
1390 return (error);
1391}
1392
1393static char hextoasc[] = "0123456789abcdef";
1394
1395/*
1396 * Silly rename. To make the NFS filesystem that is stateless look a little
1397 * more like the "ufs" a remove of an active vnode is translated to a rename
1398 * to a funny looking filename that is removed by nfs_inactive on the
1399 * nfsnode. There is the potential for another process on a different client
1400 * to create the same funny name between the nfs_lookitup() fails and the
1401 * nfs_rename() completes, but...
1402 */
a8599e88 1403int
15637ed4
RG
1404nfs_sillyrename(ndp, p)
1405 register struct nameidata *ndp;
1406 struct proc *p;
1407{
1408 register struct nfsnode *np;
1409 register struct sillyrename *sp;
1410 int error;
1411 short pid;
1412
1413 np = VTONFS(ndp->ni_dvp);
1414 cache_purge(ndp->ni_dvp);
1415 MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename),
1416 M_NFSREQ, M_WAITOK);
1417 bcopy((caddr_t)&np->n_fh, (caddr_t)&sp->s_fh, NFSX_FH);
1418 np = VTONFS(ndp->ni_vp);
1419 sp->s_cred = crdup(ndp->ni_cred);
1420 sp->s_dvp = ndp->ni_dvp;
1421 VREF(sp->s_dvp);
1422
1423 /* Fudge together a funny name */
1424 pid = p->p_pid;
1425 bcopy(".nfsAxxxx4.4", sp->s_name, 13);
1426 sp->s_namlen = 12;
1427 sp->s_name[8] = hextoasc[pid & 0xf];
1428 sp->s_name[7] = hextoasc[(pid >> 4) & 0xf];
1429 sp->s_name[6] = hextoasc[(pid >> 8) & 0xf];
1430 sp->s_name[5] = hextoasc[(pid >> 12) & 0xf];
1431
1432 /* Try lookitups until we get one that isn't there */
1433 while (nfs_lookitup(sp, (nfsv2fh_t *)0, p) == 0) {
1434 sp->s_name[4]++;
1435 if (sp->s_name[4] > 'z') {
1436 error = EINVAL;
1437 goto bad;
1438 }
1439 }
1440 if (error = nfs_renameit(ndp, sp, p))
1441 goto bad;
1442 nfs_lookitup(sp, &np->n_fh, p);
1443 np->n_sillyrename = sp;
1444 return (0);
1445bad:
1446 vrele(sp->s_dvp);
1447 crfree(sp->s_cred);
1448 free((caddr_t)sp, M_NFSREQ);
1449 return (error);
1450}
1451
1452/*
1453 * Look up a file name for silly rename stuff.
1454 * Just like nfs_lookup() except that it doesn't load returned values
1455 * into the nfsnode table.
1456 * If fhp != NULL it copies the returned file handle out
1457 */
a8599e88 1458int
15637ed4
RG
1459nfs_lookitup(sp, fhp, p)
1460 register struct sillyrename *sp;
1461 nfsv2fh_t *fhp;
1462 struct proc *p;
1463{
1464 register struct vnode *vp = sp->s_dvp;
1465 register u_long *tl;
1466 register caddr_t cp;
1467 register long t1, t2;
1468 caddr_t bpos, dpos, cp2;
1469 u_long xid;
1470 int error = 0;
1471 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1472 long len;
1473
1474 nfsstats.rpccnt[NFSPROC_LOOKUP]++;
1475 len = sp->s_namlen;
1476 nfsm_reqhead(nfs_procids[NFSPROC_LOOKUP], sp->s_cred, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len));
1477 nfsm_fhtom(vp);
1478 nfsm_strtom(sp->s_name, len, NFS_MAXNAMLEN);
1479 nfsm_request(vp, NFSPROC_LOOKUP, p, 1);
1480 if (fhp != NULL) {
1481 nfsm_disect(cp, caddr_t, NFSX_FH);
1482 bcopy(cp, (caddr_t)fhp, NFSX_FH);
1483 }
1484 nfsm_reqdone;
1485 return (error);
1486}
1487
1488/*
1489 * Kludge City..
1490 * - make nfs_bmap() essentially a no-op that does no translation
1491 * - do nfs_strategy() by faking physical I/O with nfs_readrpc/nfs_writerpc
1492 * after mapping the physical addresses into Kernel Virtual space in the
1493 * nfsiobuf area.
1494 * (Maybe I could use the process's page mapping, but I was concerned that
1495 * Kernel Write might not be enabled and also figured copyout() would do
1496 * a lot more work than bcopy() and also it currently happens in the
1497 * context of the swapper process (2).
1498 */
a8599e88 1499int
15637ed4
RG
1500nfs_bmap(vp, bn, vpp, bnp)
1501 struct vnode *vp;
1502 daddr_t bn;
1503 struct vnode **vpp;
1504 daddr_t *bnp;
1505{
1506 if (vpp != NULL)
1507 *vpp = vp;
1508 if (bnp != NULL)
1509 *bnp = bn * btodb(vp->v_mount->mnt_stat.f_bsize);
1510 return (0);
1511}
1512
1513/*
1514 * Strategy routine for phys. i/o
1515 * If the biod's are running, queue a request
1516 * otherwise just call nfs_doio() to get it done
1517 */
a8599e88 1518int
15637ed4
RG
1519nfs_strategy(bp)
1520 register struct buf *bp;
1521{
1522 register struct buf *dp;
1523 register int i;
1524 int error = 0;
1525 int fnd = 0;
1526
1527 /*
1528 * Set b_proc. It seems a bit silly to do it here, but since bread()
1529 * doesn't set it, I will.
1530 * Set b_proc == NULL for asynchronous ops, since these may still
1531 * be hanging about after the process terminates.
1532 */
1533 if ((bp->b_flags & B_PHYS) == 0) {
1534 if (bp->b_flags & B_ASYNC)
1535 bp->b_proc = (struct proc *)0;
1536 else
1537 bp->b_proc = curproc;
1538 }
1539 /*
1540 * If the op is asynchronous and an i/o daemon is waiting
1541 * queue the request, wake it up and wait for completion
1542 * otherwise just do it ourselves.
1543 */
1544 if ((bp->b_flags & B_ASYNC) == 0 || nfs_numasync == 0)
1545 return (nfs_doio(bp));
1546 for (i = 0; i < NFS_MAXASYNCDAEMON; i++) {
1547 if (nfs_iodwant[i]) {
1548 dp = &nfs_bqueue;
1549 if (dp->b_actf == NULL) {
1550 dp->b_actl = bp;
1551 bp->b_actf = dp;
1552 } else {
1553 dp->b_actf->b_actl = bp;
1554 bp->b_actf = dp->b_actf;
1555 }
1556 dp->b_actf = bp;
1557 bp->b_actl = dp;
1558 fnd++;
1559 wakeup((caddr_t)&nfs_iodwant[i]);
1560 break;
1561 }
1562 }
1563 if (!fnd)
1564 error = nfs_doio(bp);
1565 return (error);
1566}
1567
1568/*
1569 * Fun and games with i/o
1570 * Essentially play ubasetup() and disk interrupt service routine by
1571 * mapping the data buffer into kernel virtual space and doing the
1572 * nfs read or write rpc's from it.
1573 * If the nfsiod's are not running, this is just called from nfs_strategy(),
1574 * otherwise it is called by the nfsiods to do what would normally be
1575 * partially disk interrupt driven.
1576 */
a8599e88 1577int
15637ed4
RG
1578nfs_doio(bp)
1579 register struct buf *bp;
1580{
1581 register struct uio *uiop;
1582 register struct vnode *vp;
1583 struct nfsnode *np;
1584 struct ucred *cr;
a8599e88 1585 int error = 0;
15637ed4
RG
1586 struct uio uio;
1587 struct iovec io;
1588#if !defined(hp300) && !defined(i386)
1589 register struct pte *pte, *ppte;
1590 register caddr_t vaddr;
1591 int npf, npf2;
1592 int reg, o;
1593 caddr_t vbase;
1594 unsigned v;
1595#endif
1596
1597 vp = bp->b_vp;
1598 np = VTONFS(vp);
1599 uiop = &uio;
1600 uiop->uio_iov = &io;
1601 uiop->uio_iovcnt = 1;
1602 uiop->uio_segflg = UIO_SYSSPACE;
1603 uiop->uio_procp = (struct proc *)0;
1604
1605 /*
1606 * For phys i/o, map the b_addr into kernel virtual space using
1607 * the Nfsiomap pte's
1608 * Also, add a temporary b_rcred for reading using the process's uid
1609 * and a guess at a group
1610 */
1611 if (bp->b_flags & B_PHYS) {
1612 if (bp->b_flags & B_DIRTY)
1613 uiop->uio_procp = pageproc;
1614 cr = crcopy(uiop->uio_procp->p_ucred);
1615 /* mapping was already done by vmapbuf */
1616 io.iov_base = bp->b_un.b_addr;
1617
1618 /*
1619 * And do the i/o rpc
1620 */
1621 io.iov_len = uiop->uio_resid = bp->b_bcount;
1622 uiop->uio_offset = bp->b_blkno * DEV_BSIZE;
1623 if (bp->b_flags & B_READ) {
1624 uiop->uio_rw = UIO_READ;
1625 nfsstats.read_physios++;
1626 bp->b_error = error = nfs_readrpc(vp, uiop, cr);
1627 (void) vnode_pager_uncache(vp);
1628 } else {
1629 uiop->uio_rw = UIO_WRITE;
1630 nfsstats.write_physios++;
1631 bp->b_error = error = nfs_writerpc(vp, uiop, cr);
1632 }
1633
1634 /*
1635 * Finally, release pte's used by physical i/o
1636 */
1637 crfree(cr);
1638 } else {
1639 if (bp->b_flags & B_READ) {
1640 io.iov_len = uiop->uio_resid = bp->b_bcount;
1641 io.iov_base = bp->b_un.b_addr;
1642 uiop->uio_rw = UIO_READ;
1643 switch (vp->v_type) {
1644 case VREG:
1645 uiop->uio_offset = bp->b_blkno * DEV_BSIZE;
1646 nfsstats.read_bios++;
1647 error = nfs_readrpc(vp, uiop, bp->b_rcred);
1648 break;
1649 case VLNK:
1650 uiop->uio_offset = 0;
1651 nfsstats.readlink_bios++;
1652 error = nfs_readlinkrpc(vp, uiop, bp->b_rcred);
1653 break;
1654 case VDIR:
1655 uiop->uio_offset = bp->b_lblkno;
1656 nfsstats.readdir_bios++;
1657 error = nfs_readdirrpc(vp, uiop, bp->b_rcred);
1658 /*
1659 * Save offset cookie in b_blkno.
1660 */
1661 bp->b_blkno = uiop->uio_offset;
1662 break;
a8599e88
RG
1663 default:
1664 panic("nfs_doio bad type");
15637ed4
RG
1665 };
1666 bp->b_error = error;
1667 } else {
1668 io.iov_len = uiop->uio_resid = bp->b_dirtyend
1669 - bp->b_dirtyoff;
1670 uiop->uio_offset = (bp->b_blkno * DEV_BSIZE)
1671 + bp->b_dirtyoff;
1672 io.iov_base = bp->b_un.b_addr + bp->b_dirtyoff;
1673 uiop->uio_rw = UIO_WRITE;
1674 nfsstats.write_bios++;
1675 bp->b_error = error = nfs_writerpc(vp, uiop,
1676 bp->b_wcred);
1677 if (error) {
1678 np->n_error = error;
1679 np->n_flag |= NWRITEERR;
1680 }
1681 bp->b_dirtyoff = bp->b_dirtyend = 0;
1682 }
1683 }
1684 if (error)
1685 bp->b_flags |= B_ERROR;
1686 bp->b_resid = uiop->uio_resid;
1687 biodone(bp);
1688 return (error);
1689}
1690
1691/*
1692 * Mmap a file
1693 *
1694 * NB Currently unsupported.
1695 */
1696/* ARGSUSED */
a8599e88 1697int
15637ed4
RG
1698nfs_mmap(vp, fflags, cred, p)
1699 struct vnode *vp;
1700 int fflags;
1701 struct ucred *cred;
1702 struct proc *p;
1703{
1704
1705 return (EINVAL);
1706}
1707
1708/*
1709 * Flush all the blocks associated with a vnode.
1710 * Walk through the buffer pool and push any dirty pages
1711 * associated with the vnode.
1712 */
1713/* ARGSUSED */
a8599e88 1714int
15637ed4
RG
1715nfs_fsync(vp, fflags, cred, waitfor, p)
1716 register struct vnode *vp;
1717 int fflags;
1718 struct ucred *cred;
1719 int waitfor;
1720 struct proc *p;
1721{
1722 register struct nfsnode *np = VTONFS(vp);
1723 int error = 0;
1724
1725 if (np->n_flag & NMODIFIED) {
1726 np->n_flag &= ~NMODIFIED;
1727 vflushbuf(vp, waitfor == MNT_WAIT ? B_SYNC : 0);
1728 }
1729 if (!error && (np->n_flag & NWRITEERR))
1730 error = np->n_error;
1731 return (error);
1732}
1733
1734/*
1735 * NFS advisory byte-level locks.
1736 * Currently unsupported.
1737 */
a8599e88 1738int
15637ed4
RG
1739nfs_advlock(vp, id, op, fl, flags)
1740 struct vnode *vp;
1741 caddr_t id;
1742 int op;
1743 struct flock *fl;
1744 int flags;
1745{
9bd9c0b5 1746#ifdef notyet
d5311b9f 1747 register struct nfsnode *np = VTONFS(vp);
15637ed4 1748
d5311b9f 1749 return (lf_advlock(&(np->n_lockf), np->n_size, id, op, fl, flags));
9bd9c0b5
DG
1750#else
1751 return (EOPNOTSUPP);
1752#endif
15637ed4
RG
1753}
1754
1755/*
1756 * Print out the contents of an nfsnode.
1757 */
4c45483e 1758void
15637ed4
RG
1759nfs_print(vp)
1760 struct vnode *vp;
1761{
1762 register struct nfsnode *np = VTONFS(vp);
1763
1764 printf("tag VT_NFS, fileid %d fsid 0x%x",
1765 np->n_vattr.va_fileid, np->n_vattr.va_fsid);
1766#ifdef FIFO
1767 if (vp->v_type == VFIFO)
1768 fifo_printinfo(vp);
1769#endif /* FIFO */
1770 printf("%s\n", (np->n_flag & NLOCKED) ? " (LOCKED)" : "");
1771 if (np->n_lockholder == 0)
1772 return;
1773 printf("\towner pid %d", np->n_lockholder);
1774 if (np->n_lockwaiter)
1775 printf(" waiting pid %d", np->n_lockwaiter);
1776 printf("\n");
1777}