]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - fs/autofs4/expire.c
053d92a745b91c9624cc585f54b718bb8dc22c63
[linux-2.6-omap-h63xx.git] / fs / autofs4 / expire.c
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  *  Copyright 2001-2003 Ian Kent <raven@themaw.net>
8  *
9  * This file is part of the Linux kernel and is made available under
10  * the terms of the GNU General Public License, version 2, or at your
11  * option, any later version, incorporated herein by reference.
12  *
13  * ------------------------------------------------------------------------- */
14
15 #include "autofs_i.h"
16
17 static unsigned long now;
18
19 /* Check if a dentry can be expired */
20 static inline int autofs4_can_expire(struct dentry *dentry,
21                                         unsigned long timeout, int do_now)
22 {
23         struct autofs_info *ino = autofs4_dentry_ino(dentry);
24
25         /* dentry in the process of being deleted */
26         if (ino == NULL)
27                 return 0;
28
29         /* No point expiring a pending mount */
30         if (dentry->d_flags & DCACHE_AUTOFS_PENDING)
31                 return 0;
32
33         if (!do_now) {
34                 /* Too young to die */
35                 if (time_after(ino->last_used + timeout, now))
36                         return 0;
37
38                 /* update last_used here :-
39                    - obviously makes sense if it is in use now
40                    - less obviously, prevents rapid-fire expire
41                      attempts if expire fails the first time */
42                 ino->last_used = now;
43         }
44         return 1;
45 }
46
47 /* Check a mount point for busyness */
48 static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry)
49 {
50         int status = 1;
51
52         DPRINTK("dentry %p %.*s",
53                 dentry, (int)dentry->d_name.len, dentry->d_name.name);
54
55         mntget(mnt);
56         dget(dentry);
57
58         if (!autofs4_follow_mount(&mnt, &dentry))
59                 goto done;
60
61         /* This is an autofs submount, we can't expire it */
62         if (is_autofs4_dentry(dentry))
63                 goto done;
64
65         /* The big question */
66         if (may_umount_tree(mnt) == 0)
67                 status = 0;
68 done:
69         DPRINTK("returning = %d", status);
70         mntput(mnt);
71         dput(dentry);
72         return status;
73 }
74
75 /*
76  * Calculate next entry in top down tree traversal.
77  * From next_mnt in namespace.c - elegant.
78  */
79 static struct dentry *next_dentry(struct dentry *p, struct dentry *root)
80 {
81         struct list_head *next = p->d_subdirs.next;
82
83         if (next == &p->d_subdirs) {
84                 while (1) {
85                         if (p == root)
86                                 return NULL;
87                         next = p->d_u.d_child.next;
88                         if (next != &p->d_parent->d_subdirs)
89                                 break;
90                         p = p->d_parent;
91                 }
92         }
93         return list_entry(next, struct dentry, d_u.d_child);
94 }
95
96 /* Check a directory tree of mount points for busyness
97  * The tree is not busy iff no mountpoints are busy
98  */
99 static int autofs4_tree_busy(struct vfsmount *mnt,
100                              struct dentry *top,
101                              unsigned long timeout,
102                              int do_now)
103 {
104         struct autofs_info *ino;
105         struct dentry *p;
106
107         DPRINTK("top %p %.*s",
108                 top, (int)top->d_name.len, top->d_name.name);
109
110         /* Negative dentry - give up */
111         if (!simple_positive(top))
112                 return 1;
113
114         spin_lock(&dcache_lock);
115         for (p = top; p; p = next_dentry(p, top)) {
116                 /* Negative dentry - give up */
117                 if (!simple_positive(p))
118                         continue;
119
120                 DPRINTK("dentry %p %.*s",
121                         p, (int) p->d_name.len, p->d_name.name);
122
123                 p = dget(p);
124                 spin_unlock(&dcache_lock);
125
126                 /*
127                  * Is someone visiting anywhere in the subtree ?
128                  * If there's no mount we need to check the usage
129                  * count for the autofs dentry.
130                  */
131                 ino = autofs4_dentry_ino(p);
132                 if (d_mountpoint(p)) {
133                         if (autofs4_mount_busy(mnt, p)) {
134                                 dput(p);
135                                 return 1;
136                         }
137                 } else {
138                         unsigned int ino_count = atomic_read(&ino->count);
139
140                         /* allow for dget above and top is already dgot */
141                         if (p == top)
142                                 ino_count += 2;
143                         else
144                                 ino_count++;
145
146                         if (atomic_read(&p->d_count) > ino_count) {
147                                 dput(p);
148                                 return 1;
149                         }
150                 }
151                 dput(p);
152                 spin_lock(&dcache_lock);
153         }
154         spin_unlock(&dcache_lock);
155
156         /* Timeout of a tree mount is ultimately determined by its top dentry */
157         if (!autofs4_can_expire(top, timeout, do_now))
158                 return 1;
159
160         return 0;
161 }
162
163 static struct dentry *autofs4_check_leaves(struct vfsmount *mnt,
164                                            struct dentry *parent,
165                                            unsigned long timeout,
166                                            int do_now)
167 {
168         struct dentry *p;
169
170         DPRINTK("parent %p %.*s",
171                 parent, (int)parent->d_name.len, parent->d_name.name);
172
173         spin_lock(&dcache_lock);
174         for (p = parent; p; p = next_dentry(p, parent)) {
175                 /* Negative dentry - give up */
176                 if (!simple_positive(p))
177                         continue;
178
179                 DPRINTK("dentry %p %.*s",
180                         p, (int) p->d_name.len, p->d_name.name);
181
182                 p = dget(p);
183                 spin_unlock(&dcache_lock);
184
185                 if (d_mountpoint(p)) {
186                         /* Can we expire this guy */
187                         if (!autofs4_can_expire(p, timeout, do_now))
188                                 goto cont;
189
190                         /* Can we umount this guy */
191                         if (!autofs4_mount_busy(mnt, p))
192                                 return p;
193
194                 }
195 cont:
196                 dput(p);
197                 spin_lock(&dcache_lock);
198         }
199         spin_unlock(&dcache_lock);
200         return NULL;
201 }
202
203 /*
204  * Find an eligible tree to time-out
205  * A tree is eligible if :-
206  *  - it is unused by any user process
207  *  - it has been unused for exp_timeout time
208  */
209 static struct dentry *autofs4_expire(struct super_block *sb,
210                                      struct vfsmount *mnt,
211                                      struct autofs_sb_info *sbi,
212                                      int how)
213 {
214         unsigned long timeout;
215         struct dentry *root = sb->s_root;
216         struct dentry *expired = NULL;
217         struct list_head *next;
218         int do_now = how & AUTOFS_EXP_IMMEDIATE;
219         int exp_leaves = how & AUTOFS_EXP_LEAVES;
220
221         if ( !sbi->exp_timeout || !root )
222                 return NULL;
223
224         now = jiffies;
225         timeout = sbi->exp_timeout;
226
227         spin_lock(&dcache_lock);
228         next = root->d_subdirs.next;
229
230         /* On exit from the loop expire is set to a dgot dentry
231          * to expire or it's NULL */
232         while ( next != &root->d_subdirs ) {
233                 struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child);
234
235                 /* Negative dentry - give up */
236                 if (!simple_positive(dentry)) {
237                         next = next->next;
238                         continue;
239                 }
240
241                 dentry = dget(dentry);
242                 spin_unlock(&dcache_lock);
243
244                 /* Case 1: indirect mount or top level direct mount */
245                 if (d_mountpoint(dentry)) {
246                         DPRINTK("checking mountpoint %p %.*s",
247                                 dentry, (int)dentry->d_name.len, dentry->d_name.name);
248
249                         /* Can we expire this guy */
250                         if (!autofs4_can_expire(dentry, timeout, do_now))
251                                 goto next;
252
253                         /* Can we umount this guy */
254                         if (!autofs4_mount_busy(mnt, dentry)) {
255                                 expired = dentry;
256                                 break;
257                         }
258                         goto next;
259                 }
260
261                 if (simple_empty(dentry))
262                         goto next;
263
264                 /* Case 2: tree mount, expire iff entire tree is not busy */
265                 if (!exp_leaves) {
266                         /* Lock the tree as we must expire as a whole */
267                         spin_lock(&sbi->fs_lock);
268                         if (!autofs4_tree_busy(mnt, dentry, timeout, do_now)) {
269                                 struct autofs_info *inf = autofs4_dentry_ino(dentry);
270
271                                 /* Set this flag early to catch sys_chdir and the like */
272                                 inf->flags |= AUTOFS_INF_EXPIRING;
273                                 spin_unlock(&sbi->fs_lock);
274                                 expired = dentry;
275                                 break;
276                         }
277                         spin_unlock(&sbi->fs_lock);
278                 /* Case 3: direct mount, expire individual leaves */
279                 } else {
280                         expired = autofs4_check_leaves(mnt, dentry, timeout, do_now);
281                         if (expired) {
282                                 dput(dentry);
283                                 break;
284                         }
285                 }
286 next:
287                 dput(dentry);
288                 spin_lock(&dcache_lock);
289                 next = next->next;
290         }
291
292         if (expired) {
293                 DPRINTK("returning %p %.*s",
294                         expired, (int)expired->d_name.len, expired->d_name.name);
295                 spin_lock(&dcache_lock);
296                 list_del(&expired->d_parent->d_subdirs);
297                 list_add(&expired->d_parent->d_subdirs, &expired->d_u.d_child);
298                 spin_unlock(&dcache_lock);
299                 return expired;
300         }
301         spin_unlock(&dcache_lock);
302
303         return NULL;
304 }
305
306 /* Perform an expiry operation */
307 int autofs4_expire_run(struct super_block *sb,
308                       struct vfsmount *mnt,
309                       struct autofs_sb_info *sbi,
310                       struct autofs_packet_expire __user *pkt_p)
311 {
312         struct autofs_packet_expire pkt;
313         struct dentry *dentry;
314
315         memset(&pkt,0,sizeof pkt);
316
317         pkt.hdr.proto_version = sbi->version;
318         pkt.hdr.type = autofs_ptype_expire;
319
320         if ((dentry = autofs4_expire(sb, mnt, sbi, 0)) == NULL)
321                 return -EAGAIN;
322
323         pkt.len = dentry->d_name.len;
324         memcpy(pkt.name, dentry->d_name.name, pkt.len);
325         pkt.name[pkt.len] = '\0';
326         dput(dentry);
327
328         if ( copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)) )
329                 return -EFAULT;
330
331         return 0;
332 }
333
334 /* Call repeatedly until it returns -EAGAIN, meaning there's nothing
335    more to be done */
336 int autofs4_expire_multi(struct super_block *sb, struct vfsmount *mnt,
337                         struct autofs_sb_info *sbi, int __user *arg)
338 {
339         struct dentry *dentry;
340         int ret = -EAGAIN;
341         int do_now = 0;
342
343         if (arg && get_user(do_now, arg))
344                 return -EFAULT;
345
346         if ((dentry = autofs4_expire(sb, mnt, sbi, do_now)) != NULL) {
347                 struct autofs_info *ino = autofs4_dentry_ino(dentry);
348
349                 /* This is synchronous because it makes the daemon a
350                    little easier */
351                 ino->flags |= AUTOFS_INF_EXPIRING;
352                 ret = autofs4_wait(sbi, dentry, NFY_EXPIRE);
353                 ino->flags &= ~AUTOFS_INF_EXPIRING;
354                 dput(dentry);
355         }
356
357         return ret;
358 }
359