21ad7c20979c0538a6e5895019538b3e98a40d4e
[openafs.git] / src / afs / LINUX / osi_vcache.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #include "afs/param.h"
12
13 #include "afs/sysincludes.h"    /*Standard vendor system headers */
14 #include "afsincludes.h"        /*AFS-based standard headers */
15
16 int
17 osi_TryEvictVCache(struct vcache *avc, int *slept) {
18     int code;
19
20     struct dentry *dentry;
21     struct inode *inode = AFSTOV(avc);
22     struct list_head *cur, *head;
23
24     /* First, see if we can evict the inode from the dcache */
25     if (avc != afs_globalVp && VREFCOUNT(avc) > 1 && avc->opens == 0) {
26         *slept = 1;
27         ReleaseWriteLock(&afs_xvcache);
28         AFS_GUNLOCK();
29
30 #if defined(HAVE_DCACHE_LOCK)
31         spin_lock(&dcache_lock);
32         head = &inode->i_dentry;
33
34 restart:
35         cur = head;
36         while ((cur = cur->next) != head) {
37             dentry = list_entry(cur, struct dentry, d_alias);
38
39             if (d_unhashed(dentry))
40                 continue;
41             dget_locked(dentry);
42
43             spin_unlock(&dcache_lock);
44             if (d_invalidate(dentry) == -EBUSY) {
45                 dput(dentry);
46                 /* perhaps lock and try to continue? (use cur as head?) */
47                 goto inuse;
48             }
49             dput(dentry);
50             spin_lock(&dcache_lock);
51             goto restart;
52         }
53         spin_unlock(&dcache_lock);
54 #else /* HAVE_DCACHE_LOCK */
55         spin_lock(&inode->i_lock);
56         head = &inode->i_dentry;
57
58 restart:
59         cur = head;
60         while ((cur = cur->next) != head) {
61             dentry = list_entry(cur, struct dentry, d_alias);
62
63             spin_lock(&dentry->d_lock);
64             if (d_unhashed(dentry)) {
65                 spin_unlock(&dentry->d_lock);
66                 continue;
67             }
68             spin_unlock(&dentry->d_lock);
69             dget(dentry);
70
71             spin_unlock(&inode->i_lock);
72             if (d_invalidate(dentry) == -EBUSY) {
73                 dput(dentry);
74                 /* perhaps lock and try to continue? (use cur as head?) */
75                 goto inuse;
76             }
77             dput(dentry);
78             spin_lock(&inode->i_lock);
79             goto restart;
80         }
81         spin_unlock(&inode->i_lock);
82 #endif /* HAVE_DCACHE_LOCK */
83 inuse:
84         AFS_GLOCK();
85         ObtainWriteLock(&afs_xvcache, 733);
86     }
87
88     /* See if we can evict it from the VLRUQ */
89     if (VREFCOUNT_GT(avc,0) && !VREFCOUNT_GT(avc,1) && avc->opens == 0
90         && (avc->f.states & CUnlinkedDel) == 0) {
91         int didsleep = *slept;
92
93         code = afs_FlushVCache(avc, slept);
94         /* flushvcache wipes slept; restore slept if we did before */
95         if (didsleep)
96             *slept = didsleep;
97
98         if (code == 0)
99             return 1;
100     }
101
102     return 0;
103 }
104
105 struct vcache *
106 osi_NewVnode(void)
107 {
108     struct inode *ip;
109     struct vcache *tvc;
110
111     AFS_GUNLOCK();
112     ip = new_inode(afs_globalVFS);
113     if (!ip)
114         osi_Panic("afs_NewVCache: no more inodes");
115     AFS_GLOCK();
116 #if defined(STRUCT_SUPER_OPERATIONS_HAS_ALLOC_INODE)
117     tvc = VTOAFS(ip);
118 #else
119     tvc = afs_osi_Alloc(sizeof(struct vcache));
120     ip->u.generic_ip = tvc;
121     tvc->v = ip;
122 #endif
123
124     return tvc;
125 }
126
127 void
128 osi_PrePopulateVCache(struct vcache *avc) {
129     avc->uncred = 0;
130     memset(&(avc->f), 0, sizeof(struct fvcache));
131     avc->cred = NULL;
132 }
133
134 void
135 osi_AttachVnode(struct vcache *avc, int seq) { /* Nada */ }
136
137 void
138 osi_PostPopulateVCache(struct vcache *avc) {
139     vSetType(avc, VREG);
140 }
141