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 <eweiss@sbclobal.net> + * + * * Feb 25, 2005: Cleaned up code and locking + * Jeff Mahoney <jeffm@suse.com> + * + * 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: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org