diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /fs/autofs4 | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'fs/autofs4')
-rw-r--r-- | fs/autofs4/autofs_i.h | 31 | ||||
-rw-r--r-- | fs/autofs4/dev-ioctl.c | 12 | ||||
-rw-r--r-- | fs/autofs4/expire.c | 2 | ||||
-rw-r--r-- | fs/autofs4/inode.c | 63 | ||||
-rw-r--r-- | fs/autofs4/root.c | 222 |
5 files changed, 165 insertions, 165 deletions
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index 8f7cdde41733..3d283abf67d7 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h | |||
@@ -75,6 +75,8 @@ struct autofs_info { | |||
75 | struct completion expire_complete; | 75 | struct completion expire_complete; |
76 | 76 | ||
77 | struct list_head active; | 77 | struct list_head active; |
78 | int active_count; | ||
79 | |||
78 | struct list_head expiring; | 80 | struct list_head expiring; |
79 | 81 | ||
80 | struct autofs_sb_info *sbi; | 82 | struct autofs_sb_info *sbi; |
@@ -95,6 +97,7 @@ struct autofs_info { | |||
95 | 97 | ||
96 | #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 */ |
97 | #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 */ | ||
98 | 101 | ||
99 | struct autofs_wait_queue { | 102 | struct autofs_wait_queue { |
100 | wait_queue_head_t queue; | 103 | wait_queue_head_t queue; |
@@ -161,7 +164,7 @@ static inline int autofs4_ispending(struct dentry *dentry) | |||
161 | { | 164 | { |
162 | struct autofs_info *inf = autofs4_dentry_ino(dentry); | 165 | struct autofs_info *inf = autofs4_dentry_ino(dentry); |
163 | 166 | ||
164 | if (dentry->d_flags & DCACHE_AUTOFS_PENDING) | 167 | if (inf->flags & AUTOFS_INF_PENDING) |
165 | return 1; | 168 | return 1; |
166 | 169 | ||
167 | if (inf->flags & AUTOFS_INF_EXPIRING) | 170 | if (inf->flags & AUTOFS_INF_EXPIRING) |
@@ -264,5 +267,31 @@ out: | |||
264 | return ret; | 267 | return ret; |
265 | } | 268 | } |
266 | 269 | ||
270 | static inline void autofs4_add_expiring(struct dentry *dentry) | ||
271 | { | ||
272 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | ||
273 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | ||
274 | if (ino) { | ||
275 | spin_lock(&sbi->lookup_lock); | ||
276 | if (list_empty(&ino->expiring)) | ||
277 | list_add(&ino->expiring, &sbi->expiring_list); | ||
278 | spin_unlock(&sbi->lookup_lock); | ||
279 | } | ||
280 | return; | ||
281 | } | ||
282 | |||
283 | static inline void autofs4_del_expiring(struct dentry *dentry) | ||
284 | { | ||
285 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | ||
286 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | ||
287 | if (ino) { | ||
288 | spin_lock(&sbi->lookup_lock); | ||
289 | if (!list_empty(&ino->expiring)) | ||
290 | list_del_init(&ino->expiring); | ||
291 | spin_unlock(&sbi->lookup_lock); | ||
292 | } | ||
293 | return; | ||
294 | } | ||
295 | |||
267 | void autofs4_dentry_release(struct dentry *); | 296 | void autofs4_dentry_release(struct dentry *); |
268 | extern void autofs4_kill_sb(struct super_block *); | 297 | extern void autofs4_kill_sb(struct super_block *); |
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c index 00bf8fcb245f..d29b7f6df862 100644 --- a/fs/autofs4/dev-ioctl.c +++ b/fs/autofs4/dev-ioctl.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/magic.h> | 22 | #include <linux/magic.h> |
23 | #include <linux/dcache.h> | 23 | #include <linux/dcache.h> |
24 | #include <linux/uaccess.h> | 24 | #include <linux/uaccess.h> |
25 | #include <linux/slab.h> | ||
25 | 26 | ||
26 | #include "autofs_i.h" | 27 | #include "autofs_i.h" |
27 | 28 | ||
@@ -544,10 +545,9 @@ static int autofs_dev_ioctl_ismountpoint(struct file *fp, | |||
544 | goto out; | 545 | goto out; |
545 | devid = new_encode_dev(path.mnt->mnt_sb->s_dev); | 546 | devid = new_encode_dev(path.mnt->mnt_sb->s_dev); |
546 | err = 0; | 547 | err = 0; |
547 | if (path.dentry->d_inode && | 548 | if (path.mnt->mnt_root == path.dentry) { |
548 | path.mnt->mnt_root == path.dentry) { | ||
549 | err = 1; | 549 | err = 1; |
550 | magic = path.dentry->d_inode->i_sb->s_magic; | 550 | magic = path.mnt->mnt_sb->s_magic; |
551 | } | 551 | } |
552 | } else { | 552 | } else { |
553 | dev_t dev = sbi->sb->s_dev; | 553 | dev_t dev = sbi->sb->s_dev; |
@@ -560,10 +560,8 @@ static int autofs_dev_ioctl_ismountpoint(struct file *fp, | |||
560 | 560 | ||
561 | err = have_submounts(path.dentry); | 561 | err = have_submounts(path.dentry); |
562 | 562 | ||
563 | if (path.mnt->mnt_mountpoint != path.mnt->mnt_root) { | 563 | if (follow_down(&path)) |
564 | if (follow_down(&path)) | 564 | magic = path.mnt->mnt_sb->s_magic; |
565 | magic = path.mnt->mnt_sb->s_magic; | ||
566 | } | ||
567 | } | 565 | } |
568 | 566 | ||
569 | param->ismountpoint.out.devid = devid; | 567 | param->ismountpoint.out.devid = devid; |
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/inode.c b/fs/autofs4/inode.c index 69c8142da838..821b2b955dac 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c | |||
@@ -49,6 +49,7 @@ struct autofs_info *autofs4_init_ino(struct autofs_info *ino, | |||
49 | ino->dentry = NULL; | 49 | ino->dentry = NULL; |
50 | ino->size = 0; | 50 | ino->size = 0; |
51 | INIT_LIST_HEAD(&ino->active); | 51 | INIT_LIST_HEAD(&ino->active); |
52 | ino->active_count = 0; | ||
52 | INIT_LIST_HEAD(&ino->expiring); | 53 | INIT_LIST_HEAD(&ino->expiring); |
53 | atomic_set(&ino->count, 0); | 54 | atomic_set(&ino->count, 0); |
54 | } | 55 | } |
@@ -95,63 +96,6 @@ void autofs4_free_ino(struct autofs_info *ino) | |||
95 | kfree(ino); | 96 | kfree(ino); |
96 | } | 97 | } |
97 | 98 | ||
98 | /* | ||
99 | * Deal with the infamous "Busy inodes after umount ..." message. | ||
100 | * | ||
101 | * Clean up the dentry tree. This happens with autofs if the user | ||
102 | * space program goes away due to a SIGKILL, SIGSEGV etc. | ||
103 | */ | ||
104 | static void autofs4_force_release(struct autofs_sb_info *sbi) | ||
105 | { | ||
106 | struct dentry *this_parent = sbi->sb->s_root; | ||
107 | struct list_head *next; | ||
108 | |||
109 | if (!sbi->sb->s_root) | ||
110 | return; | ||
111 | |||
112 | spin_lock(&dcache_lock); | ||
113 | repeat: | ||
114 | next = this_parent->d_subdirs.next; | ||
115 | resume: | ||
116 | while (next != &this_parent->d_subdirs) { | ||
117 | struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child); | ||
118 | |||
119 | /* Negative dentry - don`t care */ | ||
120 | if (!simple_positive(dentry)) { | ||
121 | next = next->next; | ||
122 | continue; | ||
123 | } | ||
124 | |||
125 | if (!list_empty(&dentry->d_subdirs)) { | ||
126 | this_parent = dentry; | ||
127 | goto repeat; | ||
128 | } | ||
129 | |||
130 | next = next->next; | ||
131 | spin_unlock(&dcache_lock); | ||
132 | |||
133 | DPRINTK("dentry %p %.*s", | ||
134 | dentry, (int)dentry->d_name.len, dentry->d_name.name); | ||
135 | |||
136 | dput(dentry); | ||
137 | spin_lock(&dcache_lock); | ||
138 | } | ||
139 | |||
140 | if (this_parent != sbi->sb->s_root) { | ||
141 | struct dentry *dentry = this_parent; | ||
142 | |||
143 | next = this_parent->d_u.d_child.next; | ||
144 | this_parent = this_parent->d_parent; | ||
145 | spin_unlock(&dcache_lock); | ||
146 | DPRINTK("parent dentry %p %.*s", | ||
147 | dentry, (int)dentry->d_name.len, dentry->d_name.name); | ||
148 | dput(dentry); | ||
149 | spin_lock(&dcache_lock); | ||
150 | goto resume; | ||
151 | } | ||
152 | spin_unlock(&dcache_lock); | ||
153 | } | ||
154 | |||
155 | void autofs4_kill_sb(struct super_block *sb) | 99 | void autofs4_kill_sb(struct super_block *sb) |
156 | { | 100 | { |
157 | struct autofs_sb_info *sbi = autofs4_sbi(sb); | 101 | struct autofs_sb_info *sbi = autofs4_sbi(sb); |
@@ -168,15 +112,12 @@ void autofs4_kill_sb(struct super_block *sb) | |||
168 | /* Free wait queues, close pipe */ | 112 | /* Free wait queues, close pipe */ |
169 | autofs4_catatonic_mode(sbi); | 113 | autofs4_catatonic_mode(sbi); |
170 | 114 | ||
171 | /* Clean up and release dangling references */ | ||
172 | autofs4_force_release(sbi); | ||
173 | |||
174 | sb->s_fs_info = NULL; | 115 | sb->s_fs_info = NULL; |
175 | kfree(sbi); | 116 | kfree(sbi); |
176 | 117 | ||
177 | out_kill_sb: | 118 | out_kill_sb: |
178 | DPRINTK("shutting down"); | 119 | DPRINTK("shutting down"); |
179 | kill_anon_super(sb); | 120 | kill_litter_super(sb); |
180 | } | 121 | } |
181 | 122 | ||
182 | static int autofs4_show_options(struct seq_file *m, struct vfsmount *mnt) | 123 | static int autofs4_show_options(struct seq_file *m, struct vfsmount *mnt) |
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index b96a3c57359d..e8e5e63ac950 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/capability.h> | 15 | #include <linux/capability.h> |
16 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
17 | #include <linux/stat.h> | 17 | #include <linux/stat.h> |
18 | #include <linux/slab.h> | ||
18 | #include <linux/param.h> | 19 | #include <linux/param.h> |
19 | #include <linux/time.h> | 20 | #include <linux/time.h> |
20 | #include "autofs_i.h" | 21 | #include "autofs_i.h" |
@@ -72,6 +73,46 @@ const struct inode_operations autofs4_dir_inode_operations = { | |||
72 | .rmdir = autofs4_dir_rmdir, | 73 | .rmdir = autofs4_dir_rmdir, |
73 | }; | 74 | }; |
74 | 75 | ||
76 | static void autofs4_add_active(struct dentry *dentry) | ||
77 | { | ||
78 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | ||
79 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | ||
80 | if (ino) { | ||
81 | spin_lock(&sbi->lookup_lock); | ||
82 | if (!ino->active_count) { | ||
83 | if (list_empty(&ino->active)) | ||
84 | list_add(&ino->active, &sbi->active_list); | ||
85 | } | ||
86 | ino->active_count++; | ||
87 | spin_unlock(&sbi->lookup_lock); | ||
88 | } | ||
89 | return; | ||
90 | } | ||
91 | |||
92 | static void autofs4_del_active(struct dentry *dentry) | ||
93 | { | ||
94 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | ||
95 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | ||
96 | if (ino) { | ||
97 | spin_lock(&sbi->lookup_lock); | ||
98 | ino->active_count--; | ||
99 | if (!ino->active_count) { | ||
100 | if (!list_empty(&ino->active)) | ||
101 | list_del_init(&ino->active); | ||
102 | } | ||
103 | spin_unlock(&sbi->lookup_lock); | ||
104 | } | ||
105 | return; | ||
106 | } | ||
107 | |||
108 | static unsigned int autofs4_need_mount(unsigned int flags) | ||
109 | { | ||
110 | unsigned int res = 0; | ||
111 | if (flags & (TRIGGER_FLAGS | TRIGGER_INTENTS)) | ||
112 | res = 1; | ||
113 | return res; | ||
114 | } | ||
115 | |||
75 | static int autofs4_dir_open(struct inode *inode, struct file *file) | 116 | static int autofs4_dir_open(struct inode *inode, struct file *file) |
76 | { | 117 | { |
77 | struct dentry *dentry = file->f_path.dentry; | 118 | struct dentry *dentry = file->f_path.dentry; |
@@ -93,7 +134,7 @@ static int autofs4_dir_open(struct inode *inode, struct file *file) | |||
93 | * it. | 134 | * it. |
94 | */ | 135 | */ |
95 | spin_lock(&dcache_lock); | 136 | spin_lock(&dcache_lock); |
96 | if (!d_mountpoint(dentry) && __simple_empty(dentry)) { | 137 | if (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) { |
97 | spin_unlock(&dcache_lock); | 138 | spin_unlock(&dcache_lock); |
98 | return -ENOENT; | 139 | return -ENOENT; |
99 | } | 140 | } |
@@ -126,32 +167,31 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags) | |||
126 | 167 | ||
127 | /* Turn this into a real negative dentry? */ | 168 | /* Turn this into a real negative dentry? */ |
128 | if (status == -ENOENT) { | 169 | if (status == -ENOENT) { |
129 | spin_lock(&dentry->d_lock); | 170 | spin_lock(&sbi->fs_lock); |
130 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; | 171 | ino->flags &= ~AUTOFS_INF_PENDING; |
131 | spin_unlock(&dentry->d_lock); | 172 | spin_unlock(&sbi->fs_lock); |
132 | return status; | 173 | return status; |
133 | } else if (status) { | 174 | } else if (status) { |
134 | /* Return a negative dentry, but leave it "pending" */ | 175 | /* Return a negative dentry, but leave it "pending" */ |
135 | return status; | 176 | return status; |
136 | } | 177 | } |
137 | /* Trigger mount for path component or follow link */ | 178 | /* Trigger mount for path component or follow link */ |
138 | } else if (dentry->d_flags & DCACHE_AUTOFS_PENDING || | 179 | } else if (ino->flags & AUTOFS_INF_PENDING || |
139 | flags & (TRIGGER_FLAGS | TRIGGER_INTENTS) || | 180 | autofs4_need_mount(flags)) { |
140 | current->link_count) { | ||
141 | DPRINTK("waiting for mount name=%.*s", | 181 | DPRINTK("waiting for mount name=%.*s", |
142 | dentry->d_name.len, dentry->d_name.name); | 182 | dentry->d_name.len, dentry->d_name.name); |
143 | 183 | ||
144 | spin_lock(&dentry->d_lock); | 184 | spin_lock(&sbi->fs_lock); |
145 | dentry->d_flags |= DCACHE_AUTOFS_PENDING; | 185 | ino->flags |= AUTOFS_INF_PENDING; |
146 | spin_unlock(&dentry->d_lock); | 186 | spin_unlock(&sbi->fs_lock); |
147 | status = autofs4_wait(sbi, dentry, NFY_MOUNT); | 187 | status = autofs4_wait(sbi, dentry, NFY_MOUNT); |
148 | 188 | ||
149 | DPRINTK("mount done status=%d", status); | 189 | DPRINTK("mount done status=%d", status); |
150 | 190 | ||
151 | if (status) { | 191 | if (status) { |
152 | spin_lock(&dentry->d_lock); | 192 | spin_lock(&sbi->fs_lock); |
153 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; | 193 | ino->flags &= ~AUTOFS_INF_PENDING; |
154 | spin_unlock(&dentry->d_lock); | 194 | spin_unlock(&sbi->fs_lock); |
155 | return status; | 195 | return status; |
156 | } | 196 | } |
157 | } | 197 | } |
@@ -160,9 +200,9 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags) | |||
160 | if (ino) | 200 | if (ino) |
161 | ino->last_used = jiffies; | 201 | ino->last_used = jiffies; |
162 | 202 | ||
163 | spin_lock(&dentry->d_lock); | 203 | spin_lock(&sbi->fs_lock); |
164 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; | 204 | ino->flags &= ~AUTOFS_INF_PENDING; |
165 | spin_unlock(&dentry->d_lock); | 205 | spin_unlock(&sbi->fs_lock); |
166 | 206 | ||
167 | return 0; | 207 | return 0; |
168 | } | 208 | } |
@@ -202,27 +242,33 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
202 | autofs4_expire_wait(dentry); | 242 | autofs4_expire_wait(dentry); |
203 | 243 | ||
204 | /* We trigger a mount for almost all flags */ | 244 | /* We trigger a mount for almost all flags */ |
205 | lookup_type = nd->flags & (TRIGGER_FLAGS | TRIGGER_INTENTS); | 245 | lookup_type = autofs4_need_mount(nd->flags); |
206 | 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); | ||
207 | goto follow; | 251 | goto follow; |
252 | } | ||
208 | 253 | ||
209 | /* | 254 | /* |
210 | * If the dentry contains directories then it is an autofs | 255 | * If the dentry contains directories then it is an autofs |
211 | * 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 |
212 | * mount it again. | 257 | * mount it again. |
213 | */ | 258 | */ |
214 | spin_lock(&dcache_lock); | 259 | if (ino->flags & AUTOFS_INF_PENDING || |
215 | if (dentry->d_flags & DCACHE_AUTOFS_PENDING || | 260 | (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs))) { |
216 | (!d_mountpoint(dentry) && __simple_empty(dentry))) { | ||
217 | spin_unlock(&dcache_lock); | 261 | spin_unlock(&dcache_lock); |
262 | spin_unlock(&sbi->fs_lock); | ||
218 | 263 | ||
219 | status = try_to_fill_dentry(dentry, 0); | 264 | status = try_to_fill_dentry(dentry, nd->flags); |
220 | if (status) | 265 | if (status) |
221 | goto out_error; | 266 | goto out_error; |
222 | 267 | ||
223 | goto follow; | 268 | goto follow; |
224 | } | 269 | } |
225 | spin_unlock(&dcache_lock); | 270 | spin_unlock(&dcache_lock); |
271 | spin_unlock(&sbi->fs_lock); | ||
226 | follow: | 272 | follow: |
227 | /* | 273 | /* |
228 | * If there is no root mount it must be an autofs | 274 | * If there is no root mount it must be an autofs |
@@ -294,8 +340,7 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
294 | /* Check for a non-mountpoint directory with no contents */ | 340 | /* Check for a non-mountpoint directory with no contents */ |
295 | spin_lock(&dcache_lock); | 341 | spin_lock(&dcache_lock); |
296 | if (S_ISDIR(dentry->d_inode->i_mode) && | 342 | if (S_ISDIR(dentry->d_inode->i_mode) && |
297 | !d_mountpoint(dentry) && | 343 | !d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) { |
298 | __simple_empty(dentry)) { | ||
299 | DPRINTK("dentry=%p %.*s, emptydir", | 344 | DPRINTK("dentry=%p %.*s, emptydir", |
300 | dentry, dentry->d_name.len, dentry->d_name.name); | 345 | dentry, dentry->d_name.len, dentry->d_name.name); |
301 | spin_unlock(&dcache_lock); | 346 | spin_unlock(&dcache_lock); |
@@ -359,8 +404,11 @@ static const struct dentry_operations autofs4_dentry_operations = { | |||
359 | .d_release = autofs4_dentry_release, | 404 | .d_release = autofs4_dentry_release, |
360 | }; | 405 | }; |
361 | 406 | ||
362 | static struct dentry *autofs4_lookup_active(struct autofs_sb_info *sbi, struct dentry *parent, struct qstr *name) | 407 | static struct dentry *autofs4_lookup_active(struct dentry *dentry) |
363 | { | 408 | { |
409 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | ||
410 | struct dentry *parent = dentry->d_parent; | ||
411 | struct qstr *name = &dentry->d_name; | ||
364 | unsigned int len = name->len; | 412 | unsigned int len = name->len; |
365 | unsigned int hash = name->hash; | 413 | unsigned int hash = name->hash; |
366 | const unsigned char *str = name->name; | 414 | const unsigned char *str = name->name; |
@@ -371,23 +419,23 @@ static struct dentry *autofs4_lookup_active(struct autofs_sb_info *sbi, struct d | |||
371 | head = &sbi->active_list; | 419 | head = &sbi->active_list; |
372 | list_for_each(p, head) { | 420 | list_for_each(p, head) { |
373 | struct autofs_info *ino; | 421 | struct autofs_info *ino; |
374 | struct dentry *dentry; | 422 | struct dentry *active; |
375 | struct qstr *qstr; | 423 | struct qstr *qstr; |
376 | 424 | ||
377 | ino = list_entry(p, struct autofs_info, active); | 425 | ino = list_entry(p, struct autofs_info, active); |
378 | dentry = ino->dentry; | 426 | active = ino->dentry; |
379 | 427 | ||
380 | spin_lock(&dentry->d_lock); | 428 | spin_lock(&active->d_lock); |
381 | 429 | ||
382 | /* Already gone? */ | 430 | /* Already gone? */ |
383 | if (atomic_read(&dentry->d_count) == 0) | 431 | if (atomic_read(&active->d_count) == 0) |
384 | goto next; | 432 | goto next; |
385 | 433 | ||
386 | qstr = &dentry->d_name; | 434 | qstr = &active->d_name; |
387 | 435 | ||
388 | if (dentry->d_name.hash != hash) | 436 | if (active->d_name.hash != hash) |
389 | goto next; | 437 | goto next; |
390 | if (dentry->d_parent != parent) | 438 | if (active->d_parent != parent) |
391 | goto next; | 439 | goto next; |
392 | 440 | ||
393 | if (qstr->len != len) | 441 | if (qstr->len != len) |
@@ -395,15 +443,15 @@ static struct dentry *autofs4_lookup_active(struct autofs_sb_info *sbi, struct d | |||
395 | if (memcmp(qstr->name, str, len)) | 443 | if (memcmp(qstr->name, str, len)) |
396 | goto next; | 444 | goto next; |
397 | 445 | ||
398 | if (d_unhashed(dentry)) { | 446 | if (d_unhashed(active)) { |
399 | dget(dentry); | 447 | dget(active); |
400 | spin_unlock(&dentry->d_lock); | 448 | spin_unlock(&active->d_lock); |
401 | spin_unlock(&sbi->lookup_lock); | 449 | spin_unlock(&sbi->lookup_lock); |
402 | spin_unlock(&dcache_lock); | 450 | spin_unlock(&dcache_lock); |
403 | return dentry; | 451 | return active; |
404 | } | 452 | } |
405 | next: | 453 | next: |
406 | spin_unlock(&dentry->d_lock); | 454 | spin_unlock(&active->d_lock); |
407 | } | 455 | } |
408 | spin_unlock(&sbi->lookup_lock); | 456 | spin_unlock(&sbi->lookup_lock); |
409 | spin_unlock(&dcache_lock); | 457 | spin_unlock(&dcache_lock); |
@@ -411,8 +459,11 @@ next: | |||
411 | return NULL; | 459 | return NULL; |
412 | } | 460 | } |
413 | 461 | ||
414 | static struct dentry *autofs4_lookup_expiring(struct autofs_sb_info *sbi, struct dentry *parent, struct qstr *name) | 462 | static struct dentry *autofs4_lookup_expiring(struct dentry *dentry) |
415 | { | 463 | { |
464 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | ||
465 | struct dentry *parent = dentry->d_parent; | ||
466 | struct qstr *name = &dentry->d_name; | ||
416 | unsigned int len = name->len; | 467 | unsigned int len = name->len; |
417 | unsigned int hash = name->hash; | 468 | unsigned int hash = name->hash; |
418 | const unsigned char *str = name->name; | 469 | const unsigned char *str = name->name; |
@@ -423,23 +474,23 @@ static struct dentry *autofs4_lookup_expiring(struct autofs_sb_info *sbi, struct | |||
423 | head = &sbi->expiring_list; | 474 | head = &sbi->expiring_list; |
424 | list_for_each(p, head) { | 475 | list_for_each(p, head) { |
425 | struct autofs_info *ino; | 476 | struct autofs_info *ino; |
426 | struct dentry *dentry; | 477 | struct dentry *expiring; |
427 | struct qstr *qstr; | 478 | struct qstr *qstr; |
428 | 479 | ||
429 | ino = list_entry(p, struct autofs_info, expiring); | 480 | ino = list_entry(p, struct autofs_info, expiring); |
430 | dentry = ino->dentry; | 481 | expiring = ino->dentry; |
431 | 482 | ||
432 | spin_lock(&dentry->d_lock); | 483 | spin_lock(&expiring->d_lock); |
433 | 484 | ||
434 | /* Bad luck, we've already been dentry_iput */ | 485 | /* Bad luck, we've already been dentry_iput */ |
435 | if (!dentry->d_inode) | 486 | if (!expiring->d_inode) |
436 | goto next; | 487 | goto next; |
437 | 488 | ||
438 | qstr = &dentry->d_name; | 489 | qstr = &expiring->d_name; |
439 | 490 | ||
440 | if (dentry->d_name.hash != hash) | 491 | if (expiring->d_name.hash != hash) |
441 | goto next; | 492 | goto next; |
442 | if (dentry->d_parent != parent) | 493 | if (expiring->d_parent != parent) |
443 | goto next; | 494 | goto next; |
444 | 495 | ||
445 | if (qstr->len != len) | 496 | if (qstr->len != len) |
@@ -447,15 +498,15 @@ static struct dentry *autofs4_lookup_expiring(struct autofs_sb_info *sbi, struct | |||
447 | if (memcmp(qstr->name, str, len)) | 498 | if (memcmp(qstr->name, str, len)) |
448 | goto next; | 499 | goto next; |
449 | 500 | ||
450 | if (d_unhashed(dentry)) { | 501 | if (d_unhashed(expiring)) { |
451 | dget(dentry); | 502 | dget(expiring); |
452 | spin_unlock(&dentry->d_lock); | 503 | spin_unlock(&expiring->d_lock); |
453 | spin_unlock(&sbi->lookup_lock); | 504 | spin_unlock(&sbi->lookup_lock); |
454 | spin_unlock(&dcache_lock); | 505 | spin_unlock(&dcache_lock); |
455 | return dentry; | 506 | return expiring; |
456 | } | 507 | } |
457 | next: | 508 | next: |
458 | spin_unlock(&dentry->d_lock); | 509 | spin_unlock(&expiring->d_lock); |
459 | } | 510 | } |
460 | spin_unlock(&sbi->lookup_lock); | 511 | spin_unlock(&sbi->lookup_lock); |
461 | spin_unlock(&dcache_lock); | 512 | spin_unlock(&dcache_lock); |
@@ -468,7 +519,7 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
468 | { | 519 | { |
469 | struct autofs_sb_info *sbi; | 520 | struct autofs_sb_info *sbi; |
470 | struct autofs_info *ino; | 521 | struct autofs_info *ino; |
471 | struct dentry *expiring, *unhashed; | 522 | struct dentry *expiring, *active; |
472 | int oz_mode; | 523 | int oz_mode; |
473 | 524 | ||
474 | DPRINTK("name = %.*s", | 525 | DPRINTK("name = %.*s", |
@@ -484,10 +535,11 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
484 | DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d", | 535 | DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d", |
485 | current->pid, task_pgrp_nr(current), sbi->catatonic, oz_mode); | 536 | current->pid, task_pgrp_nr(current), sbi->catatonic, oz_mode); |
486 | 537 | ||
487 | unhashed = autofs4_lookup_active(sbi, dentry->d_parent, &dentry->d_name); | 538 | active = autofs4_lookup_active(dentry); |
488 | if (unhashed) | 539 | if (active) { |
489 | dentry = unhashed; | 540 | dentry = active; |
490 | else { | 541 | ino = autofs4_dentry_ino(dentry); |
542 | } else { | ||
491 | /* | 543 | /* |
492 | * Mark the dentry incomplete but don't hash it. We do this | 544 | * Mark the dentry incomplete but don't hash it. We do this |
493 | * to serialize our inode creation operations (symlink and | 545 | * to serialize our inode creation operations (symlink and |
@@ -513,36 +565,28 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
513 | dentry->d_fsdata = ino; | 565 | dentry->d_fsdata = ino; |
514 | ino->dentry = dentry; | 566 | ino->dentry = dentry; |
515 | 567 | ||
516 | spin_lock(&sbi->lookup_lock); | 568 | autofs4_add_active(dentry); |
517 | list_add(&ino->active, &sbi->active_list); | ||
518 | spin_unlock(&sbi->lookup_lock); | ||
519 | 569 | ||
520 | d_instantiate(dentry, NULL); | 570 | d_instantiate(dentry, NULL); |
521 | } | 571 | } |
522 | 572 | ||
523 | if (!oz_mode) { | 573 | if (!oz_mode) { |
524 | mutex_unlock(&dir->i_mutex); | 574 | mutex_unlock(&dir->i_mutex); |
525 | expiring = autofs4_lookup_expiring(sbi, | 575 | expiring = autofs4_lookup_expiring(dentry); |
526 | dentry->d_parent, | ||
527 | &dentry->d_name); | ||
528 | if (expiring) { | 576 | if (expiring) { |
529 | /* | 577 | /* |
530 | * If we are racing with expire the request might not | 578 | * If we are racing with expire the request might not |
531 | * be quite complete but the directory has been removed | 579 | * be quite complete but the directory has been removed |
532 | * so it must have been successful, so just wait for it. | 580 | * so it must have been successful, so just wait for it. |
533 | */ | 581 | */ |
534 | ino = autofs4_dentry_ino(expiring); | ||
535 | autofs4_expire_wait(expiring); | 582 | autofs4_expire_wait(expiring); |
536 | spin_lock(&sbi->lookup_lock); | 583 | autofs4_del_expiring(expiring); |
537 | if (!list_empty(&ino->expiring)) | ||
538 | list_del_init(&ino->expiring); | ||
539 | spin_unlock(&sbi->lookup_lock); | ||
540 | dput(expiring); | 584 | dput(expiring); |
541 | } | 585 | } |
542 | 586 | ||
543 | spin_lock(&dentry->d_lock); | 587 | spin_lock(&sbi->fs_lock); |
544 | dentry->d_flags |= DCACHE_AUTOFS_PENDING; | 588 | ino->flags |= AUTOFS_INF_PENDING; |
545 | spin_unlock(&dentry->d_lock); | 589 | spin_unlock(&sbi->fs_lock); |
546 | if (dentry->d_op && dentry->d_op->d_revalidate) | 590 | if (dentry->d_op && dentry->d_op->d_revalidate) |
547 | (dentry->d_op->d_revalidate)(dentry, nd); | 591 | (dentry->d_op->d_revalidate)(dentry, nd); |
548 | mutex_lock(&dir->i_mutex); | 592 | mutex_lock(&dir->i_mutex); |
@@ -552,22 +596,22 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
552 | * If we are still pending, check if we had to handle | 596 | * If we are still pending, check if we had to handle |
553 | * a signal. If so we can force a restart.. | 597 | * a signal. If so we can force a restart.. |
554 | */ | 598 | */ |
555 | if (dentry->d_flags & DCACHE_AUTOFS_PENDING) { | 599 | if (ino->flags & AUTOFS_INF_PENDING) { |
556 | /* See if we were interrupted */ | 600 | /* See if we were interrupted */ |
557 | if (signal_pending(current)) { | 601 | if (signal_pending(current)) { |
558 | sigset_t *sigset = ¤t->pending.signal; | 602 | sigset_t *sigset = ¤t->pending.signal; |
559 | if (sigismember (sigset, SIGKILL) || | 603 | if (sigismember (sigset, SIGKILL) || |
560 | sigismember (sigset, SIGQUIT) || | 604 | sigismember (sigset, SIGQUIT) || |
561 | sigismember (sigset, SIGINT)) { | 605 | sigismember (sigset, SIGINT)) { |
562 | if (unhashed) | 606 | if (active) |
563 | dput(unhashed); | 607 | dput(active); |
564 | return ERR_PTR(-ERESTARTNOINTR); | 608 | return ERR_PTR(-ERESTARTNOINTR); |
565 | } | 609 | } |
566 | } | 610 | } |
567 | if (!oz_mode) { | 611 | if (!oz_mode) { |
568 | spin_lock(&dentry->d_lock); | 612 | spin_lock(&sbi->fs_lock); |
569 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; | 613 | ino->flags &= ~AUTOFS_INF_PENDING; |
570 | spin_unlock(&dentry->d_lock); | 614 | spin_unlock(&sbi->fs_lock); |
571 | } | 615 | } |
572 | } | 616 | } |
573 | 617 | ||
@@ -592,14 +636,14 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
592 | else | 636 | else |
593 | dentry = ERR_PTR(-ENOENT); | 637 | dentry = ERR_PTR(-ENOENT); |
594 | 638 | ||
595 | if (unhashed) | 639 | if (active) |
596 | dput(unhashed); | 640 | dput(active); |
597 | 641 | ||
598 | return dentry; | 642 | return dentry; |
599 | } | 643 | } |
600 | 644 | ||
601 | if (unhashed) | 645 | if (active) |
602 | return unhashed; | 646 | return active; |
603 | 647 | ||
604 | return NULL; | 648 | return NULL; |
605 | } | 649 | } |
@@ -624,10 +668,7 @@ static int autofs4_dir_symlink(struct inode *dir, | |||
624 | if (!ino) | 668 | if (!ino) |
625 | return -ENOMEM; | 669 | return -ENOMEM; |
626 | 670 | ||
627 | spin_lock(&sbi->lookup_lock); | 671 | autofs4_del_active(dentry); |
628 | if (!list_empty(&ino->active)) | ||
629 | list_del_init(&ino->active); | ||
630 | spin_unlock(&sbi->lookup_lock); | ||
631 | 672 | ||
632 | ino->size = strlen(symname); | 673 | ino->size = strlen(symname); |
633 | cp = kmalloc(ino->size + 1, GFP_KERNEL); | 674 | cp = kmalloc(ino->size + 1, GFP_KERNEL); |
@@ -705,10 +746,7 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry) | |||
705 | dir->i_mtime = CURRENT_TIME; | 746 | dir->i_mtime = CURRENT_TIME; |
706 | 747 | ||
707 | spin_lock(&dcache_lock); | 748 | spin_lock(&dcache_lock); |
708 | spin_lock(&sbi->lookup_lock); | 749 | autofs4_add_expiring(dentry); |
709 | if (list_empty(&ino->expiring)) | ||
710 | list_add(&ino->expiring, &sbi->expiring_list); | ||
711 | spin_unlock(&sbi->lookup_lock); | ||
712 | spin_lock(&dentry->d_lock); | 750 | spin_lock(&dentry->d_lock); |
713 | __d_drop(dentry); | 751 | __d_drop(dentry); |
714 | spin_unlock(&dentry->d_lock); | 752 | spin_unlock(&dentry->d_lock); |
@@ -734,10 +772,7 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry) | |||
734 | spin_unlock(&dcache_lock); | 772 | spin_unlock(&dcache_lock); |
735 | return -ENOTEMPTY; | 773 | return -ENOTEMPTY; |
736 | } | 774 | } |
737 | spin_lock(&sbi->lookup_lock); | 775 | autofs4_add_expiring(dentry); |
738 | if (list_empty(&ino->expiring)) | ||
739 | list_add(&ino->expiring, &sbi->expiring_list); | ||
740 | spin_unlock(&sbi->lookup_lock); | ||
741 | spin_lock(&dentry->d_lock); | 776 | spin_lock(&dentry->d_lock); |
742 | __d_drop(dentry); | 777 | __d_drop(dentry); |
743 | spin_unlock(&dentry->d_lock); | 778 | spin_unlock(&dentry->d_lock); |
@@ -775,10 +810,7 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
775 | if (!ino) | 810 | if (!ino) |
776 | return -ENOMEM; | 811 | return -ENOMEM; |
777 | 812 | ||
778 | spin_lock(&sbi->lookup_lock); | 813 | autofs4_del_active(dentry); |
779 | if (!list_empty(&ino->active)) | ||
780 | list_del_init(&ino->active); | ||
781 | spin_unlock(&sbi->lookup_lock); | ||
782 | 814 | ||
783 | inode = autofs4_get_inode(dir->i_sb, ino); | 815 | inode = autofs4_get_inode(dir->i_sb, ino); |
784 | if (!inode) { | 816 | if (!inode) { |