2 * Copyright 2000, International Business Machines Corporation and others.
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
10 #include <afsconfig.h>
11 #include "afs/param.h"
13 #include "afs/sysincludes.h" /*Standard vendor system headers */
14 #include "afsincludes.h" /*AFS-based standard headers */
16 #include "osi_compat.h"
19 TryEvictDirDentries(struct inode
*inode
)
21 struct dentry
*dentry
;
22 #if defined(D_ALIAS_IS_HLIST) && !defined(HLIST_ITERATOR_NO_NODE)
26 afs_d_alias_lock(inode
);
29 #if defined(D_ALIAS_IS_HLIST)
30 # if defined(HLIST_ITERATOR_NO_NODE)
31 hlist_for_each_entry(dentry
, &inode
->i_dentry
, d_alias
) {
33 hlist_for_each_entry(dentry
, p
, &inode
->i_dentry
, d_alias
) {
36 list_for_each_entry(dentry
, &inode
->i_dentry
, d_alias
) {
38 spin_lock(&dentry
->d_lock
);
39 if (d_unhashed(dentry
)) {
40 spin_unlock(&dentry
->d_lock
);
43 spin_unlock(&dentry
->d_lock
);
44 afs_linux_dget(dentry
);
46 afs_d_alias_unlock(inode
);
49 * Once we have dropped the d_alias lock (above), it is no longer safe
50 * to 'continue' our iteration over d_alias because the list may change
51 * out from under us. Therefore, we must either leave the loop, or
52 * restart from the beginning. To avoid looping forever, we must only
53 * restart if we know we've d_drop'd an alias. In all other cases we
54 * must leave the loop.
58 * For a long time we used d_invalidate() for this purpose, but
59 * using shrink_dcache_parent() and checking the refcount ourselves is
60 * better, for two reasons: it avoids causing ENOENT issues for the
61 * CWD in linux versions since 3.11, and it avoids dropping Linux
64 * For non-fakestat, AFS mountpoints look like directories and end up here.
67 shrink_dcache_parent(dentry
);
68 spin_lock(&dentry
->d_lock
);
69 if (afs_dentry_count(dentry
) > 1) /* still has references */ {
70 if (dentry
->d_inode
!= NULL
) /* is not a negative dentry */ {
71 spin_unlock(&dentry
->d_lock
);
77 * This is either a negative dentry, or a dentry with no references.
78 * Either way, it is okay to unhash it now.
79 * Do so under the d_lock (that is, via __d_drop() instead of d_drop())
80 * to avoid a race with another process picking up a reference.
83 spin_unlock(&dentry
->d_lock
);
86 afs_d_alias_lock(inode
);
89 afs_d_alias_unlock(inode
);
97 osi_TryEvictVCache(struct vcache
*avc
, int *slept
, int defersleep
)
101 /* First, see if we can evict the inode from the dcache */
102 if (defersleep
&& avc
!= afs_globalVp
&& VREFCOUNT(avc
) > 1
103 && avc
->opens
== 0) {
104 struct inode
*ip
= AFSTOV(avc
);
108 ReleaseWriteLock(&afs_xvcache
);
111 if (S_ISDIR(ip
->i_mode
))
112 TryEvictDirDentries(ip
);
117 ObtainWriteLock(&afs_xvcache
, 733);
121 /* See if we can evict it from the VLRUQ */
122 if (VREFCOUNT_GT(avc
, 0) && !VREFCOUNT_GT(avc
, 1) && avc
->opens
== 0
123 && (avc
->f
.states
& CUnlinkedDel
) == 0) {
124 int didsleep
= *slept
;
126 code
= afs_FlushVCache(avc
, slept
);
127 /* flushvcache wipes slept; restore slept if we did before */
145 ip
= new_inode(afs_globalVFS
);
147 osi_Panic("afs_NewVCache: no more inodes");
149 #if defined(STRUCT_SUPER_OPERATIONS_HAS_ALLOC_INODE)
152 tvc
= afs_osi_Alloc(sizeof(struct vcache
));
153 ip
->u
.generic_ip
= tvc
;
157 INIT_LIST_HEAD(&tvc
->pagewriters
);
158 spin_lock_init(&tvc
->pagewriter_lock
);
164 osi_PrePopulateVCache(struct vcache
*avc
)
167 memset(&(avc
->f
), 0, sizeof(struct fvcache
));
172 osi_AttachVnode(struct vcache
*avc
, int seq
)
178 osi_PostPopulateVCache(struct vcache
*avc
)
184 * osi_ResetRootVCache - Reset the root vcache
185 * Reset the dentry associated with the afs root.
186 * Called from afs_CheckRootVolume when we notice that
187 * the root volume ID has changed.
189 * @volid: volume ID for the afs root
192 osi_ResetRootVCache(afs_uint32 volid
)
194 struct vrequest
*treq
= NULL
;
199 struct inode
*root
= AFSTOV(afs_globalVp
);
201 afs_rootFid
.Fid
.Volume
= volid
;
202 afs_rootFid
.Fid
.Vnode
= 1;
203 afs_rootFid
.Fid
.Unique
= 1;
206 if (afs_CreateReq(&treq
, credp
))
208 vcp
= afs_GetVCache(&afs_rootFid
, treq
, NULL
, NULL
);
211 afs_getattr(vcp
, &vattr
, credp
);
212 afs_fill_inode(AFSTOV(vcp
), &vattr
);
214 dp
= d_find_alias(root
);
216 afs_d_alias_lock(AFSTOV(vcp
));
218 spin_lock(&dp
->d_lock
);
219 #if defined(D_ALIAS_IS_HLIST)
220 hlist_del_init(&dp
->d_alias
);
221 hlist_add_head(&dp
->d_alias
, &(AFSTOV(vcp
)->i_dentry
));
223 list_del_init(&dp
->d_alias
);
224 list_add(&dp
->d_alias
, &(AFSTOV(vcp
)->i_dentry
));
226 dp
->d_inode
= AFSTOV(vcp
);
227 spin_unlock(&dp
->d_lock
);
229 afs_d_alias_unlock(AFSTOV(vcp
));
237 afs_DestroyReq(treq
);