Commit fc6504f0 authored by Ian Kent's avatar Ian Kent Committed by james toy

We need to be able to cope with the directory mutex being held during

->d_revalidate() in some cases, but not all cases, and not necessarily by
us.  Because we need to release the mutex when we call back to the daemon
to do perform a mount we must be sure that it is us who holds the mutex so
we must redirect mount requests to ->lookup() if the mutex is held.
Signed-off-by: default avatarIan Kent <raven@themaw.net>
Cc: Sage Weil <sage@newdream.net>
Cc: Al Viro <viro@ZenIV.linux.org.uk>
Cc: Andreas Dilger <adilger@sun.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Yehuda Saheh <yehuda@newdream.net>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent 283ba019
...@@ -60,6 +60,11 @@ do { \ ...@@ -60,6 +60,11 @@ do { \
current->pid, __func__, ##args); \ current->pid, __func__, ##args); \
} while (0) } while (0)
struct rehash_entry {
struct task_struct *task;
struct list_head list;
};
/* Unified info structure. This is pointed to by both the dentry and /* Unified info structure. This is pointed to by both the dentry and
inode structures. Each file in the filesystem has an instance of this inode structures. Each file in the filesystem has an instance of this
structure. It holds a reference to the dentry, so dentries are never structure. It holds a reference to the dentry, so dentries are never
...@@ -76,6 +81,7 @@ struct autofs_info { ...@@ -76,6 +81,7 @@ struct autofs_info {
struct list_head active; struct list_head active;
int active_count; int active_count;
struct list_head rehash_list;
struct list_head expiring; struct list_head expiring;
...@@ -98,6 +104,7 @@ struct autofs_info { ...@@ -98,6 +104,7 @@ struct autofs_info {
#define AUTOFS_INF_EXPIRING (1<<0) /* dentry is in the process of expiring */ #define AUTOFS_INF_EXPIRING (1<<0) /* dentry is in the process of expiring */
#define AUTOFS_INF_MOUNTPOINT (1<<1) /* mountpoint status for direct expire */ #define AUTOFS_INF_MOUNTPOINT (1<<1) /* mountpoint status for direct expire */
#define AUTOFS_INF_PENDING (1<<2) /* dentry pending mount */ #define AUTOFS_INF_PENDING (1<<2) /* dentry pending mount */
#define AUTOFS_INF_REHASH (1<<3) /* dentry in transit to ->lookup() */
struct autofs_wait_queue { struct autofs_wait_queue {
wait_queue_head_t queue; wait_queue_head_t queue;
......
...@@ -279,6 +279,7 @@ struct dentry *autofs4_expire_direct(struct super_block *sb, ...@@ -279,6 +279,7 @@ struct dentry *autofs4_expire_direct(struct super_block *sb,
root->d_mounted--; root->d_mounted--;
} }
ino->flags |= AUTOFS_INF_EXPIRING; ino->flags |= AUTOFS_INF_EXPIRING;
autofs4_add_expiring(root);
init_completion(&ino->expire_complete); init_completion(&ino->expire_complete);
spin_unlock(&sbi->fs_lock); spin_unlock(&sbi->fs_lock);
return root; return root;
...@@ -406,6 +407,7 @@ found: ...@@ -406,6 +407,7 @@ found:
expired, (int)expired->d_name.len, expired->d_name.name); expired, (int)expired->d_name.len, expired->d_name.name);
ino = autofs4_dentry_ino(expired); ino = autofs4_dentry_ino(expired);
ino->flags |= AUTOFS_INF_EXPIRING; ino->flags |= AUTOFS_INF_EXPIRING;
autofs4_add_expiring(expired);
init_completion(&ino->expire_complete); init_completion(&ino->expire_complete);
spin_unlock(&sbi->fs_lock); spin_unlock(&sbi->fs_lock);
spin_lock(&dcache_lock); spin_lock(&dcache_lock);
...@@ -433,7 +435,7 @@ int autofs4_expire_wait(struct dentry *dentry) ...@@ -433,7 +435,7 @@ int autofs4_expire_wait(struct dentry *dentry)
DPRINTK("expire done status=%d", status); DPRINTK("expire done status=%d", status);
if (d_unhashed(dentry)) if (d_unhashed(dentry) && IS_DEADDIR(dentry->d_inode))
return -EAGAIN; return -EAGAIN;
return status; return status;
...@@ -473,6 +475,7 @@ int autofs4_expire_run(struct super_block *sb, ...@@ -473,6 +475,7 @@ int autofs4_expire_run(struct super_block *sb,
spin_lock(&sbi->fs_lock); spin_lock(&sbi->fs_lock);
ino = autofs4_dentry_ino(dentry); ino = autofs4_dentry_ino(dentry);
ino->flags &= ~AUTOFS_INF_EXPIRING; ino->flags &= ~AUTOFS_INF_EXPIRING;
autofs4_del_expiring(dentry);
complete_all(&ino->expire_complete); complete_all(&ino->expire_complete);
spin_unlock(&sbi->fs_lock); spin_unlock(&sbi->fs_lock);
...@@ -503,6 +506,7 @@ int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt, ...@@ -503,6 +506,7 @@ int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
ino->flags &= ~AUTOFS_INF_MOUNTPOINT; ino->flags &= ~AUTOFS_INF_MOUNTPOINT;
} }
ino->flags &= ~AUTOFS_INF_EXPIRING; ino->flags &= ~AUTOFS_INF_EXPIRING;
autofs4_del_expiring(dentry);
complete_all(&ino->expire_complete); complete_all(&ino->expire_complete);
spin_unlock(&sbi->fs_lock); spin_unlock(&sbi->fs_lock);
dput(dentry); dput(dentry);
......
...@@ -49,6 +49,7 @@ struct autofs_info *autofs4_init_ino(struct autofs_info *ino, ...@@ -49,6 +49,7 @@ struct autofs_info *autofs4_init_ino(struct autofs_info *ino,
ino->dentry = NULL; ino->dentry = NULL;
ino->size = 0; ino->size = 0;
INIT_LIST_HEAD(&ino->active); INIT_LIST_HEAD(&ino->active);
INIT_LIST_HEAD(&ino->rehash_list);
ino->active_count = 0; ino->active_count = 0;
INIT_LIST_HEAD(&ino->expiring); INIT_LIST_HEAD(&ino->expiring);
atomic_set(&ino->count, 0); atomic_set(&ino->count, 0);
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment