v_count => v_usecount; v_lastr is being used; v_mounton is gone;
[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 *
8 * Redistribution and use in source and binary forms are permitted
9 * provided that the above copyright notice and this paragraph are
10 * duplicated in all such forms and that any documentation,
11 * advertising materials, and other materials related to such
12 * distribution and use acknowledge that the software was developed
13 * by the University of California, Berkeley. The name of the
14 * University may not be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 *
e8540f59 20 * @(#)nfs_vnops.c 7.19 (Berkeley) %G%
a2907882
KM
21 */
22
23/*
24 * vnode op calls for sun nfs version 2
25 */
26
27#include "machine/pte.h"
28#include "machine/mtpr.h"
29#include "strings.h"
30#include "param.h"
31#include "user.h"
32#include "proc.h"
33#include "mount.h"
34#include "buf.h"
35#include "vm.h"
36c3043b 36#include "../ufs/dir.h"
a2907882
KM
37#include "malloc.h"
38#include "mbuf.h"
39#include "uio.h"
40#include "ucred.h"
41#include "namei.h"
42#include "errno.h"
43#include "file.h"
44#include "conf.h"
45#include "vnode.h"
46#include "../ufs/inode.h"
9238aa59 47#include "map.h"
a2907882
KM
48#include "nfsv2.h"
49#include "nfs.h"
50#include "nfsnode.h"
51#include "nfsmount.h"
52#include "xdr_subs.h"
53#include "nfsm_subs.h"
9238aa59 54#include "nfsiom.h"
a2907882
KM
55
56/* Defs */
57#define TRUE 1
58#define FALSE 0
59
60/* Global vars */
61int nfs_lookup(),
62 nfs_create(),
f67785e5 63 nfs_mknod(),
a2907882
KM
64 nfs_open(),
65 nfs_close(),
66 nfs_access(),
67 nfs_getattr(),
68 nfs_setattr(),
69 nfs_read(),
70 nfs_write(),
71 vfs_noop(),
72 vfs_nullop(),
73 nfs_remove(),
74 nfs_link(),
75 nfs_rename(),
76 nfs_mkdir(),
77 nfs_rmdir(),
78 nfs_symlink(),
79 nfs_readdir(),
80 nfs_readlink(),
81 nfs_abortop(),
82 nfs_lock(),
83 nfs_unlock(),
84 nfs_bmap(),
85 nfs_strategy(),
9238aa59 86 nfs_fsync(),
8c7139ba 87 nfs_inactive(),
d002709d
KM
88 nfs_reclaim(),
89 nfs_print();
a2907882
KM
90
91struct vnodeops nfsv2_vnodeops = {
d002709d
KM
92 nfs_lookup, /* lookup */
93 nfs_create, /* create */
94 nfs_mknod, /* mknod */
95 nfs_open, /* open */
96 nfs_close, /* close */
97 nfs_access, /* access */
98 nfs_getattr, /* getattr */
99 nfs_setattr, /* setattr */
100 nfs_read, /* read */
101 nfs_write, /* write */
102 vfs_noop, /* ioctl */
103 vfs_noop, /* select */
104 vfs_noop, /* mmap */
105 nfs_fsync, /* fsync */
106 vfs_nullop, /* seek */
107 nfs_remove, /* remove */
108 nfs_link, /* link */
109 nfs_rename, /* rename */
110 nfs_mkdir, /* mkdir */
111 nfs_rmdir, /* rmdir */
112 nfs_symlink, /* symlink */
113 nfs_readdir, /* readdir */
114 nfs_readlink, /* readlink */
115 nfs_abortop, /* abortop */
116 nfs_inactive, /* inactive */
117 nfs_reclaim, /* reclaim */
118 nfs_lock, /* lock */
119 nfs_unlock, /* unlock */
120 nfs_bmap, /* bmap */
121 nfs_strategy, /* strategy */
122 nfs_print, /* print */
a2907882
KM
123};
124
125/* Special device vnode ops */
8a1675f3
KM
126int spec_lookup(),
127 spec_open(),
128 spec_read(),
129 spec_write(),
130 spec_strategy(),
d002709d 131 spec_bmap(),
8a1675f3
KM
132 spec_ioctl(),
133 spec_select(),
134 spec_close(),
135 spec_badop(),
136 spec_nullop();
a2907882 137
8a1675f3 138struct vnodeops spec_nfsv2nodeops = {
9106dc18
KM
139 spec_lookup, /* lookup */
140 spec_badop, /* create */
141 spec_badop, /* mknod */
142 spec_open, /* open */
143 spec_close, /* close */
144 nfs_access, /* access */
145 nfs_getattr, /* getattr */
146 nfs_setattr, /* setattr */
147 spec_read, /* read */
148 spec_write, /* write */
149 spec_ioctl, /* ioctl */
150 spec_select, /* select */
151 spec_badop, /* mmap */
152 spec_nullop, /* fsync */
153 spec_badop, /* seek */
154 spec_badop, /* remove */
155 spec_badop, /* link */
156 spec_badop, /* rename */
157 spec_badop, /* mkdir */
158 spec_badop, /* rmdir */
159 spec_badop, /* symlink */
160 spec_badop, /* readdir */
161 spec_badop, /* readlink */
162 spec_badop, /* abortop */
163 nfs_inactive, /* inactive */
164 nfs_reclaim, /* reclaim */
165 nfs_lock, /* lock */
166 nfs_unlock, /* unlock */
d002709d 167 spec_bmap, /* bmap */
9106dc18 168 spec_strategy, /* strategy */
d002709d 169 nfs_print, /* print */
a2907882
KM
170};
171
172extern u_long nfs_procids[NFS_NPROCS];
173extern u_long nfs_prog, nfs_vers;
a2907882 174extern char nfsiobuf[MAXPHYS+NBPG];
9238aa59 175struct map nfsmap[NFS_MSIZ];
a2907882 176enum vtype v_type[NFLNK+1];
9238aa59 177struct buf nfs_bqueue; /* Queue head for nfsiod's */
ffe6f482
KM
178int nfs_asyncdaemons = 0;
179struct proc *nfs_iodwant[MAX_ASYNCDAEMON];
9238aa59 180static int nfsmap_want = 0;
a2907882
KM
181
182/*
183 * nfs null call from vfs.
184 */
185nfs_null(vp, cred)
186 struct vnode *vp;
187 struct ucred *cred;
188{
13576453
KM
189 caddr_t bpos, dpos;
190 u_long xid;
191 int error = 0;
192 struct mbuf *mreq, *mrep, *md, *mb;
a2907882
KM
193
194 nfsm_reqhead(nfs_procids[NFSPROC_NULL], cred, 0);
195 nfsm_request(vp);
196 nfsm_reqdone;
197 return (error);
198}
199
200/*
201 * nfs access vnode op.
202 * Essentially just get vattr and then imitate iaccess()
203 */
204nfs_access(vp, mode, cred)
205 struct vnode *vp;
206 int mode;
207 register struct ucred *cred;
208{
209 register struct vattr *vap;
210 register gid_t *gp;
211 struct vattr vattr;
212 register int i;
213 int error;
214
215 /*
216 * If you're the super-user,
217 * you always get access.
218 */
219 if (cred->cr_uid == 0)
220 return (0);
221 vap = &vattr;
9238aa59
RM
222 if (error = nfs_getattr(vp, vap, cred))
223 return (error);
a2907882
KM
224 /*
225 * Access check is based on only one of owner, group, public.
226 * If not owner, then check group. If not a member of the
227 * group, then check public access.
228 */
229 if (cred->cr_uid != vap->va_uid) {
230 mode >>= 3;
231 gp = cred->cr_groups;
232 for (i = 0; i < cred->cr_ngroups; i++, gp++)
233 if (vap->va_gid == *gp)
234 goto found;
235 mode >>= 3;
236found:
237 ;
238 }
239 if ((vap->va_mode & mode) != 0)
240 return (0);
241 return (EACCES);
242}
243
244/*
245 * nfs open vnode op
246 * Just check to see if the type is ok
247 */
13576453 248/* ARGSUSED */
a2907882
KM
249nfs_open(vp, mode, cred)
250 struct vnode *vp;
251 int mode;
252 struct ucred *cred;
253{
254 register enum vtype vtyp;
255
256 vtyp = vp->v_type;
257 if (vtyp == VREG || vtyp == VDIR || vtyp == VLNK)
258 return (0);
259 else
260 return (EACCES);
261}
262
263/*
264 * nfs close vnode op
9238aa59 265 * For reg files, invalidate any buffer cache entries.
a2907882 266 */
13576453 267/* ARGSUSED */
a2907882
KM
268nfs_close(vp, fflags, cred)
269 register struct vnode *vp;
270 int fflags;
271 struct ucred *cred;
272{
13576453 273 register struct nfsnode *np = VTONFS(vp);
ffe6f482 274 int error = 0;
a2907882 275
e8540f59 276 if (vp->v_type == VREG && vp->v_blockh && ((np->n_flag & NMODIFIED) ||
ffe6f482 277 ((np->n_flag & NBUFFERED) && np->n_sillyrename))) {
8a1675f3 278 nfs_lock(vp);
ffe6f482 279 np->n_flag &= ~(NMODIFIED|NBUFFERED);
e8540f59 280 vinvalbuf(vp, TRUE);
ffe6f482
KM
281 if (np->n_flag & NWRITEERR) {
282 np->n_flag &= ~NWRITEERR;
e8540f59 283 error = np->n_error;
ffe6f482 284 }
8a1675f3 285 nfs_unlock(vp);
9238aa59 286 }
a2907882
KM
287 return (error);
288}
289
290/*
291 * nfs getattr call from vfs.
292 */
293nfs_getattr(vp, vap, cred)
13576453
KM
294 register struct vnode *vp;
295 struct vattr *vap;
a2907882
KM
296 struct ucred *cred;
297{
13576453
KM
298 register caddr_t cp;
299 register long t1;
300 caddr_t bpos, dpos;
301 u_long xid;
302 int error = 0;
303 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
a2907882
KM
304
305 /* First look in the cache.. */
306 if (nfs_getattrcache(vp, vap) == 0)
307 return (0);
308 nfsstats.rpccnt[NFSPROC_GETATTR]++;
309 nfsm_reqhead(nfs_procids[NFSPROC_GETATTR], cred, NFSX_FH);
310 nfsm_fhtom(vp);
311 nfsm_request(vp);
312 nfsm_loadattr(vp, vap);
313 nfsm_reqdone;
314 return (error);
315}
316
317/*
318 * nfs setattr call.
319 */
320nfs_setattr(vp, vap, cred)
13576453 321 register struct vnode *vp;
a2907882
KM
322 register struct vattr *vap;
323 struct ucred *cred;
324{
9238aa59 325 register struct nfsv2_sattr *sp;
13576453
KM
326 register caddr_t cp;
327 register long t1;
328 caddr_t bpos, dpos;
329 u_long xid;
330 int error = 0;
331 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
00b72154 332 struct nfsnode *np;
a2907882
KM
333
334 nfsstats.rpccnt[NFSPROC_SETATTR]++;
335 nfsm_reqhead(nfs_procids[NFSPROC_SETATTR], cred, NFSX_FH+NFSX_SATTR);
336 nfsm_fhtom(vp);
9238aa59 337 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
a2907882 338 if (vap->va_mode == 0xffff)
9238aa59 339 sp->sa_mode = VNOVAL;
a2907882 340 else
9238aa59 341 sp->sa_mode = vtonfs_mode(vp->v_type, vap->va_mode);
a2907882 342 if (vap->va_uid == 0xffff)
9238aa59 343 sp->sa_uid = VNOVAL;
a2907882 344 else
9238aa59 345 sp->sa_uid = txdr_unsigned(vap->va_uid);
a2907882 346 if (vap->va_gid == 0xffff)
9238aa59 347 sp->sa_gid = VNOVAL;
a2907882 348 else
9238aa59
RM
349 sp->sa_gid = txdr_unsigned(vap->va_gid);
350 sp->sa_size = txdr_unsigned(vap->va_size);
00b72154
KM
351 if (vap->va_size != VNOVAL) {
352 np = VTONFS(vp);
353 if (np->n_flag & NMODIFIED) {
354 np->n_flag &= ~NMODIFIED;
e8540f59
KM
355 if (vp->v_blockh)
356 vinvalbuf(vp, TRUE);
00b72154
KM
357 }
358 }
e8540f59
KM
359 sp->sa_atime.tv_sec = txdr_unsigned(vap->va_atime.tv_sec);
360 sp->sa_atime.tv_usec = txdr_unsigned(vap->va_flags);
9238aa59 361 txdr_time(&vap->va_mtime, &sp->sa_mtime);
a2907882
KM
362 nfsm_request(vp);
363 nfsm_loadattr(vp, (struct vattr *)0);
364 /* should we fill in any vap fields ?? */
365 nfsm_reqdone;
366 return (error);
367}
368
369/*
370 * nfs lookup call, one step at a time...
371 * First look in cache
372 * If not found, unlock the directory nfsnode and do the rpc
373 */
374nfs_lookup(vp, ndp)
375 register struct vnode *vp;
376 register struct nameidata *ndp;
377{
378 register struct vnode *vdp;
13576453
KM
379 register u_long *p;
380 register caddr_t cp;
381 register long t1, t2;
382 caddr_t bpos, dpos, cp2;
383 u_long xid;
384 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
a2907882
KM
385 struct vnode *newvp;
386 long len;
387 nfsv2fh_t *fhp;
388 struct nfsnode *np;
13576453 389 int lockparent, wantparent, flag, error = 0;
a2907882
KM
390
391 ndp->ni_dvp = vp;
392 ndp->ni_vp = NULL;
393 if (vp->v_type != VDIR)
394 return (ENOTDIR);
395 lockparent = ndp->ni_nameiop & LOCKPARENT;
396 flag = ndp->ni_nameiop & OPFLAG;
397 wantparent = ndp->ni_nameiop & (LOCKPARENT|WANTPARENT);
ffe6f482 398 if ((error = cache_lookup(ndp)) && error != ENOENT) {
9238aa59
RM
399 struct vattr vattr;
400 int vpid;
401
8a1675f3
KM
402 if (vp == ndp->ni_rdir && ndp->ni_isdotdot)
403 panic("nfs_lookup: .. through root");
404 vdp = ndp->ni_vp;
9238aa59 405 vpid = vdp->v_id;
a2907882 406 /*
9238aa59
RM
407 * See the comment starting `Step through' in ufs/ufs_lookup.c
408 * for an explanation of the locking protocol
a2907882
KM
409 */
410 if (vp == vdp) {
36c3043b 411 VREF(vdp);
8a1675f3 412 error = 0;
a2907882
KM
413 } else if (ndp->ni_isdotdot) {
414 nfs_unlock(vp);
8a1675f3 415 error = vget(vdp);
a2907882 416 } else {
8a1675f3 417 error = vget(vdp);
a2907882
KM
418 nfs_unlock(vp);
419 }
8a1675f3
KM
420 if (!error) {
421 if (vpid == vdp->v_id &&
422 !nfs_getattr(vdp, &vattr, ndp->ni_cred)) {
423 nfsstats.lookupcache_hits++;
424 return (0);
425 } else {
426 nfs_nput(vdp);
427 }
9238aa59 428 }
9238aa59 429 ndp->ni_vp = (struct vnode *)0;
e8540f59
KM
430 } else
431 nfs_unlock(vp);
ffe6f482 432 error = 0;
a2907882 433 nfsstats.lookupcache_misses++;
a2907882
KM
434 nfsstats.rpccnt[NFSPROC_LOOKUP]++;
435 len = ndp->ni_namelen;
436 nfsm_reqhead(nfs_procids[NFSPROC_LOOKUP], ndp->ni_cred, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len));
437 nfsm_fhtom(vp);
438 nfsm_strtom(ndp->ni_ptr, len, NFS_MAXNAMLEN);
439 nfsm_request(vp);
440nfsmout:
441 if (error) {
e8540f59
KM
442 if (lockparent || (flag != CREATE && flag != RENAME) ||
443 *ndp->ni_next != 0)
444 nfs_lock(vp);
a2907882
KM
445 return (ENOENT);
446 }
447 nfsm_disect(fhp,nfsv2fh_t *,NFSX_FH);
448
449 /*
450 * Handle DELETE and RENAME cases...
451 */
452 if (flag == DELETE && *ndp->ni_next == 0) {
453 if (!bcmp(VTONFS(vp)->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) {
36c3043b 454 VREF(vp);
a2907882
KM
455 newvp = vp;
456 np = VTONFS(vp);
457 } else {
458 if (error = nfs_nget(vp->v_mount, fhp, &np)) {
e8540f59 459 nfs_lock(vp);
a2907882
KM
460 m_freem(mrep);
461 return (error);
462 }
463 newvp = NFSTOV(np);
464 }
f67785e5
KM
465 if (error =
466 nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) {
e8540f59 467 nfs_lock(vp);
a2907882
KM
468 if (newvp != vp)
469 nfs_nput(newvp);
470 else
36c3043b 471 vrele(vp);
a2907882
KM
472 m_freem(mrep);
473 return (error);
474 }
a2907882 475 ndp->ni_vp = newvp;
e8540f59
KM
476 if (lockparent || vp == newvp)
477 nfs_lock(vp);
a2907882
KM
478 m_freem(mrep);
479 return (0);
480 }
481
482 if (flag == RENAME && wantparent && *ndp->ni_next == 0) {
483 if (!bcmp(VTONFS(vp)->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) {
e8540f59 484 nfs_lock(vp);
a2907882
KM
485 m_freem(mrep);
486 return (EISDIR);
487 }
488 if (error = nfs_nget(vp->v_mount, fhp, &np)) {
e8540f59 489 nfs_lock(vp);
a2907882
KM
490 m_freem(mrep);
491 return (error);
492 }
493 newvp = NFSTOV(np);
f67785e5
KM
494 if (error =
495 nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) {
e8540f59 496 nfs_lock(vp);
36c3043b 497 nfs_nput(newvp);
a2907882
KM
498 m_freem(mrep);
499 return (error);
500 }
501 ndp->ni_vp = newvp;
e8540f59
KM
502 if (lockparent)
503 nfs_lock(vp);
a2907882
KM
504 return (0);
505 }
506
507 if (!bcmp(VTONFS(vp)->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) {
36c3043b 508 VREF(vp);
a2907882
KM
509 newvp = vp;
510 np = VTONFS(vp);
511 } else if (ndp->ni_isdotdot) {
a2907882
KM
512 if (error = nfs_nget(vp->v_mount, fhp, &np)) {
513 nfs_lock(vp);
514 m_freem(mrep);
515 return (error);
516 }
a2907882
KM
517 newvp = NFSTOV(np);
518 } else {
519 if (error = nfs_nget(vp->v_mount, fhp, &np)) {
e8540f59 520 nfs_lock(vp);
a2907882
KM
521 m_freem(mrep);
522 return (error);
523 }
524 newvp = NFSTOV(np);
525 }
f67785e5 526 if (error = nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) {
e8540f59 527 nfs_lock(vp);
a2907882
KM
528 if (newvp != vp)
529 nfs_nput(newvp);
530 else
36c3043b 531 vrele(vp);
a2907882
KM
532 m_freem(mrep);
533 return (error);
534 }
535 m_freem(mrep);
a2907882 536
e8540f59
KM
537 if (vp == newvp || (lockparent && *ndp->ni_next == '\0'))
538 nfs_lock(vp);
a2907882 539 ndp->ni_vp = newvp;
a2907882
KM
540 if (error == 0 && ndp->ni_makeentry)
541 cache_enter(ndp);
a2907882
KM
542 return (error);
543}
544
545/*
546 * nfs readlink call
547 */
548nfs_readlink(vp, uiop, cred)
13576453 549 register struct vnode *vp;
a2907882
KM
550 struct uio *uiop;
551 struct ucred *cred;
552{
13576453
KM
553 register u_long *p;
554 register caddr_t cp;
555 register long t1;
556 caddr_t bpos, dpos, cp2;
557 u_long xid;
558 int error = 0;
559 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
a2907882
KM
560 long len;
561
562 nfsstats.rpccnt[NFSPROC_READLINK]++;
563 nfsm_reqhead(nfs_procids[NFSPROC_READLINK], cred, NFSX_FH);
564 nfsm_fhtom(vp);
565 nfsm_request(vp);
566 nfsm_strsiz(len, NFS_MAXPATHLEN);
567 nfsm_mtouio(uiop, len);
568 nfsm_reqdone;
569 return (error);
570}
571
572/*
573 * nfs read call
574 */
f8428623 575nfs_readrpc(vp, uiop, cred)
13576453 576 register struct vnode *vp;
a2907882 577 struct uio *uiop;
a2907882
KM
578 struct ucred *cred;
579{
13576453
KM
580 register u_long *p;
581 register caddr_t cp;
582 register long t1;
583 caddr_t bpos, dpos, cp2;
584 u_long xid;
585 int error = 0;
586 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
a2907882
KM
587 struct nfsmount *nmp;
588 long len, retlen, tsiz;
589
590 nmp = vfs_to_nfs(vp->v_mount);
591 tsiz = uiop->uio_resid;
a2907882
KM
592 while (tsiz > 0) {
593 nfsstats.rpccnt[NFSPROC_READ]++;
594 len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz;
595 nfsm_reqhead(nfs_procids[NFSPROC_READ], cred, NFSX_FH+NFSX_UNSIGNED*3);
596 nfsm_fhtom(vp);
597 nfsm_build(p, u_long *, NFSX_UNSIGNED*3);
f8428623 598 *p++ = txdr_unsigned(uiop->uio_offset);
a2907882
KM
599 *p++ = txdr_unsigned(len);
600 *p = 0;
601 nfsm_request(vp);
602 nfsm_loadattr(vp, (struct vattr *)0);
603 nfsm_strsiz(retlen, nmp->nm_rsize);
604 nfsm_mtouio(uiop, retlen);
605 m_freem(mrep);
a2907882
KM
606 if (retlen < len)
607 tsiz = 0;
608 else
609 tsiz -= len;
610 }
611nfsmout:
a2907882
KM
612 return (error);
613}
614
615/*
616 * nfs write call
617 */
f8428623 618nfs_writerpc(vp, uiop, cred)
13576453 619 register struct vnode *vp;
a2907882 620 struct uio *uiop;
a2907882
KM
621 struct ucred *cred;
622{
13576453
KM
623 register u_long *p;
624 register caddr_t cp;
625 register long t1;
626 caddr_t bpos, dpos;
627 u_long xid;
628 int error = 0;
629 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
a2907882
KM
630 struct nfsmount *nmp;
631 long len, tsiz;
a2907882
KM
632
633 nmp = vfs_to_nfs(vp->v_mount);
634 tsiz = uiop->uio_resid;
a2907882
KM
635 while (tsiz > 0) {
636 nfsstats.rpccnt[NFSPROC_WRITE]++;
637 len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz;
638 nfsm_reqhead(nfs_procids[NFSPROC_WRITE], cred,
639 NFSX_FH+NFSX_UNSIGNED*4);
640 nfsm_fhtom(vp);
641 nfsm_build(p, u_long *, NFSX_UNSIGNED*4);
f8428623 642 *(p+1) = txdr_unsigned(uiop->uio_offset);
a2907882
KM
643 *(p+3) = txdr_unsigned(len);
644 nfsm_uiotom(uiop, len);
645 nfsm_request(vp);
646 nfsm_loadattr(vp, (struct vattr *)0);
647 m_freem(mrep);
648 tsiz -= len;
a2907882
KM
649 }
650nfsmout:
a2907882
KM
651 return (error);
652}
653
f67785e5
KM
654/*
655 * nfs mknod call
656 * This call is currently not supported.
657 */
658/* ARGSUSED */
659nfs_mknod(ndp, vap, cred)
660 struct nameidata *ndp;
661 struct ucred *cred;
662 struct vattr *vap;
663{
664
665 nfs_abortop(ndp);
666 return (EOPNOTSUPP);
667}
668
a2907882
KM
669/*
670 * nfs file create call
671 */
672nfs_create(ndp, vap)
673 register struct nameidata *ndp;
674 register struct vattr *vap;
675{
9238aa59 676 register struct nfsv2_sattr *sp;
13576453
KM
677 register u_long *p;
678 register caddr_t cp;
679 register long t1, t2;
680 caddr_t bpos, dpos, cp2;
681 u_long xid;
682 int error = 0;
683 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
a2907882
KM
684
685 nfsstats.rpccnt[NFSPROC_CREATE]++;
686 nfsm_reqhead(nfs_procids[NFSPROC_CREATE], ndp->ni_cred,
687 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen)+NFSX_SATTR);
688 nfsm_fhtom(ndp->ni_dvp);
689 nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN);
9238aa59
RM
690 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
691 sp->sa_mode = vtonfs_mode(VREG, vap->va_mode);
692 sp->sa_uid = txdr_unsigned(ndp->ni_cred->cr_uid);
693 sp->sa_gid = txdr_unsigned(ndp->ni_cred->cr_gid);
694 sp->sa_size = txdr_unsigned(0);
a2907882 695 /* or should these be VNOVAL ?? */
9238aa59
RM
696 txdr_time(&vap->va_atime, &sp->sa_atime);
697 txdr_time(&vap->va_mtime, &sp->sa_mtime);
a2907882
KM
698 nfsm_request(ndp->ni_dvp);
699 nfsm_mtofh(ndp->ni_dvp, ndp->ni_vp);
700 nfsm_reqdone;
701 nfs_nput(ndp->ni_dvp);
702 return (error);
703}
704
705/*
706 * nfs file remove call
ffe6f482
KM
707 * To try and make nfs semantics closer to vfs semantics, a file that has
708 * other references to the vnode is renamed instead of removed and then
709 * removed later on the last close.
710 * Unfortunately you must flush the buffer cache and cmap to get rid of
711 * all extraneous vnode references before you check the reference cnt.
712 * 1 - If the file could have blocks in the buffer cache
713 * flush them out and invalidate them
714 * mpurge the vnode to flush out cmap references
715 * (This is necessary to update the vnode ref cnt as well as sensible
716 * for actual removes, to free up the buffers)
717 * 2 - If v_count > 1
718 * If a rename is not already in the works
719 * call nfs_sillyrename() to set it up
720 * else
721 * do the remove rpc
a2907882
KM
722 */
723nfs_remove(ndp)
724 register struct nameidata *ndp;
725{
ffe6f482
KM
726 register struct vnode *vp = ndp->ni_vp;
727 register struct nfsnode *np = VTONFS(ndp->ni_vp);
13576453
KM
728 register u_long *p;
729 register caddr_t cp;
730 register long t1, t2;
731 caddr_t bpos, dpos;
732 u_long xid;
733 int error = 0;
734 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
a2907882 735
ffe6f482
KM
736 if (vp->v_type == VREG) {
737 if (np->n_flag & (NMODIFIED|NBUFFERED)) {
738 np->n_flag &= ~(NMODIFIED|NBUFFERED);
e8540f59
KM
739 if (vp->v_blockh)
740 vinvalbuf(vp, TRUE);
ffe6f482 741 }
e8540f59
KM
742 if (np->n_flag & NPAGEDON) {
743 np->n_flag &= ~NPAGEDON;
ffe6f482 744 mpurge(vp); /* In case cmap entries still ref it */
e8540f59 745 }
ffe6f482
KM
746 }
747 if (vp->v_count > 1) {
748 if (!np->n_sillyrename)
749 error = nfs_sillyrename(ndp, REMOVE);
750 } else {
a2907882
KM
751 nfsstats.rpccnt[NFSPROC_REMOVE]++;
752 nfsm_reqhead(nfs_procids[NFSPROC_REMOVE], ndp->ni_cred,
753 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen));
754 nfsm_fhtom(ndp->ni_dvp);
755 nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN);
756 nfsm_request(ndp->ni_dvp);
757 nfsm_reqdone;
e8540f59
KM
758 /*
759 * Kludge City: If the first reply to the remove rpc is lost..
760 * the reply to the retransmitted request will be ENOENT
761 * since the file was in fact removed
762 * Therefore, we cheat and return success.
763 */
764 if (error == ENOENT)
765 error = 0;
a2907882
KM
766 }
767 if (ndp->ni_dvp == ndp->ni_vp)
36c3043b 768 vrele(ndp->ni_vp);
a2907882 769 else
36c3043b
KM
770 nfs_nput(ndp->ni_vp);
771 nfs_nput(ndp->ni_dvp);
a2907882
KM
772 return (error);
773}
774
775/*
776 * nfs file remove rpc called from nfs_inactive
777 */
778nfs_removeit(ndp)
779 register struct nameidata *ndp;
780{
13576453
KM
781 register u_long *p;
782 register caddr_t cp;
783 register long t1, t2;
784 caddr_t bpos, dpos;
785 u_long xid;
786 int error = 0;
787 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
a2907882
KM
788
789 nfsstats.rpccnt[NFSPROC_REMOVE]++;
790 nfsm_reqhead(nfs_procids[NFSPROC_REMOVE], ndp->ni_cred,
791 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen));
792 nfsm_fhtom(ndp->ni_dvp);
793 nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN);
794 nfsm_request(ndp->ni_dvp);
795 nfsm_reqdone;
796 return (error);
797}
798
799/*
800 * nfs file rename call
801 */
802nfs_rename(sndp, tndp)
803 register struct nameidata *sndp, *tndp;
804{
13576453
KM
805 register u_long *p;
806 register caddr_t cp;
807 register long t1, t2;
808 caddr_t bpos, dpos;
809 u_long xid;
810 int error = 0;
811 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
a2907882
KM
812
813 nfsstats.rpccnt[NFSPROC_RENAME]++;
814 nfsm_reqhead(nfs_procids[NFSPROC_RENAME], tndp->ni_cred,
815 (NFSX_FH+NFSX_UNSIGNED)*2+nfsm_rndup(sndp->ni_dent.d_namlen)+
816 nfsm_rndup(tndp->ni_dent.d_namlen)); /* or sndp->ni_cred?*/
817 nfsm_fhtom(sndp->ni_dvp);
818 nfsm_strtom(sndp->ni_dent.d_name,sndp->ni_dent.d_namlen,NFS_MAXNAMLEN);
819 nfsm_fhtom(tndp->ni_dvp);
820 nfsm_strtom(tndp->ni_dent.d_name,tndp->ni_dent.d_namlen,NFS_MAXNAMLEN);
821 nfsm_request(sndp->ni_dvp);
822 nfsm_reqdone;
a2907882
KM
823 if (sndp->ni_vp->v_type == VDIR) {
824 if (tndp->ni_vp != NULL && tndp->ni_vp->v_type == VDIR)
825 cache_purge(tndp->ni_dvp);
826 cache_purge(sndp->ni_dvp);
827 }
a2907882
KM
828 nfs_abortop(sndp);
829 nfs_abortop(tndp);
830 return (error);
831}
832
833/*
834 * nfs file rename rpc called from above
835 */
836nfs_renameit(sndp, tndp)
837 register struct nameidata *sndp, *tndp;
838{
13576453
KM
839 register u_long *p;
840 register caddr_t cp;
841 register long t1, t2;
842 caddr_t bpos, dpos;
843 u_long xid;
844 int error = 0;
845 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
a2907882
KM
846
847 nfsstats.rpccnt[NFSPROC_RENAME]++;
848 nfsm_reqhead(nfs_procids[NFSPROC_RENAME], tndp->ni_cred,
849 (NFSX_FH+NFSX_UNSIGNED)*2+nfsm_rndup(sndp->ni_dent.d_namlen)+
850 nfsm_rndup(tndp->ni_dent.d_namlen)); /* or sndp->ni_cred?*/
851 nfsm_fhtom(sndp->ni_dvp);
852 nfsm_strtom(sndp->ni_dent.d_name,sndp->ni_dent.d_namlen,NFS_MAXNAMLEN);
853 nfsm_fhtom(tndp->ni_dvp);
854 nfsm_strtom(tndp->ni_dent.d_name,tndp->ni_dent.d_namlen,NFS_MAXNAMLEN);
855 nfsm_request(sndp->ni_dvp);
856 nfsm_reqdone;
857 return (error);
858}
859
860/*
861 * nfs hard link create call
862 */
863nfs_link(vp, ndp)
13576453 864 register struct vnode *vp;
a2907882
KM
865 register struct nameidata *ndp;
866{
13576453
KM
867 register u_long *p;
868 register caddr_t cp;
869 register long t1, t2;
870 caddr_t bpos, dpos;
871 u_long xid;
872 int error = 0;
873 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
a2907882 874
36c3043b
KM
875 if (ndp->ni_dvp != vp)
876 nfs_lock(vp);
a2907882
KM
877 nfsstats.rpccnt[NFSPROC_LINK]++;
878 nfsm_reqhead(nfs_procids[NFSPROC_LINK], ndp->ni_cred,
879 NFSX_FH*2+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen));
880 nfsm_fhtom(vp);
881 nfsm_fhtom(ndp->ni_dvp);
882 nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN);
883 nfsm_request(vp);
884 nfsm_reqdone;
36c3043b
KM
885 if (ndp->ni_dvp != vp)
886 nfs_unlock(vp);
a2907882
KM
887 nfs_nput(ndp->ni_dvp);
888 return (error);
889}
890
891/*
892 * nfs symbolic link create call
893 */
894nfs_symlink(ndp, vap, nm)
895 struct nameidata *ndp;
896 struct vattr *vap;
897 char *nm; /* is this the path ?? */
898{
9238aa59 899 register struct nfsv2_sattr *sp;
13576453
KM
900 register u_long *p;
901 register caddr_t cp;
902 register long t1, t2;
903 caddr_t bpos, dpos;
904 u_long xid;
905 int error = 0;
906 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
a2907882
KM
907
908 nfsstats.rpccnt[NFSPROC_SYMLINK]++;
909 nfsm_reqhead(nfs_procids[NFSPROC_SYMLINK], ndp->ni_cred,
910 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen)+NFSX_UNSIGNED);
911 nfsm_fhtom(ndp->ni_dvp);
912 nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN);
913 nfsm_strtom(nm, strlen(nm), NFS_MAXPATHLEN);
9238aa59
RM
914 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
915 sp->sa_mode = vtonfs_mode(VLNK, vap->va_mode);
916 sp->sa_uid = txdr_unsigned(ndp->ni_cred->cr_uid);
917 sp->sa_gid = txdr_unsigned(ndp->ni_cred->cr_gid);
918 sp->sa_size = txdr_unsigned(VNOVAL);
919 txdr_time(&vap->va_atime, &sp->sa_atime); /* or VNOVAL ?? */
920 txdr_time(&vap->va_mtime, &sp->sa_mtime); /* or VNOVAL ?? */
a2907882
KM
921 nfsm_request(ndp->ni_dvp);
922 nfsm_reqdone;
923 nfs_nput(ndp->ni_dvp);
924 return (error);
925}
926
927/*
928 * nfs make dir call
929 */
930nfs_mkdir(ndp, vap)
13576453 931 register struct nameidata *ndp;
a2907882
KM
932 struct vattr *vap;
933{
9238aa59 934 register struct nfsv2_sattr *sp;
13576453
KM
935 register u_long *p;
936 register caddr_t cp;
937 register long t1, t2;
938 caddr_t bpos, dpos, cp2;
939 u_long xid;
940 int error = 0;
941 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
a2907882
KM
942
943 nfsstats.rpccnt[NFSPROC_MKDIR]++;
944 nfsm_reqhead(nfs_procids[NFSPROC_MKDIR], ndp->ni_cred,
945 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen)+NFSX_SATTR);
946 nfsm_fhtom(ndp->ni_dvp);
947 nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN);
9238aa59
RM
948 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
949 sp->sa_mode = vtonfs_mode(VDIR, vap->va_mode);
950 sp->sa_uid = txdr_unsigned(ndp->ni_cred->cr_uid);
951 sp->sa_gid = txdr_unsigned(ndp->ni_cred->cr_gid);
952 sp->sa_size = txdr_unsigned(VNOVAL);
953 txdr_time(&vap->va_atime, &sp->sa_atime); /* or VNOVAL ?? */
954 txdr_time(&vap->va_mtime, &sp->sa_mtime); /* or VNOVAL ?? */
a2907882
KM
955 nfsm_request(ndp->ni_dvp);
956 nfsm_mtofh(ndp->ni_dvp, ndp->ni_vp);
957 nfsm_reqdone;
a2907882
KM
958 nfs_nput(ndp->ni_dvp);
959 return (error);
960}
961
962/*
963 * nfs remove directory call
964 */
965nfs_rmdir(ndp)
966 register struct nameidata *ndp;
967{
13576453
KM
968 register u_long *p;
969 register caddr_t cp;
970 register long t1, t2;
971 caddr_t bpos, dpos;
972 u_long xid;
973 int error = 0;
974 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
a2907882
KM
975
976 if (ndp->ni_dvp == ndp->ni_vp) {
977 vrele(ndp->ni_dvp);
978 nfs_nput(ndp->ni_dvp);
979 return (EINVAL);
980 }
a2907882
KM
981 nfsstats.rpccnt[NFSPROC_RMDIR]++;
982 nfsm_reqhead(nfs_procids[NFSPROC_RMDIR], ndp->ni_cred,
983 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen));
984 nfsm_fhtom(ndp->ni_dvp);
985 nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN);
986 nfsm_request(ndp->ni_dvp);
987 nfsm_reqdone;
9238aa59
RM
988 cache_purge(ndp->ni_dvp);
989 cache_purge(ndp->ni_vp);
9238aa59
RM
990 nfs_nput(ndp->ni_vp);
991 nfs_nput(ndp->ni_dvp);
a2907882
KM
992 return (error);
993}
994
995/*
996 * nfs readdir call
997 * Although cookie is defined as opaque, I translate it to/from net byte
998 * order so that it looks more sensible. This appears consistent with the
999 * Ultrix implementation of NFS.
1000 */
f8428623 1001nfs_readdir(vp, uiop, cred)
13576453 1002 register struct vnode *vp;
a2907882 1003 struct uio *uiop;
a2907882
KM
1004 struct ucred *cred;
1005{
1006 register long len;
1007 register struct direct *dp;
13576453
KM
1008 register u_long *p;
1009 register caddr_t cp;
1010 register long t1;
1011 caddr_t bpos, dpos, cp2;
1012 u_long xid;
1013 int error = 0;
1014 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
a2907882
KM
1015 struct mbuf *md2;
1016 caddr_t dpos2;
1017 int siz;
574a968b 1018 int more_dirs;
a2907882
KM
1019 off_t off, savoff;
1020 struct direct *savdp;
1021
a2907882
KM
1022 nfsstats.rpccnt[NFSPROC_READDIR]++;
1023 nfsm_reqhead(nfs_procids[NFSPROC_READDIR], cred, xid);
1024 nfsm_fhtom(vp);
1025 nfsm_build(p, u_long *, 2*NFSX_UNSIGNED);
f8428623 1026 *p++ = txdr_unsigned(uiop->uio_offset);
a2907882
KM
1027 *p = txdr_unsigned(uiop->uio_resid);
1028 nfsm_request(vp);
1029 siz = 0;
1030 nfsm_disect(p, u_long *, NFSX_UNSIGNED);
1031 more_dirs = fxdr_unsigned(int, *p);
1032
1033 /* Save the position so that we can do nfsm_mtouio() later */
1034 dpos2 = dpos;
1035 md2 = md;
1036
1037 /* loop thru the dir entries, doctoring them to 4bsd form */
13576453
KM
1038 savoff = off = 0;
1039 savdp = dp = NULL;
a2907882
KM
1040 while (more_dirs && siz < uiop->uio_resid) {
1041 savoff = off; /* Hold onto offset and dp */
1042 savdp = dp;
1043 nfsm_disecton(p, u_long *, 2*NFSX_UNSIGNED);
1044 dp = (struct direct *)p;
1045 dp->d_ino = fxdr_unsigned(u_long, *p++);
1046 len = fxdr_unsigned(int, *p);
1047 if (len <= 0 || len > NFS_MAXNAMLEN) {
1048 error = EBADRPC;
1049 m_freem(mrep);
1050 goto nfsmout;
1051 }
1052 dp->d_namlen = (u_short)len;
1053 len = nfsm_rndup(len);
1054 nfsm_adv(len);
1055 nfsm_disecton(p, u_long *, 2*NFSX_UNSIGNED);
1056 off = fxdr_unsigned(off_t, *p);
1057 *p++ = 0; /* Ensures null termination of name */
1058 more_dirs = fxdr_unsigned(int, *p);
1059 dp->d_reclen = len+4*NFSX_UNSIGNED;
1060 siz += dp->d_reclen;
1061 }
1062 /*
1063 * If at end of rpc data, get the eof boolean
1064 */
574a968b 1065 if (!more_dirs)
a2907882 1066 nfsm_disecton(p, u_long *, NFSX_UNSIGNED);
a2907882
KM
1067 /*
1068 * If there is too much to fit in the data buffer, use savoff and
1069 * savdp to trim off the last record.
1070 * --> we are not at eof
1071 */
1072 if (siz > uiop->uio_resid) {
a2907882
KM
1073 off = savoff;
1074 siz -= dp->d_reclen;
1075 dp = savdp;
1076 }
1077 if (siz > 0) {
a2907882
KM
1078 md = md2;
1079 dpos = dpos2;
1080 nfsm_mtouio(uiop, siz);
f8428623 1081 uiop->uio_offset = off;
a2907882
KM
1082 }
1083 nfsm_reqdone;
a2907882
KM
1084 return (error);
1085}
1086
1087/*
1088 * nfs statfs call
1089 * (Actually a vfsop, not a vnode op)
1090 */
1091nfs_statfs(mp, sbp)
1092 struct mount *mp;
1093 register struct statfs *sbp;
1094{
13576453 1095 register struct vnode *vp;
9238aa59 1096 register struct nfsv2_statfs *sfp;
13576453
KM
1097 register caddr_t cp;
1098 register long t1;
1099 caddr_t bpos, dpos, cp2;
1100 u_long xid;
1101 int error = 0;
1102 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
9238aa59 1103 struct nfsmount *nmp;
a2907882
KM
1104 struct ucred *cred;
1105 struct nfsnode *np;
a2907882
KM
1106
1107 nmp = vfs_to_nfs(mp);
1108 if (error = nfs_nget(mp, &nmp->nm_fh, &np))
1109 return (error);
1110 vp = NFSTOV(np);
1111 nfsstats.rpccnt[NFSPROC_STATFS]++;
1112 cred = crget();
1113 cred->cr_ngroups = 1;
1114 nfsm_reqhead(nfs_procids[NFSPROC_STATFS], cred, NFSX_FH);
1115 nfsm_fhtom(vp);
1116 nfsm_request(vp);
9238aa59 1117 nfsm_disect(sfp, struct nfsv2_statfs *, NFSX_STATFS);
a2907882 1118 sbp->f_type = MOUNT_NFS;
e8540f59 1119 sbp->f_flags = nmp->nm_flag;
9238aa59
RM
1120 sbp->f_bsize = fxdr_unsigned(long, sfp->sf_tsize);
1121 sbp->f_fsize = fxdr_unsigned(long, sfp->sf_bsize);
1122 sbp->f_blocks = fxdr_unsigned(long, sfp->sf_blocks);
1123 sbp->f_bfree = fxdr_unsigned(long, sfp->sf_bfree);
1124 sbp->f_bavail = fxdr_unsigned(long, sfp->sf_bavail);
0b9c4686
KM
1125 sbp->f_files = 0;
1126 sbp->f_ffree = 0;
e8540f59
KM
1127 sbp->f_fsid.val[0] = mp->m_fsid.val[0];
1128 sbp->f_fsid.val[1] = mp->m_fsid.val[1];
a2907882
KM
1129 bcopy(nmp->nm_path, sbp->f_mntonname, MNAMELEN);
1130 bcopy(nmp->nm_host, sbp->f_mntfromname, MNAMELEN);
1131 nfsm_reqdone;
1132 nfs_nput(vp);
1133 crfree(cred);
1134 return (error);
1135}
1136
13576453 1137static char hextoasc[] = "0123456789abcdef";
a2907882
KM
1138
1139/*
1140 * Silly rename. To make the NFS filesystem that is stateless look a little
1141 * more like the "ufs" a remove of an active vnode is translated to a rename
1142 * to a funny looking filename that is removed by nfs_inactive on the
1143 * nfsnode. There is the potential for another process on a different client
1144 * to create the same funny name between the nfs_lookitup() fails and the
1145 * nfs_rename() completes, but...
1146 */
1147nfs_sillyrename(ndp, flag)
13576453 1148 register struct nameidata *ndp;
a2907882
KM
1149 int flag;
1150{
1151 register struct nfsnode *np;
1152 register struct sillyrename *sp;
1153 register struct nameidata *tndp;
1154 int error;
1155 short pid;
1156
1157 np = VTONFS(ndp->ni_dvp);
ffe6f482 1158 cache_purge(ndp->ni_dvp);
a2907882 1159 MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename),
9238aa59 1160 M_TEMP, M_WAITOK);
a2907882
KM
1161 sp->s_flag = flag;
1162 bcopy((caddr_t)&np->n_fh, (caddr_t)&sp->s_fh, NFSX_FH);
1163 np = VTONFS(ndp->ni_vp);
1164 tndp = &sp->s_namei;
1165 tndp->ni_cred = crdup(ndp->ni_cred);
1166
1167 /* Fudge together a funny name */
1168 pid = u.u_procp->p_pid;
1169 bcopy(".nfsAxxxx4.4", tndp->ni_dent.d_name, 13);
1170 tndp->ni_dent.d_namlen = 12;
13576453
KM
1171 tndp->ni_dent.d_name[8] = hextoasc[pid & 0xf];
1172 tndp->ni_dent.d_name[7] = hextoasc[(pid >> 4) & 0xf];
1173 tndp->ni_dent.d_name[6] = hextoasc[(pid >> 8) & 0xf];
1174 tndp->ni_dent.d_name[5] = hextoasc[(pid >> 12) & 0xf];
a2907882
KM
1175
1176 /* Try lookitups until we get one that isn't there */
1177 while (nfs_lookitup(ndp->ni_dvp, tndp, (nfsv2fh_t *)0) == 0) {
1178 tndp->ni_dent.d_name[4]++;
1179 if (tndp->ni_dent.d_name[4] > 'z') {
1180 error = EINVAL;
1181 goto bad;
1182 }
1183 }
1184 if (error = nfs_renameit(ndp, tndp))
1185 goto bad;
1186 nfs_lookitup(ndp->ni_dvp, tndp, &np->n_fh);
1187 np->n_sillyrename = sp;
1188 return (0);
1189bad:
9238aa59 1190 crfree(tndp->ni_cred);
a2907882
KM
1191 free((caddr_t)sp, M_TEMP);
1192 return (error);
1193}
1194
1195/*
1196 * Look up a file name for silly rename stuff.
1197 * Just like nfs_lookup() except that it doesn't load returned values
1198 * into the nfsnode table.
1199 * If fhp != NULL it copies the returned file handle out
1200 */
1201nfs_lookitup(vp, ndp, fhp)
1202 register struct vnode *vp;
1203 register struct nameidata *ndp;
1204 nfsv2fh_t *fhp;
1205{
13576453
KM
1206 register u_long *p;
1207 register caddr_t cp;
1208 register long t1, t2;
1209 caddr_t bpos, dpos, cp2;
1210 u_long xid;
1211 int error = 0;
1212 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
a2907882
KM
1213 long len;
1214
1215 nfsstats.rpccnt[NFSPROC_LOOKUP]++;
1216 ndp->ni_dvp = vp;
1217 ndp->ni_vp = NULL;
1218 len = ndp->ni_dent.d_namlen;
1219 nfsm_reqhead(nfs_procids[NFSPROC_LOOKUP], ndp->ni_cred, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len));
1220 nfsm_fhtom(vp);
1221 nfsm_strtom(ndp->ni_dent.d_name, len, NFS_MAXNAMLEN);
1222 nfsm_request(vp);
1223 if (fhp != NULL) {
1224 nfsm_disect(cp, caddr_t, NFSX_FH);
1225 bcopy(cp, (caddr_t)fhp, NFSX_FH);
1226 }
1227 nfsm_reqdone;
1228 return (error);
1229}
1230
1231/*
1232 * Kludge City..
1233 * - make nfs_bmap() essentially a no-op that does no translation
1234 * - do nfs_strategy() by faking physical I/O with nfs_readit/nfs_writeit
1235 * after mapping the physical addresses into Kernel Virtual space in the
1236 * nfsiobuf area.
1237 * (Maybe I could use the process's page mapping, but I was concerned that
1238 * Kernel Write might not be enabled and also figured copyout() would do
1239 * a lot more work than bcopy() and also it currently happens in the
1240 * context of the swapper process (2).
1241 */
1242nfs_bmap(vp, bn, vpp, bnp)
1243 struct vnode *vp;
1244 daddr_t bn;
1245 struct vnode **vpp;
1246 daddr_t *bnp;
1247{
1248 if (vpp != NULL)
1249 *vpp = vp;
1250 if (bnp != NULL)
1251 *bnp = bn * btodb(vp->v_mount->m_bsize);
1252 return (0);
1253}
1254
1255/*
9238aa59
RM
1256 * Strategy routine for phys. i/o
1257 * If the biod's are running, queue a request
1258 * otherwise just call nfs_doio() to get it done
a2907882
KM
1259 */
1260nfs_strategy(bp)
1261 register struct buf *bp;
9238aa59
RM
1262{
1263 register struct buf *dp;
ffe6f482 1264 register int i;
9238aa59
RM
1265 struct proc *rp;
1266 int error = 0;
ffe6f482 1267 int fnd = 0;
9238aa59
RM
1268
1269 /*
1270 * If an i/o daemon is waiting
1271 * queue the request, wake it up and wait for completion
1272 * otherwise just do it ourselves
1273 */
ffe6f482
KM
1274 for (i = 0; i < nfs_asyncdaemons; i++) {
1275 if (rp = nfs_iodwant[i]) {
1276 /*
1277 * Ensure that the async_daemon is still waiting here
1278 */
1279 if (rp->p_stat != SSLEEP ||
1280 rp->p_wchan != ((caddr_t)&nfs_iodwant[i])) {
1281 nfs_iodwant[i] = (struct proc *)0;
1282 continue;
1283 }
1284 dp = &nfs_bqueue;
1285 if (dp->b_actf == NULL) {
1286 dp->b_actl = bp;
1287 bp->b_actf = dp;
1288 } else {
1289 dp->b_actf->b_actl = bp;
1290 bp->b_actf = dp->b_actf;
1291 }
1292 dp->b_actf = bp;
1293 bp->b_actl = dp;
1294 fnd++;
1295 nfs_iodwant[i] = (struct proc *)0;
1296 wakeup((caddr_t)&nfs_iodwant[i]);
1297 break;
9238aa59 1298 }
ffe6f482
KM
1299 }
1300 if (!fnd)
9238aa59
RM
1301 error = nfs_doio(bp);
1302 return (error);
1303}
1304
1305/*
1306 * Fun and games with i/o
1307 * Essentially play ubasetup() and disk interrupt service routine by
1308 * mapping the data buffer into kernel virtual space and doing the
1309 * nfs read or write rpc's from it.
1310 * If the biod's are not running, this is just called from nfs_strategy(),
1311 * otherwise it is called by the biod's to do what would normally be
1312 * partially disk interrupt driven.
1313 */
1314nfs_doio(bp)
1315 register struct buf *bp;
a2907882
KM
1316{
1317 register struct pte *pte, *ppte;
1318 register caddr_t vaddr;
1319 register struct uio *uiop;
a2907882 1320 register struct vnode *vp;
ffe6f482 1321 struct nfsnode *np;
9238aa59
RM
1322 struct ucred *cr;
1323 int npf, npf2;
1324 int reg;
1325 caddr_t vbase;
a2907882
KM
1326 unsigned v;
1327 struct proc *rp;
1328 int o, error;
a2907882
KM
1329 struct uio uio;
1330 struct iovec io;
1331
1332 vp = bp->b_vp;
a2907882
KM
1333 uiop = &uio;
1334 uiop->uio_iov = &io;
1335 uiop->uio_iovcnt = 1;
a2907882 1336 uiop->uio_segflg = UIO_SYSSPACE;
e8540f59 1337
a2907882 1338 /*
9238aa59
RM
1339 * For phys i/o, map the b_addr into kernel virtual space using
1340 * the Nfsiomap pte's
1341 * Also, add a temporary b_rcred for reading using the process's uid
1342 * and a guess at a group
a2907882 1343 */
9238aa59 1344 if (bp->b_flags & B_PHYS) {
ffe6f482 1345 VTONFS(vp)->n_flag |= NPAGEDON;
9238aa59
RM
1346 bp->b_rcred = cr = crget();
1347 rp = (bp->b_flags & B_DIRTY) ? &proc[2] : bp->b_proc;
1348 cr->cr_uid = rp->p_uid;
1349 cr->cr_gid = 0; /* Anything ?? */
1350 cr->cr_ngroups = 1;
e8540f59
KM
1351 o = (int)bp->b_un.b_addr & PGOFSET;
1352 npf2 = npf = btoc(bp->b_bcount + o);
1353
9238aa59
RM
1354 /*
1355 * Get some mapping page table entries
1356 */
1357 while ((reg = rmalloc(nfsmap, (long)npf)) == 0) {
1358 nfsmap_want++;
1359 sleep((caddr_t)&nfsmap_want, PZERO-1);
1360 }
1361 reg--;
e8540f59
KM
1362 if (bp->b_flags & B_PAGET)
1363 pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)];
9238aa59 1364 else {
e8540f59 1365 v = btop(bp->b_un.b_addr);
9238aa59
RM
1366 if (bp->b_flags & B_UAREA)
1367 pte = &rp->p_addr[v];
1368 else
1369 pte = vtopte(rp, v);
1370 }
e8540f59 1371
9238aa59
RM
1372 /*
1373 * Play vmaccess() but with the Nfsiomap page table
1374 */
1375 ppte = &Nfsiomap[reg];
1376 vbase = vaddr = &nfsiobuf[reg*NBPG];
1377 while (npf != 0) {
1378 mapin(ppte, (u_int)vaddr, pte->pg_pfnum, (int)(PG_V|PG_KW));
a2907882 1379#if defined(tahoe)
9238aa59 1380 mtpr(P1DC, vaddr);
a2907882 1381#endif
9238aa59
RM
1382 ppte++;
1383 pte++;
1384 vaddr += NBPG;
1385 --npf;
1386 }
e8540f59
KM
1387
1388 /*
1389 * And do the i/o rpc
1390 */
9238aa59 1391 io.iov_base = vbase+o;
e8540f59
KM
1392 io.iov_len = uiop->uio_resid = bp->b_bcount;
1393 uiop->uio_offset = bp->b_lblkno * DEV_BSIZE;
1394 if (bp->b_flags & B_READ) {
1395 uiop->uio_rw = UIO_READ;
1396 nfsstats.read_physios++;
1397 bp->b_error = error = nfs_readrpc(vp, uiop, bp->b_rcred);
1398 } else {
1399 uiop->uio_rw = UIO_WRITE;
1400 nfsstats.write_physios++;
1401 bp->b_error = error = nfs_writerpc(vp, uiop, bp->b_wcred);
ffe6f482 1402 }
e8540f59
KM
1403
1404 /*
1405 * Finally, release pte's used by physical i/o
1406 */
9238aa59
RM
1407 crfree(cr);
1408 rmfree(nfsmap, (long)npf2, (long)++reg);
1409 if (nfsmap_want) {
1410 nfsmap_want = 0;
1411 wakeup((caddr_t)&nfsmap_want);
1412 }
e8540f59
KM
1413 } else {
1414 if (bp->b_flags & B_READ) {
1415 io.iov_len = uiop->uio_resid = bp->b_bcount;
1416 uiop->uio_offset = bp->b_lblkno * DEV_BSIZE;
1417 io.iov_base = bp->b_un.b_addr;
1418 uiop->uio_rw = UIO_READ;
1419 nfsstats.read_bios++;
1420 bp->b_error = error = nfs_readrpc(vp, uiop, bp->b_rcred);
1421 } else {
1422 io.iov_len = uiop->uio_resid = bp->b_dirtyend
1423 - bp->b_dirtyoff;
1424 uiop->uio_offset = (bp->b_lblkno * DEV_BSIZE)
1425 + bp->b_dirtyoff;
1426 io.iov_base = bp->b_un.b_addr + bp->b_dirtyoff;
1427 uiop->uio_rw = UIO_WRITE;
1428 nfsstats.write_bios++;
1429 bp->b_error = error = nfs_writerpc(vp, uiop, bp->b_wcred);
1430 if (error) {
1431 np = VTONFS(vp);
1432 np->n_error = error;
1433 np->n_flag |= NWRITEERR;
1434 }
1435 bp->b_dirtyoff = bp->b_dirtyend = 0;
1436 }
9238aa59 1437 }
e8540f59
KM
1438 if (error)
1439 bp->b_flags |= B_ERROR;
1440 bp->b_resid = uiop->uio_resid;
a2907882 1441 biodone(bp);
9238aa59
RM
1442 return (error);
1443}
1444
1445/*
1446 * Flush all the blocks associated with a vnode.
1447 * Walk through the buffer pool and push any dirty pages
1448 * associated with the vnode.
1449 */
13576453 1450/* ARGSUSED */
f8428623 1451nfs_fsync(vp, fflags, cred, waitfor)
9238aa59
RM
1452 register struct vnode *vp;
1453 int fflags;
1454 struct ucred *cred;
f8428623 1455 int waitfor;
9238aa59
RM
1456{
1457 register struct nfsnode *np = VTONFS(vp);
e8540f59 1458 int error = 0;
9238aa59 1459
9238aa59
RM
1460 if (np->n_flag & NMODIFIED) {
1461 np->n_flag &= ~NMODIFIED;
e8540f59 1462 vflushbuf(vp, waitfor == MNT_WAIT ? B_SYNC : 0);
9238aa59 1463 }
e8540f59
KM
1464 if (!error && (np->n_flag & NWRITEERR))
1465 error = np->n_error;
a2907882
KM
1466 return (error);
1467}
d002709d
KM
1468
1469/*
1470 * Print out the contents of an nfsnode.
1471 */
1472nfs_print(vp)
1473 struct vnode *vp;
1474{
1475 register struct nfsnode *np = VTONFS(vp);
1476
1477 printf("tag VT_NFS, fileid %d fsid 0x%x%s\n",
1478 np->n_vattr.va_fileid, np->n_vattr.va_fsid,
1479 (np->n_flag & NLOCKED) ? " (LOCKED)" : "");
1480}