Deleted Added
full compact
nfs_vnops.c (36503) nfs_vnops.c (36511)
1/*
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95
1/*
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95
37 * $Id: nfs_vnops.c,v 1.91 1998/05/31 01:03:07 peter Exp $
37 * $Id: nfs_vnops.c,v 1.92 1998/05/31 17:27:55 peter Exp $
38 */
39
40
41/*
42 * vnode op calls for Sun NFS version 2 and 3
43 */
44
45#include "opt_inet.h"
46
47#include <sys/param.h>
48#include <sys/kernel.h>
49#include <sys/systm.h>
50#include <sys/resourcevar.h>
51#include <sys/proc.h>
52#include <sys/mount.h>
53#include <sys/buf.h>
54#include <sys/malloc.h>
55#include <sys/mbuf.h>
56#include <sys/namei.h>
57#include <sys/socket.h>
58#include <sys/vnode.h>
59#include <sys/dirent.h>
60#include <sys/fcntl.h>
61#include <sys/lockf.h>
62
63#include <vm/vm.h>
64#include <vm/vm_extern.h>
65#include <vm/vm_zone.h>
66
67#include <miscfs/fifofs/fifo.h>
68#include <miscfs/specfs/specdev.h>
69
70#include <nfs/rpcv2.h>
71#include <nfs/nfsproto.h>
72#include <nfs/nfs.h>
73#include <nfs/nfsnode.h>
74#include <nfs/nfsmount.h>
75#include <nfs/xdr_subs.h>
76#include <nfs/nfsm_subs.h>
77#include <nfs/nqnfs.h>
78
79#include <net/if.h>
80#include <netinet/in.h>
81#include <netinet/in_var.h>
82
83/* Defs */
84#define TRUE 1
85#define FALSE 0
86
87/*
88 * Ifdef for FreeBSD-current merged buffer cache. It is unfortunate that these
89 * calls are not in getblk() and brelse() so that they would not be necessary
90 * here.
91 */
92#ifndef B_VMIO
93#define vfs_busy_pages(bp, f)
94#endif
95
96static int nfsspec_read __P((struct vop_read_args *));
97static int nfsspec_write __P((struct vop_write_args *));
98static int nfsfifo_read __P((struct vop_read_args *));
99static int nfsfifo_write __P((struct vop_write_args *));
100static int nfsspec_close __P((struct vop_close_args *));
101static int nfsfifo_close __P((struct vop_close_args *));
102#define nfs_poll vop_nopoll
103static int nfs_flush __P((struct vnode *,struct ucred *,int,struct proc *,int));
104static int nfs_setattrrpc __P((struct vnode *,struct vattr *,struct ucred *,struct proc *));
105static int nfs_lookup __P((struct vop_lookup_args *));
106static int nfs_create __P((struct vop_create_args *));
107static int nfs_mknod __P((struct vop_mknod_args *));
108static int nfs_open __P((struct vop_open_args *));
109static int nfs_close __P((struct vop_close_args *));
110static int nfs_access __P((struct vop_access_args *));
111static int nfs_getattr __P((struct vop_getattr_args *));
112static int nfs_setattr __P((struct vop_setattr_args *));
113static int nfs_read __P((struct vop_read_args *));
114static int nfs_mmap __P((struct vop_mmap_args *));
115static int nfs_fsync __P((struct vop_fsync_args *));
116static int nfs_remove __P((struct vop_remove_args *));
117static int nfs_link __P((struct vop_link_args *));
118static int nfs_rename __P((struct vop_rename_args *));
119static int nfs_mkdir __P((struct vop_mkdir_args *));
120static int nfs_rmdir __P((struct vop_rmdir_args *));
121static int nfs_symlink __P((struct vop_symlink_args *));
122static int nfs_readdir __P((struct vop_readdir_args *));
123static int nfs_bmap __P((struct vop_bmap_args *));
124static int nfs_strategy __P((struct vop_strategy_args *));
38 */
39
40
41/*
42 * vnode op calls for Sun NFS version 2 and 3
43 */
44
45#include "opt_inet.h"
46
47#include <sys/param.h>
48#include <sys/kernel.h>
49#include <sys/systm.h>
50#include <sys/resourcevar.h>
51#include <sys/proc.h>
52#include <sys/mount.h>
53#include <sys/buf.h>
54#include <sys/malloc.h>
55#include <sys/mbuf.h>
56#include <sys/namei.h>
57#include <sys/socket.h>
58#include <sys/vnode.h>
59#include <sys/dirent.h>
60#include <sys/fcntl.h>
61#include <sys/lockf.h>
62
63#include <vm/vm.h>
64#include <vm/vm_extern.h>
65#include <vm/vm_zone.h>
66
67#include <miscfs/fifofs/fifo.h>
68#include <miscfs/specfs/specdev.h>
69
70#include <nfs/rpcv2.h>
71#include <nfs/nfsproto.h>
72#include <nfs/nfs.h>
73#include <nfs/nfsnode.h>
74#include <nfs/nfsmount.h>
75#include <nfs/xdr_subs.h>
76#include <nfs/nfsm_subs.h>
77#include <nfs/nqnfs.h>
78
79#include <net/if.h>
80#include <netinet/in.h>
81#include <netinet/in_var.h>
82
83/* Defs */
84#define TRUE 1
85#define FALSE 0
86
87/*
88 * Ifdef for FreeBSD-current merged buffer cache. It is unfortunate that these
89 * calls are not in getblk() and brelse() so that they would not be necessary
90 * here.
91 */
92#ifndef B_VMIO
93#define vfs_busy_pages(bp, f)
94#endif
95
96static int nfsspec_read __P((struct vop_read_args *));
97static int nfsspec_write __P((struct vop_write_args *));
98static int nfsfifo_read __P((struct vop_read_args *));
99static int nfsfifo_write __P((struct vop_write_args *));
100static int nfsspec_close __P((struct vop_close_args *));
101static int nfsfifo_close __P((struct vop_close_args *));
102#define nfs_poll vop_nopoll
103static int nfs_flush __P((struct vnode *,struct ucred *,int,struct proc *,int));
104static int nfs_setattrrpc __P((struct vnode *,struct vattr *,struct ucred *,struct proc *));
105static int nfs_lookup __P((struct vop_lookup_args *));
106static int nfs_create __P((struct vop_create_args *));
107static int nfs_mknod __P((struct vop_mknod_args *));
108static int nfs_open __P((struct vop_open_args *));
109static int nfs_close __P((struct vop_close_args *));
110static int nfs_access __P((struct vop_access_args *));
111static int nfs_getattr __P((struct vop_getattr_args *));
112static int nfs_setattr __P((struct vop_setattr_args *));
113static int nfs_read __P((struct vop_read_args *));
114static int nfs_mmap __P((struct vop_mmap_args *));
115static int nfs_fsync __P((struct vop_fsync_args *));
116static int nfs_remove __P((struct vop_remove_args *));
117static int nfs_link __P((struct vop_link_args *));
118static int nfs_rename __P((struct vop_rename_args *));
119static int nfs_mkdir __P((struct vop_mkdir_args *));
120static int nfs_rmdir __P((struct vop_rmdir_args *));
121static int nfs_symlink __P((struct vop_symlink_args *));
122static int nfs_readdir __P((struct vop_readdir_args *));
123static int nfs_bmap __P((struct vop_bmap_args *));
124static int nfs_strategy __P((struct vop_strategy_args *));
125static int nfs_lookitup __P((struct vnode *,char *,int,struct ucred *,struct proc *,struct nfsnode **));
125static int nfs_lookitup __P((struct vnode *, const char *, int,
126 struct ucred *, struct proc *, struct nfsnode **));
126static int nfs_sillyrename __P((struct vnode *,struct vnode *,struct componentname *));
127static int nfsspec_access __P((struct vop_access_args *));
128static int nfs_readlink __P((struct vop_readlink_args *));
129static int nfs_print __P((struct vop_print_args *));
130static int nfs_advlock __P((struct vop_advlock_args *));
131static int nfs_bwrite __P((struct vop_bwrite_args *));
132/*
133 * Global vfs data structures for nfs
134 */
135vop_t **nfsv2_vnodeop_p;
136static struct vnodeopv_entry_desc nfsv2_vnodeop_entries[] = {
137 { &vop_default_desc, (vop_t *) vop_defaultop },
138 { &vop_abortop_desc, (vop_t *) nfs_abortop },
139 { &vop_access_desc, (vop_t *) nfs_access },
140 { &vop_advlock_desc, (vop_t *) nfs_advlock },
141 { &vop_bmap_desc, (vop_t *) nfs_bmap },
142 { &vop_bwrite_desc, (vop_t *) nfs_bwrite },
143 { &vop_close_desc, (vop_t *) nfs_close },
144 { &vop_create_desc, (vop_t *) nfs_create },
145 { &vop_fsync_desc, (vop_t *) nfs_fsync },
146 { &vop_getattr_desc, (vop_t *) nfs_getattr },
147 { &vop_getpages_desc, (vop_t *) nfs_getpages },
148 { &vop_putpages_desc, (vop_t *) nfs_putpages },
149 { &vop_inactive_desc, (vop_t *) nfs_inactive },
150 { &vop_lease_desc, (vop_t *) vop_null },
151 { &vop_link_desc, (vop_t *) nfs_link },
152 { &vop_lock_desc, (vop_t *) vop_sharedlock },
153 { &vop_lookup_desc, (vop_t *) nfs_lookup },
154 { &vop_mkdir_desc, (vop_t *) nfs_mkdir },
155 { &vop_mknod_desc, (vop_t *) nfs_mknod },
156 { &vop_mmap_desc, (vop_t *) nfs_mmap },
157 { &vop_open_desc, (vop_t *) nfs_open },
158 { &vop_poll_desc, (vop_t *) nfs_poll },
159 { &vop_print_desc, (vop_t *) nfs_print },
160 { &vop_read_desc, (vop_t *) nfs_read },
161 { &vop_readdir_desc, (vop_t *) nfs_readdir },
162 { &vop_readlink_desc, (vop_t *) nfs_readlink },
163 { &vop_reclaim_desc, (vop_t *) nfs_reclaim },
164 { &vop_remove_desc, (vop_t *) nfs_remove },
165 { &vop_rename_desc, (vop_t *) nfs_rename },
166 { &vop_rmdir_desc, (vop_t *) nfs_rmdir },
167 { &vop_setattr_desc, (vop_t *) nfs_setattr },
168 { &vop_strategy_desc, (vop_t *) nfs_strategy },
169 { &vop_symlink_desc, (vop_t *) nfs_symlink },
170 { &vop_write_desc, (vop_t *) nfs_write },
171 { NULL, NULL }
172};
173static struct vnodeopv_desc nfsv2_vnodeop_opv_desc =
174 { &nfsv2_vnodeop_p, nfsv2_vnodeop_entries };
175VNODEOP_SET(nfsv2_vnodeop_opv_desc);
176
177/*
178 * Special device vnode ops
179 */
180vop_t **spec_nfsv2nodeop_p;
181static struct vnodeopv_entry_desc nfsv2_specop_entries[] = {
182 { &vop_default_desc, (vop_t *) spec_vnoperate },
183 { &vop_access_desc, (vop_t *) nfsspec_access },
184 { &vop_close_desc, (vop_t *) nfsspec_close },
185 { &vop_fsync_desc, (vop_t *) nfs_fsync },
186 { &vop_getattr_desc, (vop_t *) nfs_getattr },
187 { &vop_inactive_desc, (vop_t *) nfs_inactive },
188 { &vop_lock_desc, (vop_t *) vop_sharedlock },
189 { &vop_print_desc, (vop_t *) nfs_print },
190 { &vop_read_desc, (vop_t *) nfsspec_read },
191 { &vop_reclaim_desc, (vop_t *) nfs_reclaim },
192 { &vop_setattr_desc, (vop_t *) nfs_setattr },
193 { &vop_write_desc, (vop_t *) nfsspec_write },
194 { NULL, NULL }
195};
196static struct vnodeopv_desc spec_nfsv2nodeop_opv_desc =
197 { &spec_nfsv2nodeop_p, nfsv2_specop_entries };
198VNODEOP_SET(spec_nfsv2nodeop_opv_desc);
199
200vop_t **fifo_nfsv2nodeop_p;
201static struct vnodeopv_entry_desc nfsv2_fifoop_entries[] = {
202 { &vop_default_desc, (vop_t *) fifo_vnoperate },
203 { &vop_access_desc, (vop_t *) nfsspec_access },
204 { &vop_close_desc, (vop_t *) nfsfifo_close },
205 { &vop_fsync_desc, (vop_t *) nfs_fsync },
206 { &vop_getattr_desc, (vop_t *) nfs_getattr },
207 { &vop_inactive_desc, (vop_t *) nfs_inactive },
208 { &vop_lock_desc, (vop_t *) vop_sharedlock },
209 { &vop_print_desc, (vop_t *) nfs_print },
210 { &vop_read_desc, (vop_t *) nfsfifo_read },
211 { &vop_reclaim_desc, (vop_t *) nfs_reclaim },
212 { &vop_setattr_desc, (vop_t *) nfs_setattr },
213 { &vop_write_desc, (vop_t *) nfsfifo_write },
214 { NULL, NULL }
215};
216static struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc =
217 { &fifo_nfsv2nodeop_p, nfsv2_fifoop_entries };
218VNODEOP_SET(fifo_nfsv2nodeop_opv_desc);
219
220static int nfs_commit __P((struct vnode *vp, u_quad_t offset, int cnt,
221 struct ucred *cred, struct proc *procp));
222static int nfs_mknodrpc __P((struct vnode *dvp, struct vnode **vpp,
223 struct componentname *cnp,
224 struct vattr *vap));
127static int nfs_sillyrename __P((struct vnode *,struct vnode *,struct componentname *));
128static int nfsspec_access __P((struct vop_access_args *));
129static int nfs_readlink __P((struct vop_readlink_args *));
130static int nfs_print __P((struct vop_print_args *));
131static int nfs_advlock __P((struct vop_advlock_args *));
132static int nfs_bwrite __P((struct vop_bwrite_args *));
133/*
134 * Global vfs data structures for nfs
135 */
136vop_t **nfsv2_vnodeop_p;
137static struct vnodeopv_entry_desc nfsv2_vnodeop_entries[] = {
138 { &vop_default_desc, (vop_t *) vop_defaultop },
139 { &vop_abortop_desc, (vop_t *) nfs_abortop },
140 { &vop_access_desc, (vop_t *) nfs_access },
141 { &vop_advlock_desc, (vop_t *) nfs_advlock },
142 { &vop_bmap_desc, (vop_t *) nfs_bmap },
143 { &vop_bwrite_desc, (vop_t *) nfs_bwrite },
144 { &vop_close_desc, (vop_t *) nfs_close },
145 { &vop_create_desc, (vop_t *) nfs_create },
146 { &vop_fsync_desc, (vop_t *) nfs_fsync },
147 { &vop_getattr_desc, (vop_t *) nfs_getattr },
148 { &vop_getpages_desc, (vop_t *) nfs_getpages },
149 { &vop_putpages_desc, (vop_t *) nfs_putpages },
150 { &vop_inactive_desc, (vop_t *) nfs_inactive },
151 { &vop_lease_desc, (vop_t *) vop_null },
152 { &vop_link_desc, (vop_t *) nfs_link },
153 { &vop_lock_desc, (vop_t *) vop_sharedlock },
154 { &vop_lookup_desc, (vop_t *) nfs_lookup },
155 { &vop_mkdir_desc, (vop_t *) nfs_mkdir },
156 { &vop_mknod_desc, (vop_t *) nfs_mknod },
157 { &vop_mmap_desc, (vop_t *) nfs_mmap },
158 { &vop_open_desc, (vop_t *) nfs_open },
159 { &vop_poll_desc, (vop_t *) nfs_poll },
160 { &vop_print_desc, (vop_t *) nfs_print },
161 { &vop_read_desc, (vop_t *) nfs_read },
162 { &vop_readdir_desc, (vop_t *) nfs_readdir },
163 { &vop_readlink_desc, (vop_t *) nfs_readlink },
164 { &vop_reclaim_desc, (vop_t *) nfs_reclaim },
165 { &vop_remove_desc, (vop_t *) nfs_remove },
166 { &vop_rename_desc, (vop_t *) nfs_rename },
167 { &vop_rmdir_desc, (vop_t *) nfs_rmdir },
168 { &vop_setattr_desc, (vop_t *) nfs_setattr },
169 { &vop_strategy_desc, (vop_t *) nfs_strategy },
170 { &vop_symlink_desc, (vop_t *) nfs_symlink },
171 { &vop_write_desc, (vop_t *) nfs_write },
172 { NULL, NULL }
173};
174static struct vnodeopv_desc nfsv2_vnodeop_opv_desc =
175 { &nfsv2_vnodeop_p, nfsv2_vnodeop_entries };
176VNODEOP_SET(nfsv2_vnodeop_opv_desc);
177
178/*
179 * Special device vnode ops
180 */
181vop_t **spec_nfsv2nodeop_p;
182static struct vnodeopv_entry_desc nfsv2_specop_entries[] = {
183 { &vop_default_desc, (vop_t *) spec_vnoperate },
184 { &vop_access_desc, (vop_t *) nfsspec_access },
185 { &vop_close_desc, (vop_t *) nfsspec_close },
186 { &vop_fsync_desc, (vop_t *) nfs_fsync },
187 { &vop_getattr_desc, (vop_t *) nfs_getattr },
188 { &vop_inactive_desc, (vop_t *) nfs_inactive },
189 { &vop_lock_desc, (vop_t *) vop_sharedlock },
190 { &vop_print_desc, (vop_t *) nfs_print },
191 { &vop_read_desc, (vop_t *) nfsspec_read },
192 { &vop_reclaim_desc, (vop_t *) nfs_reclaim },
193 { &vop_setattr_desc, (vop_t *) nfs_setattr },
194 { &vop_write_desc, (vop_t *) nfsspec_write },
195 { NULL, NULL }
196};
197static struct vnodeopv_desc spec_nfsv2nodeop_opv_desc =
198 { &spec_nfsv2nodeop_p, nfsv2_specop_entries };
199VNODEOP_SET(spec_nfsv2nodeop_opv_desc);
200
201vop_t **fifo_nfsv2nodeop_p;
202static struct vnodeopv_entry_desc nfsv2_fifoop_entries[] = {
203 { &vop_default_desc, (vop_t *) fifo_vnoperate },
204 { &vop_access_desc, (vop_t *) nfsspec_access },
205 { &vop_close_desc, (vop_t *) nfsfifo_close },
206 { &vop_fsync_desc, (vop_t *) nfs_fsync },
207 { &vop_getattr_desc, (vop_t *) nfs_getattr },
208 { &vop_inactive_desc, (vop_t *) nfs_inactive },
209 { &vop_lock_desc, (vop_t *) vop_sharedlock },
210 { &vop_print_desc, (vop_t *) nfs_print },
211 { &vop_read_desc, (vop_t *) nfsfifo_read },
212 { &vop_reclaim_desc, (vop_t *) nfs_reclaim },
213 { &vop_setattr_desc, (vop_t *) nfs_setattr },
214 { &vop_write_desc, (vop_t *) nfsfifo_write },
215 { NULL, NULL }
216};
217static struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc =
218 { &fifo_nfsv2nodeop_p, nfsv2_fifoop_entries };
219VNODEOP_SET(fifo_nfsv2nodeop_opv_desc);
220
221static int nfs_commit __P((struct vnode *vp, u_quad_t offset, int cnt,
222 struct ucred *cred, struct proc *procp));
223static int nfs_mknodrpc __P((struct vnode *dvp, struct vnode **vpp,
224 struct componentname *cnp,
225 struct vattr *vap));
225static int nfs_removerpc __P((struct vnode *dvp, char *name, int namelen,
226static int nfs_removerpc __P((struct vnode *dvp, const char *name,
227 int namelen,
226 struct ucred *cred, struct proc *proc));
228 struct ucred *cred, struct proc *proc));
227static int nfs_renamerpc __P((struct vnode *fdvp, char *fnameptr,
229static int nfs_renamerpc __P((struct vnode *fdvp, const char *fnameptr,
228 int fnamelen, struct vnode *tdvp,
230 int fnamelen, struct vnode *tdvp,
229 char *tnameptr, int tnamelen,
231 const char *tnameptr, int tnamelen,
230 struct ucred *cred, struct proc *proc));
231static int nfs_renameit __P((struct vnode *sdvp,
232 struct componentname *scnp,
233 struct sillyrename *sp));
234
235/*
236 * Global variables
237 */
238extern u_long nfs_true, nfs_false;
239extern struct nfsstats nfsstats;
240extern nfstype nfsv3_type[9];
241struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
242struct nfsmount *nfs_iodmount[NFS_MAXASYNCDAEMON];
243int nfs_numasync = 0;
244#define DIRHDSIZ (sizeof (struct dirent) - (MAXNAMLEN + 1))
245
246/*
247 * nfs access vnode op.
248 * For nfs version 2, just return ok. File accesses may fail later.
249 * For nfs version 3, use the access rpc to check accessibility. If file modes
250 * are changed on the server, accesses might still fail later.
251 */
252static int
253nfs_access(ap)
254 struct vop_access_args /* {
255 struct vnode *a_vp;
256 int a_mode;
257 struct ucred *a_cred;
258 struct proc *a_p;
259 } */ *ap;
260{
261 register struct vnode *vp = ap->a_vp;
262 register u_long *tl;
263 register caddr_t cp;
264 register int t1, t2;
265 caddr_t bpos, dpos, cp2;
266 int error = 0, attrflag;
267 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
268 u_long mode, rmode;
269 int v3 = NFS_ISV3(vp);
270
271 /*
272 * Disallow write attempts on filesystems mounted read-only;
273 * unless the file is a socket, fifo, or a block or character
274 * device resident on the filesystem.
275 */
276 if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
277 switch (vp->v_type) {
278 case VREG:
279 case VDIR:
280 case VLNK:
281 return (EROFS);
282 default:
283 break;
284 }
285 }
286 /*
287 * For nfs v3, do an access rpc, otherwise you are stuck emulating
288 * ufs_access() locally using the vattr. This may not be correct,
289 * since the server may apply other access criteria such as
290 * client uid-->server uid mapping that we do not know about, but
291 * this is better than just returning anything that is lying about
292 * in the cache.
293 */
294 if (v3) {
295 nfsstats.rpccnt[NFSPROC_ACCESS]++;
296 nfsm_reqhead(vp, NFSPROC_ACCESS, NFSX_FH(v3) + NFSX_UNSIGNED);
297 nfsm_fhtom(vp, v3);
298 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
299 if (ap->a_mode & VREAD)
300 mode = NFSV3ACCESS_READ;
301 else
302 mode = 0;
303 if (vp->v_type != VDIR) {
304 if (ap->a_mode & VWRITE)
305 mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
306 if (ap->a_mode & VEXEC)
307 mode |= NFSV3ACCESS_EXECUTE;
308 } else {
309 if (ap->a_mode & VWRITE)
310 mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
311 NFSV3ACCESS_DELETE);
312 if (ap->a_mode & VEXEC)
313 mode |= NFSV3ACCESS_LOOKUP;
314 }
315 *tl = txdr_unsigned(mode);
316 nfsm_request(vp, NFSPROC_ACCESS, ap->a_p, ap->a_cred);
317 nfsm_postop_attr(vp, attrflag);
318 if (!error) {
319 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
320 rmode = fxdr_unsigned(u_long, *tl);
321 /*
322 * The NFS V3 spec does not clarify whether or not
323 * the returned access bits can be a superset of
324 * the ones requested, so...
325 */
326 if ((rmode & mode) != mode)
327 error = EACCES;
328 }
329 nfsm_reqdone;
330 return (error);
331 } else {
332 if (error = nfsspec_access(ap))
333 return (error);
334
335 /*
336 * Attempt to prevent a mapped root from accessing a file
337 * which it shouldn't. We try to read a byte from the file
338 * if the user is root and the file is not zero length.
339 * After calling nfsspec_access, we should have the correct
340 * file size cached.
341 */
342 if (ap->a_cred->cr_uid == 0 && (ap->a_mode & VREAD)
343 && VTONFS(vp)->n_size > 0) {
344 struct iovec aiov;
345 struct uio auio;
346 char buf[1];
347
348 aiov.iov_base = buf;
349 aiov.iov_len = 1;
350 auio.uio_iov = &aiov;
351 auio.uio_iovcnt = 1;
352 auio.uio_offset = 0;
353 auio.uio_resid = 1;
354 auio.uio_segflg = UIO_SYSSPACE;
355 auio.uio_rw = UIO_READ;
356 auio.uio_procp = ap->a_p;
357
358 if (vp->v_type == VREG)
359 error = nfs_readrpc(vp, &auio, ap->a_cred);
360 else if (vp->v_type == VDIR) {
361 char* bp;
362 bp = malloc(NFS_DIRBLKSIZ, M_TEMP, M_WAITOK);
363 aiov.iov_base = bp;
364 aiov.iov_len = auio.uio_resid = NFS_DIRBLKSIZ;
365 error = nfs_readdirrpc(vp, &auio, ap->a_cred);
366 free(bp, M_TEMP);
367 } else if (vp->v_type = VLNK)
368 error = nfs_readlinkrpc(vp, &auio, ap->a_cred);
369 else
370 error = EACCES;
371 }
372 return (error);
373 }
374}
375
376/*
377 * nfs open vnode op
378 * Check to see if the type is ok
379 * and that deletion is not in progress.
380 * For paged in text files, you will need to flush the page cache
381 * if consistency is lost.
382 */
383/* ARGSUSED */
384static int
385nfs_open(ap)
386 struct vop_open_args /* {
387 struct vnode *a_vp;
388 int a_mode;
389 struct ucred *a_cred;
390 struct proc *a_p;
391 } */ *ap;
392{
393 register struct vnode *vp = ap->a_vp;
394 struct nfsnode *np = VTONFS(vp);
395 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
396 struct vattr vattr;
397 int error;
398
399 if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) {
400 printf("open eacces vtyp=%d\n",vp->v_type);
401 return (EACCES);
402 }
403 /*
404 * Get a valid lease. If cached data is stale, flush it.
405 */
406 if (nmp->nm_flag & NFSMNT_NQNFS) {
407 if (NQNFS_CKINVALID(vp, np, ND_READ)) {
408 do {
409 error = nqnfs_getlease(vp, ND_READ, ap->a_cred,
410 ap->a_p);
411 } while (error == NQNFS_EXPIRED);
412 if (error)
413 return (error);
414 if (np->n_lrev != np->n_brev ||
415 (np->n_flag & NQNFSNONCACHE)) {
416 if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
417 ap->a_p, 1)) == EINTR)
418 return (error);
419 np->n_brev = np->n_lrev;
420 }
421 }
422 } else {
423 if (np->n_flag & NMODIFIED) {
424 if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
425 ap->a_p, 1)) == EINTR)
426 return (error);
427 np->n_attrstamp = 0;
428 if (vp->v_type == VDIR)
429 np->n_direofoffset = 0;
430 error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p);
431 if (error)
432 return (error);
433 np->n_mtime = vattr.va_mtime.tv_sec;
434 } else {
435 error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p);
436 if (error)
437 return (error);
438 if (np->n_mtime != vattr.va_mtime.tv_sec) {
439 if (vp->v_type == VDIR)
440 np->n_direofoffset = 0;
441 if ((error = nfs_vinvalbuf(vp, V_SAVE,
442 ap->a_cred, ap->a_p, 1)) == EINTR)
443 return (error);
444 np->n_mtime = vattr.va_mtime.tv_sec;
445 }
446 }
447 }
448 if ((nmp->nm_flag & NFSMNT_NQNFS) == 0)
449 np->n_attrstamp = 0; /* For Open/Close consistency */
450 return (0);
451}
452
453/*
454 * nfs close vnode op
455 * What an NFS client should do upon close after writing is a debatable issue.
456 * Most NFS clients push delayed writes to the server upon close, basically for
457 * two reasons:
458 * 1 - So that any write errors may be reported back to the client process
459 * doing the close system call. By far the two most likely errors are
460 * NFSERR_NOSPC and NFSERR_DQUOT to indicate space allocation failure.
461 * 2 - To put a worst case upper bound on cache inconsistency between
462 * multiple clients for the file.
463 * There is also a consistency problem for Version 2 of the protocol w.r.t.
464 * not being able to tell if other clients are writing a file concurrently,
465 * since there is no way of knowing if the changed modify time in the reply
466 * is only due to the write for this client.
467 * (NFS Version 3 provides weak cache consistency data in the reply that
468 * should be sufficient to detect and handle this case.)
469 *
470 * The current code does the following:
471 * for NFS Version 2 - play it safe and flush/invalidate all dirty buffers
472 * for NFS Version 3 - flush dirty buffers to the server but don't invalidate
473 * or commit them (this satisfies 1 and 2 except for the
474 * case where the server crashes after this close but
475 * before the commit RPC, which is felt to be "good
476 * enough". Changing the last argument to nfs_flush() to
477 * a 1 would force a commit operation, if it is felt a
478 * commit is necessary now.
479 * for NQNFS - do nothing now, since 2 is dealt with via leases and
480 * 1 should be dealt with via an fsync() system call for
481 * cases where write errors are important.
482 */
483/* ARGSUSED */
484static int
485nfs_close(ap)
486 struct vop_close_args /* {
487 struct vnodeop_desc *a_desc;
488 struct vnode *a_vp;
489 int a_fflag;
490 struct ucred *a_cred;
491 struct proc *a_p;
492 } */ *ap;
493{
494 register struct vnode *vp = ap->a_vp;
495 register struct nfsnode *np = VTONFS(vp);
496 int error = 0;
497
498 if (vp->v_type == VREG) {
499 if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) == 0 &&
500 (np->n_flag & NMODIFIED)) {
501 if (NFS_ISV3(vp)) {
502 error = nfs_flush(vp, ap->a_cred, MNT_WAIT, ap->a_p, 0);
503 np->n_flag &= ~NMODIFIED;
504 } else
505 error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 1);
506 np->n_attrstamp = 0;
507 }
508 if (np->n_flag & NWRITEERR) {
509 np->n_flag &= ~NWRITEERR;
510 error = np->n_error;
511 }
512 }
513 return (error);
514}
515
516/*
517 * nfs getattr call from vfs.
518 */
519static int
520nfs_getattr(ap)
521 struct vop_getattr_args /* {
522 struct vnode *a_vp;
523 struct vattr *a_vap;
524 struct ucred *a_cred;
525 struct proc *a_p;
526 } */ *ap;
527{
528 register struct vnode *vp = ap->a_vp;
529 register struct nfsnode *np = VTONFS(vp);
530 register caddr_t cp;
531 register u_long *tl;
532 register int t1, t2;
533 caddr_t bpos, dpos;
534 int error = 0;
535 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
536 int v3 = NFS_ISV3(vp);
537
538 /*
539 * Update local times for special files.
540 */
541 if (np->n_flag & (NACC | NUPD))
542 np->n_flag |= NCHG;
543 /*
544 * First look in the cache.
545 */
546 if (nfs_getattrcache(vp, ap->a_vap) == 0)
547 return (0);
548 nfsstats.rpccnt[NFSPROC_GETATTR]++;
549 nfsm_reqhead(vp, NFSPROC_GETATTR, NFSX_FH(v3));
550 nfsm_fhtom(vp, v3);
551 nfsm_request(vp, NFSPROC_GETATTR, ap->a_p, ap->a_cred);
552 if (!error) {
553 nfsm_loadattr(vp, ap->a_vap);
554 }
555 nfsm_reqdone;
556 return (error);
557}
558
559/*
560 * nfs setattr call.
561 */
562static int
563nfs_setattr(ap)
564 struct vop_setattr_args /* {
565 struct vnodeop_desc *a_desc;
566 struct vnode *a_vp;
567 struct vattr *a_vap;
568 struct ucred *a_cred;
569 struct proc *a_p;
570 } */ *ap;
571{
572 register struct vnode *vp = ap->a_vp;
573 register struct nfsnode *np = VTONFS(vp);
574 register struct vattr *vap = ap->a_vap;
575 int error = 0;
576 u_quad_t tsize;
577
578#ifndef nolint
579 tsize = (u_quad_t)0;
580#endif
581 /*
582 * Disallow write attempts if the filesystem is mounted read-only.
583 */
584 if ((vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
585 vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
586 vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) &&
587 (vp->v_mount->mnt_flag & MNT_RDONLY))
588 return (EROFS);
589 if (vap->va_size != VNOVAL) {
590 switch (vp->v_type) {
591 case VDIR:
592 return (EISDIR);
593 case VCHR:
594 case VBLK:
595 case VSOCK:
596 case VFIFO:
597 if (vap->va_mtime.tv_sec == VNOVAL &&
598 vap->va_atime.tv_sec == VNOVAL &&
599 vap->va_mode == (u_short)VNOVAL &&
600 vap->va_uid == (uid_t)VNOVAL &&
601 vap->va_gid == (gid_t)VNOVAL)
602 return (0);
603 vap->va_size = VNOVAL;
604 break;
605 default:
606 /*
607 * Disallow write attempts if the filesystem is
608 * mounted read-only.
609 */
610 if (vp->v_mount->mnt_flag & MNT_RDONLY)
611 return (EROFS);
612 if (np->n_flag & NMODIFIED) {
613 if (vap->va_size == 0)
614 error = nfs_vinvalbuf(vp, 0,
615 ap->a_cred, ap->a_p, 1);
616 else
617 error = nfs_vinvalbuf(vp, V_SAVE,
618 ap->a_cred, ap->a_p, 1);
619 if (error)
620 return (error);
621 }
622 tsize = np->n_size;
623 np->n_size = np->n_vattr.va_size = vap->va_size;
624 vnode_pager_setsize(vp, (u_long)np->n_size);
625 };
626 } else if ((vap->va_mtime.tv_sec != VNOVAL ||
627 vap->va_atime.tv_sec != VNOVAL) && (np->n_flag & NMODIFIED) &&
628 vp->v_type == VREG &&
629 (error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
630 ap->a_p, 1)) == EINTR)
631 return (error);
632 error = nfs_setattrrpc(vp, vap, ap->a_cred, ap->a_p);
633 if (error && vap->va_size != VNOVAL) {
634 np->n_size = np->n_vattr.va_size = tsize;
635 vnode_pager_setsize(vp, (u_long)np->n_size);
636 }
637 return (error);
638}
639
640/*
641 * Do an nfs setattr rpc.
642 */
643static int
644nfs_setattrrpc(vp, vap, cred, procp)
645 register struct vnode *vp;
646 register struct vattr *vap;
647 struct ucred *cred;
648 struct proc *procp;
649{
650 register struct nfsv2_sattr *sp;
651 register caddr_t cp;
652 register long t1, t2;
653 caddr_t bpos, dpos, cp2;
654 u_long *tl;
655 int error = 0, wccflag = NFSV3_WCCRATTR;
656 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
657 int v3 = NFS_ISV3(vp);
658
659 nfsstats.rpccnt[NFSPROC_SETATTR]++;
660 nfsm_reqhead(vp, NFSPROC_SETATTR, NFSX_FH(v3) + NFSX_SATTR(v3));
661 nfsm_fhtom(vp, v3);
662 if (v3) {
663 if (vap->va_mode != (u_short)VNOVAL) {
664 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
665 *tl++ = nfs_true;
666 *tl = txdr_unsigned(vap->va_mode);
667 } else {
668 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
669 *tl = nfs_false;
670 }
671 if (vap->va_uid != (uid_t)VNOVAL) {
672 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
673 *tl++ = nfs_true;
674 *tl = txdr_unsigned(vap->va_uid);
675 } else {
676 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
677 *tl = nfs_false;
678 }
679 if (vap->va_gid != (gid_t)VNOVAL) {
680 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
681 *tl++ = nfs_true;
682 *tl = txdr_unsigned(vap->va_gid);
683 } else {
684 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
685 *tl = nfs_false;
686 }
687 if (vap->va_size != VNOVAL) {
688 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED);
689 *tl++ = nfs_true;
690 txdr_hyper(&vap->va_size, tl);
691 } else {
692 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
693 *tl = nfs_false;
694 }
695 if (vap->va_atime.tv_sec != VNOVAL) {
696 if (vap->va_atime.tv_sec != time_second) {
697 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED);
698 *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);
699 txdr_nfsv3time(&vap->va_atime, tl);
700 } else {
701 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
702 *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER);
703 }
704 } else {
705 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
706 *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE);
707 }
708 if (vap->va_mtime.tv_sec != VNOVAL) {
709 if (vap->va_mtime.tv_sec != time_second) {
710 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED);
711 *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);
712 txdr_nfsv3time(&vap->va_mtime, tl);
713 } else {
714 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
715 *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER);
716 }
717 } else {
718 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
719 *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE);
720 }
721 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
722 *tl = nfs_false;
723 } else {
724 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
725 if (vap->va_mode == (u_short)VNOVAL)
726 sp->sa_mode = VNOVAL;
727 else
728 sp->sa_mode = vtonfsv2_mode(vp->v_type, vap->va_mode);
729 if (vap->va_uid == (uid_t)VNOVAL)
730 sp->sa_uid = VNOVAL;
731 else
732 sp->sa_uid = txdr_unsigned(vap->va_uid);
733 if (vap->va_gid == (gid_t)VNOVAL)
734 sp->sa_gid = VNOVAL;
735 else
736 sp->sa_gid = txdr_unsigned(vap->va_gid);
737 sp->sa_size = txdr_unsigned(vap->va_size);
738 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
739 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
740 }
741 nfsm_request(vp, NFSPROC_SETATTR, procp, cred);
742 if (v3) {
743 nfsm_wcc_data(vp, wccflag);
744 } else
745 nfsm_loadattr(vp, (struct vattr *)0);
746 nfsm_reqdone;
747 return (error);
748}
749
750/*
751 * nfs lookup call, one step at a time...
752 * First look in cache
753 * If not found, unlock the directory nfsnode and do the rpc
754 */
755static int
756nfs_lookup(ap)
757 struct vop_lookup_args /* {
758 struct vnodeop_desc *a_desc;
759 struct vnode *a_dvp;
760 struct vnode **a_vpp;
761 struct componentname *a_cnp;
762 } */ *ap;
763{
764 struct componentname *cnp = ap->a_cnp;
765 struct vnode *dvp = ap->a_dvp;
766 struct vnode **vpp = ap->a_vpp;
767 int flags = cnp->cn_flags;
768 struct vnode *newvp;
769 u_long *tl;
770 caddr_t cp;
771 long t1, t2;
772 struct nfsmount *nmp;
773 caddr_t bpos, dpos, cp2;
774 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
775 long len;
776 nfsfh_t *fhp;
777 struct nfsnode *np;
778 int lockparent, wantparent, error = 0, attrflag, fhsize;
779 int v3 = NFS_ISV3(dvp);
780 struct proc *p = cnp->cn_proc;
781
782 *vpp = NULLVP;
783 if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
784 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
785 return (EROFS);
786 if (dvp->v_type != VDIR)
787 return (ENOTDIR);
788 lockparent = flags & LOCKPARENT;
789 wantparent = flags & (LOCKPARENT|WANTPARENT);
790 nmp = VFSTONFS(dvp->v_mount);
791 np = VTONFS(dvp);
792 if ((error = cache_lookup(dvp, vpp, cnp)) && error != ENOENT) {
793 struct vattr vattr;
794 int vpid;
795
796 if (error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, p)) {
797 *vpp = NULLVP;
798 return (error);
799 }
800
801 newvp = *vpp;
802 vpid = newvp->v_id;
803 /*
804 * See the comment starting `Step through' in ufs/ufs_lookup.c
805 * for an explanation of the locking protocol
806 */
807 if (dvp == newvp) {
808 VREF(newvp);
809 error = 0;
810 } else if (flags & ISDOTDOT) {
811 VOP_UNLOCK(dvp, 0, p);
812 error = vget(newvp, LK_EXCLUSIVE, p);
813 if (!error && lockparent && (flags & ISLASTCN))
814 error = vn_lock(dvp, LK_EXCLUSIVE, p);
815 } else {
816 error = vget(newvp, LK_EXCLUSIVE, p);
817 if (!lockparent || error || !(flags & ISLASTCN))
818 VOP_UNLOCK(dvp, 0, p);
819 }
820 if (!error) {
821 if (vpid == newvp->v_id) {
822 if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, p)
823 && vattr.va_ctime.tv_sec == VTONFS(newvp)->n_ctime) {
824 nfsstats.lookupcache_hits++;
825 if (cnp->cn_nameiop != LOOKUP &&
826 (flags & ISLASTCN))
827 cnp->cn_flags |= SAVENAME;
828 return (0);
829 }
830 cache_purge(newvp);
831 }
832 vput(newvp);
833 if (lockparent && dvp != newvp && (flags & ISLASTCN))
834 VOP_UNLOCK(dvp, 0, p);
835 }
836 error = vn_lock(dvp, LK_EXCLUSIVE, p);
837 *vpp = NULLVP;
838 if (error)
839 return (error);
840 }
841 error = 0;
842 newvp = NULLVP;
843 nfsstats.lookupcache_misses++;
844 nfsstats.rpccnt[NFSPROC_LOOKUP]++;
845 len = cnp->cn_namelen;
846 nfsm_reqhead(dvp, NFSPROC_LOOKUP,
847 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len));
848 nfsm_fhtom(dvp, v3);
849 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
850 nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred);
851 if (error) {
852 nfsm_postop_attr(dvp, attrflag);
853 m_freem(mrep);
854 goto nfsmout;
855 }
856 nfsm_getfh(fhp, fhsize, v3);
857
858 /*
859 * Handle RENAME case...
860 */
861 if (cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)) {
862 if (NFS_CMPFH(np, fhp, fhsize)) {
863 m_freem(mrep);
864 return (EISDIR);
865 }
866 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
867 if (error) {
868 m_freem(mrep);
869 return (error);
870 }
871 newvp = NFSTOV(np);
872 if (v3) {
873 nfsm_postop_attr(newvp, attrflag);
874 nfsm_postop_attr(dvp, attrflag);
875 } else
876 nfsm_loadattr(newvp, (struct vattr *)0);
877 *vpp = newvp;
878 m_freem(mrep);
879 cnp->cn_flags |= SAVENAME;
880 if (!lockparent)
881 VOP_UNLOCK(dvp, 0, p);
882 return (0);
883 }
884
885 if (flags & ISDOTDOT) {
886 VOP_UNLOCK(dvp, 0, p);
887 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
888 if (error) {
889 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p);
890 return (error);
891 }
892 newvp = NFSTOV(np);
893 if (lockparent && (flags & ISLASTCN) &&
894 (error = vn_lock(dvp, LK_EXCLUSIVE, p))) {
895 vput(newvp);
896 return (error);
897 }
898 } else if (NFS_CMPFH(np, fhp, fhsize)) {
899 VREF(dvp);
900 newvp = dvp;
901 } else {
902 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
903 if (error) {
904 m_freem(mrep);
905 return (error);
906 }
907 if (!lockparent || !(flags & ISLASTCN))
908 VOP_UNLOCK(dvp, 0, p);
909 newvp = NFSTOV(np);
910 }
911 if (v3) {
912 nfsm_postop_attr(newvp, attrflag);
913 nfsm_postop_attr(dvp, attrflag);
914 } else
915 nfsm_loadattr(newvp, (struct vattr *)0);
916 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
917 cnp->cn_flags |= SAVENAME;
918 if ((cnp->cn_flags & MAKEENTRY) &&
919 (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) {
920 np->n_ctime = np->n_vattr.va_ctime.tv_sec;
921 cache_enter(dvp, newvp, cnp);
922 }
923 *vpp = newvp;
924 nfsm_reqdone;
925 if (error) {
926 if (newvp != NULLVP) {
927 vrele(newvp);
928 *vpp = NULLVP;
929 }
930 if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) &&
931 (flags & ISLASTCN) && error == ENOENT) {
932 if (!lockparent)
933 VOP_UNLOCK(dvp, 0, p);
934 if (dvp->v_mount->mnt_flag & MNT_RDONLY)
935 error = EROFS;
936 else
937 error = EJUSTRETURN;
938 }
939 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
940 cnp->cn_flags |= SAVENAME;
941 }
942 return (error);
943}
944
945/*
946 * nfs read call.
947 * Just call nfs_bioread() to do the work.
948 */
949static int
950nfs_read(ap)
951 struct vop_read_args /* {
952 struct vnode *a_vp;
953 struct uio *a_uio;
954 int a_ioflag;
955 struct ucred *a_cred;
956 } */ *ap;
957{
958 register struct vnode *vp = ap->a_vp;
959
960 if (vp->v_type != VREG)
961 return (EPERM);
962 return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred, 0));
963}
964
965/*
966 * nfs readlink call
967 */
968static int
969nfs_readlink(ap)
970 struct vop_readlink_args /* {
971 struct vnode *a_vp;
972 struct uio *a_uio;
973 struct ucred *a_cred;
974 } */ *ap;
975{
976 register struct vnode *vp = ap->a_vp;
977
978 if (vp->v_type != VLNK)
979 return (EPERM);
980 return (nfs_bioread(vp, ap->a_uio, 0, ap->a_cred, 0));
981}
982
983/*
984 * Do a readlink rpc.
985 * Called by nfs_doio() from below the buffer cache.
986 */
987int
988nfs_readlinkrpc(vp, uiop, cred)
989 register struct vnode *vp;
990 struct uio *uiop;
991 struct ucred *cred;
992{
993 register u_long *tl;
994 register caddr_t cp;
995 register long t1, t2;
996 caddr_t bpos, dpos, cp2;
997 int error = 0, len, attrflag;
998 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
999 int v3 = NFS_ISV3(vp);
1000
1001 nfsstats.rpccnt[NFSPROC_READLINK]++;
1002 nfsm_reqhead(vp, NFSPROC_READLINK, NFSX_FH(v3));
1003 nfsm_fhtom(vp, v3);
1004 nfsm_request(vp, NFSPROC_READLINK, uiop->uio_procp, cred);
1005 if (v3)
1006 nfsm_postop_attr(vp, attrflag);
1007 if (!error) {
1008 nfsm_strsiz(len, NFS_MAXPATHLEN);
1009 nfsm_mtouio(uiop, len);
1010 }
1011 nfsm_reqdone;
1012 return (error);
1013}
1014
1015/*
1016 * nfs read rpc call
1017 * Ditto above
1018 */
1019int
1020nfs_readrpc(vp, uiop, cred)
1021 register struct vnode *vp;
1022 struct uio *uiop;
1023 struct ucred *cred;
1024{
1025 register u_long *tl;
1026 register caddr_t cp;
1027 register long t1, t2;
1028 caddr_t bpos, dpos, cp2;
1029 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1030 struct nfsmount *nmp;
1031 int error = 0, len, retlen, tsiz, eof, attrflag;
1032 int v3 = NFS_ISV3(vp);
1033
1034#ifndef nolint
1035 eof = 0;
1036#endif
1037 nmp = VFSTONFS(vp->v_mount);
1038 tsiz = uiop->uio_resid;
1039 if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize)
1040 return (EFBIG);
1041 while (tsiz > 0) {
1042 nfsstats.rpccnt[NFSPROC_READ]++;
1043 len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz;
1044 nfsm_reqhead(vp, NFSPROC_READ, NFSX_FH(v3) + NFSX_UNSIGNED * 3);
1045 nfsm_fhtom(vp, v3);
1046 nfsm_build(tl, u_long *, NFSX_UNSIGNED * 3);
1047 if (v3) {
1048 txdr_hyper(&uiop->uio_offset, tl);
1049 *(tl + 2) = txdr_unsigned(len);
1050 } else {
1051 *tl++ = txdr_unsigned(uiop->uio_offset);
1052 *tl++ = txdr_unsigned(len);
1053 *tl = 0;
1054 }
1055 nfsm_request(vp, NFSPROC_READ, uiop->uio_procp, cred);
1056 if (v3) {
1057 nfsm_postop_attr(vp, attrflag);
1058 if (error) {
1059 m_freem(mrep);
1060 goto nfsmout;
1061 }
1062 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
1063 eof = fxdr_unsigned(int, *(tl + 1));
1064 } else
1065 nfsm_loadattr(vp, (struct vattr *)0);
1066 nfsm_strsiz(retlen, nmp->nm_rsize);
1067 nfsm_mtouio(uiop, retlen);
1068 m_freem(mrep);
1069 tsiz -= retlen;
1070 if (v3) {
1071 if (eof || retlen == 0)
1072 tsiz = 0;
1073 } else if (retlen < len)
1074 tsiz = 0;
1075 }
1076nfsmout:
1077 return (error);
1078}
1079
1080/*
1081 * nfs write call
1082 */
1083int
1084nfs_writerpc(vp, uiop, cred, iomode, must_commit)
1085 register struct vnode *vp;
1086 register struct uio *uiop;
1087 struct ucred *cred;
1088 int *iomode, *must_commit;
1089{
1090 register u_long *tl;
1091 register caddr_t cp;
1092 register int t1, t2, backup;
1093 caddr_t bpos, dpos, cp2;
1094 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1095 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
1096 int error = 0, len, tsiz, wccflag = NFSV3_WCCRATTR, rlen, commit;
1097 int v3 = NFS_ISV3(vp), committed = NFSV3WRITE_FILESYNC;
1098
1099#ifndef DIAGNOSTIC
1100 if (uiop->uio_iovcnt != 1)
1101 panic("nfs: writerpc iovcnt > 1");
1102#endif
1103 *must_commit = 0;
1104 tsiz = uiop->uio_resid;
1105 if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize)
1106 return (EFBIG);
1107 while (tsiz > 0) {
1108 nfsstats.rpccnt[NFSPROC_WRITE]++;
1109 len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz;
1110 nfsm_reqhead(vp, NFSPROC_WRITE,
1111 NFSX_FH(v3) + 5 * NFSX_UNSIGNED + nfsm_rndup(len));
1112 nfsm_fhtom(vp, v3);
1113 if (v3) {
1114 nfsm_build(tl, u_long *, 5 * NFSX_UNSIGNED);
1115 txdr_hyper(&uiop->uio_offset, tl);
1116 tl += 2;
1117 *tl++ = txdr_unsigned(len);
1118 *tl++ = txdr_unsigned(*iomode);
1119 } else {
1120 nfsm_build(tl, u_long *, 4 * NFSX_UNSIGNED);
1121 *++tl = txdr_unsigned(uiop->uio_offset);
1122 tl += 2;
1123 }
1124 *tl = txdr_unsigned(len);
1125 nfsm_uiotom(uiop, len);
1126 nfsm_request(vp, NFSPROC_WRITE, uiop->uio_procp, cred);
1127 if (v3) {
1128 wccflag = NFSV3_WCCCHK;
1129 nfsm_wcc_data(vp, wccflag);
1130 if (!error) {
1131 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED +
1132 NFSX_V3WRITEVERF);
1133 rlen = fxdr_unsigned(int, *tl++);
1134 if (rlen == 0) {
1135 error = NFSERR_IO;
1136 break;
1137 } else if (rlen < len) {
1138 backup = len - rlen;
1139 uiop->uio_iov->iov_base -= backup;
1140 uiop->uio_iov->iov_len += backup;
1141 uiop->uio_offset -= backup;
1142 uiop->uio_resid += backup;
1143 len = rlen;
1144 }
1145 commit = fxdr_unsigned(int, *tl++);
1146
1147 /*
1148 * Return the lowest committment level
1149 * obtained by any of the RPCs.
1150 */
1151 if (committed == NFSV3WRITE_FILESYNC)
1152 committed = commit;
1153 else if (committed == NFSV3WRITE_DATASYNC &&
1154 commit == NFSV3WRITE_UNSTABLE)
1155 committed = commit;
1156 if ((nmp->nm_state & NFSSTA_HASWRITEVERF) == 0){
1157 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf,
1158 NFSX_V3WRITEVERF);
1159 nmp->nm_state |= NFSSTA_HASWRITEVERF;
1160 } else if (bcmp((caddr_t)tl,
1161 (caddr_t)nmp->nm_verf, NFSX_V3WRITEVERF)) {
1162 *must_commit = 1;
1163 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf,
1164 NFSX_V3WRITEVERF);
1165 }
1166 }
1167 } else
1168 nfsm_loadattr(vp, (struct vattr *)0);
1169 if (wccflag)
1170 VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime.tv_sec;
1171 m_freem(mrep);
1172 tsiz -= len;
1173 }
1174nfsmout:
1175 if (vp->v_mount->mnt_flag & MNT_ASYNC)
1176 committed = NFSV3WRITE_FILESYNC;
1177 *iomode = committed;
1178 if (error)
1179 uiop->uio_resid = tsiz;
1180 return (error);
1181}
1182
1183/*
1184 * nfs mknod rpc
1185 * For NFS v2 this is a kludge. Use a create rpc but with the IFMT bits of the
1186 * mode set to specify the file type and the size field for rdev.
1187 */
1188static int
1189nfs_mknodrpc(dvp, vpp, cnp, vap)
1190 register struct vnode *dvp;
1191 register struct vnode **vpp;
1192 register struct componentname *cnp;
1193 register struct vattr *vap;
1194{
1195 register struct nfsv2_sattr *sp;
1196 register struct nfsv3_sattr *sp3;
1197 register u_long *tl;
1198 register caddr_t cp;
1199 register long t1, t2;
1200 struct vnode *newvp = (struct vnode *)0;
1201 struct nfsnode *np = (struct nfsnode *)0;
1202 struct vattr vattr;
1203 char *cp2;
1204 caddr_t bpos, dpos;
1205 int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0;
1206 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1207 u_long rdev;
1208 int v3 = NFS_ISV3(dvp);
1209
1210 if (vap->va_type == VCHR || vap->va_type == VBLK)
1211 rdev = txdr_unsigned(vap->va_rdev);
1212 else if (vap->va_type == VFIFO || vap->va_type == VSOCK)
1213 rdev = 0xffffffff;
1214 else {
1215 VOP_ABORTOP(dvp, cnp);
1216 return (EOPNOTSUPP);
1217 }
1218 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) {
1219 VOP_ABORTOP(dvp, cnp);
1220 return (error);
1221 }
1222 nfsstats.rpccnt[NFSPROC_MKNOD]++;
1223 nfsm_reqhead(dvp, NFSPROC_MKNOD, NFSX_FH(v3) + 4 * NFSX_UNSIGNED +
1224 + nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3));
1225 nfsm_fhtom(dvp, v3);
1226 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1227 if (v3) {
1228 nfsm_build(tl, u_long *, NFSX_UNSIGNED + NFSX_V3SRVSATTR);
1229 *tl++ = vtonfsv3_type(vap->va_type);
1230 sp3 = (struct nfsv3_sattr *)tl;
1231 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, vattr.va_gid);
1232 if (vap->va_type == VCHR || vap->va_type == VBLK) {
1233 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
1234 *tl++ = txdr_unsigned(major(vap->va_rdev));
1235 *tl = txdr_unsigned(minor(vap->va_rdev));
1236 }
1237 } else {
1238 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1239 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
1240 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid);
1241 sp->sa_gid = txdr_unsigned(vattr.va_gid);
1242 sp->sa_size = rdev;
1243 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
1244 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
1245 }
1246 nfsm_request(dvp, NFSPROC_MKNOD, cnp->cn_proc, cnp->cn_cred);
1247 if (!error) {
1248 nfsm_mtofh(dvp, newvp, v3, gotvp);
1249 if (!gotvp) {
1250 if (newvp) {
1251 vput(newvp);
1252 newvp = (struct vnode *)0;
1253 }
1254 error = nfs_lookitup(dvp, cnp->cn_nameptr,
1255 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc, &np);
1256 if (!error)
1257 newvp = NFSTOV(np);
1258 }
1259 }
1260 if (v3)
1261 nfsm_wcc_data(dvp, wccflag);
1262 nfsm_reqdone;
1263 if (error) {
1264 if (newvp)
1265 vput(newvp);
1266 } else {
1267 if (cnp->cn_flags & MAKEENTRY)
1268 cache_enter(dvp, newvp, cnp);
1269 *vpp = newvp;
1270 }
1271 zfree(namei_zone, cnp->cn_pnbuf);
1272 VTONFS(dvp)->n_flag |= NMODIFIED;
1273 if (!wccflag)
1274 VTONFS(dvp)->n_attrstamp = 0;
1275 return (error);
1276}
1277
1278/*
1279 * nfs mknod vop
1280 * just call nfs_mknodrpc() to do the work.
1281 */
1282/* ARGSUSED */
1283static int
1284nfs_mknod(ap)
1285 struct vop_mknod_args /* {
1286 struct vnode *a_dvp;
1287 struct vnode **a_vpp;
1288 struct componentname *a_cnp;
1289 struct vattr *a_vap;
1290 } */ *ap;
1291{
1292 struct vnode *newvp;
1293 int error;
1294
1295 error = nfs_mknodrpc(ap->a_dvp, &newvp, ap->a_cnp, ap->a_vap);
1296 if (!error)
1297 vput(newvp);
1298 return (error);
1299}
1300
1301static u_long create_verf;
1302/*
1303 * nfs file create call
1304 */
1305static int
1306nfs_create(ap)
1307 struct vop_create_args /* {
1308 struct vnode *a_dvp;
1309 struct vnode **a_vpp;
1310 struct componentname *a_cnp;
1311 struct vattr *a_vap;
1312 } */ *ap;
1313{
1314 register struct vnode *dvp = ap->a_dvp;
1315 register struct vattr *vap = ap->a_vap;
1316 register struct componentname *cnp = ap->a_cnp;
1317 register struct nfsv2_sattr *sp;
1318 register struct nfsv3_sattr *sp3;
1319 register u_long *tl;
1320 register caddr_t cp;
1321 register long t1, t2;
1322 struct nfsnode *np = (struct nfsnode *)0;
1323 struct vnode *newvp = (struct vnode *)0;
1324 caddr_t bpos, dpos, cp2;
1325 int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0, fmode = 0;
1326 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1327 struct vattr vattr;
1328 int v3 = NFS_ISV3(dvp);
1329
1330 /*
1331 * Oops, not for me..
1332 */
1333 if (vap->va_type == VSOCK)
1334 return (nfs_mknodrpc(dvp, ap->a_vpp, cnp, vap));
1335
1336 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) {
1337 VOP_ABORTOP(dvp, cnp);
1338 return (error);
1339 }
1340 if (vap->va_vaflags & VA_EXCLUSIVE)
1341 fmode |= O_EXCL;
1342again:
1343 nfsstats.rpccnt[NFSPROC_CREATE]++;
1344 nfsm_reqhead(dvp, NFSPROC_CREATE, NFSX_FH(v3) + 2 * NFSX_UNSIGNED +
1345 nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3));
1346 nfsm_fhtom(dvp, v3);
1347 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1348 if (v3) {
1349 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
1350 if (fmode & O_EXCL) {
1351 *tl = txdr_unsigned(NFSV3CREATE_EXCLUSIVE);
1352 nfsm_build(tl, u_long *, NFSX_V3CREATEVERF);
1353#ifdef INET
1354 if (!TAILQ_EMPTY(&in_ifaddrhead))
1355 *tl++ = IA_SIN(in_ifaddrhead.tqh_first)->sin_addr.s_addr;
1356 else
1357#endif
1358 *tl++ = create_verf;
1359 *tl = ++create_verf;
1360 } else {
1361 *tl = txdr_unsigned(NFSV3CREATE_UNCHECKED);
1362 nfsm_build(tl, u_long *, NFSX_V3SRVSATTR);
1363 sp3 = (struct nfsv3_sattr *)tl;
1364 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, vattr.va_gid);
1365 }
1366 } else {
1367 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1368 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
1369 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid);
1370 sp->sa_gid = txdr_unsigned(vattr.va_gid);
1371 sp->sa_size = 0;
1372 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
1373 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
1374 }
1375 nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred);
1376 if (!error) {
1377 nfsm_mtofh(dvp, newvp, v3, gotvp);
1378 if (!gotvp) {
1379 if (newvp) {
1380 vput(newvp);
1381 newvp = (struct vnode *)0;
1382 }
1383 error = nfs_lookitup(dvp, cnp->cn_nameptr,
1384 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc, &np);
1385 if (!error)
1386 newvp = NFSTOV(np);
1387 }
1388 }
1389 if (v3)
1390 nfsm_wcc_data(dvp, wccflag);
1391 nfsm_reqdone;
1392 if (error) {
1393 if (v3 && (fmode & O_EXCL) && error == NFSERR_NOTSUPP) {
1394 fmode &= ~O_EXCL;
1395 goto again;
1396 }
1397 if (newvp)
1398 vput(newvp);
1399 } else if (v3 && (fmode & O_EXCL))
1400 error = nfs_setattrrpc(newvp, vap, cnp->cn_cred, cnp->cn_proc);
1401 if (!error) {
1402 if (cnp->cn_flags & MAKEENTRY)
1403 cache_enter(dvp, newvp, cnp);
1404 *ap->a_vpp = newvp;
1405 }
1406 zfree(namei_zone, cnp->cn_pnbuf);
1407 VTONFS(dvp)->n_flag |= NMODIFIED;
1408 if (!wccflag)
1409 VTONFS(dvp)->n_attrstamp = 0;
1410 return (error);
1411}
1412
1413/*
1414 * nfs file remove call
1415 * To try and make nfs semantics closer to ufs semantics, a file that has
1416 * other processes using the vnode is renamed instead of removed and then
1417 * removed later on the last close.
1418 * - If v_usecount > 1
1419 * If a rename is not already in the works
1420 * call nfs_sillyrename() to set it up
1421 * else
1422 * do the remove rpc
1423 */
1424static int
1425nfs_remove(ap)
1426 struct vop_remove_args /* {
1427 struct vnodeop_desc *a_desc;
1428 struct vnode * a_dvp;
1429 struct vnode * a_vp;
1430 struct componentname * a_cnp;
1431 } */ *ap;
1432{
1433 register struct vnode *vp = ap->a_vp;
1434 register struct vnode *dvp = ap->a_dvp;
1435 register struct componentname *cnp = ap->a_cnp;
1436 register struct nfsnode *np = VTONFS(vp);
1437 int error = 0;
1438 struct vattr vattr;
1439
1440#ifndef DIAGNOSTIC
1441 if ((cnp->cn_flags & HASBUF) == 0)
1442 panic("nfs_remove: no name");
1443 if (vp->v_usecount < 1)
1444 panic("nfs_remove: bad v_usecount");
1445#endif
1446 if (vp->v_usecount == 1 || (np->n_sillyrename &&
1447 VOP_GETATTR(vp, &vattr, cnp->cn_cred, cnp->cn_proc) == 0 &&
1448 vattr.va_nlink > 1)) {
1449 /*
1450 * Purge the name cache so that the chance of a lookup for
1451 * the name succeeding while the remove is in progress is
1452 * minimized. Without node locking it can still happen, such
1453 * that an I/O op returns ESTALE, but since you get this if
1454 * another host removes the file..
1455 */
1456 cache_purge(vp);
1457 /*
1458 * throw away biocache buffers, mainly to avoid
1459 * unnecessary delayed writes later.
1460 */
1461 error = nfs_vinvalbuf(vp, 0, cnp->cn_cred, cnp->cn_proc, 1);
1462 /* Do the rpc */
1463 if (error != EINTR)
1464 error = nfs_removerpc(dvp, cnp->cn_nameptr,
1465 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc);
1466 /*
1467 * Kludge City: If the first reply to the remove rpc is lost..
1468 * the reply to the retransmitted request will be ENOENT
1469 * since the file was in fact removed
1470 * Therefore, we cheat and return success.
1471 */
1472 if (error == ENOENT)
1473 error = 0;
1474 } else if (!np->n_sillyrename)
1475 error = nfs_sillyrename(dvp, vp, cnp);
1476 zfree(namei_zone, cnp->cn_pnbuf);
1477 np->n_attrstamp = 0;
1478 return (error);
1479}
1480
1481/*
1482 * nfs file remove rpc called from nfs_inactive
1483 */
1484int
1485nfs_removeit(sp)
1486 register struct sillyrename *sp;
1487{
1488
1489 return (nfs_removerpc(sp->s_dvp, sp->s_name, sp->s_namlen, sp->s_cred,
1490 (struct proc *)0));
1491}
1492
1493/*
1494 * Nfs remove rpc, called from nfs_remove() and nfs_removeit().
1495 */
1496static int
1497nfs_removerpc(dvp, name, namelen, cred, proc)
1498 register struct vnode *dvp;
232 struct ucred *cred, struct proc *proc));
233static int nfs_renameit __P((struct vnode *sdvp,
234 struct componentname *scnp,
235 struct sillyrename *sp));
236
237/*
238 * Global variables
239 */
240extern u_long nfs_true, nfs_false;
241extern struct nfsstats nfsstats;
242extern nfstype nfsv3_type[9];
243struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
244struct nfsmount *nfs_iodmount[NFS_MAXASYNCDAEMON];
245int nfs_numasync = 0;
246#define DIRHDSIZ (sizeof (struct dirent) - (MAXNAMLEN + 1))
247
248/*
249 * nfs access vnode op.
250 * For nfs version 2, just return ok. File accesses may fail later.
251 * For nfs version 3, use the access rpc to check accessibility. If file modes
252 * are changed on the server, accesses might still fail later.
253 */
254static int
255nfs_access(ap)
256 struct vop_access_args /* {
257 struct vnode *a_vp;
258 int a_mode;
259 struct ucred *a_cred;
260 struct proc *a_p;
261 } */ *ap;
262{
263 register struct vnode *vp = ap->a_vp;
264 register u_long *tl;
265 register caddr_t cp;
266 register int t1, t2;
267 caddr_t bpos, dpos, cp2;
268 int error = 0, attrflag;
269 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
270 u_long mode, rmode;
271 int v3 = NFS_ISV3(vp);
272
273 /*
274 * Disallow write attempts on filesystems mounted read-only;
275 * unless the file is a socket, fifo, or a block or character
276 * device resident on the filesystem.
277 */
278 if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
279 switch (vp->v_type) {
280 case VREG:
281 case VDIR:
282 case VLNK:
283 return (EROFS);
284 default:
285 break;
286 }
287 }
288 /*
289 * For nfs v3, do an access rpc, otherwise you are stuck emulating
290 * ufs_access() locally using the vattr. This may not be correct,
291 * since the server may apply other access criteria such as
292 * client uid-->server uid mapping that we do not know about, but
293 * this is better than just returning anything that is lying about
294 * in the cache.
295 */
296 if (v3) {
297 nfsstats.rpccnt[NFSPROC_ACCESS]++;
298 nfsm_reqhead(vp, NFSPROC_ACCESS, NFSX_FH(v3) + NFSX_UNSIGNED);
299 nfsm_fhtom(vp, v3);
300 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
301 if (ap->a_mode & VREAD)
302 mode = NFSV3ACCESS_READ;
303 else
304 mode = 0;
305 if (vp->v_type != VDIR) {
306 if (ap->a_mode & VWRITE)
307 mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
308 if (ap->a_mode & VEXEC)
309 mode |= NFSV3ACCESS_EXECUTE;
310 } else {
311 if (ap->a_mode & VWRITE)
312 mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
313 NFSV3ACCESS_DELETE);
314 if (ap->a_mode & VEXEC)
315 mode |= NFSV3ACCESS_LOOKUP;
316 }
317 *tl = txdr_unsigned(mode);
318 nfsm_request(vp, NFSPROC_ACCESS, ap->a_p, ap->a_cred);
319 nfsm_postop_attr(vp, attrflag);
320 if (!error) {
321 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
322 rmode = fxdr_unsigned(u_long, *tl);
323 /*
324 * The NFS V3 spec does not clarify whether or not
325 * the returned access bits can be a superset of
326 * the ones requested, so...
327 */
328 if ((rmode & mode) != mode)
329 error = EACCES;
330 }
331 nfsm_reqdone;
332 return (error);
333 } else {
334 if (error = nfsspec_access(ap))
335 return (error);
336
337 /*
338 * Attempt to prevent a mapped root from accessing a file
339 * which it shouldn't. We try to read a byte from the file
340 * if the user is root and the file is not zero length.
341 * After calling nfsspec_access, we should have the correct
342 * file size cached.
343 */
344 if (ap->a_cred->cr_uid == 0 && (ap->a_mode & VREAD)
345 && VTONFS(vp)->n_size > 0) {
346 struct iovec aiov;
347 struct uio auio;
348 char buf[1];
349
350 aiov.iov_base = buf;
351 aiov.iov_len = 1;
352 auio.uio_iov = &aiov;
353 auio.uio_iovcnt = 1;
354 auio.uio_offset = 0;
355 auio.uio_resid = 1;
356 auio.uio_segflg = UIO_SYSSPACE;
357 auio.uio_rw = UIO_READ;
358 auio.uio_procp = ap->a_p;
359
360 if (vp->v_type == VREG)
361 error = nfs_readrpc(vp, &auio, ap->a_cred);
362 else if (vp->v_type == VDIR) {
363 char* bp;
364 bp = malloc(NFS_DIRBLKSIZ, M_TEMP, M_WAITOK);
365 aiov.iov_base = bp;
366 aiov.iov_len = auio.uio_resid = NFS_DIRBLKSIZ;
367 error = nfs_readdirrpc(vp, &auio, ap->a_cred);
368 free(bp, M_TEMP);
369 } else if (vp->v_type = VLNK)
370 error = nfs_readlinkrpc(vp, &auio, ap->a_cred);
371 else
372 error = EACCES;
373 }
374 return (error);
375 }
376}
377
378/*
379 * nfs open vnode op
380 * Check to see if the type is ok
381 * and that deletion is not in progress.
382 * For paged in text files, you will need to flush the page cache
383 * if consistency is lost.
384 */
385/* ARGSUSED */
386static int
387nfs_open(ap)
388 struct vop_open_args /* {
389 struct vnode *a_vp;
390 int a_mode;
391 struct ucred *a_cred;
392 struct proc *a_p;
393 } */ *ap;
394{
395 register struct vnode *vp = ap->a_vp;
396 struct nfsnode *np = VTONFS(vp);
397 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
398 struct vattr vattr;
399 int error;
400
401 if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) {
402 printf("open eacces vtyp=%d\n",vp->v_type);
403 return (EACCES);
404 }
405 /*
406 * Get a valid lease. If cached data is stale, flush it.
407 */
408 if (nmp->nm_flag & NFSMNT_NQNFS) {
409 if (NQNFS_CKINVALID(vp, np, ND_READ)) {
410 do {
411 error = nqnfs_getlease(vp, ND_READ, ap->a_cred,
412 ap->a_p);
413 } while (error == NQNFS_EXPIRED);
414 if (error)
415 return (error);
416 if (np->n_lrev != np->n_brev ||
417 (np->n_flag & NQNFSNONCACHE)) {
418 if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
419 ap->a_p, 1)) == EINTR)
420 return (error);
421 np->n_brev = np->n_lrev;
422 }
423 }
424 } else {
425 if (np->n_flag & NMODIFIED) {
426 if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
427 ap->a_p, 1)) == EINTR)
428 return (error);
429 np->n_attrstamp = 0;
430 if (vp->v_type == VDIR)
431 np->n_direofoffset = 0;
432 error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p);
433 if (error)
434 return (error);
435 np->n_mtime = vattr.va_mtime.tv_sec;
436 } else {
437 error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p);
438 if (error)
439 return (error);
440 if (np->n_mtime != vattr.va_mtime.tv_sec) {
441 if (vp->v_type == VDIR)
442 np->n_direofoffset = 0;
443 if ((error = nfs_vinvalbuf(vp, V_SAVE,
444 ap->a_cred, ap->a_p, 1)) == EINTR)
445 return (error);
446 np->n_mtime = vattr.va_mtime.tv_sec;
447 }
448 }
449 }
450 if ((nmp->nm_flag & NFSMNT_NQNFS) == 0)
451 np->n_attrstamp = 0; /* For Open/Close consistency */
452 return (0);
453}
454
455/*
456 * nfs close vnode op
457 * What an NFS client should do upon close after writing is a debatable issue.
458 * Most NFS clients push delayed writes to the server upon close, basically for
459 * two reasons:
460 * 1 - So that any write errors may be reported back to the client process
461 * doing the close system call. By far the two most likely errors are
462 * NFSERR_NOSPC and NFSERR_DQUOT to indicate space allocation failure.
463 * 2 - To put a worst case upper bound on cache inconsistency between
464 * multiple clients for the file.
465 * There is also a consistency problem for Version 2 of the protocol w.r.t.
466 * not being able to tell if other clients are writing a file concurrently,
467 * since there is no way of knowing if the changed modify time in the reply
468 * is only due to the write for this client.
469 * (NFS Version 3 provides weak cache consistency data in the reply that
470 * should be sufficient to detect and handle this case.)
471 *
472 * The current code does the following:
473 * for NFS Version 2 - play it safe and flush/invalidate all dirty buffers
474 * for NFS Version 3 - flush dirty buffers to the server but don't invalidate
475 * or commit them (this satisfies 1 and 2 except for the
476 * case where the server crashes after this close but
477 * before the commit RPC, which is felt to be "good
478 * enough". Changing the last argument to nfs_flush() to
479 * a 1 would force a commit operation, if it is felt a
480 * commit is necessary now.
481 * for NQNFS - do nothing now, since 2 is dealt with via leases and
482 * 1 should be dealt with via an fsync() system call for
483 * cases where write errors are important.
484 */
485/* ARGSUSED */
486static int
487nfs_close(ap)
488 struct vop_close_args /* {
489 struct vnodeop_desc *a_desc;
490 struct vnode *a_vp;
491 int a_fflag;
492 struct ucred *a_cred;
493 struct proc *a_p;
494 } */ *ap;
495{
496 register struct vnode *vp = ap->a_vp;
497 register struct nfsnode *np = VTONFS(vp);
498 int error = 0;
499
500 if (vp->v_type == VREG) {
501 if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) == 0 &&
502 (np->n_flag & NMODIFIED)) {
503 if (NFS_ISV3(vp)) {
504 error = nfs_flush(vp, ap->a_cred, MNT_WAIT, ap->a_p, 0);
505 np->n_flag &= ~NMODIFIED;
506 } else
507 error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 1);
508 np->n_attrstamp = 0;
509 }
510 if (np->n_flag & NWRITEERR) {
511 np->n_flag &= ~NWRITEERR;
512 error = np->n_error;
513 }
514 }
515 return (error);
516}
517
518/*
519 * nfs getattr call from vfs.
520 */
521static int
522nfs_getattr(ap)
523 struct vop_getattr_args /* {
524 struct vnode *a_vp;
525 struct vattr *a_vap;
526 struct ucred *a_cred;
527 struct proc *a_p;
528 } */ *ap;
529{
530 register struct vnode *vp = ap->a_vp;
531 register struct nfsnode *np = VTONFS(vp);
532 register caddr_t cp;
533 register u_long *tl;
534 register int t1, t2;
535 caddr_t bpos, dpos;
536 int error = 0;
537 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
538 int v3 = NFS_ISV3(vp);
539
540 /*
541 * Update local times for special files.
542 */
543 if (np->n_flag & (NACC | NUPD))
544 np->n_flag |= NCHG;
545 /*
546 * First look in the cache.
547 */
548 if (nfs_getattrcache(vp, ap->a_vap) == 0)
549 return (0);
550 nfsstats.rpccnt[NFSPROC_GETATTR]++;
551 nfsm_reqhead(vp, NFSPROC_GETATTR, NFSX_FH(v3));
552 nfsm_fhtom(vp, v3);
553 nfsm_request(vp, NFSPROC_GETATTR, ap->a_p, ap->a_cred);
554 if (!error) {
555 nfsm_loadattr(vp, ap->a_vap);
556 }
557 nfsm_reqdone;
558 return (error);
559}
560
561/*
562 * nfs setattr call.
563 */
564static int
565nfs_setattr(ap)
566 struct vop_setattr_args /* {
567 struct vnodeop_desc *a_desc;
568 struct vnode *a_vp;
569 struct vattr *a_vap;
570 struct ucred *a_cred;
571 struct proc *a_p;
572 } */ *ap;
573{
574 register struct vnode *vp = ap->a_vp;
575 register struct nfsnode *np = VTONFS(vp);
576 register struct vattr *vap = ap->a_vap;
577 int error = 0;
578 u_quad_t tsize;
579
580#ifndef nolint
581 tsize = (u_quad_t)0;
582#endif
583 /*
584 * Disallow write attempts if the filesystem is mounted read-only.
585 */
586 if ((vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
587 vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
588 vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) &&
589 (vp->v_mount->mnt_flag & MNT_RDONLY))
590 return (EROFS);
591 if (vap->va_size != VNOVAL) {
592 switch (vp->v_type) {
593 case VDIR:
594 return (EISDIR);
595 case VCHR:
596 case VBLK:
597 case VSOCK:
598 case VFIFO:
599 if (vap->va_mtime.tv_sec == VNOVAL &&
600 vap->va_atime.tv_sec == VNOVAL &&
601 vap->va_mode == (u_short)VNOVAL &&
602 vap->va_uid == (uid_t)VNOVAL &&
603 vap->va_gid == (gid_t)VNOVAL)
604 return (0);
605 vap->va_size = VNOVAL;
606 break;
607 default:
608 /*
609 * Disallow write attempts if the filesystem is
610 * mounted read-only.
611 */
612 if (vp->v_mount->mnt_flag & MNT_RDONLY)
613 return (EROFS);
614 if (np->n_flag & NMODIFIED) {
615 if (vap->va_size == 0)
616 error = nfs_vinvalbuf(vp, 0,
617 ap->a_cred, ap->a_p, 1);
618 else
619 error = nfs_vinvalbuf(vp, V_SAVE,
620 ap->a_cred, ap->a_p, 1);
621 if (error)
622 return (error);
623 }
624 tsize = np->n_size;
625 np->n_size = np->n_vattr.va_size = vap->va_size;
626 vnode_pager_setsize(vp, (u_long)np->n_size);
627 };
628 } else if ((vap->va_mtime.tv_sec != VNOVAL ||
629 vap->va_atime.tv_sec != VNOVAL) && (np->n_flag & NMODIFIED) &&
630 vp->v_type == VREG &&
631 (error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
632 ap->a_p, 1)) == EINTR)
633 return (error);
634 error = nfs_setattrrpc(vp, vap, ap->a_cred, ap->a_p);
635 if (error && vap->va_size != VNOVAL) {
636 np->n_size = np->n_vattr.va_size = tsize;
637 vnode_pager_setsize(vp, (u_long)np->n_size);
638 }
639 return (error);
640}
641
642/*
643 * Do an nfs setattr rpc.
644 */
645static int
646nfs_setattrrpc(vp, vap, cred, procp)
647 register struct vnode *vp;
648 register struct vattr *vap;
649 struct ucred *cred;
650 struct proc *procp;
651{
652 register struct nfsv2_sattr *sp;
653 register caddr_t cp;
654 register long t1, t2;
655 caddr_t bpos, dpos, cp2;
656 u_long *tl;
657 int error = 0, wccflag = NFSV3_WCCRATTR;
658 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
659 int v3 = NFS_ISV3(vp);
660
661 nfsstats.rpccnt[NFSPROC_SETATTR]++;
662 nfsm_reqhead(vp, NFSPROC_SETATTR, NFSX_FH(v3) + NFSX_SATTR(v3));
663 nfsm_fhtom(vp, v3);
664 if (v3) {
665 if (vap->va_mode != (u_short)VNOVAL) {
666 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
667 *tl++ = nfs_true;
668 *tl = txdr_unsigned(vap->va_mode);
669 } else {
670 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
671 *tl = nfs_false;
672 }
673 if (vap->va_uid != (uid_t)VNOVAL) {
674 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
675 *tl++ = nfs_true;
676 *tl = txdr_unsigned(vap->va_uid);
677 } else {
678 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
679 *tl = nfs_false;
680 }
681 if (vap->va_gid != (gid_t)VNOVAL) {
682 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
683 *tl++ = nfs_true;
684 *tl = txdr_unsigned(vap->va_gid);
685 } else {
686 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
687 *tl = nfs_false;
688 }
689 if (vap->va_size != VNOVAL) {
690 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED);
691 *tl++ = nfs_true;
692 txdr_hyper(&vap->va_size, tl);
693 } else {
694 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
695 *tl = nfs_false;
696 }
697 if (vap->va_atime.tv_sec != VNOVAL) {
698 if (vap->va_atime.tv_sec != time_second) {
699 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED);
700 *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);
701 txdr_nfsv3time(&vap->va_atime, tl);
702 } else {
703 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
704 *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER);
705 }
706 } else {
707 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
708 *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE);
709 }
710 if (vap->va_mtime.tv_sec != VNOVAL) {
711 if (vap->va_mtime.tv_sec != time_second) {
712 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED);
713 *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);
714 txdr_nfsv3time(&vap->va_mtime, tl);
715 } else {
716 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
717 *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER);
718 }
719 } else {
720 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
721 *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE);
722 }
723 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
724 *tl = nfs_false;
725 } else {
726 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
727 if (vap->va_mode == (u_short)VNOVAL)
728 sp->sa_mode = VNOVAL;
729 else
730 sp->sa_mode = vtonfsv2_mode(vp->v_type, vap->va_mode);
731 if (vap->va_uid == (uid_t)VNOVAL)
732 sp->sa_uid = VNOVAL;
733 else
734 sp->sa_uid = txdr_unsigned(vap->va_uid);
735 if (vap->va_gid == (gid_t)VNOVAL)
736 sp->sa_gid = VNOVAL;
737 else
738 sp->sa_gid = txdr_unsigned(vap->va_gid);
739 sp->sa_size = txdr_unsigned(vap->va_size);
740 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
741 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
742 }
743 nfsm_request(vp, NFSPROC_SETATTR, procp, cred);
744 if (v3) {
745 nfsm_wcc_data(vp, wccflag);
746 } else
747 nfsm_loadattr(vp, (struct vattr *)0);
748 nfsm_reqdone;
749 return (error);
750}
751
752/*
753 * nfs lookup call, one step at a time...
754 * First look in cache
755 * If not found, unlock the directory nfsnode and do the rpc
756 */
757static int
758nfs_lookup(ap)
759 struct vop_lookup_args /* {
760 struct vnodeop_desc *a_desc;
761 struct vnode *a_dvp;
762 struct vnode **a_vpp;
763 struct componentname *a_cnp;
764 } */ *ap;
765{
766 struct componentname *cnp = ap->a_cnp;
767 struct vnode *dvp = ap->a_dvp;
768 struct vnode **vpp = ap->a_vpp;
769 int flags = cnp->cn_flags;
770 struct vnode *newvp;
771 u_long *tl;
772 caddr_t cp;
773 long t1, t2;
774 struct nfsmount *nmp;
775 caddr_t bpos, dpos, cp2;
776 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
777 long len;
778 nfsfh_t *fhp;
779 struct nfsnode *np;
780 int lockparent, wantparent, error = 0, attrflag, fhsize;
781 int v3 = NFS_ISV3(dvp);
782 struct proc *p = cnp->cn_proc;
783
784 *vpp = NULLVP;
785 if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
786 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
787 return (EROFS);
788 if (dvp->v_type != VDIR)
789 return (ENOTDIR);
790 lockparent = flags & LOCKPARENT;
791 wantparent = flags & (LOCKPARENT|WANTPARENT);
792 nmp = VFSTONFS(dvp->v_mount);
793 np = VTONFS(dvp);
794 if ((error = cache_lookup(dvp, vpp, cnp)) && error != ENOENT) {
795 struct vattr vattr;
796 int vpid;
797
798 if (error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, p)) {
799 *vpp = NULLVP;
800 return (error);
801 }
802
803 newvp = *vpp;
804 vpid = newvp->v_id;
805 /*
806 * See the comment starting `Step through' in ufs/ufs_lookup.c
807 * for an explanation of the locking protocol
808 */
809 if (dvp == newvp) {
810 VREF(newvp);
811 error = 0;
812 } else if (flags & ISDOTDOT) {
813 VOP_UNLOCK(dvp, 0, p);
814 error = vget(newvp, LK_EXCLUSIVE, p);
815 if (!error && lockparent && (flags & ISLASTCN))
816 error = vn_lock(dvp, LK_EXCLUSIVE, p);
817 } else {
818 error = vget(newvp, LK_EXCLUSIVE, p);
819 if (!lockparent || error || !(flags & ISLASTCN))
820 VOP_UNLOCK(dvp, 0, p);
821 }
822 if (!error) {
823 if (vpid == newvp->v_id) {
824 if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, p)
825 && vattr.va_ctime.tv_sec == VTONFS(newvp)->n_ctime) {
826 nfsstats.lookupcache_hits++;
827 if (cnp->cn_nameiop != LOOKUP &&
828 (flags & ISLASTCN))
829 cnp->cn_flags |= SAVENAME;
830 return (0);
831 }
832 cache_purge(newvp);
833 }
834 vput(newvp);
835 if (lockparent && dvp != newvp && (flags & ISLASTCN))
836 VOP_UNLOCK(dvp, 0, p);
837 }
838 error = vn_lock(dvp, LK_EXCLUSIVE, p);
839 *vpp = NULLVP;
840 if (error)
841 return (error);
842 }
843 error = 0;
844 newvp = NULLVP;
845 nfsstats.lookupcache_misses++;
846 nfsstats.rpccnt[NFSPROC_LOOKUP]++;
847 len = cnp->cn_namelen;
848 nfsm_reqhead(dvp, NFSPROC_LOOKUP,
849 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len));
850 nfsm_fhtom(dvp, v3);
851 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
852 nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred);
853 if (error) {
854 nfsm_postop_attr(dvp, attrflag);
855 m_freem(mrep);
856 goto nfsmout;
857 }
858 nfsm_getfh(fhp, fhsize, v3);
859
860 /*
861 * Handle RENAME case...
862 */
863 if (cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)) {
864 if (NFS_CMPFH(np, fhp, fhsize)) {
865 m_freem(mrep);
866 return (EISDIR);
867 }
868 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
869 if (error) {
870 m_freem(mrep);
871 return (error);
872 }
873 newvp = NFSTOV(np);
874 if (v3) {
875 nfsm_postop_attr(newvp, attrflag);
876 nfsm_postop_attr(dvp, attrflag);
877 } else
878 nfsm_loadattr(newvp, (struct vattr *)0);
879 *vpp = newvp;
880 m_freem(mrep);
881 cnp->cn_flags |= SAVENAME;
882 if (!lockparent)
883 VOP_UNLOCK(dvp, 0, p);
884 return (0);
885 }
886
887 if (flags & ISDOTDOT) {
888 VOP_UNLOCK(dvp, 0, p);
889 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
890 if (error) {
891 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, p);
892 return (error);
893 }
894 newvp = NFSTOV(np);
895 if (lockparent && (flags & ISLASTCN) &&
896 (error = vn_lock(dvp, LK_EXCLUSIVE, p))) {
897 vput(newvp);
898 return (error);
899 }
900 } else if (NFS_CMPFH(np, fhp, fhsize)) {
901 VREF(dvp);
902 newvp = dvp;
903 } else {
904 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
905 if (error) {
906 m_freem(mrep);
907 return (error);
908 }
909 if (!lockparent || !(flags & ISLASTCN))
910 VOP_UNLOCK(dvp, 0, p);
911 newvp = NFSTOV(np);
912 }
913 if (v3) {
914 nfsm_postop_attr(newvp, attrflag);
915 nfsm_postop_attr(dvp, attrflag);
916 } else
917 nfsm_loadattr(newvp, (struct vattr *)0);
918 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
919 cnp->cn_flags |= SAVENAME;
920 if ((cnp->cn_flags & MAKEENTRY) &&
921 (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) {
922 np->n_ctime = np->n_vattr.va_ctime.tv_sec;
923 cache_enter(dvp, newvp, cnp);
924 }
925 *vpp = newvp;
926 nfsm_reqdone;
927 if (error) {
928 if (newvp != NULLVP) {
929 vrele(newvp);
930 *vpp = NULLVP;
931 }
932 if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) &&
933 (flags & ISLASTCN) && error == ENOENT) {
934 if (!lockparent)
935 VOP_UNLOCK(dvp, 0, p);
936 if (dvp->v_mount->mnt_flag & MNT_RDONLY)
937 error = EROFS;
938 else
939 error = EJUSTRETURN;
940 }
941 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
942 cnp->cn_flags |= SAVENAME;
943 }
944 return (error);
945}
946
947/*
948 * nfs read call.
949 * Just call nfs_bioread() to do the work.
950 */
951static int
952nfs_read(ap)
953 struct vop_read_args /* {
954 struct vnode *a_vp;
955 struct uio *a_uio;
956 int a_ioflag;
957 struct ucred *a_cred;
958 } */ *ap;
959{
960 register struct vnode *vp = ap->a_vp;
961
962 if (vp->v_type != VREG)
963 return (EPERM);
964 return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred, 0));
965}
966
967/*
968 * nfs readlink call
969 */
970static int
971nfs_readlink(ap)
972 struct vop_readlink_args /* {
973 struct vnode *a_vp;
974 struct uio *a_uio;
975 struct ucred *a_cred;
976 } */ *ap;
977{
978 register struct vnode *vp = ap->a_vp;
979
980 if (vp->v_type != VLNK)
981 return (EPERM);
982 return (nfs_bioread(vp, ap->a_uio, 0, ap->a_cred, 0));
983}
984
985/*
986 * Do a readlink rpc.
987 * Called by nfs_doio() from below the buffer cache.
988 */
989int
990nfs_readlinkrpc(vp, uiop, cred)
991 register struct vnode *vp;
992 struct uio *uiop;
993 struct ucred *cred;
994{
995 register u_long *tl;
996 register caddr_t cp;
997 register long t1, t2;
998 caddr_t bpos, dpos, cp2;
999 int error = 0, len, attrflag;
1000 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1001 int v3 = NFS_ISV3(vp);
1002
1003 nfsstats.rpccnt[NFSPROC_READLINK]++;
1004 nfsm_reqhead(vp, NFSPROC_READLINK, NFSX_FH(v3));
1005 nfsm_fhtom(vp, v3);
1006 nfsm_request(vp, NFSPROC_READLINK, uiop->uio_procp, cred);
1007 if (v3)
1008 nfsm_postop_attr(vp, attrflag);
1009 if (!error) {
1010 nfsm_strsiz(len, NFS_MAXPATHLEN);
1011 nfsm_mtouio(uiop, len);
1012 }
1013 nfsm_reqdone;
1014 return (error);
1015}
1016
1017/*
1018 * nfs read rpc call
1019 * Ditto above
1020 */
1021int
1022nfs_readrpc(vp, uiop, cred)
1023 register struct vnode *vp;
1024 struct uio *uiop;
1025 struct ucred *cred;
1026{
1027 register u_long *tl;
1028 register caddr_t cp;
1029 register long t1, t2;
1030 caddr_t bpos, dpos, cp2;
1031 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1032 struct nfsmount *nmp;
1033 int error = 0, len, retlen, tsiz, eof, attrflag;
1034 int v3 = NFS_ISV3(vp);
1035
1036#ifndef nolint
1037 eof = 0;
1038#endif
1039 nmp = VFSTONFS(vp->v_mount);
1040 tsiz = uiop->uio_resid;
1041 if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize)
1042 return (EFBIG);
1043 while (tsiz > 0) {
1044 nfsstats.rpccnt[NFSPROC_READ]++;
1045 len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz;
1046 nfsm_reqhead(vp, NFSPROC_READ, NFSX_FH(v3) + NFSX_UNSIGNED * 3);
1047 nfsm_fhtom(vp, v3);
1048 nfsm_build(tl, u_long *, NFSX_UNSIGNED * 3);
1049 if (v3) {
1050 txdr_hyper(&uiop->uio_offset, tl);
1051 *(tl + 2) = txdr_unsigned(len);
1052 } else {
1053 *tl++ = txdr_unsigned(uiop->uio_offset);
1054 *tl++ = txdr_unsigned(len);
1055 *tl = 0;
1056 }
1057 nfsm_request(vp, NFSPROC_READ, uiop->uio_procp, cred);
1058 if (v3) {
1059 nfsm_postop_attr(vp, attrflag);
1060 if (error) {
1061 m_freem(mrep);
1062 goto nfsmout;
1063 }
1064 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
1065 eof = fxdr_unsigned(int, *(tl + 1));
1066 } else
1067 nfsm_loadattr(vp, (struct vattr *)0);
1068 nfsm_strsiz(retlen, nmp->nm_rsize);
1069 nfsm_mtouio(uiop, retlen);
1070 m_freem(mrep);
1071 tsiz -= retlen;
1072 if (v3) {
1073 if (eof || retlen == 0)
1074 tsiz = 0;
1075 } else if (retlen < len)
1076 tsiz = 0;
1077 }
1078nfsmout:
1079 return (error);
1080}
1081
1082/*
1083 * nfs write call
1084 */
1085int
1086nfs_writerpc(vp, uiop, cred, iomode, must_commit)
1087 register struct vnode *vp;
1088 register struct uio *uiop;
1089 struct ucred *cred;
1090 int *iomode, *must_commit;
1091{
1092 register u_long *tl;
1093 register caddr_t cp;
1094 register int t1, t2, backup;
1095 caddr_t bpos, dpos, cp2;
1096 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1097 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
1098 int error = 0, len, tsiz, wccflag = NFSV3_WCCRATTR, rlen, commit;
1099 int v3 = NFS_ISV3(vp), committed = NFSV3WRITE_FILESYNC;
1100
1101#ifndef DIAGNOSTIC
1102 if (uiop->uio_iovcnt != 1)
1103 panic("nfs: writerpc iovcnt > 1");
1104#endif
1105 *must_commit = 0;
1106 tsiz = uiop->uio_resid;
1107 if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize)
1108 return (EFBIG);
1109 while (tsiz > 0) {
1110 nfsstats.rpccnt[NFSPROC_WRITE]++;
1111 len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz;
1112 nfsm_reqhead(vp, NFSPROC_WRITE,
1113 NFSX_FH(v3) + 5 * NFSX_UNSIGNED + nfsm_rndup(len));
1114 nfsm_fhtom(vp, v3);
1115 if (v3) {
1116 nfsm_build(tl, u_long *, 5 * NFSX_UNSIGNED);
1117 txdr_hyper(&uiop->uio_offset, tl);
1118 tl += 2;
1119 *tl++ = txdr_unsigned(len);
1120 *tl++ = txdr_unsigned(*iomode);
1121 } else {
1122 nfsm_build(tl, u_long *, 4 * NFSX_UNSIGNED);
1123 *++tl = txdr_unsigned(uiop->uio_offset);
1124 tl += 2;
1125 }
1126 *tl = txdr_unsigned(len);
1127 nfsm_uiotom(uiop, len);
1128 nfsm_request(vp, NFSPROC_WRITE, uiop->uio_procp, cred);
1129 if (v3) {
1130 wccflag = NFSV3_WCCCHK;
1131 nfsm_wcc_data(vp, wccflag);
1132 if (!error) {
1133 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED +
1134 NFSX_V3WRITEVERF);
1135 rlen = fxdr_unsigned(int, *tl++);
1136 if (rlen == 0) {
1137 error = NFSERR_IO;
1138 break;
1139 } else if (rlen < len) {
1140 backup = len - rlen;
1141 uiop->uio_iov->iov_base -= backup;
1142 uiop->uio_iov->iov_len += backup;
1143 uiop->uio_offset -= backup;
1144 uiop->uio_resid += backup;
1145 len = rlen;
1146 }
1147 commit = fxdr_unsigned(int, *tl++);
1148
1149 /*
1150 * Return the lowest committment level
1151 * obtained by any of the RPCs.
1152 */
1153 if (committed == NFSV3WRITE_FILESYNC)
1154 committed = commit;
1155 else if (committed == NFSV3WRITE_DATASYNC &&
1156 commit == NFSV3WRITE_UNSTABLE)
1157 committed = commit;
1158 if ((nmp->nm_state & NFSSTA_HASWRITEVERF) == 0){
1159 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf,
1160 NFSX_V3WRITEVERF);
1161 nmp->nm_state |= NFSSTA_HASWRITEVERF;
1162 } else if (bcmp((caddr_t)tl,
1163 (caddr_t)nmp->nm_verf, NFSX_V3WRITEVERF)) {
1164 *must_commit = 1;
1165 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf,
1166 NFSX_V3WRITEVERF);
1167 }
1168 }
1169 } else
1170 nfsm_loadattr(vp, (struct vattr *)0);
1171 if (wccflag)
1172 VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime.tv_sec;
1173 m_freem(mrep);
1174 tsiz -= len;
1175 }
1176nfsmout:
1177 if (vp->v_mount->mnt_flag & MNT_ASYNC)
1178 committed = NFSV3WRITE_FILESYNC;
1179 *iomode = committed;
1180 if (error)
1181 uiop->uio_resid = tsiz;
1182 return (error);
1183}
1184
1185/*
1186 * nfs mknod rpc
1187 * For NFS v2 this is a kludge. Use a create rpc but with the IFMT bits of the
1188 * mode set to specify the file type and the size field for rdev.
1189 */
1190static int
1191nfs_mknodrpc(dvp, vpp, cnp, vap)
1192 register struct vnode *dvp;
1193 register struct vnode **vpp;
1194 register struct componentname *cnp;
1195 register struct vattr *vap;
1196{
1197 register struct nfsv2_sattr *sp;
1198 register struct nfsv3_sattr *sp3;
1199 register u_long *tl;
1200 register caddr_t cp;
1201 register long t1, t2;
1202 struct vnode *newvp = (struct vnode *)0;
1203 struct nfsnode *np = (struct nfsnode *)0;
1204 struct vattr vattr;
1205 char *cp2;
1206 caddr_t bpos, dpos;
1207 int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0;
1208 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1209 u_long rdev;
1210 int v3 = NFS_ISV3(dvp);
1211
1212 if (vap->va_type == VCHR || vap->va_type == VBLK)
1213 rdev = txdr_unsigned(vap->va_rdev);
1214 else if (vap->va_type == VFIFO || vap->va_type == VSOCK)
1215 rdev = 0xffffffff;
1216 else {
1217 VOP_ABORTOP(dvp, cnp);
1218 return (EOPNOTSUPP);
1219 }
1220 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) {
1221 VOP_ABORTOP(dvp, cnp);
1222 return (error);
1223 }
1224 nfsstats.rpccnt[NFSPROC_MKNOD]++;
1225 nfsm_reqhead(dvp, NFSPROC_MKNOD, NFSX_FH(v3) + 4 * NFSX_UNSIGNED +
1226 + nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3));
1227 nfsm_fhtom(dvp, v3);
1228 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1229 if (v3) {
1230 nfsm_build(tl, u_long *, NFSX_UNSIGNED + NFSX_V3SRVSATTR);
1231 *tl++ = vtonfsv3_type(vap->va_type);
1232 sp3 = (struct nfsv3_sattr *)tl;
1233 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, vattr.va_gid);
1234 if (vap->va_type == VCHR || vap->va_type == VBLK) {
1235 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
1236 *tl++ = txdr_unsigned(major(vap->va_rdev));
1237 *tl = txdr_unsigned(minor(vap->va_rdev));
1238 }
1239 } else {
1240 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1241 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
1242 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid);
1243 sp->sa_gid = txdr_unsigned(vattr.va_gid);
1244 sp->sa_size = rdev;
1245 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
1246 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
1247 }
1248 nfsm_request(dvp, NFSPROC_MKNOD, cnp->cn_proc, cnp->cn_cred);
1249 if (!error) {
1250 nfsm_mtofh(dvp, newvp, v3, gotvp);
1251 if (!gotvp) {
1252 if (newvp) {
1253 vput(newvp);
1254 newvp = (struct vnode *)0;
1255 }
1256 error = nfs_lookitup(dvp, cnp->cn_nameptr,
1257 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc, &np);
1258 if (!error)
1259 newvp = NFSTOV(np);
1260 }
1261 }
1262 if (v3)
1263 nfsm_wcc_data(dvp, wccflag);
1264 nfsm_reqdone;
1265 if (error) {
1266 if (newvp)
1267 vput(newvp);
1268 } else {
1269 if (cnp->cn_flags & MAKEENTRY)
1270 cache_enter(dvp, newvp, cnp);
1271 *vpp = newvp;
1272 }
1273 zfree(namei_zone, cnp->cn_pnbuf);
1274 VTONFS(dvp)->n_flag |= NMODIFIED;
1275 if (!wccflag)
1276 VTONFS(dvp)->n_attrstamp = 0;
1277 return (error);
1278}
1279
1280/*
1281 * nfs mknod vop
1282 * just call nfs_mknodrpc() to do the work.
1283 */
1284/* ARGSUSED */
1285static int
1286nfs_mknod(ap)
1287 struct vop_mknod_args /* {
1288 struct vnode *a_dvp;
1289 struct vnode **a_vpp;
1290 struct componentname *a_cnp;
1291 struct vattr *a_vap;
1292 } */ *ap;
1293{
1294 struct vnode *newvp;
1295 int error;
1296
1297 error = nfs_mknodrpc(ap->a_dvp, &newvp, ap->a_cnp, ap->a_vap);
1298 if (!error)
1299 vput(newvp);
1300 return (error);
1301}
1302
1303static u_long create_verf;
1304/*
1305 * nfs file create call
1306 */
1307static int
1308nfs_create(ap)
1309 struct vop_create_args /* {
1310 struct vnode *a_dvp;
1311 struct vnode **a_vpp;
1312 struct componentname *a_cnp;
1313 struct vattr *a_vap;
1314 } */ *ap;
1315{
1316 register struct vnode *dvp = ap->a_dvp;
1317 register struct vattr *vap = ap->a_vap;
1318 register struct componentname *cnp = ap->a_cnp;
1319 register struct nfsv2_sattr *sp;
1320 register struct nfsv3_sattr *sp3;
1321 register u_long *tl;
1322 register caddr_t cp;
1323 register long t1, t2;
1324 struct nfsnode *np = (struct nfsnode *)0;
1325 struct vnode *newvp = (struct vnode *)0;
1326 caddr_t bpos, dpos, cp2;
1327 int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0, fmode = 0;
1328 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1329 struct vattr vattr;
1330 int v3 = NFS_ISV3(dvp);
1331
1332 /*
1333 * Oops, not for me..
1334 */
1335 if (vap->va_type == VSOCK)
1336 return (nfs_mknodrpc(dvp, ap->a_vpp, cnp, vap));
1337
1338 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) {
1339 VOP_ABORTOP(dvp, cnp);
1340 return (error);
1341 }
1342 if (vap->va_vaflags & VA_EXCLUSIVE)
1343 fmode |= O_EXCL;
1344again:
1345 nfsstats.rpccnt[NFSPROC_CREATE]++;
1346 nfsm_reqhead(dvp, NFSPROC_CREATE, NFSX_FH(v3) + 2 * NFSX_UNSIGNED +
1347 nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3));
1348 nfsm_fhtom(dvp, v3);
1349 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1350 if (v3) {
1351 nfsm_build(tl, u_long *, NFSX_UNSIGNED);
1352 if (fmode & O_EXCL) {
1353 *tl = txdr_unsigned(NFSV3CREATE_EXCLUSIVE);
1354 nfsm_build(tl, u_long *, NFSX_V3CREATEVERF);
1355#ifdef INET
1356 if (!TAILQ_EMPTY(&in_ifaddrhead))
1357 *tl++ = IA_SIN(in_ifaddrhead.tqh_first)->sin_addr.s_addr;
1358 else
1359#endif
1360 *tl++ = create_verf;
1361 *tl = ++create_verf;
1362 } else {
1363 *tl = txdr_unsigned(NFSV3CREATE_UNCHECKED);
1364 nfsm_build(tl, u_long *, NFSX_V3SRVSATTR);
1365 sp3 = (struct nfsv3_sattr *)tl;
1366 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, vattr.va_gid);
1367 }
1368 } else {
1369 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1370 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
1371 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid);
1372 sp->sa_gid = txdr_unsigned(vattr.va_gid);
1373 sp->sa_size = 0;
1374 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
1375 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
1376 }
1377 nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred);
1378 if (!error) {
1379 nfsm_mtofh(dvp, newvp, v3, gotvp);
1380 if (!gotvp) {
1381 if (newvp) {
1382 vput(newvp);
1383 newvp = (struct vnode *)0;
1384 }
1385 error = nfs_lookitup(dvp, cnp->cn_nameptr,
1386 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc, &np);
1387 if (!error)
1388 newvp = NFSTOV(np);
1389 }
1390 }
1391 if (v3)
1392 nfsm_wcc_data(dvp, wccflag);
1393 nfsm_reqdone;
1394 if (error) {
1395 if (v3 && (fmode & O_EXCL) && error == NFSERR_NOTSUPP) {
1396 fmode &= ~O_EXCL;
1397 goto again;
1398 }
1399 if (newvp)
1400 vput(newvp);
1401 } else if (v3 && (fmode & O_EXCL))
1402 error = nfs_setattrrpc(newvp, vap, cnp->cn_cred, cnp->cn_proc);
1403 if (!error) {
1404 if (cnp->cn_flags & MAKEENTRY)
1405 cache_enter(dvp, newvp, cnp);
1406 *ap->a_vpp = newvp;
1407 }
1408 zfree(namei_zone, cnp->cn_pnbuf);
1409 VTONFS(dvp)->n_flag |= NMODIFIED;
1410 if (!wccflag)
1411 VTONFS(dvp)->n_attrstamp = 0;
1412 return (error);
1413}
1414
1415/*
1416 * nfs file remove call
1417 * To try and make nfs semantics closer to ufs semantics, a file that has
1418 * other processes using the vnode is renamed instead of removed and then
1419 * removed later on the last close.
1420 * - If v_usecount > 1
1421 * If a rename is not already in the works
1422 * call nfs_sillyrename() to set it up
1423 * else
1424 * do the remove rpc
1425 */
1426static int
1427nfs_remove(ap)
1428 struct vop_remove_args /* {
1429 struct vnodeop_desc *a_desc;
1430 struct vnode * a_dvp;
1431 struct vnode * a_vp;
1432 struct componentname * a_cnp;
1433 } */ *ap;
1434{
1435 register struct vnode *vp = ap->a_vp;
1436 register struct vnode *dvp = ap->a_dvp;
1437 register struct componentname *cnp = ap->a_cnp;
1438 register struct nfsnode *np = VTONFS(vp);
1439 int error = 0;
1440 struct vattr vattr;
1441
1442#ifndef DIAGNOSTIC
1443 if ((cnp->cn_flags & HASBUF) == 0)
1444 panic("nfs_remove: no name");
1445 if (vp->v_usecount < 1)
1446 panic("nfs_remove: bad v_usecount");
1447#endif
1448 if (vp->v_usecount == 1 || (np->n_sillyrename &&
1449 VOP_GETATTR(vp, &vattr, cnp->cn_cred, cnp->cn_proc) == 0 &&
1450 vattr.va_nlink > 1)) {
1451 /*
1452 * Purge the name cache so that the chance of a lookup for
1453 * the name succeeding while the remove is in progress is
1454 * minimized. Without node locking it can still happen, such
1455 * that an I/O op returns ESTALE, but since you get this if
1456 * another host removes the file..
1457 */
1458 cache_purge(vp);
1459 /*
1460 * throw away biocache buffers, mainly to avoid
1461 * unnecessary delayed writes later.
1462 */
1463 error = nfs_vinvalbuf(vp, 0, cnp->cn_cred, cnp->cn_proc, 1);
1464 /* Do the rpc */
1465 if (error != EINTR)
1466 error = nfs_removerpc(dvp, cnp->cn_nameptr,
1467 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc);
1468 /*
1469 * Kludge City: If the first reply to the remove rpc is lost..
1470 * the reply to the retransmitted request will be ENOENT
1471 * since the file was in fact removed
1472 * Therefore, we cheat and return success.
1473 */
1474 if (error == ENOENT)
1475 error = 0;
1476 } else if (!np->n_sillyrename)
1477 error = nfs_sillyrename(dvp, vp, cnp);
1478 zfree(namei_zone, cnp->cn_pnbuf);
1479 np->n_attrstamp = 0;
1480 return (error);
1481}
1482
1483/*
1484 * nfs file remove rpc called from nfs_inactive
1485 */
1486int
1487nfs_removeit(sp)
1488 register struct sillyrename *sp;
1489{
1490
1491 return (nfs_removerpc(sp->s_dvp, sp->s_name, sp->s_namlen, sp->s_cred,
1492 (struct proc *)0));
1493}
1494
1495/*
1496 * Nfs remove rpc, called from nfs_remove() and nfs_removeit().
1497 */
1498static int
1499nfs_removerpc(dvp, name, namelen, cred, proc)
1500 register struct vnode *dvp;
1499 char *name;
1501 const char *name;
1500 int namelen;
1501 struct ucred *cred;
1502 struct proc *proc;
1503{
1504 register u_long *tl;
1505 register caddr_t cp;
1506 register long t1, t2;
1507 caddr_t bpos, dpos, cp2;
1508 int error = 0, wccflag = NFSV3_WCCRATTR;
1509 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1510 int v3 = NFS_ISV3(dvp);
1511
1512 nfsstats.rpccnt[NFSPROC_REMOVE]++;
1513 nfsm_reqhead(dvp, NFSPROC_REMOVE,
1514 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(namelen));
1515 nfsm_fhtom(dvp, v3);
1516 nfsm_strtom(name, namelen, NFS_MAXNAMLEN);
1517 nfsm_request(dvp, NFSPROC_REMOVE, proc, cred);
1518 if (v3)
1519 nfsm_wcc_data(dvp, wccflag);
1520 nfsm_reqdone;
1521 VTONFS(dvp)->n_flag |= NMODIFIED;
1522 if (!wccflag)
1523 VTONFS(dvp)->n_attrstamp = 0;
1524 return (error);
1525}
1526
1527/*
1528 * nfs file rename call
1529 */
1530static int
1531nfs_rename(ap)
1532 struct vop_rename_args /* {
1533 struct vnode *a_fdvp;
1534 struct vnode *a_fvp;
1535 struct componentname *a_fcnp;
1536 struct vnode *a_tdvp;
1537 struct vnode *a_tvp;
1538 struct componentname *a_tcnp;
1539 } */ *ap;
1540{
1541 register struct vnode *fvp = ap->a_fvp;
1542 register struct vnode *tvp = ap->a_tvp;
1543 register struct vnode *fdvp = ap->a_fdvp;
1544 register struct vnode *tdvp = ap->a_tdvp;
1545 register struct componentname *tcnp = ap->a_tcnp;
1546 register struct componentname *fcnp = ap->a_fcnp;
1547 int error;
1548
1549#ifndef DIAGNOSTIC
1550 if ((tcnp->cn_flags & HASBUF) == 0 ||
1551 (fcnp->cn_flags & HASBUF) == 0)
1552 panic("nfs_rename: no name");
1553#endif
1554 /* Check for cross-device rename */
1555 if ((fvp->v_mount != tdvp->v_mount) ||
1556 (tvp && (fvp->v_mount != tvp->v_mount))) {
1557 error = EXDEV;
1558 goto out;
1559 }
1560
1561 /*
1562 * If the tvp exists and is in use, sillyrename it before doing the
1563 * rename of the new file over it.
1564 * XXX Can't sillyrename a directory.
1565 */
1566 if (tvp && tvp->v_usecount > 1 && !VTONFS(tvp)->n_sillyrename &&
1567 tvp->v_type != VDIR && !nfs_sillyrename(tdvp, tvp, tcnp)) {
1568 vput(tvp);
1569 tvp = NULL;
1570 }
1571
1572 error = nfs_renamerpc(fdvp, fcnp->cn_nameptr, fcnp->cn_namelen,
1573 tdvp, tcnp->cn_nameptr, tcnp->cn_namelen, tcnp->cn_cred,
1574 tcnp->cn_proc);
1575
1576 if (fvp->v_type == VDIR) {
1577 if (tvp != NULL && tvp->v_type == VDIR)
1578 cache_purge(tdvp);
1579 cache_purge(fdvp);
1580 }
1581out:
1582 if (tdvp == tvp)
1583 vrele(tdvp);
1584 else
1585 vput(tdvp);
1586 if (tvp)
1587 vput(tvp);
1588 vrele(fdvp);
1589 vrele(fvp);
1590 /*
1591 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry.
1592 */
1593 if (error == ENOENT)
1594 error = 0;
1595 return (error);
1596}
1597
1598/*
1599 * nfs file rename rpc called from nfs_remove() above
1600 */
1601static int
1602nfs_renameit(sdvp, scnp, sp)
1603 struct vnode *sdvp;
1604 struct componentname *scnp;
1605 register struct sillyrename *sp;
1606{
1607 return (nfs_renamerpc(sdvp, scnp->cn_nameptr, scnp->cn_namelen,
1608 sdvp, sp->s_name, sp->s_namlen, scnp->cn_cred, scnp->cn_proc));
1609}
1610
1611/*
1612 * Do an nfs rename rpc. Called from nfs_rename() and nfs_renameit().
1613 */
1614static int
1615nfs_renamerpc(fdvp, fnameptr, fnamelen, tdvp, tnameptr, tnamelen, cred, proc)
1616 register struct vnode *fdvp;
1502 int namelen;
1503 struct ucred *cred;
1504 struct proc *proc;
1505{
1506 register u_long *tl;
1507 register caddr_t cp;
1508 register long t1, t2;
1509 caddr_t bpos, dpos, cp2;
1510 int error = 0, wccflag = NFSV3_WCCRATTR;
1511 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1512 int v3 = NFS_ISV3(dvp);
1513
1514 nfsstats.rpccnt[NFSPROC_REMOVE]++;
1515 nfsm_reqhead(dvp, NFSPROC_REMOVE,
1516 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(namelen));
1517 nfsm_fhtom(dvp, v3);
1518 nfsm_strtom(name, namelen, NFS_MAXNAMLEN);
1519 nfsm_request(dvp, NFSPROC_REMOVE, proc, cred);
1520 if (v3)
1521 nfsm_wcc_data(dvp, wccflag);
1522 nfsm_reqdone;
1523 VTONFS(dvp)->n_flag |= NMODIFIED;
1524 if (!wccflag)
1525 VTONFS(dvp)->n_attrstamp = 0;
1526 return (error);
1527}
1528
1529/*
1530 * nfs file rename call
1531 */
1532static int
1533nfs_rename(ap)
1534 struct vop_rename_args /* {
1535 struct vnode *a_fdvp;
1536 struct vnode *a_fvp;
1537 struct componentname *a_fcnp;
1538 struct vnode *a_tdvp;
1539 struct vnode *a_tvp;
1540 struct componentname *a_tcnp;
1541 } */ *ap;
1542{
1543 register struct vnode *fvp = ap->a_fvp;
1544 register struct vnode *tvp = ap->a_tvp;
1545 register struct vnode *fdvp = ap->a_fdvp;
1546 register struct vnode *tdvp = ap->a_tdvp;
1547 register struct componentname *tcnp = ap->a_tcnp;
1548 register struct componentname *fcnp = ap->a_fcnp;
1549 int error;
1550
1551#ifndef DIAGNOSTIC
1552 if ((tcnp->cn_flags & HASBUF) == 0 ||
1553 (fcnp->cn_flags & HASBUF) == 0)
1554 panic("nfs_rename: no name");
1555#endif
1556 /* Check for cross-device rename */
1557 if ((fvp->v_mount != tdvp->v_mount) ||
1558 (tvp && (fvp->v_mount != tvp->v_mount))) {
1559 error = EXDEV;
1560 goto out;
1561 }
1562
1563 /*
1564 * If the tvp exists and is in use, sillyrename it before doing the
1565 * rename of the new file over it.
1566 * XXX Can't sillyrename a directory.
1567 */
1568 if (tvp && tvp->v_usecount > 1 && !VTONFS(tvp)->n_sillyrename &&
1569 tvp->v_type != VDIR && !nfs_sillyrename(tdvp, tvp, tcnp)) {
1570 vput(tvp);
1571 tvp = NULL;
1572 }
1573
1574 error = nfs_renamerpc(fdvp, fcnp->cn_nameptr, fcnp->cn_namelen,
1575 tdvp, tcnp->cn_nameptr, tcnp->cn_namelen, tcnp->cn_cred,
1576 tcnp->cn_proc);
1577
1578 if (fvp->v_type == VDIR) {
1579 if (tvp != NULL && tvp->v_type == VDIR)
1580 cache_purge(tdvp);
1581 cache_purge(fdvp);
1582 }
1583out:
1584 if (tdvp == tvp)
1585 vrele(tdvp);
1586 else
1587 vput(tdvp);
1588 if (tvp)
1589 vput(tvp);
1590 vrele(fdvp);
1591 vrele(fvp);
1592 /*
1593 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry.
1594 */
1595 if (error == ENOENT)
1596 error = 0;
1597 return (error);
1598}
1599
1600/*
1601 * nfs file rename rpc called from nfs_remove() above
1602 */
1603static int
1604nfs_renameit(sdvp, scnp, sp)
1605 struct vnode *sdvp;
1606 struct componentname *scnp;
1607 register struct sillyrename *sp;
1608{
1609 return (nfs_renamerpc(sdvp, scnp->cn_nameptr, scnp->cn_namelen,
1610 sdvp, sp->s_name, sp->s_namlen, scnp->cn_cred, scnp->cn_proc));
1611}
1612
1613/*
1614 * Do an nfs rename rpc. Called from nfs_rename() and nfs_renameit().
1615 */
1616static int
1617nfs_renamerpc(fdvp, fnameptr, fnamelen, tdvp, tnameptr, tnamelen, cred, proc)
1618 register struct vnode *fdvp;
1617 char *fnameptr;
1619 const char *fnameptr;
1618 int fnamelen;
1619 register struct vnode *tdvp;
1620 int fnamelen;
1621 register struct vnode *tdvp;
1620 char *tnameptr;
1622 const char *tnameptr;
1621 int tnamelen;
1622 struct ucred *cred;
1623 struct proc *proc;
1624{
1625 register u_long *tl;
1626 register caddr_t cp;
1627 register long t1, t2;
1628 caddr_t bpos, dpos, cp2;
1629 int error = 0, fwccflag = NFSV3_WCCRATTR, twccflag = NFSV3_WCCRATTR;
1630 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1631 int v3 = NFS_ISV3(fdvp);
1632
1633 nfsstats.rpccnt[NFSPROC_RENAME]++;
1634 nfsm_reqhead(fdvp, NFSPROC_RENAME,
1635 (NFSX_FH(v3) + NFSX_UNSIGNED)*2 + nfsm_rndup(fnamelen) +
1636 nfsm_rndup(tnamelen));
1637 nfsm_fhtom(fdvp, v3);
1638 nfsm_strtom(fnameptr, fnamelen, NFS_MAXNAMLEN);
1639 nfsm_fhtom(tdvp, v3);
1640 nfsm_strtom(tnameptr, tnamelen, NFS_MAXNAMLEN);
1641 nfsm_request(fdvp, NFSPROC_RENAME, proc, cred);
1642 if (v3) {
1643 nfsm_wcc_data(fdvp, fwccflag);
1644 nfsm_wcc_data(tdvp, twccflag);
1645 }
1646 nfsm_reqdone;
1647 VTONFS(fdvp)->n_flag |= NMODIFIED;
1648 VTONFS(tdvp)->n_flag |= NMODIFIED;
1649 if (!fwccflag)
1650 VTONFS(fdvp)->n_attrstamp = 0;
1651 if (!twccflag)
1652 VTONFS(tdvp)->n_attrstamp = 0;
1653 return (error);
1654}
1655
1656/*
1657 * nfs hard link create call
1658 */
1659static int
1660nfs_link(ap)
1661 struct vop_link_args /* {
1662 struct vnode *a_tdvp;
1663 struct vnode *a_vp;
1664 struct componentname *a_cnp;
1665 } */ *ap;
1666{
1667 register struct vnode *vp = ap->a_vp;
1668 register struct vnode *tdvp = ap->a_tdvp;
1669 register struct componentname *cnp = ap->a_cnp;
1670 register u_long *tl;
1671 register caddr_t cp;
1672 register long t1, t2;
1673 caddr_t bpos, dpos, cp2;
1674 int error = 0, wccflag = NFSV3_WCCRATTR, attrflag = 0;
1675 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1676 int v3 = NFS_ISV3(vp);
1677
1678 if (vp->v_mount != tdvp->v_mount) {
1679 VOP_ABORTOP(tdvp, cnp);
1680 return (EXDEV);
1681 }
1682
1683 /*
1684 * Push all writes to the server, so that the attribute cache
1685 * doesn't get "out of sync" with the server.
1686 * XXX There should be a better way!
1687 */
1688 VOP_FSYNC(vp, cnp->cn_cred, MNT_WAIT, cnp->cn_proc);
1689
1690 nfsstats.rpccnt[NFSPROC_LINK]++;
1691 nfsm_reqhead(vp, NFSPROC_LINK,
1692 NFSX_FH(v3)*2 + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen));
1693 nfsm_fhtom(vp, v3);
1694 nfsm_fhtom(tdvp, v3);
1695 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1696 nfsm_request(vp, NFSPROC_LINK, cnp->cn_proc, cnp->cn_cred);
1697 if (v3) {
1698 nfsm_postop_attr(vp, attrflag);
1699 nfsm_wcc_data(tdvp, wccflag);
1700 }
1701 nfsm_reqdone;
1702 zfree(namei_zone, cnp->cn_pnbuf);
1703 VTONFS(tdvp)->n_flag |= NMODIFIED;
1704 if (!attrflag)
1705 VTONFS(vp)->n_attrstamp = 0;
1706 if (!wccflag)
1707 VTONFS(tdvp)->n_attrstamp = 0;
1708 /*
1709 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
1710 */
1711 if (error == EEXIST)
1712 error = 0;
1713 return (error);
1714}
1715
1716/*
1717 * nfs symbolic link create call
1718 */
1719static int
1720nfs_symlink(ap)
1721 struct vop_symlink_args /* {
1722 struct vnode *a_dvp;
1723 struct vnode **a_vpp;
1724 struct componentname *a_cnp;
1725 struct vattr *a_vap;
1726 char *a_target;
1727 } */ *ap;
1728{
1729 register struct vnode *dvp = ap->a_dvp;
1730 register struct vattr *vap = ap->a_vap;
1731 register struct componentname *cnp = ap->a_cnp;
1732 register struct nfsv2_sattr *sp;
1733 register struct nfsv3_sattr *sp3;
1734 register u_long *tl;
1735 register caddr_t cp;
1736 register long t1, t2;
1737 caddr_t bpos, dpos, cp2;
1738 int slen, error = 0, wccflag = NFSV3_WCCRATTR, gotvp;
1739 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1740 struct vnode *newvp = (struct vnode *)0;
1741 int v3 = NFS_ISV3(dvp);
1742
1743 nfsstats.rpccnt[NFSPROC_SYMLINK]++;
1744 slen = strlen(ap->a_target);
1745 nfsm_reqhead(dvp, NFSPROC_SYMLINK, NFSX_FH(v3) + 2*NFSX_UNSIGNED +
1746 nfsm_rndup(cnp->cn_namelen) + nfsm_rndup(slen) + NFSX_SATTR(v3));
1747 nfsm_fhtom(dvp, v3);
1748 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1749 if (v3) {
1750 nfsm_build(sp3, struct nfsv3_sattr *, NFSX_V3SRVSATTR);
1751 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid,
1752 cnp->cn_cred->cr_gid);
1753 }
1754 nfsm_strtom(ap->a_target, slen, NFS_MAXPATHLEN);
1755 if (!v3) {
1756 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1757 sp->sa_mode = vtonfsv2_mode(VLNK, vap->va_mode);
1758 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid);
1759 sp->sa_gid = txdr_unsigned(cnp->cn_cred->cr_gid);
1760 sp->sa_size = -1;
1761 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
1762 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
1763 }
1764 nfsm_request(dvp, NFSPROC_SYMLINK, cnp->cn_proc, cnp->cn_cred);
1765 if (v3) {
1766 if (!error)
1767 nfsm_mtofh(dvp, newvp, v3, gotvp);
1768 nfsm_wcc_data(dvp, wccflag);
1769 }
1770 nfsm_reqdone;
1771 if (newvp)
1772 vput(newvp);
1773 zfree(namei_zone, cnp->cn_pnbuf);
1774 VTONFS(dvp)->n_flag |= NMODIFIED;
1775 if (!wccflag)
1776 VTONFS(dvp)->n_attrstamp = 0;
1777 /*
1778 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
1779 */
1780 if (error == EEXIST)
1781 error = 0;
1782 return (error);
1783}
1784
1785/*
1786 * nfs make dir call
1787 */
1788static int
1789nfs_mkdir(ap)
1790 struct vop_mkdir_args /* {
1791 struct vnode *a_dvp;
1792 struct vnode **a_vpp;
1793 struct componentname *a_cnp;
1794 struct vattr *a_vap;
1795 } */ *ap;
1796{
1797 register struct vnode *dvp = ap->a_dvp;
1798 register struct vattr *vap = ap->a_vap;
1799 register struct componentname *cnp = ap->a_cnp;
1800 register struct nfsv2_sattr *sp;
1801 register struct nfsv3_sattr *sp3;
1802 register u_long *tl;
1803 register caddr_t cp;
1804 register long t1, t2;
1805 register int len;
1806 struct nfsnode *np = (struct nfsnode *)0;
1807 struct vnode *newvp = (struct vnode *)0;
1808 caddr_t bpos, dpos, cp2;
1809 int error = 0, wccflag = NFSV3_WCCRATTR;
1810 int gotvp = 0;
1811 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1812 struct vattr vattr;
1813 int v3 = NFS_ISV3(dvp);
1814
1815 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) {
1816 VOP_ABORTOP(dvp, cnp);
1817 return (error);
1818 }
1819 len = cnp->cn_namelen;
1820 nfsstats.rpccnt[NFSPROC_MKDIR]++;
1821 nfsm_reqhead(dvp, NFSPROC_MKDIR,
1822 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len) + NFSX_SATTR(v3));
1823 nfsm_fhtom(dvp, v3);
1824 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
1825 if (v3) {
1826 nfsm_build(sp3, struct nfsv3_sattr *, NFSX_V3SRVSATTR);
1827 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, vattr.va_gid);
1828 } else {
1829 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1830 sp->sa_mode = vtonfsv2_mode(VDIR, vap->va_mode);
1831 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid);
1832 sp->sa_gid = txdr_unsigned(vattr.va_gid);
1833 sp->sa_size = -1;
1834 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
1835 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
1836 }
1837 nfsm_request(dvp, NFSPROC_MKDIR, cnp->cn_proc, cnp->cn_cred);
1838 if (!error)
1839 nfsm_mtofh(dvp, newvp, v3, gotvp);
1840 if (v3)
1841 nfsm_wcc_data(dvp, wccflag);
1842 nfsm_reqdone;
1843 VTONFS(dvp)->n_flag |= NMODIFIED;
1844 if (!wccflag)
1845 VTONFS(dvp)->n_attrstamp = 0;
1846 /*
1847 * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry
1848 * if we can succeed in looking up the directory.
1849 */
1850 if (error == EEXIST || (!error && !gotvp)) {
1851 if (newvp) {
1852 vrele(newvp);
1853 newvp = (struct vnode *)0;
1854 }
1855 error = nfs_lookitup(dvp, cnp->cn_nameptr, len, cnp->cn_cred,
1856 cnp->cn_proc, &np);
1857 if (!error) {
1858 newvp = NFSTOV(np);
1859 if (newvp->v_type != VDIR)
1860 error = EEXIST;
1861 }
1862 }
1863 if (error) {
1864 if (newvp)
1865 vrele(newvp);
1866 } else
1867 *ap->a_vpp = newvp;
1868 zfree(namei_zone, cnp->cn_pnbuf);
1869 return (error);
1870}
1871
1872/*
1873 * nfs remove directory call
1874 */
1875static int
1876nfs_rmdir(ap)
1877 struct vop_rmdir_args /* {
1878 struct vnode *a_dvp;
1879 struct vnode *a_vp;
1880 struct componentname *a_cnp;
1881 } */ *ap;
1882{
1883 register struct vnode *vp = ap->a_vp;
1884 register struct vnode *dvp = ap->a_dvp;
1885 register struct componentname *cnp = ap->a_cnp;
1886 register u_long *tl;
1887 register caddr_t cp;
1888 register long t1, t2;
1889 caddr_t bpos, dpos, cp2;
1890 int error = 0, wccflag = NFSV3_WCCRATTR;
1891 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1892 int v3 = NFS_ISV3(dvp);
1893
1894 nfsstats.rpccnt[NFSPROC_RMDIR]++;
1895 nfsm_reqhead(dvp, NFSPROC_RMDIR,
1896 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen));
1897 nfsm_fhtom(dvp, v3);
1898 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1899 nfsm_request(dvp, NFSPROC_RMDIR, cnp->cn_proc, cnp->cn_cred);
1900 if (v3)
1901 nfsm_wcc_data(dvp, wccflag);
1902 nfsm_reqdone;
1903 zfree(namei_zone, cnp->cn_pnbuf);
1904 VTONFS(dvp)->n_flag |= NMODIFIED;
1905 if (!wccflag)
1906 VTONFS(dvp)->n_attrstamp = 0;
1907 cache_purge(dvp);
1908 cache_purge(vp);
1909 /*
1910 * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry.
1911 */
1912 if (error == ENOENT)
1913 error = 0;
1914 return (error);
1915}
1916
1917/*
1918 * nfs readdir call
1919 */
1920static int
1921nfs_readdir(ap)
1922 struct vop_readdir_args /* {
1923 struct vnode *a_vp;
1924 struct uio *a_uio;
1925 struct ucred *a_cred;
1926 } */ *ap;
1927{
1928 register struct vnode *vp = ap->a_vp;
1929 register struct nfsnode *np = VTONFS(vp);
1930 register struct uio *uio = ap->a_uio;
1931 int tresid, error;
1932 struct vattr vattr;
1933
1934 if (vp->v_type != VDIR)
1935 return (EPERM);
1936 /*
1937 * First, check for hit on the EOF offset cache
1938 */
1939 if (np->n_direofoffset > 0 && uio->uio_offset >= np->n_direofoffset &&
1940 (np->n_flag & NMODIFIED) == 0) {
1941 if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) {
1942 if (NQNFS_CKCACHABLE(vp, ND_READ)) {
1943 nfsstats.direofcache_hits++;
1944 return (0);
1945 }
1946 } else if (VOP_GETATTR(vp, &vattr, ap->a_cred, uio->uio_procp) == 0 &&
1947 np->n_mtime == vattr.va_mtime.tv_sec) {
1948 nfsstats.direofcache_hits++;
1949 return (0);
1950 }
1951 }
1952
1953 /*
1954 * Call nfs_bioread() to do the real work.
1955 */
1956 tresid = uio->uio_resid;
1957 error = nfs_bioread(vp, uio, 0, ap->a_cred, 0);
1958
1959 if (!error && uio->uio_resid == tresid)
1960 nfsstats.direofcache_misses++;
1961 return (error);
1962}
1963
1964/*
1965 * Readdir rpc call.
1966 * Called from below the buffer cache by nfs_doio().
1967 */
1968int
1969nfs_readdirrpc(vp, uiop, cred)
1970 struct vnode *vp;
1971 register struct uio *uiop;
1972 struct ucred *cred;
1973
1974{
1975 register int len, left;
1976 register struct dirent *dp;
1977 register u_long *tl;
1978 register caddr_t cp;
1979 register long t1, t2;
1980 register nfsuint64 *cookiep;
1981 caddr_t bpos, dpos, cp2;
1982 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1983 nfsuint64 cookie;
1984 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
1985 struct nfsnode *dnp = VTONFS(vp);
1986 u_quad_t fileno;
1987 int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1;
1988 int attrflag;
1989 int v3 = NFS_ISV3(vp);
1990
1991#ifndef nolint
1992 dp = (struct dirent *)0;
1993#endif
1994#ifndef DIAGNOSTIC
1995 if (uiop->uio_iovcnt != 1 || (uiop->uio_offset & (NFS_DIRBLKSIZ - 1)) ||
1996 (uiop->uio_resid & (NFS_DIRBLKSIZ - 1)))
1997 panic("nfs readdirrpc bad uio");
1998#endif
1999
2000 /*
2001 * If there is no cookie, assume directory was stale.
2002 */
2003 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 0);
2004 if (cookiep)
2005 cookie = *cookiep;
2006 else
2007 return (NFSERR_BAD_COOKIE);
2008 /*
2009 * Loop around doing readdir rpc's of size nm_readdirsize
2010 * truncated to a multiple of DIRBLKSIZ.
2011 * The stopping criteria is EOF or buffer full.
2012 */
2013 while (more_dirs && bigenough) {
2014 nfsstats.rpccnt[NFSPROC_READDIR]++;
2015 nfsm_reqhead(vp, NFSPROC_READDIR, NFSX_FH(v3) +
2016 NFSX_READDIR(v3));
2017 nfsm_fhtom(vp, v3);
2018 if (v3) {
2019 nfsm_build(tl, u_long *, 5 * NFSX_UNSIGNED);
2020 *tl++ = cookie.nfsuquad[0];
2021 *tl++ = cookie.nfsuquad[1];
2022 *tl++ = dnp->n_cookieverf.nfsuquad[0];
2023 *tl++ = dnp->n_cookieverf.nfsuquad[1];
2024 } else {
2025 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
2026 *tl++ = cookie.nfsuquad[0];
2027 }
2028 *tl = txdr_unsigned(nmp->nm_readdirsize);
2029 nfsm_request(vp, NFSPROC_READDIR, uiop->uio_procp, cred);
2030 if (v3) {
2031 nfsm_postop_attr(vp, attrflag);
2032 if (!error) {
2033 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
2034 dnp->n_cookieverf.nfsuquad[0] = *tl++;
2035 dnp->n_cookieverf.nfsuquad[1] = *tl;
2036 } else {
2037 m_freem(mrep);
2038 goto nfsmout;
2039 }
2040 }
2041 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
2042 more_dirs = fxdr_unsigned(int, *tl);
2043
2044 /* loop thru the dir entries, doctoring them to 4bsd form */
2045 while (more_dirs && bigenough) {
2046 if (v3) {
2047 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
2048 fxdr_hyper(tl, &fileno);
2049 len = fxdr_unsigned(int, *(tl + 2));
2050 } else {
2051 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
2052 fileno = fxdr_unsigned(u_quad_t, *tl++);
2053 len = fxdr_unsigned(int, *tl);
2054 }
2055 if (len <= 0 || len > NFS_MAXNAMLEN) {
2056 error = EBADRPC;
2057 m_freem(mrep);
2058 goto nfsmout;
2059 }
2060 tlen = nfsm_rndup(len);
2061 if (tlen == len)
2062 tlen += 4; /* To ensure null termination */
2063 left = DIRBLKSIZ - blksiz;
2064 if ((tlen + DIRHDSIZ) > left) {
2065 dp->d_reclen += left;
2066 uiop->uio_iov->iov_base += left;
2067 uiop->uio_iov->iov_len -= left;
2068 uiop->uio_offset += left;
2069 uiop->uio_resid -= left;
2070 blksiz = 0;
2071 }
2072 if ((tlen + DIRHDSIZ) > uiop->uio_resid)
2073 bigenough = 0;
2074 if (bigenough) {
2075 dp = (struct dirent *)uiop->uio_iov->iov_base;
2076 dp->d_fileno = (int)fileno;
2077 dp->d_namlen = len;
2078 dp->d_reclen = tlen + DIRHDSIZ;
2079 dp->d_type = DT_UNKNOWN;
2080 blksiz += dp->d_reclen;
2081 if (blksiz == DIRBLKSIZ)
2082 blksiz = 0;
2083 uiop->uio_offset += DIRHDSIZ;
2084 uiop->uio_resid -= DIRHDSIZ;
2085 uiop->uio_iov->iov_base += DIRHDSIZ;
2086 uiop->uio_iov->iov_len -= DIRHDSIZ;
2087 nfsm_mtouio(uiop, len);
2088 cp = uiop->uio_iov->iov_base;
2089 tlen -= len;
2090 *cp = '\0'; /* null terminate */
2091 uiop->uio_iov->iov_base += tlen;
2092 uiop->uio_iov->iov_len -= tlen;
2093 uiop->uio_offset += tlen;
2094 uiop->uio_resid -= tlen;
2095 } else
2096 nfsm_adv(nfsm_rndup(len));
2097 if (v3) {
2098 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
2099 } else {
2100 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
2101 }
2102 if (bigenough) {
2103 cookie.nfsuquad[0] = *tl++;
2104 if (v3)
2105 cookie.nfsuquad[1] = *tl++;
2106 } else if (v3)
2107 tl += 2;
2108 else
2109 tl++;
2110 more_dirs = fxdr_unsigned(int, *tl);
2111 }
2112 /*
2113 * If at end of rpc data, get the eof boolean
2114 */
2115 if (!more_dirs) {
2116 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
2117 more_dirs = (fxdr_unsigned(int, *tl) == 0);
2118 }
2119 m_freem(mrep);
2120 }
2121 /*
2122 * Fill last record, iff any, out to a multiple of DIRBLKSIZ
2123 * by increasing d_reclen for the last record.
2124 */
2125 if (blksiz > 0) {
2126 left = DIRBLKSIZ - blksiz;
2127 dp->d_reclen += left;
2128 uiop->uio_iov->iov_base += left;
2129 uiop->uio_iov->iov_len -= left;
2130 uiop->uio_offset += left;
2131 uiop->uio_resid -= left;
2132 }
2133
2134 /*
2135 * We are now either at the end of the directory or have filled the
2136 * block.
2137 */
2138 if (bigenough)
2139 dnp->n_direofoffset = uiop->uio_offset;
2140 else {
2141 if (uiop->uio_resid > 0)
2142 printf("EEK! readdirrpc resid > 0\n");
2143 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 1);
2144 *cookiep = cookie;
2145 }
2146nfsmout:
2147 return (error);
2148}
2149
2150/*
2151 * NFS V3 readdir plus RPC. Used in place of nfs_readdirrpc().
2152 */
2153int
2154nfs_readdirplusrpc(vp, uiop, cred)
2155 struct vnode *vp;
2156 register struct uio *uiop;
2157 struct ucred *cred;
2158{
2159 register int len, left;
2160 register struct dirent *dp;
2161 register u_long *tl;
2162 register caddr_t cp;
2163 register long t1, t2;
2164 register struct vnode *newvp;
2165 register nfsuint64 *cookiep;
2166 caddr_t bpos, dpos, cp2, dpossav1, dpossav2;
2167 struct mbuf *mreq, *mrep, *md, *mb, *mb2, *mdsav1, *mdsav2;
2168 struct nameidata nami, *ndp = &nami;
2169 struct componentname *cnp = &ndp->ni_cnd;
2170 nfsuint64 cookie;
2171 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2172 struct nfsnode *dnp = VTONFS(vp), *np;
2173 nfsfh_t *fhp;
2174 u_quad_t fileno;
2175 int error = 0, tlen, more_dirs = 1, blksiz = 0, doit, bigenough = 1, i;
2176 int attrflag, fhsize;
2177
2178#ifndef nolint
2179 dp = (struct dirent *)0;
2180#endif
2181#ifndef DIAGNOSTIC
2182 if (uiop->uio_iovcnt != 1 || (uiop->uio_offset & (DIRBLKSIZ - 1)) ||
2183 (uiop->uio_resid & (DIRBLKSIZ - 1)))
2184 panic("nfs readdirplusrpc bad uio");
2185#endif
2186 ndp->ni_dvp = vp;
2187 newvp = NULLVP;
2188
2189 /*
2190 * If there is no cookie, assume directory was stale.
2191 */
2192 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 0);
2193 if (cookiep)
2194 cookie = *cookiep;
2195 else
2196 return (NFSERR_BAD_COOKIE);
2197 /*
2198 * Loop around doing readdir rpc's of size nm_readdirsize
2199 * truncated to a multiple of DIRBLKSIZ.
2200 * The stopping criteria is EOF or buffer full.
2201 */
2202 while (more_dirs && bigenough) {
2203 nfsstats.rpccnt[NFSPROC_READDIRPLUS]++;
2204 nfsm_reqhead(vp, NFSPROC_READDIRPLUS,
2205 NFSX_FH(1) + 6 * NFSX_UNSIGNED);
2206 nfsm_fhtom(vp, 1);
2207 nfsm_build(tl, u_long *, 6 * NFSX_UNSIGNED);
2208 *tl++ = cookie.nfsuquad[0];
2209 *tl++ = cookie.nfsuquad[1];
2210 *tl++ = dnp->n_cookieverf.nfsuquad[0];
2211 *tl++ = dnp->n_cookieverf.nfsuquad[1];
2212 *tl++ = txdr_unsigned(nmp->nm_readdirsize);
2213 *tl = txdr_unsigned(nmp->nm_rsize);
2214 nfsm_request(vp, NFSPROC_READDIRPLUS, uiop->uio_procp, cred);
2215 nfsm_postop_attr(vp, attrflag);
2216 if (error) {
2217 m_freem(mrep);
2218 goto nfsmout;
2219 }
2220 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
2221 dnp->n_cookieverf.nfsuquad[0] = *tl++;
2222 dnp->n_cookieverf.nfsuquad[1] = *tl++;
2223 more_dirs = fxdr_unsigned(int, *tl);
2224
2225 /* loop thru the dir entries, doctoring them to 4bsd form */
2226 while (more_dirs && bigenough) {
2227 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
2228 fxdr_hyper(tl, &fileno);
2229 len = fxdr_unsigned(int, *(tl + 2));
2230 if (len <= 0 || len > NFS_MAXNAMLEN) {
2231 error = EBADRPC;
2232 m_freem(mrep);
2233 goto nfsmout;
2234 }
2235 tlen = nfsm_rndup(len);
2236 if (tlen == len)
2237 tlen += 4; /* To ensure null termination*/
2238 left = DIRBLKSIZ - blksiz;
2239 if ((tlen + DIRHDSIZ) > left) {
2240 dp->d_reclen += left;
2241 uiop->uio_iov->iov_base += left;
2242 uiop->uio_iov->iov_len -= left;
2243 uiop->uio_offset += left;
2244 uiop->uio_resid -= left;
2245 blksiz = 0;
2246 }
2247 if ((tlen + DIRHDSIZ) > uiop->uio_resid)
2248 bigenough = 0;
2249 if (bigenough) {
2250 dp = (struct dirent *)uiop->uio_iov->iov_base;
2251 dp->d_fileno = (int)fileno;
2252 dp->d_namlen = len;
2253 dp->d_reclen = tlen + DIRHDSIZ;
2254 dp->d_type = DT_UNKNOWN;
2255 blksiz += dp->d_reclen;
2256 if (blksiz == DIRBLKSIZ)
2257 blksiz = 0;
2258 uiop->uio_offset += DIRHDSIZ;
2259 uiop->uio_resid -= DIRHDSIZ;
2260 uiop->uio_iov->iov_base += DIRHDSIZ;
2261 uiop->uio_iov->iov_len -= DIRHDSIZ;
2262 cnp->cn_nameptr = uiop->uio_iov->iov_base;
2263 cnp->cn_namelen = len;
2264 nfsm_mtouio(uiop, len);
2265 cp = uiop->uio_iov->iov_base;
2266 tlen -= len;
2267 *cp = '\0';
2268 uiop->uio_iov->iov_base += tlen;
2269 uiop->uio_iov->iov_len -= tlen;
2270 uiop->uio_offset += tlen;
2271 uiop->uio_resid -= tlen;
2272 } else
2273 nfsm_adv(nfsm_rndup(len));
2274 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
2275 if (bigenough) {
2276 cookie.nfsuquad[0] = *tl++;
2277 cookie.nfsuquad[1] = *tl++;
2278 } else
2279 tl += 2;
2280
2281 /*
2282 * Since the attributes are before the file handle
2283 * (sigh), we must skip over the attributes and then
2284 * come back and get them.
2285 */
2286 attrflag = fxdr_unsigned(int, *tl);
2287 if (attrflag) {
2288 dpossav1 = dpos;
2289 mdsav1 = md;
2290 nfsm_adv(NFSX_V3FATTR);
2291 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
2292 doit = fxdr_unsigned(int, *tl);
2293 if (doit) {
2294 nfsm_getfh(fhp, fhsize, 1);
2295 if (NFS_CMPFH(dnp, fhp, fhsize)) {
2296 VREF(vp);
2297 newvp = vp;
2298 np = dnp;
2299 } else {
2300 error = nfs_nget(vp->v_mount, fhp,
2301 fhsize, &np);
2302 if (error)
2303 doit = 0;
2304 else
2305 newvp = NFSTOV(np);
2306 }
2307 }
2308 if (doit) {
2309 dpossav2 = dpos;
2310 dpos = dpossav1;
2311 mdsav2 = md;
2312 md = mdsav1;
2313 nfsm_loadattr(newvp, (struct vattr *)0);
2314 dpos = dpossav2;
2315 md = mdsav2;
2316 dp->d_type =
2317 IFTODT(VTTOIF(np->n_vattr.va_type));
2318 ndp->ni_vp = newvp;
2319 cnp->cn_hash = 0;
2320 for (cp = cnp->cn_nameptr, i = 1; i <= len;
2321 i++, cp++)
2322 cnp->cn_hash += (unsigned char)*cp * i;
2323 cache_enter(ndp->ni_dvp, ndp->ni_vp, cnp);
2324 }
2325 } else {
2326 /* Just skip over the file handle */
2327 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
2328 i = fxdr_unsigned(int, *tl);
2329 nfsm_adv(nfsm_rndup(i));
2330 }
2331 if (newvp != NULLVP) {
2332 vrele(newvp);
2333 newvp = NULLVP;
2334 }
2335 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
2336 more_dirs = fxdr_unsigned(int, *tl);
2337 }
2338 /*
2339 * If at end of rpc data, get the eof boolean
2340 */
2341 if (!more_dirs) {
2342 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
2343 more_dirs = (fxdr_unsigned(int, *tl) == 0);
2344 }
2345 m_freem(mrep);
2346 }
2347 /*
2348 * Fill last record, iff any, out to a multiple of NFS_DIRBLKSIZ
2349 * by increasing d_reclen for the last record.
2350 */
2351 if (blksiz > 0) {
2352 left = DIRBLKSIZ - blksiz;
2353 dp->d_reclen += left;
2354 uiop->uio_iov->iov_base += left;
2355 uiop->uio_iov->iov_len -= left;
2356 uiop->uio_offset += left;
2357 uiop->uio_resid -= left;
2358 }
2359
2360 /*
2361 * We are now either at the end of the directory or have filled the
2362 * block.
2363 */
2364 if (bigenough)
2365 dnp->n_direofoffset = uiop->uio_offset;
2366 else {
2367 if (uiop->uio_resid > 0)
2368 printf("EEK! readdirplusrpc resid > 0\n");
2369 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 1);
2370 *cookiep = cookie;
2371 }
2372nfsmout:
2373 if (newvp != NULLVP) {
2374 if (newvp == vp)
2375 vrele(newvp);
2376 else
2377 vput(newvp);
2378 newvp = NULLVP;
2379 }
2380 return (error);
2381}
2382
2383/*
2384 * Silly rename. To make the NFS filesystem that is stateless look a little
2385 * more like the "ufs" a remove of an active vnode is translated to a rename
2386 * to a funny looking filename that is removed by nfs_inactive on the
2387 * nfsnode. There is the potential for another process on a different client
2388 * to create the same funny name between the nfs_lookitup() fails and the
2389 * nfs_rename() completes, but...
2390 */
2391static int
2392nfs_sillyrename(dvp, vp, cnp)
2393 struct vnode *dvp, *vp;
2394 struct componentname *cnp;
2395{
2396 register struct sillyrename *sp;
2397 struct nfsnode *np;
2398 int error;
2399 short pid;
2400
2401 cache_purge(dvp);
2402 np = VTONFS(vp);
2403#ifndef DIAGNOSTIC
2404 if (vp->v_type == VDIR)
2405 panic("nfs: sillyrename dir");
2406#endif
2407 MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename),
2408 M_NFSREQ, M_WAITOK);
2409 sp->s_cred = crdup(cnp->cn_cred);
2410 sp->s_dvp = dvp;
2411 VREF(dvp);
2412
2413 /* Fudge together a funny name */
2414 pid = cnp->cn_proc->p_pid;
2415 sp->s_namlen = sprintf(sp->s_name, ".nfsA%04x4.4", pid);
2416
2417 /* Try lookitups until we get one that isn't there */
2418 while (nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred,
2419 cnp->cn_proc, (struct nfsnode **)0) == 0) {
2420 sp->s_name[4]++;
2421 if (sp->s_name[4] > 'z') {
2422 error = EINVAL;
2423 goto bad;
2424 }
2425 }
2426 error = nfs_renameit(dvp, cnp, sp);
2427 if (error)
2428 goto bad;
2429 error = nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred,
2430 cnp->cn_proc, &np);
2431 np->n_sillyrename = sp;
2432 return (0);
2433bad:
2434 vrele(sp->s_dvp);
2435 crfree(sp->s_cred);
2436 free((caddr_t)sp, M_NFSREQ);
2437 return (error);
2438}
2439
2440/*
2441 * Look up a file name and optionally either update the file handle or
2442 * allocate an nfsnode, depending on the value of npp.
2443 * npp == NULL --> just do the lookup
2444 * *npp == NULL --> allocate a new nfsnode and make sure attributes are
2445 * handled too
2446 * *npp != NULL --> update the file handle in the vnode
2447 */
2448static int
2449nfs_lookitup(dvp, name, len, cred, procp, npp)
2450 register struct vnode *dvp;
1623 int tnamelen;
1624 struct ucred *cred;
1625 struct proc *proc;
1626{
1627 register u_long *tl;
1628 register caddr_t cp;
1629 register long t1, t2;
1630 caddr_t bpos, dpos, cp2;
1631 int error = 0, fwccflag = NFSV3_WCCRATTR, twccflag = NFSV3_WCCRATTR;
1632 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1633 int v3 = NFS_ISV3(fdvp);
1634
1635 nfsstats.rpccnt[NFSPROC_RENAME]++;
1636 nfsm_reqhead(fdvp, NFSPROC_RENAME,
1637 (NFSX_FH(v3) + NFSX_UNSIGNED)*2 + nfsm_rndup(fnamelen) +
1638 nfsm_rndup(tnamelen));
1639 nfsm_fhtom(fdvp, v3);
1640 nfsm_strtom(fnameptr, fnamelen, NFS_MAXNAMLEN);
1641 nfsm_fhtom(tdvp, v3);
1642 nfsm_strtom(tnameptr, tnamelen, NFS_MAXNAMLEN);
1643 nfsm_request(fdvp, NFSPROC_RENAME, proc, cred);
1644 if (v3) {
1645 nfsm_wcc_data(fdvp, fwccflag);
1646 nfsm_wcc_data(tdvp, twccflag);
1647 }
1648 nfsm_reqdone;
1649 VTONFS(fdvp)->n_flag |= NMODIFIED;
1650 VTONFS(tdvp)->n_flag |= NMODIFIED;
1651 if (!fwccflag)
1652 VTONFS(fdvp)->n_attrstamp = 0;
1653 if (!twccflag)
1654 VTONFS(tdvp)->n_attrstamp = 0;
1655 return (error);
1656}
1657
1658/*
1659 * nfs hard link create call
1660 */
1661static int
1662nfs_link(ap)
1663 struct vop_link_args /* {
1664 struct vnode *a_tdvp;
1665 struct vnode *a_vp;
1666 struct componentname *a_cnp;
1667 } */ *ap;
1668{
1669 register struct vnode *vp = ap->a_vp;
1670 register struct vnode *tdvp = ap->a_tdvp;
1671 register struct componentname *cnp = ap->a_cnp;
1672 register u_long *tl;
1673 register caddr_t cp;
1674 register long t1, t2;
1675 caddr_t bpos, dpos, cp2;
1676 int error = 0, wccflag = NFSV3_WCCRATTR, attrflag = 0;
1677 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1678 int v3 = NFS_ISV3(vp);
1679
1680 if (vp->v_mount != tdvp->v_mount) {
1681 VOP_ABORTOP(tdvp, cnp);
1682 return (EXDEV);
1683 }
1684
1685 /*
1686 * Push all writes to the server, so that the attribute cache
1687 * doesn't get "out of sync" with the server.
1688 * XXX There should be a better way!
1689 */
1690 VOP_FSYNC(vp, cnp->cn_cred, MNT_WAIT, cnp->cn_proc);
1691
1692 nfsstats.rpccnt[NFSPROC_LINK]++;
1693 nfsm_reqhead(vp, NFSPROC_LINK,
1694 NFSX_FH(v3)*2 + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen));
1695 nfsm_fhtom(vp, v3);
1696 nfsm_fhtom(tdvp, v3);
1697 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1698 nfsm_request(vp, NFSPROC_LINK, cnp->cn_proc, cnp->cn_cred);
1699 if (v3) {
1700 nfsm_postop_attr(vp, attrflag);
1701 nfsm_wcc_data(tdvp, wccflag);
1702 }
1703 nfsm_reqdone;
1704 zfree(namei_zone, cnp->cn_pnbuf);
1705 VTONFS(tdvp)->n_flag |= NMODIFIED;
1706 if (!attrflag)
1707 VTONFS(vp)->n_attrstamp = 0;
1708 if (!wccflag)
1709 VTONFS(tdvp)->n_attrstamp = 0;
1710 /*
1711 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
1712 */
1713 if (error == EEXIST)
1714 error = 0;
1715 return (error);
1716}
1717
1718/*
1719 * nfs symbolic link create call
1720 */
1721static int
1722nfs_symlink(ap)
1723 struct vop_symlink_args /* {
1724 struct vnode *a_dvp;
1725 struct vnode **a_vpp;
1726 struct componentname *a_cnp;
1727 struct vattr *a_vap;
1728 char *a_target;
1729 } */ *ap;
1730{
1731 register struct vnode *dvp = ap->a_dvp;
1732 register struct vattr *vap = ap->a_vap;
1733 register struct componentname *cnp = ap->a_cnp;
1734 register struct nfsv2_sattr *sp;
1735 register struct nfsv3_sattr *sp3;
1736 register u_long *tl;
1737 register caddr_t cp;
1738 register long t1, t2;
1739 caddr_t bpos, dpos, cp2;
1740 int slen, error = 0, wccflag = NFSV3_WCCRATTR, gotvp;
1741 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1742 struct vnode *newvp = (struct vnode *)0;
1743 int v3 = NFS_ISV3(dvp);
1744
1745 nfsstats.rpccnt[NFSPROC_SYMLINK]++;
1746 slen = strlen(ap->a_target);
1747 nfsm_reqhead(dvp, NFSPROC_SYMLINK, NFSX_FH(v3) + 2*NFSX_UNSIGNED +
1748 nfsm_rndup(cnp->cn_namelen) + nfsm_rndup(slen) + NFSX_SATTR(v3));
1749 nfsm_fhtom(dvp, v3);
1750 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1751 if (v3) {
1752 nfsm_build(sp3, struct nfsv3_sattr *, NFSX_V3SRVSATTR);
1753 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid,
1754 cnp->cn_cred->cr_gid);
1755 }
1756 nfsm_strtom(ap->a_target, slen, NFS_MAXPATHLEN);
1757 if (!v3) {
1758 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1759 sp->sa_mode = vtonfsv2_mode(VLNK, vap->va_mode);
1760 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid);
1761 sp->sa_gid = txdr_unsigned(cnp->cn_cred->cr_gid);
1762 sp->sa_size = -1;
1763 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
1764 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
1765 }
1766 nfsm_request(dvp, NFSPROC_SYMLINK, cnp->cn_proc, cnp->cn_cred);
1767 if (v3) {
1768 if (!error)
1769 nfsm_mtofh(dvp, newvp, v3, gotvp);
1770 nfsm_wcc_data(dvp, wccflag);
1771 }
1772 nfsm_reqdone;
1773 if (newvp)
1774 vput(newvp);
1775 zfree(namei_zone, cnp->cn_pnbuf);
1776 VTONFS(dvp)->n_flag |= NMODIFIED;
1777 if (!wccflag)
1778 VTONFS(dvp)->n_attrstamp = 0;
1779 /*
1780 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
1781 */
1782 if (error == EEXIST)
1783 error = 0;
1784 return (error);
1785}
1786
1787/*
1788 * nfs make dir call
1789 */
1790static int
1791nfs_mkdir(ap)
1792 struct vop_mkdir_args /* {
1793 struct vnode *a_dvp;
1794 struct vnode **a_vpp;
1795 struct componentname *a_cnp;
1796 struct vattr *a_vap;
1797 } */ *ap;
1798{
1799 register struct vnode *dvp = ap->a_dvp;
1800 register struct vattr *vap = ap->a_vap;
1801 register struct componentname *cnp = ap->a_cnp;
1802 register struct nfsv2_sattr *sp;
1803 register struct nfsv3_sattr *sp3;
1804 register u_long *tl;
1805 register caddr_t cp;
1806 register long t1, t2;
1807 register int len;
1808 struct nfsnode *np = (struct nfsnode *)0;
1809 struct vnode *newvp = (struct vnode *)0;
1810 caddr_t bpos, dpos, cp2;
1811 int error = 0, wccflag = NFSV3_WCCRATTR;
1812 int gotvp = 0;
1813 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1814 struct vattr vattr;
1815 int v3 = NFS_ISV3(dvp);
1816
1817 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) {
1818 VOP_ABORTOP(dvp, cnp);
1819 return (error);
1820 }
1821 len = cnp->cn_namelen;
1822 nfsstats.rpccnt[NFSPROC_MKDIR]++;
1823 nfsm_reqhead(dvp, NFSPROC_MKDIR,
1824 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len) + NFSX_SATTR(v3));
1825 nfsm_fhtom(dvp, v3);
1826 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
1827 if (v3) {
1828 nfsm_build(sp3, struct nfsv3_sattr *, NFSX_V3SRVSATTR);
1829 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, vattr.va_gid);
1830 } else {
1831 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1832 sp->sa_mode = vtonfsv2_mode(VDIR, vap->va_mode);
1833 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid);
1834 sp->sa_gid = txdr_unsigned(vattr.va_gid);
1835 sp->sa_size = -1;
1836 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
1837 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
1838 }
1839 nfsm_request(dvp, NFSPROC_MKDIR, cnp->cn_proc, cnp->cn_cred);
1840 if (!error)
1841 nfsm_mtofh(dvp, newvp, v3, gotvp);
1842 if (v3)
1843 nfsm_wcc_data(dvp, wccflag);
1844 nfsm_reqdone;
1845 VTONFS(dvp)->n_flag |= NMODIFIED;
1846 if (!wccflag)
1847 VTONFS(dvp)->n_attrstamp = 0;
1848 /*
1849 * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry
1850 * if we can succeed in looking up the directory.
1851 */
1852 if (error == EEXIST || (!error && !gotvp)) {
1853 if (newvp) {
1854 vrele(newvp);
1855 newvp = (struct vnode *)0;
1856 }
1857 error = nfs_lookitup(dvp, cnp->cn_nameptr, len, cnp->cn_cred,
1858 cnp->cn_proc, &np);
1859 if (!error) {
1860 newvp = NFSTOV(np);
1861 if (newvp->v_type != VDIR)
1862 error = EEXIST;
1863 }
1864 }
1865 if (error) {
1866 if (newvp)
1867 vrele(newvp);
1868 } else
1869 *ap->a_vpp = newvp;
1870 zfree(namei_zone, cnp->cn_pnbuf);
1871 return (error);
1872}
1873
1874/*
1875 * nfs remove directory call
1876 */
1877static int
1878nfs_rmdir(ap)
1879 struct vop_rmdir_args /* {
1880 struct vnode *a_dvp;
1881 struct vnode *a_vp;
1882 struct componentname *a_cnp;
1883 } */ *ap;
1884{
1885 register struct vnode *vp = ap->a_vp;
1886 register struct vnode *dvp = ap->a_dvp;
1887 register struct componentname *cnp = ap->a_cnp;
1888 register u_long *tl;
1889 register caddr_t cp;
1890 register long t1, t2;
1891 caddr_t bpos, dpos, cp2;
1892 int error = 0, wccflag = NFSV3_WCCRATTR;
1893 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1894 int v3 = NFS_ISV3(dvp);
1895
1896 nfsstats.rpccnt[NFSPROC_RMDIR]++;
1897 nfsm_reqhead(dvp, NFSPROC_RMDIR,
1898 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen));
1899 nfsm_fhtom(dvp, v3);
1900 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1901 nfsm_request(dvp, NFSPROC_RMDIR, cnp->cn_proc, cnp->cn_cred);
1902 if (v3)
1903 nfsm_wcc_data(dvp, wccflag);
1904 nfsm_reqdone;
1905 zfree(namei_zone, cnp->cn_pnbuf);
1906 VTONFS(dvp)->n_flag |= NMODIFIED;
1907 if (!wccflag)
1908 VTONFS(dvp)->n_attrstamp = 0;
1909 cache_purge(dvp);
1910 cache_purge(vp);
1911 /*
1912 * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry.
1913 */
1914 if (error == ENOENT)
1915 error = 0;
1916 return (error);
1917}
1918
1919/*
1920 * nfs readdir call
1921 */
1922static int
1923nfs_readdir(ap)
1924 struct vop_readdir_args /* {
1925 struct vnode *a_vp;
1926 struct uio *a_uio;
1927 struct ucred *a_cred;
1928 } */ *ap;
1929{
1930 register struct vnode *vp = ap->a_vp;
1931 register struct nfsnode *np = VTONFS(vp);
1932 register struct uio *uio = ap->a_uio;
1933 int tresid, error;
1934 struct vattr vattr;
1935
1936 if (vp->v_type != VDIR)
1937 return (EPERM);
1938 /*
1939 * First, check for hit on the EOF offset cache
1940 */
1941 if (np->n_direofoffset > 0 && uio->uio_offset >= np->n_direofoffset &&
1942 (np->n_flag & NMODIFIED) == 0) {
1943 if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) {
1944 if (NQNFS_CKCACHABLE(vp, ND_READ)) {
1945 nfsstats.direofcache_hits++;
1946 return (0);
1947 }
1948 } else if (VOP_GETATTR(vp, &vattr, ap->a_cred, uio->uio_procp) == 0 &&
1949 np->n_mtime == vattr.va_mtime.tv_sec) {
1950 nfsstats.direofcache_hits++;
1951 return (0);
1952 }
1953 }
1954
1955 /*
1956 * Call nfs_bioread() to do the real work.
1957 */
1958 tresid = uio->uio_resid;
1959 error = nfs_bioread(vp, uio, 0, ap->a_cred, 0);
1960
1961 if (!error && uio->uio_resid == tresid)
1962 nfsstats.direofcache_misses++;
1963 return (error);
1964}
1965
1966/*
1967 * Readdir rpc call.
1968 * Called from below the buffer cache by nfs_doio().
1969 */
1970int
1971nfs_readdirrpc(vp, uiop, cred)
1972 struct vnode *vp;
1973 register struct uio *uiop;
1974 struct ucred *cred;
1975
1976{
1977 register int len, left;
1978 register struct dirent *dp;
1979 register u_long *tl;
1980 register caddr_t cp;
1981 register long t1, t2;
1982 register nfsuint64 *cookiep;
1983 caddr_t bpos, dpos, cp2;
1984 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1985 nfsuint64 cookie;
1986 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
1987 struct nfsnode *dnp = VTONFS(vp);
1988 u_quad_t fileno;
1989 int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1;
1990 int attrflag;
1991 int v3 = NFS_ISV3(vp);
1992
1993#ifndef nolint
1994 dp = (struct dirent *)0;
1995#endif
1996#ifndef DIAGNOSTIC
1997 if (uiop->uio_iovcnt != 1 || (uiop->uio_offset & (NFS_DIRBLKSIZ - 1)) ||
1998 (uiop->uio_resid & (NFS_DIRBLKSIZ - 1)))
1999 panic("nfs readdirrpc bad uio");
2000#endif
2001
2002 /*
2003 * If there is no cookie, assume directory was stale.
2004 */
2005 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 0);
2006 if (cookiep)
2007 cookie = *cookiep;
2008 else
2009 return (NFSERR_BAD_COOKIE);
2010 /*
2011 * Loop around doing readdir rpc's of size nm_readdirsize
2012 * truncated to a multiple of DIRBLKSIZ.
2013 * The stopping criteria is EOF or buffer full.
2014 */
2015 while (more_dirs && bigenough) {
2016 nfsstats.rpccnt[NFSPROC_READDIR]++;
2017 nfsm_reqhead(vp, NFSPROC_READDIR, NFSX_FH(v3) +
2018 NFSX_READDIR(v3));
2019 nfsm_fhtom(vp, v3);
2020 if (v3) {
2021 nfsm_build(tl, u_long *, 5 * NFSX_UNSIGNED);
2022 *tl++ = cookie.nfsuquad[0];
2023 *tl++ = cookie.nfsuquad[1];
2024 *tl++ = dnp->n_cookieverf.nfsuquad[0];
2025 *tl++ = dnp->n_cookieverf.nfsuquad[1];
2026 } else {
2027 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
2028 *tl++ = cookie.nfsuquad[0];
2029 }
2030 *tl = txdr_unsigned(nmp->nm_readdirsize);
2031 nfsm_request(vp, NFSPROC_READDIR, uiop->uio_procp, cred);
2032 if (v3) {
2033 nfsm_postop_attr(vp, attrflag);
2034 if (!error) {
2035 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
2036 dnp->n_cookieverf.nfsuquad[0] = *tl++;
2037 dnp->n_cookieverf.nfsuquad[1] = *tl;
2038 } else {
2039 m_freem(mrep);
2040 goto nfsmout;
2041 }
2042 }
2043 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
2044 more_dirs = fxdr_unsigned(int, *tl);
2045
2046 /* loop thru the dir entries, doctoring them to 4bsd form */
2047 while (more_dirs && bigenough) {
2048 if (v3) {
2049 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
2050 fxdr_hyper(tl, &fileno);
2051 len = fxdr_unsigned(int, *(tl + 2));
2052 } else {
2053 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
2054 fileno = fxdr_unsigned(u_quad_t, *tl++);
2055 len = fxdr_unsigned(int, *tl);
2056 }
2057 if (len <= 0 || len > NFS_MAXNAMLEN) {
2058 error = EBADRPC;
2059 m_freem(mrep);
2060 goto nfsmout;
2061 }
2062 tlen = nfsm_rndup(len);
2063 if (tlen == len)
2064 tlen += 4; /* To ensure null termination */
2065 left = DIRBLKSIZ - blksiz;
2066 if ((tlen + DIRHDSIZ) > left) {
2067 dp->d_reclen += left;
2068 uiop->uio_iov->iov_base += left;
2069 uiop->uio_iov->iov_len -= left;
2070 uiop->uio_offset += left;
2071 uiop->uio_resid -= left;
2072 blksiz = 0;
2073 }
2074 if ((tlen + DIRHDSIZ) > uiop->uio_resid)
2075 bigenough = 0;
2076 if (bigenough) {
2077 dp = (struct dirent *)uiop->uio_iov->iov_base;
2078 dp->d_fileno = (int)fileno;
2079 dp->d_namlen = len;
2080 dp->d_reclen = tlen + DIRHDSIZ;
2081 dp->d_type = DT_UNKNOWN;
2082 blksiz += dp->d_reclen;
2083 if (blksiz == DIRBLKSIZ)
2084 blksiz = 0;
2085 uiop->uio_offset += DIRHDSIZ;
2086 uiop->uio_resid -= DIRHDSIZ;
2087 uiop->uio_iov->iov_base += DIRHDSIZ;
2088 uiop->uio_iov->iov_len -= DIRHDSIZ;
2089 nfsm_mtouio(uiop, len);
2090 cp = uiop->uio_iov->iov_base;
2091 tlen -= len;
2092 *cp = '\0'; /* null terminate */
2093 uiop->uio_iov->iov_base += tlen;
2094 uiop->uio_iov->iov_len -= tlen;
2095 uiop->uio_offset += tlen;
2096 uiop->uio_resid -= tlen;
2097 } else
2098 nfsm_adv(nfsm_rndup(len));
2099 if (v3) {
2100 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
2101 } else {
2102 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
2103 }
2104 if (bigenough) {
2105 cookie.nfsuquad[0] = *tl++;
2106 if (v3)
2107 cookie.nfsuquad[1] = *tl++;
2108 } else if (v3)
2109 tl += 2;
2110 else
2111 tl++;
2112 more_dirs = fxdr_unsigned(int, *tl);
2113 }
2114 /*
2115 * If at end of rpc data, get the eof boolean
2116 */
2117 if (!more_dirs) {
2118 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
2119 more_dirs = (fxdr_unsigned(int, *tl) == 0);
2120 }
2121 m_freem(mrep);
2122 }
2123 /*
2124 * Fill last record, iff any, out to a multiple of DIRBLKSIZ
2125 * by increasing d_reclen for the last record.
2126 */
2127 if (blksiz > 0) {
2128 left = DIRBLKSIZ - blksiz;
2129 dp->d_reclen += left;
2130 uiop->uio_iov->iov_base += left;
2131 uiop->uio_iov->iov_len -= left;
2132 uiop->uio_offset += left;
2133 uiop->uio_resid -= left;
2134 }
2135
2136 /*
2137 * We are now either at the end of the directory or have filled the
2138 * block.
2139 */
2140 if (bigenough)
2141 dnp->n_direofoffset = uiop->uio_offset;
2142 else {
2143 if (uiop->uio_resid > 0)
2144 printf("EEK! readdirrpc resid > 0\n");
2145 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 1);
2146 *cookiep = cookie;
2147 }
2148nfsmout:
2149 return (error);
2150}
2151
2152/*
2153 * NFS V3 readdir plus RPC. Used in place of nfs_readdirrpc().
2154 */
2155int
2156nfs_readdirplusrpc(vp, uiop, cred)
2157 struct vnode *vp;
2158 register struct uio *uiop;
2159 struct ucred *cred;
2160{
2161 register int len, left;
2162 register struct dirent *dp;
2163 register u_long *tl;
2164 register caddr_t cp;
2165 register long t1, t2;
2166 register struct vnode *newvp;
2167 register nfsuint64 *cookiep;
2168 caddr_t bpos, dpos, cp2, dpossav1, dpossav2;
2169 struct mbuf *mreq, *mrep, *md, *mb, *mb2, *mdsav1, *mdsav2;
2170 struct nameidata nami, *ndp = &nami;
2171 struct componentname *cnp = &ndp->ni_cnd;
2172 nfsuint64 cookie;
2173 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2174 struct nfsnode *dnp = VTONFS(vp), *np;
2175 nfsfh_t *fhp;
2176 u_quad_t fileno;
2177 int error = 0, tlen, more_dirs = 1, blksiz = 0, doit, bigenough = 1, i;
2178 int attrflag, fhsize;
2179
2180#ifndef nolint
2181 dp = (struct dirent *)0;
2182#endif
2183#ifndef DIAGNOSTIC
2184 if (uiop->uio_iovcnt != 1 || (uiop->uio_offset & (DIRBLKSIZ - 1)) ||
2185 (uiop->uio_resid & (DIRBLKSIZ - 1)))
2186 panic("nfs readdirplusrpc bad uio");
2187#endif
2188 ndp->ni_dvp = vp;
2189 newvp = NULLVP;
2190
2191 /*
2192 * If there is no cookie, assume directory was stale.
2193 */
2194 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 0);
2195 if (cookiep)
2196 cookie = *cookiep;
2197 else
2198 return (NFSERR_BAD_COOKIE);
2199 /*
2200 * Loop around doing readdir rpc's of size nm_readdirsize
2201 * truncated to a multiple of DIRBLKSIZ.
2202 * The stopping criteria is EOF or buffer full.
2203 */
2204 while (more_dirs && bigenough) {
2205 nfsstats.rpccnt[NFSPROC_READDIRPLUS]++;
2206 nfsm_reqhead(vp, NFSPROC_READDIRPLUS,
2207 NFSX_FH(1) + 6 * NFSX_UNSIGNED);
2208 nfsm_fhtom(vp, 1);
2209 nfsm_build(tl, u_long *, 6 * NFSX_UNSIGNED);
2210 *tl++ = cookie.nfsuquad[0];
2211 *tl++ = cookie.nfsuquad[1];
2212 *tl++ = dnp->n_cookieverf.nfsuquad[0];
2213 *tl++ = dnp->n_cookieverf.nfsuquad[1];
2214 *tl++ = txdr_unsigned(nmp->nm_readdirsize);
2215 *tl = txdr_unsigned(nmp->nm_rsize);
2216 nfsm_request(vp, NFSPROC_READDIRPLUS, uiop->uio_procp, cred);
2217 nfsm_postop_attr(vp, attrflag);
2218 if (error) {
2219 m_freem(mrep);
2220 goto nfsmout;
2221 }
2222 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
2223 dnp->n_cookieverf.nfsuquad[0] = *tl++;
2224 dnp->n_cookieverf.nfsuquad[1] = *tl++;
2225 more_dirs = fxdr_unsigned(int, *tl);
2226
2227 /* loop thru the dir entries, doctoring them to 4bsd form */
2228 while (more_dirs && bigenough) {
2229 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
2230 fxdr_hyper(tl, &fileno);
2231 len = fxdr_unsigned(int, *(tl + 2));
2232 if (len <= 0 || len > NFS_MAXNAMLEN) {
2233 error = EBADRPC;
2234 m_freem(mrep);
2235 goto nfsmout;
2236 }
2237 tlen = nfsm_rndup(len);
2238 if (tlen == len)
2239 tlen += 4; /* To ensure null termination*/
2240 left = DIRBLKSIZ - blksiz;
2241 if ((tlen + DIRHDSIZ) > left) {
2242 dp->d_reclen += left;
2243 uiop->uio_iov->iov_base += left;
2244 uiop->uio_iov->iov_len -= left;
2245 uiop->uio_offset += left;
2246 uiop->uio_resid -= left;
2247 blksiz = 0;
2248 }
2249 if ((tlen + DIRHDSIZ) > uiop->uio_resid)
2250 bigenough = 0;
2251 if (bigenough) {
2252 dp = (struct dirent *)uiop->uio_iov->iov_base;
2253 dp->d_fileno = (int)fileno;
2254 dp->d_namlen = len;
2255 dp->d_reclen = tlen + DIRHDSIZ;
2256 dp->d_type = DT_UNKNOWN;
2257 blksiz += dp->d_reclen;
2258 if (blksiz == DIRBLKSIZ)
2259 blksiz = 0;
2260 uiop->uio_offset += DIRHDSIZ;
2261 uiop->uio_resid -= DIRHDSIZ;
2262 uiop->uio_iov->iov_base += DIRHDSIZ;
2263 uiop->uio_iov->iov_len -= DIRHDSIZ;
2264 cnp->cn_nameptr = uiop->uio_iov->iov_base;
2265 cnp->cn_namelen = len;
2266 nfsm_mtouio(uiop, len);
2267 cp = uiop->uio_iov->iov_base;
2268 tlen -= len;
2269 *cp = '\0';
2270 uiop->uio_iov->iov_base += tlen;
2271 uiop->uio_iov->iov_len -= tlen;
2272 uiop->uio_offset += tlen;
2273 uiop->uio_resid -= tlen;
2274 } else
2275 nfsm_adv(nfsm_rndup(len));
2276 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
2277 if (bigenough) {
2278 cookie.nfsuquad[0] = *tl++;
2279 cookie.nfsuquad[1] = *tl++;
2280 } else
2281 tl += 2;
2282
2283 /*
2284 * Since the attributes are before the file handle
2285 * (sigh), we must skip over the attributes and then
2286 * come back and get them.
2287 */
2288 attrflag = fxdr_unsigned(int, *tl);
2289 if (attrflag) {
2290 dpossav1 = dpos;
2291 mdsav1 = md;
2292 nfsm_adv(NFSX_V3FATTR);
2293 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
2294 doit = fxdr_unsigned(int, *tl);
2295 if (doit) {
2296 nfsm_getfh(fhp, fhsize, 1);
2297 if (NFS_CMPFH(dnp, fhp, fhsize)) {
2298 VREF(vp);
2299 newvp = vp;
2300 np = dnp;
2301 } else {
2302 error = nfs_nget(vp->v_mount, fhp,
2303 fhsize, &np);
2304 if (error)
2305 doit = 0;
2306 else
2307 newvp = NFSTOV(np);
2308 }
2309 }
2310 if (doit) {
2311 dpossav2 = dpos;
2312 dpos = dpossav1;
2313 mdsav2 = md;
2314 md = mdsav1;
2315 nfsm_loadattr(newvp, (struct vattr *)0);
2316 dpos = dpossav2;
2317 md = mdsav2;
2318 dp->d_type =
2319 IFTODT(VTTOIF(np->n_vattr.va_type));
2320 ndp->ni_vp = newvp;
2321 cnp->cn_hash = 0;
2322 for (cp = cnp->cn_nameptr, i = 1; i <= len;
2323 i++, cp++)
2324 cnp->cn_hash += (unsigned char)*cp * i;
2325 cache_enter(ndp->ni_dvp, ndp->ni_vp, cnp);
2326 }
2327 } else {
2328 /* Just skip over the file handle */
2329 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
2330 i = fxdr_unsigned(int, *tl);
2331 nfsm_adv(nfsm_rndup(i));
2332 }
2333 if (newvp != NULLVP) {
2334 vrele(newvp);
2335 newvp = NULLVP;
2336 }
2337 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
2338 more_dirs = fxdr_unsigned(int, *tl);
2339 }
2340 /*
2341 * If at end of rpc data, get the eof boolean
2342 */
2343 if (!more_dirs) {
2344 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
2345 more_dirs = (fxdr_unsigned(int, *tl) == 0);
2346 }
2347 m_freem(mrep);
2348 }
2349 /*
2350 * Fill last record, iff any, out to a multiple of NFS_DIRBLKSIZ
2351 * by increasing d_reclen for the last record.
2352 */
2353 if (blksiz > 0) {
2354 left = DIRBLKSIZ - blksiz;
2355 dp->d_reclen += left;
2356 uiop->uio_iov->iov_base += left;
2357 uiop->uio_iov->iov_len -= left;
2358 uiop->uio_offset += left;
2359 uiop->uio_resid -= left;
2360 }
2361
2362 /*
2363 * We are now either at the end of the directory or have filled the
2364 * block.
2365 */
2366 if (bigenough)
2367 dnp->n_direofoffset = uiop->uio_offset;
2368 else {
2369 if (uiop->uio_resid > 0)
2370 printf("EEK! readdirplusrpc resid > 0\n");
2371 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 1);
2372 *cookiep = cookie;
2373 }
2374nfsmout:
2375 if (newvp != NULLVP) {
2376 if (newvp == vp)
2377 vrele(newvp);
2378 else
2379 vput(newvp);
2380 newvp = NULLVP;
2381 }
2382 return (error);
2383}
2384
2385/*
2386 * Silly rename. To make the NFS filesystem that is stateless look a little
2387 * more like the "ufs" a remove of an active vnode is translated to a rename
2388 * to a funny looking filename that is removed by nfs_inactive on the
2389 * nfsnode. There is the potential for another process on a different client
2390 * to create the same funny name between the nfs_lookitup() fails and the
2391 * nfs_rename() completes, but...
2392 */
2393static int
2394nfs_sillyrename(dvp, vp, cnp)
2395 struct vnode *dvp, *vp;
2396 struct componentname *cnp;
2397{
2398 register struct sillyrename *sp;
2399 struct nfsnode *np;
2400 int error;
2401 short pid;
2402
2403 cache_purge(dvp);
2404 np = VTONFS(vp);
2405#ifndef DIAGNOSTIC
2406 if (vp->v_type == VDIR)
2407 panic("nfs: sillyrename dir");
2408#endif
2409 MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename),
2410 M_NFSREQ, M_WAITOK);
2411 sp->s_cred = crdup(cnp->cn_cred);
2412 sp->s_dvp = dvp;
2413 VREF(dvp);
2414
2415 /* Fudge together a funny name */
2416 pid = cnp->cn_proc->p_pid;
2417 sp->s_namlen = sprintf(sp->s_name, ".nfsA%04x4.4", pid);
2418
2419 /* Try lookitups until we get one that isn't there */
2420 while (nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred,
2421 cnp->cn_proc, (struct nfsnode **)0) == 0) {
2422 sp->s_name[4]++;
2423 if (sp->s_name[4] > 'z') {
2424 error = EINVAL;
2425 goto bad;
2426 }
2427 }
2428 error = nfs_renameit(dvp, cnp, sp);
2429 if (error)
2430 goto bad;
2431 error = nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred,
2432 cnp->cn_proc, &np);
2433 np->n_sillyrename = sp;
2434 return (0);
2435bad:
2436 vrele(sp->s_dvp);
2437 crfree(sp->s_cred);
2438 free((caddr_t)sp, M_NFSREQ);
2439 return (error);
2440}
2441
2442/*
2443 * Look up a file name and optionally either update the file handle or
2444 * allocate an nfsnode, depending on the value of npp.
2445 * npp == NULL --> just do the lookup
2446 * *npp == NULL --> allocate a new nfsnode and make sure attributes are
2447 * handled too
2448 * *npp != NULL --> update the file handle in the vnode
2449 */
2450static int
2451nfs_lookitup(dvp, name, len, cred, procp, npp)
2452 register struct vnode *dvp;
2451 char *name;
2453 const char *name;
2452 int len;
2453 struct ucred *cred;
2454 struct proc *procp;
2455 struct nfsnode **npp;
2456{
2457 register u_long *tl;
2458 register caddr_t cp;
2459 register long t1, t2;
2460 struct vnode *newvp = (struct vnode *)0;
2461 struct nfsnode *np, *dnp = VTONFS(dvp);
2462 caddr_t bpos, dpos, cp2;
2463 int error = 0, fhlen, attrflag;
2464 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
2465 nfsfh_t *nfhp;
2466 int v3 = NFS_ISV3(dvp);
2467
2468 nfsstats.rpccnt[NFSPROC_LOOKUP]++;
2469 nfsm_reqhead(dvp, NFSPROC_LOOKUP,
2470 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len));
2471 nfsm_fhtom(dvp, v3);
2472 nfsm_strtom(name, len, NFS_MAXNAMLEN);
2473 nfsm_request(dvp, NFSPROC_LOOKUP, procp, cred);
2474 if (npp && !error) {
2475 nfsm_getfh(nfhp, fhlen, v3);
2476 if (*npp) {
2477 np = *npp;
2478 if (np->n_fhsize > NFS_SMALLFH && fhlen <= NFS_SMALLFH) {
2479 free((caddr_t)np->n_fhp, M_NFSBIGFH);
2480 np->n_fhp = &np->n_fh;
2481 } else if (np->n_fhsize <= NFS_SMALLFH && fhlen>NFS_SMALLFH)
2482 np->n_fhp =(nfsfh_t *)malloc(fhlen,M_NFSBIGFH,M_WAITOK);
2483 bcopy((caddr_t)nfhp, (caddr_t)np->n_fhp, fhlen);
2484 np->n_fhsize = fhlen;
2485 newvp = NFSTOV(np);
2486 } else if (NFS_CMPFH(dnp, nfhp, fhlen)) {
2487 VREF(dvp);
2488 newvp = dvp;
2489 } else {
2490 error = nfs_nget(dvp->v_mount, nfhp, fhlen, &np);
2491 if (error) {
2492 m_freem(mrep);
2493 return (error);
2494 }
2495 newvp = NFSTOV(np);
2496 }
2497 if (v3) {
2498 nfsm_postop_attr(newvp, attrflag);
2499 if (!attrflag && *npp == NULL) {
2500 m_freem(mrep);
2501 if (newvp == dvp)
2502 vrele(newvp);
2503 else
2504 vput(newvp);
2505 return (ENOENT);
2506 }
2507 } else
2508 nfsm_loadattr(newvp, (struct vattr *)0);
2509 }
2510 nfsm_reqdone;
2511 if (npp && *npp == NULL) {
2512 if (error) {
2513 if (newvp)
2514 if (newvp == dvp)
2515 vrele(newvp);
2516 else
2517 vput(newvp);
2518 } else
2519 *npp = np;
2520 }
2521 return (error);
2522}
2523
2524/*
2525 * Nfs Version 3 commit rpc
2526 */
2527static int
2528nfs_commit(vp, offset, cnt, cred, procp)
2529 register struct vnode *vp;
2530 u_quad_t offset;
2531 int cnt;
2532 struct ucred *cred;
2533 struct proc *procp;
2534{
2535 register caddr_t cp;
2536 register u_long *tl;
2537 register int t1, t2;
2538 register 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_state & NFSSTA_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_long *, 3 * NFSX_UNSIGNED);
2549 txdr_hyper(&offset, tl);
2550 tl += 2;
2551 *tl = txdr_unsigned(cnt);
2552 nfsm_request(vp, NFSPROC_COMMIT, procp, cred);
2553 nfsm_wcc_data(vp, wccflag);
2554 if (!error) {
2555 nfsm_dissect(tl, u_long *, 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 * Kludge City..
2569 * - make nfs_bmap() essentially a no-op that does no translation
2570 * - do nfs_strategy() by doing I/O with nfs_readrpc/nfs_writerpc
2571 * (Maybe I could use the process's page mapping, but I was concerned that
2572 * Kernel Write might not be enabled and also figured copyout() would do
2573 * a lot more work than bcopy() and also it currently happens in the
2574 * context of the swapper process (2).
2575 */
2576static int
2577nfs_bmap(ap)
2578 struct vop_bmap_args /* {
2579 struct vnode *a_vp;
2580 daddr_t a_bn;
2581 struct vnode **a_vpp;
2582 daddr_t *a_bnp;
2583 int *a_runp;
2584 int *a_runb;
2585 } */ *ap;
2586{
2587 register struct vnode *vp = ap->a_vp;
2588
2589 if (ap->a_vpp != NULL)
2590 *ap->a_vpp = vp;
2591 if (ap->a_bnp != NULL)
2592 *ap->a_bnp = ap->a_bn * btodb(vp->v_mount->mnt_stat.f_iosize);
2593 if (ap->a_runp != NULL)
2594 *ap->a_runp = 0;
2595 if (ap->a_runb != NULL)
2596 *ap->a_runb = 0;
2597 return (0);
2598}
2599
2600/*
2601 * Strategy routine.
2602 * For async requests when nfsiod(s) are running, queue the request by
2603 * calling nfs_asyncio(), otherwise just all nfs_doio() to do the
2604 * request.
2605 */
2606static int
2607nfs_strategy(ap)
2608 struct vop_strategy_args *ap;
2609{
2610 register struct buf *bp = ap->a_bp;
2611 struct ucred *cr;
2612 struct proc *p;
2613 int error = 0;
2614
2615 if (bp->b_flags & B_PHYS)
2616 panic("nfs physio");
2617 if (bp->b_flags & B_ASYNC)
2618 p = (struct proc *)0;
2619 else
2620 p = curproc; /* XXX */
2621 if (bp->b_flags & B_READ)
2622 cr = bp->b_rcred;
2623 else
2624 cr = bp->b_wcred;
2625 /*
2626 * If the op is asynchronous and an i/o daemon is waiting
2627 * queue the request, wake it up and wait for completion
2628 * otherwise just do it ourselves.
2629 */
2630 if ((bp->b_flags & B_ASYNC) == 0 ||
2631 nfs_asyncio(bp, NOCRED))
2632 error = nfs_doio(bp, cr, p);
2633 return (error);
2634}
2635
2636/*
2637 * Mmap a file
2638 *
2639 * NB Currently unsupported.
2640 */
2641/* ARGSUSED */
2642static int
2643nfs_mmap(ap)
2644 struct vop_mmap_args /* {
2645 struct vnode *a_vp;
2646 int a_fflags;
2647 struct ucred *a_cred;
2648 struct proc *a_p;
2649 } */ *ap;
2650{
2651
2652 return (EINVAL);
2653}
2654
2655/*
2656 * fsync vnode op. Just call nfs_flush() with commit == 1.
2657 */
2658/* ARGSUSED */
2659static int
2660nfs_fsync(ap)
2661 struct vop_fsync_args /* {
2662 struct vnodeop_desc *a_desc;
2663 struct vnode * a_vp;
2664 struct ucred * a_cred;
2665 int a_waitfor;
2666 struct proc * a_p;
2667 } */ *ap;
2668{
2669
2670 return (nfs_flush(ap->a_vp, ap->a_cred, ap->a_waitfor, ap->a_p, 1));
2671}
2672
2673/*
2674 * Flush all the blocks associated with a vnode.
2675 * Walk through the buffer pool and push any dirty pages
2676 * associated with the vnode.
2677 */
2678static int
2679nfs_flush(vp, cred, waitfor, p, commit)
2680 register struct vnode *vp;
2681 struct ucred *cred;
2682 int waitfor;
2683 struct proc *p;
2684 int commit;
2685{
2686 register struct nfsnode *np = VTONFS(vp);
2687 register struct buf *bp;
2688 register int i;
2689 struct buf *nbp;
2690 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2691 int s, error = 0, slptimeo = 0, slpflag = 0, retv, bvecpos;
2692 int passone = 1;
2693 u_quad_t off, endoff, toff;
2694 struct ucred* wcred = NULL;
2695 struct buf **bvec = NULL;
2696#ifndef NFS_COMMITBVECSIZ
2697#define NFS_COMMITBVECSIZ 20
2698#endif
2699 struct buf *bvec_on_stack[NFS_COMMITBVECSIZ];
2700 int bvecsize = 0, bveccount;
2701
2702 if (nmp->nm_flag & NFSMNT_INT)
2703 slpflag = PCATCH;
2704 if (!commit)
2705 passone = 0;
2706 /*
2707 * A b_flags == (B_DELWRI | B_NEEDCOMMIT) block has been written to the
2708 * server, but nas not been committed to stable storage on the server
2709 * yet. On the first pass, the byte range is worked out and the commit
2710 * rpc is done. On the second pass, nfs_writebp() is called to do the
2711 * job.
2712 */
2713again:
2714 off = (u_quad_t)-1;
2715 endoff = 0;
2716 bvecpos = 0;
2717 if (NFS_ISV3(vp) && commit) {
2718 s = splbio();
2719 /*
2720 * Count up how many buffers waiting for a commit.
2721 */
2722 bveccount = 0;
2723 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
2724 nbp = bp->b_vnbufs.le_next;
2725 if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT))
2726 == (B_DELWRI | B_NEEDCOMMIT))
2727 bveccount++;
2728 }
2729 /*
2730 * Allocate space to remember the list of bufs to commit. It is
2731 * important to use M_NOWAIT here to avoid a race with nfs_write.
2732 * If we can't get memory (for whatever reason), we will end up
2733 * committing the buffers one-by-one in the loop below.
2734 */
2735 if (bveccount > NFS_COMMITBVECSIZ) {
2736 if (bvec != NULL && bvec != bvec_on_stack)
2737 free(bvec, M_TEMP);
2738 bvec = (struct buf **)
2739 malloc(bveccount * sizeof(struct buf *),
2740 M_TEMP, M_NOWAIT);
2741 if (bvec == NULL) {
2742 bvec = bvec_on_stack;
2743 bvecsize = NFS_COMMITBVECSIZ;
2744 } else
2745 bvecsize = bveccount;
2746 } else {
2747 bvec = bvec_on_stack;
2748 bvecsize = NFS_COMMITBVECSIZ;
2749 }
2750 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
2751 nbp = bp->b_vnbufs.le_next;
2752 if (bvecpos >= bvecsize)
2753 break;
2754 if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT))
2755 != (B_DELWRI | B_NEEDCOMMIT))
2756 continue;
2757 bremfree(bp);
2758 /*
2759 * Work out if all buffers are using the same cred
2760 * so we can deal with them all with one commit.
2761 */
2762 if (wcred == NULL)
2763 wcred = bp->b_wcred;
2764 else if (wcred != bp->b_wcred)
2765 wcred = NOCRED;
2766 bp->b_flags |= (B_BUSY | B_WRITEINPROG);
2767 vfs_busy_pages(bp, 1);
2768 /*
2769 * A list of these buffers is kept so that the
2770 * second loop knows which buffers have actually
2771 * been committed. This is necessary, since there
2772 * may be a race between the commit rpc and new
2773 * uncommitted writes on the file.
2774 */
2775 bvec[bvecpos++] = bp;
2776 toff = ((u_quad_t)bp->b_blkno) * DEV_BSIZE +
2777 bp->b_dirtyoff;
2778 if (toff < off)
2779 off = toff;
2780 toff += (u_quad_t)(bp->b_dirtyend - bp->b_dirtyoff);
2781 if (toff > endoff)
2782 endoff = toff;
2783 }
2784 splx(s);
2785 }
2786 if (bvecpos > 0) {
2787 /*
2788 * Commit data on the server, as required.
2789 * If all bufs are using the same wcred, then use that with
2790 * one call for all of them, otherwise commit each one
2791 * separately.
2792 */
2793 if (wcred != NOCRED)
2794 retv = nfs_commit(vp, off, (int)(endoff - off),
2795 wcred, p);
2796 else {
2797 retv = 0;
2798 for (i = 0; i < bvecpos; i++) {
2799 off_t off, size;
2800 bp = bvec[i];
2801 off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE +
2802 bp->b_dirtyoff;
2803 size = (u_quad_t)(bp->b_dirtyend
2804 - bp->b_dirtyoff);
2805 retv = nfs_commit(vp, off, (int)size,
2806 bp->b_wcred, p);
2807 if (retv) break;
2808 }
2809 }
2810
2811 if (retv == NFSERR_STALEWRITEVERF)
2812 nfs_clearcommit(vp->v_mount);
2813 /*
2814 * Now, either mark the blocks I/O done or mark the
2815 * blocks dirty, depending on whether the commit
2816 * succeeded.
2817 */
2818 for (i = 0; i < bvecpos; i++) {
2819 bp = bvec[i];
2820 bp->b_flags &= ~(B_NEEDCOMMIT | B_WRITEINPROG);
2821 if (retv) {
2822 vfs_unbusy_pages(bp);
2823 brelse(bp);
2824 } else {
2825 vp->v_numoutput++;
2826 bp->b_flags |= B_ASYNC;
2827 if (bp->b_flags & B_DELWRI) {
2828 --numdirtybuffers;
2829 if (needsbuffer) {
2830 vfs_bio_need_satisfy();
2831 }
2832 }
2833 s = splbio(); /* XXX check this positionning */
2834 bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI);
2835 bp->b_dirtyoff = bp->b_dirtyend = 0;
2836 reassignbuf(bp, vp);
2837 splx(s);
2838 biodone(bp);
2839 }
2840 }
2841 }
2842
2843 /*
2844 * Start/do any write(s) that are required.
2845 */
2846loop:
2847 s = splbio();
2848 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
2849 nbp = bp->b_vnbufs.le_next;
2850 if (bp->b_flags & B_BUSY) {
2851 if (waitfor != MNT_WAIT || passone)
2852 continue;
2853 bp->b_flags |= B_WANTED;
2854 error = tsleep((caddr_t)bp, slpflag | (PRIBIO + 1),
2855 "nfsfsync", slptimeo);
2856 splx(s);
2857 if (error) {
2858 if (nfs_sigintr(nmp, (struct nfsreq *)0, p)) {
2859 error = EINTR;
2860 goto done;
2861 }
2862 if (slpflag == PCATCH) {
2863 slpflag = 0;
2864 slptimeo = 2 * hz;
2865 }
2866 }
2867 goto loop;
2868 }
2869 if ((bp->b_flags & B_DELWRI) == 0)
2870 panic("nfs_fsync: not dirty");
2871 if ((passone || !commit) && (bp->b_flags & B_NEEDCOMMIT))
2872 continue;
2873 bremfree(bp);
2874 if (passone || !commit)
2875 bp->b_flags |= (B_BUSY|B_ASYNC);
2876 else
2877 bp->b_flags |= (B_BUSY|B_ASYNC|B_WRITEINPROG|B_NEEDCOMMIT);
2878 splx(s);
2879 VOP_BWRITE(bp);
2880 goto loop;
2881 }
2882 splx(s);
2883 if (passone) {
2884 passone = 0;
2885 goto again;
2886 }
2887 if (waitfor == MNT_WAIT) {
2888 while (vp->v_numoutput) {
2889 vp->v_flag |= VBWAIT;
2890 error = tsleep((caddr_t)&vp->v_numoutput,
2891 slpflag | (PRIBIO + 1), "nfsfsync", slptimeo);
2892 if (error) {
2893 if (nfs_sigintr(nmp, (struct nfsreq *)0, p)) {
2894 error = EINTR;
2895 goto done;
2896 }
2897 if (slpflag == PCATCH) {
2898 slpflag = 0;
2899 slptimeo = 2 * hz;
2900 }
2901 }
2902 }
2903 if (vp->v_dirtyblkhd.lh_first && commit) {
2904 goto loop;
2905 }
2906 }
2907 if (np->n_flag & NWRITEERR) {
2908 error = np->n_error;
2909 np->n_flag &= ~NWRITEERR;
2910 }
2911done:
2912 if (bvec != NULL && bvec != bvec_on_stack)
2913 free(bvec, M_TEMP);
2914 return (error);
2915}
2916
2917/*
2918 * NFS advisory byte-level locks.
2919 * Currently unsupported.
2920 */
2921static int
2922nfs_advlock(ap)
2923 struct vop_advlock_args /* {
2924 struct vnode *a_vp;
2925 caddr_t a_id;
2926 int a_op;
2927 struct flock *a_fl;
2928 int a_flags;
2929 } */ *ap;
2930{
2931 register struct nfsnode *np = VTONFS(ap->a_vp);
2932
2933 /*
2934 * The following kludge is to allow diskless support to work
2935 * until a real NFS lockd is implemented. Basically, just pretend
2936 * that this is a local lock.
2937 */
2938 return (lf_advlock(ap, &(np->n_lockf), np->n_size));
2939}
2940
2941/*
2942 * Print out the contents of an nfsnode.
2943 */
2944static int
2945nfs_print(ap)
2946 struct vop_print_args /* {
2947 struct vnode *a_vp;
2948 } */ *ap;
2949{
2950 register struct vnode *vp = ap->a_vp;
2951 register struct nfsnode *np = VTONFS(vp);
2952
2953 printf("tag VT_NFS, fileid %ld fsid 0x%lx",
2954 np->n_vattr.va_fileid, np->n_vattr.va_fsid);
2955 if (vp->v_type == VFIFO)
2956 fifo_printinfo(vp);
2957 printf("\n");
2958 return (0);
2959}
2960
2961/*
2962 * Just call nfs_writebp() with the force argument set to 1.
2963 */
2964static int
2965nfs_bwrite(ap)
2966 struct vop_bwrite_args /* {
2967 struct vnode *a_bp;
2968 } */ *ap;
2969{
2970
2971 return (nfs_writebp(ap->a_bp, 1));
2972}
2973
2974/*
2975 * This is a clone of vn_bwrite(), except that B_WRITEINPROG isn't set unless
2976 * the force flag is one and it also handles the B_NEEDCOMMIT flag.
2977 */
2978int
2979nfs_writebp(bp, force)
2980 register struct buf *bp;
2981 int force;
2982{
2983 int s;
2984 register int oldflags = bp->b_flags, retv = 1;
2985 off_t off;
2986
2987 if(!(bp->b_flags & B_BUSY))
2988 panic("bwrite: buffer is not busy???");
2989
2990 if (bp->b_flags & B_INVAL)
2991 bp->b_flags |= B_INVAL | B_NOCACHE;
2992
2993 if (bp->b_flags & B_DELWRI) {
2994 --numdirtybuffers;
2995 if (needsbuffer)
2996 vfs_bio_need_satisfy();
2997 }
2998 s = splbio(); /* XXX check if needed */
2999 bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI);
3000
3001 if ((oldflags & (B_ASYNC|B_DELWRI)) == (B_ASYNC|B_DELWRI)) {
3002 reassignbuf(bp, bp->b_vp);
3003 }
3004
3005 bp->b_vp->v_numoutput++;
3006 curproc->p_stats->p_ru.ru_oublock++;
3007 splx(s);
3008
3009 /*
3010 * If B_NEEDCOMMIT is set, a commit rpc may do the trick. If not
3011 * an actual write will have to be scheduled via. VOP_STRATEGY().
3012 * If B_WRITEINPROG is already set, then push it with a write anyhow.
3013 */
3014 vfs_busy_pages(bp, 1);
3015 if ((oldflags & (B_NEEDCOMMIT | B_WRITEINPROG)) == B_NEEDCOMMIT) {
3016 off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + bp->b_dirtyoff;
3017 bp->b_flags |= B_WRITEINPROG;
3018 retv = nfs_commit(bp->b_vp, off, bp->b_dirtyend-bp->b_dirtyoff,
3019 bp->b_wcred, bp->b_proc);
3020 bp->b_flags &= ~B_WRITEINPROG;
3021 if (!retv) {
3022 bp->b_dirtyoff = bp->b_dirtyend = 0;
3023 bp->b_flags &= ~B_NEEDCOMMIT;
3024 biodone(bp);
3025 } else if (retv == NFSERR_STALEWRITEVERF)
3026 nfs_clearcommit(bp->b_vp->v_mount);
3027 }
3028 if (retv) {
3029 if (force)
3030 bp->b_flags |= B_WRITEINPROG;
3031 VOP_STRATEGY(bp);
3032 }
3033
3034 if( (oldflags & B_ASYNC) == 0) {
3035 int rtval = biowait(bp);
3036
3037 if (oldflags & B_DELWRI) {
3038 s = splbio();
3039 reassignbuf(bp, bp->b_vp);
3040 splx(s);
3041 }
3042
3043 brelse(bp);
3044 return (rtval);
3045 }
3046
3047 return (0);
3048}
3049
3050/*
3051 * nfs special file access vnode op.
3052 * Essentially just get vattr and then imitate iaccess() since the device is
3053 * local to the client.
3054 */
3055static int
3056nfsspec_access(ap)
3057 struct vop_access_args /* {
3058 struct vnode *a_vp;
3059 int a_mode;
3060 struct ucred *a_cred;
3061 struct proc *a_p;
3062 } */ *ap;
3063{
3064 register struct vattr *vap;
3065 register gid_t *gp;
3066 register struct ucred *cred = ap->a_cred;
3067 struct vnode *vp = ap->a_vp;
3068 mode_t mode = ap->a_mode;
3069 struct vattr vattr;
3070 register int i;
3071 int error;
3072
3073 /*
3074 * Disallow write attempts on filesystems mounted read-only;
3075 * unless the file is a socket, fifo, or a block or character
3076 * device resident on the filesystem.
3077 */
3078 if ((mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
3079 switch (vp->v_type) {
3080 case VREG:
3081 case VDIR:
3082 case VLNK:
3083 return (EROFS);
3084 default:
3085 break;
3086 }
3087 }
3088 /*
3089 * If you're the super-user,
3090 * you always get access.
3091 */
3092 if (cred->cr_uid == 0)
3093 return (0);
3094 vap = &vattr;
3095 error = VOP_GETATTR(vp, vap, cred, ap->a_p);
3096 if (error)
3097 return (error);
3098 /*
3099 * Access check is based on only one of owner, group, public.
3100 * If not owner, then check group. If not a member of the
3101 * group, then check public access.
3102 */
3103 if (cred->cr_uid != vap->va_uid) {
3104 mode >>= 3;
3105 gp = cred->cr_groups;
3106 for (i = 0; i < cred->cr_ngroups; i++, gp++)
3107 if (vap->va_gid == *gp)
3108 goto found;
3109 mode >>= 3;
3110found:
3111 ;
3112 }
3113 error = (vap->va_mode & mode) == mode ? 0 : EACCES;
3114 return (error);
3115}
3116
3117/*
3118 * Read wrapper for special devices.
3119 */
3120static int
3121nfsspec_read(ap)
3122 struct vop_read_args /* {
3123 struct vnode *a_vp;
3124 struct uio *a_uio;
3125 int a_ioflag;
3126 struct ucred *a_cred;
3127 } */ *ap;
3128{
3129 register struct nfsnode *np = VTONFS(ap->a_vp);
3130
3131 /*
3132 * Set access flag.
3133 */
3134 np->n_flag |= NACC;
3135 getnanotime(&np->n_atim);
3136 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap));
3137}
3138
3139/*
3140 * Write wrapper for special devices.
3141 */
3142static int
3143nfsspec_write(ap)
3144 struct vop_write_args /* {
3145 struct vnode *a_vp;
3146 struct uio *a_uio;
3147 int a_ioflag;
3148 struct ucred *a_cred;
3149 } */ *ap;
3150{
3151 register struct nfsnode *np = VTONFS(ap->a_vp);
3152
3153 /*
3154 * Set update flag.
3155 */
3156 np->n_flag |= NUPD;
3157 getnanotime(&np->n_mtim);
3158 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap));
3159}
3160
3161/*
3162 * Close wrapper for special devices.
3163 *
3164 * Update the times on the nfsnode then do device close.
3165 */
3166static int
3167nfsspec_close(ap)
3168 struct vop_close_args /* {
3169 struct vnode *a_vp;
3170 int a_fflag;
3171 struct ucred *a_cred;
3172 struct proc *a_p;
3173 } */ *ap;
3174{
3175 register struct vnode *vp = ap->a_vp;
3176 register struct nfsnode *np = VTONFS(vp);
3177 struct vattr vattr;
3178
3179 if (np->n_flag & (NACC | NUPD)) {
3180 np->n_flag |= NCHG;
3181 if (vp->v_usecount == 1 &&
3182 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
3183 VATTR_NULL(&vattr);
3184 if (np->n_flag & NACC)
3185 vattr.va_atime = np->n_atim;
3186 if (np->n_flag & NUPD)
3187 vattr.va_mtime = np->n_mtim;
3188 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p);
3189 }
3190 }
3191 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap));
3192}
3193
3194/*
3195 * Read wrapper for fifos.
3196 */
3197static int
3198nfsfifo_read(ap)
3199 struct vop_read_args /* {
3200 struct vnode *a_vp;
3201 struct uio *a_uio;
3202 int a_ioflag;
3203 struct ucred *a_cred;
3204 } */ *ap;
3205{
3206 register struct nfsnode *np = VTONFS(ap->a_vp);
3207
3208 /*
3209 * Set access flag.
3210 */
3211 np->n_flag |= NACC;
3212 getnanotime(&np->n_atim);
3213 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap));
3214}
3215
3216/*
3217 * Write wrapper for fifos.
3218 */
3219static int
3220nfsfifo_write(ap)
3221 struct vop_write_args /* {
3222 struct vnode *a_vp;
3223 struct uio *a_uio;
3224 int a_ioflag;
3225 struct ucred *a_cred;
3226 } */ *ap;
3227{
3228 register struct nfsnode *np = VTONFS(ap->a_vp);
3229
3230 /*
3231 * Set update flag.
3232 */
3233 np->n_flag |= NUPD;
3234 getnanotime(&np->n_mtim);
3235 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap));
3236}
3237
3238/*
3239 * Close wrapper for fifos.
3240 *
3241 * Update the times on the nfsnode then do fifo close.
3242 */
3243static int
3244nfsfifo_close(ap)
3245 struct vop_close_args /* {
3246 struct vnode *a_vp;
3247 int a_fflag;
3248 struct ucred *a_cred;
3249 struct proc *a_p;
3250 } */ *ap;
3251{
3252 register struct vnode *vp = ap->a_vp;
3253 register struct nfsnode *np = VTONFS(vp);
3254 struct vattr vattr;
3255 struct timespec ts;
3256
3257 if (np->n_flag & (NACC | NUPD)) {
3258 getnanotime(&ts);
3259 if (np->n_flag & NACC)
3260 np->n_atim = ts;
3261 if (np->n_flag & NUPD)
3262 np->n_mtim = ts;
3263 np->n_flag |= NCHG;
3264 if (vp->v_usecount == 1 &&
3265 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
3266 VATTR_NULL(&vattr);
3267 if (np->n_flag & NACC)
3268 vattr.va_atime = np->n_atim;
3269 if (np->n_flag & NUPD)
3270 vattr.va_mtime = np->n_mtim;
3271 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p);
3272 }
3273 }
3274 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap));
3275}
2454 int len;
2455 struct ucred *cred;
2456 struct proc *procp;
2457 struct nfsnode **npp;
2458{
2459 register u_long *tl;
2460 register caddr_t cp;
2461 register long t1, t2;
2462 struct vnode *newvp = (struct vnode *)0;
2463 struct nfsnode *np, *dnp = VTONFS(dvp);
2464 caddr_t bpos, dpos, cp2;
2465 int error = 0, fhlen, attrflag;
2466 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
2467 nfsfh_t *nfhp;
2468 int v3 = NFS_ISV3(dvp);
2469
2470 nfsstats.rpccnt[NFSPROC_LOOKUP]++;
2471 nfsm_reqhead(dvp, NFSPROC_LOOKUP,
2472 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len));
2473 nfsm_fhtom(dvp, v3);
2474 nfsm_strtom(name, len, NFS_MAXNAMLEN);
2475 nfsm_request(dvp, NFSPROC_LOOKUP, procp, cred);
2476 if (npp && !error) {
2477 nfsm_getfh(nfhp, fhlen, v3);
2478 if (*npp) {
2479 np = *npp;
2480 if (np->n_fhsize > NFS_SMALLFH && fhlen <= NFS_SMALLFH) {
2481 free((caddr_t)np->n_fhp, M_NFSBIGFH);
2482 np->n_fhp = &np->n_fh;
2483 } else if (np->n_fhsize <= NFS_SMALLFH && fhlen>NFS_SMALLFH)
2484 np->n_fhp =(nfsfh_t *)malloc(fhlen,M_NFSBIGFH,M_WAITOK);
2485 bcopy((caddr_t)nfhp, (caddr_t)np->n_fhp, fhlen);
2486 np->n_fhsize = fhlen;
2487 newvp = NFSTOV(np);
2488 } else if (NFS_CMPFH(dnp, nfhp, fhlen)) {
2489 VREF(dvp);
2490 newvp = dvp;
2491 } else {
2492 error = nfs_nget(dvp->v_mount, nfhp, fhlen, &np);
2493 if (error) {
2494 m_freem(mrep);
2495 return (error);
2496 }
2497 newvp = NFSTOV(np);
2498 }
2499 if (v3) {
2500 nfsm_postop_attr(newvp, attrflag);
2501 if (!attrflag && *npp == NULL) {
2502 m_freem(mrep);
2503 if (newvp == dvp)
2504 vrele(newvp);
2505 else
2506 vput(newvp);
2507 return (ENOENT);
2508 }
2509 } else
2510 nfsm_loadattr(newvp, (struct vattr *)0);
2511 }
2512 nfsm_reqdone;
2513 if (npp && *npp == NULL) {
2514 if (error) {
2515 if (newvp)
2516 if (newvp == dvp)
2517 vrele(newvp);
2518 else
2519 vput(newvp);
2520 } else
2521 *npp = np;
2522 }
2523 return (error);
2524}
2525
2526/*
2527 * Nfs Version 3 commit rpc
2528 */
2529static int
2530nfs_commit(vp, offset, cnt, cred, procp)
2531 register struct vnode *vp;
2532 u_quad_t offset;
2533 int cnt;
2534 struct ucred *cred;
2535 struct proc *procp;
2536{
2537 register caddr_t cp;
2538 register u_long *tl;
2539 register int t1, t2;
2540 register struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2541 caddr_t bpos, dpos, cp2;
2542 int error = 0, wccflag = NFSV3_WCCRATTR;
2543 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
2544
2545 if ((nmp->nm_state & NFSSTA_HASWRITEVERF) == 0)
2546 return (0);
2547 nfsstats.rpccnt[NFSPROC_COMMIT]++;
2548 nfsm_reqhead(vp, NFSPROC_COMMIT, NFSX_FH(1));
2549 nfsm_fhtom(vp, 1);
2550 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED);
2551 txdr_hyper(&offset, tl);
2552 tl += 2;
2553 *tl = txdr_unsigned(cnt);
2554 nfsm_request(vp, NFSPROC_COMMIT, procp, cred);
2555 nfsm_wcc_data(vp, wccflag);
2556 if (!error) {
2557 nfsm_dissect(tl, u_long *, NFSX_V3WRITEVERF);
2558 if (bcmp((caddr_t)nmp->nm_verf, (caddr_t)tl,
2559 NFSX_V3WRITEVERF)) {
2560 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf,
2561 NFSX_V3WRITEVERF);
2562 error = NFSERR_STALEWRITEVERF;
2563 }
2564 }
2565 nfsm_reqdone;
2566 return (error);
2567}
2568
2569/*
2570 * Kludge City..
2571 * - make nfs_bmap() essentially a no-op that does no translation
2572 * - do nfs_strategy() by doing I/O with nfs_readrpc/nfs_writerpc
2573 * (Maybe I could use the process's page mapping, but I was concerned that
2574 * Kernel Write might not be enabled and also figured copyout() would do
2575 * a lot more work than bcopy() and also it currently happens in the
2576 * context of the swapper process (2).
2577 */
2578static int
2579nfs_bmap(ap)
2580 struct vop_bmap_args /* {
2581 struct vnode *a_vp;
2582 daddr_t a_bn;
2583 struct vnode **a_vpp;
2584 daddr_t *a_bnp;
2585 int *a_runp;
2586 int *a_runb;
2587 } */ *ap;
2588{
2589 register struct vnode *vp = ap->a_vp;
2590
2591 if (ap->a_vpp != NULL)
2592 *ap->a_vpp = vp;
2593 if (ap->a_bnp != NULL)
2594 *ap->a_bnp = ap->a_bn * btodb(vp->v_mount->mnt_stat.f_iosize);
2595 if (ap->a_runp != NULL)
2596 *ap->a_runp = 0;
2597 if (ap->a_runb != NULL)
2598 *ap->a_runb = 0;
2599 return (0);
2600}
2601
2602/*
2603 * Strategy routine.
2604 * For async requests when nfsiod(s) are running, queue the request by
2605 * calling nfs_asyncio(), otherwise just all nfs_doio() to do the
2606 * request.
2607 */
2608static int
2609nfs_strategy(ap)
2610 struct vop_strategy_args *ap;
2611{
2612 register struct buf *bp = ap->a_bp;
2613 struct ucred *cr;
2614 struct proc *p;
2615 int error = 0;
2616
2617 if (bp->b_flags & B_PHYS)
2618 panic("nfs physio");
2619 if (bp->b_flags & B_ASYNC)
2620 p = (struct proc *)0;
2621 else
2622 p = curproc; /* XXX */
2623 if (bp->b_flags & B_READ)
2624 cr = bp->b_rcred;
2625 else
2626 cr = bp->b_wcred;
2627 /*
2628 * If the op is asynchronous and an i/o daemon is waiting
2629 * queue the request, wake it up and wait for completion
2630 * otherwise just do it ourselves.
2631 */
2632 if ((bp->b_flags & B_ASYNC) == 0 ||
2633 nfs_asyncio(bp, NOCRED))
2634 error = nfs_doio(bp, cr, p);
2635 return (error);
2636}
2637
2638/*
2639 * Mmap a file
2640 *
2641 * NB Currently unsupported.
2642 */
2643/* ARGSUSED */
2644static int
2645nfs_mmap(ap)
2646 struct vop_mmap_args /* {
2647 struct vnode *a_vp;
2648 int a_fflags;
2649 struct ucred *a_cred;
2650 struct proc *a_p;
2651 } */ *ap;
2652{
2653
2654 return (EINVAL);
2655}
2656
2657/*
2658 * fsync vnode op. Just call nfs_flush() with commit == 1.
2659 */
2660/* ARGSUSED */
2661static int
2662nfs_fsync(ap)
2663 struct vop_fsync_args /* {
2664 struct vnodeop_desc *a_desc;
2665 struct vnode * a_vp;
2666 struct ucred * a_cred;
2667 int a_waitfor;
2668 struct proc * a_p;
2669 } */ *ap;
2670{
2671
2672 return (nfs_flush(ap->a_vp, ap->a_cred, ap->a_waitfor, ap->a_p, 1));
2673}
2674
2675/*
2676 * Flush all the blocks associated with a vnode.
2677 * Walk through the buffer pool and push any dirty pages
2678 * associated with the vnode.
2679 */
2680static int
2681nfs_flush(vp, cred, waitfor, p, commit)
2682 register struct vnode *vp;
2683 struct ucred *cred;
2684 int waitfor;
2685 struct proc *p;
2686 int commit;
2687{
2688 register struct nfsnode *np = VTONFS(vp);
2689 register struct buf *bp;
2690 register int i;
2691 struct buf *nbp;
2692 struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2693 int s, error = 0, slptimeo = 0, slpflag = 0, retv, bvecpos;
2694 int passone = 1;
2695 u_quad_t off, endoff, toff;
2696 struct ucred* wcred = NULL;
2697 struct buf **bvec = NULL;
2698#ifndef NFS_COMMITBVECSIZ
2699#define NFS_COMMITBVECSIZ 20
2700#endif
2701 struct buf *bvec_on_stack[NFS_COMMITBVECSIZ];
2702 int bvecsize = 0, bveccount;
2703
2704 if (nmp->nm_flag & NFSMNT_INT)
2705 slpflag = PCATCH;
2706 if (!commit)
2707 passone = 0;
2708 /*
2709 * A b_flags == (B_DELWRI | B_NEEDCOMMIT) block has been written to the
2710 * server, but nas not been committed to stable storage on the server
2711 * yet. On the first pass, the byte range is worked out and the commit
2712 * rpc is done. On the second pass, nfs_writebp() is called to do the
2713 * job.
2714 */
2715again:
2716 off = (u_quad_t)-1;
2717 endoff = 0;
2718 bvecpos = 0;
2719 if (NFS_ISV3(vp) && commit) {
2720 s = splbio();
2721 /*
2722 * Count up how many buffers waiting for a commit.
2723 */
2724 bveccount = 0;
2725 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
2726 nbp = bp->b_vnbufs.le_next;
2727 if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT))
2728 == (B_DELWRI | B_NEEDCOMMIT))
2729 bveccount++;
2730 }
2731 /*
2732 * Allocate space to remember the list of bufs to commit. It is
2733 * important to use M_NOWAIT here to avoid a race with nfs_write.
2734 * If we can't get memory (for whatever reason), we will end up
2735 * committing the buffers one-by-one in the loop below.
2736 */
2737 if (bveccount > NFS_COMMITBVECSIZ) {
2738 if (bvec != NULL && bvec != bvec_on_stack)
2739 free(bvec, M_TEMP);
2740 bvec = (struct buf **)
2741 malloc(bveccount * sizeof(struct buf *),
2742 M_TEMP, M_NOWAIT);
2743 if (bvec == NULL) {
2744 bvec = bvec_on_stack;
2745 bvecsize = NFS_COMMITBVECSIZ;
2746 } else
2747 bvecsize = bveccount;
2748 } else {
2749 bvec = bvec_on_stack;
2750 bvecsize = NFS_COMMITBVECSIZ;
2751 }
2752 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
2753 nbp = bp->b_vnbufs.le_next;
2754 if (bvecpos >= bvecsize)
2755 break;
2756 if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT))
2757 != (B_DELWRI | B_NEEDCOMMIT))
2758 continue;
2759 bremfree(bp);
2760 /*
2761 * Work out if all buffers are using the same cred
2762 * so we can deal with them all with one commit.
2763 */
2764 if (wcred == NULL)
2765 wcred = bp->b_wcred;
2766 else if (wcred != bp->b_wcred)
2767 wcred = NOCRED;
2768 bp->b_flags |= (B_BUSY | B_WRITEINPROG);
2769 vfs_busy_pages(bp, 1);
2770 /*
2771 * A list of these buffers is kept so that the
2772 * second loop knows which buffers have actually
2773 * been committed. This is necessary, since there
2774 * may be a race between the commit rpc and new
2775 * uncommitted writes on the file.
2776 */
2777 bvec[bvecpos++] = bp;
2778 toff = ((u_quad_t)bp->b_blkno) * DEV_BSIZE +
2779 bp->b_dirtyoff;
2780 if (toff < off)
2781 off = toff;
2782 toff += (u_quad_t)(bp->b_dirtyend - bp->b_dirtyoff);
2783 if (toff > endoff)
2784 endoff = toff;
2785 }
2786 splx(s);
2787 }
2788 if (bvecpos > 0) {
2789 /*
2790 * Commit data on the server, as required.
2791 * If all bufs are using the same wcred, then use that with
2792 * one call for all of them, otherwise commit each one
2793 * separately.
2794 */
2795 if (wcred != NOCRED)
2796 retv = nfs_commit(vp, off, (int)(endoff - off),
2797 wcred, p);
2798 else {
2799 retv = 0;
2800 for (i = 0; i < bvecpos; i++) {
2801 off_t off, size;
2802 bp = bvec[i];
2803 off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE +
2804 bp->b_dirtyoff;
2805 size = (u_quad_t)(bp->b_dirtyend
2806 - bp->b_dirtyoff);
2807 retv = nfs_commit(vp, off, (int)size,
2808 bp->b_wcred, p);
2809 if (retv) break;
2810 }
2811 }
2812
2813 if (retv == NFSERR_STALEWRITEVERF)
2814 nfs_clearcommit(vp->v_mount);
2815 /*
2816 * Now, either mark the blocks I/O done or mark the
2817 * blocks dirty, depending on whether the commit
2818 * succeeded.
2819 */
2820 for (i = 0; i < bvecpos; i++) {
2821 bp = bvec[i];
2822 bp->b_flags &= ~(B_NEEDCOMMIT | B_WRITEINPROG);
2823 if (retv) {
2824 vfs_unbusy_pages(bp);
2825 brelse(bp);
2826 } else {
2827 vp->v_numoutput++;
2828 bp->b_flags |= B_ASYNC;
2829 if (bp->b_flags & B_DELWRI) {
2830 --numdirtybuffers;
2831 if (needsbuffer) {
2832 vfs_bio_need_satisfy();
2833 }
2834 }
2835 s = splbio(); /* XXX check this positionning */
2836 bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI);
2837 bp->b_dirtyoff = bp->b_dirtyend = 0;
2838 reassignbuf(bp, vp);
2839 splx(s);
2840 biodone(bp);
2841 }
2842 }
2843 }
2844
2845 /*
2846 * Start/do any write(s) that are required.
2847 */
2848loop:
2849 s = splbio();
2850 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
2851 nbp = bp->b_vnbufs.le_next;
2852 if (bp->b_flags & B_BUSY) {
2853 if (waitfor != MNT_WAIT || passone)
2854 continue;
2855 bp->b_flags |= B_WANTED;
2856 error = tsleep((caddr_t)bp, slpflag | (PRIBIO + 1),
2857 "nfsfsync", slptimeo);
2858 splx(s);
2859 if (error) {
2860 if (nfs_sigintr(nmp, (struct nfsreq *)0, p)) {
2861 error = EINTR;
2862 goto done;
2863 }
2864 if (slpflag == PCATCH) {
2865 slpflag = 0;
2866 slptimeo = 2 * hz;
2867 }
2868 }
2869 goto loop;
2870 }
2871 if ((bp->b_flags & B_DELWRI) == 0)
2872 panic("nfs_fsync: not dirty");
2873 if ((passone || !commit) && (bp->b_flags & B_NEEDCOMMIT))
2874 continue;
2875 bremfree(bp);
2876 if (passone || !commit)
2877 bp->b_flags |= (B_BUSY|B_ASYNC);
2878 else
2879 bp->b_flags |= (B_BUSY|B_ASYNC|B_WRITEINPROG|B_NEEDCOMMIT);
2880 splx(s);
2881 VOP_BWRITE(bp);
2882 goto loop;
2883 }
2884 splx(s);
2885 if (passone) {
2886 passone = 0;
2887 goto again;
2888 }
2889 if (waitfor == MNT_WAIT) {
2890 while (vp->v_numoutput) {
2891 vp->v_flag |= VBWAIT;
2892 error = tsleep((caddr_t)&vp->v_numoutput,
2893 slpflag | (PRIBIO + 1), "nfsfsync", slptimeo);
2894 if (error) {
2895 if (nfs_sigintr(nmp, (struct nfsreq *)0, p)) {
2896 error = EINTR;
2897 goto done;
2898 }
2899 if (slpflag == PCATCH) {
2900 slpflag = 0;
2901 slptimeo = 2 * hz;
2902 }
2903 }
2904 }
2905 if (vp->v_dirtyblkhd.lh_first && commit) {
2906 goto loop;
2907 }
2908 }
2909 if (np->n_flag & NWRITEERR) {
2910 error = np->n_error;
2911 np->n_flag &= ~NWRITEERR;
2912 }
2913done:
2914 if (bvec != NULL && bvec != bvec_on_stack)
2915 free(bvec, M_TEMP);
2916 return (error);
2917}
2918
2919/*
2920 * NFS advisory byte-level locks.
2921 * Currently unsupported.
2922 */
2923static int
2924nfs_advlock(ap)
2925 struct vop_advlock_args /* {
2926 struct vnode *a_vp;
2927 caddr_t a_id;
2928 int a_op;
2929 struct flock *a_fl;
2930 int a_flags;
2931 } */ *ap;
2932{
2933 register struct nfsnode *np = VTONFS(ap->a_vp);
2934
2935 /*
2936 * The following kludge is to allow diskless support to work
2937 * until a real NFS lockd is implemented. Basically, just pretend
2938 * that this is a local lock.
2939 */
2940 return (lf_advlock(ap, &(np->n_lockf), np->n_size));
2941}
2942
2943/*
2944 * Print out the contents of an nfsnode.
2945 */
2946static int
2947nfs_print(ap)
2948 struct vop_print_args /* {
2949 struct vnode *a_vp;
2950 } */ *ap;
2951{
2952 register struct vnode *vp = ap->a_vp;
2953 register struct nfsnode *np = VTONFS(vp);
2954
2955 printf("tag VT_NFS, fileid %ld fsid 0x%lx",
2956 np->n_vattr.va_fileid, np->n_vattr.va_fsid);
2957 if (vp->v_type == VFIFO)
2958 fifo_printinfo(vp);
2959 printf("\n");
2960 return (0);
2961}
2962
2963/*
2964 * Just call nfs_writebp() with the force argument set to 1.
2965 */
2966static int
2967nfs_bwrite(ap)
2968 struct vop_bwrite_args /* {
2969 struct vnode *a_bp;
2970 } */ *ap;
2971{
2972
2973 return (nfs_writebp(ap->a_bp, 1));
2974}
2975
2976/*
2977 * This is a clone of vn_bwrite(), except that B_WRITEINPROG isn't set unless
2978 * the force flag is one and it also handles the B_NEEDCOMMIT flag.
2979 */
2980int
2981nfs_writebp(bp, force)
2982 register struct buf *bp;
2983 int force;
2984{
2985 int s;
2986 register int oldflags = bp->b_flags, retv = 1;
2987 off_t off;
2988
2989 if(!(bp->b_flags & B_BUSY))
2990 panic("bwrite: buffer is not busy???");
2991
2992 if (bp->b_flags & B_INVAL)
2993 bp->b_flags |= B_INVAL | B_NOCACHE;
2994
2995 if (bp->b_flags & B_DELWRI) {
2996 --numdirtybuffers;
2997 if (needsbuffer)
2998 vfs_bio_need_satisfy();
2999 }
3000 s = splbio(); /* XXX check if needed */
3001 bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI);
3002
3003 if ((oldflags & (B_ASYNC|B_DELWRI)) == (B_ASYNC|B_DELWRI)) {
3004 reassignbuf(bp, bp->b_vp);
3005 }
3006
3007 bp->b_vp->v_numoutput++;
3008 curproc->p_stats->p_ru.ru_oublock++;
3009 splx(s);
3010
3011 /*
3012 * If B_NEEDCOMMIT is set, a commit rpc may do the trick. If not
3013 * an actual write will have to be scheduled via. VOP_STRATEGY().
3014 * If B_WRITEINPROG is already set, then push it with a write anyhow.
3015 */
3016 vfs_busy_pages(bp, 1);
3017 if ((oldflags & (B_NEEDCOMMIT | B_WRITEINPROG)) == B_NEEDCOMMIT) {
3018 off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + bp->b_dirtyoff;
3019 bp->b_flags |= B_WRITEINPROG;
3020 retv = nfs_commit(bp->b_vp, off, bp->b_dirtyend-bp->b_dirtyoff,
3021 bp->b_wcred, bp->b_proc);
3022 bp->b_flags &= ~B_WRITEINPROG;
3023 if (!retv) {
3024 bp->b_dirtyoff = bp->b_dirtyend = 0;
3025 bp->b_flags &= ~B_NEEDCOMMIT;
3026 biodone(bp);
3027 } else if (retv == NFSERR_STALEWRITEVERF)
3028 nfs_clearcommit(bp->b_vp->v_mount);
3029 }
3030 if (retv) {
3031 if (force)
3032 bp->b_flags |= B_WRITEINPROG;
3033 VOP_STRATEGY(bp);
3034 }
3035
3036 if( (oldflags & B_ASYNC) == 0) {
3037 int rtval = biowait(bp);
3038
3039 if (oldflags & B_DELWRI) {
3040 s = splbio();
3041 reassignbuf(bp, bp->b_vp);
3042 splx(s);
3043 }
3044
3045 brelse(bp);
3046 return (rtval);
3047 }
3048
3049 return (0);
3050}
3051
3052/*
3053 * nfs special file access vnode op.
3054 * Essentially just get vattr and then imitate iaccess() since the device is
3055 * local to the client.
3056 */
3057static int
3058nfsspec_access(ap)
3059 struct vop_access_args /* {
3060 struct vnode *a_vp;
3061 int a_mode;
3062 struct ucred *a_cred;
3063 struct proc *a_p;
3064 } */ *ap;
3065{
3066 register struct vattr *vap;
3067 register gid_t *gp;
3068 register struct ucred *cred = ap->a_cred;
3069 struct vnode *vp = ap->a_vp;
3070 mode_t mode = ap->a_mode;
3071 struct vattr vattr;
3072 register int i;
3073 int error;
3074
3075 /*
3076 * Disallow write attempts on filesystems mounted read-only;
3077 * unless the file is a socket, fifo, or a block or character
3078 * device resident on the filesystem.
3079 */
3080 if ((mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
3081 switch (vp->v_type) {
3082 case VREG:
3083 case VDIR:
3084 case VLNK:
3085 return (EROFS);
3086 default:
3087 break;
3088 }
3089 }
3090 /*
3091 * If you're the super-user,
3092 * you always get access.
3093 */
3094 if (cred->cr_uid == 0)
3095 return (0);
3096 vap = &vattr;
3097 error = VOP_GETATTR(vp, vap, cred, ap->a_p);
3098 if (error)
3099 return (error);
3100 /*
3101 * Access check is based on only one of owner, group, public.
3102 * If not owner, then check group. If not a member of the
3103 * group, then check public access.
3104 */
3105 if (cred->cr_uid != vap->va_uid) {
3106 mode >>= 3;
3107 gp = cred->cr_groups;
3108 for (i = 0; i < cred->cr_ngroups; i++, gp++)
3109 if (vap->va_gid == *gp)
3110 goto found;
3111 mode >>= 3;
3112found:
3113 ;
3114 }
3115 error = (vap->va_mode & mode) == mode ? 0 : EACCES;
3116 return (error);
3117}
3118
3119/*
3120 * Read wrapper for special devices.
3121 */
3122static int
3123nfsspec_read(ap)
3124 struct vop_read_args /* {
3125 struct vnode *a_vp;
3126 struct uio *a_uio;
3127 int a_ioflag;
3128 struct ucred *a_cred;
3129 } */ *ap;
3130{
3131 register struct nfsnode *np = VTONFS(ap->a_vp);
3132
3133 /*
3134 * Set access flag.
3135 */
3136 np->n_flag |= NACC;
3137 getnanotime(&np->n_atim);
3138 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap));
3139}
3140
3141/*
3142 * Write wrapper for special devices.
3143 */
3144static int
3145nfsspec_write(ap)
3146 struct vop_write_args /* {
3147 struct vnode *a_vp;
3148 struct uio *a_uio;
3149 int a_ioflag;
3150 struct ucred *a_cred;
3151 } */ *ap;
3152{
3153 register struct nfsnode *np = VTONFS(ap->a_vp);
3154
3155 /*
3156 * Set update flag.
3157 */
3158 np->n_flag |= NUPD;
3159 getnanotime(&np->n_mtim);
3160 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap));
3161}
3162
3163/*
3164 * Close wrapper for special devices.
3165 *
3166 * Update the times on the nfsnode then do device close.
3167 */
3168static int
3169nfsspec_close(ap)
3170 struct vop_close_args /* {
3171 struct vnode *a_vp;
3172 int a_fflag;
3173 struct ucred *a_cred;
3174 struct proc *a_p;
3175 } */ *ap;
3176{
3177 register struct vnode *vp = ap->a_vp;
3178 register struct nfsnode *np = VTONFS(vp);
3179 struct vattr vattr;
3180
3181 if (np->n_flag & (NACC | NUPD)) {
3182 np->n_flag |= NCHG;
3183 if (vp->v_usecount == 1 &&
3184 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
3185 VATTR_NULL(&vattr);
3186 if (np->n_flag & NACC)
3187 vattr.va_atime = np->n_atim;
3188 if (np->n_flag & NUPD)
3189 vattr.va_mtime = np->n_mtim;
3190 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p);
3191 }
3192 }
3193 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap));
3194}
3195
3196/*
3197 * Read wrapper for fifos.
3198 */
3199static int
3200nfsfifo_read(ap)
3201 struct vop_read_args /* {
3202 struct vnode *a_vp;
3203 struct uio *a_uio;
3204 int a_ioflag;
3205 struct ucred *a_cred;
3206 } */ *ap;
3207{
3208 register struct nfsnode *np = VTONFS(ap->a_vp);
3209
3210 /*
3211 * Set access flag.
3212 */
3213 np->n_flag |= NACC;
3214 getnanotime(&np->n_atim);
3215 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap));
3216}
3217
3218/*
3219 * Write wrapper for fifos.
3220 */
3221static int
3222nfsfifo_write(ap)
3223 struct vop_write_args /* {
3224 struct vnode *a_vp;
3225 struct uio *a_uio;
3226 int a_ioflag;
3227 struct ucred *a_cred;
3228 } */ *ap;
3229{
3230 register struct nfsnode *np = VTONFS(ap->a_vp);
3231
3232 /*
3233 * Set update flag.
3234 */
3235 np->n_flag |= NUPD;
3236 getnanotime(&np->n_mtim);
3237 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap));
3238}
3239
3240/*
3241 * Close wrapper for fifos.
3242 *
3243 * Update the times on the nfsnode then do fifo close.
3244 */
3245static int
3246nfsfifo_close(ap)
3247 struct vop_close_args /* {
3248 struct vnode *a_vp;
3249 int a_fflag;
3250 struct ucred *a_cred;
3251 struct proc *a_p;
3252 } */ *ap;
3253{
3254 register struct vnode *vp = ap->a_vp;
3255 register struct nfsnode *np = VTONFS(vp);
3256 struct vattr vattr;
3257 struct timespec ts;
3258
3259 if (np->n_flag & (NACC | NUPD)) {
3260 getnanotime(&ts);
3261 if (np->n_flag & NACC)
3262 np->n_atim = ts;
3263 if (np->n_flag & NUPD)
3264 np->n_mtim = ts;
3265 np->n_flag |= NCHG;
3266 if (vp->v_usecount == 1 &&
3267 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
3268 VATTR_NULL(&vattr);
3269 if (np->n_flag & NACC)
3270 vattr.va_atime = np->n_atim;
3271 if (np->n_flag & NUPD)
3272 vattr.va_mtime = np->n_mtim;
3273 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p);
3274 }
3275 }
3276 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap));
3277}