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