G'day, The attached patch fixes a bug in the VFS code which causes "Busy inodes after unmount" and a subsequent oops.
Greg. -- Greg Banks, R&D Software Engineer, SGI Australian Software Group. I don't speak for SGI.
Following an absolute symlink opens a window during which the filesystem containing the symlink has an outstanding dentry count and no outstanding vfsmount count. A umount() of the filesystem can (incorrectly) proceed, resulting in the "Busy inodes after unmount" message and an oops shortly thereafter. Systems using autofs-controlled NFS mounts are especially vulnerable, as autofs both increases the number of unmounts happening and does NFS mounting in response to lookups which can result in multiple-second vulnerability windows. However the bug could happen on any filesystem. This patch adds a mntget()/mntput() pair around the link following code (as the 2.6 code does). Attempts to umount() during link following now return EBUSY. Signed-off-by: Greg Banks <[EMAIL PROTECTED]> --- linux/linux/fs/namei.c | 7 +++++++ 1 files changed, 7 insertions(+) --- a/linux/linux/fs/namei.c 2005-03-21 12:53:48 +11:00 +++ b/linux/linux/fs/namei.c 2005-03-21 12:16:46 +11:00 @@ -541,8 +541,10 @@ goto out_dput; if (inode->i_op->follow_link) { + struct vfsmount *mnt = mntget(nd->mnt); err = do_follow_link(dentry, nd); dput(dentry); + mntput(mnt); if (err) goto return_err; err = -ENOENT; @@ -596,8 +598,10 @@ inode = dentry->d_inode; if ((lookup_flags & LOOKUP_FOLLOW) && inode && inode->i_op && inode->i_op->follow_link) { + struct vfsmount *mnt = mntget(nd->mnt); err = do_follow_link(dentry, nd); dput(dentry); + mntput(mnt); if (err) goto return_err; inode = nd->dentry->d_inode; @@ -1002,6 +1006,7 @@ int acc_mode, error = 0; struct inode *inode; struct dentry *dentry; + struct vfsmount *mnt; struct dentry *dir; int count = 0; @@ -1185,8 +1190,10 @@ * are done. Procfs-like symlinks just set LAST_BIND. */ UPDATE_ATIME(dentry->d_inode); + mnt = mntget(nd->mnt); error = dentry->d_inode->i_op->follow_link(dentry, nd); dput(dentry); + mntput(mnt); if (error) return error; if (nd->last_type == LAST_BIND) {