2 /* $Id: nfs_vnops.c,v 1.45 2003/11/05 14:59:02 rees Exp $ */
6 * the regents of the university of michigan
9 * permission is granted to use, copy, create derivative works and redistribute
10 * this software and such derivative works for any purpose, so long as the name
11 * of the university of michigan is not used in any advertising or publicity
12 * pertaining to the use or distribution of this software without specific,
13 * written prior authorization. if the above copyright notice or any other
14 * identification of the university of michigan is included in any copy of any
15 * portion of this software, then the disclaimer below must also be included.
17 * this software is provided as is, without representation from the university
18 * of michigan as to its fitness for any purpose, and without warranty by the
19 * university of michigan of any kind, either express or implied, including
20 * without limitation the implied warranties of merchantability and fitness for
21 * a particular purpose. the regents of the university of michigan shall not be
22 * liable for any damages, including special, indirect, incidental, or
23 * consequential damages, with respect to any claim arising out of or in
24 * connection with the use of the software, even if it has been or is hereafter
25 * advised of the possibility of such damages.
29 * Copyright (c) 1989, 1993
30 * The Regents of the University of California. All rights reserved.
32 * This code is derived from software contributed to Berkeley by
33 * Rick Macklem at The University of Guelph.
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
38 * 1. Redistributions of source code must retain the above copyright
39 * notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 * notice, this list of conditions and the following disclaimer in the
42 * documentation and/or other materials provided with the distribution.
43 * 4. Neither the name of the University nor the names of its contributors
44 * may be used to endorse or promote products derived from this software
45 * without specific prior written permission.
47 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95
62 #include <sys/cdefs.h>
63 __FBSDID("$FreeBSD$");
66 * vnode op calls for Sun NFS version 2 and 3
71 #include <sys/param.h>
72 #include <sys/kernel.h>
73 #include <sys/systm.h>
74 #include <sys/resourcevar.h>
76 #include <sys/mount.h>
79 #include <sys/malloc.h>
81 #include <sys/namei.h>
82 #include <sys/socket.h>
83 #include <sys/vnode.h>
84 #include <sys/dirent.h>
85 #include <sys/fcntl.h>
86 #include <sys/lockf.h>
88 #include <sys/sysctl.h>
89 #include <sys/lockmgr.h>
92 #include <vm/vm_extern.h>
94 #include <fs/fifofs/fifo.h>
96 #include <rpc/rpcclnt.h>
98 #include <nfs/rpcv2.h>
99 #include <nfs/nfsproto.h>
100 #include <nfsclient/nfs.h>
101 #include <nfs4client/nfs4.h>
102 #include <nfsclient/nfsnode.h>
103 #include <nfsclient/nfsmount.h>
104 #include <nfsclient/nfs_lock.h>
105 #include <nfs/xdr_subs.h>
106 #include <nfsclient/nfsm_subs.h>
109 #include <netinet/in.h>
110 #include <netinet/in_var.h>
113 #include <nfs4client/nfs4m_subs.h>
114 #include <nfs4client/nfs4_vn.h>
121 * Ifdef for FreeBSD-current merged buffer cache. It is unfortunate that these
122 * calls are not in getblk() and brelse() so that they would not be necessary
126 #define vfs_busy_pages(bp, f)
129 static int nfsspec_read(struct vop_read_args *);
130 static int nfsspec_write(struct vop_write_args *);
131 static int nfsfifo_read(struct vop_read_args *);
132 static int nfsfifo_write(struct vop_write_args *);
133 static int nfsspec_close(struct vop_close_args *);
134 static int nfsfifo_close(struct vop_close_args *);
135 static int nfs4_flush(struct vnode *, struct ucred *, int, struct thread *,
137 static int nfs4_setattrrpc(struct vnode *, struct vattr *, struct ucred *,
139 static int nfs4_closerpc(struct vnode *, struct ucred *, struct thread *, int);
141 static int nfs4_lookup(struct vop_lookup_args *);
142 static int nfs4_create(struct vop_create_args *);
143 static int nfs4_mknod(struct vop_mknod_args *);
144 static int nfs4_open(struct vop_open_args *);
145 static int nfs4_close(struct vop_close_args *);
146 static int nfs4_access(struct vop_access_args *);
147 static int nfs4_getattr(struct vop_getattr_args *);
148 static int nfs4_setattr(struct vop_setattr_args *);
149 static int nfs4_read(struct vop_read_args *);
150 static int nfs4_fsync(struct vop_fsync_args *);
151 static int nfs4_remove(struct vop_remove_args *);
152 static int nfs4_link(struct vop_link_args *);
153 static int nfs4_rename(struct vop_rename_args *);
154 static int nfs4_mkdir(struct vop_mkdir_args *);
155 static int nfs4_rmdir(struct vop_rmdir_args *);
156 static int nfs4_symlink(struct vop_symlink_args *);
157 static int nfs4_readdir(struct vop_readdir_args *);
158 static int nfs4_strategy(struct vop_strategy_args *);
159 static int nfs4_lookitup(struct vnode *, const char *, int,
160 struct ucred *, struct thread *, struct nfsnode **);
161 static int nfs4_sillyrename(struct vnode *, struct vnode *,
162 struct componentname *);
163 static int nfsspec_access(struct vop_access_args *);
164 static int nfs4_readlink(struct vop_readlink_args *);
165 static int nfs4_print(struct vop_print_args *);
166 static int nfs4_advlock(struct vop_advlock_args *);
169 * Global vfs data structures for nfs
171 vop_t **nfs4_vnodeop_p;
172 static struct vnodeopv_entry_desc nfs4_vnodeop_entries[] = {
173 { &vop_default_desc, (vop_t *) vop_defaultop },
174 { &vop_access_desc, (vop_t *) nfs4_access },
175 { &vop_advlock_desc, (vop_t *) nfs4_advlock },
176 { &vop_close_desc, (vop_t *) nfs4_close },
177 { &vop_create_desc, (vop_t *) nfs4_create },
178 { &vop_fsync_desc, (vop_t *) nfs4_fsync },
179 { &vop_getattr_desc, (vop_t *) nfs4_getattr },
180 { &vop_getpages_desc, (vop_t *) nfs_getpages },
181 { &vop_putpages_desc, (vop_t *) nfs_putpages },
182 { &vop_inactive_desc, (vop_t *) nfs_inactive },
183 { &vop_lease_desc, (vop_t *) vop_null },
184 { &vop_link_desc, (vop_t *) nfs4_link },
185 { &vop_lookup_desc, (vop_t *) nfs4_lookup },
186 { &vop_mkdir_desc, (vop_t *) nfs4_mkdir },
187 { &vop_mknod_desc, (vop_t *) nfs4_mknod },
188 { &vop_open_desc, (vop_t *) nfs4_open },
189 { &vop_print_desc, (vop_t *) nfs4_print },
190 { &vop_read_desc, (vop_t *) nfs4_read },
191 { &vop_readdir_desc, (vop_t *) nfs4_readdir },
192 { &vop_readlink_desc, (vop_t *) nfs4_readlink },
193 { &vop_reclaim_desc, (vop_t *) nfs_reclaim },
194 { &vop_remove_desc, (vop_t *) nfs4_remove },
195 { &vop_rename_desc, (vop_t *) nfs4_rename },
196 { &vop_rmdir_desc, (vop_t *) nfs4_rmdir },
197 { &vop_setattr_desc, (vop_t *) nfs4_setattr },
198 { &vop_strategy_desc, (vop_t *) nfs4_strategy },
199 { &vop_symlink_desc, (vop_t *) nfs4_symlink },
200 { &vop_write_desc, (vop_t *) nfs_write },
203 static struct vnodeopv_desc nfs4_vnodeop_opv_desc =
204 { &nfs4_vnodeop_p, nfs4_vnodeop_entries };
205 VNODEOP_SET(nfs4_vnodeop_opv_desc);
208 * Special device vnode ops
210 vop_t **spec_nfs4nodeop_p;
211 static struct vnodeopv_entry_desc nfs4_specop_entries[] = {
212 { &vop_default_desc, (vop_t *) spec_vnoperate },
213 { &vop_access_desc, (vop_t *) nfsspec_access },
214 { &vop_close_desc, (vop_t *) nfsspec_close },
215 { &vop_fsync_desc, (vop_t *) nfs4_fsync },
216 { &vop_getattr_desc, (vop_t *) nfs4_getattr },
217 { &vop_inactive_desc, (vop_t *) nfs_inactive },
218 { &vop_print_desc, (vop_t *) nfs4_print },
219 { &vop_read_desc, (vop_t *) nfsspec_read },
220 { &vop_reclaim_desc, (vop_t *) nfs_reclaim },
221 { &vop_setattr_desc, (vop_t *) nfs4_setattr },
222 { &vop_write_desc, (vop_t *) nfsspec_write },
225 static struct vnodeopv_desc spec_nfs4nodeop_opv_desc =
226 { &spec_nfs4nodeop_p, nfs4_specop_entries };
227 VNODEOP_SET(spec_nfs4nodeop_opv_desc);
229 vop_t **fifo_nfs4nodeop_p;
230 static struct vnodeopv_entry_desc nfs4_fifoop_entries[] = {
231 { &vop_default_desc, (vop_t *) fifo_vnoperate },
232 { &vop_access_desc, (vop_t *) nfsspec_access },
233 { &vop_close_desc, (vop_t *) nfsfifo_close },
234 { &vop_fsync_desc, (vop_t *) nfs4_fsync },
235 { &vop_getattr_desc, (vop_t *) nfs4_getattr },
236 { &vop_inactive_desc, (vop_t *) nfs_inactive },
237 { &vop_print_desc, (vop_t *) nfs4_print },
238 { &vop_read_desc, (vop_t *) nfsfifo_read },
239 { &vop_reclaim_desc, (vop_t *) nfs_reclaim },
240 { &vop_setattr_desc, (vop_t *) nfs4_setattr },
241 { &vop_write_desc, (vop_t *) nfsfifo_write },
244 static struct vnodeopv_desc fifo_nfs4nodeop_opv_desc =
245 { &fifo_nfs4nodeop_p, nfs4_fifoop_entries };
246 VNODEOP_SET(fifo_nfs4nodeop_opv_desc);
248 static int nfs4_removerpc(struct vnode *dvp, const char *name, int namelen,
249 struct ucred *cred, struct thread *td);
250 static int nfs4_renamerpc(struct vnode *fdvp, const char *fnameptr,
251 int fnamelen, struct vnode *tdvp,
252 const char *tnameptr, int tnamelen,
253 struct ucred *cred, struct thread *td);
254 static int nfs4_renameit(struct vnode *sdvp, struct componentname *scnp,
255 struct sillyrename *sp);
256 static int nfs4_openrpc(struct vnode *, struct vnode **,
257 struct componentname *, int, struct vattr *);
258 static int nfs4_open_confirm(struct vnode *vp, struct nfs4_compound *cpp,
259 struct nfs4_oparg_open *openap,
260 struct nfs4_oparg_getfh *gfh,
261 struct ucred *cred, struct thread *td);
262 static int nfs4_createrpc(struct vnode *, struct vnode **,
263 struct componentname *, nfstype,
264 struct vattr *, char *);
269 struct nfs4_lowner nfs4_masterlowner;
271 #define DIRHDSIZ (sizeof (struct dirent) - (MAXNAMLEN + 1))
273 SYSCTL_DECL(_vfs_nfs4);
275 static int nfsaccess_cache_timeout = NFS_MAXATTRTIMO;
276 SYSCTL_INT(_vfs_nfs4, OID_AUTO, access_cache_timeout, CTLFLAG_RW,
277 &nfsaccess_cache_timeout, 0, "NFS ACCESS cache timeout");
279 static int nfsv3_commit_on_close = 0;
280 SYSCTL_INT(_vfs_nfs4, OID_AUTO, nfsv3_commit_on_close, CTLFLAG_RW,
281 &nfsv3_commit_on_close, 0, "write+commit on close, else only write");
283 SYSCTL_INT(_vfs_nfs4, OID_AUTO, access_cache_hits, CTLFLAG_RD,
284 &nfsstats.accesscache_hits, 0, "NFS ACCESS cache hit count");
286 SYSCTL_INT(_vfs_nfs4, OID_AUTO, access_cache_misses, CTLFLAG_RD,
287 &nfsstats.accesscache_misses, 0, "NFS ACCESS cache miss count");
290 #define NFSV3ACCESS_ALL (NFSV3ACCESS_READ | NFSV3ACCESS_MODIFY \
291 | NFSV3ACCESS_EXTEND | NFSV3ACCESS_EXECUTE \
292 | NFSV3ACCESS_DELETE | NFSV3ACCESS_LOOKUP)
294 nfs3_access_otw(struct vnode *vp, int wmode, struct thread *td,
299 int error = 0, attrflag;
303 struct mbuf *mreq, *mrep = NULL, *md, *mb;
306 struct nfsnode *np = VTONFS(vp);
308 nfsstats.rpccnt[NFSPROC_ACCESS]++;
309 mreq = nfsm_reqhead(vp, NFSPROC_ACCESS, NFSX_FH(v3) + NFSX_UNSIGNED);
311 bpos = mtod(mb, caddr_t);
313 tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
314 *tl = txdr_unsigned(wmode);
315 nfsm_request(vp, NFSPROC_ACCESS, td, cred);
316 nfsm_postop_attr(vp, attrflag);
318 tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
319 rmode = fxdr_unsigned(u_int32_t, *tl);
321 np->n_modeuid = cred->cr_uid;
322 np->n_modestamp = time_second;
330 * nfs access vnode op.
331 * For nfs version 2, just return ok. File accesses may fail later.
332 * For nfs version 3, use the access rpc to check accessibility. If file modes
333 * are changed on the server, accesses might still fail later.
336 nfs4_access(struct vop_access_args *ap)
338 struct vnode *vp = ap->a_vp;
340 u_int32_t mode, wmode;
341 int v3 = NFS_ISV3(vp); /* v3 \in v4 */
342 struct nfsnode *np = VTONFS(vp);
344 struct mbuf *mreq, *mrep = NULL, *md, *mb;
345 struct nfs4_compound cp;
346 struct nfs4_oparg_access acc;
347 struct thread *td = ap->a_td;
348 struct ucred *cred = ap->a_cred;
351 * Disallow write attempts on filesystems mounted read-only;
352 * unless the file is a socket, fifo, or a block or character
353 * device resident on the filesystem.
355 if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
356 switch (vp->v_type) {
366 * For nfs v3, check to see if we have done this recently, and if
367 * so return our cached result instead of making an ACCESS call.
368 * If not, do an access rpc, otherwise you are stuck emulating
369 * ufs_access() locally using the vattr. This may not be correct,
370 * since the server may apply other access criteria such as
371 * client uid-->server uid mapping that we do not know about.
373 /* XXX Disable this for now; needs fixing of _access_otw() */
375 if (ap->a_mode & VREAD)
376 mode = NFSV3ACCESS_READ;
379 if (vp->v_type != VDIR) {
380 if (ap->a_mode & VWRITE)
381 mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
382 if (ap->a_mode & VEXEC)
383 mode |= NFSV3ACCESS_EXECUTE;
385 if (ap->a_mode & VWRITE)
386 mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
388 if (ap->a_mode & VEXEC)
389 mode |= NFSV3ACCESS_LOOKUP;
391 /* XXX safety belt, only make blanket request if caching */
392 if (nfsaccess_cache_timeout > 0) {
393 wmode = NFSV3ACCESS_READ | NFSV3ACCESS_MODIFY |
394 NFSV3ACCESS_EXTEND | NFSV3ACCESS_EXECUTE |
395 NFSV3ACCESS_DELETE | NFSV3ACCESS_LOOKUP;
401 * Does our cached result allow us to give a definite yes to
404 if ((time_second < (np->n_modestamp + nfsaccess_cache_timeout)) &&
405 (ap->a_cred->cr_uid == np->n_modeuid) &&
406 ((np->n_mode & mode) == mode)) {
407 nfsstats.accesscache_hits++;
410 * Either a no, or a don't know. Go to the wire.
412 nfsstats.accesscache_misses++;
413 error = nfs3_access_otw(vp, wmode, ap->a_td,ap->a_cred);
415 if ((np->n_mode & mode) != mode) {
423 /* XXX use generic access code here? */
424 mode = ap->a_mode & VREAD ? NFSV4ACCESS_READ : 0;
425 if (vp->v_type == VDIR) {
426 if (ap->a_mode & VWRITE)
427 mode |= NFSV4ACCESS_MODIFY | NFSV4ACCESS_EXTEND | NFSV4ACCESS_DELETE;
428 if (ap->a_mode & VEXEC)
429 mode |= NFSV4ACCESS_LOOKUP;
431 if (ap->a_mode & VWRITE)
432 mode |= NFSV4ACCESS_MODIFY | NFSV4ACCESS_EXTEND;
433 if (ap->a_mode & VEXEC)
434 mode |= NFSV4ACCESS_EXECUTE;
437 nfs_v4initcompound(&cp);
440 mreq = nfsm_reqhead(vp, NFSV4PROC_COMPOUND, 0);
442 bpos = mtod(mb, caddr_t);
444 nfsm_v4build_compound(&cp, "nfs4_access()");
445 nfsm_v4build_putfh(&cp, vp);
446 nfsm_v4build_access(&cp, &acc);
447 nfsm_v4build_finalize(&cp);
449 nfsm_request(vp, NFSV4PROC_COMPOUND, td, cred);
453 nfsm_v4dissect_compound(&cp);
454 nfsm_v4dissect_putfh(&cp);
455 nfsm_v4dissect_access(&cp, &acc);
457 if ((acc.rmode & mode) != mode)
461 error = nfs_v4postop(&cp, error);
470 nfs4_openrpc(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp,
471 int flags, struct vattr *vap)
473 struct vnode *vp = *vpp;
474 struct nfs4_oparg_getattr getattr;
475 struct nfs4_oparg_getfh getfh;
476 struct nfs4_oparg_open opena;
477 struct nfs4_compound cp;
480 struct mbuf *mreq, *mrep = NULL, *md, *mb;
481 struct ucred *cred = cnp->cn_cred;
482 struct thread *td = cnp->cn_thread;
483 struct nfs4_fctx xfc, *fcp;
487 /* Create a new file */
490 bzero(fcp, sizeof(*fcp));
493 fcp = flags & FWRITE ? &np->n_wfc : &np->n_rfc;
497 * Since we are currently only one lockowner; we only open the
498 * file once each for reading and writing.
500 if (fcp->refcnt++ != 0) {
502 /*printf("not opening %s\n", np->n_name != NULL ? np->n_name : "");*/
506 fcp->lop = &nfs4_masterlowner;
509 nfs_v4initcompound(&cp);
510 cp.nmp = VFSTONFS(dvp->v_mount);
512 opena.ctype = NCLNULL;
515 opena.fcp = fcp; /* For lockowner */
518 getattr.bm = &nfsv4_getattrbm;
520 mreq = nfsm_reqhead(vp, NFSV4PROC_COMPOUND, 0);
522 bpos = mtod(mb, caddr_t);
524 nfsm_v4build_compound(&cp, "nfs4_openrpc()");
525 nfsm_v4build_putfh(&cp, dvp);
526 nfsm_v4build_open(&cp, &opena);
527 nfsm_v4build_getattr(&cp, &getattr);
528 nfsm_v4build_getfh(&cp, &getfh);
529 nfsm_v4build_finalize(&cp);
531 nfsm_request(vp != NULL ? vp : dvp, NFSV4PROC_COMPOUND, td, cred);
535 nfsm_v4dissect_compound(&cp);
536 nfsm_v4dissect_putfh(&cp);
537 nfsm_v4dissect_open(&cp, &opena);
538 nfsm_v4dissect_getattr(&cp, &getattr);
539 nfsm_v4dissect_getfh(&cp, &getfh);
541 error = nfs_v4postop(&cp, error);
543 if (opena.rflags & NFSV4OPENRES_CONFIRM) {
544 error = nfs4_open_confirm(vp ? vp : dvp, &cp, &opena, &getfh, cred, td);
551 error = nfs_nget(dvp->v_mount, &getfh.fh_val,
558 np->n_namelen = cnp->cn_namelen; /* XXX memory leaks on these; track! */
559 if (np->n_name != NULL)
560 FREE(np->n_name, M_NFSREQ);
561 MALLOC(np->n_name, u_char *, np->n_namelen + 1, M_NFSREQ, M_WAITOK);
562 bcopy(cnp->cn_nameptr, np->n_name, np->n_namelen);
563 np->n_name[np->n_namelen] = '\0';
569 /*printf("opened new file %s\n", np->n_name);*/
571 nfs4_vnop_loadattrcache(vp, &getattr.fa, NULL);
574 /*printf("openend \"old\" %s\n", np->n_name != NULL ? np->n_name : "");*/
576 if (flags & O_TRUNC && np->n_size != 0) {
581 error = nfs4_setattrrpc(vp, &va,
582 cnp->cn_cred, cnp->cn_thread);
595 nfs4_open_confirm(struct vnode *vp, struct nfs4_compound *cpp,
596 struct nfs4_oparg_open *openap, struct nfs4_oparg_getfh *gfh,
597 struct ucred *cred, struct thread *td)
601 struct mbuf *mreq, *mrep = NULL, *md, *mb;
603 nfs_v4initcompound(cpp);
604 cpp->nmp = VFSTONFS(vp->v_mount);
606 mreq = nfsm_reqhead(vp, NFSV4PROC_COMPOUND, 0);
608 bpos = mtod(mb, caddr_t);
610 nfsm_v4build_compound(cpp, "nfs4_open_confirm()");
611 nfsm_v4build_putfh_nv(cpp, gfh);
612 nfsm_v4build_open_confirm(cpp, openap);
613 nfsm_v4build_finalize(cpp);
615 nfsm_request(vp, NFSV4PROC_COMPOUND, td, cred);
619 nfsm_v4dissect_compound(cpp);
620 nfsm_v4dissect_putfh(cpp);
621 nfsm_v4dissect_open_confirm(cpp, openap);
624 error = nfs_v4postop(cpp, error);
635 * Check to see if the type is ok
636 * and that deletion is not in progress.
637 * For paged in text files, you will need to flush the page cache
638 * if consistency is lost.
642 nfs4_open(struct vop_open_args *ap)
644 struct vnode *vp = ap->a_vp;
645 struct nfsnode *np = VTONFS(vp);
646 enum vtype vtype = vp->v_type;
647 int mode = ap->a_mode;
648 struct componentname cn;
651 if (vtype != VDIR && vtype != VLNK) {
653 printf("open eacces vtyp=%d\n", vp->v_type);
660 if (np->n_flag & NCREATED) {
661 np->n_flag &= ~NCREATED;
665 cn.cn_nameptr = np->n_name;
666 cn.cn_namelen = np->n_namelen;
667 cn.cn_cred = ap->a_cred;
668 cn.cn_thread = ap->a_td;
670 return (nfs4_openrpc(np->n_dvp, &vp, &cn, mode, NULL));
674 nfs4_closerpc(struct vnode *vp, struct ucred *cred, struct thread *td, int flags)
678 struct mbuf *mreq, *mrep = NULL, *md, *mb;
679 struct nfs4_fctx *fcp;
680 struct nfs4_compound cp;
681 struct nfsnode *np = VTONFS(vp);
683 fcp = flags & FWRITE ? &np->n_wfc : &np->n_rfc;
685 nfs_v4initcompound(&cp);
687 if (--fcp->refcnt != 0)
690 /*printf("closing %s\n", np->n_name != NULL ? np->n_name : "");*/
694 mreq = nfsm_reqhead(vp, NFSV4PROC_COMPOUND, 0);
696 bpos = mtod(mb, caddr_t);
698 nfsm_v4build_compound(&cp, "nfs4_closerpc()");
699 nfsm_v4build_putfh(&cp, vp);
700 nfsm_v4build_close(&cp, fcp);
701 nfsm_v4build_finalize(&cp);
703 nfsm_request(vp, NFSV4PROC_COMPOUND, td, cred);
707 nfsm_v4dissect_compound(&cp);
708 nfsm_v4dissect_putfh(&cp);
709 nfsm_v4dissect_close(&cp, fcp);
712 error = nfs_v4postop(&cp, error);
722 * play it safe for now (see comments in v2/v3 nfs_close regarding dirty buffers)
726 nfs4_close(struct vop_close_args *ap)
728 struct vnode *vp = ap->a_vp;
729 struct nfsnode *np = VTONFS(vp);
732 if (vp->v_type != VREG)
735 if (np->n_flag & NMODIFIED) {
736 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, ap->a_td);
737 error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_td, 1);
738 VOP_UNLOCK(vp, 0, ap->a_td);
742 error = nfs4_closerpc(vp, ap->a_cred, ap->a_td, ap->a_fflag);
744 if (!error && np->n_flag & NWRITEERR) {
745 np->n_flag &= ~NWRITEERR;
752 * nfs getattr call from vfs.
755 nfs4_getattr(struct vop_getattr_args *ap)
757 struct vnode *vp = ap->a_vp;
758 struct nfsnode *np = VTONFS(vp);
761 struct mbuf *mreq, *mrep = NULL, *md, *mb;
762 struct nfs4_oparg_getattr ga;
763 struct nfs4_compound cp;
766 * Update local times for special files.
768 if (np->n_flag & (NACC | NUPD))
771 * First look in the cache.
773 if (nfs_getattrcache(vp, ap->a_vap) == 0)
776 nfsstats.rpccnt[NFSPROC_GETATTR]++;
778 mreq = nfsm_reqhead(vp, NFSV4PROC_COMPOUND, NFSX_FH(1));
780 bpos = mtod(mb, caddr_t);
782 ga.bm = &nfsv4_getattrbm;
783 nfs_v4initcompound(&cp);
785 nfsm_v4build_compound(&cp, "nfs4_getattr()");
786 nfsm_v4build_putfh(&cp, vp);
787 nfsm_v4build_getattr(&cp, &ga);
788 nfsm_v4build_finalize(&cp);
790 nfsm_request(vp, NFSV4PROC_COMPOUND, ap->a_td, ap->a_cred);
794 nfsm_v4dissect_compound(&cp);
795 nfsm_v4dissect_putfh(&cp);
796 nfsm_v4dissect_getattr(&cp, &ga);
798 nfs4_vnop_loadattrcache(vp, &ga.fa, ap->a_vap);
801 error = nfs_v4postop(&cp, error);
812 nfs4_setattr(struct vop_setattr_args *ap)
814 struct vnode *vp = ap->a_vp;
815 struct nfsnode *np = VTONFS(vp);
816 struct vattr *vap = ap->a_vap;
825 * Setting of flags is not supported.
827 if (vap->va_flags != VNOVAL)
831 * Disallow write attempts if the filesystem is mounted read-only.
833 if ((vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
834 vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
835 vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) &&
836 (vp->v_mount->mnt_flag & MNT_RDONLY))
838 if (vap->va_size != VNOVAL) {
839 switch (vp->v_type) {
846 if (vap->va_mtime.tv_sec == VNOVAL &&
847 vap->va_atime.tv_sec == VNOVAL &&
848 vap->va_mode == (mode_t)VNOVAL &&
849 vap->va_uid == (uid_t)VNOVAL &&
850 vap->va_gid == (gid_t)VNOVAL)
852 vap->va_size = VNOVAL;
856 * Disallow write attempts if the filesystem is
859 if (vp->v_mount->mnt_flag & MNT_RDONLY)
863 * We run vnode_pager_setsize() early (why?),
864 * we must set np->n_size now to avoid vinvalbuf
865 * V_SAVE races that might setsize a lower
870 error = nfs_meta_setsize(vp, ap->a_cred,
871 ap->a_td, vap->va_size);
873 if (np->n_flag & NMODIFIED) {
874 if (vap->va_size == 0)
875 error = nfs_vinvalbuf(vp, 0,
876 ap->a_cred, ap->a_td, 1);
878 error = nfs_vinvalbuf(vp, V_SAVE,
879 ap->a_cred, ap->a_td, 1);
881 vnode_pager_setsize(vp, np->n_size);
886 * np->n_size has already been set to vap->va_size
887 * in nfs_meta_setsize(). We must set it again since
888 * nfs_loadattrcache() could be called through
889 * nfs_meta_setsize() and could modify np->n_size.
891 np->n_vattr.va_size = np->n_size = vap->va_size;
893 } else if ((vap->va_mtime.tv_sec != VNOVAL ||
894 vap->va_atime.tv_sec != VNOVAL) && (np->n_flag & NMODIFIED) &&
895 vp->v_type == VREG &&
896 (error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
897 ap->a_td, 1)) == EINTR)
900 if (vap->va_size != VNOVAL && np->n_wfc.refcnt == 0) {
901 /* Have to open the file before we can truncate it */
902 struct componentname cn;
904 cn.cn_nameptr = np->n_name;
905 cn.cn_namelen = np->n_namelen;
906 cn.cn_cred = ap->a_cred;
907 cn.cn_thread = ap->a_td;
908 error = nfs4_openrpc(np->n_dvp, &vp, &cn, FWRITE, NULL);
911 np->n_flag |= NTRUNCATE;
914 error = nfs4_setattrrpc(vp, vap, ap->a_cred, ap->a_td);
915 if (error && vap->va_size != VNOVAL) {
916 np->n_size = np->n_vattr.va_size = tsize;
917 vnode_pager_setsize(vp, np->n_size);
923 * Do an nfs setattr rpc.
926 nfs4_setattrrpc(struct vnode *vp, struct vattr *vap, struct ucred *cred,
931 struct mbuf *mreq, *mrep = NULL, *md, *mb;
932 struct nfs4_compound cp;
933 struct nfs4_oparg_getattr ga;
934 struct nfsnode *np = VTONFS(vp);
935 struct nfs4_fctx *fcp;
937 nfsstats.rpccnt[NFSPROC_SETATTR]++;
938 mreq = nfsm_reqhead(vp, NFSV4PROC_COMPOUND, 0);
940 bpos = mtod(mb, caddr_t);
942 ga.bm = &nfsv4_getattrbm;
943 fcp = (vap->va_size != VNOVAL) ? &np->n_wfc : NULL;
944 nfs_v4initcompound(&cp);
946 nfsm_v4build_compound(&cp, "nfs4_setattrrpc");
947 nfsm_v4build_putfh(&cp, vp);
948 nfsm_v4build_setattr(&cp, vap, fcp);
949 nfsm_v4build_getattr(&cp, &ga);
950 nfsm_v4build_finalize(&cp);
952 nfsm_request(vp, NFSV4PROC_COMPOUND, td, cred);
956 nfsm_v4dissect_compound(&cp);
957 nfsm_v4dissect_putfh(&cp);
958 nfsm_v4dissect_setattr(&cp);
959 nfsm_v4dissect_getattr(&cp, &ga);
961 nfs4_vnop_loadattrcache(vp, &ga.fa, NULL);
963 /* TODO: do the settatr and close in a single compound rpc */
964 if (np->n_flag & NTRUNCATE) {
965 error = nfs4_closerpc(vp, cred, td, FWRITE);
966 np->n_flag &= ~NTRUNCATE;
970 error = nfs_v4postop(&cp, error);
979 * nfs lookup call, one step at a time...
980 * First look in cache
981 * If not found, unlock the directory nfsnode and do the rpc
984 nfs4_lookup(struct vop_lookup_args *ap)
986 struct componentname *cnp = ap->a_cnp;
987 struct vnode *dvp = ap->a_dvp;
988 struct vnode **vpp = ap->a_vpp;
989 int isdot, flags = cnp->cn_flags;
991 struct nfsmount *nmp;
993 struct mbuf *mreq, *mrep = NULL, *md, *mb;
997 int lockparent, wantparent, error = 0, fhsize;
998 struct thread *td = cnp->cn_thread;
999 struct nfs4_compound cp;
1000 struct nfs4_oparg_getattr ga, dga;
1001 struct nfs4_oparg_lookup l;
1002 struct nfs4_oparg_getfh gfh;
1005 cnp->cn_flags &= ~PDIRUNLOCK;
1006 if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
1007 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
1009 if (dvp->v_type != VDIR)
1011 lockparent = flags & LOCKPARENT;
1012 wantparent = flags & (LOCKPARENT|WANTPARENT);
1013 nmp = VFSTONFS(dvp->v_mount);
1016 isdot = cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.';
1018 if ((error = cache_lookup(dvp, vpp, cnp)) && error != ENOENT) {
1022 if ((error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, td)) != 0) {
1031 * See the comment starting `Step through' in ufs/ufs_lookup.c
1032 * for an explanation of the locking protocol
1037 } else if (flags & ISDOTDOT) {
1038 VOP_UNLOCK(dvp, 0, td);
1039 cnp->cn_flags |= PDIRUNLOCK;
1040 error = vget(newvp, LK_EXCLUSIVE, td);
1041 if (!error && lockparent && (flags & ISLASTCN)) {
1042 error = vn_lock(dvp, LK_EXCLUSIVE, td);
1044 cnp->cn_flags &= ~PDIRUNLOCK;
1047 error = vget(newvp, LK_EXCLUSIVE, td);
1048 if (!lockparent || error || !(flags & ISLASTCN)) {
1049 VOP_UNLOCK(dvp, 0, td);
1050 cnp->cn_flags |= PDIRUNLOCK;
1054 if (vpid == newvp->v_id) {
1055 if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, td)
1056 && vattr.va_ctime.tv_sec == VTONFS(newvp)->n_ctime) {
1057 nfsstats.lookupcache_hits++;
1058 if (cnp->cn_nameiop != LOOKUP &&
1060 cnp->cn_flags |= SAVENAME;
1067 if (lockparent && dvp != newvp && (flags & ISLASTCN))
1068 VOP_UNLOCK(dvp, 0, td);
1071 error = vn_lock(dvp, LK_EXCLUSIVE, td);
1074 cnp->cn_flags |= PDIRUNLOCK;
1077 cnp->cn_flags &= ~PDIRUNLOCK;
1082 nfsstats.lookupcache_misses++;
1083 nfsstats.rpccnt[NFSPROC_LOOKUP]++;
1085 len = cnp->cn_namelen;
1086 mreq = nfsm_reqhead(NULL, NFSV4PROC_COMPOUND, 0);
1088 bpos = mtod(mb, caddr_t);
1090 ga.bm = &nfsv4_getattrbm;
1091 dga.bm = &nfsv4_getattrbm;
1092 nfs_v4initcompound(&cp);
1094 nfsm_v4build_compound(&cp, "nfs4_lookup()");
1095 nfsm_v4build_putfh(&cp, dvp);
1096 nfsm_v4build_getattr(&cp, &dga);
1097 if (flags & ISDOTDOT)
1098 nfsm_v4build_lookupp(&cp);
1100 l.name = cnp->cn_nameptr;
1102 nfsm_v4build_lookup(&cp, &l);
1104 nfsm_v4build_getattr(&cp, &ga);
1105 nfsm_v4build_getfh(&cp, &gfh);
1106 nfsm_v4build_finalize(&cp);
1108 nfsm_request(dvp, NFSV4PROC_COMPOUND, cnp->cn_thread, cnp->cn_cred);
1112 nfsm_v4dissect_compound(&cp);
1113 nfsm_v4dissect_putfh(&cp);
1114 nfsm_v4dissect_getattr(&cp, &dga);
1115 if (flags & ISDOTDOT)
1116 nfsm_v4dissect_lookupp(&cp);
1118 nfsm_v4dissect_lookup(&cp);
1119 nfsm_v4dissect_getattr(&cp, &ga);
1120 nfsm_v4dissect_getfh(&cp, &gfh);
1122 nfs4_vnop_loadattrcache(dvp, &dga.fa, NULL);
1124 fhsize = gfh.fh_len;
1127 * Handle RENAME case...
1129 if (cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)) {
1130 if (NFS_CMPFH(np, fhp, fhsize))
1133 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
1139 nfs4_vnop_loadattrcache(newvp, &ga.fa, NULL);
1142 cnp->cn_flags |= SAVENAME;
1144 VOP_UNLOCK(dvp, 0, td);
1145 cnp->cn_flags |= PDIRUNLOCK;
1150 if (flags & ISDOTDOT) {
1151 VOP_UNLOCK(dvp, 0, td);
1153 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
1155 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td);
1160 nfs4_vnop_loadattrcache(newvp, &ga.fa, NULL);
1162 if (lockparent && (flags & ISLASTCN)) {
1163 error = vn_lock(dvp, LK_EXCLUSIVE, td);
1165 cnp->cn_flags |= PDIRUNLOCK;
1170 cnp->cn_flags |= PDIRUNLOCK;
1171 } else if (NFS_CMPFH(np, fhp, fhsize)) {
1175 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
1179 if (!lockparent || !(flags & ISLASTCN)) {
1180 cnp->cn_flags |= PDIRUNLOCK;
1181 VOP_UNLOCK(dvp, 0, td);
1185 /* Fill in np used by open. */
1187 np->n_namelen = cnp->cn_namelen;
1188 if (np->n_name != NULL)
1189 FREE(np->n_name, M_NFSREQ);
1190 MALLOC(np->n_name, u_char *, np->n_namelen + 1, M_NFSREQ, M_WAITOK);
1191 bcopy(cnp->cn_nameptr, np->n_name, np->n_namelen);
1192 np->n_name[np->n_namelen] = '\0';
1194 nfs4_vnop_loadattrcache(newvp, &ga.fa, NULL);
1197 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
1198 cnp->cn_flags |= SAVENAME;
1199 if ((cnp->cn_flags & MAKEENTRY) &&
1200 (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) {
1201 np->n_ctime = np->n_vattr.va_ctime.tv_sec;
1202 cache_enter(dvp, newvp, cnp);
1207 error = nfs_v4postop(&cp, error);
1210 if (newvp != NULLVP) {
1214 if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) &&
1215 (flags & ISLASTCN) && error == ENOENT) {
1217 VOP_UNLOCK(dvp, 0, td);
1218 cnp->cn_flags |= PDIRUNLOCK;
1220 if (dvp->v_mount->mnt_flag & MNT_RDONLY)
1223 error = EJUSTRETURN;
1225 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
1226 cnp->cn_flags |= SAVENAME;
1234 * Just call nfs_bioread() to do the work.
1237 nfs4_read(struct vop_read_args *ap)
1239 struct vnode *vp = ap->a_vp;
1241 switch (vp->v_type) {
1243 return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred));
1247 return (EOPNOTSUPP);
1255 nfs4_readlink(struct vop_readlink_args *ap)
1257 struct vnode *vp = ap->a_vp;
1259 if (vp->v_type != VLNK)
1261 return (nfs_bioread(vp, ap->a_uio, 0, ap->a_cred));
1265 * Do a readlink rpc.
1266 * Called by nfs_doio() from below the buffer cache.
1269 nfs4_readlinkrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred)
1273 struct mbuf *mreq, *mrep = NULL, *md, *mb;
1274 struct nfs4_compound cp;
1276 nfsstats.rpccnt[NFSPROC_READLINK]++;
1278 mreq = nfsm_reqhead(vp, NFSV4PROC_COMPOUND, 0);
1280 bpos = mtod(mb, caddr_t);
1282 nfs_v4initcompound(&cp);
1284 nfsm_v4build_compound(&cp, "nfs4_readlinkrpc()");
1285 nfsm_v4build_putfh(&cp, vp);
1286 nfsm_v4build_readlink(&cp);
1287 nfsm_v4build_finalize(&cp);
1289 nfsm_request(vp, NFSV4PROC_COMPOUND, uiop->uio_td, cred);
1293 nfsm_v4dissect_compound(&cp);
1294 nfsm_v4dissect_putfh(&cp);
1295 nfsm_v4dissect_readlink(&cp, uiop);
1298 error = nfs_v4postop(&cp, error);
1300 if (m_freem != NULL)
1310 nfs4_readrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred)
1313 struct mbuf *mreq, *mrep = NULL, *md, *mb;
1314 struct nfsmount *nmp;
1315 int error = 0, len, tsiz;
1316 struct nfs4_compound cp;
1317 struct nfs4_oparg_read read;
1318 struct nfsnode *np = VTONFS(vp);
1320 nmp = VFSTONFS(vp->v_mount);
1321 tsiz = uiop->uio_resid;
1322 if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize)
1329 read.fcp = np->n_rfc.refcnt > 0 ? &np->n_rfc : &np->n_wfc;
1332 nfsstats.rpccnt[NFSPROC_READ]++;
1333 len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz;
1335 read.off = uiop->uio_offset;
1337 nfs_v4initcompound(&cp);
1339 mreq = nfsm_reqhead(vp, NFSV4PROC_COMPOUND, 0);
1341 bpos = mtod(mb, caddr_t);
1343 nfsm_v4build_compound(&cp, "nfs4_readrpc()");
1344 nfsm_v4build_putfh(&cp, vp);
1345 nfsm_v4build_read(&cp, &read);
1346 nfsm_v4build_finalize(&cp);
1348 nfsm_request(vp, NFSV4PROC_COMPOUND, uiop->uio_td, cred);
1350 error = nfs_v4postop(&cp, error);
1354 nfsm_v4dissect_compound(&cp);
1355 nfsm_v4dissect_putfh(&cp);
1356 nfsm_v4dissect_read(&cp, &read);
1358 if (read.eof || read.retlen == 0)
1361 tsiz -= read.retlen;
1363 error = nfs_v4postop(&cp, error);
1379 nfs4_writerpc(struct vnode *vp, struct uio *uiop, struct ucred *cred,
1380 int *iomode, int *must_commit)
1384 struct mbuf *mreq, *mrep = NULL, *md, *mb;
1385 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
1386 int error = 0, len, tsiz, wccflag = 1, rlen;
1387 struct nfs4_compound cp;
1388 struct nfs4_oparg_write write;
1389 nfsv4stablehow commit, committed = NSHFILESYNC;
1391 struct nfsnode *np = VTONFS(vp);
1394 if (uiop->uio_iovcnt != 1)
1395 panic("nfs: writerpc iovcnt > 1");
1398 tsiz = uiop->uio_resid;
1399 if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize)
1405 write.stable = (nfsv4stablehow)*iomode;
1407 write.fcp = &np->n_wfc;
1410 nfsstats.rpccnt[NFSPROC_WRITE]++;
1411 len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz;
1413 write.off = uiop->uio_offset;
1415 nfs_v4initcompound(&cp);
1417 mreq = nfsm_reqhead(vp, NFSV4PROC_COMPOUND, 0);
1419 bpos = mtod(mb, caddr_t);
1421 nfsm_v4build_compound(&cp, "nfs4_writerpc()");
1422 nfsm_v4build_putfh(&cp, vp);
1423 nfsm_v4build_write(&cp, &write);
1424 nfsm_v4build_finalize(&cp);
1426 nfsm_request(vp, NFSV4PROC_COMPOUND, uiop->uio_td, cred);
1428 error = nfs_v4postop(&cp, error);
1432 nfsm_v4dissect_compound(&cp);
1433 nfsm_v4dissect_putfh(&cp);
1434 nfsm_v4dissect_write(&cp, &write);
1436 rlen = write.retlen;
1440 } else if (rlen < len) {
1441 backup = len - rlen;
1442 uiop->uio_iov->iov_base =
1443 (char *)uiop->uio_iov->iov_base - backup;
1444 uiop->uio_iov->iov_len += backup;
1445 uiop->uio_offset -= backup;
1446 uiop->uio_resid += backup;
1450 commit = write.committed;
1452 if (committed == NSHFILESYNC ||
1453 (committed = NSHDATASYNC && commit == NSHUNSTABLE))
1456 verf = (caddr_t)write.wverf;
1458 if ((nmp->nm_flag & NFSSTA_HASWRITEVERF) == 0) {
1459 bcopy(verf, nmp->nm_verf, NFSX_V4VERF);
1460 nmp->nm_flag |= NFSMNT_HASWRITEVERF;
1461 } else if (bcmp(verf, nmp->nm_verf, NFSX_V4VERF)) {
1463 bcopy(verf, nmp->nm_verf, NFSX_V4VERF);
1468 VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime.tv_sec;
1470 error = nfs_v4postop(&cp, error);
1481 *iomode = committed;
1483 uiop->uio_resid = tsiz;
1489 nfs4_mknod(struct vop_mknod_args *ap)
1491 struct vattr *vap = ap->a_vap;
1492 struct vnode *newvp = NULL;
1495 error = nfs4_createrpc(ap->a_dvp, &newvp,
1496 ap->a_cnp, (nfstype)vap->va_type, vap, NULL);
1498 /* XXX - is this actually referenced here? */
1508 nfs4_createrpc(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp,
1509 nfstype ftype, struct vattr *vap, char *linktarget)
1511 struct nfsnode *dnp = VTONFS(dvp);
1512 struct nfsnode *np = NULL;
1513 struct vnode *newvp = NULL;
1514 struct nfs4_compound cp;
1515 struct nfs4_oparg_create c;
1516 struct nfs4_oparg_getattr ga;
1517 struct nfs4_oparg_getfh gfh;
1519 struct mbuf *mreq, *mrep = NULL, *md, *mb;
1522 nfsstats.rpccnt[NFSPROC_CREATE]++;
1524 mreq = nfsm_reqhead(dvp, NFSV4PROC_COMPOUND, 0);
1526 bpos = mtod(mb, caddr_t);
1528 bzero(&c, sizeof(c));
1529 bzero(&ga, sizeof(ga));
1533 c.linktext = linktarget;
1534 c.name = cnp->cn_nameptr;
1535 c.namelen = cnp->cn_namelen;
1537 ga.bm = &nfsv4_getattrbm;
1538 nfs_v4initcompound(&cp);
1540 nfsm_v4build_compound(&cp, "nfs4_createrpc()");
1541 nfsm_v4build_putfh(&cp, dvp);
1542 nfsm_v4build_create(&cp, &c);
1543 nfsm_v4build_getattr(&cp, &ga);
1544 nfsm_v4build_getfh(&cp, &gfh);
1545 nfsm_v4build_finalize(&cp);
1547 nfsm_request(dvp, NFSV4PROC_COMPOUND, cnp->cn_thread, cnp->cn_cred);
1551 nfsm_v4dissect_compound(&cp);
1552 nfsm_v4dissect_putfh(&cp);
1553 nfsm_v4dissect_create(&cp, &c);
1554 nfsm_v4dissect_getattr(&cp, &ga);
1555 nfsm_v4dissect_getfh(&cp, &gfh);
1557 error = nfs_nget(dvp->v_mount, &gfh.fh_val, gfh.fh_len, &np);
1562 nfs4_vnop_loadattrcache(newvp, &ga.fa, NULL);
1564 if (cnp->cn_flags & MAKEENTRY)
1565 cache_enter(dvp, newvp, cnp);
1567 dnp->n_flag |= NMODIFIED;
1568 dnp->n_attrstamp = 0;
1571 error = nfs_v4postop(&cp, error);
1577 /*FREE(cnp->cn_pnbuf, M_NAMEI);*/
1578 if (error != 0 && newvp != NULL)
1580 else if (error == 0)
1587 nfs4_renamerpc(struct vnode *fdvp, const char *fnameptr, int fnamelen,
1588 struct vnode *tdvp, const char *tnameptr, int tnamelen,
1589 struct ucred *cred, struct thread *td)
1592 struct nfsnode *fnp = VTONFS(fdvp), *tnp = VTONFS(tdvp);
1594 struct mbuf *mreq, *mrep = NULL, *md, *mb;
1595 struct nfs4_compound cp;
1596 struct nfs4_oparg_rename r;
1599 nfsstats.rpccnt[NFSPROC_RENAME]++;
1602 r.fnamelen = fnamelen;
1604 r.tnamelen = tnamelen;
1605 nfs_v4initcompound(&cp);
1607 mreq = nfsm_reqhead(fdvp, NFSV4PROC_COMPOUND, 0);
1609 bpos = mtod(mb, caddr_t);
1611 nfsm_v4build_compound(&cp, "nfs4_renamerpc()");
1612 nfsm_v4build_putfh(&cp, fdvp);
1613 nfsm_v4build_savefh(&cp);
1614 nfsm_v4build_putfh(&cp, tdvp);
1615 nfsm_v4build_rename(&cp, &r);
1616 nfsm_v4build_finalize(&cp);
1618 nfsm_request(fdvp, NFSV4PROC_COMPOUND, td, cred);
1622 nfsm_v4dissect_compound(&cp);
1623 nfsm_v4dissect_putfh(&cp);
1624 nfsm_v4dissect_savefh(&cp);
1625 nfsm_v4dissect_putfh(&cp);
1626 nfsm_v4dissect_rename(&cp);
1628 /* XXX should this always be performed? */
1629 fnp->n_flag |= NMODIFIED;
1630 tnp->n_flag |= NMODIFIED;
1631 fnp->n_attrstamp = tnp->n_attrstamp = 0;
1634 error = nfs_v4postop(&cp, error);
1643 * nfs file create call
1646 nfs4_create(struct vop_create_args *ap)
1648 struct vnode *dvp = ap->a_dvp;
1649 struct vattr *vap = ap->a_vap;
1650 struct nfsnode *dnp = VTONFS(dvp);
1651 struct componentname *cnp = ap->a_cnp;
1652 struct vnode *newvp = NULL;
1653 int error = 0, fmode = (O_CREAT | FREAD | FWRITE);
1656 if ((error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_thread)) != 0)
1659 if (vap->va_vaflags & VA_EXCLUSIVE)
1662 error = nfs4_openrpc(dvp, &newvp, cnp, fmode, vap);
1666 VTONFS(newvp)->n_flag |= NCREATED;
1668 if (cnp->cn_flags & MAKEENTRY)
1669 cache_enter(dvp, newvp, cnp);
1673 dnp->n_flag |= NMODIFIED;
1674 dnp->n_attrstamp = 0; /* XXX; wccflag */
1681 * nfs file remove call
1682 * To try and make nfs semantics closer to ufs semantics, a file that has
1683 * other processes using the vnode is renamed instead of removed and then
1684 * removed later on the last close.
1685 * - If v_usecount > 1
1686 * If a rename is not already in the works
1687 * call nfs4_sillyrename() to set it up
1692 nfs4_remove(struct vop_remove_args *ap)
1694 struct vnode *vp = ap->a_vp;
1695 struct vnode *dvp = ap->a_dvp;
1696 struct componentname *cnp = ap->a_cnp;
1697 struct nfsnode *np = VTONFS(vp);
1702 if ((cnp->cn_flags & HASBUF) == 0)
1703 panic("nfs4_remove: no name");
1704 if (vrefcnt(vp) < 1)
1705 panic("nfs4_remove: bad v_usecount");
1707 if (vp->v_type == VDIR)
1709 else if (vrefcnt(vp) == 1 || (np->n_sillyrename &&
1710 VOP_GETATTR(vp, &vattr, cnp->cn_cred, cnp->cn_thread) == 0 &&
1711 vattr.va_nlink > 1)) {
1713 * Purge the name cache so that the chance of a lookup for
1714 * the name succeeding while the remove is in progress is
1715 * minimized. Without node locking it can still happen, such
1716 * that an I/O op returns ESTALE, but since you get this if
1717 * another host removes the file..
1721 * throw away biocache buffers, mainly to avoid
1722 * unnecessary delayed writes later.
1724 error = nfs_vinvalbuf(vp, 0, cnp->cn_cred, cnp->cn_thread, 1);
1727 error = nfs4_removerpc(dvp, cnp->cn_nameptr,
1728 cnp->cn_namelen, cnp->cn_cred, cnp->cn_thread);
1730 * Kludge City: If the first reply to the remove rpc is lost..
1731 * the reply to the retransmitted request will be ENOENT
1732 * since the file was in fact removed
1733 * Therefore, we cheat and return success.
1735 if (error == ENOENT)
1737 } else if (!np->n_sillyrename)
1738 error = nfs4_sillyrename(dvp, vp, cnp);
1739 np->n_attrstamp = 0;
1744 * nfs file remove rpc called from nfs_inactive
1747 nfs4_removeit(struct sillyrename *sp)
1750 * Make sure that the directory vnode is still valid.
1751 * XXX we should lock sp->s_dvp here.
1753 if (sp->s_dvp->v_type == VBAD)
1755 return (nfs4_removerpc(sp->s_dvp, sp->s_name, sp->s_namlen, sp->s_cred,
1760 * Nfs remove rpc, called from nfs4_remove() and nfs4_removeit().
1763 nfs4_removerpc(struct vnode *dvp, const char *name, int namelen,
1764 struct ucred *cred, struct thread *td)
1768 struct mbuf *mreq, *mrep = NULL, *md, *mb;
1769 struct nfs4_compound cp;
1771 nfsstats.rpccnt[NFSPROC_REMOVE]++;
1773 mreq = nfsm_reqhead(dvp, NFSV4PROC_COMPOUND, 0);
1775 bpos = mtod(mb, caddr_t);
1777 nfs_v4initcompound(&cp);
1779 nfsm_v4build_compound(&cp, "nfs4_removerpc()");
1780 nfsm_v4build_putfh(&cp, dvp);
1781 nfsm_v4build_remove(&cp, name, namelen);
1782 nfsm_v4build_finalize(&cp);
1784 nfsm_request(dvp, NFSV4PROC_COMPOUND, td, cred);
1788 nfsm_v4dissect_compound(&cp);
1789 nfsm_v4dissect_putfh(&cp);
1790 nfsm_v4dissect_remove(&cp);
1793 error = nfs_v4postop(&cp, error);
1798 VTONFS(dvp)->n_flag |= NMODIFIED;
1799 VTONFS(dvp)->n_attrstamp = 0; /* XXX wccflag */
1805 * nfs file rename call
1808 nfs4_rename(struct vop_rename_args *ap)
1810 struct vnode *fvp = ap->a_fvp;
1811 struct vnode *tvp = ap->a_tvp;
1812 struct vnode *fdvp = ap->a_fdvp;
1813 struct vnode *tdvp = ap->a_tdvp;
1814 struct componentname *tcnp = ap->a_tcnp;
1815 struct componentname *fcnp = ap->a_fcnp;
1819 if ((tcnp->cn_flags & HASBUF) == 0 ||
1820 (fcnp->cn_flags & HASBUF) == 0)
1821 panic("nfs4_rename: no name");
1823 /* Check for cross-device rename */
1824 if ((fvp->v_mount != tdvp->v_mount) ||
1825 (tvp && (fvp->v_mount != tvp->v_mount))) {
1831 printf("nfs4_rename: fvp == tvp (can't happen)\n");
1835 if ((error = vn_lock(fvp, LK_EXCLUSIVE, fcnp->cn_thread)) != 0)
1839 * We have to flush B_DELWRI data prior to renaming
1840 * the file. If we don't, the delayed-write buffers
1841 * can be flushed out later after the file has gone stale
1842 * under NFSV3. NFSV2 does not have this problem because
1843 * ( as far as I can tell ) it flushes dirty buffers more
1846 VOP_FSYNC(fvp, fcnp->cn_cred, MNT_WAIT, fcnp->cn_thread);
1847 VOP_UNLOCK(fvp, 0, fcnp->cn_thread);
1849 VOP_FSYNC(tvp, tcnp->cn_cred, MNT_WAIT, tcnp->cn_thread);
1852 * If the tvp exists and is in use, sillyrename it before doing the
1853 * rename of the new file over it.
1854 * XXX Can't sillyrename a directory.
1856 if (tvp && vrefcnt(tvp) > 1 && !VTONFS(tvp)->n_sillyrename &&
1857 tvp->v_type != VDIR && !nfs4_sillyrename(tdvp, tvp, tcnp)) {
1862 error = nfs4_renamerpc(fdvp, fcnp->cn_nameptr, fcnp->cn_namelen,
1863 tdvp, tcnp->cn_nameptr, tcnp->cn_namelen, tcnp->cn_cred,
1866 if (fvp->v_type == VDIR) {
1867 if (tvp != NULL && tvp->v_type == VDIR)
1882 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry.
1884 if (error == ENOENT)
1890 * nfs file rename rpc called from nfs4_remove() above
1893 nfs4_renameit(struct vnode *sdvp, struct componentname *scnp,
1894 struct sillyrename *sp)
1896 return (nfs4_renamerpc(sdvp, scnp->cn_nameptr, scnp->cn_namelen, sdvp,
1897 sp->s_name, sp->s_namlen, scnp->cn_cred, scnp->cn_thread));
1901 * nfs hard link create call
1904 nfs4_link(struct vop_link_args *ap)
1906 struct vnode *vp = ap->a_vp;
1907 struct vnode *tdvp = ap->a_tdvp;
1908 struct componentname *cnp = ap->a_cnp;
1911 struct mbuf *mreq, *mrep = NULL, *md, *mb;
1912 struct nfs4_compound cp;
1913 struct nfs4_oparg_link l;
1915 if (vp->v_mount != tdvp->v_mount) {
1920 * Push all writes to the server, so that the attribute cache
1921 * doesn't get "out of sync" with the server.
1922 * XXX There should be a better way!
1924 VOP_FSYNC(vp, cnp->cn_cred, MNT_WAIT, cnp->cn_thread);
1926 nfsstats.rpccnt[NFSPROC_LINK]++;
1928 l.name = cnp->cn_nameptr;
1929 l.namelen = cnp->cn_namelen;
1930 nfs_v4initcompound(&cp);
1932 mreq = nfsm_reqhead(vp, NFSV4PROC_COMPOUND, 0);
1934 bpos = mtod(mb, caddr_t);
1936 nfsm_v4build_compound(&cp, "nfs4_link()");
1937 nfsm_v4build_putfh(&cp, vp);
1938 nfsm_v4build_savefh(&cp);
1939 nfsm_v4build_putfh(&cp, tdvp);
1940 nfsm_v4build_link(&cp, &l);
1941 nfsm_v4build_finalize(&cp);
1943 nfsm_request(vp, NFSV4PROC_COMPOUND, cnp->cn_thread, cnp->cn_cred);
1947 nfsm_v4dissect_compound(&cp);
1948 nfsm_v4dissect_putfh(&cp);
1949 nfsm_v4dissect_savefh(&cp);
1950 nfsm_v4dissect_putfh(&cp);
1951 nfsm_v4dissect_link(&cp);
1953 VTONFS(tdvp)->n_flag |= NMODIFIED;
1954 VTONFS(vp)->n_attrstamp = 0;
1955 VTONFS(tdvp)->n_attrstamp = 0;
1958 error = nfs_v4postop(&cp, error);
1967 * nfs symbolic link create call
1970 nfs4_symlink(struct vop_symlink_args *ap)
1972 struct vnode *dvp = ap->a_dvp;
1974 struct vnode *newvp = NULL;
1976 nfsstats.rpccnt[NFSPROC_SYMLINK]++;
1978 error = nfs4_createrpc(ap->a_dvp, &newvp, ap->a_cnp, NFLNK,
1979 ap->a_vap, ap->a_target);
1981 if (error != 0 && newvp != NULL)
1983 else if (error == 0)
1986 VTONFS(dvp)->n_flag |= NMODIFIED;
1987 VTONFS(dvp)->n_attrstamp = 0; /* XXX wccflags */
1996 nfs4_mkdir(struct vop_mkdir_args *ap)
1998 return (nfs4_createrpc(ap->a_dvp, ap->a_vpp, ap->a_cnp, NFDIR,
2003 * nfs remove directory call
2006 nfs4_rmdir(struct vop_rmdir_args *ap)
2008 struct vnode *vp = ap->a_vp;
2009 struct vnode *dvp = ap->a_dvp;
2010 struct nfsnode *dnp = VTONFS(dvp);
2011 struct componentname *cnp = ap->a_cnp;
2017 error = (nfs4_removerpc(dvp, cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_cred,
2022 dnp->n_flag |= NMODIFIED;
2023 dnp->n_attrstamp = 0;
2034 nfs4_readdir(struct vop_readdir_args *ap)
2036 struct vnode *vp = ap->a_vp;
2037 struct nfsnode *np = VTONFS(vp);
2038 struct uio *uio = ap->a_uio;
2042 if (vp->v_type != VDIR)
2045 * First, check for hit on the EOF offset cache
2047 if (np->n_direofoffset > 0 && uio->uio_offset >= np->n_direofoffset &&
2048 (np->n_flag & NMODIFIED) == 0) {
2049 if (VOP_GETATTR(vp, &vattr, ap->a_cred, uio->uio_td) == 0 &&
2050 np->n_mtime == vattr.va_mtime.tv_sec) {
2051 nfsstats.direofcache_hits++;
2057 * Call nfs_bioread() to do the real work.
2059 tresid = uio->uio_resid;
2060 error = nfs_bioread(vp, uio, 0, ap->a_cred);
2062 if (!error && uio->uio_resid == tresid)
2063 nfsstats.direofcache_misses++;
2067 static u_char fty_to_dty[] = {
2068 DT_UNKNOWN, /* NFNON */
2074 DT_SOCK, /* NFSOCK */
2075 DT_FIFO, /* NFFIFO */
2076 DT_UNKNOWN, /* NFATTRDIT */
2077 DT_UNKNOWN, /* NFNAMEDATTR */
2078 DT_UNKNOWN, /* NFBAD */
2083 * Called from below the buffer cache by nfs_doio().
2086 nfs4_readdirrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred)
2089 struct dirent *dp = NULL;
2094 struct mbuf *mreq, *mrep = NULL, *md, *mb;
2096 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2097 struct nfsnode *dnp = VTONFS(vp);
2098 int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1;
2099 struct nfs4_compound cp;
2100 struct nfs4_oparg_readdir readdir;
2101 struct nfsv4_fattr fattr;
2105 if (uiop->uio_iovcnt != 1 || (uiop->uio_offset & (DIRBLKSIZ - 1)) ||
2106 (uiop->uio_resid & (DIRBLKSIZ - 1)))
2107 panic("nfs readdirrpc bad uio");
2111 * If there is no cookie, assume directory was stale.
2113 cookiep = nfs4_getcookie(dnp, uiop->uio_offset, 0);
2117 return (NFSERR_BAD_COOKIE);
2119 /* Generate fake entries for "." and ".." */
2120 while (cookie < 2 && bigenough) {
2124 if (len > uiop->uio_resid) {
2128 dp = (struct dirent *)uiop->uio_iov->iov_base;
2130 dp->d_namlen = cookie;
2132 dp->d_type = DT_DIR;
2134 dp->d_fileno = dnp->n_vattr.va_fileid; /* XXX has problems with pynfs virtualhandles */
2136 dp->d_fileno = dnp->n_dvp != NULL ?
2137 VTONFS(dnp->n_dvp)->n_vattr.va_fileid : cookie;
2146 if (blksiz == DIRBLKSIZ)
2148 uiop->uio_offset += len;
2149 uiop->uio_resid -= len;
2150 uiop->uio_iov->iov_base = (char *)uiop->uio_iov->iov_base + len;
2151 uiop->uio_iov->iov_len -= len;
2157 /* This is sort of ugly, to prevent v4postop() from acting weird */
2158 bzero(&cp, sizeof(cp));
2161 * Loop around doing readdir rpc's of size nm_readdirsize
2162 * truncated to a multiple of DIRBLKSIZ.
2163 * The stopping criteria is EOF or buffer full.
2166 * XXX this is sort of ugly for nfsv4; we don't maintain the
2167 * strict abstraction, but do the decoding inline. that's ok.
2169 while (more_dirs && bigenough) {
2170 nfsstats.rpccnt[NFSPROC_READDIR]++;
2172 mreq = nfsm_reqhead(vp, NFSV4PROC_COMPOUND, 0);
2174 bpos = mtod(mb, caddr_t);
2176 readdir.cnt = nmp->nm_readdirsize;
2177 readdir.cookie = cookie;
2178 readdir.bm = &nfsv4_readdirbm;
2180 bzero(&readdir.verf, sizeof(readdir.verf));
2182 bcopy(&dnp->n_cookieverf, &readdir.verf,
2183 sizeof(readdir.verf));
2185 nfs_v4initcompound(&cp);
2187 nfsm_v4build_compound(&cp, "nfs4_readdirrpc()");
2188 nfsm_v4build_putfh(&cp, vp);
2189 nfsm_v4build_readdir(&cp, &readdir);
2190 nfsm_v4build_finalize(&cp);
2192 nfsm_request(vp, NFSV4PROC_COMPOUND, uiop->uio_td, cred);
2196 nfsm_v4dissect_compound(&cp);
2197 nfsm_v4dissect_putfh(&cp);
2200 * XXX - Readdir gets handled inline like in
2201 * NFSv{2,3}. This is a nasty inconsistency and
2205 tl = nfsm_dissect(uint32_t *, 5 * NFSX_UNSIGNED);
2206 if (fxdr_unsigned(uint32_t, *tl++) != NFSV4OP_READDIR) {
2210 if (fxdr_unsigned(uint32_t, *tl++) != 0) {
2215 bcopy(tl, &dnp->n_cookieverf, NFSX_V4VERF);
2217 more_dirs = fxdr_unsigned(int, *tl++);
2219 /* loop thru the dir entries, doctoring them to 4bsd form */
2220 while (more_dirs && bigenough) {
2221 tl = nfsm_dissect(uint32_t *, 3 * NFSX_UNSIGNED);
2222 cookie = fxdr_hyper(tl);
2224 /* XXX cookie sanity check */
2225 len = fxdr_unsigned(int, *tl++);
2226 if (len <= 0 || len > NFS_MAXNAMLEN) {
2230 tlen = nfsm_rndup(len);
2232 tlen += 4; /* To ensure null termination */
2233 left = DIRBLKSIZ - blksiz;
2234 if ((tlen + DIRHDSIZ) > left) {
2235 dp->d_reclen += left;
2236 uiop->uio_iov->iov_base =
2237 (char *)uiop->uio_iov->iov_base + left;
2238 uiop->uio_iov->iov_len -= left;
2239 uiop->uio_offset += left;
2240 uiop->uio_resid -= left;
2243 if ((tlen + DIRHDSIZ) > uiop->uio_resid)
2246 dp = (struct dirent *)uiop->uio_iov->iov_base;
2249 dp->d_reclen = tlen + DIRHDSIZ;
2251 blksiz += dp->d_reclen;
2252 if (blksiz == DIRBLKSIZ)
2254 uiop->uio_offset += DIRHDSIZ;
2255 uiop->uio_resid -= DIRHDSIZ;
2256 uiop->uio_iov->iov_base =
2257 (char *)uiop->uio_iov->iov_base + DIRHDSIZ;
2258 uiop->uio_iov->iov_len -= DIRHDSIZ;
2261 nfsm_mtouio(uiop, len);
2262 p = uiop->uio_iov->iov_base;
2264 *p = '\0'; /* null terminate */
2265 /* printf("nfs4_readdirrpc: name: \"%s\" cookie %d\n",
2266 p - len, (int) cookie);*/
2267 uiop->uio_iov->iov_base =
2268 (char *)uiop->uio_iov->iov_base + tlen;
2269 uiop->uio_iov->iov_len -= tlen;
2270 uiop->uio_offset += tlen;
2271 uiop->uio_resid -= tlen;
2273 /* Copy attributes */
2274 nfsm_v4dissect_attrs(&fattr);
2276 dp->d_fileno = nfs_v4fileid4_to_fileid(
2277 fattr.fa4_valid & FA4V_FILEID &&
2279 fattr.fa4_fileid : cookie);
2281 fty = (u_int)fattr.fa4_type;
2282 dp->d_type = fattr.fa4_valid & FA4V_TYPE &&
2283 (fty < sizeof(fty_to_dty)) ?
2284 fty_to_dty[fty] : DT_UNKNOWN;
2286 nfsm_adv(nfsm_rndup(len));
2288 tl = nfsm_dissect(uint32_t *, NFSX_UNSIGNED);
2289 more_dirs = fxdr_unsigned(int, *tl++);
2292 * If at end of rpc data, get the eof boolean
2295 tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
2296 more_dirs = (fxdr_unsigned(int, *tl) == 0);
2299 error = nfs_v4postop(&cp, error);
2305 * Fill last record, iff any, out to a multiple of DIRBLKSIZ
2306 * by increasing d_reclen for the last record.
2309 left = DIRBLKSIZ - blksiz;
2310 dp->d_reclen += left;
2311 uiop->uio_iov->iov_base =
2312 (char *)uiop->uio_iov->iov_base + left;
2313 uiop->uio_iov->iov_len -= left;
2314 uiop->uio_offset += left;
2315 uiop->uio_resid -= left;
2319 * We are now either at the end of the directory or have filled the
2323 dnp->n_direofoffset = uiop->uio_offset;
2325 if (uiop->uio_resid > 0)
2326 printf("EEK! readdirrpc resid > 0\n");
2327 cookiep = nfs4_getcookie(dnp, uiop->uio_offset, 1);
2337 * Silly rename. To make the NFS filesystem that is stateless look a little
2338 * more like the "ufs" a remove of an active vnode is translated to a rename
2339 * to a funny looking filename that is removed by nfs_inactive on the
2340 * nfsnode. There is the potential for another process on a different client
2341 * to create the same funny name between the nfs_lookitup() fails and the
2342 * nfs_rename() completes, but...
2345 nfs4_sillyrename(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
2347 struct sillyrename *sp;
2355 if (vp->v_type == VDIR)
2356 panic("nfs: sillyrename dir");
2358 MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename),
2359 M_NFSREQ, M_WAITOK);
2360 sp->s_cred = crhold(cnp->cn_cred);
2362 sp->s_removeit = nfs4_removeit;
2365 /* Fudge together a funny name */
2366 pid = cnp->cn_thread->td_proc->p_pid;
2367 sp->s_namlen = sprintf(sp->s_name, ".nfsA%04x4.4", pid);
2369 /* Try lookitups until we get one that isn't there */
2370 while (nfs4_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred,
2371 cnp->cn_thread, NULL) == 0) {
2373 if (sp->s_name[4] > 'z') {
2378 error = nfs4_renameit(dvp, cnp, sp);
2381 error = nfs4_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred,
2382 cnp->cn_thread, &np);
2383 np->n_sillyrename = sp;
2388 free((caddr_t)sp, M_NFSREQ);
2393 * Look up a file name and optionally either update the file handle or
2394 * allocate an nfsnode, depending on the value of npp.
2395 * npp == NULL --> just do the lookup
2396 * *npp == NULL --> allocate a new nfsnode and make sure attributes are
2398 * *npp != NULL --> update the file handle in the vnode
2401 nfs4_lookitup(struct vnode *dvp, const char *name, int len, struct ucred *cred,
2402 struct thread *td, struct nfsnode **npp)
2404 struct vnode *newvp = NULL;
2405 struct nfsnode *np, *dnp = VTONFS(dvp);
2407 int error = 0, fhlen;
2408 struct mbuf *mreq, *mrep = NULL, *md, *mb;
2410 struct nfs4_compound cp;
2411 struct nfs4_oparg_lookup l;
2412 struct nfs4_oparg_getfh gfh;
2413 struct nfs4_oparg_getattr ga;
2415 nfsstats.rpccnt[NFSPROC_RENAME]++;
2417 mreq = nfsm_reqhead(dvp, NFSV4PROC_COMPOUND, 0);
2419 bpos = mtod(mb, caddr_t);
2424 nfs_v4initcompound(&cp);
2426 ga.bm = &nfsv4_getattrbm;
2428 nfsm_v4build_compound(&cp, "nfs4_renamerpc()");
2429 nfsm_v4build_putfh(&cp, dvp);
2430 nfsm_v4build_lookup(&cp, &l);
2431 nfsm_v4build_getfh(&cp, &gfh);
2432 nfsm_v4build_getattr(&cp, &ga);
2434 nfsm_request(dvp, NFSV4PROC_COMPOUND, td, cred);
2438 nfsm_v4dissect_compound(&cp);
2439 nfsm_v4dissect_putfh(&cp);
2440 nfsm_v4dissect_lookup(&cp);
2441 nfsm_v4dissect_getfh(&cp, &gfh);
2442 nfsm_v4dissect_getattr(&cp, &ga);
2444 if (npp != NULL && error == 0) {
2450 if (np->n_fhsize > NFS_SMALLFH && fhlen <= NFS_SMALLFH) {
2451 free((caddr_t)np->n_fhp, M_NFSBIGFH);
2452 np->n_fhp = &np->n_fh;
2453 } else if (np->n_fhsize <= NFS_SMALLFH && fhlen>NFS_SMALLFH)
2454 np->n_fhp =(nfsfh_t *)malloc(fhlen, M_NFSBIGFH, M_WAITOK);
2455 bcopy((caddr_t)nfhp, (caddr_t)np->n_fhp, fhlen);
2456 np->n_fhsize = fhlen;
2458 } else if (NFS_CMPFH(dnp, nfhp, fhlen)) {
2462 error = nfs_nget(dvp->v_mount, nfhp, fhlen, &np);
2472 np->n_namelen = len;
2473 if (np->n_name != NULL)
2474 FREE(np->n_name, M_NFSREQ);
2475 MALLOC(np->n_name, u_char *,
2476 np->n_namelen + 1, M_NFSREQ, M_WAITOK);
2477 memcpy(np->n_name, name, len);
2478 np->n_name[len] = '\0';
2480 nfs4_vnop_loadattrcache(newvp, &ga.fa, NULL);
2484 error = nfs_v4postop(&cp, error);
2488 if (npp && *npp == NULL) {
2505 * Nfs Version 3 commit rpc
2508 nfs4_commit(struct vnode *vp, u_quad_t offset, int cnt, struct ucred *cred,
2511 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2514 struct mbuf *mreq, *mrep = NULL, *md, *mb;
2515 struct nfs4_compound cp;
2516 struct nfs4_oparg_commit commit;
2518 if ((nmp->nm_state & NFSSTA_HASWRITEVERF) == 0)
2520 nfsstats.rpccnt[NFSPROC_COMMIT]++;
2522 mreq = nfsm_reqhead(vp, NFSV4PROC_COMPOUND, 0);
2524 bpos = mtod(mb, caddr_t);
2526 commit.start = offset;
2529 nfs_v4initcompound(&cp);
2531 nfsm_v4build_compound(&cp, "nfs4_commit()");
2532 nfsm_v4build_putfh(&cp, vp);
2533 nfsm_v4build_commit(&cp, &commit);
2534 nfsm_v4build_finalize(&cp);
2536 nfsm_request(vp, NFSV4PROC_COMPOUND, td, cred);
2540 nfsm_v4dissect_compound(&cp);
2541 nfsm_v4dissect_putfh(&cp);
2542 nfsm_v4dissect_commit(&cp, &commit);
2545 /* nfsm_wcc_data(vp, wccflag);*/
2546 if (bcmp(nmp->nm_verf, commit.verf, NFSX_V4VERF)) {
2547 bcopy(commit.verf, nmp->nm_verf, NFSX_V4VERF);
2548 error = NFSERR_STALEWRITEVERF;
2552 error = nfs_v4postop(&cp, error);
2561 * For async requests when nfsiod(s) are running, queue the request by
2562 * calling nfs_asyncio(), otherwise just all nfs_doio() to do the
2566 nfs4_strategy(struct vop_strategy_args *ap)
2568 struct buf *bp = ap->a_bp;
2573 KASSERT(ap->a_vp == ap->a_bp->b_vp, ("%s(%p != %p)",
2574 __func__, ap->a_vp, ap->a_bp->b_vp));
2575 KASSERT(!(bp->b_flags & B_DONE), ("nfs4_strategy: buffer %p unexpectedly marked B_DONE", bp));
2576 KASSERT(BUF_REFCNT(bp) > 0, ("nfs4_strategy: buffer %p not locked", bp));
2578 if (bp->b_flags & B_ASYNC)
2581 td = curthread; /* XXX */
2583 if (bp->b_iocmd == BIO_READ)
2589 * If the op is asynchronous and an i/o daemon is waiting
2590 * queue the request, wake it up and wait for completion
2591 * otherwise just do it ourselves.
2593 if ((bp->b_flags & B_ASYNC) == 0 ||
2594 nfs_asyncio(bp, NOCRED, td))
2595 error = nfs_doio(bp, cr, td);
2600 * fsync vnode op. Just call nfs4_flush() with commit == 1.
2604 nfs4_fsync(struct vop_fsync_args *ap)
2606 return (nfs4_flush(ap->a_vp, ap->a_cred, ap->a_waitfor, ap->a_td, 1));
2610 * Flush all the blocks associated with a vnode.
2611 * Walk through the buffer pool and push any dirty pages
2612 * associated with the vnode.
2615 nfs4_flush(struct vnode *vp, struct ucred *cred, int waitfor, struct thread *td,
2618 struct nfsnode *np = VTONFS(vp);
2622 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2623 int s, error = 0, slptimeo = 0, slpflag = 0, retv, bvecpos;
2625 u_quad_t off, endoff, toff;
2626 struct ucred* wcred = NULL;
2627 struct buf **bvec = NULL;
2628 #ifndef NFS_COMMITBVECSIZ
2629 #define NFS_COMMITBVECSIZ 20
2631 struct buf *bvec_on_stack[NFS_COMMITBVECSIZ];
2632 int bvecsize = 0, bveccount;
2634 if (nmp->nm_flag & NFSMNT_INT)
2639 * A b_flags == (B_DELWRI | B_NEEDCOMMIT) block has been written to the
2640 * server, but nas not been committed to stable storage on the server
2641 * yet. On the first pass, the byte range is worked out and the commit
2642 * rpc is done. On the second pass, nfs_writebp() is called to do the
2649 if (NFS_ISV3(vp) && commit) {
2651 if (bvec != NULL && bvec != bvec_on_stack)
2654 * Count up how many buffers waiting for a commit.
2658 for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
2659 nbp = TAILQ_NEXT(bp, b_vnbufs);
2660 if (BUF_REFCNT(bp) == 0 &&
2661 (bp->b_flags & (B_DELWRI | B_NEEDCOMMIT))
2662 == (B_DELWRI | B_NEEDCOMMIT))
2666 * Allocate space to remember the list of bufs to commit. It is
2667 * important to use M_NOWAIT here to avoid a race with nfs4_write.
2668 * If we can't get memory (for whatever reason), we will end up
2669 * committing the buffers one-by-one in the loop below.
2671 if (bveccount > NFS_COMMITBVECSIZ) {
2673 * Release the vnode interlock to avoid a lock
2677 bvec = (struct buf **)
2678 malloc(bveccount * sizeof(struct buf *),
2682 bvec = bvec_on_stack;
2683 bvecsize = NFS_COMMITBVECSIZ;
2685 bvecsize = bveccount;
2687 bvec = bvec_on_stack;
2688 bvecsize = NFS_COMMITBVECSIZ;
2690 for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
2691 if (bvecpos >= bvecsize)
2693 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL)) {
2694 nbp = TAILQ_NEXT(bp, b_vnbufs);
2697 if ((bp->b_flags & (B_DELWRI | B_NEEDCOMMIT)) !=
2698 (B_DELWRI | B_NEEDCOMMIT)) {
2700 nbp = TAILQ_NEXT(bp, b_vnbufs);
2706 * Work out if all buffers are using the same cred
2707 * so we can deal with them all with one commit.
2709 * NOTE: we are not clearing B_DONE here, so we have
2710 * to do it later on in this routine if we intend to
2711 * initiate I/O on the bp.
2713 * Note: to avoid loopback deadlocks, we do not
2714 * assign b_runningbufspace.
2717 wcred = bp->b_wcred;
2718 else if (wcred != bp->b_wcred)
2720 bp->b_flags |= B_WRITEINPROG;
2721 vfs_busy_pages(bp, 1);
2725 * bp is protected by being locked, but nbp is not
2726 * and vfs_busy_pages() may sleep. We have to
2729 nbp = TAILQ_NEXT(bp, b_vnbufs);
2732 * A list of these buffers is kept so that the
2733 * second loop knows which buffers have actually
2734 * been committed. This is necessary, since there
2735 * may be a race between the commit rpc and new
2736 * uncommitted writes on the file.
2738 bvec[bvecpos++] = bp;
2739 toff = ((u_quad_t)bp->b_blkno) * DEV_BSIZE +
2743 toff += (u_quad_t)(bp->b_dirtyend - bp->b_dirtyoff);
2752 * Commit data on the server, as required.
2753 * If all bufs are using the same wcred, then use that with
2754 * one call for all of them, otherwise commit each one
2757 if (wcred != NOCRED)
2758 retv = nfs4_commit(vp, off, (int)(endoff - off),
2762 for (i = 0; i < bvecpos; i++) {
2765 off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE +
2767 size = (u_quad_t)(bp->b_dirtyend
2769 retv = nfs4_commit(vp, off, (int)size,
2775 if (retv == NFSERR_STALEWRITEVERF)
2776 nfs_clearcommit(vp->v_mount);
2779 * Now, either mark the blocks I/O done or mark the
2780 * blocks dirty, depending on whether the commit
2783 for (i = 0; i < bvecpos; i++) {
2785 bp->b_flags &= ~(B_NEEDCOMMIT | B_WRITEINPROG | B_CLUSTEROK);
2788 * Error, leave B_DELWRI intact
2790 vfs_unbusy_pages(bp);
2794 * Success, remove B_DELWRI ( bundirty() ).
2796 * b_dirtyoff/b_dirtyend seem to be NFS
2797 * specific. We should probably move that
2798 * into bundirty(). XXX
2804 bp->b_flags |= B_ASYNC;
2806 bp->b_flags &= ~B_DONE;
2807 bp->b_ioflags &= ~BIO_ERROR;
2808 bp->b_dirtyoff = bp->b_dirtyend = 0;
2816 * Start/do any write(s) that are required.
2821 for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
2822 nbp = TAILQ_NEXT(bp, b_vnbufs);
2823 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL)) {
2824 if (waitfor != MNT_WAIT || passone)
2827 error = BUF_TIMELOCK(bp,
2828 LK_EXCLUSIVE | LK_SLEEPFAIL | LK_INTERLOCK,
2829 VI_MTX(vp), "nfsfsync", slpflag, slptimeo);
2832 panic("nfs4_fsync: inconsistent lock");
2833 if (error == ENOLCK)
2835 if (nfs4_sigintr(nmp, NULL, td)) {
2839 if (slpflag == PCATCH) {
2845 if ((bp->b_flags & B_DELWRI) == 0)
2846 panic("nfs4_fsync: not dirty");
2847 if ((passone || !commit) && (bp->b_flags & B_NEEDCOMMIT)) {
2853 if (passone || !commit)
2854 bp->b_flags |= B_ASYNC;
2856 bp->b_flags |= B_ASYNC | B_WRITEINPROG;
2867 if (waitfor == MNT_WAIT) {
2868 while (vp->v_numoutput) {
2869 vp->v_iflag |= VI_BWAIT;
2870 error = msleep((caddr_t)&vp->v_numoutput, VI_MTX(vp),
2871 slpflag | (PRIBIO + 1), "nfsfsync", slptimeo);
2874 if (nfs4_sigintr(nmp, NULL, td)) {
2878 if (slpflag == PCATCH) {
2885 if (!TAILQ_EMPTY(&vp->v_dirtyblkhd) && commit) {
2891 if (np->n_flag & NWRITEERR) {
2892 error = np->n_error;
2893 np->n_flag &= ~NWRITEERR;
2896 if (bvec != NULL && bvec != bvec_on_stack)
2902 * NFS advisory byte-level locks.
2905 nfs4_advlock(struct vop_advlock_args *ap)
2909 if ((VFSTONFS(ap->a_vp->v_mount)->nm_flag & NFSMNT_NOLOCKD) != 0) {
2910 struct nfsnode *np = VTONFS(ap->a_vp);
2912 return (lf_advlock(ap, &(np->n_lockf), np->n_size));
2914 return (nfs_dolock(ap));
2918 * Print out the contents of an nfsnode.
2921 nfs4_print(struct vop_print_args *ap)
2923 struct vnode *vp = ap->a_vp;
2924 struct nfsnode *np = VTONFS(vp);
2926 printf("\tfileid %ld fsid 0x%x",
2927 np->n_vattr.va_fileid, np->n_vattr.va_fsid);
2928 if (vp->v_type == VFIFO)
2935 * This is the "real" nfs::bwrite(struct buf*).
2936 * B_WRITEINPROG isn't set unless the force flag is one and it
2937 * handles the B_NEEDCOMMIT flag.
2938 * We set B_CACHE if this is a VMIO buffer.
2941 nfs4_writebp(struct buf *bp, int force, struct thread *td)
2944 int oldflags = bp->b_flags;
2950 if (BUF_REFCNT(bp) == 0)
2951 panic("bwrite: buffer is not locked???");
2953 if (bp->b_flags & B_INVAL) {
2958 bp->b_flags |= B_CACHE;
2961 * Undirty the bp. We will redirty it later if the I/O fails.
2966 bp->b_flags &= ~B_DONE;
2967 bp->b_ioflags &= ~BIO_ERROR;
2968 bp->b_iocmd = BIO_WRITE;
2971 bp->b_vp->v_numoutput++;
2972 VI_UNLOCK(bp->b_vp);
2973 curthread->td_proc->p_stats->p_ru.ru_oublock++;
2977 * Note: to avoid loopback deadlocks, we do not
2978 * assign b_runningbufspace.
2980 vfs_busy_pages(bp, 1);
2983 bp->b_flags |= B_WRITEINPROG;
2985 bp->b_iooffset = dbtob(bp->b_blkno);
2986 VOP_STRATEGY(bp->b_vp, bp);
2988 if( (oldflags & B_ASYNC) == 0) {
2989 int rtval = bufwait(bp);
2991 if (oldflags & B_DELWRI) {
3005 * nfs special file access vnode op.
3006 * Essentially just get vattr and then imitate iaccess() since the device is
3007 * local to the client.
3010 nfsspec_access(struct vop_access_args *ap)
3013 struct ucred *cred = ap->a_cred;
3014 struct vnode *vp = ap->a_vp;
3015 mode_t mode = ap->a_mode;
3020 * Disallow write attempts on filesystems mounted read-only;
3021 * unless the file is a socket, fifo, or a block or character
3022 * device resident on the filesystem.
3024 if ((mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
3025 switch (vp->v_type) {
3035 error = VOP_GETATTR(vp, vap, cred, ap->a_td);
3038 return (vaccess(vp->v_type, vap->va_mode, vap->va_uid, vap->va_gid,
3043 * Read wrapper for special devices.
3046 nfsspec_read(struct vop_read_args *ap)
3048 struct nfsnode *np = VTONFS(ap->a_vp);
3054 getnanotime(&np->n_atim);
3055 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap));
3059 * Write wrapper for special devices.
3062 nfsspec_write(struct vop_write_args *ap)
3064 struct nfsnode *np = VTONFS(ap->a_vp);
3070 getnanotime(&np->n_mtim);
3071 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap));
3075 * Close wrapper for special devices.
3077 * Update the times on the nfsnode then do device close.
3080 nfsspec_close(struct vop_close_args *ap)
3082 struct vnode *vp = ap->a_vp;
3083 struct nfsnode *np = VTONFS(vp);
3086 if (np->n_flag & (NACC | NUPD)) {
3088 if (vrefcnt(vp) == 1 &&
3089 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
3091 if (np->n_flag & NACC)
3092 vattr.va_atime = np->n_atim;
3093 if (np->n_flag & NUPD)
3094 vattr.va_mtime = np->n_mtim;
3095 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_td);
3098 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap));
3102 * Read wrapper for fifos.
3105 nfsfifo_read(struct vop_read_args *ap)
3107 struct nfsnode *np = VTONFS(ap->a_vp);
3113 getnanotime(&np->n_atim);
3114 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap));
3118 * Write wrapper for fifos.
3121 nfsfifo_write(struct vop_write_args *ap)
3123 struct nfsnode *np = VTONFS(ap->a_vp);
3129 getnanotime(&np->n_mtim);
3130 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap));
3134 * Close wrapper for fifos.
3136 * Update the times on the nfsnode then do fifo close.
3139 nfsfifo_close(struct vop_close_args *ap)
3141 struct vnode *vp = ap->a_vp;
3142 struct nfsnode *np = VTONFS(vp);
3146 if (np->n_flag & (NACC | NUPD)) {
3148 if (np->n_flag & NACC)
3150 if (np->n_flag & NUPD)
3153 if (vrefcnt(vp) == 1 &&
3154 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
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 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, ap->a_td);
3161 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_td);
3162 VOP_UNLOCK(vp, 0, ap->a_td);
3165 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap));