This source file includes following definitions.
- nfs_null
- nfs_access
- nfs_open
- nfs_close
- nfs_getattr
- nfs_setattr
- nfs_setattrrpc
- nfs_lookup
- nfs_read
- nfs_readlink
- nfs_readlinkrpc
- nfs_readrpc
- nfs_writerpc
- nfs_mknodrpc
- nfs_mknod
- nfs_create
- nfs_remove
- nfs_removeit
- nfs_removerpc
- nfs_rename
- nfs_renameit
- nfs_renamerpc
- nfs_link
- nfs_symlink
- nfs_mkdir
- nfs_rmdir
- nfs_readdir
- nfs_readdirrpc
- nfs_readdirplusrpc
- nfs_sillyrename
- nfs_lookitup
- nfs_commit
- nfs_bmap
- nfs_strategy
- nfs_fsync
- nfs_flush
- nfs_pathconf
- nfs_advlock
- nfs_print
- nfs_bwrite
- nfs_writebp
- nfsspec_access
- nfs_poll
- nfsspec_read
- nfsspec_write
- nfsspec_close
- nfsfifo_read
- nfsfifo_write
- nfsfifo_close
- nfsfifo_reclaim
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 #include <sys/param.h>
44 #include <sys/proc.h>
45 #include <sys/kernel.h>
46 #include <sys/systm.h>
47 #include <sys/resourcevar.h>
48 #include <sys/poll.h>
49 #include <sys/proc.h>
50 #include <sys/mount.h>
51 #include <sys/buf.h>
52 #include <sys/malloc.h>
53 #include <sys/pool.h>
54 #include <sys/mbuf.h>
55 #include <sys/conf.h>
56 #include <sys/namei.h>
57 #include <sys/vnode.h>
58 #include <sys/dirent.h>
59 #include <sys/fcntl.h>
60 #include <sys/lockf.h>
61 #include <sys/hash.h>
62
63 #include <uvm/uvm_extern.h>
64
65 #include <miscfs/specfs/specdev.h>
66 #include <miscfs/fifofs/fifo.h>
67
68 #include <nfs/rpcv2.h>
69 #include <nfs/nfsproto.h>
70 #include <nfs/nfs.h>
71 #include <nfs/nfsnode.h>
72 #include <nfs/nfsmount.h>
73 #include <nfs/xdr_subs.h>
74 #include <nfs/nfsm_subs.h>
75 #include <nfs/nfs_var.h>
76
77 #include <net/if.h>
78 #include <netinet/in.h>
79 #include <netinet/in_var.h>
80
81
82 #define TRUE 1
83 #define FALSE 0
84
85
86
87
88 int (**nfsv2_vnodeop_p)(void *);
89 struct vnodeopv_entry_desc nfsv2_vnodeop_entries[] = {
90 { &vop_default_desc, vn_default_error },
91 { &vop_lookup_desc, nfs_lookup },
92 { &vop_create_desc, nfs_create },
93 { &vop_mknod_desc, nfs_mknod },
94 { &vop_open_desc, nfs_open },
95 { &vop_close_desc, nfs_close },
96 { &vop_access_desc, nfs_access },
97 { &vop_getattr_desc, nfs_getattr },
98 { &vop_setattr_desc, nfs_setattr },
99 { &vop_read_desc, nfs_read },
100 { &vop_write_desc, nfs_write },
101 { &vop_ioctl_desc, nfs_ioctl },
102 { &vop_poll_desc, nfs_poll },
103 { &vop_kqfilter_desc, nfs_kqfilter },
104 { &vop_revoke_desc, nfs_revoke },
105 { &vop_fsync_desc, nfs_fsync },
106 { &vop_remove_desc, nfs_remove },
107 { &vop_link_desc, nfs_link },
108 { &vop_rename_desc, nfs_rename },
109 { &vop_mkdir_desc, nfs_mkdir },
110 { &vop_rmdir_desc, nfs_rmdir },
111 { &vop_symlink_desc, nfs_symlink },
112 { &vop_readdir_desc, nfs_readdir },
113 { &vop_readlink_desc, nfs_readlink },
114 { &vop_abortop_desc, vop_generic_abortop },
115 { &vop_inactive_desc, nfs_inactive },
116 { &vop_reclaim_desc, nfs_reclaim },
117 { &vop_lock_desc, nfs_lock },
118 { &vop_unlock_desc, nfs_unlock },
119 { &vop_bmap_desc, nfs_bmap },
120 { &vop_strategy_desc, nfs_strategy },
121 { &vop_print_desc, nfs_print },
122 { &vop_islocked_desc, nfs_islocked },
123 { &vop_pathconf_desc, nfs_pathconf },
124 { &vop_advlock_desc, nfs_advlock },
125 { &vop_bwrite_desc, nfs_bwrite },
126 { NULL, NULL }
127 };
128 struct vnodeopv_desc nfsv2_vnodeop_opv_desc =
129 { &nfsv2_vnodeop_p, nfsv2_vnodeop_entries };
130
131
132
133
134 int (**spec_nfsv2nodeop_p)(void *);
135 struct vnodeopv_entry_desc spec_nfsv2nodeop_entries[] = {
136 { &vop_default_desc, spec_vnoperate },
137 { &vop_close_desc, nfsspec_close },
138 { &vop_access_desc, nfsspec_access },
139 { &vop_getattr_desc, nfs_getattr },
140 { &vop_setattr_desc, nfs_setattr },
141 { &vop_read_desc, nfsspec_read },
142 { &vop_write_desc, nfsspec_write },
143 { &vop_fsync_desc, nfs_fsync },
144 { &vop_inactive_desc, nfs_inactive },
145 { &vop_reclaim_desc, nfs_reclaim },
146 { &vop_lock_desc, nfs_lock },
147 { &vop_unlock_desc, nfs_unlock },
148 { &vop_print_desc, nfs_print },
149 { &vop_islocked_desc, nfs_islocked },
150 { NULL, NULL }
151 };
152 struct vnodeopv_desc spec_nfsv2nodeop_opv_desc =
153 { &spec_nfsv2nodeop_p, spec_nfsv2nodeop_entries };
154
155 #ifdef FIFO
156 int (**fifo_nfsv2nodeop_p)(void *);
157 struct vnodeopv_entry_desc fifo_nfsv2nodeop_entries[] = {
158 { &vop_default_desc, fifo_vnoperate },
159 { &vop_close_desc, nfsfifo_close },
160 { &vop_access_desc, nfsspec_access },
161 { &vop_getattr_desc, nfs_getattr },
162 { &vop_setattr_desc, nfs_setattr },
163 { &vop_read_desc, nfsfifo_read },
164 { &vop_write_desc, nfsfifo_write },
165 { &vop_fsync_desc, nfs_fsync },
166 { &vop_inactive_desc, nfs_inactive },
167 { &vop_reclaim_desc, nfsfifo_reclaim },
168 { &vop_lock_desc, nfs_lock },
169 { &vop_unlock_desc, nfs_unlock },
170 { &vop_print_desc, nfs_print },
171 { &vop_islocked_desc, nfs_islocked },
172 { &vop_bwrite_desc, vop_generic_bwrite },
173 { NULL, NULL }
174 };
175 struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc =
176 { &fifo_nfsv2nodeop_p, fifo_nfsv2nodeop_entries };
177 #endif
178
179
180
181
182 extern u_int32_t nfs_true, nfs_false;
183 extern u_int32_t nfs_xdrneg1;
184 extern struct nfsstats nfsstats;
185 extern nfstype nfsv3_type[9];
186 struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
187 int nfs_numasync = 0;
188
189
190
191
192 int
193 nfs_null(vp, cred, procp)
194 struct vnode *vp;
195 struct ucred *cred;
196 struct proc *procp;
197 {
198 caddr_t bpos, dpos;
199 int error = 0;
200 struct mbuf *mreq, *mrep, *md, *mb;
201
202 nfsm_reqhead(vp, NFSPROC_NULL, 0);
203 nfsm_request(vp, NFSPROC_NULL, procp, cred);
204 nfsm_reqdone;
205 return (error);
206 }
207
208
209
210
211
212
213
214 int
215 nfs_access(v)
216 void *v;
217 {
218 struct vop_access_args *ap = v;
219 struct vnode *vp = ap->a_vp;
220 u_int32_t *tl;
221 caddr_t cp;
222 int32_t t1, t2;
223 caddr_t bpos, dpos, cp2;
224 int error = 0, attrflag;
225 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
226 u_int32_t mode, rmode;
227 int v3 = NFS_ISV3(vp);
228
229
230
231
232
233
234 if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
235 switch (vp->v_type) {
236 case VREG:
237 case VDIR:
238 case VLNK:
239 return (EROFS);
240 default:
241 break;
242 }
243 }
244
245
246
247
248
249
250
251
252 if (v3) {
253 nfsstats.rpccnt[NFSPROC_ACCESS]++;
254 nfsm_reqhead(vp, NFSPROC_ACCESS, NFSX_FH(v3) + NFSX_UNSIGNED);
255 nfsm_fhtom(vp, v3);
256 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
257 if (ap->a_mode & VREAD)
258 mode = NFSV3ACCESS_READ;
259 else
260 mode = 0;
261 if (vp->v_type == VDIR) {
262 if (ap->a_mode & VWRITE)
263 mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
264 NFSV3ACCESS_DELETE);
265 if (ap->a_mode & VEXEC)
266 mode |= NFSV3ACCESS_LOOKUP;
267 } else {
268 if (ap->a_mode & VWRITE)
269 mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
270 if (ap->a_mode & VEXEC)
271 mode |= NFSV3ACCESS_EXECUTE;
272 }
273 *tl = txdr_unsigned(mode);
274 nfsm_request(vp, NFSPROC_ACCESS, ap->a_p, ap->a_cred);
275 nfsm_postop_attr(vp, attrflag);
276 if (!error) {
277 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
278 rmode = fxdr_unsigned(u_int32_t, *tl);
279
280
281
282
283
284 if ((rmode & mode) != mode)
285 error = EACCES;
286 }
287 nfsm_reqdone;
288 return (error);
289 } else
290 return (nfsspec_access(ap));
291 }
292
293
294
295
296
297
298
299
300
301 int
302 nfs_open(v)
303 void *v;
304 {
305 struct vop_open_args *ap = v;
306 struct vnode *vp = ap->a_vp;
307 struct nfsnode *np = VTONFS(vp);
308 struct vattr vattr;
309 int error;
310
311 if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) {
312 #ifdef DIAGNOSTIC
313 printf("open eacces vtyp=%d\n",vp->v_type);
314 #endif
315 return (EACCES);
316 }
317
318
319
320
321
322
323 if (ap->a_mode & FREAD) {
324 if (np->n_rcred) {
325 crfree(np->n_rcred);
326 }
327 np->n_rcred = ap->a_cred;
328 crhold(np->n_rcred);
329 }
330 if (ap->a_mode & FWRITE) {
331 if (np->n_wcred) {
332 crfree(np->n_wcred);
333 }
334 np->n_wcred = ap->a_cred;
335 crhold(np->n_wcred);
336 }
337
338 if (np->n_flag & NMODIFIED) {
339 if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
340 ap->a_p, 1)) == EINTR)
341 return (error);
342 uvm_vnp_uncache(vp);
343 np->n_attrstamp = 0;
344 if (vp->v_type == VDIR)
345 np->n_direofoffset = 0;
346 error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p);
347 if (error)
348 return (error);
349 np->n_mtime = vattr.va_mtime.tv_sec;
350 } else {
351 error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p);
352 if (error)
353 return (error);
354 if (np->n_mtime != vattr.va_mtime.tv_sec) {
355 if (vp->v_type == VDIR)
356 np->n_direofoffset = 0;
357 if ((error = nfs_vinvalbuf(vp, V_SAVE,
358 ap->a_cred, ap->a_p, 1)) == EINTR)
359 return (error);
360 uvm_vnp_uncache(vp);
361 np->n_mtime = vattr.va_mtime.tv_sec;
362 }
363 }
364 np->n_attrstamp = 0;
365 return (0);
366 }
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396 int
397 nfs_close(v)
398 void *v;
399 {
400 struct vop_close_args *ap = v;
401 struct vnode *vp = ap->a_vp;
402 struct nfsnode *np = VTONFS(vp);
403 int error = 0;
404
405 if (vp->v_type == VREG) {
406 if (np->n_flag & NMODIFIED) {
407 if (NFS_ISV3(vp)) {
408 error = nfs_flush(vp, ap->a_cred, MNT_WAIT, ap->a_p, 0);
409 np->n_flag &= ~NMODIFIED;
410 } else
411 error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 1);
412 np->n_attrstamp = 0;
413 }
414 if (np->n_flag & NWRITEERR) {
415 np->n_flag &= ~NWRITEERR;
416 error = np->n_error;
417 }
418 }
419 return (error);
420 }
421
422
423
424
425 int
426 nfs_getattr(v)
427 void *v;
428 {
429 struct vop_getattr_args *ap = v;
430 struct vnode *vp = ap->a_vp;
431 struct nfsnode *np = VTONFS(vp);
432 caddr_t cp;
433 u_int32_t *tl;
434 int32_t t1, t2;
435 caddr_t bpos, dpos;
436 int error = 0;
437 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
438 int v3 = NFS_ISV3(vp);
439
440
441
442
443 if (np->n_flag & (NACC | NUPD))
444 np->n_flag |= NCHG;
445
446
447
448 if (nfs_getattrcache(vp, ap->a_vap) == 0)
449 return (0);
450 nfsstats.rpccnt[NFSPROC_GETATTR]++;
451 nfsm_reqhead(vp, NFSPROC_GETATTR, NFSX_FH(v3));
452 nfsm_fhtom(vp, v3);
453 nfsm_request(vp, NFSPROC_GETATTR, ap->a_p, ap->a_cred);
454 if (!error)
455 nfsm_loadattr(vp, ap->a_vap);
456 nfsm_reqdone;
457 return (error);
458 }
459
460
461
462
463 int
464 nfs_setattr(v)
465 void *v;
466 {
467 struct vop_setattr_args *ap = v;
468 struct vnode *vp = ap->a_vp;
469 struct nfsnode *np = VTONFS(vp);
470 struct vattr *vap = ap->a_vap;
471 int error = 0;
472 u_quad_t tsize = 0;
473
474
475
476
477 if (vap->va_flags != VNOVAL)
478 return (EOPNOTSUPP);
479
480
481
482
483 if ((vap->va_uid != (uid_t)VNOVAL ||
484 vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
485 vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) &&
486 (vp->v_mount->mnt_flag & MNT_RDONLY))
487 return (EROFS);
488 if (vap->va_size != VNOVAL) {
489 switch (vp->v_type) {
490 case VDIR:
491 return (EISDIR);
492 case VCHR:
493 case VBLK:
494 case VSOCK:
495 case VFIFO:
496 if (vap->va_mtime.tv_sec == VNOVAL &&
497 vap->va_atime.tv_sec == VNOVAL &&
498 vap->va_mode == (mode_t)VNOVAL &&
499 vap->va_uid == (uid_t)VNOVAL &&
500 vap->va_gid == (gid_t)VNOVAL)
501 return (0);
502 vap->va_size = VNOVAL;
503 break;
504 default:
505
506
507
508
509 if (vp->v_mount->mnt_flag & MNT_RDONLY)
510 return (EROFS);
511 if (vap->va_size == 0)
512 error = nfs_vinvalbuf(vp, 0,
513 ap->a_cred, ap->a_p, 1);
514 else
515 error = nfs_vinvalbuf(vp, V_SAVE,
516 ap->a_cred, ap->a_p, 1);
517 if (error)
518 return (error);
519 tsize = np->n_size;
520 np->n_size = np->n_vattr.va_size = vap->va_size;
521 uvm_vnp_setsize(vp, np->n_size);
522 };
523 } else if ((vap->va_mtime.tv_sec != VNOVAL ||
524 vap->va_atime.tv_sec != VNOVAL) &&
525 vp->v_type == VREG &&
526 (error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
527 ap->a_p, 1)) == EINTR)
528 return (error);
529 error = nfs_setattrrpc(vp, vap, ap->a_cred, ap->a_p);
530 if (error && vap->va_size != VNOVAL) {
531 np->n_size = np->n_vattr.va_size = tsize;
532 uvm_vnp_setsize(vp, np->n_size);
533 }
534
535 VN_KNOTE(vp, NOTE_ATTRIB);
536
537 return (error);
538 }
539
540
541
542
543 int
544 nfs_setattrrpc(vp, vap, cred, procp)
545 struct vnode *vp;
546 struct vattr *vap;
547 struct ucred *cred;
548 struct proc *procp;
549 {
550 struct nfsv2_sattr *sp;
551 caddr_t cp;
552 int32_t t1, t2;
553 caddr_t bpos, dpos, cp2;
554 u_int32_t *tl;
555 int error = 0, wccflag = NFSV3_WCCRATTR;
556 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
557 int v3 = NFS_ISV3(vp);
558
559 nfsstats.rpccnt[NFSPROC_SETATTR]++;
560 nfsm_reqhead(vp, NFSPROC_SETATTR, NFSX_FH(v3) + NFSX_SATTR(v3));
561 nfsm_fhtom(vp, v3);
562 if (v3) {
563 nfsm_v3attrbuild(vap, TRUE);
564 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
565 *tl = nfs_false;
566 } else {
567 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
568 if (vap->va_mode == (mode_t)VNOVAL)
569 sp->sa_mode = nfs_xdrneg1;
570 else
571 sp->sa_mode = vtonfsv2_mode(vp->v_type, vap->va_mode);
572 if (vap->va_uid == (uid_t)VNOVAL)
573 sp->sa_uid = nfs_xdrneg1;
574 else
575 sp->sa_uid = txdr_unsigned(vap->va_uid);
576 if (vap->va_gid == (gid_t)VNOVAL)
577 sp->sa_gid = nfs_xdrneg1;
578 else
579 sp->sa_gid = txdr_unsigned(vap->va_gid);
580 sp->sa_size = txdr_unsigned(vap->va_size);
581 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
582 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
583 }
584 nfsm_request(vp, NFSPROC_SETATTR, procp, cred);
585 if (v3) {
586 nfsm_wcc_data(vp, wccflag);
587 } else
588 nfsm_loadattr(vp, (struct vattr *)0);
589 nfsm_reqdone;
590 return (error);
591 }
592
593
594
595
596
597
598 int
599 nfs_lookup(v)
600 void *v;
601 {
602 struct vop_lookup_args *ap = v;
603 struct componentname *cnp = ap->a_cnp;
604 struct vnode *dvp = ap->a_dvp;
605 struct vnode **vpp = ap->a_vpp;
606 struct proc *p = cnp->cn_proc;
607 int flags;
608 struct vnode *newvp;
609 u_int32_t *tl;
610 caddr_t cp;
611 int32_t t1, t2;
612 struct nfsmount *nmp;
613 caddr_t bpos, dpos, cp2;
614 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
615 long len;
616 nfsfh_t *fhp;
617 struct nfsnode *np;
618 int lockparent, wantparent, error = 0, attrflag, fhsize;
619 int v3 = NFS_ISV3(dvp);
620
621 cnp->cn_flags &= ~PDIRUNLOCK;
622 flags = cnp->cn_flags;
623
624 *vpp = NULLVP;
625 if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
626 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
627 return (EROFS);
628 if (dvp->v_type != VDIR)
629 return (ENOTDIR);
630 lockparent = flags & LOCKPARENT;
631 wantparent = flags & (LOCKPARENT|WANTPARENT);
632 nmp = VFSTONFS(dvp->v_mount);
633 np = VTONFS(dvp);
634
635
636
637
638
639
640
641
642
643
644 if ((error = cache_lookup(dvp, vpp, cnp)) >= 0) {
645 struct vattr vattr;
646 int err2;
647
648 if (error && error != ENOENT) {
649 *vpp = NULLVP;
650 return (error);
651 }
652
653 if (cnp->cn_flags & PDIRUNLOCK) {
654 err2 = vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p);
655 if (err2 != 0) {
656 *vpp = NULLVP;
657 return (err2);
658 }
659 cnp->cn_flags &= ~PDIRUNLOCK;
660 }
661
662 err2 = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, cnp->cn_proc);
663 if (err2 != 0) {
664 if (error == 0) {
665 if (*vpp != dvp)
666 vput(*vpp);
667 else
668 vrele(*vpp);
669 }
670 *vpp = NULLVP;
671 return (err2);
672 }
673
674 if (error == ENOENT) {
675 if (!VOP_GETATTR(dvp, &vattr, cnp->cn_cred,
676 cnp->cn_proc) && vattr.va_mtime.tv_sec ==
677 VTONFS(dvp)->n_ctime)
678 return (ENOENT);
679 cache_purge(dvp);
680 np->n_ctime = 0;
681 goto dorpc;
682 }
683
684 newvp = *vpp;
685 if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, cnp->cn_proc)
686 && vattr.va_ctime.tv_sec == VTONFS(newvp)->n_ctime)
687 {
688 nfsstats.lookupcache_hits++;
689 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
690 cnp->cn_flags |= SAVENAME;
691 if ((!lockparent || !(flags & ISLASTCN)) &&
692 newvp != dvp)
693 VOP_UNLOCK(dvp, 0, p);
694 return (0);
695 }
696 cache_purge(newvp);
697 if (newvp != dvp)
698 vput(newvp);
699 else
700 vrele(newvp);
701 *vpp = NULLVP;
702 }
703 dorpc:
704 error = 0;
705 newvp = NULLVP;
706 nfsstats.lookupcache_misses++;
707 nfsstats.rpccnt[NFSPROC_LOOKUP]++;
708 len = cnp->cn_namelen;
709 nfsm_reqhead(dvp, NFSPROC_LOOKUP,
710 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len));
711 nfsm_fhtom(dvp, v3);
712 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
713 nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred);
714 if (error) {
715 nfsm_postop_attr(dvp, attrflag);
716 m_freem(mrep);
717 goto nfsmout;
718 }
719 nfsm_getfh(fhp, fhsize, v3);
720
721
722
723
724 if (cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)) {
725 if (NFS_CMPFH(np, fhp, fhsize)) {
726 m_freem(mrep);
727 return (EISDIR);
728 }
729 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
730 if (error) {
731 m_freem(mrep);
732 return (error);
733 }
734 newvp = NFSTOV(np);
735 if (v3) {
736 nfsm_postop_attr(newvp, attrflag);
737 nfsm_postop_attr(dvp, attrflag);
738 } else
739 nfsm_loadattr(newvp, (struct vattr *)0);
740 *vpp = newvp;
741 m_freem(mrep);
742 cnp->cn_flags |= SAVENAME;
743 if (!lockparent) {
744 VOP_UNLOCK(dvp, 0, p);
745 cnp->cn_flags |= PDIRUNLOCK;
746 }
747 return (0);
748 }
749
750
751
752
753
754
755
756 if (NFS_CMPFH(np, fhp, fhsize)) {
757 VREF(dvp);
758 newvp = dvp;
759 if (v3) {
760 nfsm_postop_attr(newvp, attrflag);
761 nfsm_postop_attr(dvp, attrflag);
762 } else
763 nfsm_loadattr(newvp, (struct vattr *)0);
764 } else if (flags & ISDOTDOT) {
765 VOP_UNLOCK(dvp, 0, p);
766 cnp->cn_flags |= PDIRUNLOCK;
767
768 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
769 if (error) {
770 if (vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p) == 0)
771 cnp->cn_flags &= ~PDIRUNLOCK;
772 m_freem(mrep);
773 return (error);
774 }
775 newvp = NFSTOV(np);
776
777 if (v3) {
778 nfsm_postop_attr(newvp, attrflag);
779 nfsm_postop_attr(dvp, attrflag);
780 } else
781 nfsm_loadattr(newvp, (struct vattr *)0);
782
783 if (lockparent && (flags & ISLASTCN)) {
784 if ((error = vn_lock(dvp, LK_EXCLUSIVE, p))) {
785 m_freem(mrep);
786 vput(newvp);
787 return error;
788 }
789 cnp->cn_flags &= ~PDIRUNLOCK;
790 }
791
792 } else {
793 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
794 if (error) {
795 m_freem(mrep);
796 return error;
797 }
798 newvp = NFSTOV(np);
799 if (v3) {
800 nfsm_postop_attr(newvp, attrflag);
801 nfsm_postop_attr(dvp, attrflag);
802 } else
803 nfsm_loadattr(newvp, (struct vattr *)0);
804 if (!lockparent || !(flags & ISLASTCN)) {
805 VOP_UNLOCK(dvp, 0, p);
806 cnp->cn_flags |= PDIRUNLOCK;
807 }
808 }
809 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
810 cnp->cn_flags |= SAVENAME;
811 if ((cnp->cn_flags & MAKEENTRY) &&
812 (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) {
813 np->n_ctime = np->n_vattr.va_ctime.tv_sec;
814 cache_enter(dvp, newvp, cnp);
815 }
816 *vpp = newvp;
817 nfsm_reqdone;
818 if (error) {
819
820
821
822
823
824
825 if (error == ENOENT && (cnp->cn_flags & MAKEENTRY) &&
826 cnp->cn_nameiop != CREATE) {
827 if (VTONFS(dvp)->n_ctime == 0)
828 VTONFS(dvp)->n_ctime =
829 VTONFS(dvp)->n_vattr.va_mtime.tv_sec;
830 cache_enter(dvp, NULL, cnp);
831 }
832 if (newvp != NULLVP) {
833 vrele(newvp);
834 if (newvp != dvp)
835 VOP_UNLOCK(newvp, 0, p);
836 }
837 if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) &&
838 (flags & ISLASTCN) && error == ENOENT) {
839 if (dvp->v_mount->mnt_flag & MNT_RDONLY)
840 error = EROFS;
841 else
842 error = EJUSTRETURN;
843 }
844 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
845 cnp->cn_flags |= SAVENAME;
846 *vpp = NULL;
847 }
848 return (error);
849 }
850
851
852
853
854
855 int
856 nfs_read(v)
857 void *v;
858 {
859 struct vop_read_args *ap = v;
860 struct vnode *vp = ap->a_vp;
861
862 if (vp->v_type != VREG)
863 return (EPERM);
864 return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred));
865 }
866
867
868
869
870 int
871 nfs_readlink(v)
872 void *v;
873 {
874 struct vop_readlink_args *ap = v;
875 struct vnode *vp = ap->a_vp;
876
877 if (vp->v_type != VLNK)
878 return (EPERM);
879 return (nfs_bioread(vp, ap->a_uio, 0, ap->a_cred));
880 }
881
882
883
884
885
886 int
887 nfs_readlinkrpc(vp, uiop, cred)
888 struct vnode *vp;
889 struct uio *uiop;
890 struct ucred *cred;
891 {
892 u_int32_t *tl;
893 caddr_t cp;
894 int32_t t1, t2;
895 caddr_t bpos, dpos, cp2;
896 int error = 0, len, attrflag;
897 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
898 int v3 = NFS_ISV3(vp);
899
900 nfsstats.rpccnt[NFSPROC_READLINK]++;
901 nfsm_reqhead(vp, NFSPROC_READLINK, NFSX_FH(v3));
902 nfsm_fhtom(vp, v3);
903 nfsm_request(vp, NFSPROC_READLINK, uiop->uio_procp, cred);
904 if (v3)
905 nfsm_postop_attr(vp, attrflag);
906 if (!error) {
907 nfsm_strsiz(len, NFS_MAXPATHLEN);
908 nfsm_mtouio(uiop, len);
909 }
910 nfsm_reqdone;
911 return (error);
912 }
913
914
915
916
917
918 int
919 nfs_readrpc(vp, uiop)
920 struct vnode *vp;
921 struct uio *uiop;
922 {
923 u_int32_t *tl;
924 caddr_t cp;
925 int32_t t1, t2;
926 caddr_t bpos, dpos, cp2;
927 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
928 struct nfsmount *nmp;
929 int error = 0, len, retlen, tsiz, eof, attrflag;
930 int v3 = NFS_ISV3(vp);
931
932 #ifndef nolint
933 eof = 0;
934 #endif
935 nmp = VFSTONFS(vp->v_mount);
936 tsiz = uiop->uio_resid;
937 if (uiop->uio_offset + tsiz > 0xffffffff && !v3)
938 return (EFBIG);
939 while (tsiz > 0) {
940 nfsstats.rpccnt[NFSPROC_READ]++;
941 len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz;
942 nfsm_reqhead(vp, NFSPROC_READ, NFSX_FH(v3) + NFSX_UNSIGNED * 3);
943 nfsm_fhtom(vp, v3);
944 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED * 3);
945 if (v3) {
946 txdr_hyper(uiop->uio_offset, tl);
947 *(tl + 2) = txdr_unsigned(len);
948 } else {
949 *tl++ = txdr_unsigned(uiop->uio_offset);
950 *tl++ = txdr_unsigned(len);
951 *tl = 0;
952 }
953 nfsm_request(vp, NFSPROC_READ, uiop->uio_procp,
954 VTONFS(vp)->n_rcred);
955 if (v3) {
956 nfsm_postop_attr(vp, attrflag);
957 if (error) {
958 m_freem(mrep);
959 goto nfsmout;
960 }
961 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
962 eof = fxdr_unsigned(int, *(tl + 1));
963 } else
964 nfsm_loadattr(vp, (struct vattr *)0);
965 nfsm_strsiz(retlen, nmp->nm_rsize);
966 nfsm_mtouio(uiop, retlen);
967 m_freem(mrep);
968 tsiz -= retlen;
969 if (v3) {
970 if (eof || retlen == 0)
971 tsiz = 0;
972 } else if (retlen < len)
973 tsiz = 0;
974 }
975 nfsmout:
976 return (error);
977 }
978
979
980
981
982 int
983 nfs_writerpc(vp, uiop, iomode, must_commit)
984 struct vnode *vp;
985 struct uio *uiop;
986 int *iomode, *must_commit;
987 {
988 u_int32_t *tl;
989 caddr_t cp;
990 int32_t t1, t2, backup;
991 caddr_t bpos, dpos, cp2;
992 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
993 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
994 int error = 0, len, tsiz, wccflag = NFSV3_WCCRATTR, rlen, commit;
995 int v3 = NFS_ISV3(vp), committed = NFSV3WRITE_FILESYNC;
996
997 #ifndef DIAGNOSTIC
998 if (uiop->uio_iovcnt != 1)
999 panic("nfs: writerpc iovcnt > 1");
1000 #endif
1001 *must_commit = 0;
1002 tsiz = uiop->uio_resid;
1003 if (uiop->uio_offset + tsiz > 0xffffffff && !v3)
1004 return (EFBIG);
1005 while (tsiz > 0) {
1006 nfsstats.rpccnt[NFSPROC_WRITE]++;
1007 len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz;
1008 nfsm_reqhead(vp, NFSPROC_WRITE,
1009 NFSX_FH(v3) + 5 * NFSX_UNSIGNED + nfsm_rndup(len));
1010 nfsm_fhtom(vp, v3);
1011 if (v3) {
1012 nfsm_build(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
1013 txdr_hyper(uiop->uio_offset, tl);
1014 tl += 2;
1015 *tl++ = txdr_unsigned(len);
1016 *tl++ = txdr_unsigned(*iomode);
1017 *tl = txdr_unsigned(len);
1018 } else {
1019 u_int32_t x;
1020
1021 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
1022
1023 x = txdr_unsigned((u_int32_t)uiop->uio_offset);
1024 *tl++ = x;
1025 *tl++ = x;
1026 x = txdr_unsigned(len);
1027 *tl++ = x;
1028 *tl = x;
1029
1030 }
1031 nfsm_uiotom(uiop, len);
1032 nfsm_request(vp, NFSPROC_WRITE, uiop->uio_procp,
1033 VTONFS(vp)->n_wcred);
1034 if (v3) {
1035 wccflag = NFSV3_WCCCHK;
1036 nfsm_wcc_data(vp, wccflag);
1037 if (!error) {
1038 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED
1039 + NFSX_V3WRITEVERF);
1040 rlen = fxdr_unsigned(int, *tl++);
1041 if (rlen == 0) {
1042 error = NFSERR_IO;
1043 break;
1044 } else if (rlen < len) {
1045 backup = len - rlen;
1046 (char *)uiop->uio_iov->iov_base -= backup;
1047 uiop->uio_iov->iov_len += backup;
1048 uiop->uio_offset -= backup;
1049 uiop->uio_resid += backup;
1050 len = rlen;
1051 }
1052 commit = fxdr_unsigned(int, *tl++);
1053
1054
1055
1056
1057
1058 if (committed == NFSV3WRITE_FILESYNC)
1059 committed = commit;
1060 else if (committed == NFSV3WRITE_DATASYNC &&
1061 commit == NFSV3WRITE_UNSTABLE)
1062 committed = commit;
1063 if ((nmp->nm_flag & NFSMNT_HASWRITEVERF) == 0) {
1064 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf,
1065 NFSX_V3WRITEVERF);
1066 nmp->nm_flag |= NFSMNT_HASWRITEVERF;
1067 } else if (bcmp((caddr_t)tl,
1068 (caddr_t)nmp->nm_verf, NFSX_V3WRITEVERF)) {
1069 *must_commit = 1;
1070 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf,
1071 NFSX_V3WRITEVERF);
1072 }
1073 }
1074 } else
1075 nfsm_loadattr(vp, (struct vattr *)0);
1076 if (wccflag)
1077 VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime.tv_sec;
1078 m_freem(mrep);
1079 tsiz -= len;
1080 }
1081 nfsmout:
1082 *iomode = committed;
1083 if (error)
1084 uiop->uio_resid = tsiz;
1085 return (error);
1086 }
1087
1088
1089
1090
1091
1092
1093 int
1094 nfs_mknodrpc(dvp, vpp, cnp, vap)
1095 struct vnode *dvp;
1096 struct vnode **vpp;
1097 struct componentname *cnp;
1098 struct vattr *vap;
1099 {
1100 struct nfsv2_sattr *sp;
1101 u_int32_t *tl;
1102 caddr_t cp;
1103 int32_t t1, t2;
1104 struct vnode *newvp = (struct vnode *)0;
1105 struct nfsnode *np;
1106 char *cp2;
1107 caddr_t bpos, dpos;
1108 int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0;
1109 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1110 u_int32_t rdev;
1111 int v3 = NFS_ISV3(dvp);
1112
1113 if (vap->va_type == VCHR || vap->va_type == VBLK)
1114 rdev = txdr_unsigned(vap->va_rdev);
1115 else if (vap->va_type == VFIFO || vap->va_type == VSOCK)
1116 rdev = nfs_xdrneg1;
1117 else {
1118 VOP_ABORTOP(dvp, cnp);
1119 vput(dvp);
1120 return (EOPNOTSUPP);
1121 }
1122 nfsstats.rpccnt[NFSPROC_MKNOD]++;
1123 nfsm_reqhead(dvp, NFSPROC_MKNOD, NFSX_FH(v3) + 4 * NFSX_UNSIGNED +
1124 + nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3));
1125 nfsm_fhtom(dvp, v3);
1126 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1127 if (v3) {
1128 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
1129 *tl++ = vtonfsv3_type(vap->va_type);
1130 nfsm_v3attrbuild(vap, FALSE);
1131 if (vap->va_type == VCHR || vap->va_type == VBLK) {
1132 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1133 *tl++ = txdr_unsigned(major(vap->va_rdev));
1134 *tl = txdr_unsigned(minor(vap->va_rdev));
1135 }
1136 } else {
1137 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1138 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
1139 sp->sa_uid = nfs_xdrneg1;
1140 sp->sa_gid = nfs_xdrneg1;
1141 sp->sa_size = rdev;
1142 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
1143 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
1144 }
1145 nfsm_request(dvp, NFSPROC_MKNOD, cnp->cn_proc, cnp->cn_cred);
1146 if (!error) {
1147 nfsm_mtofh(dvp, newvp, v3, gotvp);
1148 if (!gotvp) {
1149 if (newvp) {
1150 vrele(newvp);
1151 newvp = (struct vnode *)0;
1152 }
1153 error = nfs_lookitup(dvp, cnp->cn_nameptr,
1154 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc, &np);
1155 if (!error)
1156 newvp = NFSTOV(np);
1157 }
1158 }
1159 if (v3)
1160 nfsm_wcc_data(dvp, wccflag);
1161 nfsm_reqdone;
1162 if (error) {
1163 if (newvp)
1164 vrele(newvp);
1165 } else {
1166 if (cnp->cn_flags & MAKEENTRY)
1167 cache_enter(dvp, newvp, cnp);
1168 *vpp = newvp;
1169 }
1170 pool_put(&namei_pool, cnp->cn_pnbuf);
1171 VTONFS(dvp)->n_flag |= NMODIFIED;
1172 if (!wccflag)
1173 VTONFS(dvp)->n_attrstamp = 0;
1174 vrele(dvp);
1175 return (error);
1176 }
1177
1178
1179
1180
1181
1182
1183 int
1184 nfs_mknod(v)
1185 void *v;
1186 {
1187 struct vop_mknod_args *ap = v;
1188 struct vnode *newvp;
1189 int error;
1190
1191 error = nfs_mknodrpc(ap->a_dvp, &newvp, ap->a_cnp, ap->a_vap);
1192 if (!error)
1193 vrele(newvp);
1194
1195 VN_KNOTE(ap->a_dvp, NOTE_WRITE);
1196
1197 return (error);
1198 }
1199
1200 static u_long create_verf;
1201
1202
1203
1204 int
1205 nfs_create(v)
1206 void *v;
1207 {
1208 struct vop_create_args *ap = v;
1209 struct vnode *dvp = ap->a_dvp;
1210 struct vattr *vap = ap->a_vap;
1211 struct componentname *cnp = ap->a_cnp;
1212 struct nfsv2_sattr *sp;
1213 u_int32_t *tl;
1214 caddr_t cp;
1215 int32_t t1, t2;
1216 struct nfsnode *np = (struct nfsnode *)0;
1217 struct vnode *newvp = (struct vnode *)0;
1218 caddr_t bpos, dpos, cp2;
1219 int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0, fmode = 0;
1220 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1221 int v3 = NFS_ISV3(dvp);
1222
1223
1224
1225
1226 if (vap->va_type == VSOCK)
1227 return (nfs_mknodrpc(dvp, ap->a_vpp, cnp, vap));
1228
1229 #ifdef VA_EXCLUSIVE
1230 if (vap->va_vaflags & VA_EXCLUSIVE)
1231 fmode |= O_EXCL;
1232 #endif
1233 again:
1234 nfsstats.rpccnt[NFSPROC_CREATE]++;
1235 nfsm_reqhead(dvp, NFSPROC_CREATE, NFSX_FH(v3) + 2 * NFSX_UNSIGNED +
1236 nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3));
1237 nfsm_fhtom(dvp, v3);
1238 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1239 if (v3) {
1240 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
1241 if (fmode & O_EXCL) {
1242 *tl = txdr_unsigned(NFSV3CREATE_EXCLUSIVE);
1243 nfsm_build(tl, u_int32_t *, NFSX_V3CREATEVERF);
1244 if (TAILQ_FIRST(&in_ifaddr))
1245 *tl++ = TAILQ_FIRST(&in_ifaddr)->ia_addr.sin_addr.s_addr;
1246 else
1247 *tl++ = create_verf;
1248 *tl = ++create_verf;
1249 } else {
1250 *tl = txdr_unsigned(NFSV3CREATE_UNCHECKED);
1251 nfsm_v3attrbuild(vap, FALSE);
1252 }
1253 } else {
1254 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1255 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
1256 sp->sa_uid = nfs_xdrneg1;
1257 sp->sa_gid = nfs_xdrneg1;
1258 sp->sa_size = 0;
1259 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
1260 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
1261 }
1262 nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred);
1263 if (!error) {
1264 nfsm_mtofh(dvp, newvp, v3, gotvp);
1265 if (!gotvp) {
1266 if (newvp) {
1267 vrele(newvp);
1268 newvp = (struct vnode *)0;
1269 }
1270 error = nfs_lookitup(dvp, cnp->cn_nameptr,
1271 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc, &np);
1272 if (!error)
1273 newvp = NFSTOV(np);
1274 }
1275 }
1276 if (v3)
1277 nfsm_wcc_data(dvp, wccflag);
1278 nfsm_reqdone;
1279 if (error) {
1280 if (v3 && (fmode & O_EXCL) && error == NFSERR_NOTSUPP) {
1281 fmode &= ~O_EXCL;
1282 goto again;
1283 }
1284 if (newvp)
1285 vrele(newvp);
1286 } else if (v3 && (fmode & O_EXCL))
1287 error = nfs_setattrrpc(newvp, vap, cnp->cn_cred, cnp->cn_proc);
1288 if (!error) {
1289 if (cnp->cn_flags & MAKEENTRY)
1290 cache_enter(dvp, newvp, cnp);
1291 *ap->a_vpp = newvp;
1292 }
1293 pool_put(&namei_pool, cnp->cn_pnbuf);
1294 VTONFS(dvp)->n_flag |= NMODIFIED;
1295 if (!wccflag)
1296 VTONFS(dvp)->n_attrstamp = 0;
1297 VN_KNOTE(ap->a_dvp, NOTE_WRITE);
1298 vrele(dvp);
1299 return (error);
1300 }
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313 int
1314 nfs_remove(v)
1315 void *v;
1316 {
1317 struct vop_remove_args *ap = v;
1318 struct vnode *vp = ap->a_vp;
1319 struct vnode *dvp = ap->a_dvp;
1320 struct componentname *cnp = ap->a_cnp;
1321 struct nfsnode *np = VTONFS(vp);
1322 int error = 0;
1323 struct vattr vattr;
1324
1325 #ifndef DIAGNOSTIC
1326 if ((cnp->cn_flags & HASBUF) == 0)
1327 panic("nfs_remove: no name");
1328 if (vp->v_usecount < 1)
1329 panic("nfs_remove: bad v_usecount");
1330 #endif
1331 if (vp->v_type == VDIR)
1332 error = EPERM;
1333 else if (vp->v_usecount == 1 || (np->n_sillyrename &&
1334 VOP_GETATTR(vp, &vattr, cnp->cn_cred, cnp->cn_proc) == 0 &&
1335 vattr.va_nlink > 1)) {
1336
1337
1338
1339
1340
1341
1342
1343 cache_purge(vp);
1344
1345
1346
1347
1348 error = nfs_vinvalbuf(vp, 0, cnp->cn_cred, cnp->cn_proc, 1);
1349
1350 if (error != EINTR)
1351 error = nfs_removerpc(dvp, cnp->cn_nameptr,
1352 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc);
1353
1354
1355
1356
1357
1358
1359 if (error == ENOENT)
1360 error = 0;
1361 } else if (!np->n_sillyrename)
1362 error = nfs_sillyrename(dvp, vp, cnp);
1363 pool_put(&namei_pool, cnp->cn_pnbuf);
1364 np->n_attrstamp = 0;
1365 vrele(dvp);
1366 vrele(vp);
1367
1368 VN_KNOTE(vp, NOTE_DELETE);
1369 VN_KNOTE(dvp, NOTE_WRITE);
1370
1371 return (error);
1372 }
1373
1374
1375
1376
1377 int
1378 nfs_removeit(sp)
1379 struct sillyrename *sp;
1380 {
1381
1382 return (nfs_removerpc(sp->s_dvp, sp->s_name, sp->s_namlen, sp->s_cred,
1383 (struct proc *)0));
1384 }
1385
1386
1387
1388
1389 int
1390 nfs_removerpc(dvp, name, namelen, cred, proc)
1391 struct vnode *dvp;
1392 char *name;
1393 int namelen;
1394 struct ucred *cred;
1395 struct proc *proc;
1396 {
1397 u_int32_t *tl;
1398 caddr_t cp;
1399 int32_t t1, t2;
1400 caddr_t bpos, dpos, cp2;
1401 int error = 0, wccflag = NFSV3_WCCRATTR;
1402 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1403 int v3 = NFS_ISV3(dvp);
1404
1405 nfsstats.rpccnt[NFSPROC_REMOVE]++;
1406 nfsm_reqhead(dvp, NFSPROC_REMOVE,
1407 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(namelen));
1408 nfsm_fhtom(dvp, v3);
1409 nfsm_strtom(name, namelen, NFS_MAXNAMLEN);
1410 nfsm_request(dvp, NFSPROC_REMOVE, proc, cred);
1411 if (v3)
1412 nfsm_wcc_data(dvp, wccflag);
1413 nfsm_reqdone;
1414 VTONFS(dvp)->n_flag |= NMODIFIED;
1415 if (!wccflag)
1416 VTONFS(dvp)->n_attrstamp = 0;
1417 return (error);
1418 }
1419
1420
1421
1422
1423 int
1424 nfs_rename(v)
1425 void *v;
1426 {
1427 struct vop_rename_args *ap = v;
1428 struct vnode *fvp = ap->a_fvp;
1429 struct vnode *tvp = ap->a_tvp;
1430 struct vnode *fdvp = ap->a_fdvp;
1431 struct vnode *tdvp = ap->a_tdvp;
1432 struct componentname *tcnp = ap->a_tcnp;
1433 struct componentname *fcnp = ap->a_fcnp;
1434 int error;
1435
1436 #ifndef DIAGNOSTIC
1437 if ((tcnp->cn_flags & HASBUF) == 0 ||
1438 (fcnp->cn_flags & HASBUF) == 0)
1439 panic("nfs_rename: no name");
1440 #endif
1441
1442 if ((fvp->v_mount != tdvp->v_mount) ||
1443 (tvp && (fvp->v_mount != tvp->v_mount))) {
1444 error = EXDEV;
1445 goto out;
1446 }
1447
1448
1449
1450
1451
1452 if (tvp && tvp->v_usecount > 1 && !VTONFS(tvp)->n_sillyrename &&
1453 tvp->v_type != VDIR && !nfs_sillyrename(tdvp, tvp, tcnp)) {
1454 VN_KNOTE(tvp, NOTE_DELETE);
1455 vrele(tvp);
1456 tvp = NULL;
1457 }
1458
1459 error = nfs_renamerpc(fdvp, fcnp->cn_nameptr, fcnp->cn_namelen,
1460 tdvp, tcnp->cn_nameptr, tcnp->cn_namelen, tcnp->cn_cred,
1461 tcnp->cn_proc);
1462
1463 VN_KNOTE(fdvp, NOTE_WRITE);
1464 VN_KNOTE(tdvp, NOTE_WRITE);
1465
1466 if (fvp->v_type == VDIR) {
1467 if (tvp != NULL && tvp->v_type == VDIR)
1468 cache_purge(tdvp);
1469 cache_purge(fdvp);
1470 }
1471 out:
1472 if (tdvp == tvp)
1473 vrele(tdvp);
1474 else
1475 vput(tdvp);
1476 if (tvp)
1477 vput(tvp);
1478 vrele(fdvp);
1479 vrele(fvp);
1480
1481
1482
1483 if (error == ENOENT)
1484 error = 0;
1485 return (error);
1486 }
1487
1488
1489
1490
1491 int
1492 nfs_renameit(sdvp, scnp, sp)
1493 struct vnode *sdvp;
1494 struct componentname *scnp;
1495 struct sillyrename *sp;
1496 {
1497 return (nfs_renamerpc(sdvp, scnp->cn_nameptr, scnp->cn_namelen,
1498 sdvp, sp->s_name, sp->s_namlen, scnp->cn_cred, scnp->cn_proc));
1499 }
1500
1501
1502
1503
1504 int
1505 nfs_renamerpc(fdvp, fnameptr, fnamelen, tdvp, tnameptr, tnamelen, cred, proc)
1506 struct vnode *fdvp;
1507 char *fnameptr;
1508 int fnamelen;
1509 struct vnode *tdvp;
1510 char *tnameptr;
1511 int tnamelen;
1512 struct ucred *cred;
1513 struct proc *proc;
1514 {
1515 u_int32_t *tl;
1516 caddr_t cp;
1517 int32_t t1, t2;
1518 caddr_t bpos, dpos, cp2;
1519 int error = 0, fwccflag = NFSV3_WCCRATTR, twccflag = NFSV3_WCCRATTR;
1520 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1521 int v3 = NFS_ISV3(fdvp);
1522
1523 nfsstats.rpccnt[NFSPROC_RENAME]++;
1524 nfsm_reqhead(fdvp, NFSPROC_RENAME,
1525 (NFSX_FH(v3) + NFSX_UNSIGNED)*2 + nfsm_rndup(fnamelen) +
1526 nfsm_rndup(tnamelen));
1527 nfsm_fhtom(fdvp, v3);
1528 nfsm_strtom(fnameptr, fnamelen, NFS_MAXNAMLEN);
1529 nfsm_fhtom(tdvp, v3);
1530 nfsm_strtom(tnameptr, tnamelen, NFS_MAXNAMLEN);
1531 nfsm_request(fdvp, NFSPROC_RENAME, proc, cred);
1532 if (v3) {
1533 nfsm_wcc_data(fdvp, fwccflag);
1534 nfsm_wcc_data(tdvp, twccflag);
1535 }
1536 nfsm_reqdone;
1537 VTONFS(fdvp)->n_flag |= NMODIFIED;
1538 VTONFS(tdvp)->n_flag |= NMODIFIED;
1539 if (!fwccflag)
1540 VTONFS(fdvp)->n_attrstamp = 0;
1541 if (!twccflag)
1542 VTONFS(tdvp)->n_attrstamp = 0;
1543 return (error);
1544 }
1545
1546
1547
1548
1549 int
1550 nfs_link(v)
1551 void *v;
1552 {
1553 struct vop_link_args *ap = v;
1554 struct vnode *vp = ap->a_vp;
1555 struct vnode *dvp = ap->a_dvp;
1556 struct componentname *cnp = ap->a_cnp;
1557 u_int32_t *tl;
1558 caddr_t cp;
1559 int32_t t1, t2;
1560 caddr_t bpos, dpos, cp2;
1561 int error = 0, wccflag = NFSV3_WCCRATTR, attrflag = 0;
1562 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1563 int v3;
1564
1565 if (dvp->v_mount != vp->v_mount) {
1566 pool_put(&namei_pool, cnp->cn_pnbuf);
1567 if (vp == dvp)
1568 vrele(dvp);
1569 else
1570 vput(dvp);
1571 return (EXDEV);
1572 }
1573
1574
1575
1576
1577
1578
1579 VOP_FSYNC(vp, cnp->cn_cred, MNT_WAIT, cnp->cn_proc);
1580
1581 v3 = NFS_ISV3(vp);
1582 nfsstats.rpccnt[NFSPROC_LINK]++;
1583 nfsm_reqhead(vp, NFSPROC_LINK,
1584 NFSX_FH(v3)*2 + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen));
1585 nfsm_fhtom(vp, v3);
1586 nfsm_fhtom(dvp, v3);
1587 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1588 nfsm_request(vp, NFSPROC_LINK, cnp->cn_proc, cnp->cn_cred);
1589 if (v3) {
1590 nfsm_postop_attr(vp, attrflag);
1591 nfsm_wcc_data(dvp, wccflag);
1592 }
1593 nfsm_reqdone;
1594 pool_put(&namei_pool, cnp->cn_pnbuf);
1595 VTONFS(dvp)->n_flag |= NMODIFIED;
1596 if (!attrflag)
1597 VTONFS(vp)->n_attrstamp = 0;
1598 if (!wccflag)
1599 VTONFS(dvp)->n_attrstamp = 0;
1600
1601 VN_KNOTE(vp, NOTE_LINK);
1602 VN_KNOTE(dvp, NOTE_WRITE);
1603 vput(dvp);
1604
1605
1606
1607 if (error == EEXIST)
1608 error = 0;
1609 return (error);
1610 }
1611
1612
1613
1614
1615 int
1616 nfs_symlink(v)
1617 void *v;
1618 {
1619 struct vop_symlink_args *ap = v;
1620 struct vnode *dvp = ap->a_dvp;
1621 struct vattr *vap = ap->a_vap;
1622 struct componentname *cnp = ap->a_cnp;
1623 struct nfsv2_sattr *sp;
1624 u_int32_t *tl;
1625 caddr_t cp;
1626 int32_t t1, t2;
1627 caddr_t bpos, dpos, cp2;
1628 int slen, error = 0, wccflag = NFSV3_WCCRATTR, gotvp;
1629 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1630 struct vnode *newvp = (struct vnode *)0;
1631 int v3 = NFS_ISV3(dvp);
1632
1633 nfsstats.rpccnt[NFSPROC_SYMLINK]++;
1634 slen = strlen(ap->a_target);
1635 nfsm_reqhead(dvp, NFSPROC_SYMLINK, NFSX_FH(v3) + 2*NFSX_UNSIGNED +
1636 nfsm_rndup(cnp->cn_namelen) + nfsm_rndup(slen) + NFSX_SATTR(v3));
1637 nfsm_fhtom(dvp, v3);
1638 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1639 if (v3)
1640 nfsm_v3attrbuild(vap, FALSE);
1641 nfsm_strtom(ap->a_target, slen, NFS_MAXPATHLEN);
1642 if (!v3) {
1643 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1644 sp->sa_mode = vtonfsv2_mode(VLNK, vap->va_mode);
1645 sp->sa_uid = nfs_xdrneg1;
1646 sp->sa_gid = nfs_xdrneg1;
1647 sp->sa_size = nfs_xdrneg1;
1648 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
1649 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
1650 }
1651 nfsm_request(dvp, NFSPROC_SYMLINK, cnp->cn_proc, cnp->cn_cred);
1652 if (v3) {
1653 if (!error)
1654 nfsm_mtofh(dvp, newvp, v3, gotvp);
1655 nfsm_wcc_data(dvp, wccflag);
1656 }
1657 nfsm_reqdone;
1658 if (newvp)
1659 vrele(newvp);
1660 pool_put(&namei_pool, cnp->cn_pnbuf);
1661 VTONFS(dvp)->n_flag |= NMODIFIED;
1662 if (!wccflag)
1663 VTONFS(dvp)->n_attrstamp = 0;
1664 VN_KNOTE(dvp, NOTE_WRITE);
1665 vrele(dvp);
1666
1667
1668
1669 if (error == EEXIST)
1670 error = 0;
1671 return (error);
1672 }
1673
1674
1675
1676
1677 int
1678 nfs_mkdir(v)
1679 void *v;
1680 {
1681 struct vop_mkdir_args *ap = v;
1682 struct vnode *dvp = ap->a_dvp;
1683 struct vattr *vap = ap->a_vap;
1684 struct componentname *cnp = ap->a_cnp;
1685 struct nfsv2_sattr *sp;
1686 u_int32_t *tl;
1687 caddr_t cp;
1688 int32_t t1, t2;
1689 int len;
1690 struct nfsnode *np = (struct nfsnode *)0;
1691 struct vnode *newvp = (struct vnode *)0;
1692 caddr_t bpos, dpos, cp2;
1693 int error = 0, wccflag = NFSV3_WCCRATTR;
1694 int gotvp = 0;
1695 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1696 int v3 = NFS_ISV3(dvp);
1697
1698 len = cnp->cn_namelen;
1699 nfsstats.rpccnt[NFSPROC_MKDIR]++;
1700 nfsm_reqhead(dvp, NFSPROC_MKDIR,
1701 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len) + NFSX_SATTR(v3));
1702 nfsm_fhtom(dvp, v3);
1703 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
1704 if (v3) {
1705 nfsm_v3attrbuild(vap, FALSE);
1706 } else {
1707 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1708 sp->sa_mode = vtonfsv2_mode(VDIR, vap->va_mode);
1709 sp->sa_uid = nfs_xdrneg1;
1710 sp->sa_gid = nfs_xdrneg1;
1711 sp->sa_size = nfs_xdrneg1;
1712 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
1713 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
1714 }
1715 nfsm_request(dvp, NFSPROC_MKDIR, cnp->cn_proc, cnp->cn_cred);
1716 if (!error)
1717 nfsm_mtofh(dvp, newvp, v3, gotvp);
1718 if (v3)
1719 nfsm_wcc_data(dvp, wccflag);
1720 nfsm_reqdone;
1721 VTONFS(dvp)->n_flag |= NMODIFIED;
1722 if (!wccflag)
1723 VTONFS(dvp)->n_attrstamp = 0;
1724
1725
1726
1727
1728 if (error == EEXIST || (!error && !gotvp)) {
1729 if (newvp) {
1730 vrele(newvp);
1731 newvp = (struct vnode *)0;
1732 }
1733 error = nfs_lookitup(dvp, cnp->cn_nameptr, len, cnp->cn_cred,
1734 cnp->cn_proc, &np);
1735 if (!error) {
1736 newvp = NFSTOV(np);
1737 if (newvp->v_type != VDIR)
1738 error = EEXIST;
1739 }
1740 }
1741 if (error) {
1742 if (newvp)
1743 vrele(newvp);
1744 } else {
1745 VN_KNOTE(dvp, NOTE_WRITE|NOTE_LINK);
1746 *ap->a_vpp = newvp;
1747 }
1748 pool_put(&namei_pool, cnp->cn_pnbuf);
1749 vrele(dvp);
1750 return (error);
1751 }
1752
1753
1754
1755
1756 int
1757 nfs_rmdir(v)
1758 void *v;
1759 {
1760 struct vop_rmdir_args *ap = v;
1761 struct vnode *vp = ap->a_vp;
1762 struct vnode *dvp = ap->a_dvp;
1763 struct componentname *cnp = ap->a_cnp;
1764 u_int32_t *tl;
1765 caddr_t cp;
1766 int32_t t1, t2;
1767 caddr_t bpos, dpos, cp2;
1768 int error = 0, wccflag = NFSV3_WCCRATTR;
1769 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1770 int v3 = NFS_ISV3(dvp);
1771
1772 if (dvp == vp) {
1773 vrele(dvp);
1774 vrele(dvp);
1775 pool_put(&namei_pool, cnp->cn_pnbuf);
1776 return (EINVAL);
1777 }
1778 nfsstats.rpccnt[NFSPROC_RMDIR]++;
1779 nfsm_reqhead(dvp, NFSPROC_RMDIR,
1780 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen));
1781 nfsm_fhtom(dvp, v3);
1782 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1783 nfsm_request(dvp, NFSPROC_RMDIR, cnp->cn_proc, cnp->cn_cred);
1784 if (v3)
1785 nfsm_wcc_data(dvp, wccflag);
1786 nfsm_reqdone;
1787 pool_put(&namei_pool, cnp->cn_pnbuf);
1788 VTONFS(dvp)->n_flag |= NMODIFIED;
1789 if (!wccflag)
1790 VTONFS(dvp)->n_attrstamp = 0;
1791
1792 VN_KNOTE(dvp, NOTE_WRITE|NOTE_LINK);
1793 VN_KNOTE(vp, NOTE_DELETE);
1794
1795 cache_purge(dvp);
1796 cache_purge(vp);
1797 vrele(vp);
1798 vrele(dvp);
1799
1800
1801
1802 if (error == ENOENT)
1803 error = 0;
1804 return (error);
1805 }
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820 struct nfs_dirent {
1821 u_int32_t cookie[2];
1822 struct dirent dirent;
1823 };
1824
1825 #define NFS_DIRHDSIZ (sizeof (struct nfs_dirent) - (MAXNAMLEN + 1))
1826 #define NFS_DIRENT_OVERHEAD offsetof(struct nfs_dirent, dirent)
1827
1828
1829
1830
1831 int
1832 nfs_readdir(v)
1833 void *v;
1834 {
1835 struct vop_readdir_args *ap = v;
1836 struct vnode *vp = ap->a_vp;
1837 struct nfsnode *np = VTONFS(vp);
1838 struct uio *uio = ap->a_uio;
1839 int tresid, error;
1840 struct vattr vattr;
1841 u_long *cookies = NULL;
1842 int ncookies = 0, cnt;
1843 u_int64_t newoff = uio->uio_offset;
1844 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
1845 struct uio readdir_uio;
1846 struct iovec readdir_iovec;
1847 struct proc * p = uio->uio_procp;
1848 int done = 0, eof = 0;
1849 struct ucred *cred = ap->a_cred;
1850 void *data;
1851
1852 if (vp->v_type != VDIR)
1853 return (EPERM);
1854
1855
1856
1857 if (np->n_direofoffset != 0 &&
1858 uio->uio_offset == np->n_direofoffset) {
1859 if (VOP_GETATTR(vp, &vattr, ap->a_cred, uio->uio_procp) == 0 &&
1860 np->n_mtime == vattr.va_mtime.tv_sec) {
1861 nfsstats.direofcache_hits++;
1862 *ap->a_eofflag = 1;
1863 return (0);
1864 }
1865 }
1866
1867 if (uio->uio_resid < NFS_FABLKSIZE)
1868 return (EINVAL);
1869
1870 tresid = uio->uio_resid;
1871
1872 if (uio->uio_rw != UIO_READ)
1873 return (EINVAL);
1874
1875 if (ap->a_cookies) {
1876 ncookies = uio->uio_resid / 20;
1877
1878 MALLOC(cookies, u_long *, sizeof(*cookies) * ncookies,
1879 M_TEMP, M_WAITOK);
1880 *ap->a_ncookies = ncookies;
1881 *ap->a_cookies = cookies;
1882 }
1883
1884 if ((nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_GOTFSINFO)) == NFSMNT_NFSV3)
1885 (void)nfs_fsinfo(nmp, vp, cred, p);
1886
1887 cnt = 5;
1888
1889 MALLOC(data, void *, NFS_DIRBLKSIZ, M_TEMP,
1890 M_WAITOK);
1891
1892 do {
1893 struct nfs_dirent *ndp = data;
1894
1895 readdir_iovec.iov_len = NFS_DIRBLKSIZ;
1896 readdir_iovec.iov_base = data;
1897 readdir_uio.uio_offset = newoff;
1898 readdir_uio.uio_iov = &readdir_iovec;
1899 readdir_uio.uio_iovcnt = 1;
1900 readdir_uio.uio_segflg = UIO_SYSSPACE;
1901 readdir_uio.uio_rw = UIO_READ;
1902 readdir_uio.uio_resid = NFS_DIRBLKSIZ;
1903 readdir_uio.uio_procp = curproc;
1904
1905 if (nmp->nm_flag & NFSMNT_RDIRPLUS) {
1906 error = nfs_readdirplusrpc(vp, &readdir_uio, cred,
1907 &eof);
1908 if (error == NFSERR_NOTSUPP)
1909 nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
1910 }
1911 if ((nmp->nm_flag & NFSMNT_RDIRPLUS) == 0)
1912 error = nfs_readdirrpc(vp, &readdir_uio, cred, &eof);
1913
1914 if (error == NFSERR_BAD_COOKIE)
1915 error = EINVAL;
1916
1917 while (error == 0 &&
1918 (ap->a_cookies == NULL || ncookies != 0) &&
1919 ndp < (struct nfs_dirent *)readdir_iovec.iov_base) {
1920 struct dirent *dp = &ndp->dirent;
1921 int reclen = dp->d_reclen;
1922
1923 dp->d_reclen -= NFS_DIRENT_OVERHEAD;
1924
1925 if (uio->uio_resid < dp->d_reclen) {
1926 eof = 0;
1927 done = 1;
1928 break;
1929 }
1930
1931 error = uiomove((caddr_t)dp, dp->d_reclen, uio);
1932 if (error)
1933 break;
1934
1935 newoff = fxdr_hyper(&ndp->cookie[0]);
1936
1937 if (ap->a_cookies != NULL) {
1938 *cookies = newoff;
1939 cookies++;
1940 ncookies--;
1941 }
1942
1943 ndp = (struct nfs_dirent *)((u_int8_t *)ndp + reclen);
1944 }
1945 } while (!error && !done && !eof && cnt--);
1946
1947 FREE(data, M_TEMP);
1948 data = NULL;
1949
1950 if (ap->a_cookies) {
1951 if (error) {
1952 FREE(*ap->a_cookies, M_TEMP);
1953 *ap->a_cookies = NULL;
1954 *ap->a_ncookies = 0;
1955 } else {
1956 *ap->a_ncookies -= ncookies;
1957 }
1958 }
1959
1960 if (!error)
1961 uio->uio_offset = newoff;
1962
1963 if (!error && (eof || uio->uio_resid == tresid)) {
1964 nfsstats.direofcache_misses++;
1965 *ap->a_eofflag = 1;
1966 return (0);
1967 }
1968
1969 *ap->a_eofflag = 0;
1970 return (error);
1971 }
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981 int
1982 nfs_readdirrpc(struct vnode *vp,
1983 struct uio *uiop,
1984 struct ucred *cred,
1985 int *end_of_directory)
1986 {
1987 int len, left;
1988 struct nfs_dirent *ndp = NULL;
1989 struct dirent *dp = NULL;
1990 u_int32_t *tl;
1991 caddr_t cp;
1992 int32_t t1, t2;
1993 caddr_t bpos, dpos, cp2;
1994 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1995 nfsuint64 cookie;
1996 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
1997 struct nfsnode *dnp = VTONFS(vp);
1998 u_quad_t fileno;
1999 int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1;
2000 int attrflag;
2001 int v3 = NFS_ISV3(vp);
2002
2003 #ifndef DIAGNOSTIC
2004 if (uiop->uio_iovcnt != 1 ||
2005 (uiop->uio_resid & (NFS_DIRBLKSIZ - 1)))
2006 panic("nfs readdirrpc bad uio");
2007 #endif
2008
2009 txdr_hyper(uiop->uio_offset, &cookie.nfsuquad[0]);
2010
2011
2012
2013
2014
2015
2016 while (more_dirs && bigenough) {
2017 nfsstats.rpccnt[NFSPROC_READDIR]++;
2018 nfsm_reqhead(vp, NFSPROC_READDIR, NFSX_FH(v3) +
2019 NFSX_READDIR(v3));
2020 nfsm_fhtom(vp, v3);
2021 if (v3) {
2022 nfsm_build(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
2023 *tl++ = cookie.nfsuquad[0];
2024 *tl++ = cookie.nfsuquad[1];
2025 if (cookie.nfsuquad[0] == 0 &&
2026 cookie.nfsuquad[1] == 0) {
2027 *tl++ = 0;
2028 *tl++ = 0;
2029 } else {
2030 *tl++ = dnp->n_cookieverf.nfsuquad[0];
2031 *tl++ = dnp->n_cookieverf.nfsuquad[1];
2032 }
2033 } else {
2034 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2035 *tl++ = cookie.nfsuquad[1];
2036 }
2037 *tl = txdr_unsigned(nmp->nm_readdirsize);
2038 nfsm_request(vp, NFSPROC_READDIR, uiop->uio_procp, cred);
2039 if (v3) {
2040 nfsm_postop_attr(vp, attrflag);
2041 if (!error) {
2042 nfsm_dissect(tl, u_int32_t *,
2043 2 * NFSX_UNSIGNED);
2044 dnp->n_cookieverf.nfsuquad[0] = *tl++;
2045 dnp->n_cookieverf.nfsuquad[1] = *tl;
2046 } else {
2047 m_freem(mrep);
2048 goto nfsmout;
2049 }
2050 }
2051 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2052 more_dirs = fxdr_unsigned(int, *tl);
2053
2054
2055 while (more_dirs && bigenough) {
2056 if (v3) {
2057 nfsm_dissect(tl, u_int32_t *,
2058 3 * NFSX_UNSIGNED);
2059 fileno = fxdr_hyper(tl);
2060 len = fxdr_unsigned(int, *(tl + 2));
2061 } else {
2062 nfsm_dissect(tl, u_int32_t *,
2063 2 * NFSX_UNSIGNED);
2064 fileno = fxdr_unsigned(u_quad_t, *tl++);
2065 len = fxdr_unsigned(int, *tl);
2066 }
2067 if (len <= 0 || len > NFS_MAXNAMLEN) {
2068 error = EBADRPC;
2069 m_freem(mrep);
2070 goto nfsmout;
2071 }
2072 tlen = nfsm_rndup(len + 1);
2073 left = NFS_READDIRBLKSIZ - blksiz;
2074 if ((tlen + NFS_DIRHDSIZ) > left) {
2075 dp->d_reclen += left;
2076 uiop->uio_iov->iov_base += left;
2077 uiop->uio_iov->iov_len -= left;
2078 uiop->uio_resid -= left;
2079 blksiz = 0;
2080 }
2081 if ((tlen + NFS_DIRHDSIZ) > uiop->uio_resid)
2082 bigenough = 0;
2083 if (bigenough) {
2084 ndp = (struct nfs_dirent *)
2085 uiop->uio_iov->iov_base;
2086 dp = &ndp->dirent;
2087 dp->d_fileno = (int)fileno;
2088 dp->d_namlen = len;
2089 dp->d_reclen = tlen + NFS_DIRHDSIZ;
2090 dp->d_type = DT_UNKNOWN;
2091 blksiz += dp->d_reclen;
2092 if (blksiz == NFS_READDIRBLKSIZ)
2093 blksiz = 0;
2094 uiop->uio_resid -= NFS_DIRHDSIZ;
2095 (char *)uiop->uio_iov->iov_base += NFS_DIRHDSIZ;
2096 uiop->uio_iov->iov_len -= NFS_DIRHDSIZ;
2097 nfsm_mtouio(uiop, len);
2098 cp = uiop->uio_iov->iov_base;
2099 tlen -= len;
2100 *cp = '\0';
2101 uiop->uio_iov->iov_base += tlen;
2102 uiop->uio_iov->iov_len -= tlen;
2103 uiop->uio_resid -= tlen;
2104 } else
2105 nfsm_adv(nfsm_rndup(len));
2106 if (v3) {
2107 nfsm_dissect(tl, u_int32_t *,
2108 3 * NFSX_UNSIGNED);
2109 } else {
2110 nfsm_dissect(tl, u_int32_t *,
2111 2 * NFSX_UNSIGNED);
2112 }
2113 if (bigenough) {
2114 if (v3) {
2115 ndp->cookie[0] = cookie.nfsuquad[0] =
2116 *tl++;
2117 } else
2118 ndp->cookie[0] = 0;
2119
2120 ndp->cookie[1] = cookie.nfsuquad[1] = *tl++;
2121 } else if (v3)
2122 tl += 2;
2123 else
2124 tl++;
2125 more_dirs = fxdr_unsigned(int, *tl);
2126 }
2127
2128
2129
2130 if (!more_dirs) {
2131 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2132 more_dirs = (fxdr_unsigned(int, *tl) == 0);
2133 }
2134 m_freem(mrep);
2135 }
2136
2137
2138
2139
2140 if (blksiz > 0) {
2141 left = NFS_READDIRBLKSIZ - blksiz;
2142 dp->d_reclen += left;
2143 (char *)uiop->uio_iov->iov_base += left;
2144 uiop->uio_iov->iov_len -= left;
2145 uiop->uio_resid -= left;
2146 }
2147
2148
2149
2150
2151
2152 if (bigenough) {
2153 dnp->n_direofoffset = fxdr_hyper(&cookie.nfsuquad[0]);
2154 if (end_of_directory) *end_of_directory = 1;
2155 } else {
2156 if (uiop->uio_resid > 0)
2157 printf("EEK! readdirrpc resid > 0\n");
2158 }
2159
2160 nfsmout:
2161 return (error);
2162 }
2163
2164
2165
2166
2167 int
2168 nfs_readdirplusrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred,
2169 int *end_of_directory)
2170 {
2171 int len, left;
2172 struct nfs_dirent *ndirp = NULL;
2173 struct dirent *dp = NULL;
2174 u_int32_t *tl;
2175 caddr_t cp;
2176 int32_t t1, t2;
2177 struct vnode *newvp;
2178 caddr_t bpos, dpos, cp2, dpossav1, dpossav2;
2179 struct mbuf *mreq, *mrep, *md, *mb, *mb2, *mdsav1, *mdsav2;
2180 struct nameidata nami, *ndp = &nami;
2181 struct componentname *cnp = &ndp->ni_cnd;
2182 nfsuint64 cookie;
2183 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2184 struct nfsnode *dnp = VTONFS(vp), *np;
2185 nfsfh_t *fhp;
2186 u_quad_t fileno;
2187 int error = 0, tlen, more_dirs = 1, blksiz = 0, doit, bigenough = 1, i;
2188 int attrflag, fhsize;
2189
2190 #ifndef DIAGNOSTIC
2191 if (uiop->uio_iovcnt != 1 ||
2192 (uiop->uio_resid & (NFS_DIRBLKSIZ - 1)))
2193 panic("nfs readdirplusrpc bad uio");
2194 #endif
2195 ndp->ni_dvp = vp;
2196 newvp = NULLVP;
2197
2198 txdr_hyper(uiop->uio_offset, &cookie.nfsuquad[0]);
2199
2200
2201
2202
2203
2204
2205 while (more_dirs && bigenough) {
2206 nfsstats.rpccnt[NFSPROC_READDIRPLUS]++;
2207 nfsm_reqhead(vp, NFSPROC_READDIRPLUS,
2208 NFSX_FH(1) + 6 * NFSX_UNSIGNED);
2209 nfsm_fhtom(vp, 1);
2210 nfsm_build(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
2211 *tl++ = cookie.nfsuquad[0];
2212 *tl++ = cookie.nfsuquad[1];
2213 if (cookie.nfsuquad[0] == 0 &&
2214 cookie.nfsuquad[1] == 0) {
2215 *tl++ = 0;
2216 *tl++ = 0;
2217 } else {
2218 *tl++ = dnp->n_cookieverf.nfsuquad[0];
2219 *tl++ = dnp->n_cookieverf.nfsuquad[1];
2220 }
2221 *tl++ = txdr_unsigned(nmp->nm_readdirsize);
2222 *tl = txdr_unsigned(nmp->nm_rsize);
2223 nfsm_request(vp, NFSPROC_READDIRPLUS, uiop->uio_procp, cred);
2224 nfsm_postop_attr(vp, attrflag);
2225 if (error) {
2226 m_freem(mrep);
2227 goto nfsmout;
2228 }
2229 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
2230 dnp->n_cookieverf.nfsuquad[0] = *tl++;
2231 dnp->n_cookieverf.nfsuquad[1] = *tl++;
2232 more_dirs = fxdr_unsigned(int, *tl);
2233
2234
2235 while (more_dirs && bigenough) {
2236 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
2237 fileno = fxdr_hyper(tl);
2238 len = fxdr_unsigned(int, *(tl + 2));
2239 if (len <= 0 || len > NFS_MAXNAMLEN) {
2240 error = EBADRPC;
2241 m_freem(mrep);
2242 goto nfsmout;
2243 }
2244 tlen = nfsm_rndup(len + 1);
2245 left = NFS_READDIRBLKSIZ - blksiz;
2246 if ((tlen + NFS_DIRHDSIZ) > left) {
2247 dp->d_reclen += left;
2248 (char *)uiop->uio_iov->iov_base += left;
2249 uiop->uio_iov->iov_len -= left;
2250 uiop->uio_resid -= left;
2251 blksiz = 0;
2252 }
2253 if ((tlen + NFS_DIRHDSIZ) > uiop->uio_resid)
2254 bigenough = 0;
2255 if (bigenough) {
2256 ndirp = (struct nfs_dirent *)
2257 uiop->uio_iov->iov_base;
2258 dp = &ndirp->dirent;
2259 dp->d_fileno = (int)fileno;
2260 dp->d_namlen = len;
2261 dp->d_reclen = tlen + NFS_DIRHDSIZ;
2262 dp->d_type = DT_UNKNOWN;
2263 blksiz += dp->d_reclen;
2264 if (blksiz == NFS_READDIRBLKSIZ)
2265 blksiz = 0;
2266 uiop->uio_resid -= NFS_DIRHDSIZ;
2267 (char *)uiop->uio_iov->iov_base += NFS_DIRHDSIZ;
2268 uiop->uio_iov->iov_len -= NFS_DIRHDSIZ;
2269 cnp->cn_nameptr = uiop->uio_iov->iov_base;
2270 cnp->cn_namelen = len;
2271 nfsm_mtouio(uiop, len);
2272 cp = uiop->uio_iov->iov_base;
2273 tlen -= len;
2274 *cp = '\0';
2275 uiop->uio_iov->iov_base += tlen;
2276 uiop->uio_iov->iov_len -= tlen;
2277 uiop->uio_resid -= tlen;
2278 } else
2279 nfsm_adv(nfsm_rndup(len));
2280 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
2281 if (bigenough) {
2282 ndirp->cookie[0] = cookie.nfsuquad[0] = *tl++;
2283 ndirp->cookie[1] = cookie.nfsuquad[1] = *tl++;
2284 } else
2285 tl += 2;
2286
2287
2288
2289
2290
2291
2292 attrflag = fxdr_unsigned(int, *tl);
2293 if (attrflag) {
2294 dpossav1 = dpos;
2295 mdsav1 = md;
2296 nfsm_adv(NFSX_V3FATTR);
2297 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2298 doit = fxdr_unsigned(int, *tl);
2299 if (doit) {
2300 nfsm_getfh(fhp, fhsize, 1);
2301 if (NFS_CMPFH(dnp, fhp, fhsize)) {
2302 VREF(vp);
2303 newvp = vp;
2304 np = dnp;
2305 } else {
2306 error = nfs_nget(vp->v_mount, fhp,
2307 fhsize, &np);
2308 if (error)
2309 doit = 0;
2310 else
2311 newvp = NFSTOV(np);
2312 }
2313 }
2314 if (doit && bigenough) {
2315 dpossav2 = dpos;
2316 dpos = dpossav1;
2317 mdsav2 = md;
2318 md = mdsav1;
2319 nfsm_loadattr(newvp, (struct vattr *)0);
2320 dpos = dpossav2;
2321 md = mdsav2;
2322 dp->d_type =
2323 IFTODT(VTTOIF(np->n_vattr.va_type));
2324 if (cnp->cn_namelen <= NCHNAMLEN) {
2325 ndp->ni_vp = newvp;
2326 cnp->cn_hash =
2327 hash32_str(cnp->cn_nameptr,
2328 HASHINIT);
2329 cache_enter(ndp->ni_dvp, ndp->ni_vp,
2330 cnp);
2331 }
2332 }
2333 } else {
2334
2335 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2336 i = fxdr_unsigned(int, *tl);
2337 nfsm_adv(nfsm_rndup(i));
2338 }
2339 if (newvp != NULLVP) {
2340 vrele(newvp);
2341 newvp = NULLVP;
2342 }
2343 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2344 more_dirs = fxdr_unsigned(int, *tl);
2345 }
2346
2347
2348
2349 if (!more_dirs) {
2350 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2351 more_dirs = (fxdr_unsigned(int, *tl) == 0);
2352 }
2353 m_freem(mrep);
2354 }
2355
2356
2357
2358
2359 if (blksiz > 0) {
2360 left = NFS_READDIRBLKSIZ - blksiz;
2361 dp->d_reclen += left;
2362 (char *)uiop->uio_iov->iov_base += left;
2363 uiop->uio_iov->iov_len -= left;
2364 uiop->uio_resid -= left;
2365 }
2366
2367
2368
2369
2370
2371 if (bigenough) {
2372 dnp->n_direofoffset = fxdr_hyper(&cookie.nfsuquad[0]);
2373 if (end_of_directory) *end_of_directory = 1;
2374 } else {
2375 if (uiop->uio_resid > 0)
2376 printf("EEK! readdirplusrpc resid > 0\n");
2377 }
2378
2379 nfsmout:
2380 if (newvp != NULLVP)
2381 vrele(newvp);
2382 return (error);
2383 }
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393 int
2394 nfs_sillyrename(dvp, vp, cnp)
2395 struct vnode *dvp, *vp;
2396 struct componentname *cnp;
2397 {
2398 struct sillyrename *sp;
2399 struct nfsnode *np;
2400 int error;
2401
2402 cache_purge(dvp);
2403 np = VTONFS(vp);
2404 MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename),
2405 M_NFSREQ, M_WAITOK);
2406 sp->s_cred = crdup(cnp->cn_cred);
2407 sp->s_dvp = dvp;
2408 VREF(dvp);
2409
2410 if (vp->v_type == VDIR) {
2411 #ifdef DIAGNOSTIC
2412 printf("nfs: sillyrename dir\n");
2413 #endif
2414 error = EINVAL;
2415 goto bad;
2416 }
2417
2418
2419 sp->s_namlen = snprintf(sp->s_name, sizeof sp->s_name,
2420 ".nfsA%05x4.4", cnp->cn_proc->p_pid);
2421 if (sp->s_namlen > sizeof sp->s_name)
2422 sp->s_namlen = strlen(sp->s_name);
2423
2424
2425 while (nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred,
2426 cnp->cn_proc, (struct nfsnode **)0) == 0) {
2427 sp->s_name[4]++;
2428 if (sp->s_name[4] > 'z') {
2429 error = EINVAL;
2430 goto bad;
2431 }
2432 }
2433 error = nfs_renameit(dvp, cnp, sp);
2434 if (error)
2435 goto bad;
2436 error = nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred,
2437 cnp->cn_proc, &np);
2438 np->n_sillyrename = sp;
2439 return (0);
2440 bad:
2441 vrele(sp->s_dvp);
2442 crfree(sp->s_cred);
2443 FREE((caddr_t)sp, M_NFSREQ);
2444 return (error);
2445 }
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455 int
2456 nfs_lookitup(dvp, name, len, cred, procp, npp)
2457 struct vnode *dvp;
2458 char *name;
2459 int len;
2460 struct ucred *cred;
2461 struct proc *procp;
2462 struct nfsnode **npp;
2463 {
2464 u_int32_t *tl;
2465 caddr_t cp;
2466 int32_t t1, t2;
2467 struct vnode *newvp = (struct vnode *)0;
2468 struct nfsnode *np, *dnp = VTONFS(dvp);
2469 caddr_t bpos, dpos, cp2;
2470 int error = 0, fhlen, attrflag;
2471 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
2472 nfsfh_t *nfhp;
2473 int v3 = NFS_ISV3(dvp);
2474
2475 nfsstats.rpccnt[NFSPROC_LOOKUP]++;
2476 nfsm_reqhead(dvp, NFSPROC_LOOKUP,
2477 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len));
2478 nfsm_fhtom(dvp, v3);
2479 nfsm_strtom(name, len, NFS_MAXNAMLEN);
2480 nfsm_request(dvp, NFSPROC_LOOKUP, procp, cred);
2481 if (npp && !error) {
2482 nfsm_getfh(nfhp, fhlen, v3);
2483 if (*npp) {
2484 np = *npp;
2485 if (np->n_fhsize > NFS_SMALLFH && fhlen <= NFS_SMALLFH) {
2486 free((caddr_t)np->n_fhp, M_NFSBIGFH);
2487 np->n_fhp = &np->n_fh;
2488 } else if (np->n_fhsize <= NFS_SMALLFH && fhlen>NFS_SMALLFH)
2489 np->n_fhp =(nfsfh_t *)malloc(fhlen,M_NFSBIGFH,M_WAITOK);
2490 bcopy((caddr_t)nfhp, (caddr_t)np->n_fhp, fhlen);
2491 np->n_fhsize = fhlen;
2492 newvp = NFSTOV(np);
2493 } else if (NFS_CMPFH(dnp, nfhp, fhlen)) {
2494 VREF(dvp);
2495 newvp = dvp;
2496 } else {
2497 error = nfs_nget(dvp->v_mount, nfhp, fhlen, &np);
2498 if (error) {
2499 m_freem(mrep);
2500 return (error);
2501 }
2502 newvp = NFSTOV(np);
2503 }
2504 if (v3) {
2505 nfsm_postop_attr(newvp, attrflag);
2506 if (!attrflag && *npp == NULL) {
2507 m_freem(mrep);
2508 vrele(newvp);
2509 return (ENOENT);
2510 }
2511 } else
2512 nfsm_loadattr(newvp, (struct vattr *)0);
2513 }
2514 nfsm_reqdone;
2515 if (npp && *npp == NULL) {
2516 if (error) {
2517 if (newvp)
2518 vrele(newvp);
2519 } else
2520 *npp = np;
2521 }
2522 return (error);
2523 }
2524
2525
2526
2527
2528 int
2529 nfs_commit(vp, offset, cnt, procp)
2530 struct vnode *vp;
2531 u_quad_t offset;
2532 int cnt;
2533 struct proc *procp;
2534 {
2535 caddr_t cp;
2536 u_int32_t *tl;
2537 int32_t t1, t2;
2538 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2539 caddr_t bpos, dpos, cp2;
2540 int error = 0, wccflag = NFSV3_WCCRATTR;
2541 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
2542
2543 if ((nmp->nm_flag & NFSMNT_HASWRITEVERF) == 0)
2544 return (0);
2545 nfsstats.rpccnt[NFSPROC_COMMIT]++;
2546 nfsm_reqhead(vp, NFSPROC_COMMIT, NFSX_FH(1));
2547 nfsm_fhtom(vp, 1);
2548 nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
2549 txdr_hyper(offset, tl);
2550 tl += 2;
2551 *tl = txdr_unsigned(cnt);
2552 nfsm_request(vp, NFSPROC_COMMIT, procp, VTONFS(vp)->n_wcred);
2553 nfsm_wcc_data(vp, wccflag);
2554 if (!error) {
2555 nfsm_dissect(tl, u_int32_t *, NFSX_V3WRITEVERF);
2556 if (bcmp((caddr_t)nmp->nm_verf, (caddr_t)tl,
2557 NFSX_V3WRITEVERF)) {
2558 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf,
2559 NFSX_V3WRITEVERF);
2560 error = NFSERR_STALEWRITEVERF;
2561 }
2562 }
2563 nfsm_reqdone;
2564 return (error);
2565 }
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576 int
2577 nfs_bmap(v)
2578 void *v;
2579 {
2580 struct vop_bmap_args *ap = v;
2581 struct vnode *vp = ap->a_vp;
2582
2583 if (ap->a_vpp != NULL)
2584 *ap->a_vpp = vp;
2585 if (ap->a_bnp != NULL)
2586 *ap->a_bnp = ap->a_bn * btodb(vp->v_mount->mnt_stat.f_iosize);
2587 return (0);
2588 }
2589
2590
2591
2592
2593
2594
2595
2596 int
2597 nfs_strategy(v)
2598 void *v;
2599 {
2600 struct vop_strategy_args *ap = v;
2601 struct buf *bp = ap->a_bp;
2602 struct proc *p;
2603 int error = 0;
2604
2605 if ((bp->b_flags & (B_PHYS|B_ASYNC)) == (B_PHYS|B_ASYNC))
2606 panic("nfs physio/async");
2607 if (bp->b_flags & B_ASYNC)
2608 p = NULL;
2609 else
2610 p = curproc;
2611
2612
2613
2614
2615
2616 if ((bp->b_flags & B_ASYNC) == 0 || nfs_asyncio(bp))
2617 error = nfs_doio(bp, p);
2618 return (error);
2619 }
2620
2621
2622
2623
2624
2625 int
2626 nfs_fsync(v)
2627 void *v;
2628 {
2629 struct vop_fsync_args *ap = v;
2630
2631 return (nfs_flush(ap->a_vp, ap->a_cred, ap->a_waitfor, ap->a_p, 1));
2632 }
2633
2634
2635
2636
2637
2638
2639 int
2640 nfs_flush(vp, cred, waitfor, p, commit)
2641 struct vnode *vp;
2642 struct ucred *cred;
2643 int waitfor;
2644 struct proc *p;
2645 int commit;
2646 {
2647 struct nfsnode *np = VTONFS(vp);
2648 struct buf *bp;
2649 int i;
2650 struct buf *nbp;
2651 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2652 int s, error = 0, slptimeo = 0, slpflag = 0, retv, bvecpos;
2653 int passone = 1;
2654 u_quad_t off = (u_quad_t)-1, endoff = 0, toff;
2655 #ifndef NFS_COMMITBVECSIZ
2656 #define NFS_COMMITBVECSIZ 20
2657 #endif
2658 struct buf *bvec[NFS_COMMITBVECSIZ];
2659
2660 if (nmp->nm_flag & NFSMNT_INT)
2661 slpflag = PCATCH;
2662 if (!commit)
2663 passone = 0;
2664
2665
2666
2667
2668
2669
2670
2671 again:
2672 bvecpos = 0;
2673 if (NFS_ISV3(vp) && commit) {
2674 s = splbio();
2675 for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp != NULL; bp = nbp) {
2676 nbp = LIST_NEXT(bp, b_vnbufs);
2677 if (bvecpos >= NFS_COMMITBVECSIZ)
2678 break;
2679 if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT))
2680 != (B_DELWRI | B_NEEDCOMMIT))
2681 continue;
2682 bremfree(bp);
2683 bp->b_flags |= (B_BUSY | B_WRITEINPROG);
2684
2685
2686
2687
2688
2689
2690
2691 bvec[bvecpos++] = bp;
2692 toff = ((u_quad_t)bp->b_blkno) * DEV_BSIZE +
2693 bp->b_dirtyoff;
2694 if (toff < off)
2695 off = toff;
2696 toff += (u_quad_t)(bp->b_dirtyend - bp->b_dirtyoff);
2697 if (toff > endoff)
2698 endoff = toff;
2699 }
2700 splx(s);
2701 }
2702 if (bvecpos > 0) {
2703
2704
2705
2706 retv = nfs_commit(vp, off, (int)(endoff - off), p);
2707 if (retv == NFSERR_STALEWRITEVERF)
2708 nfs_clearcommit(vp->v_mount);
2709
2710
2711
2712
2713
2714 for (i = 0; i < bvecpos; i++) {
2715 bp = bvec[i];
2716 bp->b_flags &= ~(B_NEEDCOMMIT | B_WRITEINPROG);
2717 if (retv)
2718 brelse(bp);
2719 else {
2720 s = splbio();
2721 buf_undirty(bp);
2722 vp->v_numoutput++;
2723 bp->b_flags |= B_ASYNC;
2724 bp->b_flags &= ~(B_READ|B_DONE|B_ERROR);
2725 bp->b_dirtyoff = bp->b_dirtyend = 0;
2726 biodone(bp);
2727 splx(s);
2728 }
2729 }
2730 }
2731
2732
2733
2734
2735 loop:
2736 s = splbio();
2737 for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp != NULL; bp = nbp) {
2738 nbp = LIST_NEXT(bp, b_vnbufs);
2739 if (bp->b_flags & B_BUSY) {
2740 if (waitfor != MNT_WAIT || passone)
2741 continue;
2742 bp->b_flags |= B_WANTED;
2743 error = tsleep((caddr_t)bp, slpflag | (PRIBIO + 1),
2744 "nfsfsync", slptimeo);
2745 splx(s);
2746 if (error) {
2747 if (nfs_sigintr(nmp, (struct nfsreq *)0, p))
2748 return (EINTR);
2749 if (slpflag == PCATCH) {
2750 slpflag = 0;
2751 slptimeo = 2 * hz;
2752 }
2753 }
2754 goto loop;
2755 }
2756 if ((bp->b_flags & B_DELWRI) == 0)
2757 panic("nfs_fsync: not dirty");
2758 if ((passone || !commit) && (bp->b_flags & B_NEEDCOMMIT))
2759 continue;
2760 bremfree(bp);
2761 if (passone || !commit)
2762 bp->b_flags |= (B_BUSY|B_ASYNC);
2763 else
2764 bp->b_flags |= (B_BUSY|B_ASYNC|B_WRITEINPROG|B_NEEDCOMMIT);
2765 splx(s);
2766 VOP_BWRITE(bp);
2767 goto loop;
2768 }
2769 splx(s);
2770 if (passone) {
2771 passone = 0;
2772 goto again;
2773 }
2774 if (waitfor == MNT_WAIT) {
2775 loop2:
2776 s = splbio();
2777 error = vwaitforio(vp, slpflag, "nfs_fsync", slptimeo);
2778 splx(s);
2779 if (error) {
2780 if (nfs_sigintr(nmp, (struct nfsreq *)0, p))
2781 return (EINTR);
2782 if (slpflag == PCATCH) {
2783 slpflag = 0;
2784 slptimeo = 2 * hz;
2785 }
2786 goto loop2;
2787 }
2788
2789 if (LIST_FIRST(&vp->v_dirtyblkhd) && commit) {
2790 #if 0
2791 vprint("nfs_fsync: dirty", vp);
2792 #endif
2793 goto loop;
2794 }
2795 }
2796 if (np->n_flag & NWRITEERR) {
2797 error = np->n_error;
2798 np->n_flag &= ~NWRITEERR;
2799 }
2800 return (error);
2801 }
2802
2803
2804
2805
2806
2807
2808
2809
2810 int
2811 nfs_pathconf(v)
2812 void *v;
2813 {
2814 #if 0
2815 struct vop_pathconf_args *ap = v;
2816 #endif
2817
2818 return (EINVAL);
2819 }
2820
2821
2822
2823
2824 int
2825 nfs_advlock(v)
2826 void *v;
2827 {
2828 struct vop_advlock_args *ap = v;
2829 struct nfsnode *np = VTONFS(ap->a_vp);
2830
2831 return (lf_advlock(&np->n_lockf, np->n_size, ap->a_id, ap->a_op,
2832 ap->a_fl, ap->a_flags));
2833 }
2834
2835
2836
2837
2838 int
2839 nfs_print(v)
2840 void *v;
2841 {
2842 struct vop_print_args *ap = v;
2843 struct vnode *vp = ap->a_vp;
2844 struct nfsnode *np = VTONFS(vp);
2845
2846 printf("tag VT_NFS, fileid %ld fsid 0x%lx",
2847 np->n_vattr.va_fileid, np->n_vattr.va_fsid);
2848 #ifdef FIFO
2849 if (vp->v_type == VFIFO)
2850 fifo_printinfo(vp);
2851 #endif
2852 printf("\n");
2853 return (0);
2854 }
2855
2856
2857
2858
2859 int
2860 nfs_bwrite(v)
2861 void *v;
2862 {
2863 struct vop_bwrite_args *ap = v;
2864
2865 return (nfs_writebp(ap->a_bp, 1));
2866 }
2867
2868
2869
2870
2871
2872 int
2873 nfs_writebp(bp, force)
2874 struct buf *bp;
2875 int force;
2876 {
2877 int oldflags = bp->b_flags, retv = 1;
2878 struct proc *p = curproc;
2879 off_t off;
2880 size_t cnt;
2881 int s;
2882 struct vnode *vp;
2883 struct nfsnode *np;
2884
2885 if(!(bp->b_flags & B_BUSY))
2886 panic("bwrite: buffer is not busy???");
2887
2888 vp = bp->b_vp;
2889 np = VTONFS(vp);
2890
2891 bp->b_flags &= ~(B_READ|B_DONE|B_ERROR);
2892
2893 s = splbio();
2894 buf_undirty(bp);
2895
2896 if ((oldflags & B_ASYNC) && !(oldflags & B_DELWRI) && p)
2897 ++p->p_stats->p_ru.ru_oublock;
2898
2899 bp->b_vp->v_numoutput++;
2900 splx(s);
2901
2902
2903
2904
2905
2906
2907 if ((oldflags & (B_NEEDCOMMIT | B_WRITEINPROG)) == B_NEEDCOMMIT) {
2908 off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + bp->b_dirtyoff;
2909 cnt = bp->b_dirtyend - bp->b_dirtyoff;
2910
2911 rw_enter_write(&np->n_commitlock);
2912 if (!(bp->b_flags & B_NEEDCOMMIT)) {
2913 rw_exit_write(&np->n_commitlock);
2914 return (0);
2915 }
2916
2917
2918
2919
2920
2921 if (!nfs_in_committed_range(vp, bp)) {
2922 int pushedrange = 0;
2923
2924
2925
2926
2927
2928 if (nfs_in_tobecommitted_range(vp, bp)) {
2929 pushedrange = 1;
2930 off = np->n_pushlo;
2931 cnt = np->n_pushhi - np->n_pushlo;
2932 }
2933
2934 bp->b_flags |= B_WRITEINPROG;
2935 retv = nfs_commit(bp->b_vp, off, cnt, bp->b_proc);
2936 bp->b_flags &= ~B_WRITEINPROG;
2937
2938 if (retv == 0) {
2939 if (pushedrange)
2940 nfs_merge_commit_ranges(vp);
2941 else
2942 nfs_add_committed_range(vp, bp);
2943 }
2944 } else
2945 retv = 0;
2946
2947 rw_exit_write(&np->n_commitlock);
2948 if (!retv) {
2949 bp->b_dirtyoff = bp->b_dirtyend = 0;
2950 bp->b_flags &= ~B_NEEDCOMMIT;
2951 s = splbio();
2952 biodone(bp);
2953 splx(s);
2954 } else if (retv == NFSERR_STALEWRITEVERF)
2955 nfs_clearcommit(bp->b_vp->v_mount);
2956 }
2957 if (retv) {
2958 if (force)
2959 bp->b_flags |= B_WRITEINPROG;
2960 VOP_STRATEGY(bp);
2961 }
2962
2963 if( (oldflags & B_ASYNC) == 0) {
2964 int rtval = biowait(bp);
2965 if (!(oldflags & B_DELWRI) && p) {
2966 ++p->p_stats->p_ru.ru_oublock;
2967 }
2968 brelse(bp);
2969 return (rtval);
2970 }
2971
2972 return (0);
2973 }
2974
2975
2976
2977
2978
2979
2980 int
2981 nfsspec_access(v)
2982 void *v;
2983 {
2984 struct vop_access_args *ap = v;
2985 struct vattr va;
2986 struct vnode *vp = ap->a_vp;
2987 int error;
2988
2989
2990
2991
2992
2993
2994 if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
2995 switch (vp->v_type) {
2996 case VREG:
2997 case VDIR:
2998 case VLNK:
2999 return (EROFS);
3000 default:
3001 break;
3002 }
3003 }
3004
3005 error = VOP_GETATTR(vp, &va, ap->a_cred, ap->a_p);
3006 if (error)
3007 return (error);
3008
3009 return (vaccess(va.va_mode, va.va_uid, va.va_gid, ap->a_mode,
3010 ap->a_cred));
3011 }
3012
3013
3014 int
3015 nfs_poll(v)
3016 void *v;
3017 {
3018 struct vop_poll_args *ap = v;
3019
3020
3021
3022
3023 return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
3024 }
3025
3026
3027
3028
3029 int
3030 nfsspec_read(v)
3031 void *v;
3032 {
3033 struct vop_read_args *ap = v;
3034 struct nfsnode *np = VTONFS(ap->a_vp);
3035
3036
3037
3038
3039 np->n_flag |= NACC;
3040 getnanotime(&np->n_atim);
3041 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap));
3042 }
3043
3044
3045
3046
3047 int
3048 nfsspec_write(v)
3049 void *v;
3050 {
3051 struct vop_write_args *ap = v;
3052 struct nfsnode *np = VTONFS(ap->a_vp);
3053
3054
3055
3056
3057 np->n_flag |= NUPD;
3058 getnanotime(&np->n_mtim);
3059 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap));
3060 }
3061
3062
3063
3064
3065
3066
3067 int
3068 nfsspec_close(v)
3069 void *v;
3070 {
3071 struct vop_close_args *ap = v;
3072 struct vnode *vp = ap->a_vp;
3073 struct nfsnode *np = VTONFS(vp);
3074 struct vattr vattr;
3075
3076 if (np->n_flag & (NACC | NUPD)) {
3077 np->n_flag |= NCHG;
3078 if (vp->v_usecount == 1 &&
3079 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
3080 VATTR_NULL(&vattr);
3081 if (np->n_flag & NACC)
3082 vattr.va_atime = np->n_atim;
3083 if (np->n_flag & NUPD)
3084 vattr.va_mtime = np->n_mtim;
3085 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p);
3086 }
3087 }
3088 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap));
3089 }
3090
3091 #ifdef FIFO
3092
3093
3094
3095 int
3096 nfsfifo_read(v)
3097 void *v;
3098 {
3099 struct vop_read_args *ap = v;
3100 extern int (**fifo_vnodeop_p)(void *);
3101 struct nfsnode *np = VTONFS(ap->a_vp);
3102
3103
3104
3105
3106 np->n_flag |= NACC;
3107 getnanotime(&np->n_atim);
3108 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap));
3109 }
3110
3111
3112
3113
3114 int
3115 nfsfifo_write(v)
3116 void *v;
3117 {
3118 struct vop_write_args *ap = v;
3119 extern int (**fifo_vnodeop_p)(void *);
3120 struct nfsnode *np = VTONFS(ap->a_vp);
3121
3122
3123
3124
3125 np->n_flag |= NUPD;
3126 getnanotime(&np->n_mtim);
3127 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap));
3128 }
3129
3130
3131
3132
3133
3134
3135 int
3136 nfsfifo_close(v)
3137 void *v;
3138 {
3139 struct vop_close_args *ap = v;
3140 struct vnode *vp = ap->a_vp;
3141 struct nfsnode *np = VTONFS(vp);
3142 struct vattr vattr;
3143 extern int (**fifo_vnodeop_p)(void *);
3144
3145 if (np->n_flag & (NACC | NUPD)) {
3146 if (np->n_flag & NACC) {
3147 getnanotime(&np->n_atim);
3148 }
3149 if (np->n_flag & NUPD) {
3150 getnanotime(&np->n_mtim);
3151 }
3152 np->n_flag |= NCHG;
3153 if (vp->v_usecount == 1 &&
3154 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
3155 VATTR_NULL(&vattr);
3156 if (np->n_flag & NACC)
3157 vattr.va_atime = np->n_atim;
3158 if (np->n_flag & NUPD)
3159 vattr.va_mtime = np->n_mtim;
3160 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p);
3161 }
3162 }
3163 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap));
3164 }
3165
3166 int
3167 nfsfifo_reclaim(void *v)
3168 {
3169 fifo_reclaim(v);
3170 return (nfs_reclaim(v));
3171 }
3172 #endif