diff options
Diffstat (limited to 'fs/autofs4')
-rw-r--r-- | fs/autofs4/autofs_i.h | 1 | ||||
-rw-r--r-- | fs/autofs4/inode.c | 73 |
2 files changed, 74 insertions, 0 deletions
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index 9c09641ce907..fca83e28edcf 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h | |||
@@ -92,6 +92,7 @@ struct autofs_wait_queue { | |||
92 | 92 | ||
93 | struct autofs_sb_info { | 93 | struct autofs_sb_info { |
94 | u32 magic; | 94 | u32 magic; |
95 | struct dentry *root; | ||
95 | struct file *pipe; | 96 | struct file *pipe; |
96 | pid_t oz_pgrp; | 97 | pid_t oz_pgrp; |
97 | int catatonic; | 98 | int catatonic; |
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index 4bb14cc68040..0a3c05d10167 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/pagemap.h> | 16 | #include <linux/pagemap.h> |
17 | #include <linux/parser.h> | 17 | #include <linux/parser.h> |
18 | #include <linux/bitops.h> | 18 | #include <linux/bitops.h> |
19 | #include <linux/smp_lock.h> | ||
19 | #include "autofs_i.h" | 20 | #include "autofs_i.h" |
20 | #include <linux/module.h> | 21 | #include <linux/module.h> |
21 | 22 | ||
@@ -76,6 +77,66 @@ void autofs4_free_ino(struct autofs_info *ino) | |||
76 | kfree(ino); | 77 | kfree(ino); |
77 | } | 78 | } |
78 | 79 | ||
80 | /* | ||
81 | * Deal with the infamous "Busy inodes after umount ..." message. | ||
82 | * | ||
83 | * Clean up the dentry tree. This happens with autofs if the user | ||
84 | * space program goes away due to a SIGKILL, SIGSEGV etc. | ||
85 | */ | ||
86 | static void autofs4_force_release(struct autofs_sb_info *sbi) | ||
87 | { | ||
88 | struct dentry *this_parent = sbi->root; | ||
89 | struct list_head *next; | ||
90 | |||
91 | spin_lock(&dcache_lock); | ||
92 | repeat: | ||
93 | next = this_parent->d_subdirs.next; | ||
94 | resume: | ||
95 | while (next != &this_parent->d_subdirs) { | ||
96 | struct dentry *dentry = list_entry(next, struct dentry, d_child); | ||
97 | |||
98 | /* Negative dentry - don`t care */ | ||
99 | if (!simple_positive(dentry)) { | ||
100 | next = next->next; | ||
101 | continue; | ||
102 | } | ||
103 | |||
104 | if (!list_empty(&dentry->d_subdirs)) { | ||
105 | this_parent = dentry; | ||
106 | goto repeat; | ||
107 | } | ||
108 | |||
109 | next = next->next; | ||
110 | spin_unlock(&dcache_lock); | ||
111 | |||
112 | DPRINTK("dentry %p %.*s", | ||
113 | dentry, (int)dentry->d_name.len, dentry->d_name.name); | ||
114 | |||
115 | dput(dentry); | ||
116 | spin_lock(&dcache_lock); | ||
117 | } | ||
118 | |||
119 | if (this_parent != sbi->root) { | ||
120 | struct dentry *dentry = this_parent; | ||
121 | |||
122 | next = this_parent->d_child.next; | ||
123 | this_parent = this_parent->d_parent; | ||
124 | spin_unlock(&dcache_lock); | ||
125 | DPRINTK("parent dentry %p %.*s", | ||
126 | dentry, (int)dentry->d_name.len, dentry->d_name.name); | ||
127 | dput(dentry); | ||
128 | spin_lock(&dcache_lock); | ||
129 | goto resume; | ||
130 | } | ||
131 | spin_unlock(&dcache_lock); | ||
132 | |||
133 | dput(sbi->root); | ||
134 | sbi->root = NULL; | ||
135 | shrink_dcache_sb(sbi->sb); | ||
136 | |||
137 | return; | ||
138 | } | ||
139 | |||
79 | static void autofs4_put_super(struct super_block *sb) | 140 | static void autofs4_put_super(struct super_block *sb) |
80 | { | 141 | { |
81 | struct autofs_sb_info *sbi = autofs4_sbi(sb); | 142 | struct autofs_sb_info *sbi = autofs4_sbi(sb); |
@@ -85,6 +146,10 @@ static void autofs4_put_super(struct super_block *sb) | |||
85 | if ( !sbi->catatonic ) | 146 | if ( !sbi->catatonic ) |
86 | autofs4_catatonic_mode(sbi); /* Free wait queues, close pipe */ | 147 | autofs4_catatonic_mode(sbi); /* Free wait queues, close pipe */ |
87 | 148 | ||
149 | /* Clean up and release dangling references */ | ||
150 | if (sbi) | ||
151 | autofs4_force_release(sbi); | ||
152 | |||
88 | kfree(sbi); | 153 | kfree(sbi); |
89 | 154 | ||
90 | DPRINTK("shutting down"); | 155 | DPRINTK("shutting down"); |
@@ -199,6 +264,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) | |||
199 | 264 | ||
200 | s->s_fs_info = sbi; | 265 | s->s_fs_info = sbi; |
201 | sbi->magic = AUTOFS_SBI_MAGIC; | 266 | sbi->magic = AUTOFS_SBI_MAGIC; |
267 | sbi->root = NULL; | ||
202 | sbi->catatonic = 0; | 268 | sbi->catatonic = 0; |
203 | sbi->exp_timeout = 0; | 269 | sbi->exp_timeout = 0; |
204 | sbi->oz_pgrp = process_group(current); | 270 | sbi->oz_pgrp = process_group(current); |
@@ -267,6 +333,13 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) | |||
267 | sbi->pipe = pipe; | 333 | sbi->pipe = pipe; |
268 | 334 | ||
269 | /* | 335 | /* |
336 | * Take a reference to the root dentry so we get a chance to | ||
337 | * clean up the dentry tree on umount. | ||
338 | * See autofs4_force_release. | ||
339 | */ | ||
340 | sbi->root = dget(root); | ||
341 | |||
342 | /* | ||
270 | * Success! Install the root dentry now to indicate completion. | 343 | * Success! Install the root dentry now to indicate completion. |
271 | */ | 344 | */ |
272 | s->s_root = root; | 345 | s->s_root = root; |