diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-07-26 11:48:49 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-07-26 11:48:49 -0400 |
commit | c3cc99ff5d24e2eeaf7ec2032e720681916990e3 (patch) | |
tree | c3e74171bbbd2adde9d60b9db1c440415c8d2831 /fs/autofs4 | |
parent | 38ffbe66d59051fd9cfcfc8545f164700e2fa3bc (diff) | |
parent | 024e8ac04453b3525448c31ef39848cf675ba6db (diff) |
Merge branch 'linus' into x86/xen
Diffstat (limited to 'fs/autofs4')
-rw-r--r-- | fs/autofs4/autofs_i.h | 28 | ||||
-rw-r--r-- | fs/autofs4/expire.c | 91 | ||||
-rw-r--r-- | fs/autofs4/inode.c | 33 | ||||
-rw-r--r-- | fs/autofs4/root.c | 589 | ||||
-rw-r--r-- | fs/autofs4/waitq.c | 267 |
5 files changed, 520 insertions, 488 deletions
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index c3d352d7fa93..69a2f5c92319 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h | |||
@@ -52,7 +52,10 @@ struct autofs_info { | |||
52 | 52 | ||
53 | int flags; | 53 | int flags; |
54 | 54 | ||
55 | struct list_head rehash; | 55 | struct completion expire_complete; |
56 | |||
57 | struct list_head active; | ||
58 | struct list_head expiring; | ||
56 | 59 | ||
57 | struct autofs_sb_info *sbi; | 60 | struct autofs_sb_info *sbi; |
58 | unsigned long last_used; | 61 | unsigned long last_used; |
@@ -68,15 +71,14 @@ struct autofs_info { | |||
68 | }; | 71 | }; |
69 | 72 | ||
70 | #define AUTOFS_INF_EXPIRING (1<<0) /* dentry is in the process of expiring */ | 73 | #define AUTOFS_INF_EXPIRING (1<<0) /* dentry is in the process of expiring */ |
74 | #define AUTOFS_INF_MOUNTPOINT (1<<1) /* mountpoint status for direct expire */ | ||
71 | 75 | ||
72 | struct autofs_wait_queue { | 76 | struct autofs_wait_queue { |
73 | wait_queue_head_t queue; | 77 | wait_queue_head_t queue; |
74 | struct autofs_wait_queue *next; | 78 | struct autofs_wait_queue *next; |
75 | autofs_wqt_t wait_queue_token; | 79 | autofs_wqt_t wait_queue_token; |
76 | /* We use the following to see what we are waiting for */ | 80 | /* We use the following to see what we are waiting for */ |
77 | unsigned int hash; | 81 | struct qstr name; |
78 | unsigned int len; | ||
79 | char *name; | ||
80 | u32 dev; | 82 | u32 dev; |
81 | u64 ino; | 83 | u64 ino; |
82 | uid_t uid; | 84 | uid_t uid; |
@@ -85,7 +87,7 @@ struct autofs_wait_queue { | |||
85 | pid_t tgid; | 87 | pid_t tgid; |
86 | /* This is for status reporting upon return */ | 88 | /* This is for status reporting upon return */ |
87 | int status; | 89 | int status; |
88 | atomic_t wait_ctr; | 90 | unsigned int wait_ctr; |
89 | }; | 91 | }; |
90 | 92 | ||
91 | #define AUTOFS_SBI_MAGIC 0x6d4a556d | 93 | #define AUTOFS_SBI_MAGIC 0x6d4a556d |
@@ -112,8 +114,9 @@ struct autofs_sb_info { | |||
112 | struct mutex wq_mutex; | 114 | struct mutex wq_mutex; |
113 | spinlock_t fs_lock; | 115 | spinlock_t fs_lock; |
114 | struct autofs_wait_queue *queues; /* Wait queue pointer */ | 116 | struct autofs_wait_queue *queues; /* Wait queue pointer */ |
115 | spinlock_t rehash_lock; | 117 | spinlock_t lookup_lock; |
116 | struct list_head rehash_list; | 118 | struct list_head active_list; |
119 | struct list_head expiring_list; | ||
117 | }; | 120 | }; |
118 | 121 | ||
119 | static inline struct autofs_sb_info *autofs4_sbi(struct super_block *sb) | 122 | static inline struct autofs_sb_info *autofs4_sbi(struct super_block *sb) |
@@ -138,18 +141,14 @@ static inline int autofs4_oz_mode(struct autofs_sb_info *sbi) { | |||
138 | static inline int autofs4_ispending(struct dentry *dentry) | 141 | static inline int autofs4_ispending(struct dentry *dentry) |
139 | { | 142 | { |
140 | struct autofs_info *inf = autofs4_dentry_ino(dentry); | 143 | struct autofs_info *inf = autofs4_dentry_ino(dentry); |
141 | int pending = 0; | ||
142 | 144 | ||
143 | if (dentry->d_flags & DCACHE_AUTOFS_PENDING) | 145 | if (dentry->d_flags & DCACHE_AUTOFS_PENDING) |
144 | return 1; | 146 | return 1; |
145 | 147 | ||
146 | if (inf) { | 148 | if (inf->flags & AUTOFS_INF_EXPIRING) |
147 | spin_lock(&inf->sbi->fs_lock); | 149 | return 1; |
148 | pending = inf->flags & AUTOFS_INF_EXPIRING; | ||
149 | spin_unlock(&inf->sbi->fs_lock); | ||
150 | } | ||
151 | 150 | ||
152 | return pending; | 151 | return 0; |
153 | } | 152 | } |
154 | 153 | ||
155 | static inline void autofs4_copy_atime(struct file *src, struct file *dst) | 154 | static inline void autofs4_copy_atime(struct file *src, struct file *dst) |
@@ -164,6 +163,7 @@ void autofs4_free_ino(struct autofs_info *); | |||
164 | 163 | ||
165 | /* Expiration */ | 164 | /* Expiration */ |
166 | int is_autofs4_dentry(struct dentry *); | 165 | int is_autofs4_dentry(struct dentry *); |
166 | int autofs4_expire_wait(struct dentry *dentry); | ||
167 | int autofs4_expire_run(struct super_block *, struct vfsmount *, | 167 | int autofs4_expire_run(struct super_block *, struct vfsmount *, |
168 | struct autofs_sb_info *, | 168 | struct autofs_sb_info *, |
169 | struct autofs_packet_expire __user *); | 169 | struct autofs_packet_expire __user *); |
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index 894fee54d4d8..cdabb796ff01 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c | |||
@@ -259,13 +259,15 @@ static struct dentry *autofs4_expire_direct(struct super_block *sb, | |||
259 | now = jiffies; | 259 | now = jiffies; |
260 | timeout = sbi->exp_timeout; | 260 | timeout = sbi->exp_timeout; |
261 | 261 | ||
262 | /* Lock the tree as we must expire as a whole */ | ||
263 | spin_lock(&sbi->fs_lock); | 262 | spin_lock(&sbi->fs_lock); |
264 | if (!autofs4_direct_busy(mnt, root, timeout, do_now)) { | 263 | if (!autofs4_direct_busy(mnt, root, timeout, do_now)) { |
265 | struct autofs_info *ino = autofs4_dentry_ino(root); | 264 | struct autofs_info *ino = autofs4_dentry_ino(root); |
266 | 265 | if (d_mountpoint(root)) { | |
267 | /* Set this flag early to catch sys_chdir and the like */ | 266 | ino->flags |= AUTOFS_INF_MOUNTPOINT; |
267 | root->d_mounted--; | ||
268 | } | ||
268 | ino->flags |= AUTOFS_INF_EXPIRING; | 269 | ino->flags |= AUTOFS_INF_EXPIRING; |
270 | init_completion(&ino->expire_complete); | ||
269 | spin_unlock(&sbi->fs_lock); | 271 | spin_unlock(&sbi->fs_lock); |
270 | return root; | 272 | return root; |
271 | } | 273 | } |
@@ -292,6 +294,8 @@ static struct dentry *autofs4_expire_indirect(struct super_block *sb, | |||
292 | struct list_head *next; | 294 | struct list_head *next; |
293 | int do_now = how & AUTOFS_EXP_IMMEDIATE; | 295 | int do_now = how & AUTOFS_EXP_IMMEDIATE; |
294 | int exp_leaves = how & AUTOFS_EXP_LEAVES; | 296 | int exp_leaves = how & AUTOFS_EXP_LEAVES; |
297 | struct autofs_info *ino; | ||
298 | unsigned int ino_count; | ||
295 | 299 | ||
296 | if (!root) | 300 | if (!root) |
297 | return NULL; | 301 | return NULL; |
@@ -316,6 +320,9 @@ static struct dentry *autofs4_expire_indirect(struct super_block *sb, | |||
316 | dentry = dget(dentry); | 320 | dentry = dget(dentry); |
317 | spin_unlock(&dcache_lock); | 321 | spin_unlock(&dcache_lock); |
318 | 322 | ||
323 | spin_lock(&sbi->fs_lock); | ||
324 | ino = autofs4_dentry_ino(dentry); | ||
325 | |||
319 | /* | 326 | /* |
320 | * Case 1: (i) indirect mount or top level pseudo direct mount | 327 | * Case 1: (i) indirect mount or top level pseudo direct mount |
321 | * (autofs-4.1). | 328 | * (autofs-4.1). |
@@ -326,6 +333,11 @@ static struct dentry *autofs4_expire_indirect(struct super_block *sb, | |||
326 | DPRINTK("checking mountpoint %p %.*s", | 333 | DPRINTK("checking mountpoint %p %.*s", |
327 | dentry, (int)dentry->d_name.len, dentry->d_name.name); | 334 | dentry, (int)dentry->d_name.len, dentry->d_name.name); |
328 | 335 | ||
336 | /* Path walk currently on this dentry? */ | ||
337 | ino_count = atomic_read(&ino->count) + 2; | ||
338 | if (atomic_read(&dentry->d_count) > ino_count) | ||
339 | goto next; | ||
340 | |||
329 | /* Can we umount this guy */ | 341 | /* Can we umount this guy */ |
330 | if (autofs4_mount_busy(mnt, dentry)) | 342 | if (autofs4_mount_busy(mnt, dentry)) |
331 | goto next; | 343 | goto next; |
@@ -343,23 +355,25 @@ static struct dentry *autofs4_expire_indirect(struct super_block *sb, | |||
343 | 355 | ||
344 | /* Case 2: tree mount, expire iff entire tree is not busy */ | 356 | /* Case 2: tree mount, expire iff entire tree is not busy */ |
345 | if (!exp_leaves) { | 357 | if (!exp_leaves) { |
346 | /* Lock the tree as we must expire as a whole */ | 358 | /* Path walk currently on this dentry? */ |
347 | spin_lock(&sbi->fs_lock); | 359 | ino_count = atomic_read(&ino->count) + 1; |
348 | if (!autofs4_tree_busy(mnt, dentry, timeout, do_now)) { | 360 | if (atomic_read(&dentry->d_count) > ino_count) |
349 | struct autofs_info *inf = autofs4_dentry_ino(dentry); | 361 | goto next; |
350 | 362 | ||
351 | /* Set this flag early to catch sys_chdir and the like */ | 363 | if (!autofs4_tree_busy(mnt, dentry, timeout, do_now)) { |
352 | inf->flags |= AUTOFS_INF_EXPIRING; | ||
353 | spin_unlock(&sbi->fs_lock); | ||
354 | expired = dentry; | 364 | expired = dentry; |
355 | goto found; | 365 | goto found; |
356 | } | 366 | } |
357 | spin_unlock(&sbi->fs_lock); | ||
358 | /* | 367 | /* |
359 | * Case 3: pseudo direct mount, expire individual leaves | 368 | * Case 3: pseudo direct mount, expire individual leaves |
360 | * (autofs-4.1). | 369 | * (autofs-4.1). |
361 | */ | 370 | */ |
362 | } else { | 371 | } else { |
372 | /* Path walk currently on this dentry? */ | ||
373 | ino_count = atomic_read(&ino->count) + 1; | ||
374 | if (atomic_read(&dentry->d_count) > ino_count) | ||
375 | goto next; | ||
376 | |||
363 | expired = autofs4_check_leaves(mnt, dentry, timeout, do_now); | 377 | expired = autofs4_check_leaves(mnt, dentry, timeout, do_now); |
364 | if (expired) { | 378 | if (expired) { |
365 | dput(dentry); | 379 | dput(dentry); |
@@ -367,6 +381,7 @@ static struct dentry *autofs4_expire_indirect(struct super_block *sb, | |||
367 | } | 381 | } |
368 | } | 382 | } |
369 | next: | 383 | next: |
384 | spin_unlock(&sbi->fs_lock); | ||
370 | dput(dentry); | 385 | dput(dentry); |
371 | spin_lock(&dcache_lock); | 386 | spin_lock(&dcache_lock); |
372 | next = next->next; | 387 | next = next->next; |
@@ -377,12 +392,45 @@ next: | |||
377 | found: | 392 | found: |
378 | DPRINTK("returning %p %.*s", | 393 | DPRINTK("returning %p %.*s", |
379 | expired, (int)expired->d_name.len, expired->d_name.name); | 394 | expired, (int)expired->d_name.len, expired->d_name.name); |
395 | ino = autofs4_dentry_ino(expired); | ||
396 | ino->flags |= AUTOFS_INF_EXPIRING; | ||
397 | init_completion(&ino->expire_complete); | ||
398 | spin_unlock(&sbi->fs_lock); | ||
380 | spin_lock(&dcache_lock); | 399 | spin_lock(&dcache_lock); |
381 | list_move(&expired->d_parent->d_subdirs, &expired->d_u.d_child); | 400 | list_move(&expired->d_parent->d_subdirs, &expired->d_u.d_child); |
382 | spin_unlock(&dcache_lock); | 401 | spin_unlock(&dcache_lock); |
383 | return expired; | 402 | return expired; |
384 | } | 403 | } |
385 | 404 | ||
405 | int autofs4_expire_wait(struct dentry *dentry) | ||
406 | { | ||
407 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | ||
408 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | ||
409 | int status; | ||
410 | |||
411 | /* Block on any pending expire */ | ||
412 | spin_lock(&sbi->fs_lock); | ||
413 | if (ino->flags & AUTOFS_INF_EXPIRING) { | ||
414 | spin_unlock(&sbi->fs_lock); | ||
415 | |||
416 | DPRINTK("waiting for expire %p name=%.*s", | ||
417 | dentry, dentry->d_name.len, dentry->d_name.name); | ||
418 | |||
419 | status = autofs4_wait(sbi, dentry, NFY_NONE); | ||
420 | wait_for_completion(&ino->expire_complete); | ||
421 | |||
422 | DPRINTK("expire done status=%d", status); | ||
423 | |||
424 | if (d_unhashed(dentry)) | ||
425 | return -EAGAIN; | ||
426 | |||
427 | return status; | ||
428 | } | ||
429 | spin_unlock(&sbi->fs_lock); | ||
430 | |||
431 | return 0; | ||
432 | } | ||
433 | |||
386 | /* Perform an expiry operation */ | 434 | /* Perform an expiry operation */ |
387 | int autofs4_expire_run(struct super_block *sb, | 435 | int autofs4_expire_run(struct super_block *sb, |
388 | struct vfsmount *mnt, | 436 | struct vfsmount *mnt, |
@@ -390,7 +438,9 @@ int autofs4_expire_run(struct super_block *sb, | |||
390 | struct autofs_packet_expire __user *pkt_p) | 438 | struct autofs_packet_expire __user *pkt_p) |
391 | { | 439 | { |
392 | struct autofs_packet_expire pkt; | 440 | struct autofs_packet_expire pkt; |
441 | struct autofs_info *ino; | ||
393 | struct dentry *dentry; | 442 | struct dentry *dentry; |
443 | int ret = 0; | ||
394 | 444 | ||
395 | memset(&pkt,0,sizeof pkt); | 445 | memset(&pkt,0,sizeof pkt); |
396 | 446 | ||
@@ -406,9 +456,15 @@ int autofs4_expire_run(struct super_block *sb, | |||
406 | dput(dentry); | 456 | dput(dentry); |
407 | 457 | ||
408 | if ( copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)) ) | 458 | if ( copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)) ) |
409 | return -EFAULT; | 459 | ret = -EFAULT; |
410 | 460 | ||
411 | return 0; | 461 | spin_lock(&sbi->fs_lock); |
462 | ino = autofs4_dentry_ino(dentry); | ||
463 | ino->flags &= ~AUTOFS_INF_EXPIRING; | ||
464 | complete_all(&ino->expire_complete); | ||
465 | spin_unlock(&sbi->fs_lock); | ||
466 | |||
467 | return ret; | ||
412 | } | 468 | } |
413 | 469 | ||
414 | /* Call repeatedly until it returns -EAGAIN, meaning there's nothing | 470 | /* Call repeatedly until it returns -EAGAIN, meaning there's nothing |
@@ -433,9 +489,16 @@ int autofs4_expire_multi(struct super_block *sb, struct vfsmount *mnt, | |||
433 | 489 | ||
434 | /* This is synchronous because it makes the daemon a | 490 | /* This is synchronous because it makes the daemon a |
435 | little easier */ | 491 | little easier */ |
436 | ino->flags |= AUTOFS_INF_EXPIRING; | ||
437 | ret = autofs4_wait(sbi, dentry, NFY_EXPIRE); | 492 | ret = autofs4_wait(sbi, dentry, NFY_EXPIRE); |
493 | |||
494 | spin_lock(&sbi->fs_lock); | ||
495 | if (ino->flags & AUTOFS_INF_MOUNTPOINT) { | ||
496 | sb->s_root->d_mounted++; | ||
497 | ino->flags &= ~AUTOFS_INF_MOUNTPOINT; | ||
498 | } | ||
438 | ino->flags &= ~AUTOFS_INF_EXPIRING; | 499 | ino->flags &= ~AUTOFS_INF_EXPIRING; |
500 | complete_all(&ino->expire_complete); | ||
501 | spin_unlock(&sbi->fs_lock); | ||
439 | dput(dentry); | 502 | dput(dentry); |
440 | } | 503 | } |
441 | 504 | ||
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index 2fdcf5e1d236..7bb3e5ba0537 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c | |||
@@ -24,8 +24,10 @@ | |||
24 | 24 | ||
25 | static void ino_lnkfree(struct autofs_info *ino) | 25 | static void ino_lnkfree(struct autofs_info *ino) |
26 | { | 26 | { |
27 | kfree(ino->u.symlink); | 27 | if (ino->u.symlink) { |
28 | ino->u.symlink = NULL; | 28 | kfree(ino->u.symlink); |
29 | ino->u.symlink = NULL; | ||
30 | } | ||
29 | } | 31 | } |
30 | 32 | ||
31 | struct autofs_info *autofs4_init_ino(struct autofs_info *ino, | 33 | struct autofs_info *autofs4_init_ino(struct autofs_info *ino, |
@@ -41,16 +43,18 @@ struct autofs_info *autofs4_init_ino(struct autofs_info *ino, | |||
41 | if (ino == NULL) | 43 | if (ino == NULL) |
42 | return NULL; | 44 | return NULL; |
43 | 45 | ||
44 | ino->flags = 0; | 46 | if (!reinit) { |
45 | ino->mode = mode; | 47 | ino->flags = 0; |
46 | ino->inode = NULL; | 48 | ino->inode = NULL; |
47 | ino->dentry = NULL; | 49 | ino->dentry = NULL; |
48 | ino->size = 0; | 50 | ino->size = 0; |
49 | 51 | INIT_LIST_HEAD(&ino->active); | |
50 | INIT_LIST_HEAD(&ino->rehash); | 52 | INIT_LIST_HEAD(&ino->expiring); |
53 | atomic_set(&ino->count, 0); | ||
54 | } | ||
51 | 55 | ||
56 | ino->mode = mode; | ||
52 | ino->last_used = jiffies; | 57 | ino->last_used = jiffies; |
53 | atomic_set(&ino->count, 0); | ||
54 | 58 | ||
55 | ino->sbi = sbi; | 59 | ino->sbi = sbi; |
56 | 60 | ||
@@ -159,8 +163,8 @@ void autofs4_kill_sb(struct super_block *sb) | |||
159 | if (!sbi) | 163 | if (!sbi) |
160 | goto out_kill_sb; | 164 | goto out_kill_sb; |
161 | 165 | ||
162 | if (!sbi->catatonic) | 166 | /* Free wait queues, close pipe */ |
163 | autofs4_catatonic_mode(sbi); /* Free wait queues, close pipe */ | 167 | autofs4_catatonic_mode(sbi); |
164 | 168 | ||
165 | /* Clean up and release dangling references */ | 169 | /* Clean up and release dangling references */ |
166 | autofs4_force_release(sbi); | 170 | autofs4_force_release(sbi); |
@@ -338,8 +342,9 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) | |||
338 | mutex_init(&sbi->wq_mutex); | 342 | mutex_init(&sbi->wq_mutex); |
339 | spin_lock_init(&sbi->fs_lock); | 343 | spin_lock_init(&sbi->fs_lock); |
340 | sbi->queues = NULL; | 344 | sbi->queues = NULL; |
341 | spin_lock_init(&sbi->rehash_lock); | 345 | spin_lock_init(&sbi->lookup_lock); |
342 | INIT_LIST_HEAD(&sbi->rehash_list); | 346 | INIT_LIST_HEAD(&sbi->active_list); |
347 | INIT_LIST_HEAD(&sbi->expiring_list); | ||
343 | s->s_blocksize = 1024; | 348 | s->s_blocksize = 1024; |
344 | s->s_blocksize_bits = 10; | 349 | s->s_blocksize_bits = 10; |
345 | s->s_magic = AUTOFS_SUPER_MAGIC; | 350 | s->s_magic = AUTOFS_SUPER_MAGIC; |
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index edf5b6bddb52..bcfb2dc0a61b 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
@@ -25,25 +25,25 @@ static int autofs4_dir_rmdir(struct inode *,struct dentry *); | |||
25 | static int autofs4_dir_mkdir(struct inode *,struct dentry *,int); | 25 | static int autofs4_dir_mkdir(struct inode *,struct dentry *,int); |
26 | static int autofs4_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long); | 26 | static int autofs4_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long); |
27 | static int autofs4_dir_open(struct inode *inode, struct file *file); | 27 | static int autofs4_dir_open(struct inode *inode, struct file *file); |
28 | static int autofs4_dir_close(struct inode *inode, struct file *file); | ||
29 | static int autofs4_dir_readdir(struct file * filp, void * dirent, filldir_t filldir); | ||
30 | static int autofs4_root_readdir(struct file * filp, void * dirent, filldir_t filldir); | ||
31 | static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *); | 28 | static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *); |
32 | static void *autofs4_follow_link(struct dentry *, struct nameidata *); | 29 | static void *autofs4_follow_link(struct dentry *, struct nameidata *); |
33 | 30 | ||
31 | #define TRIGGER_FLAGS (LOOKUP_CONTINUE | LOOKUP_DIRECTORY) | ||
32 | #define TRIGGER_INTENTS (LOOKUP_OPEN | LOOKUP_CREATE) | ||
33 | |||
34 | const struct file_operations autofs4_root_operations = { | 34 | const struct file_operations autofs4_root_operations = { |
35 | .open = dcache_dir_open, | 35 | .open = dcache_dir_open, |
36 | .release = dcache_dir_close, | 36 | .release = dcache_dir_close, |
37 | .read = generic_read_dir, | 37 | .read = generic_read_dir, |
38 | .readdir = autofs4_root_readdir, | 38 | .readdir = dcache_readdir, |
39 | .ioctl = autofs4_root_ioctl, | 39 | .ioctl = autofs4_root_ioctl, |
40 | }; | 40 | }; |
41 | 41 | ||
42 | const struct file_operations autofs4_dir_operations = { | 42 | const struct file_operations autofs4_dir_operations = { |
43 | .open = autofs4_dir_open, | 43 | .open = autofs4_dir_open, |
44 | .release = autofs4_dir_close, | 44 | .release = dcache_dir_close, |
45 | .read = generic_read_dir, | 45 | .read = generic_read_dir, |
46 | .readdir = autofs4_dir_readdir, | 46 | .readdir = dcache_readdir, |
47 | }; | 47 | }; |
48 | 48 | ||
49 | const struct inode_operations autofs4_indirect_root_inode_operations = { | 49 | const struct inode_operations autofs4_indirect_root_inode_operations = { |
@@ -70,42 +70,10 @@ const struct inode_operations autofs4_dir_inode_operations = { | |||
70 | .rmdir = autofs4_dir_rmdir, | 70 | .rmdir = autofs4_dir_rmdir, |
71 | }; | 71 | }; |
72 | 72 | ||
73 | static int autofs4_root_readdir(struct file *file, void *dirent, | ||
74 | filldir_t filldir) | ||
75 | { | ||
76 | struct autofs_sb_info *sbi = autofs4_sbi(file->f_path.dentry->d_sb); | ||
77 | int oz_mode = autofs4_oz_mode(sbi); | ||
78 | |||
79 | DPRINTK("called, filp->f_pos = %lld", file->f_pos); | ||
80 | |||
81 | /* | ||
82 | * Don't set reghost flag if: | ||
83 | * 1) f_pos is larger than zero -- we've already been here. | ||
84 | * 2) we haven't even enabled reghosting in the 1st place. | ||
85 | * 3) this is the daemon doing a readdir | ||
86 | */ | ||
87 | if (oz_mode && file->f_pos == 0 && sbi->reghost_enabled) | ||
88 | sbi->needs_reghost = 1; | ||
89 | |||
90 | DPRINTK("needs_reghost = %d", sbi->needs_reghost); | ||
91 | |||
92 | return dcache_readdir(file, dirent, filldir); | ||
93 | } | ||
94 | |||
95 | static int autofs4_dir_open(struct inode *inode, struct file *file) | 73 | static int autofs4_dir_open(struct inode *inode, struct file *file) |
96 | { | 74 | { |
97 | struct dentry *dentry = file->f_path.dentry; | 75 | struct dentry *dentry = file->f_path.dentry; |
98 | struct vfsmount *mnt = file->f_path.mnt; | ||
99 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | 76 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); |
100 | struct dentry *cursor; | ||
101 | int status; | ||
102 | |||
103 | status = dcache_dir_open(inode, file); | ||
104 | if (status) | ||
105 | goto out; | ||
106 | |||
107 | cursor = file->private_data; | ||
108 | cursor->d_fsdata = NULL; | ||
109 | 77 | ||
110 | DPRINTK("file=%p dentry=%p %.*s", | 78 | DPRINTK("file=%p dentry=%p %.*s", |
111 | file, dentry, dentry->d_name.len, dentry->d_name.name); | 79 | file, dentry, dentry->d_name.len, dentry->d_name.name); |
@@ -113,159 +81,32 @@ static int autofs4_dir_open(struct inode *inode, struct file *file) | |||
113 | if (autofs4_oz_mode(sbi)) | 81 | if (autofs4_oz_mode(sbi)) |
114 | goto out; | 82 | goto out; |
115 | 83 | ||
116 | if (autofs4_ispending(dentry)) { | 84 | /* |
117 | DPRINTK("dentry busy"); | 85 | * An empty directory in an autofs file system is always a |
118 | dcache_dir_close(inode, file); | 86 | * mount point. The daemon must have failed to mount this |
119 | status = -EBUSY; | 87 | * during lookup so it doesn't exist. This can happen, for |
120 | goto out; | 88 | * example, if user space returns an incorrect status for a |
121 | } | 89 | * mount request. Otherwise we're doing a readdir on the |
122 | 90 | * autofs file system so just let the libfs routines handle | |
123 | status = -ENOENT; | 91 | * it. |
124 | if (!d_mountpoint(dentry) && dentry->d_op && dentry->d_op->d_revalidate) { | 92 | */ |
125 | struct nameidata nd; | 93 | spin_lock(&dcache_lock); |
126 | int empty, ret; | 94 | if (!d_mountpoint(dentry) && __simple_empty(dentry)) { |
127 | |||
128 | /* In case there are stale directory dentrys from a failed mount */ | ||
129 | spin_lock(&dcache_lock); | ||
130 | empty = list_empty(&dentry->d_subdirs); | ||
131 | spin_unlock(&dcache_lock); | 95 | spin_unlock(&dcache_lock); |
132 | 96 | return -ENOENT; | |
133 | if (!empty) | ||
134 | d_invalidate(dentry); | ||
135 | |||
136 | nd.flags = LOOKUP_DIRECTORY; | ||
137 | ret = (dentry->d_op->d_revalidate)(dentry, &nd); | ||
138 | |||
139 | if (ret <= 0) { | ||
140 | if (ret < 0) | ||
141 | status = ret; | ||
142 | dcache_dir_close(inode, file); | ||
143 | goto out; | ||
144 | } | ||
145 | } | 97 | } |
98 | spin_unlock(&dcache_lock); | ||
146 | 99 | ||
147 | if (d_mountpoint(dentry)) { | ||
148 | struct file *fp = NULL; | ||
149 | struct path fp_path = { .dentry = dentry, .mnt = mnt }; | ||
150 | |||
151 | path_get(&fp_path); | ||
152 | |||
153 | if (!autofs4_follow_mount(&fp_path.mnt, &fp_path.dentry)) { | ||
154 | path_put(&fp_path); | ||
155 | dcache_dir_close(inode, file); | ||
156 | goto out; | ||
157 | } | ||
158 | |||
159 | fp = dentry_open(fp_path.dentry, fp_path.mnt, file->f_flags); | ||
160 | status = PTR_ERR(fp); | ||
161 | if (IS_ERR(fp)) { | ||
162 | dcache_dir_close(inode, file); | ||
163 | goto out; | ||
164 | } | ||
165 | cursor->d_fsdata = fp; | ||
166 | } | ||
167 | return 0; | ||
168 | out: | ||
169 | return status; | ||
170 | } | ||
171 | |||
172 | static int autofs4_dir_close(struct inode *inode, struct file *file) | ||
173 | { | ||
174 | struct dentry *dentry = file->f_path.dentry; | ||
175 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | ||
176 | struct dentry *cursor = file->private_data; | ||
177 | int status = 0; | ||
178 | |||
179 | DPRINTK("file=%p dentry=%p %.*s", | ||
180 | file, dentry, dentry->d_name.len, dentry->d_name.name); | ||
181 | |||
182 | if (autofs4_oz_mode(sbi)) | ||
183 | goto out; | ||
184 | |||
185 | if (autofs4_ispending(dentry)) { | ||
186 | DPRINTK("dentry busy"); | ||
187 | status = -EBUSY; | ||
188 | goto out; | ||
189 | } | ||
190 | |||
191 | if (d_mountpoint(dentry)) { | ||
192 | struct file *fp = cursor->d_fsdata; | ||
193 | if (!fp) { | ||
194 | status = -ENOENT; | ||
195 | goto out; | ||
196 | } | ||
197 | filp_close(fp, current->files); | ||
198 | } | ||
199 | out: | ||
200 | dcache_dir_close(inode, file); | ||
201 | return status; | ||
202 | } | ||
203 | |||
204 | static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldir) | ||
205 | { | ||
206 | struct dentry *dentry = file->f_path.dentry; | ||
207 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | ||
208 | struct dentry *cursor = file->private_data; | ||
209 | int status; | ||
210 | |||
211 | DPRINTK("file=%p dentry=%p %.*s", | ||
212 | file, dentry, dentry->d_name.len, dentry->d_name.name); | ||
213 | |||
214 | if (autofs4_oz_mode(sbi)) | ||
215 | goto out; | ||
216 | |||
217 | if (autofs4_ispending(dentry)) { | ||
218 | DPRINTK("dentry busy"); | ||
219 | return -EBUSY; | ||
220 | } | ||
221 | |||
222 | if (d_mountpoint(dentry)) { | ||
223 | struct file *fp = cursor->d_fsdata; | ||
224 | |||
225 | if (!fp) | ||
226 | return -ENOENT; | ||
227 | |||
228 | if (!fp->f_op || !fp->f_op->readdir) | ||
229 | goto out; | ||
230 | |||
231 | status = vfs_readdir(fp, filldir, dirent); | ||
232 | file->f_pos = fp->f_pos; | ||
233 | if (status) | ||
234 | autofs4_copy_atime(file, fp); | ||
235 | return status; | ||
236 | } | ||
237 | out: | 100 | out: |
238 | return dcache_readdir(file, dirent, filldir); | 101 | return dcache_dir_open(inode, file); |
239 | } | 102 | } |
240 | 103 | ||
241 | static int try_to_fill_dentry(struct dentry *dentry, int flags) | 104 | static int try_to_fill_dentry(struct dentry *dentry, int flags) |
242 | { | 105 | { |
243 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | 106 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); |
244 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | 107 | struct autofs_info *ino = autofs4_dentry_ino(dentry); |
245 | struct dentry *new; | ||
246 | int status; | 108 | int status; |
247 | 109 | ||
248 | /* Block on any pending expiry here; invalidate the dentry | ||
249 | when expiration is done to trigger mount request with a new | ||
250 | dentry */ | ||
251 | if (ino && (ino->flags & AUTOFS_INF_EXPIRING)) { | ||
252 | DPRINTK("waiting for expire %p name=%.*s", | ||
253 | dentry, dentry->d_name.len, dentry->d_name.name); | ||
254 | |||
255 | status = autofs4_wait(sbi, dentry, NFY_NONE); | ||
256 | |||
257 | DPRINTK("expire done status=%d", status); | ||
258 | |||
259 | /* | ||
260 | * If the directory still exists the mount request must | ||
261 | * continue otherwise it can't be followed at the right | ||
262 | * time during the walk. | ||
263 | */ | ||
264 | status = d_invalidate(dentry); | ||
265 | if (status != -EBUSY) | ||
266 | return -EAGAIN; | ||
267 | } | ||
268 | |||
269 | DPRINTK("dentry=%p %.*s ino=%p", | 110 | DPRINTK("dentry=%p %.*s ino=%p", |
270 | dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode); | 111 | dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode); |
271 | 112 | ||
@@ -292,7 +133,8 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags) | |||
292 | return status; | 133 | return status; |
293 | } | 134 | } |
294 | /* Trigger mount for path component or follow link */ | 135 | /* Trigger mount for path component or follow link */ |
295 | } else if (flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY) || | 136 | } else if (dentry->d_flags & DCACHE_AUTOFS_PENDING || |
137 | flags & (TRIGGER_FLAGS | TRIGGER_INTENTS) || | ||
296 | current->link_count) { | 138 | current->link_count) { |
297 | DPRINTK("waiting for mount name=%.*s", | 139 | DPRINTK("waiting for mount name=%.*s", |
298 | dentry->d_name.len, dentry->d_name.name); | 140 | dentry->d_name.len, dentry->d_name.name); |
@@ -320,26 +162,6 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags) | |||
320 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; | 162 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; |
321 | spin_unlock(&dentry->d_lock); | 163 | spin_unlock(&dentry->d_lock); |
322 | 164 | ||
323 | /* | ||
324 | * The dentry that is passed in from lookup may not be the one | ||
325 | * we end up using, as mkdir can create a new one. If this | ||
326 | * happens, and another process tries the lookup at the same time, | ||
327 | * it will set the PENDING flag on this new dentry, but add itself | ||
328 | * to our waitq. Then, if after the lookup succeeds, the first | ||
329 | * process that requested the mount performs another lookup of the | ||
330 | * same directory, it will show up as still pending! So, we need | ||
331 | * to redo the lookup here and clear pending on that dentry. | ||
332 | */ | ||
333 | if (d_unhashed(dentry)) { | ||
334 | new = d_lookup(dentry->d_parent, &dentry->d_name); | ||
335 | if (new) { | ||
336 | spin_lock(&new->d_lock); | ||
337 | new->d_flags &= ~DCACHE_AUTOFS_PENDING; | ||
338 | spin_unlock(&new->d_lock); | ||
339 | dput(new); | ||
340 | } | ||
341 | } | ||
342 | |||
343 | return 0; | 165 | return 0; |
344 | } | 166 | } |
345 | 167 | ||
@@ -355,51 +177,63 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
355 | DPRINTK("dentry=%p %.*s oz_mode=%d nd->flags=%d", | 177 | DPRINTK("dentry=%p %.*s oz_mode=%d nd->flags=%d", |
356 | dentry, dentry->d_name.len, dentry->d_name.name, oz_mode, | 178 | dentry, dentry->d_name.len, dentry->d_name.name, oz_mode, |
357 | nd->flags); | 179 | nd->flags); |
358 | 180 | /* | |
359 | /* If it's our master or we shouldn't trigger a mount we're done */ | 181 | * For an expire of a covered direct or offset mount we need |
360 | lookup_type = nd->flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY); | 182 | * to beeak out of follow_down() at the autofs mount trigger |
361 | if (oz_mode || !lookup_type) | 183 | * (d_mounted--), so we can see the expiring flag, and manage |
184 | * the blocking and following here until the expire is completed. | ||
185 | */ | ||
186 | if (oz_mode) { | ||
187 | spin_lock(&sbi->fs_lock); | ||
188 | if (ino->flags & AUTOFS_INF_EXPIRING) { | ||
189 | spin_unlock(&sbi->fs_lock); | ||
190 | /* Follow down to our covering mount. */ | ||
191 | if (!follow_down(&nd->path.mnt, &nd->path.dentry)) | ||
192 | goto done; | ||
193 | goto follow; | ||
194 | } | ||
195 | spin_unlock(&sbi->fs_lock); | ||
362 | goto done; | 196 | goto done; |
197 | } | ||
363 | 198 | ||
364 | /* If an expire request is pending wait for it. */ | 199 | /* If an expire request is pending everyone must wait. */ |
365 | if (ino && (ino->flags & AUTOFS_INF_EXPIRING)) { | 200 | autofs4_expire_wait(dentry); |
366 | DPRINTK("waiting for active request %p name=%.*s", | ||
367 | dentry, dentry->d_name.len, dentry->d_name.name); | ||
368 | |||
369 | status = autofs4_wait(sbi, dentry, NFY_NONE); | ||
370 | 201 | ||
371 | DPRINTK("request done status=%d", status); | 202 | /* We trigger a mount for almost all flags */ |
372 | } | 203 | lookup_type = nd->flags & (TRIGGER_FLAGS | TRIGGER_INTENTS); |
204 | if (!(lookup_type || dentry->d_flags & DCACHE_AUTOFS_PENDING)) | ||
205 | goto follow; | ||
373 | 206 | ||
374 | /* | 207 | /* |
375 | * If the dentry contains directories then it is an | 208 | * If the dentry contains directories then it is an autofs |
376 | * autofs multi-mount with no root mount offset. So | 209 | * multi-mount with no root mount offset. So don't try to |
377 | * don't try to mount it again. | 210 | * mount it again. |
378 | */ | 211 | */ |
379 | spin_lock(&dcache_lock); | 212 | spin_lock(&dcache_lock); |
380 | if (!d_mountpoint(dentry) && __simple_empty(dentry)) { | 213 | if (dentry->d_flags & DCACHE_AUTOFS_PENDING || |
214 | (!d_mountpoint(dentry) && __simple_empty(dentry))) { | ||
381 | spin_unlock(&dcache_lock); | 215 | spin_unlock(&dcache_lock); |
382 | 216 | ||
383 | status = try_to_fill_dentry(dentry, 0); | 217 | status = try_to_fill_dentry(dentry, 0); |
384 | if (status) | 218 | if (status) |
385 | goto out_error; | 219 | goto out_error; |
386 | 220 | ||
387 | /* | 221 | goto follow; |
388 | * The mount succeeded but if there is no root mount | ||
389 | * it must be an autofs multi-mount with no root offset | ||
390 | * so we don't need to follow the mount. | ||
391 | */ | ||
392 | if (d_mountpoint(dentry)) { | ||
393 | if (!autofs4_follow_mount(&nd->path.mnt, | ||
394 | &nd->path.dentry)) { | ||
395 | status = -ENOENT; | ||
396 | goto out_error; | ||
397 | } | ||
398 | } | ||
399 | |||
400 | goto done; | ||
401 | } | 222 | } |
402 | spin_unlock(&dcache_lock); | 223 | spin_unlock(&dcache_lock); |
224 | follow: | ||
225 | /* | ||
226 | * If there is no root mount it must be an autofs | ||
227 | * multi-mount with no root offset so we don't need | ||
228 | * to follow it. | ||
229 | */ | ||
230 | if (d_mountpoint(dentry)) { | ||
231 | if (!autofs4_follow_mount(&nd->path.mnt, | ||
232 | &nd->path.dentry)) { | ||
233 | status = -ENOENT; | ||
234 | goto out_error; | ||
235 | } | ||
236 | } | ||
403 | 237 | ||
404 | done: | 238 | done: |
405 | return NULL; | 239 | return NULL; |
@@ -424,12 +258,23 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
424 | int status = 1; | 258 | int status = 1; |
425 | 259 | ||
426 | /* Pending dentry */ | 260 | /* Pending dentry */ |
261 | spin_lock(&sbi->fs_lock); | ||
427 | if (autofs4_ispending(dentry)) { | 262 | if (autofs4_ispending(dentry)) { |
428 | /* The daemon never causes a mount to trigger */ | 263 | /* The daemon never causes a mount to trigger */ |
264 | spin_unlock(&sbi->fs_lock); | ||
265 | |||
429 | if (oz_mode) | 266 | if (oz_mode) |
430 | return 1; | 267 | return 1; |
431 | 268 | ||
432 | /* | 269 | /* |
270 | * If the directory has gone away due to an expire | ||
271 | * we have been called as ->d_revalidate() and so | ||
272 | * we need to return false and proceed to ->lookup(). | ||
273 | */ | ||
274 | if (autofs4_expire_wait(dentry) == -EAGAIN) | ||
275 | return 0; | ||
276 | |||
277 | /* | ||
433 | * A zero status is success otherwise we have a | 278 | * A zero status is success otherwise we have a |
434 | * negative error code. | 279 | * negative error code. |
435 | */ | 280 | */ |
@@ -437,17 +282,9 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
437 | if (status == 0) | 282 | if (status == 0) |
438 | return 1; | 283 | return 1; |
439 | 284 | ||
440 | /* | ||
441 | * A status of EAGAIN here means that the dentry has gone | ||
442 | * away while waiting for an expire to complete. If we are | ||
443 | * racing with expire lookup will wait for it so this must | ||
444 | * be a revalidate and we need to send it to lookup. | ||
445 | */ | ||
446 | if (status == -EAGAIN) | ||
447 | return 0; | ||
448 | |||
449 | return status; | 285 | return status; |
450 | } | 286 | } |
287 | spin_unlock(&sbi->fs_lock); | ||
451 | 288 | ||
452 | /* Negative dentry.. invalidate if "old" */ | 289 | /* Negative dentry.. invalidate if "old" */ |
453 | if (dentry->d_inode == NULL) | 290 | if (dentry->d_inode == NULL) |
@@ -461,6 +298,7 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
461 | DPRINTK("dentry=%p %.*s, emptydir", | 298 | DPRINTK("dentry=%p %.*s, emptydir", |
462 | dentry, dentry->d_name.len, dentry->d_name.name); | 299 | dentry, dentry->d_name.len, dentry->d_name.name); |
463 | spin_unlock(&dcache_lock); | 300 | spin_unlock(&dcache_lock); |
301 | |||
464 | /* The daemon never causes a mount to trigger */ | 302 | /* The daemon never causes a mount to trigger */ |
465 | if (oz_mode) | 303 | if (oz_mode) |
466 | return 1; | 304 | return 1; |
@@ -493,10 +331,12 @@ void autofs4_dentry_release(struct dentry *de) | |||
493 | struct autofs_sb_info *sbi = autofs4_sbi(de->d_sb); | 331 | struct autofs_sb_info *sbi = autofs4_sbi(de->d_sb); |
494 | 332 | ||
495 | if (sbi) { | 333 | if (sbi) { |
496 | spin_lock(&sbi->rehash_lock); | 334 | spin_lock(&sbi->lookup_lock); |
497 | if (!list_empty(&inf->rehash)) | 335 | if (!list_empty(&inf->active)) |
498 | list_del(&inf->rehash); | 336 | list_del(&inf->active); |
499 | spin_unlock(&sbi->rehash_lock); | 337 | if (!list_empty(&inf->expiring)) |
338 | list_del(&inf->expiring); | ||
339 | spin_unlock(&sbi->lookup_lock); | ||
500 | } | 340 | } |
501 | 341 | ||
502 | inf->dentry = NULL; | 342 | inf->dentry = NULL; |
@@ -518,7 +358,7 @@ static struct dentry_operations autofs4_dentry_operations = { | |||
518 | .d_release = autofs4_dentry_release, | 358 | .d_release = autofs4_dentry_release, |
519 | }; | 359 | }; |
520 | 360 | ||
521 | static struct dentry *autofs4_lookup_unhashed(struct autofs_sb_info *sbi, struct dentry *parent, struct qstr *name) | 361 | static struct dentry *autofs4_lookup_active(struct autofs_sb_info *sbi, struct dentry *parent, struct qstr *name) |
522 | { | 362 | { |
523 | unsigned int len = name->len; | 363 | unsigned int len = name->len; |
524 | unsigned int hash = name->hash; | 364 | unsigned int hash = name->hash; |
@@ -526,14 +366,66 @@ static struct dentry *autofs4_lookup_unhashed(struct autofs_sb_info *sbi, struct | |||
526 | struct list_head *p, *head; | 366 | struct list_head *p, *head; |
527 | 367 | ||
528 | spin_lock(&dcache_lock); | 368 | spin_lock(&dcache_lock); |
529 | spin_lock(&sbi->rehash_lock); | 369 | spin_lock(&sbi->lookup_lock); |
530 | head = &sbi->rehash_list; | 370 | head = &sbi->active_list; |
531 | list_for_each(p, head) { | 371 | list_for_each(p, head) { |
532 | struct autofs_info *ino; | 372 | struct autofs_info *ino; |
533 | struct dentry *dentry; | 373 | struct dentry *dentry; |
534 | struct qstr *qstr; | 374 | struct qstr *qstr; |
535 | 375 | ||
536 | ino = list_entry(p, struct autofs_info, rehash); | 376 | ino = list_entry(p, struct autofs_info, active); |
377 | dentry = ino->dentry; | ||
378 | |||
379 | spin_lock(&dentry->d_lock); | ||
380 | |||
381 | /* Already gone? */ | ||
382 | if (atomic_read(&dentry->d_count) == 0) | ||
383 | goto next; | ||
384 | |||
385 | qstr = &dentry->d_name; | ||
386 | |||
387 | if (dentry->d_name.hash != hash) | ||
388 | goto next; | ||
389 | if (dentry->d_parent != parent) | ||
390 | goto next; | ||
391 | |||
392 | if (qstr->len != len) | ||
393 | goto next; | ||
394 | if (memcmp(qstr->name, str, len)) | ||
395 | goto next; | ||
396 | |||
397 | if (d_unhashed(dentry)) { | ||
398 | dget(dentry); | ||
399 | spin_unlock(&dentry->d_lock); | ||
400 | spin_unlock(&sbi->lookup_lock); | ||
401 | spin_unlock(&dcache_lock); | ||
402 | return dentry; | ||
403 | } | ||
404 | next: | ||
405 | spin_unlock(&dentry->d_lock); | ||
406 | } | ||
407 | spin_unlock(&sbi->lookup_lock); | ||
408 | spin_unlock(&dcache_lock); | ||
409 | |||
410 | return NULL; | ||
411 | } | ||
412 | |||
413 | static struct dentry *autofs4_lookup_expiring(struct autofs_sb_info *sbi, struct dentry *parent, struct qstr *name) | ||
414 | { | ||
415 | unsigned int len = name->len; | ||
416 | unsigned int hash = name->hash; | ||
417 | const unsigned char *str = name->name; | ||
418 | struct list_head *p, *head; | ||
419 | |||
420 | spin_lock(&dcache_lock); | ||
421 | spin_lock(&sbi->lookup_lock); | ||
422 | head = &sbi->expiring_list; | ||
423 | list_for_each(p, head) { | ||
424 | struct autofs_info *ino; | ||
425 | struct dentry *dentry; | ||
426 | struct qstr *qstr; | ||
427 | |||
428 | ino = list_entry(p, struct autofs_info, expiring); | ||
537 | dentry = ino->dentry; | 429 | dentry = ino->dentry; |
538 | 430 | ||
539 | spin_lock(&dentry->d_lock); | 431 | spin_lock(&dentry->d_lock); |
@@ -555,33 +447,16 @@ static struct dentry *autofs4_lookup_unhashed(struct autofs_sb_info *sbi, struct | |||
555 | goto next; | 447 | goto next; |
556 | 448 | ||
557 | if (d_unhashed(dentry)) { | 449 | if (d_unhashed(dentry)) { |
558 | struct inode *inode = dentry->d_inode; | ||
559 | |||
560 | ino = autofs4_dentry_ino(dentry); | ||
561 | list_del_init(&ino->rehash); | ||
562 | dget(dentry); | 450 | dget(dentry); |
563 | /* | ||
564 | * Make the rehashed dentry negative so the VFS | ||
565 | * behaves as it should. | ||
566 | */ | ||
567 | if (inode) { | ||
568 | dentry->d_inode = NULL; | ||
569 | list_del_init(&dentry->d_alias); | ||
570 | spin_unlock(&dentry->d_lock); | ||
571 | spin_unlock(&sbi->rehash_lock); | ||
572 | spin_unlock(&dcache_lock); | ||
573 | iput(inode); | ||
574 | return dentry; | ||
575 | } | ||
576 | spin_unlock(&dentry->d_lock); | 451 | spin_unlock(&dentry->d_lock); |
577 | spin_unlock(&sbi->rehash_lock); | 452 | spin_unlock(&sbi->lookup_lock); |
578 | spin_unlock(&dcache_lock); | 453 | spin_unlock(&dcache_lock); |
579 | return dentry; | 454 | return dentry; |
580 | } | 455 | } |
581 | next: | 456 | next: |
582 | spin_unlock(&dentry->d_lock); | 457 | spin_unlock(&dentry->d_lock); |
583 | } | 458 | } |
584 | spin_unlock(&sbi->rehash_lock); | 459 | spin_unlock(&sbi->lookup_lock); |
585 | spin_unlock(&dcache_lock); | 460 | spin_unlock(&dcache_lock); |
586 | 461 | ||
587 | return NULL; | 462 | return NULL; |
@@ -591,7 +466,8 @@ next: | |||
591 | static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 466 | static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) |
592 | { | 467 | { |
593 | struct autofs_sb_info *sbi; | 468 | struct autofs_sb_info *sbi; |
594 | struct dentry *unhashed; | 469 | struct autofs_info *ino; |
470 | struct dentry *expiring, *unhashed; | ||
595 | int oz_mode; | 471 | int oz_mode; |
596 | 472 | ||
597 | DPRINTK("name = %.*s", | 473 | DPRINTK("name = %.*s", |
@@ -607,8 +483,26 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
607 | DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d", | 483 | DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d", |
608 | current->pid, task_pgrp_nr(current), sbi->catatonic, oz_mode); | 484 | current->pid, task_pgrp_nr(current), sbi->catatonic, oz_mode); |
609 | 485 | ||
610 | unhashed = autofs4_lookup_unhashed(sbi, dentry->d_parent, &dentry->d_name); | 486 | expiring = autofs4_lookup_expiring(sbi, dentry->d_parent, &dentry->d_name); |
611 | if (!unhashed) { | 487 | if (expiring) { |
488 | /* | ||
489 | * If we are racing with expire the request might not | ||
490 | * be quite complete but the directory has been removed | ||
491 | * so it must have been successful, so just wait for it. | ||
492 | */ | ||
493 | ino = autofs4_dentry_ino(expiring); | ||
494 | autofs4_expire_wait(expiring); | ||
495 | spin_lock(&sbi->lookup_lock); | ||
496 | if (!list_empty(&ino->expiring)) | ||
497 | list_del_init(&ino->expiring); | ||
498 | spin_unlock(&sbi->lookup_lock); | ||
499 | dput(expiring); | ||
500 | } | ||
501 | |||
502 | unhashed = autofs4_lookup_active(sbi, dentry->d_parent, &dentry->d_name); | ||
503 | if (unhashed) | ||
504 | dentry = unhashed; | ||
505 | else { | ||
612 | /* | 506 | /* |
613 | * Mark the dentry incomplete but don't hash it. We do this | 507 | * Mark the dentry incomplete but don't hash it. We do this |
614 | * to serialize our inode creation operations (symlink and | 508 | * to serialize our inode creation operations (symlink and |
@@ -622,39 +516,34 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
622 | */ | 516 | */ |
623 | dentry->d_op = &autofs4_root_dentry_operations; | 517 | dentry->d_op = &autofs4_root_dentry_operations; |
624 | 518 | ||
625 | dentry->d_fsdata = NULL; | ||
626 | d_instantiate(dentry, NULL); | ||
627 | } else { | ||
628 | struct autofs_info *ino = autofs4_dentry_ino(unhashed); | ||
629 | DPRINTK("rehash %p with %p", dentry, unhashed); | ||
630 | /* | 519 | /* |
631 | * If we are racing with expire the request might not | 520 | * And we need to ensure that the same dentry is used for |
632 | * be quite complete but the directory has been removed | 521 | * all following lookup calls until it is hashed so that |
633 | * so it must have been successful, so just wait for it. | 522 | * the dentry flags are persistent throughout the request. |
634 | * We need to ensure the AUTOFS_INF_EXPIRING flag is clear | ||
635 | * before continuing as revalidate may fail when calling | ||
636 | * try_to_fill_dentry (returning EAGAIN) if we don't. | ||
637 | */ | 523 | */ |
638 | while (ino && (ino->flags & AUTOFS_INF_EXPIRING)) { | 524 | ino = autofs4_init_ino(NULL, sbi, 0555); |
639 | DPRINTK("wait for incomplete expire %p name=%.*s", | 525 | if (!ino) |
640 | unhashed, unhashed->d_name.len, | 526 | return ERR_PTR(-ENOMEM); |
641 | unhashed->d_name.name); | 527 | |
642 | autofs4_wait(sbi, unhashed, NFY_NONE); | 528 | dentry->d_fsdata = ino; |
643 | DPRINTK("request completed"); | 529 | ino->dentry = dentry; |
644 | } | 530 | |
645 | dentry = unhashed; | 531 | spin_lock(&sbi->lookup_lock); |
532 | list_add(&ino->active, &sbi->active_list); | ||
533 | spin_unlock(&sbi->lookup_lock); | ||
534 | |||
535 | d_instantiate(dentry, NULL); | ||
646 | } | 536 | } |
647 | 537 | ||
648 | if (!oz_mode) { | 538 | if (!oz_mode) { |
649 | spin_lock(&dentry->d_lock); | 539 | spin_lock(&dentry->d_lock); |
650 | dentry->d_flags |= DCACHE_AUTOFS_PENDING; | 540 | dentry->d_flags |= DCACHE_AUTOFS_PENDING; |
651 | spin_unlock(&dentry->d_lock); | 541 | spin_unlock(&dentry->d_lock); |
652 | } | 542 | if (dentry->d_op && dentry->d_op->d_revalidate) { |
653 | 543 | mutex_unlock(&dir->i_mutex); | |
654 | if (dentry->d_op && dentry->d_op->d_revalidate) { | 544 | (dentry->d_op->d_revalidate)(dentry, nd); |
655 | mutex_unlock(&dir->i_mutex); | 545 | mutex_lock(&dir->i_mutex); |
656 | (dentry->d_op->d_revalidate)(dentry, nd); | 546 | } |
657 | mutex_lock(&dir->i_mutex); | ||
658 | } | 547 | } |
659 | 548 | ||
660 | /* | 549 | /* |
@@ -673,9 +562,11 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
673 | return ERR_PTR(-ERESTARTNOINTR); | 562 | return ERR_PTR(-ERESTARTNOINTR); |
674 | } | 563 | } |
675 | } | 564 | } |
676 | spin_lock(&dentry->d_lock); | 565 | if (!oz_mode) { |
677 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; | 566 | spin_lock(&dentry->d_lock); |
678 | spin_unlock(&dentry->d_lock); | 567 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; |
568 | spin_unlock(&dentry->d_lock); | ||
569 | } | ||
679 | } | 570 | } |
680 | 571 | ||
681 | /* | 572 | /* |
@@ -706,7 +597,7 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
706 | } | 597 | } |
707 | 598 | ||
708 | if (unhashed) | 599 | if (unhashed) |
709 | return dentry; | 600 | return unhashed; |
710 | 601 | ||
711 | return NULL; | 602 | return NULL; |
712 | } | 603 | } |
@@ -728,20 +619,31 @@ static int autofs4_dir_symlink(struct inode *dir, | |||
728 | return -EACCES; | 619 | return -EACCES; |
729 | 620 | ||
730 | ino = autofs4_init_ino(ino, sbi, S_IFLNK | 0555); | 621 | ino = autofs4_init_ino(ino, sbi, S_IFLNK | 0555); |
731 | if (ino == NULL) | 622 | if (!ino) |
732 | return -ENOSPC; | 623 | return -ENOMEM; |
733 | 624 | ||
734 | ino->size = strlen(symname); | 625 | spin_lock(&sbi->lookup_lock); |
735 | ino->u.symlink = cp = kmalloc(ino->size + 1, GFP_KERNEL); | 626 | if (!list_empty(&ino->active)) |
627 | list_del_init(&ino->active); | ||
628 | spin_unlock(&sbi->lookup_lock); | ||
736 | 629 | ||
737 | if (cp == NULL) { | 630 | ino->size = strlen(symname); |
738 | kfree(ino); | 631 | cp = kmalloc(ino->size + 1, GFP_KERNEL); |
739 | return -ENOSPC; | 632 | if (!cp) { |
633 | if (!dentry->d_fsdata) | ||
634 | kfree(ino); | ||
635 | return -ENOMEM; | ||
740 | } | 636 | } |
741 | 637 | ||
742 | strcpy(cp, symname); | 638 | strcpy(cp, symname); |
743 | 639 | ||
744 | inode = autofs4_get_inode(dir->i_sb, ino); | 640 | inode = autofs4_get_inode(dir->i_sb, ino); |
641 | if (!inode) { | ||
642 | kfree(cp); | ||
643 | if (!dentry->d_fsdata) | ||
644 | kfree(ino); | ||
645 | return -ENOMEM; | ||
646 | } | ||
745 | d_add(dentry, inode); | 647 | d_add(dentry, inode); |
746 | 648 | ||
747 | if (dir == dir->i_sb->s_root->d_inode) | 649 | if (dir == dir->i_sb->s_root->d_inode) |
@@ -757,6 +659,7 @@ static int autofs4_dir_symlink(struct inode *dir, | |||
757 | atomic_inc(&p_ino->count); | 659 | atomic_inc(&p_ino->count); |
758 | ino->inode = inode; | 660 | ino->inode = inode; |
759 | 661 | ||
662 | ino->u.symlink = cp; | ||
760 | dir->i_mtime = CURRENT_TIME; | 663 | dir->i_mtime = CURRENT_TIME; |
761 | 664 | ||
762 | return 0; | 665 | return 0; |
@@ -769,9 +672,8 @@ static int autofs4_dir_symlink(struct inode *dir, | |||
769 | * that the file no longer exists. However, doing that means that the | 672 | * that the file no longer exists. However, doing that means that the |
770 | * VFS layer can turn the dentry into a negative dentry. We don't want | 673 | * VFS layer can turn the dentry into a negative dentry. We don't want |
771 | * this, because the unlink is probably the result of an expire. | 674 | * this, because the unlink is probably the result of an expire. |
772 | * We simply d_drop it and add it to a rehash candidates list in the | 675 | * We simply d_drop it and add it to a expiring list in the super block, |
773 | * super block, which allows the dentry lookup to reuse it retaining | 676 | * which allows the dentry lookup to check for an incomplete expire. |
774 | * the flags, such as expire in progress, in case we're racing with expire. | ||
775 | * | 677 | * |
776 | * If a process is blocked on the dentry waiting for the expire to finish, | 678 | * If a process is blocked on the dentry waiting for the expire to finish, |
777 | * it will invalidate the dentry and try to mount with a new one. | 679 | * it will invalidate the dentry and try to mount with a new one. |
@@ -801,9 +703,10 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry) | |||
801 | dir->i_mtime = CURRENT_TIME; | 703 | dir->i_mtime = CURRENT_TIME; |
802 | 704 | ||
803 | spin_lock(&dcache_lock); | 705 | spin_lock(&dcache_lock); |
804 | spin_lock(&sbi->rehash_lock); | 706 | spin_lock(&sbi->lookup_lock); |
805 | list_add(&ino->rehash, &sbi->rehash_list); | 707 | if (list_empty(&ino->expiring)) |
806 | spin_unlock(&sbi->rehash_lock); | 708 | list_add(&ino->expiring, &sbi->expiring_list); |
709 | spin_unlock(&sbi->lookup_lock); | ||
807 | spin_lock(&dentry->d_lock); | 710 | spin_lock(&dentry->d_lock); |
808 | __d_drop(dentry); | 711 | __d_drop(dentry); |
809 | spin_unlock(&dentry->d_lock); | 712 | spin_unlock(&dentry->d_lock); |
@@ -829,9 +732,10 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry) | |||
829 | spin_unlock(&dcache_lock); | 732 | spin_unlock(&dcache_lock); |
830 | return -ENOTEMPTY; | 733 | return -ENOTEMPTY; |
831 | } | 734 | } |
832 | spin_lock(&sbi->rehash_lock); | 735 | spin_lock(&sbi->lookup_lock); |
833 | list_add(&ino->rehash, &sbi->rehash_list); | 736 | if (list_empty(&ino->expiring)) |
834 | spin_unlock(&sbi->rehash_lock); | 737 | list_add(&ino->expiring, &sbi->expiring_list); |
738 | spin_unlock(&sbi->lookup_lock); | ||
835 | spin_lock(&dentry->d_lock); | 739 | spin_lock(&dentry->d_lock); |
836 | __d_drop(dentry); | 740 | __d_drop(dentry); |
837 | spin_unlock(&dentry->d_lock); | 741 | spin_unlock(&dentry->d_lock); |
@@ -866,10 +770,20 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
866 | dentry, dentry->d_name.len, dentry->d_name.name); | 770 | dentry, dentry->d_name.len, dentry->d_name.name); |
867 | 771 | ||
868 | ino = autofs4_init_ino(ino, sbi, S_IFDIR | 0555); | 772 | ino = autofs4_init_ino(ino, sbi, S_IFDIR | 0555); |
869 | if (ino == NULL) | 773 | if (!ino) |
870 | return -ENOSPC; | 774 | return -ENOMEM; |
775 | |||
776 | spin_lock(&sbi->lookup_lock); | ||
777 | if (!list_empty(&ino->active)) | ||
778 | list_del_init(&ino->active); | ||
779 | spin_unlock(&sbi->lookup_lock); | ||
871 | 780 | ||
872 | inode = autofs4_get_inode(dir->i_sb, ino); | 781 | inode = autofs4_get_inode(dir->i_sb, ino); |
782 | if (!inode) { | ||
783 | if (!dentry->d_fsdata) | ||
784 | kfree(ino); | ||
785 | return -ENOMEM; | ||
786 | } | ||
873 | d_add(dentry, inode); | 787 | d_add(dentry, inode); |
874 | 788 | ||
875 | if (dir == dir->i_sb->s_root->d_inode) | 789 | if (dir == dir->i_sb->s_root->d_inode) |
@@ -922,44 +836,6 @@ static inline int autofs4_get_protosubver(struct autofs_sb_info *sbi, int __user | |||
922 | } | 836 | } |
923 | 837 | ||
924 | /* | 838 | /* |
925 | * Tells the daemon whether we need to reghost or not. Also, clears | ||
926 | * the reghost_needed flag. | ||
927 | */ | ||
928 | static inline int autofs4_ask_reghost(struct autofs_sb_info *sbi, int __user *p) | ||
929 | { | ||
930 | int status; | ||
931 | |||
932 | DPRINTK("returning %d", sbi->needs_reghost); | ||
933 | |||
934 | status = put_user(sbi->needs_reghost, p); | ||
935 | if (status) | ||
936 | return status; | ||
937 | |||
938 | sbi->needs_reghost = 0; | ||
939 | return 0; | ||
940 | } | ||
941 | |||
942 | /* | ||
943 | * Enable / Disable reghosting ioctl() operation | ||
944 | */ | ||
945 | static inline int autofs4_toggle_reghost(struct autofs_sb_info *sbi, int __user *p) | ||
946 | { | ||
947 | int status; | ||
948 | int val; | ||
949 | |||
950 | status = get_user(val, p); | ||
951 | |||
952 | DPRINTK("reghost = %d", val); | ||
953 | |||
954 | if (status) | ||
955 | return status; | ||
956 | |||
957 | /* turn on/off reghosting, with the val */ | ||
958 | sbi->reghost_enabled = val; | ||
959 | return 0; | ||
960 | } | ||
961 | |||
962 | /* | ||
963 | * Tells the daemon whether it can umount the autofs mount. | 839 | * Tells the daemon whether it can umount the autofs mount. |
964 | */ | 840 | */ |
965 | static inline int autofs4_ask_umount(struct vfsmount *mnt, int __user *p) | 841 | static inline int autofs4_ask_umount(struct vfsmount *mnt, int __user *p) |
@@ -1023,11 +899,6 @@ static int autofs4_root_ioctl(struct inode *inode, struct file *filp, | |||
1023 | case AUTOFS_IOC_SETTIMEOUT: | 899 | case AUTOFS_IOC_SETTIMEOUT: |
1024 | return autofs4_get_set_timeout(sbi, p); | 900 | return autofs4_get_set_timeout(sbi, p); |
1025 | 901 | ||
1026 | case AUTOFS_IOC_TOGGLEREGHOST: | ||
1027 | return autofs4_toggle_reghost(sbi, p); | ||
1028 | case AUTOFS_IOC_ASKREGHOST: | ||
1029 | return autofs4_ask_reghost(sbi, p); | ||
1030 | |||
1031 | case AUTOFS_IOC_ASKUMOUNT: | 902 | case AUTOFS_IOC_ASKUMOUNT: |
1032 | return autofs4_ask_umount(filp->f_path.mnt, p); | 903 | return autofs4_ask_umount(filp->f_path.mnt, p); |
1033 | 904 | ||
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c index 75e5955c3f6d..35216d18d8b5 100644 --- a/fs/autofs4/waitq.c +++ b/fs/autofs4/waitq.c | |||
@@ -28,6 +28,12 @@ void autofs4_catatonic_mode(struct autofs_sb_info *sbi) | |||
28 | { | 28 | { |
29 | struct autofs_wait_queue *wq, *nwq; | 29 | struct autofs_wait_queue *wq, *nwq; |
30 | 30 | ||
31 | mutex_lock(&sbi->wq_mutex); | ||
32 | if (sbi->catatonic) { | ||
33 | mutex_unlock(&sbi->wq_mutex); | ||
34 | return; | ||
35 | } | ||
36 | |||
31 | DPRINTK("entering catatonic mode"); | 37 | DPRINTK("entering catatonic mode"); |
32 | 38 | ||
33 | sbi->catatonic = 1; | 39 | sbi->catatonic = 1; |
@@ -36,13 +42,18 @@ void autofs4_catatonic_mode(struct autofs_sb_info *sbi) | |||
36 | while (wq) { | 42 | while (wq) { |
37 | nwq = wq->next; | 43 | nwq = wq->next; |
38 | wq->status = -ENOENT; /* Magic is gone - report failure */ | 44 | wq->status = -ENOENT; /* Magic is gone - report failure */ |
39 | kfree(wq->name); | 45 | if (wq->name.name) { |
40 | wq->name = NULL; | 46 | kfree(wq->name.name); |
47 | wq->name.name = NULL; | ||
48 | } | ||
49 | wq->wait_ctr--; | ||
41 | wake_up_interruptible(&wq->queue); | 50 | wake_up_interruptible(&wq->queue); |
42 | wq = nwq; | 51 | wq = nwq; |
43 | } | 52 | } |
44 | fput(sbi->pipe); /* Close the pipe */ | 53 | fput(sbi->pipe); /* Close the pipe */ |
45 | sbi->pipe = NULL; | 54 | sbi->pipe = NULL; |
55 | sbi->pipefd = -1; | ||
56 | mutex_unlock(&sbi->wq_mutex); | ||
46 | } | 57 | } |
47 | 58 | ||
48 | static int autofs4_write(struct file *file, const void *addr, int bytes) | 59 | static int autofs4_write(struct file *file, const void *addr, int bytes) |
@@ -89,10 +100,11 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi, | |||
89 | union autofs_packet_union v4_pkt; | 100 | union autofs_packet_union v4_pkt; |
90 | union autofs_v5_packet_union v5_pkt; | 101 | union autofs_v5_packet_union v5_pkt; |
91 | } pkt; | 102 | } pkt; |
103 | struct file *pipe = NULL; | ||
92 | size_t pktsz; | 104 | size_t pktsz; |
93 | 105 | ||
94 | DPRINTK("wait id = 0x%08lx, name = %.*s, type=%d", | 106 | DPRINTK("wait id = 0x%08lx, name = %.*s, type=%d", |
95 | wq->wait_queue_token, wq->len, wq->name, type); | 107 | wq->wait_queue_token, wq->name.len, wq->name.name, type); |
96 | 108 | ||
97 | memset(&pkt,0,sizeof pkt); /* For security reasons */ | 109 | memset(&pkt,0,sizeof pkt); /* For security reasons */ |
98 | 110 | ||
@@ -107,9 +119,9 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi, | |||
107 | pktsz = sizeof(*mp); | 119 | pktsz = sizeof(*mp); |
108 | 120 | ||
109 | mp->wait_queue_token = wq->wait_queue_token; | 121 | mp->wait_queue_token = wq->wait_queue_token; |
110 | mp->len = wq->len; | 122 | mp->len = wq->name.len; |
111 | memcpy(mp->name, wq->name, wq->len); | 123 | memcpy(mp->name, wq->name.name, wq->name.len); |
112 | mp->name[wq->len] = '\0'; | 124 | mp->name[wq->name.len] = '\0'; |
113 | break; | 125 | break; |
114 | } | 126 | } |
115 | case autofs_ptype_expire_multi: | 127 | case autofs_ptype_expire_multi: |
@@ -119,9 +131,9 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi, | |||
119 | pktsz = sizeof(*ep); | 131 | pktsz = sizeof(*ep); |
120 | 132 | ||
121 | ep->wait_queue_token = wq->wait_queue_token; | 133 | ep->wait_queue_token = wq->wait_queue_token; |
122 | ep->len = wq->len; | 134 | ep->len = wq->name.len; |
123 | memcpy(ep->name, wq->name, wq->len); | 135 | memcpy(ep->name, wq->name.name, wq->name.len); |
124 | ep->name[wq->len] = '\0'; | 136 | ep->name[wq->name.len] = '\0'; |
125 | break; | 137 | break; |
126 | } | 138 | } |
127 | /* | 139 | /* |
@@ -138,9 +150,9 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi, | |||
138 | pktsz = sizeof(*packet); | 150 | pktsz = sizeof(*packet); |
139 | 151 | ||
140 | packet->wait_queue_token = wq->wait_queue_token; | 152 | packet->wait_queue_token = wq->wait_queue_token; |
141 | packet->len = wq->len; | 153 | packet->len = wq->name.len; |
142 | memcpy(packet->name, wq->name, wq->len); | 154 | memcpy(packet->name, wq->name.name, wq->name.len); |
143 | packet->name[wq->len] = '\0'; | 155 | packet->name[wq->name.len] = '\0'; |
144 | packet->dev = wq->dev; | 156 | packet->dev = wq->dev; |
145 | packet->ino = wq->ino; | 157 | packet->ino = wq->ino; |
146 | packet->uid = wq->uid; | 158 | packet->uid = wq->uid; |
@@ -154,8 +166,19 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi, | |||
154 | return; | 166 | return; |
155 | } | 167 | } |
156 | 168 | ||
157 | if (autofs4_write(sbi->pipe, &pkt, pktsz)) | 169 | /* Check if we have become catatonic */ |
158 | autofs4_catatonic_mode(sbi); | 170 | mutex_lock(&sbi->wq_mutex); |
171 | if (!sbi->catatonic) { | ||
172 | pipe = sbi->pipe; | ||
173 | get_file(pipe); | ||
174 | } | ||
175 | mutex_unlock(&sbi->wq_mutex); | ||
176 | |||
177 | if (pipe) { | ||
178 | if (autofs4_write(pipe, &pkt, pktsz)) | ||
179 | autofs4_catatonic_mode(sbi); | ||
180 | fput(pipe); | ||
181 | } | ||
159 | } | 182 | } |
160 | 183 | ||
161 | static int autofs4_getpath(struct autofs_sb_info *sbi, | 184 | static int autofs4_getpath(struct autofs_sb_info *sbi, |
@@ -191,58 +214,55 @@ static int autofs4_getpath(struct autofs_sb_info *sbi, | |||
191 | } | 214 | } |
192 | 215 | ||
193 | static struct autofs_wait_queue * | 216 | static struct autofs_wait_queue * |
194 | autofs4_find_wait(struct autofs_sb_info *sbi, | 217 | autofs4_find_wait(struct autofs_sb_info *sbi, struct qstr *qstr) |
195 | char *name, unsigned int hash, unsigned int len) | ||
196 | { | 218 | { |
197 | struct autofs_wait_queue *wq; | 219 | struct autofs_wait_queue *wq; |
198 | 220 | ||
199 | for (wq = sbi->queues; wq; wq = wq->next) { | 221 | for (wq = sbi->queues; wq; wq = wq->next) { |
200 | if (wq->hash == hash && | 222 | if (wq->name.hash == qstr->hash && |
201 | wq->len == len && | 223 | wq->name.len == qstr->len && |
202 | wq->name && !memcmp(wq->name, name, len)) | 224 | wq->name.name && |
225 | !memcmp(wq->name.name, qstr->name, qstr->len)) | ||
203 | break; | 226 | break; |
204 | } | 227 | } |
205 | return wq; | 228 | return wq; |
206 | } | 229 | } |
207 | 230 | ||
208 | int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | 231 | /* |
209 | enum autofs_notify notify) | 232 | * Check if we have a valid request. |
233 | * Returns | ||
234 | * 1 if the request should continue. | ||
235 | * In this case we can return an autofs_wait_queue entry if one is | ||
236 | * found or NULL to idicate a new wait needs to be created. | ||
237 | * 0 or a negative errno if the request shouldn't continue. | ||
238 | */ | ||
239 | static int validate_request(struct autofs_wait_queue **wait, | ||
240 | struct autofs_sb_info *sbi, | ||
241 | struct qstr *qstr, | ||
242 | struct dentry*dentry, enum autofs_notify notify) | ||
210 | { | 243 | { |
211 | struct autofs_info *ino; | ||
212 | struct autofs_wait_queue *wq; | 244 | struct autofs_wait_queue *wq; |
213 | char *name; | 245 | struct autofs_info *ino; |
214 | unsigned int len = 0; | ||
215 | unsigned int hash = 0; | ||
216 | int status, type; | ||
217 | |||
218 | /* In catatonic mode, we don't wait for nobody */ | ||
219 | if (sbi->catatonic) | ||
220 | return -ENOENT; | ||
221 | |||
222 | name = kmalloc(NAME_MAX + 1, GFP_KERNEL); | ||
223 | if (!name) | ||
224 | return -ENOMEM; | ||
225 | 246 | ||
226 | /* If this is a direct mount request create a dummy name */ | 247 | /* Wait in progress, continue; */ |
227 | if (IS_ROOT(dentry) && (sbi->type & AUTOFS_TYPE_DIRECT)) | 248 | wq = autofs4_find_wait(sbi, qstr); |
228 | len = sprintf(name, "%p", dentry); | 249 | if (wq) { |
229 | else { | 250 | *wait = wq; |
230 | len = autofs4_getpath(sbi, dentry, &name); | 251 | return 1; |
231 | if (!len) { | ||
232 | kfree(name); | ||
233 | return -ENOENT; | ||
234 | } | ||
235 | } | 252 | } |
236 | hash = full_name_hash(name, len); | ||
237 | 253 | ||
238 | if (mutex_lock_interruptible(&sbi->wq_mutex)) { | 254 | *wait = NULL; |
239 | kfree(name); | ||
240 | return -EINTR; | ||
241 | } | ||
242 | 255 | ||
243 | wq = autofs4_find_wait(sbi, name, hash, len); | 256 | /* If we don't yet have any info this is a new request */ |
244 | ino = autofs4_dentry_ino(dentry); | 257 | ino = autofs4_dentry_ino(dentry); |
245 | if (!wq && ino && notify == NFY_NONE) { | 258 | if (!ino) |
259 | return 1; | ||
260 | |||
261 | /* | ||
262 | * If we've been asked to wait on an existing expire (NFY_NONE) | ||
263 | * but there is no wait in the queue ... | ||
264 | */ | ||
265 | if (notify == NFY_NONE) { | ||
246 | /* | 266 | /* |
247 | * Either we've betean the pending expire to post it's | 267 | * Either we've betean the pending expire to post it's |
248 | * wait or it finished while we waited on the mutex. | 268 | * wait or it finished while we waited on the mutex. |
@@ -253,13 +273,14 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | |||
253 | while (ino->flags & AUTOFS_INF_EXPIRING) { | 273 | while (ino->flags & AUTOFS_INF_EXPIRING) { |
254 | mutex_unlock(&sbi->wq_mutex); | 274 | mutex_unlock(&sbi->wq_mutex); |
255 | schedule_timeout_interruptible(HZ/10); | 275 | schedule_timeout_interruptible(HZ/10); |
256 | if (mutex_lock_interruptible(&sbi->wq_mutex)) { | 276 | if (mutex_lock_interruptible(&sbi->wq_mutex)) |
257 | kfree(name); | ||
258 | return -EINTR; | 277 | return -EINTR; |
278 | |||
279 | wq = autofs4_find_wait(sbi, qstr); | ||
280 | if (wq) { | ||
281 | *wait = wq; | ||
282 | return 1; | ||
259 | } | 283 | } |
260 | wq = autofs4_find_wait(sbi, name, hash, len); | ||
261 | if (wq) | ||
262 | break; | ||
263 | } | 284 | } |
264 | 285 | ||
265 | /* | 286 | /* |
@@ -267,18 +288,96 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | |||
267 | * cases where we wait on NFY_NONE neither depend on the | 288 | * cases where we wait on NFY_NONE neither depend on the |
268 | * return status of the wait. | 289 | * return status of the wait. |
269 | */ | 290 | */ |
270 | if (!wq) { | 291 | return 0; |
292 | } | ||
293 | |||
294 | /* | ||
295 | * If we've been asked to trigger a mount and the request | ||
296 | * completed while we waited on the mutex ... | ||
297 | */ | ||
298 | if (notify == NFY_MOUNT) { | ||
299 | /* | ||
300 | * If the dentry isn't hashed just go ahead and try the | ||
301 | * mount again with a new wait (not much else we can do). | ||
302 | */ | ||
303 | if (!d_unhashed(dentry)) { | ||
304 | /* | ||
305 | * But if the dentry is hashed, that means that we | ||
306 | * got here through the revalidate path. Thus, we | ||
307 | * need to check if the dentry has been mounted | ||
308 | * while we waited on the wq_mutex. If it has, | ||
309 | * simply return success. | ||
310 | */ | ||
311 | if (d_mountpoint(dentry)) | ||
312 | return 0; | ||
313 | } | ||
314 | } | ||
315 | |||
316 | return 1; | ||
317 | } | ||
318 | |||
319 | int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | ||
320 | enum autofs_notify notify) | ||
321 | { | ||
322 | struct autofs_wait_queue *wq; | ||
323 | struct qstr qstr; | ||
324 | char *name; | ||
325 | int status, ret, type; | ||
326 | |||
327 | /* In catatonic mode, we don't wait for nobody */ | ||
328 | if (sbi->catatonic) | ||
329 | return -ENOENT; | ||
330 | |||
331 | if (!dentry->d_inode) { | ||
332 | /* | ||
333 | * A wait for a negative dentry is invalid for certain | ||
334 | * cases. A direct or offset mount "always" has its mount | ||
335 | * point directory created and so the request dentry must | ||
336 | * be positive or the map key doesn't exist. The situation | ||
337 | * is very similar for indirect mounts except only dentrys | ||
338 | * in the root of the autofs file system may be negative. | ||
339 | */ | ||
340 | if (sbi->type & (AUTOFS_TYPE_DIRECT|AUTOFS_TYPE_OFFSET)) | ||
341 | return -ENOENT; | ||
342 | else if (!IS_ROOT(dentry->d_parent)) | ||
343 | return -ENOENT; | ||
344 | } | ||
345 | |||
346 | name = kmalloc(NAME_MAX + 1, GFP_KERNEL); | ||
347 | if (!name) | ||
348 | return -ENOMEM; | ||
349 | |||
350 | /* If this is a direct mount request create a dummy name */ | ||
351 | if (IS_ROOT(dentry) && (sbi->type & AUTOFS_TYPE_DIRECT)) | ||
352 | qstr.len = sprintf(name, "%p", dentry); | ||
353 | else { | ||
354 | qstr.len = autofs4_getpath(sbi, dentry, &name); | ||
355 | if (!qstr.len) { | ||
271 | kfree(name); | 356 | kfree(name); |
272 | mutex_unlock(&sbi->wq_mutex); | 357 | return -ENOENT; |
273 | return 0; | ||
274 | } | 358 | } |
275 | } | 359 | } |
360 | qstr.name = name; | ||
361 | qstr.hash = full_name_hash(name, qstr.len); | ||
362 | |||
363 | if (mutex_lock_interruptible(&sbi->wq_mutex)) { | ||
364 | kfree(qstr.name); | ||
365 | return -EINTR; | ||
366 | } | ||
367 | |||
368 | ret = validate_request(&wq, sbi, &qstr, dentry, notify); | ||
369 | if (ret <= 0) { | ||
370 | if (ret == 0) | ||
371 | mutex_unlock(&sbi->wq_mutex); | ||
372 | kfree(qstr.name); | ||
373 | return ret; | ||
374 | } | ||
276 | 375 | ||
277 | if (!wq) { | 376 | if (!wq) { |
278 | /* Create a new wait queue */ | 377 | /* Create a new wait queue */ |
279 | wq = kmalloc(sizeof(struct autofs_wait_queue),GFP_KERNEL); | 378 | wq = kmalloc(sizeof(struct autofs_wait_queue),GFP_KERNEL); |
280 | if (!wq) { | 379 | if (!wq) { |
281 | kfree(name); | 380 | kfree(qstr.name); |
282 | mutex_unlock(&sbi->wq_mutex); | 381 | mutex_unlock(&sbi->wq_mutex); |
283 | return -ENOMEM; | 382 | return -ENOMEM; |
284 | } | 383 | } |
@@ -289,9 +388,7 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | |||
289 | wq->next = sbi->queues; | 388 | wq->next = sbi->queues; |
290 | sbi->queues = wq; | 389 | sbi->queues = wq; |
291 | init_waitqueue_head(&wq->queue); | 390 | init_waitqueue_head(&wq->queue); |
292 | wq->hash = hash; | 391 | memcpy(&wq->name, &qstr, sizeof(struct qstr)); |
293 | wq->name = name; | ||
294 | wq->len = len; | ||
295 | wq->dev = autofs4_get_dev(sbi); | 392 | wq->dev = autofs4_get_dev(sbi); |
296 | wq->ino = autofs4_get_ino(sbi); | 393 | wq->ino = autofs4_get_ino(sbi); |
297 | wq->uid = current->uid; | 394 | wq->uid = current->uid; |
@@ -299,7 +396,7 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | |||
299 | wq->pid = current->pid; | 396 | wq->pid = current->pid; |
300 | wq->tgid = current->tgid; | 397 | wq->tgid = current->tgid; |
301 | wq->status = -EINTR; /* Status return if interrupted */ | 398 | wq->status = -EINTR; /* Status return if interrupted */ |
302 | atomic_set(&wq->wait_ctr, 2); | 399 | wq->wait_ctr = 2; |
303 | mutex_unlock(&sbi->wq_mutex); | 400 | mutex_unlock(&sbi->wq_mutex); |
304 | 401 | ||
305 | if (sbi->version < 5) { | 402 | if (sbi->version < 5) { |
@@ -319,28 +416,25 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | |||
319 | } | 416 | } |
320 | 417 | ||
321 | DPRINTK("new wait id = 0x%08lx, name = %.*s, nfy=%d\n", | 418 | DPRINTK("new wait id = 0x%08lx, name = %.*s, nfy=%d\n", |
322 | (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify); | 419 | (unsigned long) wq->wait_queue_token, wq->name.len, |
420 | wq->name.name, notify); | ||
323 | 421 | ||
324 | /* autofs4_notify_daemon() may block */ | 422 | /* autofs4_notify_daemon() may block */ |
325 | autofs4_notify_daemon(sbi, wq, type); | 423 | autofs4_notify_daemon(sbi, wq, type); |
326 | } else { | 424 | } else { |
327 | atomic_inc(&wq->wait_ctr); | 425 | wq->wait_ctr++; |
328 | mutex_unlock(&sbi->wq_mutex); | 426 | mutex_unlock(&sbi->wq_mutex); |
329 | kfree(name); | 427 | kfree(qstr.name); |
330 | DPRINTK("existing wait id = 0x%08lx, name = %.*s, nfy=%d", | 428 | DPRINTK("existing wait id = 0x%08lx, name = %.*s, nfy=%d", |
331 | (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify); | 429 | (unsigned long) wq->wait_queue_token, wq->name.len, |
332 | } | 430 | wq->name.name, notify); |
333 | |||
334 | /* wq->name is NULL if and only if the lock is already released */ | ||
335 | |||
336 | if (sbi->catatonic) { | ||
337 | /* We might have slept, so check again for catatonic mode */ | ||
338 | wq->status = -ENOENT; | ||
339 | kfree(wq->name); | ||
340 | wq->name = NULL; | ||
341 | } | 431 | } |
342 | 432 | ||
343 | if (wq->name) { | 433 | /* |
434 | * wq->name.name is NULL iff the lock is already released | ||
435 | * or the mount has been made catatonic. | ||
436 | */ | ||
437 | if (wq->name.name) { | ||
344 | /* Block all but "shutdown" signals while waiting */ | 438 | /* Block all but "shutdown" signals while waiting */ |
345 | sigset_t oldset; | 439 | sigset_t oldset; |
346 | unsigned long irqflags; | 440 | unsigned long irqflags; |
@@ -351,7 +445,7 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | |||
351 | recalc_sigpending(); | 445 | recalc_sigpending(); |
352 | spin_unlock_irqrestore(¤t->sighand->siglock, irqflags); | 446 | spin_unlock_irqrestore(¤t->sighand->siglock, irqflags); |
353 | 447 | ||
354 | wait_event_interruptible(wq->queue, wq->name == NULL); | 448 | wait_event_interruptible(wq->queue, wq->name.name == NULL); |
355 | 449 | ||
356 | spin_lock_irqsave(¤t->sighand->siglock, irqflags); | 450 | spin_lock_irqsave(¤t->sighand->siglock, irqflags); |
357 | current->blocked = oldset; | 451 | current->blocked = oldset; |
@@ -364,8 +458,10 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | |||
364 | status = wq->status; | 458 | status = wq->status; |
365 | 459 | ||
366 | /* Are we the last process to need status? */ | 460 | /* Are we the last process to need status? */ |
367 | if (atomic_dec_and_test(&wq->wait_ctr)) | 461 | mutex_lock(&sbi->wq_mutex); |
462 | if (!--wq->wait_ctr) | ||
368 | kfree(wq); | 463 | kfree(wq); |
464 | mutex_unlock(&sbi->wq_mutex); | ||
369 | 465 | ||
370 | return status; | 466 | return status; |
371 | } | 467 | } |
@@ -387,16 +483,13 @@ int autofs4_wait_release(struct autofs_sb_info *sbi, autofs_wqt_t wait_queue_tok | |||
387 | } | 483 | } |
388 | 484 | ||
389 | *wql = wq->next; /* Unlink from chain */ | 485 | *wql = wq->next; /* Unlink from chain */ |
390 | mutex_unlock(&sbi->wq_mutex); | 486 | kfree(wq->name.name); |
391 | kfree(wq->name); | 487 | wq->name.name = NULL; /* Do not wait on this queue */ |
392 | wq->name = NULL; /* Do not wait on this queue */ | ||
393 | |||
394 | wq->status = status; | 488 | wq->status = status; |
395 | 489 | wake_up_interruptible(&wq->queue); | |
396 | if (atomic_dec_and_test(&wq->wait_ctr)) /* Is anyone still waiting for this guy? */ | 490 | if (!--wq->wait_ctr) |
397 | kfree(wq); | 491 | kfree(wq); |
398 | else | 492 | mutex_unlock(&sbi->wq_mutex); |
399 | wake_up_interruptible(&wq->queue); | ||
400 | 493 | ||
401 | return 0; | 494 | return 0; |
402 | } | 495 | } |