- Don't vput() a vnode that we do not hold locked. - Eliminate one of the few remaining uses of LK_CANRECURSE.diff -r1.107 -r1.108 src/sys/nfs/nfs_node.c
(ad)
--- src/sys/nfs/nfs_node.c 2008/11/19 18:36:09 1.107
+++ src/sys/nfs/nfs_node.c 2009/01/02 12:57:29 1.108
@@ -1,376 +1,389 @@ | @@ -1,376 +1,389 @@ | |||
1 | /* $NetBSD: nfs_node.c,v 1.107 2008/11/19 18:36:09 ad Exp $ */ | 1 | /* $NetBSD: nfs_node.c,v 1.108 2009/01/02 12:57:29 ad Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1989, 1993 | 4 | * Copyright (c) 1989, 1993 | |
5 | * The Regents of the University of California. All rights reserved. | 5 | * The Regents of the University of California. All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to Berkeley by | 7 | * This code is derived from software contributed to Berkeley by | |
8 | * Rick Macklem at The University of Guelph. | 8 | * Rick Macklem at The University of Guelph. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * 3. Neither the name of the University nor the names of its contributors | 18 | * 3. Neither the name of the University nor the names of its contributors | |
19 | * may be used to endorse or promote products derived from this software | 19 | * may be used to endorse or promote products derived from this software | |
20 | * without specific prior written permission. | 20 | * without specific prior written permission. | |
21 | * | 21 | * | |
22 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | 22 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
32 | * SUCH DAMAGE. | 32 | * SUCH DAMAGE. | |
33 | * | 33 | * | |
34 | * @(#)nfs_node.c 8.6 (Berkeley) 5/22/95 | 34 | * @(#)nfs_node.c 8.6 (Berkeley) 5/22/95 | |
35 | */ | 35 | */ | |
36 | 36 | |||
37 | #include <sys/cdefs.h> | 37 | #include <sys/cdefs.h> | |
38 | __KERNEL_RCSID(0, "$NetBSD: nfs_node.c,v 1.107 2008/11/19 18:36:09 ad Exp $"); | 38 | __KERNEL_RCSID(0, "$NetBSD: nfs_node.c,v 1.108 2009/01/02 12:57:29 ad Exp $"); | |
39 | 39 | |||
40 | #ifdef _KERNEL_OPT | 40 | #ifdef _KERNEL_OPT | |
41 | #include "opt_nfs.h" | 41 | #include "opt_nfs.h" | |
42 | #endif | 42 | #endif | |
43 | 43 | |||
44 | #include <sys/param.h> | 44 | #include <sys/param.h> | |
45 | #include <sys/systm.h> | 45 | #include <sys/systm.h> | |
46 | #include <sys/proc.h> | 46 | #include <sys/proc.h> | |
47 | #include <sys/mount.h> | 47 | #include <sys/mount.h> | |
48 | #include <sys/namei.h> | 48 | #include <sys/namei.h> | |
49 | #include <sys/vnode.h> | 49 | #include <sys/vnode.h> | |
50 | #include <sys/kernel.h> | 50 | #include <sys/kernel.h> | |
51 | #include <sys/pool.h> | 51 | #include <sys/pool.h> | |
52 | #include <sys/lock.h> | 52 | #include <sys/lock.h> | |
53 | #include <sys/hash.h> | 53 | #include <sys/hash.h> | |
54 | #include <sys/kauth.h> | 54 | #include <sys/kauth.h> | |
55 | 55 | |||
56 | #include <nfs/rpcv2.h> | 56 | #include <nfs/rpcv2.h> | |
57 | #include <nfs/nfsproto.h> | 57 | #include <nfs/nfsproto.h> | |
58 | #include <nfs/nfs.h> | 58 | #include <nfs/nfs.h> | |
59 | #include <nfs/nfsnode.h> | 59 | #include <nfs/nfsnode.h> | |
60 | #include <nfs/nfsmount.h> | 60 | #include <nfs/nfsmount.h> | |
61 | #include <nfs/nfs_var.h> | 61 | #include <nfs/nfs_var.h> | |
62 | 62 | |||
63 | struct pool nfs_node_pool; | 63 | struct pool nfs_node_pool; | |
64 | struct pool nfs_vattr_pool; | 64 | struct pool nfs_vattr_pool; | |
65 | 65 | static struct workqueue *nfs_sillyworkq; | ||
66 | MALLOC_JUSTDEFINE(M_NFSNODE, "NFS node", "NFS vnode private part"); | |||
67 | 66 | |||
68 | extern int prtactive; | 67 | extern int prtactive; | |
69 | 68 | |||
70 | void nfs_gop_size(struct vnode *, off_t, off_t *, int); | 69 | static void nfs_gop_size(struct vnode *, off_t, off_t *, int); | |
71 | int nfs_gop_alloc(struct vnode *, off_t, off_t, int, kauth_cred_t); | 70 | static int nfs_gop_alloc(struct vnode *, off_t, off_t, int, kauth_cred_t); | |
72 | int nfs_gop_write(struct vnode *, struct vm_page **, int, int); | 71 | static int nfs_gop_write(struct vnode *, struct vm_page **, int, int); | |
72 | static void nfs_sillyworker(struct work *, void *); | |||
73 | 73 | |||
74 | static const struct genfs_ops nfs_genfsops = { | 74 | static const struct genfs_ops nfs_genfsops = { | |
75 | .gop_size = nfs_gop_size, | 75 | .gop_size = nfs_gop_size, | |
76 | .gop_alloc = nfs_gop_alloc, | 76 | .gop_alloc = nfs_gop_alloc, | |
77 | .gop_write = nfs_gop_write, | 77 | .gop_write = nfs_gop_write, | |
78 | }; | 78 | }; | |
79 | 79 | |||
80 | /* | 80 | /* | |
81 | * Reinitialize inode hash table. | 81 | * Reinitialize inode hash table. | |
82 | */ | 82 | */ | |
83 | void | 83 | void | |
84 | nfs_node_init() | 84 | nfs_node_init() | |
85 | { | 85 | { | |
86 | malloc_type_attach(M_NFSNODE); | 86 | ||
87 | pool_init(&nfs_node_pool, sizeof(struct nfsnode), 0, 0, 0, "nfsnodepl", | 87 | pool_init(&nfs_node_pool, sizeof(struct nfsnode), 0, 0, 0, "nfsnodepl", | |
88 | &pool_allocator_nointr, IPL_NONE); | 88 | &pool_allocator_nointr, IPL_NONE); | |
89 | pool_init(&nfs_vattr_pool, sizeof(struct vattr), 0, 0, 0, "nfsvapl", | 89 | pool_init(&nfs_vattr_pool, sizeof(struct vattr), 0, 0, 0, "nfsvapl", | |
90 | &pool_allocator_nointr, IPL_NONE); | 90 | &pool_allocator_nointr, IPL_NONE); | |
91 | if (workqueue_create(&nfs_sillyworkq, "nfssilly", nfs_sillyworker, | |||
92 | NULL, PRI_NONE, IPL_NONE, 0) != 0) { | |||
93 | panic("nfs_node_init"); | |||
94 | } | |||
91 | } | 95 | } | |
92 | 96 | |||
93 | /* | 97 | /* | |
94 | * Free resources previously allocated in nfs_node_reinit(). | 98 | * Free resources previously allocated in nfs_node_reinit(). | |
95 | */ | 99 | */ | |
96 | void | 100 | void | |
97 | nfs_node_done() | 101 | nfs_node_done() | |
98 | { | 102 | { | |
103 | ||||
99 | pool_destroy(&nfs_node_pool); | 104 | pool_destroy(&nfs_node_pool); | |
100 | pool_destroy(&nfs_vattr_pool); | 105 | pool_destroy(&nfs_vattr_pool); | |
101 | malloc_type_detach(M_NFSNODE); | 106 | workqueue_destroy(nfs_sillyworkq); | |
102 | } | 107 | } | |
103 | 108 | |||
104 | #define RBTONFSNODE(node) \ | 109 | #define RBTONFSNODE(node) \ | |
105 | (void *)((uintptr_t)(node) - offsetof(struct nfsnode, n_rbnode)) | 110 | (void *)((uintptr_t)(node) - offsetof(struct nfsnode, n_rbnode)) | |
106 | 111 | |||
107 | struct fh_match { | 112 | struct fh_match { | |
108 | nfsfh_t *fhm_fhp; | 113 | nfsfh_t *fhm_fhp; | |
109 | size_t fhm_fhsize; | 114 | size_t fhm_fhsize; | |
110 | size_t fhm_fhoffset; | 115 | size_t fhm_fhoffset; | |
111 | }; | 116 | }; | |
112 | 117 | |||
113 | static int | 118 | static int | |
114 | nfs_compare_nodes(const struct rb_node *parent, const struct rb_node *node) | 119 | nfs_compare_nodes(const struct rb_node *parent, const struct rb_node *node) | |
115 | { | 120 | { | |
116 | const struct nfsnode * const pnp = RBTONFSNODE(parent); | 121 | const struct nfsnode * const pnp = RBTONFSNODE(parent); | |
117 | const struct nfsnode * const np = RBTONFSNODE(node); | 122 | const struct nfsnode * const np = RBTONFSNODE(node); | |
118 | 123 | |||
119 | if (pnp->n_fhsize != np->n_fhsize) | 124 | if (pnp->n_fhsize != np->n_fhsize) | |
120 | return np->n_fhsize - pnp->n_fhsize; | 125 | return np->n_fhsize - pnp->n_fhsize; | |
121 | 126 | |||
122 | return memcmp(np->n_fhp, pnp->n_fhp, np->n_fhsize); | 127 | return memcmp(np->n_fhp, pnp->n_fhp, np->n_fhsize); | |
123 | } | 128 | } | |
124 | 129 | |||
125 | static int | 130 | static int | |
126 | nfs_compare_node_fh(const struct rb_node *b, const void *key) | 131 | nfs_compare_node_fh(const struct rb_node *b, const void *key) | |
127 | { | 132 | { | |
128 | const struct nfsnode * const pnp = RBTONFSNODE(b); | 133 | const struct nfsnode * const pnp = RBTONFSNODE(b); | |
129 | const struct fh_match * const fhm = key; | 134 | const struct fh_match * const fhm = key; | |
130 | 135 | |||
131 | if (pnp->n_fhsize != fhm->fhm_fhsize) | 136 | if (pnp->n_fhsize != fhm->fhm_fhsize) | |
132 | return fhm->fhm_fhsize - pnp->n_fhsize; | 137 | return fhm->fhm_fhsize - pnp->n_fhsize; | |
133 | 138 | |||
134 | return memcmp(fhm->fhm_fhp, pnp->n_fhp, pnp->n_fhsize); | 139 | return memcmp(fhm->fhm_fhp, pnp->n_fhp, pnp->n_fhsize); | |
135 | } | 140 | } | |
136 | 141 | |||
137 | static const struct rb_tree_ops nfs_node_rbtree_ops = { | 142 | static const struct rb_tree_ops nfs_node_rbtree_ops = { | |
138 | .rbto_compare_nodes = nfs_compare_nodes, | 143 | .rbto_compare_nodes = nfs_compare_nodes, | |
139 | .rbto_compare_key = nfs_compare_node_fh, | 144 | .rbto_compare_key = nfs_compare_node_fh, | |
140 | }; | 145 | }; | |
141 | 146 | |||
142 | void | 147 | void | |
143 | nfs_rbtinit(struct nfsmount *nmp) | 148 | nfs_rbtinit(struct nfsmount *nmp) | |
144 | { | 149 | { | |
145 | rb_tree_init(&nmp->nm_rbtree, &nfs_node_rbtree_ops); | 150 | rb_tree_init(&nmp->nm_rbtree, &nfs_node_rbtree_ops); | |
146 | } | 151 | } | |
147 | 152 | |||
148 | 153 | |||
149 | /* | 154 | /* | |
150 | * Look up a vnode/nfsnode by file handle. | 155 | * Look up a vnode/nfsnode by file handle. | |
151 | * Callers must check for mount points!! | 156 | * Callers must check for mount points!! | |
152 | * In all cases, a pointer to a | 157 | * In all cases, a pointer to a | |
153 | * nfsnode structure is returned. | 158 | * nfsnode structure is returned. | |
154 | */ | 159 | */ | |
155 | int | 160 | int | |
156 | nfs_nget1(mntp, fhp, fhsize, npp, lkflags) | 161 | nfs_nget1(mntp, fhp, fhsize, npp, lkflags) | |
157 | struct mount *mntp; | 162 | struct mount *mntp; | |
158 | nfsfh_t *fhp; | 163 | nfsfh_t *fhp; | |
159 | int fhsize; | 164 | int fhsize; | |
160 | struct nfsnode **npp; | 165 | struct nfsnode **npp; | |
161 | int lkflags; | 166 | int lkflags; | |
162 | { | 167 | { | |
163 | struct nfsnode *np; | 168 | struct nfsnode *np; | |
164 | struct vnode *vp; | 169 | struct vnode *vp; | |
165 | struct nfsmount *nmp = VFSTONFS(mntp); | 170 | struct nfsmount *nmp = VFSTONFS(mntp); | |
166 | int error; | 171 | int error; | |
167 | struct fh_match fhm; | 172 | struct fh_match fhm; | |
168 | struct rb_node *node; | 173 | struct rb_node *node; | |
169 | 174 | |||
170 | fhm.fhm_fhp = fhp; | 175 | fhm.fhm_fhp = fhp; | |
171 | fhm.fhm_fhsize = fhsize; | 176 | fhm.fhm_fhsize = fhsize; | |
172 | 177 | |||
173 | loop: | 178 | loop: | |
174 | rw_enter(&nmp->nm_rbtlock, RW_READER); | 179 | rw_enter(&nmp->nm_rbtlock, RW_READER); | |
175 | node = rb_tree_find_node(&nmp->nm_rbtree, &fhm); | 180 | node = rb_tree_find_node(&nmp->nm_rbtree, &fhm); | |
176 | if (node != NULL) { | 181 | if (node != NULL) { | |
177 | np = RBTONFSNODE(node); | 182 | np = RBTONFSNODE(node); | |
178 | vp = NFSTOV(np); | 183 | vp = NFSTOV(np); | |
179 | mutex_enter(&vp->v_interlock); | 184 | mutex_enter(&vp->v_interlock); | |
180 | rw_exit(&nmp->nm_rbtlock); | 185 | rw_exit(&nmp->nm_rbtlock); | |
181 | error = vget(vp, LK_EXCLUSIVE | LK_INTERLOCK | lkflags); | 186 | error = vget(vp, LK_EXCLUSIVE | LK_INTERLOCK | lkflags); | |
182 | if (error == EBUSY) | 187 | if (error == EBUSY) | |
183 | return error; | 188 | return error; | |
184 | if (error) | 189 | if (error) | |
185 | goto loop; | 190 | goto loop; | |
186 | *npp = np; | 191 | *npp = np; | |
187 | return(0); | 192 | return(0); | |
188 | } | 193 | } | |
189 | rw_exit(&nmp->nm_rbtlock); | 194 | rw_exit(&nmp->nm_rbtlock); | |
190 | 195 | |||
191 | error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, &vp); | 196 | error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, &vp); | |
192 | if (error) { | 197 | if (error) { | |
193 | *npp = 0; | 198 | *npp = 0; | |
194 | return (error); | 199 | return (error); | |
195 | } | 200 | } | |
196 | np = pool_get(&nfs_node_pool, PR_WAITOK); | 201 | np = pool_get(&nfs_node_pool, PR_WAITOK); | |
197 | memset(np, 0, sizeof *np); | 202 | memset(np, 0, sizeof *np); | |
198 | np->n_vnode = vp; | 203 | np->n_vnode = vp; | |
199 | 204 | |||
200 | /* | 205 | /* | |
201 | * Insert the nfsnode in the hash queue for its new file handle | 206 | * Insert the nfsnode in the hash queue for its new file handle | |
202 | */ | 207 | */ | |
203 | 208 | |||
204 | if (fhsize > NFS_SMALLFH) { | 209 | if (fhsize > NFS_SMALLFH) { | |
205 | np->n_fhp = kmem_alloc(fhsize, KM_SLEEP); | 210 | np->n_fhp = kmem_alloc(fhsize, KM_SLEEP); | |
206 | } else | 211 | } else | |
207 | np->n_fhp = &np->n_fh; | 212 | np->n_fhp = &np->n_fh; | |
208 | memcpy(np->n_fhp, fhp, fhsize); | 213 | memcpy(np->n_fhp, fhp, fhsize); | |
209 | np->n_fhsize = fhsize; | 214 | np->n_fhsize = fhsize; | |
210 | np->n_accstamp = -1; | 215 | np->n_accstamp = -1; | |
211 | np->n_vattr = pool_get(&nfs_vattr_pool, PR_WAITOK); | 216 | np->n_vattr = pool_get(&nfs_vattr_pool, PR_WAITOK); | |
212 | 217 | |||
213 | rw_enter(&nmp->nm_rbtlock, RW_WRITER); | 218 | rw_enter(&nmp->nm_rbtlock, RW_WRITER); | |
214 | if (NULL != rb_tree_find_node(&nmp->nm_rbtree, &fhm)) { | 219 | if (NULL != rb_tree_find_node(&nmp->nm_rbtree, &fhm)) { | |
215 | rw_exit(&nmp->nm_rbtlock); | 220 | rw_exit(&nmp->nm_rbtlock); | |
216 | if (fhsize > NFS_SMALLFH) { | 221 | if (fhsize > NFS_SMALLFH) { | |
217 | kmem_free(np->n_fhp, fhsize); | 222 | kmem_free(np->n_fhp, fhsize); | |
218 | } | 223 | } | |
219 | pool_put(&nfs_vattr_pool, np->n_vattr); | 224 | pool_put(&nfs_vattr_pool, np->n_vattr); | |
220 | pool_put(&nfs_node_pool, np); | 225 | pool_put(&nfs_node_pool, np); | |
221 | ungetnewvnode(vp); | 226 | ungetnewvnode(vp); | |
222 | goto loop; | 227 | goto loop; | |
223 | } | 228 | } | |
224 | vp->v_data = np; | 229 | vp->v_data = np; | |
225 | genfs_node_init(vp, &nfs_genfsops); | 230 | genfs_node_init(vp, &nfs_genfsops); | |
226 | /* | 231 | /* | |
227 | * Initalize read/write creds to useful values. VOP_OPEN will | 232 | * Initalize read/write creds to useful values. VOP_OPEN will | |
228 | * overwrite these. | 233 | * overwrite these. | |
229 | */ | 234 | */ | |
230 | np->n_rcred = curlwp->l_cred; | 235 | np->n_rcred = curlwp->l_cred; | |
231 | kauth_cred_hold(np->n_rcred); | 236 | kauth_cred_hold(np->n_rcred); | |
232 | np->n_wcred = curlwp->l_cred; | 237 | np->n_wcred = curlwp->l_cred; | |
233 | kauth_cred_hold(np->n_wcred); | 238 | kauth_cred_hold(np->n_wcred); | |
234 | vlockmgr(&vp->v_lock, LK_EXCLUSIVE); | 239 | vlockmgr(&vp->v_lock, LK_EXCLUSIVE); | |
235 | NFS_INVALIDATE_ATTRCACHE(np); | 240 | NFS_INVALIDATE_ATTRCACHE(np); | |
236 | uvm_vnp_setsize(vp, 0); | 241 | uvm_vnp_setsize(vp, 0); | |
237 | rb_tree_insert_node(&nmp->nm_rbtree, &np->n_rbnode); | 242 | rb_tree_insert_node(&nmp->nm_rbtree, &np->n_rbnode); | |
238 | rw_exit(&nmp->nm_rbtlock); | 243 | rw_exit(&nmp->nm_rbtlock); | |
239 | 244 | |||
240 | *npp = np; | 245 | *npp = np; | |
241 | return (0); | 246 | return (0); | |
242 | } | 247 | } | |
243 | 248 | |||
244 | int | 249 | int | |
245 | nfs_inactive(v) | 250 | nfs_inactive(v) | |
246 | void *v; | 251 | void *v; | |
247 | { | 252 | { | |
248 | struct vop_inactive_args /* { | 253 | struct vop_inactive_args /* { | |
249 | struct vnode *a_vp; | 254 | struct vnode *a_vp; | |
250 | bool *a_recycle; | 255 | bool *a_recycle; | |
251 | } */ *ap = v; | 256 | } */ *ap = v; | |
252 | struct nfsnode *np; | 257 | struct nfsnode *np; | |
253 | struct sillyrename *sp; | 258 | struct sillyrename *sp; | |
254 | struct vnode *vp = ap->a_vp; | 259 | struct vnode *vp = ap->a_vp; | |
255 | 260 | |||
256 | np = VTONFS(vp); | 261 | np = VTONFS(vp); | |
257 | if (vp->v_type != VDIR) { | 262 | if (vp->v_type != VDIR) { | |
258 | sp = np->n_sillyrename; | 263 | sp = np->n_sillyrename; | |
259 | np->n_sillyrename = (struct sillyrename *)0; | 264 | np->n_sillyrename = (struct sillyrename *)0; | |
260 | } else | 265 | } else | |
261 | sp = NULL; | 266 | sp = NULL; | |
262 | if (sp != NULL) | 267 | if (sp != NULL) | |
263 | nfs_vinvalbuf(vp, 0, sp->s_cred, curlwp, 1); | 268 | nfs_vinvalbuf(vp, 0, sp->s_cred, curlwp, 1); | |
264 | *ap->a_recycle = (np->n_flag & NREMOVED) != 0; | 269 | *ap->a_recycle = (np->n_flag & NREMOVED) != 0; | |
265 | np->n_flag &= | 270 | np->n_flag &= | |
266 | (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NEOFVALID | NTRUNCDELAYED); | 271 | (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NEOFVALID | NTRUNCDELAYED); | |
267 | 272 | |||
268 | if (vp->v_type == VDIR && np->n_dircache) | 273 | if (vp->v_type == VDIR && np->n_dircache) | |
269 | nfs_invaldircache(vp, | 274 | nfs_invaldircache(vp, | |
270 | NFS_INVALDIRCACHE_FORCE | NFS_INVALDIRCACHE_KEEPEOF); | 275 | NFS_INVALDIRCACHE_FORCE | NFS_INVALDIRCACHE_KEEPEOF); | |
271 | 276 | |||
272 | VOP_UNLOCK(vp, 0); | 277 | VOP_UNLOCK(vp, 0); | |
273 | 278 | |||
274 | if (sp != NULL) { | 279 | if (sp != NULL) { | |
275 | int error; | 280 | workqueue_enqueue(nfs_sillyworkq, &sp->s_work, NULL); | |
276 | ||||
277 | /* | |||
278 | * Remove the silly file that was rename'd earlier | |||
279 | * | |||
280 | * Just in case our thread also has the parent node locked, | |||
281 | * we use LK_CANRECURSE. | |||
282 | */ | |||
283 | ||||
284 | error = vn_lock(sp->s_dvp, LK_EXCLUSIVE | LK_CANRECURSE); | |||
285 | if (error || sp->s_dvp->v_data == NULL) { | |||
286 | /* XXX should recover */ | |||
287 | printf("%s: vp=%p error=%d\n", | |||
288 | __func__, sp->s_dvp, error); | |||
289 | } else { | |||
290 | nfs_removeit(sp); | |||
291 | } | |||
292 | kauth_cred_free(sp->s_cred); | |||
293 | vput(sp->s_dvp); | |||
294 | kmem_free(sp, sizeof(*sp)); | |||
295 | } | 281 | } | |
296 | 282 | |||
297 | return (0); | 283 | return (0); | |
298 | } | 284 | } | |
299 | 285 | |||
300 | /* | 286 | /* | |
301 | * Reclaim an nfsnode so that it can be used for other purposes. | 287 | * Reclaim an nfsnode so that it can be used for other purposes. | |
302 | */ | 288 | */ | |
303 | int | 289 | int | |
304 | nfs_reclaim(v) | 290 | nfs_reclaim(v) | |
305 | void *v; | 291 | void *v; | |
306 | { | 292 | { | |
307 | struct vop_reclaim_args /* { | 293 | struct vop_reclaim_args /* { | |
308 | struct vnode *a_vp; | 294 | struct vnode *a_vp; | |
309 | } */ *ap = v; | 295 | } */ *ap = v; | |
310 | struct vnode *vp = ap->a_vp; | 296 | struct vnode *vp = ap->a_vp; | |
311 | struct nfsnode *np = VTONFS(vp); | 297 | struct nfsnode *np = VTONFS(vp); | |
312 | struct nfsmount *nmp = VFSTONFS(vp->v_mount); | 298 | struct nfsmount *nmp = VFSTONFS(vp->v_mount); | |
313 | 299 | |||
314 | if (prtactive && vp->v_usecount > 1) | 300 | if (prtactive && vp->v_usecount > 1) | |
315 | vprint("nfs_reclaim: pushing active", vp); | 301 | vprint("nfs_reclaim: pushing active", vp); | |
316 | 302 | |||
317 | rw_enter(&nmp->nm_rbtlock, RW_WRITER); | 303 | rw_enter(&nmp->nm_rbtlock, RW_WRITER); | |
318 | rb_tree_remove_node(&nmp->nm_rbtree, &np->n_rbnode); | 304 | rb_tree_remove_node(&nmp->nm_rbtree, &np->n_rbnode); | |
319 | rw_exit(&nmp->nm_rbtlock); | 305 | rw_exit(&nmp->nm_rbtlock); | |
320 | 306 | |||
321 | /* | 307 | /* | |
322 | * Free up any directory cookie structures and | 308 | * Free up any directory cookie structures and | |
323 | * large file handle structures that might be associated with | 309 | * large file handle structures that might be associated with | |
324 | * this nfs node. | 310 | * this nfs node. | |
325 | */ | 311 | */ | |
326 | if (vp->v_type == VDIR && np->n_dircache != NULL) { | 312 | if (vp->v_type == VDIR && np->n_dircache != NULL) { | |
327 | nfs_invaldircache(vp, NFS_INVALDIRCACHE_FORCE); | 313 | nfs_invaldircache(vp, NFS_INVALDIRCACHE_FORCE); | |
328 | hashdone(np->n_dircache, HASH_LIST, nfsdirhashmask); | 314 | hashdone(np->n_dircache, HASH_LIST, nfsdirhashmask); | |
329 | } | 315 | } | |
330 | KASSERT(np->n_dirgens == NULL); | 316 | KASSERT(np->n_dirgens == NULL); | |
331 | 317 | |||
332 | if (np->n_fhsize > NFS_SMALLFH) | 318 | if (np->n_fhsize > NFS_SMALLFH) | |
333 | kmem_free(np->n_fhp, np->n_fhsize); | 319 | kmem_free(np->n_fhp, np->n_fhsize); | |
334 | 320 | |||
335 | pool_put(&nfs_vattr_pool, np->n_vattr); | 321 | pool_put(&nfs_vattr_pool, np->n_vattr); | |
336 | if (np->n_rcred) | 322 | if (np->n_rcred) | |
337 | kauth_cred_free(np->n_rcred); | 323 | kauth_cred_free(np->n_rcred); | |
338 | 324 | |||
339 | if (np->n_wcred) | 325 | if (np->n_wcred) | |
340 | kauth_cred_free(np->n_wcred); | 326 | kauth_cred_free(np->n_wcred); | |
341 | 327 | |||
342 | cache_purge(vp); | 328 | cache_purge(vp); | |
343 | if (vp->v_type == VREG) { | 329 | if (vp->v_type == VREG) { | |
344 | mutex_destroy(&np->n_commitlock); | 330 | mutex_destroy(&np->n_commitlock); | |
345 | } | 331 | } | |
346 | genfs_node_destroy(vp); | 332 | genfs_node_destroy(vp); | |
347 | pool_put(&nfs_node_pool, np); | 333 | pool_put(&nfs_node_pool, np); | |
348 | vp->v_data = NULL; | 334 | vp->v_data = NULL; | |
349 | return (0); | 335 | return (0); | |
350 | } | 336 | } | |
351 | 337 | |||
352 | void | 338 | void | |
353 | nfs_gop_size(struct vnode *vp, off_t size, off_t *eobp, int flags) | 339 | nfs_gop_size(struct vnode *vp, off_t size, off_t *eobp, int flags) | |
354 | { | 340 | { | |
355 | 341 | |||
356 | *eobp = MAX(size, vp->v_size); | 342 | *eobp = MAX(size, vp->v_size); | |
357 | } | 343 | } | |
358 | 344 | |||
359 | int | 345 | int | |
360 | nfs_gop_alloc(struct vnode *vp, off_t off, off_t len, int flags, | 346 | nfs_gop_alloc(struct vnode *vp, off_t off, off_t len, int flags, | |
361 | kauth_cred_t cred) | 347 | kauth_cred_t cred) | |
362 | { | 348 | { | |
363 | 349 | |||
364 | return 0; | 350 | return 0; | |
365 | } | 351 | } | |
366 | 352 | |||
367 | int | 353 | int | |
368 | nfs_gop_write(struct vnode *vp, struct vm_page **pgs, int npages, int flags) | 354 | nfs_gop_write(struct vnode *vp, struct vm_page **pgs, int npages, int flags) | |
369 | { | 355 | { | |
370 | int i; | 356 | int i; | |
371 | 357 | |||
372 | for (i = 0; i < npages; i++) { | 358 | for (i = 0; i < npages; i++) { | |
373 | pmap_page_protect(pgs[i], VM_PROT_READ); | 359 | pmap_page_protect(pgs[i], VM_PROT_READ); | |
374 | } | 360 | } | |
375 | return genfs_gop_write(vp, pgs, npages, flags); | 361 | return genfs_gop_write(vp, pgs, npages, flags); | |
376 | } | 362 | } | |
363 | ||||
364 | /* | |||
365 | * Remove a silly file that was rename'd earlier | |||
366 | */ | |||
367 | static void | |||
368 | nfs_sillyworker(struct work *work, void *arg) | |||
369 | { | |||
370 | struct sillyrename *sp; | |||
371 | int error; | |||
372 | ||||
373 | sp = (struct sillyrename *)work; | |||
374 | error = vn_lock(sp->s_dvp, LK_EXCLUSIVE); | |||
375 | if (error || sp->s_dvp->v_data == NULL) { | |||
376 | /* XXX should recover */ | |||
377 | printf("%s: vp=%p error=%d\n", __func__, sp->s_dvp, error); | |||
378 | if (error == 0) { | |||
379 | vput(sp->s_dvp); | |||
380 | } else { | |||
381 | vrele(sp->s_dvp); | |||
382 | } | |||
383 | } else { | |||
384 | nfs_removeit(sp); | |||
385 | vput(sp->s_dvp); | |||
386 | } | |||
387 | kauth_cred_free(sp->s_cred); | |||
388 | kmem_free(sp, sizeof(*sp)); | |||
389 | } |
--- src/sys/nfs/nfsnode.h 2008/10/22 11:36:06 1.68
+++ src/sys/nfs/nfsnode.h 2009/01/02 12:57:29 1.69
@@ -1,293 +1,294 @@ | @@ -1,293 +1,294 @@ | |||
1 | /* $NetBSD: nfsnode.h,v 1.68 2008/10/22 11:36:06 matt Exp $ */ | 1 | /* $NetBSD: nfsnode.h,v 1.69 2009/01/02 12:57:29 ad Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1989, 1993 | 4 | * Copyright (c) 1989, 1993 | |
5 | * The Regents of the University of California. All rights reserved. | 5 | * The Regents of the University of California. All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to Berkeley by | 7 | * This code is derived from software contributed to Berkeley by | |
8 | * Rick Macklem at The University of Guelph. | 8 | * Rick Macklem at The University of Guelph. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * 3. Neither the name of the University nor the names of its contributors | 18 | * 3. Neither the name of the University nor the names of its contributors | |
19 | * may be used to endorse or promote products derived from this software | 19 | * may be used to endorse or promote products derived from this software | |
20 | * without specific prior written permission. | 20 | * without specific prior written permission. | |
21 | * | 21 | * | |
22 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | 22 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
32 | * SUCH DAMAGE. | 32 | * SUCH DAMAGE. | |
33 | * | 33 | * | |
34 | * @(#)nfsnode.h 8.9 (Berkeley) 5/14/95 | 34 | * @(#)nfsnode.h 8.9 (Berkeley) 5/14/95 | |
35 | */ | 35 | */ | |
36 | 36 | |||
37 | 37 | |||
38 | #ifndef _NFS_NFSNODE_H_ | 38 | #ifndef _NFS_NFSNODE_H_ | |
39 | #define _NFS_NFSNODE_H_ | 39 | #define _NFS_NFSNODE_H_ | |
40 | 40 | |||
41 | #include <sys/condvar.h> | 41 | #include <sys/condvar.h> | |
42 | #include <sys/mutex.h> | 42 | #include <sys/mutex.h> | |
43 | #include <sys/rb.h> | 43 | #include <sys/rb.h> | |
44 | #include <sys/workqueue.h> | |||
44 | 45 | |||
45 | #ifndef _NFS_NFS_H_ | 46 | #ifndef _NFS_NFS_H_ | |
46 | #include <nfs/nfs.h> | 47 | #include <nfs/nfs.h> | |
47 | #endif | 48 | #endif | |
48 | #include <miscfs/genfs/genfs.h> | 49 | #include <miscfs/genfs/genfs.h> | |
49 | #include <miscfs/genfs/genfs_node.h> | 50 | #include <miscfs/genfs/genfs_node.h> | |
50 | 51 | |||
51 | /* | 52 | /* | |
52 | * Silly rename structure that hangs off the nfsnode until the name | 53 | * Silly rename structure that hangs off the nfsnode until the name | |
53 | * can be removed by nfs_inactive() | 54 | * can be removed by nfs_inactive() | |
54 | */ | 55 | */ | |
55 | struct sillyrename { | 56 | struct sillyrename { | |
57 | struct work s_work; | |||
56 | kauth_cred_t s_cred; | 58 | kauth_cred_t s_cred; | |
57 | struct vnode *s_dvp; | 59 | struct vnode *s_dvp; | |
58 | long s_namlen; | 60 | long s_namlen; | |
59 | char s_name[20]; | 61 | char s_name[20]; | |
60 | }; | 62 | }; | |
61 | 63 | |||
62 | /* | 64 | /* | |
63 | * Definitions for the directory cache. Because directory cookies | 65 | * Definitions for the directory cache. Because directory cookies | |
64 | * are an opaque 64 bit entity, we need to provide some sort of | 66 | * are an opaque 64 bit entity, we need to provide some sort of | |
65 | * mapping between cookies and logical blocknumbers. Also, | 67 | * mapping between cookies and logical blocknumbers. Also, | |
66 | * we should store the cookies from the server somewhere, | 68 | * we should store the cookies from the server somewhere, | |
67 | * to be able to satisfy VOP_READDIR requests for cookies. | 69 | * to be able to satisfy VOP_READDIR requests for cookies. | |
68 | * We can't store the cookies in the dirent structure, as some | 70 | * We can't store the cookies in the dirent structure, as some | |
69 | * other systems. | 71 | * other systems. | |
70 | * | 72 | * | |
71 | * Each offset is hashed into a per-nfsnode hashtable. An entry | 73 | * Each offset is hashed into a per-nfsnode hashtable. An entry | |
72 | * found therein contains information about the (faked up) | 74 | * found therein contains information about the (faked up) | |
73 | * logical blocknumber, and also a pointer to a buffer where | 75 | * logical blocknumber, and also a pointer to a buffer where | |
74 | * the cookies are stored. | 76 | * the cookies are stored. | |
75 | */ | 77 | */ | |
76 | 78 | |||
77 | 79 | |||
78 | LIST_HEAD(nfsdirhashhead, nfsdircache); | 80 | LIST_HEAD(nfsdirhashhead, nfsdircache); | |
79 | TAILQ_HEAD(nfsdirchainhead, nfsdircache); | 81 | TAILQ_HEAD(nfsdirchainhead, nfsdircache); | |
80 | 82 | |||
81 | struct nfsdircache { | 83 | struct nfsdircache { | |
82 | off_t dc_cookie; /* Own offset (key) */ | 84 | off_t dc_cookie; /* Own offset (key) */ | |
83 | off_t dc_blkcookie; /* Offset of block we're in */ | 85 | off_t dc_blkcookie; /* Offset of block we're in */ | |
84 | LIST_ENTRY(nfsdircache) dc_hash; /* Hash chain */ | 86 | LIST_ENTRY(nfsdircache) dc_hash; /* Hash chain */ | |
85 | TAILQ_ENTRY(nfsdircache) dc_chain; /* Least recently entered chn */ | 87 | TAILQ_ENTRY(nfsdircache) dc_chain; /* Least recently entered chn */ | |
86 | u_int32_t dc_cookie32; /* Key for 64<->32 xlate case */ | 88 | u_int32_t dc_cookie32; /* Key for 64<->32 xlate case */ | |
87 | int dc_entry; /* Entry number within block */ | 89 | int dc_entry; /* Entry number within block */ | |
88 | int dc_refcnt; /* Reference count */ | 90 | int dc_refcnt; /* Reference count */ | |
89 | int dc_flags; /* NFSDC_ flags */ | 91 | int dc_flags; /* NFSDC_ flags */ | |
90 | }; | 92 | }; | |
91 | 93 | |||
92 | #define NFSDC_INVALID 1 | 94 | #define NFSDC_INVALID 1 | |
93 | 95 | |||
94 | /* | 96 | /* | |
95 | * NFSDC_BLKNO: get buffer cache index | 97 | * NFSDC_BLKNO: get buffer cache index | |
96 | */ | 98 | */ | |
97 | #define NFSDC_BLKNO(ndp) ((daddr_t)(ndp)->dc_blkcookie) | 99 | #define NFSDC_BLKNO(ndp) ((daddr_t)(ndp)->dc_blkcookie) | |
98 | 100 | |||
99 | /* | 101 | /* | |
100 | * The nfsnode is the nfs equivalent to ufs's inode. Any similarity | 102 | * The nfsnode is the nfs equivalent to ufs's inode. Any similarity | |
101 | * is purely coincidental. | 103 | * is purely coincidental. | |
102 | * There is a unique nfsnode allocated for each active file, | 104 | * There is a unique nfsnode allocated for each active file, | |
103 | * each current directory, each mounted-on file, text file, and the root. | 105 | * each current directory, each mounted-on file, text file, and the root. | |
104 | * An nfsnode is 'named' by its file handle. (nget/nfs_node.c) | 106 | * An nfsnode is 'named' by its file handle. (nget/nfs_node.c) | |
105 | */ | 107 | */ | |
106 | 108 | |||
107 | struct nfsnode_spec { | 109 | struct nfsnode_spec { | |
108 | struct timespec nspec_mtim; /* local mtime */ | 110 | struct timespec nspec_mtim; /* local mtime */ | |
109 | struct timespec nspec_atim; /* local atime */ | 111 | struct timespec nspec_atim; /* local atime */ | |
110 | }; | 112 | }; | |
111 | 113 | |||
112 | struct nfsnode_reg { | 114 | struct nfsnode_reg { | |
113 | off_t nreg_pushedlo; /* 1st blk in commited range */ | 115 | off_t nreg_pushedlo; /* 1st blk in commited range */ | |
114 | off_t nreg_pushedhi; /* Last block in range */ | 116 | off_t nreg_pushedhi; /* Last block in range */ | |
115 | off_t nreg_pushlo; /* 1st block in commit range */ | 117 | off_t nreg_pushlo; /* 1st block in commit range */ | |
116 | off_t nreg_pushhi; /* Last block in range */ | 118 | off_t nreg_pushhi; /* Last block in range */ | |
117 | kmutex_t nreg_commitlock; /* Serialize commits XXX */ | 119 | kmutex_t nreg_commitlock; /* Serialize commits XXX */ | |
118 | int nreg_commitflags; | 120 | int nreg_commitflags; | |
119 | int nreg_error; /* Save write error value */ | 121 | int nreg_error; /* Save write error value */ | |
120 | }; | 122 | }; | |
121 | 123 | |||
122 | struct nfsnode_dir { | 124 | struct nfsnode_dir { | |
123 | off_t ndir_direof; /* EOF offset cache */ | 125 | off_t ndir_direof; /* EOF offset cache */ | |
124 | nfsuint64 ndir_cookieverf; /* Cookie verifier */ | 126 | nfsuint64 ndir_cookieverf; /* Cookie verifier */ | |
125 | struct nfsdirhashhead *ndir_dircache; /* offset -> cache hash heads */ | 127 | struct nfsdirhashhead *ndir_dircache; /* offset -> cache hash heads */ | |
126 | struct nfsdirchainhead ndir_dirchain; /* Chain of dir cookies */ | 128 | struct nfsdirchainhead ndir_dirchain; /* Chain of dir cookies */ | |
127 | struct timespec ndir_nctime; /* Last name cache entry */ | 129 | struct timespec ndir_nctime; /* Last name cache entry */ | |
128 | unsigned ndir_dircachesize; /* Size of dir cookie cache */ | 130 | unsigned ndir_dircachesize; /* Size of dir cookie cache */ | |
129 | }; | 131 | }; | |
130 | 132 | |||
131 | struct nfsnode { | 133 | struct nfsnode { | |
132 | struct genfs_node n_gnode; | 134 | struct genfs_node n_gnode; | |
133 | u_quad_t n_size; /* Current size of file */ | 135 | u_quad_t n_size; /* Current size of file */ | |
134 | 136 | |||
135 | union { | 137 | union { | |
136 | struct nfsnode_spec nu_spec; | 138 | struct nfsnode_spec nu_spec; | |
137 | struct nfsnode_reg nu_reg; | 139 | struct nfsnode_reg nu_reg; | |
138 | struct nfsnode_dir nu_dir; | 140 | struct nfsnode_dir nu_dir; | |
139 | } n_un1; | 141 | } n_un1; | |
140 | 142 | |||
141 | #define n_mtim n_un1.nu_spec.nspec_mtim | 143 | #define n_mtim n_un1.nu_spec.nspec_mtim | |
142 | #define n_atim n_un1.nu_spec.nspec_atim | 144 | #define n_atim n_un1.nu_spec.nspec_atim | |
143 | 145 | |||
144 | #define n_pushedlo n_un1.nu_reg.nreg_pushedlo | 146 | #define n_pushedlo n_un1.nu_reg.nreg_pushedlo | |
145 | #define n_pushedhi n_un1.nu_reg.nreg_pushedhi | 147 | #define n_pushedhi n_un1.nu_reg.nreg_pushedhi | |
146 | #define n_pushlo n_un1.nu_reg.nreg_pushlo | 148 | #define n_pushlo n_un1.nu_reg.nreg_pushlo | |
147 | #define n_pushhi n_un1.nu_reg.nreg_pushhi | 149 | #define n_pushhi n_un1.nu_reg.nreg_pushhi | |
148 | #define n_commitlock n_un1.nu_reg.nreg_commitlock | 150 | #define n_commitlock n_un1.nu_reg.nreg_commitlock | |
149 | #define n_commitflags n_un1.nu_reg.nreg_commitflags | 151 | #define n_commitflags n_un1.nu_reg.nreg_commitflags | |
150 | #define n_error n_un1.nu_reg.nreg_error | 152 | #define n_error n_un1.nu_reg.nreg_error | |
151 | 153 | |||
152 | #define n_direofoffset n_un1.nu_dir.ndir_direof | 154 | #define n_direofoffset n_un1.nu_dir.ndir_direof | |
153 | #define n_cookieverf n_un1.nu_dir.ndir_cookieverf | 155 | #define n_cookieverf n_un1.nu_dir.ndir_cookieverf | |
154 | #define n_dircache n_un1.nu_dir.ndir_dircache | 156 | #define n_dircache n_un1.nu_dir.ndir_dircache | |
155 | #define n_dirchain n_un1.nu_dir.ndir_dirchain | 157 | #define n_dirchain n_un1.nu_dir.ndir_dirchain | |
156 | #define n_nctime n_un1.nu_dir.ndir_nctime | 158 | #define n_nctime n_un1.nu_dir.ndir_nctime | |
157 | #define n_dircachesize n_un1.nu_dir.ndir_dircachesize | 159 | #define n_dircachesize n_un1.nu_dir.ndir_dircachesize | |
158 | 160 | |||
159 | union { | 161 | union { | |
160 | struct sillyrename *nf_silly; /* !VDIR: silly rename struct */ | 162 | struct sillyrename *nf_silly; /* !VDIR: silly rename struct */ | |
161 | unsigned *ndir_dirgens; /* 32<->64bit xlate gen. no. */ | 163 | unsigned *ndir_dirgens; /* 32<->64bit xlate gen. no. */ | |
162 | } n_un2; | 164 | } n_un2; | |
163 | 165 | |||
164 | #define n_sillyrename n_un2.nf_silly | 166 | #define n_sillyrename n_un2.nf_silly | |
165 | #define n_dirgens n_un2.ndir_dirgens | 167 | #define n_dirgens n_un2.ndir_dirgens | |
166 | 168 | |||
167 | struct rb_node n_rbnode; /* red/black node */ | 169 | struct rb_node n_rbnode; /* red/black node */ | |
168 | nfsfh_t *n_fhp; /* NFS File Handle */ | 170 | nfsfh_t *n_fhp; /* NFS File Handle */ | |
169 | struct vattr *n_vattr; /* Vnode attribute cache */ | 171 | struct vattr *n_vattr; /* Vnode attribute cache */ | |
170 | struct vnode *n_vnode; /* associated vnode */ | 172 | struct vnode *n_vnode; /* associated vnode */ | |
171 | struct lockf *n_lockf; /* Locking record of file */ | 173 | struct lockf *n_lockf; /* Locking record of file */ | |
172 | time_t n_attrstamp; /* Attr. cache timestamp */ | 174 | time_t n_attrstamp; /* Attr. cache timestamp */ | |
173 | struct timespec n_mtime; /* Prev modify time. */ | 175 | struct timespec n_mtime; /* Prev modify time. */ | |
174 | time_t n_ctime; /* Prev create time. */ | 176 | time_t n_ctime; /* Prev create time. */ | |
175 | short n_fhsize; /* size in bytes, of fh */ | 177 | short n_fhsize; /* size in bytes, of fh */ | |
176 | short n_flag; /* Flag for locking.. */ | 178 | short n_flag; /* Flag for locking.. */ | |
177 | nfsfh_t n_fh; /* Small File Handle */ | 179 | nfsfh_t n_fh; /* Small File Handle */ | |
178 | time_t n_accstamp; /* Access cache timestamp */ | 180 | time_t n_accstamp; /* Access cache timestamp */ | |
179 | uid_t n_accuid; /* Last access requester */ | 181 | uid_t n_accuid; /* Last access requester */ | |
180 | int n_accmode; /* Mode last requested */ | 182 | int n_accmode; /* Mode last requested */ | |
181 | int n_accerror; /* Error last returned */ | 183 | int n_accerror; /* Error last returned */ | |
182 | kauth_cred_t n_rcred; | 184 | kauth_cred_t n_rcred; | |
183 | kauth_cred_t n_wcred; | 185 | kauth_cred_t n_wcred; | |
184 | }; | 186 | }; | |
185 | 187 | |||
186 | /* | 188 | /* | |
187 | * Values for n_commitflags | 189 | * Values for n_commitflags | |
188 | */ | 190 | */ | |
189 | #define NFS_COMMIT_PUSH_VALID 0x0001 /* push range valid */ | 191 | #define NFS_COMMIT_PUSH_VALID 0x0001 /* push range valid */ | |
190 | #define NFS_COMMIT_PUSHED_VALID 0x0002 /* pushed range valid */ | 192 | #define NFS_COMMIT_PUSHED_VALID 0x0002 /* pushed range valid */ | |
191 | 193 | |||
192 | /* | 194 | /* | |
193 | * Flags for n_flag | 195 | * Flags for n_flag | |
194 | */ | 196 | */ | |
195 | #define NFLUSHWANT 0x0001 /* Want wakeup from a flush in prog. */ | 197 | #define NFLUSHWANT 0x0001 /* Want wakeup from a flush in prog. */ | |
196 | #define NFLUSHINPROG 0x0002 /* Avoid multiple calls to vinvalbuf() */ | 198 | #define NFLUSHINPROG 0x0002 /* Avoid multiple calls to vinvalbuf() */ | |
197 | #define NMODIFIED 0x0004 /* Might have a modified buffer in bio */ | 199 | #define NMODIFIED 0x0004 /* Might have a modified buffer in bio */ | |
198 | #define NWRITEERR 0x0008 /* Flag write errors so close will know */ | 200 | #define NWRITEERR 0x0008 /* Flag write errors so close will know */ | |
199 | #define NACC 0x0100 /* Special file accessed */ | 201 | #define NACC 0x0100 /* Special file accessed */ | |
200 | #define NUPD 0x0200 /* Special file updated */ | 202 | #define NUPD 0x0200 /* Special file updated */ | |
201 | #define NCHG 0x0400 /* Special file times changed */ | 203 | #define NCHG 0x0400 /* Special file times changed */ | |
202 | #define NTRUNCDELAYED 0x1000 /* Should be truncated later; | 204 | #define NTRUNCDELAYED 0x1000 /* Should be truncated later; | |
203 | implies stale cache */ | 205 | implies stale cache */ | |
204 | #define NREMOVED 0x2000 /* Has been removed */ | 206 | #define NREMOVED 0x2000 /* Has been removed */ | |
205 | #define NUSEOPENCRED 0x4000 /* Try open cred first rather than owner's */ | 207 | #define NUSEOPENCRED 0x4000 /* Try open cred first rather than owner's */ | |
206 | #define NEOFVALID 0x8000 /* dir: n_direofoffset is valid */ | 208 | #define NEOFVALID 0x8000 /* dir: n_direofoffset is valid */ | |
207 | 209 | |||
208 | #define NFS_EOFVALID(ndp) ((ndp)->n_flag & NEOFVALID) | 210 | #define NFS_EOFVALID(ndp) ((ndp)->n_flag & NEOFVALID) | |
209 | 211 | |||
210 | /* | 212 | /* | |
211 | * Convert between nfsnode pointers and vnode pointers | 213 | * Convert between nfsnode pointers and vnode pointers | |
212 | */ | 214 | */ | |
213 | #define VTONFS(vp) ((struct nfsnode *)(vp)->v_data) | 215 | #define VTONFS(vp) ((struct nfsnode *)(vp)->v_data) | |
214 | #define NFSTOV(np) ((np)->n_vnode) | 216 | #define NFSTOV(np) ((np)->n_vnode) | |
215 | 217 | |||
216 | #ifdef _KERNEL | 218 | #ifdef _KERNEL | |
217 | 219 | |||
218 | /* | 220 | /* | |
219 | * Per-nfsiod datas | 221 | * Per-nfsiod datas | |
220 | */ | 222 | */ | |
221 | struct nfs_iod { | 223 | struct nfs_iod { | |
222 | kmutex_t nid_lock; | 224 | kmutex_t nid_lock; | |
223 | kcondvar_t nid_cv; | 225 | kcondvar_t nid_cv; | |
224 | LIST_ENTRY(nfs_iod) nid_idle; | 226 | LIST_ENTRY(nfs_iod) nid_idle; | |
225 | struct nfsmount *nid_mount; | 227 | struct nfsmount *nid_mount; | |
226 | bool nid_exiting; | 228 | bool nid_exiting; | |
227 | 229 | |||
228 | LIST_ENTRY(nfs_iod) nid_all; | 230 | LIST_ENTRY(nfs_iod) nid_all; | |
229 | }; | 231 | }; | |
230 | 232 | |||
231 | LIST_HEAD(nfs_iodlist, nfs_iod); | 233 | LIST_HEAD(nfs_iodlist, nfs_iod); | |
232 | extern kmutex_t nfs_iodlist_lock; | 234 | extern kmutex_t nfs_iodlist_lock; | |
233 | extern struct nfs_iodlist nfs_iodlist_idle; | 235 | extern struct nfs_iodlist nfs_iodlist_idle; | |
234 | extern struct nfs_iodlist nfs_iodlist_all; | 236 | extern struct nfs_iodlist nfs_iodlist_all; | |
235 | extern u_long nfsdirhashmask; | 237 | extern u_long nfsdirhashmask; | |
236 | 238 | |||
237 | /* | 239 | /* | |
238 | * Prototypes for NFS vnode operations | 240 | * Prototypes for NFS vnode operations | |
239 | */ | 241 | */ | |
240 | int nfs_lookup __P((void *)); | 242 | int nfs_lookup __P((void *)); | |
241 | int nfs_create __P((void *)); | 243 | int nfs_create __P((void *)); | |
242 | int nfs_mknod __P((void *)); | 244 | int nfs_mknod __P((void *)); | |
243 | int nfs_open __P((void *)); | 245 | int nfs_open __P((void *)); | |
244 | int nfs_close __P((void *)); | 246 | int nfs_close __P((void *)); | |
245 | int nfsspec_close __P((void *)); | 247 | int nfsspec_close __P((void *)); | |
246 | int nfsfifo_close __P((void *)); | 248 | int nfsfifo_close __P((void *)); | |
247 | int nfs_access __P((void *)); | 249 | int nfs_access __P((void *)); | |
248 | int nfsspec_access __P((void *)); | 250 | int nfsspec_access __P((void *)); | |
249 | int nfs_getattr __P((void *)); | 251 | int nfs_getattr __P((void *)); | |
250 | int nfs_setattr __P((void *)); | 252 | int nfs_setattr __P((void *)); | |
251 | int nfs_read __P((void *)); | 253 | int nfs_read __P((void *)); | |
252 | int nfs_write __P((void *)); | 254 | int nfs_write __P((void *)); | |
253 | int nfsspec_read __P((void *)); | 255 | int nfsspec_read __P((void *)); | |
254 | int nfsspec_write __P((void *)); | 256 | int nfsspec_write __P((void *)); | |
255 | int nfsfifo_read __P((void *)); | 257 | int nfsfifo_read __P((void *)); | |
256 | int nfsfifo_write __P((void *)); | 258 | int nfsfifo_write __P((void *)); | |
257 | #define nfs_ioctl genfs_enoioctl | 259 | #define nfs_ioctl genfs_enoioctl | |
258 | #define nfs_poll genfs_poll | 260 | #define nfs_poll genfs_poll | |
259 | #define nfs_revoke genfs_revoke | 261 | #define nfs_revoke genfs_revoke | |
260 | #define nfs_mmap genfs_mmap | 262 | #define nfs_mmap genfs_mmap | |
261 | int nfs_fsync __P((void *)); | 263 | int nfs_fsync __P((void *)); | |
262 | #define nfs_seek genfs_seek | 264 | #define nfs_seek genfs_seek | |
263 | int nfs_remove __P((void *)); | 265 | int nfs_remove __P((void *)); | |
264 | int nfs_link __P((void *)); | 266 | int nfs_link __P((void *)); | |
265 | int nfs_rename __P((void *)); | 267 | int nfs_rename __P((void *)); | |
266 | int nfs_mkdir __P((void *)); | 268 | int nfs_mkdir __P((void *)); | |
267 | int nfs_rmdir __P((void *)); | 269 | int nfs_rmdir __P((void *)); | |
268 | int nfs_symlink __P((void *)); | 270 | int nfs_symlink __P((void *)); | |
269 | int nfs_readdir __P((void *)); | 271 | int nfs_readdir __P((void *)); | |
270 | int nfs_readlink __P((void *)); | 272 | int nfs_readlink __P((void *)); | |
271 | #define nfs_abortop genfs_abortop | 273 | #define nfs_abortop genfs_abortop | |
272 | int nfs_inactive __P((void *)); | 274 | int nfs_inactive __P((void *)); | |
273 | int nfs_reclaim __P((void *)); | 275 | int nfs_reclaim __P((void *)); | |
274 | #define nfs_lock genfs_lock | 276 | #define nfs_lock genfs_lock | |
275 | int nfs_unlock __P((void *)); | 277 | int nfs_unlock __P((void *)); | |
276 | #define nfs_islocked genfs_islocked | 278 | #define nfs_islocked genfs_islocked | |
277 | int nfs_bmap __P((void *)); | 279 | int nfs_bmap __P((void *)); | |
278 | int nfs_strategy __P((void *)); | 280 | int nfs_strategy __P((void *)); | |
279 | int nfs_print __P((void *)); | 281 | int nfs_print __P((void *)); | |
280 | int nfs_pathconf __P((void *)); | 282 | int nfs_pathconf __P((void *)); | |
281 | int nfs_advlock __P((void *)); | 283 | int nfs_advlock __P((void *)); | |
282 | int nfs_getpages __P((void *)); | 284 | int nfs_getpages __P((void *)); | |
283 | int nfs_putpages __P((void *)); | 285 | int nfs_putpages __P((void *)); | |
284 | int nfs_gop_write(struct vnode *, struct vm_page **, int, int); | |||
285 | int nfs_kqfilter __P((void *)); | 286 | int nfs_kqfilter __P((void *)); | |
286 | 287 | |||
287 | extern int (**nfsv2_vnodeop_p) __P((void *)); | 288 | extern int (**nfsv2_vnodeop_p) __P((void *)); | |
288 | 289 | |||
289 | #define NFS_INVALIDATE_ATTRCACHE(np) (np)->n_attrstamp = 0 | 290 | #define NFS_INVALIDATE_ATTRCACHE(np) (np)->n_attrstamp = 0 | |
290 | 291 | |||
291 | #endif /* _KERNEL */ | 292 | #endif /* _KERNEL */ | |
292 | 293 | |||
293 | #endif | 294 | #endif |