Thanks,
Did you try this?
I think it has a locking problem when mounting the root filesystem, it
hangs very hard during root mount, probably too many lock kernels in
some path.
I like the idea of getting rid of the call, but it looks like it needs
a little work yet (I will dig into it).
Steve
> Hi,
>
> the lookup_vfsmnt function in the xfs tree is broken by design
> as it tries to get a struct vfsmnt for a given kdev_t but a
> filesystem can be mounted at multiple mount points in Linux 2.4
> and so the mapping is not unique.
>
> The actual usage of the function is not broken as it is used only
> to get the struct super_block from the vfsmnt which is again
> unique for a kdev_t (but doesn't have to - I know of at least one
> fs design where there might be multiple sb's for a dev).
>
> Suggestion: kill lookup_vfsmnt and use get_super instead.
> Patch attached.
>
> Christoph
>
> --
> Of course it doesn't work. We've performed a software upgrade.
>
>
> Index: fs/super.c
> ===================================================================
> RCS file: /cvs/linux-2.4-xfs/linux/fs/super.c,v
> retrieving revision 1.42
> diff -u -b -B -r1.42 super.c
> --- fs/super.c 2001/02/22 21:09:04 1.42
> +++ fs/super.c 2001/03/03 18:29:44
> @@ -456,24 +456,6 @@
> return sp - buf; /* no trailing NUL */
> }
>
> -struct vfsmount *lookup_vfsmnt(kdev_t dev)
> -{
> - struct list_head *p;
> -
> - if (list_empty(&vfsmntlist))
> - return NULL;
> -
> - for (p = vfsmntlist.next; p != &vfsmntlist; p = p->next) {
> - struct vfsmount *tmp = list_entry(p, struct vfsmount, mnt_list)
> ;
> - if (tmp->mnt_sb->s_dev == dev) {
> - return (tmp);
> - }
> - }
> -
> - return NULL;
> -}
> -
> -
> static struct proc_fs_info {
> int flag;
> char *str;
> Index: fs/xfs/linux/xfs_vfs.c
> ===================================================================
> RCS file: /cvs/linux-2.4-xfs/linux/fs/xfs/linux/xfs_vfs.c,v
> retrieving revision 1.21
> diff -u -b -B -r1.21 xfs_vfs.c
> --- fs/xfs/linux/xfs_vfs.c 2000/11/22 06:53:25 1.21
> +++ fs/xfs/linux/xfs_vfs.c 2001/03/03 18:30:20
> @@ -211,14 +211,16 @@
> long s;
> struct vfs *vfsp;
> kdev_t kdev = MKDEV(MAJOR(dev), MINOR(dev));
> - struct vfsmount *entry;
> + struct super_block *sb;
>
> lock_kernel();
> - entry = lookup_vfsmnt(kdev);
> -
> + sb = get_super(kdev);
> unlock_kernel();
> - if (entry) {
> - vfsp = LINVFS_GET_VFS(entry->mnt_sb);
> +
> + if (!sb)
> + return NULL;
> +
> + vfsp = LINVFS_GET_VFS(sb);
> again:
> spin_lock_irqsave(&vfslock, s);
> if (vfsp->vfs_dev == dev &&
> @@ -241,9 +243,6 @@
> }
> spin_unlock_irqrestore(&vfslock, s);
> return vfsp;
> - } else {
> - return NULL;
> - }
> }
>
> void
> @@ -312,14 +311,13 @@
> {
> register struct vfs *vfsp;
> kdev_t kdev = MKDEV(MAJOR(dev), MINOR(dev));
> - struct vfsmount *entry;
> + struct super_block *sb;
>
> lock_kernel();
> - entry = lookup_vfsmnt(kdev);
> -
> + sb = get_super(kdev);
>
> - if (entry) {
> - vfsp = LINVFS_GET_VFS(entry->mnt_sb);
> + if (sb) {
> + vfsp = LINVFS_GET_VFS(sb);
> if ((vfsp->vfs_dev == dev) &&
> (fstype == VFS_FSTYPE_ANY || fstype == vfsp->vfs_fstype)
> ) {
> unlock_kernel();
> Index: include/linux/mount.h
> ===================================================================
> RCS file: /cvs/linux-2.4-xfs/linux/include/linux/mount.h,v
> retrieving revision 1.12
> diff -u -b -B -r1.12 mount.h
> --- include/linux/mount.h 2000/10/23 18:56:35 1.12
> +++ include/linux/mount.h 2001/03/03 18:30:35
> @@ -38,7 +38,6 @@
> atomic_inc(&mnt->mnt_count);
> return mnt;
> }
> -struct vfsmount *lookup_vfsmnt(kdev_t dev);
>
> static inline void mntput(struct vfsmount *mnt)
> {
> Index: kernel/ksyms.c
> ===================================================================
> RCS file: /cvs/linux-2.4-xfs/linux/kernel/ksyms.c,v
> retrieving revision 1.80
> diff -u -b -B -r1.80 ksyms.c
> --- kernel/ksyms.c 2001/03/01 21:13:39 1.80
> +++ kernel/ksyms.c 2001/03/03 18:30:40
> @@ -143,7 +143,6 @@
> EXPORT_SYMBOL(get_fs_type);
> EXPORT_SYMBOL(get_super);
> EXPORT_SYMBOL(get_empty_super);
> -EXPORT_SYMBOL(lookup_vfsmnt);
> EXPORT_SYMBOL(getname);
> EXPORT_SYMBOL(names_cachep);
> EXPORT_SYMBOL(fput);
|