diff options
Diffstat (limited to 'fs/autofs4/inode.c')
| -rw-r--r-- | fs/autofs4/inode.c | 73 |
1 files changed, 73 insertions, 0 deletions
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; |
