On Tue, Nov 27, 2007 at 03:10:43PM -0600, K.R. Foley wrote:
> Ruben Safir wrote:
> > Hello
> > 
> > I updated my kernel and its broken the automounter.  Does anyone know how I 
> > might
> > repair it for the USB devices, Floppy and CDROM?
> > 
> > Thanks
> > 
> > Ruben
> 
> Suse kernels of the 9.x era carried a patch for subfs. If you can get
> that to apply to your newer kernel it might work. I am attaching a copy
> that worked with a 2.6.16 kernel. Good luck.
> 
> -- 
>    kr

that's interesting.  I figured that SuSE had to make a kernel hack to make the 
automounter to 
work correctly since it just doesn't work well in standard distrobution.

Do you have a link that tells you how to add a patch like this to the kernel 
module?

Ruben

> 

> diff -uprN -X linux-2.6.16.orig/Documentation/dontdiff 
> linux-2.6.16.orig/fs/Kconfig linux-2.6.16/fs/Kconfig
> --- linux-2.6.16.orig/fs/Kconfig      2006-03-19 23:53:29.000000000 -0600
> +++ linux-2.6.16/fs/Kconfig   2006-07-25 09:08:37.000000000 -0500
> @@ -449,6 +449,12 @@ config DNOTIFY
>  
>         Because of this, if unsure, say Y.
>  
> +config SUBFS_FS
> +     tristate "subfs file system support"
> +     ---help---
> +       If you don't know whether you need it, then you don't need it:
> +       answer N.
> +
>  config AUTOFS_FS
>       tristate "Kernel automounter support"
>       help
> diff -uprN -X linux-2.6.16.orig/Documentation/dontdiff 
> linux-2.6.16.orig/fs/Makefile linux-2.6.16/fs/Makefile
> --- linux-2.6.16.orig/fs/Makefile     2006-03-19 23:53:29.000000000 -0600
> +++ linux-2.6.16/fs/Makefile  2006-07-25 09:08:37.000000000 -0500
> @@ -85,6 +85,7 @@ obj-$(CONFIG_JFFS_FS)               += jffs/
>  obj-$(CONFIG_JFFS2_FS)               += jffs2/
>  obj-$(CONFIG_AFFS_FS)                += affs/
>  obj-$(CONFIG_ROMFS_FS)               += romfs/
> +obj-$(CONFIG_SUBFS_FS)               += subfs/
>  obj-$(CONFIG_QNX4FS_FS)              += qnx4/
>  obj-$(CONFIG_AUTOFS_FS)              += autofs/
>  obj-$(CONFIG_AUTOFS4_FS)     += autofs4/
> diff -uprN -X linux-2.6.16.orig/Documentation/dontdiff 
> linux-2.6.16.orig/fs/namespace.c linux-2.6.16/fs/namespace.c
> --- linux-2.6.16.orig/fs/namespace.c  2006-03-19 23:53:29.000000000 -0600
> +++ linux-2.6.16/fs/namespace.c       2006-07-25 09:08:44.000000000 -0500
> @@ -131,6 +131,8 @@ struct vfsmount *lookup_mnt(struct vfsmo
>       return child_mnt;
>  }
>  
> +EXPORT_SYMBOL(lookup_mnt);
> +
>  static inline int check_mnt(struct vfsmount *mnt)
>  {
>       return mnt->mnt_namespace == current->namespace;
> diff -uprN -X linux-2.6.16.orig/Documentation/dontdiff 
> linux-2.6.16.orig/fs/subfs/Makefile linux-2.6.16/fs/subfs/Makefile
> --- linux-2.6.16.orig/fs/subfs/Makefile       1969-12-31 18:00:00.000000000 
> -0600
> +++ linux-2.6.16/fs/subfs/Makefile    2006-07-25 09:08:37.000000000 -0500
> @@ -0,0 +1,5 @@
> +#
> +# Makefile for the SuSE Windows XP subfs filesystem routines.
> +#
> +
> +obj-$(CONFIG_SUBFS_FS) += subfs.o
> diff -uprN -X linux-2.6.16.orig/Documentation/dontdiff 
> linux-2.6.16.orig/fs/subfs/subfs.c linux-2.6.16/fs/subfs/subfs.c
> --- linux-2.6.16.orig/fs/subfs/subfs.c        1969-12-31 18:00:00.000000000 
> -0600
> +++ linux-2.6.16/fs/subfs/subfs.c     2006-07-25 09:08:44.000000000 -0500
> @@ -0,0 +1,470 @@
> +/*
> + *  subfs.c
> + *
> + *  Copyright (C) 2003-2004 Eugene S. Weiss <[EMAIL PROTECTED]>
> + *
> + *  * Feb 25, 2005: Cleaned up code and locking
> + *                  Jeff Mahoney <[EMAIL PROTECTED]>
> + *
> + *  Distributed under the terms of the GNU General Public License version 2
> + *  or above.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/moduleparam.h>
> +#include <linux/pagemap.h>
> +#include <linux/fs.h>
> +#include <asm/atomic.h>
> +#include <asm/uaccess.h>
> +#include <linux/list.h>
> +#include <linux/mount.h>
> +#include <linux/namespace.h>
> +#include <linux/namei.h>
> +#include <linux/dcache.h>
> +#include <linux/sysfs.h>
> +#include <asm/semaphore.h>
> +#include <asm/signal.h>
> +#include <linux/signal.h>
> +#include <linux/sched.h>
> +
> +#define SUBFS_MAGIC 0x2c791058
> +#define SUBFS_VER "0.9"
> +#define SUBMOUNTD_PATH "/sbin/submountd"
> +#define ROOT_MODE 0777
> +
> +struct subfs_mount {
> +     char *device;
> +     char *options;
> +     char *req_fs;
> +        char *helper_prog;
> +     struct super_block *sb;
> +     struct semaphore sem;
> +     int procuid;
> +};
> +
> +/* Same as set_fs_pwd from namespace.c.  There's a problem with the
> + * symbol.  When it is fixed, discard this.
> + * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values.
> + * It can block. Requires the big lock held.
> + */
> +static void subfs_set_fs_pwd(struct fs_struct *fs, struct vfsmount *mnt,
> +                          struct dentry *dentry)
> +{
> +     struct dentry *old_pwd;
> +     struct vfsmount *old_pwdmnt;
> +
> +     write_lock(&fs->lock);
> +     old_pwd = fs->pwd;
> +     old_pwdmnt = fs->pwdmnt;
> +     fs->pwdmnt = mntget(mnt);
> +     fs->pwd = dget(dentry);
> +     write_unlock(&fs->lock);
> +
> +     if (old_pwd) {
> +             dput(old_pwd);
> +             mntput(old_pwdmnt);
> +     }
> +}
> +
> +
> +/* Quickly sends an ignored signal to the signal handling system. This
> + * causes the system to restart the system call when it receives the
> + * -ERESTARTSYS error.
> + */
> +static void subfs_send_signal(void)
> +{
> +     struct task_struct *task = current;
> +     int signal = SIGCONT;
> +
> +     read_lock(&tasklist_lock);
> +     spin_lock_irq(&task->sighand->siglock);
> +     sigaddset(&task->pending.signal, signal);
> +     spin_unlock_irq(&task->sighand->siglock);
> +     read_unlock(&tasklist_lock);
> +     set_tsk_thread_flag(task, TIF_SIGPENDING);
> +     return;
> +}
> +
> +
> +/* If the option "procuid" is chosen when subfs is mounted, the uid
> + * and gid numbers for the current process will  be added to the mount
> + * option line.  Hence, non-unix filesystems will be mounted with
> + * that ownership.
> + */
> +static void add_procuid(struct subfs_mount *sfs_mnt)
> +{
> +     struct task_struct *task = current;
> +
> +     char *o = kmalloc(strlen(sfs_mnt->options) + 1 + 32 + 1, GFP_KERNEL);
> +
> +     if (sfs_mnt->options[0] == '\0')
> +             sprintf(o, "uid=%d,gid=%d", task->uid, task->gid);
> +     else
> +             sprintf(o, "%s,uid=%d,gid=%d", sfs_mnt->options, task->uid, 
> task->gid);
> +
> +     kfree(sfs_mnt->options);
> +     sfs_mnt->options = o;
> +}
> +
> +
> +/* This routine calls the /sbin/submountd program to mount the
> + * appropriate filesystem on top of the subfs mount.  Returns
> + * 0 if the userspace program exited normally, or an error if
> + * it did not.
> + */
> +static int mount_real_fs(struct subfs_mount *sfs_mnt, struct vfsmount *mnt, 
> unsigned long flags)
> +{
> +     char *argv[7] =
> +         { sfs_mnt->helper_prog, NULL, NULL, NULL, NULL, NULL, NULL };
> +     char *envp[2] = { "HOME=/", NULL };
> +     char *path_buf;
> +     int result, len = 0;
> +
> +     argv[1] = sfs_mnt->device;
> +     path_buf = (char *) __get_free_page(GFP_KERNEL);
> +     if (!path_buf)
> +             return -ENOMEM;
> +     argv[2] = d_path(mnt->mnt_mountpoint, mnt->mnt_parent,
> +                         path_buf, PAGE_SIZE);
> +     argv[3] = sfs_mnt->req_fs;
> +     if (!(argv[4] = kmalloc(17, GFP_KERNEL))) {
> +             free_page((unsigned long) path_buf);
> +             return -ENOMEM; /* 64 bits on some platforms */
> +     }
> +     sprintf(argv[4], "%lx", flags);
> +     len = strlen(sfs_mnt->options);
> +     if (sfs_mnt->procuid) 
> +             add_procuid(sfs_mnt);
> +     argv[5] = sfs_mnt->options;
> +     result = call_usermodehelper(sfs_mnt->helper_prog, argv, envp, 1);
> +     free_page((unsigned long) path_buf);
> +     kfree(argv[4]);
> +     if (sfs_mnt->procuid)
> +             sfs_mnt->options[len] = '\0';
> +     return result;
> +}
> +
> +
> +/*  This routine returns a pointer to the filesystem mounted on top
> + *   of the subfs mountpoint, or an error pointer if it was unable to.
> + */
> +static struct vfsmount *get_child_mount (struct subfs_mount *sfs_mnt,
> +                                         struct vfsmount *mnt)
> +{
> +     struct vfsmount *child;
> +     int result;
> +        unsigned long flags = 0;
> +
> +        /* Lookup the child mount - if it's not mounted, mount it */
> +        child = lookup_mnt (mnt, sfs_mnt->sb->s_root);
> +        if (!child) {
> +                     flags = sfs_mnt->sb->s_flags;
> +             if (mnt->mnt_flags & MNT_NOSUID) flags |= MS_NOSUID;
> +             if (mnt->mnt_flags & MNT_NODEV) flags |= MS_NODEV;
> +             if (mnt->mnt_flags & MNT_NOEXEC) flags |= MS_NOEXEC;
> +
> +                result = mount_real_fs (sfs_mnt, mnt, flags);
> +             if (result) {
> +                     printk (KERN_ERR "subfs: unsuccessful attempt to "
> +                                "mount media (%d)\n", result);
> +                     /* Workaround for call_usermodehelper return value bug. 
> */
> +                     if(result < 0)
> +                             return ERR_PTR(result);
> +                     return ERR_PTR(-ENOMEDIUM);
> +             }
> +
> +                child = lookup_mnt (mnt, sfs_mnt->sb->s_root);
> +
> +                /* The mount did succeed (error caught directly above), but
> +                 * it was umounted already. Tell the process to retry. */
> +                if (!child) {
> +                    subfs_send_signal();
> +                    return ERR_PTR(-ERESTARTSYS);
> +                }
> +        }
> +
> +        return child;
> +}
> +
> +
> +/* Implements the lookup method for subfs.  Tries to get the child
> + * mount.  If it succeeds, it emits a signal and returns
> + * -ERESTARSYS.  If it receives an error, it passes it on to the
> + * system. It raises the semaphore in the directory inode before mounting
> + * because the mount routine also calls lookup, and hence a function is
> + * calling itself from within semaphore protected code.  Only the semaphore
> + * on the subfs pseudo-directory is effected, so this isn't deadly.
> + */
> +static struct dentry *subfs_lookup(struct inode *dir,
> +                             struct dentry *dentry, struct nameidata *nd)
> +{
> +     struct subfs_mount *sfs_mnt = dir->i_sb->s_fs_info;
> +     struct vfsmount *child;
> +
> +     /* This is ugly, but prevents a lockup during mount. */
> +     mutex_unlock(&dir->i_mutex);
> +     if (down_interruptible(&sfs_mnt->sem)) {
> +             mutex_lock(&dir->i_mutex);
> +             return ERR_PTR(-ERESTARTSYS);
> +     }
> +     child = get_child_mount(sfs_mnt, nd->mnt);
> +     up(&sfs_mnt->sem);
> +     mutex_lock(&dir->i_mutex);
> +     if (IS_ERR(child))
> +             return (void *) child;
> +     subfs_send_signal();
> +        if (nd->mnt == current->fs->pwdmnt)
> +                subfs_set_fs_pwd(current->fs, child, child->mnt_root);
> +        mntput (child);
> +     return ERR_PTR(-ERESTARTSYS);
> +}
> +
> +
> +/* Implements the open method for subfs.  Tries to get the child mount
> + * for the subfs mountpoint which is being opened.  Returns -ERESTARTSYS
> + * and emits an ignored signal to the calling process if it succeeds,
> + * or passes the error message received if it fails.
> + */
> +static int subfs_open(struct inode *inode, struct file *filp)
> +{
> +     struct subfs_mount *sfs_mnt = filp->f_dentry->d_sb->s_fs_info;
> +     struct vfsmount *child;
> +
> +     if (down_interruptible(&sfs_mnt->sem))
> +             return -ERESTARTSYS;
> +     child = get_child_mount(sfs_mnt, filp->f_vfsmnt);
> +     up(&sfs_mnt->sem);
> +     if (IS_ERR(child))
> +             return PTR_ERR(child);
> +     subfs_send_signal();
> +     if (filp->f_vfsmnt == current->fs->pwdmnt)
> +             subfs_set_fs_pwd(current->fs, child, child->mnt_root);
> +        mntput (child);
> +     return -ERESTARTSYS;
> +}
> +
> +
> +/*  Implements the statfs method so df and such will work on the mountpoint.
> + */
> +static int subfs_statfs(struct super_block *sb, struct kstatfs *buf)
> +{
> +#if 1
> +/* disable stafs, so "df" and other tools do not trigger to mount
> +   the media, which might cause error messages or hang, if the block
> +   device driver hangs */
> +     return 0;
> +#else
> +     struct subfs_mount *sfs_mnt = sb->s_fs_info;
> +     struct vfsmount *child;
> +     if (down_interruptible(&sfs_mnt->sem))
> +             return -ERESTARTSYS;
> +     child = get_child_mount(sfs_mnt);
> +     up(&sfs_mnt->sem);
> +     if (IS_ERR(child))
> +             return PTR_ERR(child);
> +     subfs_send_signal();
> +        mntput (child);
> +     return -ERESTARTSYS;
> +#endif
> +}
> +
> +static struct super_operations subfs_s_ops = {
> +     .statfs = subfs_statfs,
> +     .drop_inode = generic_delete_inode,
> +};
> +
> +
> +static struct inode_operations subfs_dir_inode_operations = {
> +     .lookup = subfs_lookup,
> +};
> +
> +
> +static struct file_operations subfs_file_ops = {
> +     .open = subfs_open,
> +};
> +
> +
> +/*  Creates the inodes for subfs superblocks.
> + */
> +static struct inode *subfs_make_inode(struct super_block *sb, int mode)
> +{
> +     struct inode *ret = new_inode(sb);
> +
> +     if (ret) {
> +             ret->i_mode = mode;
> +             ret->i_uid = ret->i_gid = 0;
> +             ret->i_blksize = PAGE_CACHE_SIZE;
> +             ret->i_blocks = 0;
> +             ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
> +             ret->i_fop = &subfs_file_ops;
> +     }
> +     return ret;
> +}
> +
> +/*  Fills the fields for the superblock created when subfs is mounted.
> + */
> +static int subfs_fill_super(struct super_block *sb, void *data, int silent)
> +{
> +     struct inode *root;
> +     struct dentry *root_dentry;
> +
> +     sb->s_blocksize = PAGE_CACHE_SIZE;
> +     sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
> +     sb->s_magic = SUBFS_MAGIC;
> +     sb->s_op = &subfs_s_ops;
> +     root = subfs_make_inode(sb, S_IFDIR|ROOT_MODE);
> +     if (!root)
> +             goto out;
> +     root->i_op = &subfs_dir_inode_operations;
> +     root_dentry = d_alloc_root(root);
> +     if (!root_dentry)
> +             goto out_iput;
> +     sb->s_root = root_dentry;
> +     return 0;
> +      out_iput:
> +     iput(root);
> +      out:
> +     return -ENOMEM;
> +}
> +
> +
> +/* Parse the options string and remove submount specific options
> + * and store the appropriate data.
> + */
> +static int proc_opts(struct subfs_mount *sfs_mnt, void *data)
> +{
> +     char *opts = data, *opt, *ptr, *fs = NULL, *prog;
> +     int len;
> +
> +     if (!opts) {
> +             if (!(data = opts = kmalloc(PAGE_SIZE, GFP_KERNEL)))
> +                     return -EINVAL;
> +             strcat(opts, "fs=auto");
> +     }
> +     len = strnlen(opts, PAGE_SIZE - 1) + 1;
> +     if (strstr(opts, "procuid"))
> +             sfs_mnt->procuid = 1;
> +     if (!(sfs_mnt->options = kmalloc(len, GFP_KERNEL)))
> +             return -ENOMEM;
> +     sfs_mnt->options[0] = '\0';
> +     while ((opt = strsep(&opts, ","))) {
> +             if ((ptr = strstr(opt, "program="))) {
> +                     if (!(prog = kmalloc((strlen(ptr) - 7), GFP_KERNEL)))
> +                             return -ENOMEM;
> +                     strcpy(prog, (ptr + 8));
> +                        kfree(sfs_mnt->helper_prog);
> +                        sfs_mnt->helper_prog = prog;
> +             }
> +             else if ((ptr = strstr(opt, "fs="))) {
> +                     if (!(fs = kmalloc((strlen(ptr) - 2), GFP_KERNEL)))
> +                             return -ENOMEM;
> +                     strcpy(fs, (ptr + 3));
> +                     sfs_mnt->req_fs = fs;
> +             }
> +             else if ((ptr = strstr(opt, "procuid"))) {
> +             } else {
> +                     strncat(sfs_mnt->options, opt, 32);
> +                     strcat(sfs_mnt->options, ",");
> +             }
> +     }
> +     if((len = strlen(sfs_mnt->options)) && (sfs_mnt->options[len-1] == ','))
> +             sfs_mnt->options[len-1] = '\0';
> +     if ( !sfs_mnt->req_fs ){
> +             if (!(sfs_mnt->req_fs = kmalloc(5, GFP_KERNEL)))
> +                     return -ENOMEM; /* 64 bits on some platforms */
> +             strcpy(sfs_mnt->req_fs, "auto" );
> +     }
> +     return 0;
> +}
> +
> +
> +/* subfs_get_super is the subfs implementation of the get_sb method on
> + * the file_system_type structure.  It should only be called in the
> + * case of a mount.  It creates a new subfs_mount structure, fills
> + * the fields of the structure, except for the mount structure, and then
> + * calls a generic get_sb function.  The superblock pointer is stored on
> + * the subfs_mount structure, and returned to the calling function.  The
> + * subfs_mount structure is pointed to by the s_fs_info field of the
> + * superblock structure.
> + */
> +static struct super_block *subfs_get_super(struct file_system_type *fst,
> +                             int flags, const char *devname, void *data)
> +{
> +     char *device;
> +     struct subfs_mount *newmount;
> +     int ret;
> +
> +     if (!(newmount = kmalloc(sizeof(struct subfs_mount), GFP_KERNEL)))
> +             return ERR_PTR(-ENOMEM);
> +     newmount->req_fs = NULL;
> +     newmount->sb = NULL;
> +     newmount->procuid = 0;
> +     sema_init(&newmount->sem, 1);
> +     if (!(device = kmalloc((strlen(devname) + 1), GFP_KERNEL)))
> +             return ERR_PTR(-ENOMEM);
> +     strcpy(device, devname);
> +     newmount->device = device;
> +        if (!(newmount->helper_prog =
> +                     kmalloc(sizeof(SUBMOUNTD_PATH), GFP_KERNEL)))
> +             return ERR_PTR(-ENOMEM);
> +     strcpy(newmount->helper_prog, SUBMOUNTD_PATH);
> +     if ((ret = proc_opts(newmount, data)))
> +             return ERR_PTR(ret);
> +     newmount->sb = get_sb_nodev(fst, flags, data, subfs_fill_super);
> +     newmount->sb->s_fs_info = newmount;
> +     return newmount->sb;
> +}
> +
> +
> +/* subfs_kill_super is the subfs implementation of the kill_sb method.
> + * It should be called only on umount.  It cleans up the appropriate
> + * subfs_mount structure and then calls a generic function to actually
> + * clean up the superblock structure.
> + */
> +static void subfs_kill_super(struct super_block *sb)
> +{
> +     struct subfs_mount *sfs_mnt = sb->s_fs_info;
> +
> +        if(sfs_mnt) {
> +             if (sfs_mnt->device)
> +                     kfree(sfs_mnt->device);
> +             if (sfs_mnt->options)
> +                     kfree(sfs_mnt->options);
> +             if (sfs_mnt->req_fs)
> +                     kfree(sfs_mnt->req_fs);
> +             if (sfs_mnt->helper_prog)
> +                     kfree(sfs_mnt->helper_prog);
> +             kfree(sfs_mnt);
> +             sb->s_fs_info = NULL;
> +     }
> +     kill_litter_super(sb);
> +     return;
> +}
> +
> +static struct file_system_type subfs_type = {
> +     .owner = THIS_MODULE,
> +     .name = "subfs",
> +     .get_sb = subfs_get_super,
> +     .kill_sb = subfs_kill_super,
> +};
> +
> +static int __init subfs_init(void)
> +{
> +     printk(KERN_INFO "subfs %s\n", SUBFS_VER);
> +     return register_filesystem(&subfs_type);
> +}
> +
> +static void __exit subfs_exit(void)
> +{
> +     printk(KERN_INFO "subfs exiting.\n");
> +     unregister_filesystem(&subfs_type);
> +}
> +
> +MODULE_DESCRIPTION("subfs virtual filesystem " SUBFS_VER );
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Eugene S. Weiss");
> +
> +module_init(subfs_init);
> +module_exit(subfs_exit);
> 


-- 
http://www.mrbrklyn.com - Interesting Stuff
http://www.nylxs.com - Leadership Development in Free Software

So many immigrant groups have swept through our town that Brooklyn, like 
Atlantis, reaches mythological proportions in the mind of the world  - RI Safir 
1998

http://fairuse.nylxs.com  DRM is THEFT - We are the STAKEHOLDERS - RI Safir 2002

"Yeah - I write Free Software...so SUE ME"

"The tremendous problem we face is that we are becoming sharecroppers to our 
own cultural heritage -- we need the ability to participate in our own society."

"> I'm an engineer. I choose the best tool for the job, politics be damned.<
You must be a stupid engineer then, because politcs and technology have been 
attached at the hip since the 1st dynasty in Ancient Egypt.  I guess you missed 
that one."

© Copyright for the Digital Millennium
-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to