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