diff options
-rw-r--r-- | fs/autofs4/autofs_i.h | 3 | ||||
-rw-r--r-- | fs/autofs4/expire.c | 2 | ||||
-rw-r--r-- | fs/autofs4/root.c | 58 |
3 files changed, 35 insertions, 28 deletions
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index fe9fc235ee75..3d283abf67d7 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h | |||
@@ -97,6 +97,7 @@ struct autofs_info { | |||
97 | 97 | ||
98 | #define AUTOFS_INF_EXPIRING (1<<0) /* dentry is in the process of expiring */ | 98 | #define AUTOFS_INF_EXPIRING (1<<0) /* dentry is in the process of expiring */ |
99 | #define AUTOFS_INF_MOUNTPOINT (1<<1) /* mountpoint status for direct expire */ | 99 | #define AUTOFS_INF_MOUNTPOINT (1<<1) /* mountpoint status for direct expire */ |
100 | #define AUTOFS_INF_PENDING (1<<2) /* dentry pending mount */ | ||
100 | 101 | ||
101 | struct autofs_wait_queue { | 102 | struct autofs_wait_queue { |
102 | wait_queue_head_t queue; | 103 | wait_queue_head_t queue; |
@@ -163,7 +164,7 @@ static inline int autofs4_ispending(struct dentry *dentry) | |||
163 | { | 164 | { |
164 | struct autofs_info *inf = autofs4_dentry_ino(dentry); | 165 | struct autofs_info *inf = autofs4_dentry_ino(dentry); |
165 | 166 | ||
166 | if (dentry->d_flags & DCACHE_AUTOFS_PENDING) | 167 | if (inf->flags & AUTOFS_INF_PENDING) |
167 | return 1; | 168 | return 1; |
168 | 169 | ||
169 | if (inf->flags & AUTOFS_INF_EXPIRING) | 170 | if (inf->flags & AUTOFS_INF_EXPIRING) |
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index 3da18d453488..a796c9417fb1 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c | |||
@@ -27,7 +27,7 @@ static inline int autofs4_can_expire(struct dentry *dentry, | |||
27 | return 0; | 27 | return 0; |
28 | 28 | ||
29 | /* No point expiring a pending mount */ | 29 | /* No point expiring a pending mount */ |
30 | if (dentry->d_flags & DCACHE_AUTOFS_PENDING) | 30 | if (ino->flags & AUTOFS_INF_PENDING) |
31 | return 0; | 31 | return 0; |
32 | 32 | ||
33 | if (!do_now) { | 33 | if (!do_now) { |
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index f6e8ca9ea56a..305136ba74b6 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
@@ -166,32 +166,32 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags) | |||
166 | 166 | ||
167 | /* Turn this into a real negative dentry? */ | 167 | /* Turn this into a real negative dentry? */ |
168 | if (status == -ENOENT) { | 168 | if (status == -ENOENT) { |
169 | spin_lock(&dentry->d_lock); | 169 | spin_lock(&sbi->fs_lock); |
170 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; | 170 | ino->flags &= ~AUTOFS_INF_PENDING; |
171 | spin_unlock(&dentry->d_lock); | 171 | spin_unlock(&sbi->fs_lock); |
172 | return status; | 172 | return status; |
173 | } else if (status) { | 173 | } else if (status) { |
174 | /* Return a negative dentry, but leave it "pending" */ | 174 | /* Return a negative dentry, but leave it "pending" */ |
175 | return status; | 175 | return status; |
176 | } | 176 | } |
177 | /* Trigger mount for path component or follow link */ | 177 | /* Trigger mount for path component or follow link */ |
178 | } else if (dentry->d_flags & DCACHE_AUTOFS_PENDING || | 178 | } else if (ino->flags & AUTOFS_INF_PENDING || |
179 | autofs4_need_mount(flags) || | 179 | autofs4_need_mount(flags) || |
180 | current->link_count) { | 180 | current->link_count) { |
181 | DPRINTK("waiting for mount name=%.*s", | 181 | DPRINTK("waiting for mount name=%.*s", |
182 | dentry->d_name.len, dentry->d_name.name); | 182 | dentry->d_name.len, dentry->d_name.name); |
183 | 183 | ||
184 | spin_lock(&dentry->d_lock); | 184 | spin_lock(&sbi->fs_lock); |
185 | dentry->d_flags |= DCACHE_AUTOFS_PENDING; | 185 | ino->flags |= AUTOFS_INF_PENDING; |
186 | spin_unlock(&dentry->d_lock); | 186 | spin_unlock(&sbi->fs_lock); |
187 | status = autofs4_wait(sbi, dentry, NFY_MOUNT); | 187 | status = autofs4_wait(sbi, dentry, NFY_MOUNT); |
188 | 188 | ||
189 | DPRINTK("mount done status=%d", status); | 189 | DPRINTK("mount done status=%d", status); |
190 | 190 | ||
191 | if (status) { | 191 | if (status) { |
192 | spin_lock(&dentry->d_lock); | 192 | spin_lock(&sbi->fs_lock); |
193 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; | 193 | ino->flags &= ~AUTOFS_INF_PENDING; |
194 | spin_unlock(&dentry->d_lock); | 194 | spin_unlock(&sbi->fs_lock); |
195 | return status; | 195 | return status; |
196 | } | 196 | } |
197 | } | 197 | } |
@@ -200,9 +200,9 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags) | |||
200 | if (ino) | 200 | if (ino) |
201 | ino->last_used = jiffies; | 201 | ino->last_used = jiffies; |
202 | 202 | ||
203 | spin_lock(&dentry->d_lock); | 203 | spin_lock(&sbi->fs_lock); |
204 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; | 204 | ino->flags &= ~AUTOFS_INF_PENDING; |
205 | spin_unlock(&dentry->d_lock); | 205 | spin_unlock(&sbi->fs_lock); |
206 | 206 | ||
207 | return 0; | 207 | return 0; |
208 | } | 208 | } |
@@ -243,18 +243,23 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
243 | 243 | ||
244 | /* We trigger a mount for almost all flags */ | 244 | /* We trigger a mount for almost all flags */ |
245 | lookup_type = autofs4_need_mount(nd->flags); | 245 | lookup_type = autofs4_need_mount(nd->flags); |
246 | if (!(lookup_type || dentry->d_flags & DCACHE_AUTOFS_PENDING)) | 246 | spin_lock(&sbi->fs_lock); |
247 | spin_lock(&dcache_lock); | ||
248 | if (!(lookup_type || ino->flags & AUTOFS_INF_PENDING)) { | ||
249 | spin_unlock(&dcache_lock); | ||
250 | spin_unlock(&sbi->fs_lock); | ||
247 | goto follow; | 251 | goto follow; |
252 | } | ||
248 | 253 | ||
249 | /* | 254 | /* |
250 | * If the dentry contains directories then it is an autofs | 255 | * If the dentry contains directories then it is an autofs |
251 | * multi-mount with no root mount offset. So don't try to | 256 | * multi-mount with no root mount offset. So don't try to |
252 | * mount it again. | 257 | * mount it again. |
253 | */ | 258 | */ |
254 | spin_lock(&dcache_lock); | 259 | if (ino->flags & AUTOFS_INF_PENDING || |
255 | if (dentry->d_flags & DCACHE_AUTOFS_PENDING || | ||
256 | (!d_mountpoint(dentry) && __simple_empty(dentry))) { | 260 | (!d_mountpoint(dentry) && __simple_empty(dentry))) { |
257 | spin_unlock(&dcache_lock); | 261 | spin_unlock(&dcache_lock); |
262 | spin_unlock(&sbi->fs_lock); | ||
258 | 263 | ||
259 | status = try_to_fill_dentry(dentry, 0); | 264 | status = try_to_fill_dentry(dentry, 0); |
260 | if (status) | 265 | if (status) |
@@ -263,6 +268,7 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
263 | goto follow; | 268 | goto follow; |
264 | } | 269 | } |
265 | spin_unlock(&dcache_lock); | 270 | spin_unlock(&dcache_lock); |
271 | spin_unlock(&sbi->fs_lock); | ||
266 | follow: | 272 | follow: |
267 | /* | 273 | /* |
268 | * If there is no root mount it must be an autofs | 274 | * If there is no root mount it must be an autofs |
@@ -525,9 +531,10 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
525 | current->pid, task_pgrp_nr(current), sbi->catatonic, oz_mode); | 531 | current->pid, task_pgrp_nr(current), sbi->catatonic, oz_mode); |
526 | 532 | ||
527 | unhashed = autofs4_lookup_active(sbi, dentry->d_parent, &dentry->d_name); | 533 | unhashed = autofs4_lookup_active(sbi, dentry->d_parent, &dentry->d_name); |
528 | if (unhashed) | 534 | if (unhashed) { |
529 | dentry = unhashed; | 535 | dentry = unhashed; |
530 | else { | 536 | ino = autofs4_dentry_ino(dentry); |
537 | } else { | ||
531 | /* | 538 | /* |
532 | * Mark the dentry incomplete but don't hash it. We do this | 539 | * Mark the dentry incomplete but don't hash it. We do this |
533 | * to serialize our inode creation operations (symlink and | 540 | * to serialize our inode creation operations (symlink and |
@@ -569,15 +576,14 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
569 | * be quite complete but the directory has been removed | 576 | * be quite complete but the directory has been removed |
570 | * so it must have been successful, so just wait for it. | 577 | * so it must have been successful, so just wait for it. |
571 | */ | 578 | */ |
572 | ino = autofs4_dentry_ino(expiring); | ||
573 | autofs4_expire_wait(expiring); | 579 | autofs4_expire_wait(expiring); |
574 | autofs4_del_expiring(expiring); | 580 | autofs4_del_expiring(expiring); |
575 | dput(expiring); | 581 | dput(expiring); |
576 | } | 582 | } |
577 | 583 | ||
578 | spin_lock(&dentry->d_lock); | 584 | spin_lock(&sbi->fs_lock); |
579 | dentry->d_flags |= DCACHE_AUTOFS_PENDING; | 585 | ino->flags |= AUTOFS_INF_PENDING; |
580 | spin_unlock(&dentry->d_lock); | 586 | spin_unlock(&sbi->fs_lock); |
581 | if (dentry->d_op && dentry->d_op->d_revalidate) | 587 | if (dentry->d_op && dentry->d_op->d_revalidate) |
582 | (dentry->d_op->d_revalidate)(dentry, nd); | 588 | (dentry->d_op->d_revalidate)(dentry, nd); |
583 | mutex_lock(&dir->i_mutex); | 589 | mutex_lock(&dir->i_mutex); |
@@ -587,7 +593,7 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
587 | * If we are still pending, check if we had to handle | 593 | * If we are still pending, check if we had to handle |
588 | * a signal. If so we can force a restart.. | 594 | * a signal. If so we can force a restart.. |
589 | */ | 595 | */ |
590 | if (dentry->d_flags & DCACHE_AUTOFS_PENDING) { | 596 | if (ino->flags & AUTOFS_INF_PENDING) { |
591 | /* See if we were interrupted */ | 597 | /* See if we were interrupted */ |
592 | if (signal_pending(current)) { | 598 | if (signal_pending(current)) { |
593 | sigset_t *sigset = ¤t->pending.signal; | 599 | sigset_t *sigset = ¤t->pending.signal; |
@@ -600,9 +606,9 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
600 | } | 606 | } |
601 | } | 607 | } |
602 | if (!oz_mode) { | 608 | if (!oz_mode) { |
603 | spin_lock(&dentry->d_lock); | 609 | spin_lock(&sbi->fs_lock); |
604 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; | 610 | ino->flags &= ~AUTOFS_INF_PENDING; |
605 | spin_unlock(&dentry->d_lock); | 611 | spin_unlock(&sbi->fs_lock); |
606 | } | 612 | } |
607 | } | 613 | } |
608 | 614 | ||