1 /* -*- c -*- --------------------------------------------------------------- *
2 *
3 * linux/fs/autofs/expire.c
4 *
5 * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
6 * Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org>
7 *
8 * This file is part of the Linux kernel and is made available under
9 * the terms of the GNU General Public License, version 2, or at your
10 * option, any later version, incorporated herein by reference.
11 *
12 * ------------------------------------------------------------------------- */
13
14 #include "autofs_i.h"
15
16 /*
17 * Determine if a subtree of the namespace is busy.
18 *
19 * mnt is the mount tree under the autofs mountpoint
20 */
21 static inline int is_vfsmnt_tree_busy(struct vfsmount *mnt)
22 {
23 struct vfsmount *this_parent = mnt;
24 struct list_head *next;
25 int count;
26
27 count = atomic_read(&mnt->mnt_count) - 1;
28
29 repeat:
30 next = this_parent->mnt_mounts.next;
31 DPRINTK(("is_vfsmnt_tree_busy: mnt=%p, this_parent=%p, next=%p\n",
32 mnt, this_parent, next));
33 resume:
34 for( ; next != &this_parent->mnt_mounts; next = next->next) {
35 struct vfsmount *p = list_entry(next, struct vfsmount,
36 mnt_child);
37
38 /* -1 for struct vfs_mount's normal count,
39 -1 to compensate for child's reference to parent */
40 count += atomic_read(&p->mnt_count) - 1 - 1;
41
42 DPRINTK(("is_vfsmnt_tree_busy: p=%p, count now %d\n",
43 p, count));
44
45 if (!list_empty(&p->mnt_mounts)) {
46 this_parent = p;
47 goto repeat;
48 }
49 /* root is busy if any leaf is busy */
50 if (atomic_read(&p->mnt_count) > 1)
51 return 1;
52 }
53
54 /* All done at this level ... ascend and resume the search. */
55 if (this_parent != mnt) {
56 next = this_parent->mnt_child.next;
57 this_parent = this_parent->mnt_parent;
58 goto resume;
59 }
60
61 DPRINTK(("is_vfsmnt_tree_busy: count=%d\n", count));
62 return count != 0; /* remaining users? */
63 }
64
65 /* Traverse a dentry's list of vfsmounts and return the number of
66 non-busy mounts */
67 static int check_vfsmnt(struct vfsmount *mnt, struct dentry *dentry)
68 {
69 int ret = 0;
70 struct list_head *tmp;
71
72 list_for_each(tmp, &dentry->d_vfsmnt) {
73 struct vfsmount *vfs = list_entry(tmp, struct vfsmount,
74 mnt_clash);
75 DPRINTK(("check_vfsmnt: mnt=%p, dentry=%p, tmp=%p, vfs=%p\n",
76 mnt, dentry, tmp, vfs));
77 if (vfs->mnt_parent != mnt || /* don't care about busy-ness of other namespaces */
78 !is_vfsmnt_tree_busy(vfs))
79 ret++;
80 }
81
82 DPRINTK(("check_vfsmnt: ret=%d\n", ret));
83 return ret;
84 }
85
86 /* Check dentry tree for busyness. If a dentry appears to be busy
87 because it is a mountpoint, check to see if the mounted
88 filesystem is busy. */
89 static int is_tree_busy(struct vfsmount *topmnt, struct dentry *top)
90 {
91 struct dentry *this_parent;
92 struct list_head *next;
93 int count;
94
95 count = atomic_read(&top->d_count);
96
97 DPRINTK(("is_tree_busy: top=%p initial count=%d\n",
98 top, count));
99 this_parent = top;
100
101 count--; /* top is passed in after being dgot */
102
103 if (is_autofs4_dentry(top)) {
104 count--;
105 DPRINTK(("is_tree_busy: autofs; count=%d\n", count));
106 }
107
108 if (d_mountpoint(top))
109 count -= check_vfsmnt(topmnt, top);
110
111 repeat:
112 next = this_parent->d_subdirs.next;
113 resume:
114 while (next != &this_parent->d_subdirs) {
115 int adj = 0;
116 struct dentry *dentry = list_entry(next, struct dentry,
117 d_child);
118 next = next->next;
119
120 count += atomic_read(&dentry->d_count) - 1;
121
122 if (d_mountpoint(dentry))
123 adj += check_vfsmnt(topmnt, dentry);
124
125 if (is_autofs4_dentry(dentry)) {
126 adj++;
127 DPRINTK(("is_tree_busy: autofs; adj=%d\n",
128 adj));
129 }
130
131 count -= adj;
132
133 if (!list_empty(&dentry->d_subdirs)) {
134 this_parent = dentry;
135 goto repeat;
136 }
137
138 if (atomic_read(&dentry->d_count) != adj) {
139 DPRINTK(("is_tree_busy: busy leaf (d_count=%d adj=%d)\n",
140 atomic_read(&dentry->d_count), adj));
141 return 1;
142 }
143 }
144
145 /* All done at this level ... ascend and resume the search. */
146 if (this_parent != top) {
147 next = this_parent->d_child.next;
148 this_parent = this_parent->d_parent;
149 goto resume;
150 }
151
152 DPRINTK(("is_tree_busy: count=%d\n", count));
153 return count != 0; /* remaining users? */
154 }
155
156 /*
157 * Find an eligible tree to time-out
158 * A tree is eligible if :-
159 * - it is unused by any user process
160 * - it has been unused for exp_timeout time
161 */
162 static struct dentry *autofs4_expire(struct super_block *sb,
163 struct vfsmount *mnt,
164 struct autofs_sb_info *sbi,
165 int do_now)
166 {
167 unsigned long now = jiffies;
168 unsigned long timeout;
169 struct dentry *root = sb->s_root;
170 struct list_head *tmp;
171 struct dentry *d;
172 struct vfsmount *p;
173
174 if (!sbi->exp_timeout || !root)
175 return NULL;
176
177 timeout = sbi->exp_timeout;
178
179 spin_lock(&dcache_lock);
180 for(tmp = root->d_subdirs.next;
181 tmp != &root->d_subdirs;
182 tmp = tmp->next) {
183 struct autofs_info *ino;
184 struct dentry *dentry = list_entry(tmp, struct dentry, d_child);
185
186 if (dentry->d_inode == NULL)
187 continue;
188
189 ino = autofs4_dentry_ino(dentry);
190
191 if (ino == NULL) {
192 /* dentry in the process of being deleted */
193 continue;
194 }
195
196 /* No point expiring a pending mount */
197 if (dentry->d_flags & DCACHE_AUTOFS_PENDING)
198 continue;
199
200 if (!do_now) {
201 /* Too young to die */
202 if (time_after(ino->last_used + timeout, now))
203 continue;
204
205 /* update last_used here :-
206 - obviously makes sense if it is in use now
207 - less obviously, prevents rapid-fire expire
208 attempts if expire fails the first time */
209 ino->last_used = now;
210 }
211 p = mntget(mnt);
212 d = dget_locked(dentry);
213
214 if (!is_tree_busy(p, d)) {
215 DPRINTK(("autofs_expire: returning %p %.*s\n",
216 dentry, (int)dentry->d_name.len, dentry->d_name.name));
217 /* Start from here next time */
218 list_del(&root->d_subdirs);
219 list_add(&root->d_subdirs, &dentry->d_child);
220 spin_unlock(&dcache_lock);
221
222 dput(d);
223 mntput(p);
224 return dentry;
225 }
226 dput(d);
227 mntput(p);
228 }
229 spin_unlock(&dcache_lock);
230
231 return NULL;
232 }
233
234 /* Perform an expiry operation */
235 int autofs4_expire_run(struct super_block *sb,
236 struct vfsmount *mnt,
237 struct autofs_sb_info *sbi,
238 struct autofs_packet_expire *pkt_p)
239 {
240 struct autofs_packet_expire pkt;
241 struct dentry *dentry;
242
243 memset(&pkt,0,sizeof pkt);
244
245 pkt.hdr.proto_version = sbi->version;
246 pkt.hdr.type = autofs_ptype_expire;
247
248 if ((dentry = autofs4_expire(sb, mnt, sbi, 0)) == NULL)
249 return -EAGAIN;
250
251 pkt.len = dentry->d_name.len;
252 memcpy(pkt.name, dentry->d_name.name, pkt.len);
253 pkt.name[pkt.len] = '\0';
254
255 if ( copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)) )
256 return -EFAULT;
257
258 return 0;
259 }
260
261 /* Call repeatedly until it returns -EAGAIN, meaning there's nothing
262 more to be done */
263 int autofs4_expire_multi(struct super_block *sb, struct vfsmount *mnt,
264 struct autofs_sb_info *sbi, int *arg)
265 {
266 struct dentry *dentry;
267 int ret = -EAGAIN;
268 int do_now = 0;
269
270 if (arg && get_user(do_now, arg))
271 return -EFAULT;
272
273 if ((dentry = autofs4_expire(sb, mnt, sbi, do_now)) != NULL) {
274 struct autofs_info *de_info = autofs4_dentry_ino(dentry);
275
276 /* This is synchronous because it makes the daemon a
277 little easier */
278 de_info->flags |= AUTOFS_INF_EXPIRING;
279 ret = autofs4_wait(sbi, &dentry->d_name, NFY_EXPIRE);
280 de_info->flags &= ~AUTOFS_INF_EXPIRING;
281 }
282
283 return ret;
284 }
285
286
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.