diff options
author | Ian Kent <raven@themaw.net> | 2006-11-14 05:03:29 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-11-14 12:09:27 -0500 |
commit | ba8df43c0ee93ec05fc526278a80aaf4cb5ab1fa (patch) | |
tree | 510db3f9141e0bf091eccaf7ef7a0db3c81338bb | |
parent | 6a34b57bec41c95f1e38f700cd9b81324baaffc7 (diff) |
[PATCH] autofs4: panic after mount fail
Resolve the panic on failed mount of an autofs filesystem originally
reported by Mao Bibo.
It addresses two issues that happen after the mount fail. The first a NULL
pointer reference to a field (pipe) in the autofs superblock info structure
and second the lack of super block cleanup by the autofs and autofs4
modules.
Signed-off-by: Ian Kent <raven@themaw.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | fs/autofs/inode.c | 14 | ||||
-rw-r--r-- | fs/autofs/waitq.c | 1 | ||||
-rw-r--r-- | fs/autofs4/inode.c | 17 | ||||
-rw-r--r-- | fs/autofs4/waitq.c | 6 |
4 files changed, 32 insertions, 6 deletions
diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c index 54c518c89e4c..38ede5c9d6fd 100644 --- a/fs/autofs/inode.c +++ b/fs/autofs/inode.c | |||
@@ -25,6 +25,14 @@ void autofs_kill_sb(struct super_block *sb) | |||
25 | struct autofs_sb_info *sbi = autofs_sbi(sb); | 25 | struct autofs_sb_info *sbi = autofs_sbi(sb); |
26 | unsigned int n; | 26 | unsigned int n; |
27 | 27 | ||
28 | /* | ||
29 | * In the event of a failure in get_sb_nodev the superblock | ||
30 | * info is not present so nothing else has been setup, so | ||
31 | * just exit when we are called from deactivate_super. | ||
32 | */ | ||
33 | if (!sbi) | ||
34 | return; | ||
35 | |||
28 | if ( !sbi->catatonic ) | 36 | if ( !sbi->catatonic ) |
29 | autofs_catatonic_mode(sbi); /* Free wait queues, close pipe */ | 37 | autofs_catatonic_mode(sbi); /* Free wait queues, close pipe */ |
30 | 38 | ||
@@ -136,7 +144,8 @@ int autofs_fill_super(struct super_block *s, void *data, int silent) | |||
136 | 144 | ||
137 | s->s_fs_info = sbi; | 145 | s->s_fs_info = sbi; |
138 | sbi->magic = AUTOFS_SBI_MAGIC; | 146 | sbi->magic = AUTOFS_SBI_MAGIC; |
139 | sbi->catatonic = 0; | 147 | sbi->pipe = NULL; |
148 | sbi->catatonic = 1; | ||
140 | sbi->exp_timeout = 0; | 149 | sbi->exp_timeout = 0; |
141 | sbi->oz_pgrp = process_group(current); | 150 | sbi->oz_pgrp = process_group(current); |
142 | autofs_initialize_hash(&sbi->dirhash); | 151 | autofs_initialize_hash(&sbi->dirhash); |
@@ -180,6 +189,7 @@ int autofs_fill_super(struct super_block *s, void *data, int silent) | |||
180 | if ( !pipe->f_op || !pipe->f_op->write ) | 189 | if ( !pipe->f_op || !pipe->f_op->write ) |
181 | goto fail_fput; | 190 | goto fail_fput; |
182 | sbi->pipe = pipe; | 191 | sbi->pipe = pipe; |
192 | sbi->catatonic = 0; | ||
183 | 193 | ||
184 | /* | 194 | /* |
185 | * Success! Install the root dentry now to indicate completion. | 195 | * Success! Install the root dentry now to indicate completion. |
@@ -198,6 +208,8 @@ fail_iput: | |||
198 | iput(root_inode); | 208 | iput(root_inode); |
199 | fail_free: | 209 | fail_free: |
200 | kfree(sbi); | 210 | kfree(sbi); |
211 | s->s_fs_info = NULL; | ||
212 | kill_anon_super(s); | ||
201 | fail_unlock: | 213 | fail_unlock: |
202 | return -EINVAL; | 214 | return -EINVAL; |
203 | } | 215 | } |
diff --git a/fs/autofs/waitq.c b/fs/autofs/waitq.c index 633f628005b4..19a9cafb5ddf 100644 --- a/fs/autofs/waitq.c +++ b/fs/autofs/waitq.c | |||
@@ -41,6 +41,7 @@ void autofs_catatonic_mode(struct autofs_sb_info *sbi) | |||
41 | wq = nwq; | 41 | wq = nwq; |
42 | } | 42 | } |
43 | fput(sbi->pipe); /* Close the pipe */ | 43 | fput(sbi->pipe); /* Close the pipe */ |
44 | sbi->pipe = NULL; | ||
44 | autofs_hash_dputall(&sbi->dirhash); /* Remove all dentry pointers */ | 45 | autofs_hash_dputall(&sbi->dirhash); /* Remove all dentry pointers */ |
45 | } | 46 | } |
46 | 47 | ||
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index 51fd8595bf85..ce7c0f1dd529 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c | |||
@@ -99,6 +99,9 @@ static void autofs4_force_release(struct autofs_sb_info *sbi) | |||
99 | struct dentry *this_parent = sbi->sb->s_root; | 99 | struct dentry *this_parent = sbi->sb->s_root; |
100 | struct list_head *next; | 100 | struct list_head *next; |
101 | 101 | ||
102 | if (!sbi->sb->s_root) | ||
103 | return; | ||
104 | |||
102 | spin_lock(&dcache_lock); | 105 | spin_lock(&dcache_lock); |
103 | repeat: | 106 | repeat: |
104 | next = this_parent->d_subdirs.next; | 107 | next = this_parent->d_subdirs.next; |
@@ -146,6 +149,14 @@ void autofs4_kill_sb(struct super_block *sb) | |||
146 | { | 149 | { |
147 | struct autofs_sb_info *sbi = autofs4_sbi(sb); | 150 | struct autofs_sb_info *sbi = autofs4_sbi(sb); |
148 | 151 | ||
152 | /* | ||
153 | * In the event of a failure in get_sb_nodev the superblock | ||
154 | * info is not present so nothing else has been setup, so | ||
155 | * just exit when we are called from deactivate_super. | ||
156 | */ | ||
157 | if (!sbi) | ||
158 | return; | ||
159 | |||
149 | sb->s_fs_info = NULL; | 160 | sb->s_fs_info = NULL; |
150 | 161 | ||
151 | if ( !sbi->catatonic ) | 162 | if ( !sbi->catatonic ) |
@@ -310,7 +321,8 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) | |||
310 | s->s_fs_info = sbi; | 321 | s->s_fs_info = sbi; |
311 | sbi->magic = AUTOFS_SBI_MAGIC; | 322 | sbi->magic = AUTOFS_SBI_MAGIC; |
312 | sbi->pipefd = -1; | 323 | sbi->pipefd = -1; |
313 | sbi->catatonic = 0; | 324 | sbi->pipe = NULL; |
325 | sbi->catatonic = 1; | ||
314 | sbi->exp_timeout = 0; | 326 | sbi->exp_timeout = 0; |
315 | sbi->oz_pgrp = process_group(current); | 327 | sbi->oz_pgrp = process_group(current); |
316 | sbi->sb = s; | 328 | sbi->sb = s; |
@@ -388,6 +400,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) | |||
388 | goto fail_fput; | 400 | goto fail_fput; |
389 | sbi->pipe = pipe; | 401 | sbi->pipe = pipe; |
390 | sbi->pipefd = pipefd; | 402 | sbi->pipefd = pipefd; |
403 | sbi->catatonic = 0; | ||
391 | 404 | ||
392 | /* | 405 | /* |
393 | * Success! Install the root dentry now to indicate completion. | 406 | * Success! Install the root dentry now to indicate completion. |
@@ -412,6 +425,8 @@ fail_ino: | |||
412 | kfree(ino); | 425 | kfree(ino); |
413 | fail_free: | 426 | fail_free: |
414 | kfree(sbi); | 427 | kfree(sbi); |
428 | s->s_fs_info = NULL; | ||
429 | kill_anon_super(s); | ||
415 | fail_unlock: | 430 | fail_unlock: |
416 | return -EINVAL; | 431 | return -EINVAL; |
417 | } | 432 | } |
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c index c0a6c8d445c7..1e4a539f4417 100644 --- a/fs/autofs4/waitq.c +++ b/fs/autofs4/waitq.c | |||
@@ -41,10 +41,8 @@ void autofs4_catatonic_mode(struct autofs_sb_info *sbi) | |||
41 | wake_up_interruptible(&wq->queue); | 41 | wake_up_interruptible(&wq->queue); |
42 | wq = nwq; | 42 | wq = nwq; |
43 | } | 43 | } |
44 | if (sbi->pipe) { | 44 | fput(sbi->pipe); /* Close the pipe */ |
45 | fput(sbi->pipe); /* Close the pipe */ | 45 | sbi->pipe = NULL; |
46 | sbi->pipe = NULL; | ||
47 | } | ||
48 | } | 46 | } |
49 | 47 | ||
50 | static int autofs4_write(struct file *file, const void *addr, int bytes) | 48 | static int autofs4_write(struct file *file, const void *addr, int bytes) |