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