[PATCH] autofs4: panic after mount fail
authorIan Kent <raven@themaw.net>
Tue, 14 Nov 2006 10:03:29 +0000 (02:03 -0800)
committerLinus Torvalds <torvalds@woody.osdl.org>
Tue, 14 Nov 2006 17:09:27 +0000 (09:09 -0800)
Resolve the panic on failed mount of an autofs filesystem originally
reported by Mao Bibo.

It addresses two issues that happen after the mount fail.  The first a NULL
pointer reference to a field (pipe) in the autofs superblock info structure
and second the lack of super block cleanup by the autofs and autofs4
modules.

Signed-off-by: Ian Kent <raven@themaw.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
fs/autofs/inode.c
fs/autofs/waitq.c
fs/autofs4/inode.c
fs/autofs4/waitq.c

index 54c518c..38ede5c 100644 (file)
@@ -25,6 +25,14 @@ void autofs_kill_sb(struct super_block *sb)
        struct autofs_sb_info *sbi = autofs_sbi(sb);
        unsigned int n;
 
+       /*
+        * In the event of a failure in get_sb_nodev the superblock
+        * info is not present so nothing else has been setup, so
+        * just exit when we are called from deactivate_super.
+        */
+       if (!sbi)
+               return;
+
        if ( !sbi->catatonic )
                autofs_catatonic_mode(sbi); /* Free wait queues, close pipe */
 
@@ -136,7 +144,8 @@ int autofs_fill_super(struct super_block *s, void *data, int silent)
 
        s->s_fs_info = sbi;
        sbi->magic = AUTOFS_SBI_MAGIC;
-       sbi->catatonic = 0;
+       sbi->pipe = NULL;
+       sbi->catatonic = 1;
        sbi->exp_timeout = 0;
        sbi->oz_pgrp = process_group(current);
        autofs_initialize_hash(&sbi->dirhash);
@@ -180,6 +189,7 @@ int autofs_fill_super(struct super_block *s, void *data, int silent)
        if ( !pipe->f_op || !pipe->f_op->write )
                goto fail_fput;
        sbi->pipe = pipe;
+       sbi->catatonic = 0;
 
        /*
         * Success! Install the root dentry now to indicate completion.
@@ -198,6 +208,8 @@ fail_iput:
        iput(root_inode);
 fail_free:
        kfree(sbi);
+       s->s_fs_info = NULL;
+       kill_anon_super(s);
 fail_unlock:
        return -EINVAL;
 }
index 633f628..19a9caf 100644 (file)
@@ -41,6 +41,7 @@ void autofs_catatonic_mode(struct autofs_sb_info *sbi)
                wq = nwq;
        }
        fput(sbi->pipe);        /* Close the pipe */
+       sbi->pipe = NULL;
        autofs_hash_dputall(&sbi->dirhash); /* Remove all dentry pointers */
 }
 
index 51fd859..ce7c0f1 100644 (file)
@@ -99,6 +99,9 @@ static void autofs4_force_release(struct autofs_sb_info *sbi)
        struct dentry *this_parent = sbi->sb->s_root;
        struct list_head *next;
 
+       if (!sbi->sb->s_root)
+               return;
+
        spin_lock(&dcache_lock);
 repeat:
        next = this_parent->d_subdirs.next;
@@ -146,6 +149,14 @@ void autofs4_kill_sb(struct super_block *sb)
 {
        struct autofs_sb_info *sbi = autofs4_sbi(sb);
 
+       /*
+        * In the event of a failure in get_sb_nodev the superblock
+        * info is not present so nothing else has been setup, so
+        * just exit when we are called from deactivate_super.
+        */
+       if (!sbi)
+               return;
+
        sb->s_fs_info = NULL;
 
        if ( !sbi->catatonic )
@@ -310,7 +321,8 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
        s->s_fs_info = sbi;
        sbi->magic = AUTOFS_SBI_MAGIC;
        sbi->pipefd = -1;
-       sbi->catatonic = 0;
+       sbi->pipe = NULL;
+       sbi->catatonic = 1;
        sbi->exp_timeout = 0;
        sbi->oz_pgrp = process_group(current);
        sbi->sb = s;
@@ -388,6 +400,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
                goto fail_fput;
        sbi->pipe = pipe;
        sbi->pipefd = pipefd;
+       sbi->catatonic = 0;
 
        /*
         * Success! Install the root dentry now to indicate completion.
@@ -412,6 +425,8 @@ fail_ino:
        kfree(ino);
 fail_free:
        kfree(sbi);
+       s->s_fs_info = NULL;
+       kill_anon_super(s);
 fail_unlock:
        return -EINVAL;
 }
index c0a6c8d..1e4a539 100644 (file)
@@ -41,10 +41,8 @@ void autofs4_catatonic_mode(struct autofs_sb_info *sbi)
                wake_up_interruptible(&wq->queue);
                wq = nwq;
        }
-       if (sbi->pipe) {
-               fput(sbi->pipe);        /* Close the pipe */
-               sbi->pipe = NULL;
-       }
+       fput(sbi->pipe);        /* Close the pipe */
+       sbi->pipe = NULL;
 }
 
 static int autofs4_write(struct file *file, const void *addr, int bytes)