| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
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. |
| @@ -25,90 +25,95 @@ | | | @@ -25,90 +25,95 @@ |
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) |
| @@ -262,46 +267,27 @@ nfs_inactive(v) | | | @@ -262,46 +267,27 @@ nfs_inactive(v) |
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 /* { |
| @@ -364,13 +350,40 @@ nfs_gop_alloc(struct vnode *vp, off_t of | | | @@ -364,13 +350,40 @@ nfs_gop_alloc(struct vnode *vp, off_t of |
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 | } |