From c949d4eb40ce021b1abc3b63af23aa535662cb17 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Wed, 6 Dec 2006 20:39:38 -0800 Subject: [PATCH] autofs: fix error code path in autofs_fill_sb() When kernel is compiled with old version of autofs (CONFIG_AUTOFS_FS), and new (observed at least with 5.x.x) automount deamon is started, kernel correctly reports incompatible version of kernel and userland daemon, but then screws things up instead of correct handling of the error: autofs: kernel does not match daemon version ===================================== [ BUG: bad unlock balance detected! ] ------------------------------------- automount/4199 is trying to release lock (&type->s_umount_key) at: [] get_sb_nodev+0x76/0xa4 but there are no more locks to release! other info that might help us debug this: no locks held by automount/4199. stack backtrace: [] dump_trace+0x68/0x1b2 [] show_trace_log_lvl+0x18/0x2c [] show_trace+0xf/0x11 [] dump_stack+0x12/0x14 [] print_unlock_inbalance_bug+0xe7/0xf3 [] lock_release+0x8d/0x164 [] up_write+0x14/0x27 [] get_sb_nodev+0x76/0xa4 [] vfs_kern_mount+0x83/0xf6 [] do_kern_mount+0x2d/0x3e [] do_mount+0x607/0x67a [] sys_mount+0x72/0xa4 [] sysenter_past_esp+0x5f/0x99 DWARF2 unwinder stuck at sysenter_past_esp+0x5f/0x99 Leftover inexact backtrace: ======================= and then deadlock comes. The problem: autofs_fill_super() returns EINVAL to get_sb_nodev(), but before that, it calls kill_anon_super() to destroy the superblock which won't be needed. This is however way too soon to call kill_anon_super(), because get_sb_nodev() has to perform its own cleanup of the superblock first (deactivate_super(), etc.). The correct time to call kill_anon_super() is in the autofs_kill_sb() callback, which is called by deactivate_super() at proper time, when the superblock is ready to be killed. I can see the same faulty codepath also in autofs4. This patch solves issues in both filesystems in a same way - it postpones the kill_anon_super() until the proper time is signalized by deactivate_super() calling the kill_sb() callback. [raven@themaw.net: update comment] Signed-off-by: Jiri Kosina Acked-by: Ian Kent Cc: Signed-off-by: Ian Kent Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/autofs4/inode.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'fs/autofs4') diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index ce7c0f1dd529..9c48250fd726 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c @@ -152,10 +152,11 @@ void autofs4_kill_sb(struct super_block *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. + * just call kill_anon_super when we are called from + * deactivate_super. */ if (!sbi) - return; + goto out_kill_sb; sb->s_fs_info = NULL; @@ -167,6 +168,7 @@ void autofs4_kill_sb(struct super_block *sb) kfree(sbi); +out_kill_sb: DPRINTK("shutting down"); kill_anon_super(sb); } @@ -426,7 +428,6 @@ fail_ino: fail_free: kfree(sbi); s->s_fs_info = NULL; - kill_anon_super(s); fail_unlock: return -EINVAL; } -- cgit v1.2.1 From a4669ed8ed982dab494c5d4f2b32921e5a6531d8 Mon Sep 17 00:00:00 2001 From: "Josef \"Jeff\" Sipek" Date: Fri, 8 Dec 2006 02:36:46 -0800 Subject: [PATCH] autofs4: change uses of f_{dentry, vfsmnt} to use f_path Change all the uses of f_{dentry,vfsmnt} to f_path.{dentry,mnt} in the autofs4 filesystem. Signed-off-by: Josef "Jeff" Sipek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/autofs4/autofs_i.h | 3 ++- fs/autofs4/root.c | 16 ++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) (limited to 'fs/autofs4') diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index b13f32c8aeee..216b1a364ccb 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h @@ -150,7 +150,8 @@ static inline int autofs4_ispending(struct dentry *dentry) static inline void autofs4_copy_atime(struct file *src, struct file *dst) { - dst->f_dentry->d_inode->i_atime = src->f_dentry->d_inode->i_atime; + dst->f_path.dentry->d_inode->i_atime = + src->f_path.dentry->d_inode->i_atime; return; } diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index c1493524da4d..8d05b9f7578d 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -74,7 +74,7 @@ struct inode_operations autofs4_dir_inode_operations = { static int autofs4_root_readdir(struct file *file, void *dirent, filldir_t filldir) { - struct autofs_sb_info *sbi = autofs4_sbi(file->f_dentry->d_sb); + struct autofs_sb_info *sbi = autofs4_sbi(file->f_path.dentry->d_sb); int oz_mode = autofs4_oz_mode(sbi); DPRINTK("called, filp->f_pos = %lld", file->f_pos); @@ -95,8 +95,8 @@ static int autofs4_root_readdir(struct file *file, void *dirent, static int autofs4_dir_open(struct inode *inode, struct file *file) { - struct dentry *dentry = file->f_dentry; - struct vfsmount *mnt = file->f_vfsmnt; + struct dentry *dentry = file->f_path.dentry; + struct vfsmount *mnt = file->f_path.mnt; struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); struct dentry *cursor; int status; @@ -172,7 +172,7 @@ out: static int autofs4_dir_close(struct inode *inode, struct file *file) { - struct dentry *dentry = file->f_dentry; + struct dentry *dentry = file->f_path.dentry; struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); struct dentry *cursor = file->private_data; int status = 0; @@ -204,7 +204,7 @@ out: static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldir) { - struct dentry *dentry = file->f_dentry; + struct dentry *dentry = file->f_path.dentry; struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); struct dentry *cursor = file->private_data; int status; @@ -858,14 +858,14 @@ static int autofs4_root_ioctl(struct inode *inode, struct file *filp, return autofs4_ask_reghost(sbi, p); case AUTOFS_IOC_ASKUMOUNT: - return autofs4_ask_umount(filp->f_vfsmnt, p); + return autofs4_ask_umount(filp->f_path.mnt, p); /* return a single thing to expire */ case AUTOFS_IOC_EXPIRE: - return autofs4_expire_run(inode->i_sb,filp->f_vfsmnt,sbi, p); + return autofs4_expire_run(inode->i_sb,filp->f_path.mnt,sbi, p); /* same as above, but can send multiple expires through pipe */ case AUTOFS_IOC_EXPIRE_MULTI: - return autofs4_expire_multi(inode->i_sb,filp->f_vfsmnt,sbi, p); + return autofs4_expire_multi(inode->i_sb,filp->f_path.mnt,sbi, p); default: return -ENOSYS; -- cgit v1.2.1 From 5cbded585d129d0226cb48ac4202b253c781be26 Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Wed, 13 Dec 2006 00:35:56 -0800 Subject: [PATCH] getting rid of all casts of k[cmz]alloc() calls Run this: #!/bin/sh for f in $(grep -Erl "\([^\)]*\) *k[cmz]alloc" *) ; do echo "De-casting $f..." perl -pi -e "s/ ?= ?\([^\)]*\) *(k[cmz]alloc) *\(/ = \1\(/" $f done And then go through and reinstate those cases where code is casting pointers to non-pointers. And then drop a few hunks which conflicted with outstanding work. Cc: Russell King , Ian Molton Cc: Mikael Starvik Cc: Yoshinori Sato Cc: Roman Zippel Cc: Geert Uytterhoeven Cc: Ralf Baechle Cc: Paul Mackerras Cc: Kyle McMartin Cc: Benjamin Herrenschmidt Cc: Martin Schwidefsky Cc: "David S. Miller" Cc: Jeff Dike Cc: Greg KH Cc: Jens Axboe Cc: Paul Fulghum Cc: Alan Cox Cc: Karsten Keil Cc: Mauro Carvalho Chehab Cc: Jeff Garzik Cc: James Bottomley Cc: Ian Kent Cc: Steven French Cc: David Woodhouse Cc: Neil Brown Cc: Jaroslav Kysela Cc: Takashi Iwai Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/autofs4/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/autofs4') diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index 9c48250fd726..e8f6c5ad3e90 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c @@ -313,7 +313,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) struct autofs_sb_info *sbi; struct autofs_info *ino; - sbi = (struct autofs_sb_info *) kmalloc(sizeof(*sbi), GFP_KERNEL); + sbi = kmalloc(sizeof(*sbi), GFP_KERNEL); if ( !sbi ) goto fail_unlock; DPRINTK("starting up, sbi = %p",sbi); -- cgit v1.2.1