aboutsummaryrefslogtreecommitdiffstats
path: root/fs/autofs4
diff options
context:
space:
mode:
Diffstat (limited to 'fs/autofs4')
-rw-r--r--fs/autofs4/autofs_i.h11
-rw-r--r--fs/autofs4/expire.c127
-rw-r--r--fs/autofs4/root.c18
3 files changed, 87 insertions, 69 deletions
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index 3912dcf047e5..9d2ae9b30d9f 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -254,6 +254,17 @@ static inline int simple_positive(struct dentry *dentry)
254 return dentry->d_inode && !d_unhashed(dentry); 254 return dentry->d_inode && !d_unhashed(dentry);
255} 255}
256 256
257static inline void __autofs4_add_expiring(struct dentry *dentry)
258{
259 struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
260 struct autofs_info *ino = autofs4_dentry_ino(dentry);
261 if (ino) {
262 if (list_empty(&ino->expiring))
263 list_add(&ino->expiring, &sbi->expiring_list);
264 }
265 return;
266}
267
257static inline void autofs4_add_expiring(struct dentry *dentry) 268static inline void autofs4_add_expiring(struct dentry *dentry)
258{ 269{
259 struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); 270 struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index ee6402050f13..968c1434af62 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -91,24 +91,64 @@ done:
91} 91}
92 92
93/* 93/*
94 * Calculate next entry in top down tree traversal. 94 * Calculate and dget next entry in top down tree traversal.
95 * From next_mnt in namespace.c - elegant.
96 */ 95 */
97static struct dentry *next_dentry(struct dentry *p, struct dentry *root) 96static struct dentry *get_next_positive_dentry(struct dentry *prev,
97 struct dentry *root)
98{ 98{
99 struct list_head *next = p->d_subdirs.next; 99 struct list_head *next;
100 struct dentry *p, *ret;
101
102 if (prev == NULL)
103 return dget(prev);
100 104
105 spin_lock(&dcache_lock);
106relock:
107 p = prev;
108 spin_lock(&p->d_lock);
109again:
110 next = p->d_subdirs.next;
101 if (next == &p->d_subdirs) { 111 if (next == &p->d_subdirs) {
102 while (1) { 112 while (1) {
103 if (p == root) 113 struct dentry *parent;
114
115 if (p == root) {
116 spin_unlock(&p->d_lock);
117 spin_unlock(&dcache_lock);
118 dput(prev);
104 return NULL; 119 return NULL;
120 }
121
122 parent = p->d_parent;
123 if (!spin_trylock(&parent->d_lock)) {
124 spin_unlock(&p->d_lock);
125 cpu_relax();
126 goto relock;
127 }
128 spin_unlock(&p->d_lock);
105 next = p->d_u.d_child.next; 129 next = p->d_u.d_child.next;
106 if (next != &p->d_parent->d_subdirs) 130 p = parent;
131 if (next != &parent->d_subdirs)
107 break; 132 break;
108 p = p->d_parent;
109 } 133 }
110 } 134 }
111 return list_entry(next, struct dentry, d_u.d_child); 135 ret = list_entry(next, struct dentry, d_u.d_child);
136
137 spin_lock_nested(&ret->d_lock, DENTRY_D_LOCK_NESTED);
138 /* Negative dentry - try next */
139 if (!simple_positive(ret)) {
140 spin_unlock(&ret->d_lock);
141 p = ret;
142 goto again;
143 }
144 dget_dlock(ret);
145 spin_unlock(&ret->d_lock);
146 spin_unlock(&p->d_lock);
147 spin_unlock(&dcache_lock);
148
149 dput(prev);
150
151 return ret;
112} 152}
113 153
114/* 154/*
@@ -158,22 +198,11 @@ static int autofs4_tree_busy(struct vfsmount *mnt,
158 if (!simple_positive(top)) 198 if (!simple_positive(top))
159 return 1; 199 return 1;
160 200
161 spin_lock(&dcache_lock); 201 p = NULL;
162 for (p = top; p; p = next_dentry(p, top)) { 202 while ((p = get_next_positive_dentry(p, top))) {
163 spin_lock(&p->d_lock);
164 /* Negative dentry - give up */
165 if (!simple_positive(p)) {
166 spin_unlock(&p->d_lock);
167 continue;
168 }
169
170 DPRINTK("dentry %p %.*s", 203 DPRINTK("dentry %p %.*s",
171 p, (int) p->d_name.len, p->d_name.name); 204 p, (int) p->d_name.len, p->d_name.name);
172 205
173 p = dget_dlock(p);
174 spin_unlock(&p->d_lock);
175 spin_unlock(&dcache_lock);
176
177 /* 206 /*
178 * Is someone visiting anywhere in the subtree ? 207 * Is someone visiting anywhere in the subtree ?
179 * If there's no mount we need to check the usage 208 * If there's no mount we need to check the usage
@@ -208,10 +237,7 @@ static int autofs4_tree_busy(struct vfsmount *mnt,
208 return 1; 237 return 1;
209 } 238 }
210 } 239 }
211 dput(p);
212 spin_lock(&dcache_lock);
213 } 240 }
214 spin_unlock(&dcache_lock);
215 241
216 /* Timeout of a tree mount is ultimately determined by its top dentry */ 242 /* Timeout of a tree mount is ultimately determined by its top dentry */
217 if (!autofs4_can_expire(top, timeout, do_now)) 243 if (!autofs4_can_expire(top, timeout, do_now))
@@ -230,36 +256,21 @@ static struct dentry *autofs4_check_leaves(struct vfsmount *mnt,
230 DPRINTK("parent %p %.*s", 256 DPRINTK("parent %p %.*s",
231 parent, (int)parent->d_name.len, parent->d_name.name); 257 parent, (int)parent->d_name.len, parent->d_name.name);
232 258
233 spin_lock(&dcache_lock); 259 p = NULL;
234 for (p = parent; p; p = next_dentry(p, parent)) { 260 while ((p = get_next_positive_dentry(p, parent))) {
235 spin_lock(&p->d_lock);
236 /* Negative dentry - give up */
237 if (!simple_positive(p)) {
238 spin_unlock(&p->d_lock);
239 continue;
240 }
241
242 DPRINTK("dentry %p %.*s", 261 DPRINTK("dentry %p %.*s",
243 p, (int) p->d_name.len, p->d_name.name); 262 p, (int) p->d_name.len, p->d_name.name);
244 263
245 p = dget_dlock(p);
246 spin_unlock(&p->d_lock);
247 spin_unlock(&dcache_lock);
248
249 if (d_mountpoint(p)) { 264 if (d_mountpoint(p)) {
250 /* Can we umount this guy */ 265 /* Can we umount this guy */
251 if (autofs4_mount_busy(mnt, p)) 266 if (autofs4_mount_busy(mnt, p))
252 goto cont; 267 continue;
253 268
254 /* Can we expire this guy */ 269 /* Can we expire this guy */
255 if (autofs4_can_expire(p, timeout, do_now)) 270 if (autofs4_can_expire(p, timeout, do_now))
256 return p; 271 return p;
257 } 272 }
258cont:
259 dput(p);
260 spin_lock(&dcache_lock);
261 } 273 }
262 spin_unlock(&dcache_lock);
263 return NULL; 274 return NULL;
264} 275}
265 276
@@ -310,8 +321,8 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
310{ 321{
311 unsigned long timeout; 322 unsigned long timeout;
312 struct dentry *root = sb->s_root; 323 struct dentry *root = sb->s_root;
324 struct dentry *dentry;
313 struct dentry *expired = NULL; 325 struct dentry *expired = NULL;
314 struct list_head *next;
315 int do_now = how & AUTOFS_EXP_IMMEDIATE; 326 int do_now = how & AUTOFS_EXP_IMMEDIATE;
316 int exp_leaves = how & AUTOFS_EXP_LEAVES; 327 int exp_leaves = how & AUTOFS_EXP_LEAVES;
317 struct autofs_info *ino; 328 struct autofs_info *ino;
@@ -323,26 +334,8 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
323 now = jiffies; 334 now = jiffies;
324 timeout = sbi->exp_timeout; 335 timeout = sbi->exp_timeout;
325 336
326 spin_lock(&dcache_lock); 337 dentry = NULL;
327 next = root->d_subdirs.next; 338 while ((dentry = get_next_positive_dentry(dentry, root))) {
328
329 /* On exit from the loop expire is set to a dgot dentry
330 * to expire or it's NULL */
331 while ( next != &root->d_subdirs ) {
332 struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child);
333
334 /* Negative dentry - give up */
335 spin_lock(&dentry->d_lock);
336 if (!simple_positive(dentry)) {
337 next = next->next;
338 spin_unlock(&dentry->d_lock);
339 continue;
340 }
341
342 dentry = dget_dlock(dentry);
343 spin_unlock(&dentry->d_lock);
344 spin_unlock(&dcache_lock);
345
346 spin_lock(&sbi->fs_lock); 339 spin_lock(&sbi->fs_lock);
347 ino = autofs4_dentry_ino(dentry); 340 ino = autofs4_dentry_ino(dentry);
348 341
@@ -405,11 +398,7 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
405 } 398 }
406next: 399next:
407 spin_unlock(&sbi->fs_lock); 400 spin_unlock(&sbi->fs_lock);
408 dput(dentry);
409 spin_lock(&dcache_lock);
410 next = next->next;
411 } 401 }
412 spin_unlock(&dcache_lock);
413 return NULL; 402 return NULL;
414 403
415found: 404found:
@@ -420,7 +409,11 @@ found:
420 init_completion(&ino->expire_complete); 409 init_completion(&ino->expire_complete);
421 spin_unlock(&sbi->fs_lock); 410 spin_unlock(&sbi->fs_lock);
422 spin_lock(&dcache_lock); 411 spin_lock(&dcache_lock);
412 spin_lock(&expired->d_parent->d_lock);
413 spin_lock_nested(&expired->d_lock, DENTRY_D_LOCK_NESTED);
423 list_move(&expired->d_parent->d_subdirs, &expired->d_u.d_child); 414 list_move(&expired->d_parent->d_subdirs, &expired->d_u.d_child);
415 spin_unlock(&expired->d_lock);
416 spin_unlock(&expired->d_parent->d_lock);
424 spin_unlock(&dcache_lock); 417 spin_unlock(&dcache_lock);
425 return expired; 418 return expired;
426} 419}
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 7922509b5b2b..7a9ed6b88291 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -143,10 +143,13 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
143 * it. 143 * it.
144 */ 144 */
145 spin_lock(&dcache_lock); 145 spin_lock(&dcache_lock);
146 spin_lock(&dentry->d_lock);
146 if (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) { 147 if (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) {
148 spin_unlock(&dentry->d_lock);
147 spin_unlock(&dcache_lock); 149 spin_unlock(&dcache_lock);
148 return -ENOENT; 150 return -ENOENT;
149 } 151 }
152 spin_unlock(&dentry->d_lock);
150 spin_unlock(&dcache_lock); 153 spin_unlock(&dcache_lock);
151 154
152out: 155out:
@@ -253,7 +256,9 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
253 lookup_type = autofs4_need_mount(nd->flags); 256 lookup_type = autofs4_need_mount(nd->flags);
254 spin_lock(&sbi->fs_lock); 257 spin_lock(&sbi->fs_lock);
255 spin_lock(&dcache_lock); 258 spin_lock(&dcache_lock);
259 spin_lock(&dentry->d_lock);
256 if (!(lookup_type || ino->flags & AUTOFS_INF_PENDING)) { 260 if (!(lookup_type || ino->flags & AUTOFS_INF_PENDING)) {
261 spin_unlock(&dentry->d_lock);
257 spin_unlock(&dcache_lock); 262 spin_unlock(&dcache_lock);
258 spin_unlock(&sbi->fs_lock); 263 spin_unlock(&sbi->fs_lock);
259 goto follow; 264 goto follow;
@@ -266,6 +271,7 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
266 */ 271 */
267 if (ino->flags & AUTOFS_INF_PENDING || 272 if (ino->flags & AUTOFS_INF_PENDING ||
268 (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs))) { 273 (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs))) {
274 spin_unlock(&dentry->d_lock);
269 spin_unlock(&dcache_lock); 275 spin_unlock(&dcache_lock);
270 spin_unlock(&sbi->fs_lock); 276 spin_unlock(&sbi->fs_lock);
271 277
@@ -275,6 +281,7 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd)
275 281
276 goto follow; 282 goto follow;
277 } 283 }
284 spin_unlock(&dentry->d_lock);
278 spin_unlock(&dcache_lock); 285 spin_unlock(&dcache_lock);
279 spin_unlock(&sbi->fs_lock); 286 spin_unlock(&sbi->fs_lock);
280follow: 287follow:
@@ -347,10 +354,12 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
347 354
348 /* Check for a non-mountpoint directory with no contents */ 355 /* Check for a non-mountpoint directory with no contents */
349 spin_lock(&dcache_lock); 356 spin_lock(&dcache_lock);
357 spin_lock(&dentry->d_lock);
350 if (S_ISDIR(dentry->d_inode->i_mode) && 358 if (S_ISDIR(dentry->d_inode->i_mode) &&
351 !d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) { 359 !d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) {
352 DPRINTK("dentry=%p %.*s, emptydir", 360 DPRINTK("dentry=%p %.*s, emptydir",
353 dentry, dentry->d_name.len, dentry->d_name.name); 361 dentry, dentry->d_name.len, dentry->d_name.name);
362 spin_unlock(&dentry->d_lock);
354 spin_unlock(&dcache_lock); 363 spin_unlock(&dcache_lock);
355 364
356 /* The daemon never causes a mount to trigger */ 365 /* The daemon never causes a mount to trigger */
@@ -367,6 +376,7 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
367 376
368 return status; 377 return status;
369 } 378 }
379 spin_unlock(&dentry->d_lock);
370 spin_unlock(&dcache_lock); 380 spin_unlock(&dcache_lock);
371 381
372 return 1; 382 return 1;
@@ -776,12 +786,16 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
776 return -EACCES; 786 return -EACCES;
777 787
778 spin_lock(&dcache_lock); 788 spin_lock(&dcache_lock);
789 spin_lock(&sbi->lookup_lock);
790 spin_lock(&dentry->d_lock);
779 if (!list_empty(&dentry->d_subdirs)) { 791 if (!list_empty(&dentry->d_subdirs)) {
792 spin_unlock(&dentry->d_lock);
793 spin_unlock(&sbi->lookup_lock);
780 spin_unlock(&dcache_lock); 794 spin_unlock(&dcache_lock);
781 return -ENOTEMPTY; 795 return -ENOTEMPTY;
782 } 796 }
783 autofs4_add_expiring(dentry); 797 __autofs4_add_expiring(dentry);
784 spin_lock(&dentry->d_lock); 798 spin_unlock(&sbi->lookup_lock);
785 __d_drop(dentry); 799 __d_drop(dentry);
786 spin_unlock(&dentry->d_lock); 800 spin_unlock(&dentry->d_lock);
787 spin_unlock(&dcache_lock); 801 spin_unlock(&dcache_lock);