Here is a patch which makes usbdevfs use the mount options. The problem was, the options were being parsed at super_block read-time; for a non-single fs, a new super_block is created every mount, thus the super_block read was happening every mount and the options got parsed and used. But with a FS_SINGLE, the super_block is only read at kern_mount() time, which is usbdevfs_init(). Subsequent mounts are now actually 'remounts' and unless remount_fs() is defined the options are ignored. This implements remount_fs(), which does nothing more than parse the options and reset all inode's values. The option parsing is moved out of the usbdevfs_read_super() into its own function. I noticed that fs/super.c, get_sb_single() calls do_remount_sb() but doesn't care if it succeeds or fails. Is this a bug? Anyway here's the patch, against 2.4.4. diff -ur 2.4.4-clean/drivers/usb/inode.c linux/drivers/usb/inode.c --- 2.4.4-clean/drivers/usb/inode.c Fri Mar 2 16:47:21 2001 +++ linux/drivers/usb/inode.c Mon May 21 15:44:36 2001 @@ -43,6 +43,11 @@ /* --------------------------------------------------------------------- */ +/* + * This list of superblocks is still used, + * but since usbdevfs became FS_SINGLE + * there is only one super_block. + */ static LIST_HEAD(superlist); struct special { @@ -159,6 +164,97 @@ iput(inode); } +static int parse_options(struct super_block *s, char *data) +{ + uid_t devuid = 0, busuid = 0, listuid = 0; + gid_t devgid = 0, busgid = 0, listgid = 0; + umode_t devmode = S_IWUSR | S_IRUGO, busmode = S_IXUGO | S_IRUGO, listmode = +S_IRUGO; + char *curopt = NULL, *value; + + /* parse options */ + if (data) + curopt = strtok(data, ","); + for (; curopt; curopt = strtok(NULL, ",")) { + if ((value = strchr(curopt, '=')) != NULL) + *value++ = 0; + if (!strcmp(curopt, "devuid")) { + if (!value || !value[0]) + return -EINVAL; + devuid = simple_strtoul(value, &value, 0); + if (*value) + return -EINVAL; + } + if (!strcmp(curopt, "devgid")) { + if (!value || !value[0]) + return -EINVAL; + devgid = simple_strtoul(value, &value, 0); + if (*value) + return -EINVAL; + } + if (!strcmp(curopt, "devmode")) { + if (!value || !value[0]) + return -EINVAL; + devmode = simple_strtoul(value, &value, 0) & S_IRWXUGO; + if (*value) + return -EINVAL; + } + if (!strcmp(curopt, "busuid")) { + if (!value || !value[0]) + return -EINVAL; + busuid = simple_strtoul(value, &value, 0); + if (*value) + return -EINVAL; + } + if (!strcmp(curopt, "busgid")) { + if (!value || !value[0]) + return -EINVAL; + busgid = simple_strtoul(value, &value, 0); + if (*value) + return -EINVAL; + } + if (!strcmp(curopt, "busmode")) { + if (!value || !value[0]) + return -EINVAL; + busmode = simple_strtoul(value, &value, 0) & S_IRWXUGO; + if (*value) + return -EINVAL; + } + if (!strcmp(curopt, "listuid")) { + if (!value || !value[0]) + return -EINVAL; + listuid = simple_strtoul(value, &value, 0); + if (*value) + return -EINVAL; + } + if (!strcmp(curopt, "listgid")) { + if (!value || !value[0]) + return -EINVAL; + listgid = simple_strtoul(value, &value, 0); + if (*value) + return -EINVAL; + } + if (!strcmp(curopt, "listmode")) { + if (!value || !value[0]) + return -EINVAL; + listmode = simple_strtoul(value, &value, 0) & S_IRWXUGO; + if (*value) + return -EINVAL; + } + } + + s->u.usbdevfs_sb.devuid = devuid; + s->u.usbdevfs_sb.devgid = devgid; + s->u.usbdevfs_sb.devmode = devmode; + s->u.usbdevfs_sb.busuid = busuid; + s->u.usbdevfs_sb.busgid = busgid; + s->u.usbdevfs_sb.busmode = busmode; + s->u.usbdevfs_sb.listuid = listuid; + s->u.usbdevfs_sb.listgid = listgid; + s->u.usbdevfs_sb.listmode = listmode; + + return 0; +} + static struct usb_bus *usbdevfs_findbus(int busnr) { struct list_head *list; @@ -460,10 +556,47 @@ return 0; } +static int usbdevfs_remount(struct super_block *s, int *flags, char *data) +{ + struct list_head *ilist = s->u.usbdevfs_sb.ilist.next; + struct inode *inode; + int ret; + + if ((ret = parse_options(s, data))) { + printk(KERN_WARNING "usbdevfs: remount parameter error\n"); + return ret; + } + + for (; ilist != &s->u.usbdevfs_sb.ilist; ilist = ilist->next) { + inode = list_entry(ilist, struct inode, u.usbdev_i.slist); + + switch (ITYPE(inode->i_ino)) { + case ISPECIAL : + inode->i_uid = s->u.usbdevfs_sb.listuid; + inode->i_gid = s->u.usbdevfs_sb.listgid; + inode->i_mode = s->u.usbdevfs_sb.listmode | S_IFREG; + break; + case IBUS : + inode->i_uid = s->u.usbdevfs_sb.busuid; + inode->i_gid = s->u.usbdevfs_sb.busgid; + inode->i_mode = s->u.usbdevfs_sb.busmode | S_IFDIR; + break; + case IDEVICE : + inode->i_uid = s->u.usbdevfs_sb.devuid; + inode->i_gid = s->u.usbdevfs_sb.devgid; + inode->i_mode = s->u.usbdevfs_sb.devmode | S_IFREG; + break; + } + } + + return 0; +} + static struct super_operations usbdevfs_sops = { read_inode: usbdevfs_read_inode, put_super: usbdevfs_put_super, statfs: usbdevfs_statfs, + remount_fs: usbdevfs_remount, }; struct super_block *usbdevfs_read_super(struct super_block *s, void *data, int silent) @@ -472,81 +605,12 @@ struct list_head *blist; struct usb_bus *bus; unsigned int i; - uid_t devuid = 0, busuid = 0, listuid = 0; - gid_t devgid = 0, busgid = 0, listgid = 0; - umode_t devmode = S_IWUSR | S_IRUGO, busmode = S_IXUGO | S_IRUGO, listmode = S_IRUGO; - char *curopt = NULL, *value; - /* parse options */ - if (data) - curopt = strtok(data, ","); - for (; curopt; curopt = strtok(NULL, ",")) { - if ((value = strchr(curopt, '=')) != NULL) - *value++ = 0; - if (!strcmp(curopt, "devuid")) { - if (!value || !value[0]) - goto opterr; - devuid = simple_strtoul(value, &value, 0); - if (*value) - goto opterr; - } - if (!strcmp(curopt, "devgid")) { - if (!value || !value[0]) - goto opterr; - devgid = simple_strtoul(value, &value, 0); - if (*value) - goto opterr; - } - if (!strcmp(curopt, "devmode")) { - if (!value || !value[0]) - goto opterr; - devmode = simple_strtoul(value, &value, 0) & S_IRWXUGO; - if (*value) - goto opterr; - } - if (!strcmp(curopt, "busuid")) { - if (!value || !value[0]) - goto opterr; - busuid = simple_strtoul(value, &value, 0); - if (*value) - goto opterr; - } - if (!strcmp(curopt, "busgid")) { - if (!value || !value[0]) - goto opterr; - busgid = simple_strtoul(value, &value, 0); - if (*value) - goto opterr; - } - if (!strcmp(curopt, "busmode")) { - if (!value || !value[0]) - goto opterr; - busmode = simple_strtoul(value, &value, 0) & S_IRWXUGO; - if (*value) - goto opterr; - } - if (!strcmp(curopt, "listuid")) { - if (!value || !value[0]) - goto opterr; - listuid = simple_strtoul(value, &value, 0); - if (*value) - goto opterr; - } - if (!strcmp(curopt, "listgid")) { - if (!value || !value[0]) - goto opterr; - listgid = simple_strtoul(value, &value, 0); - if (*value) - goto opterr; - } - if (!strcmp(curopt, "listmode")) { - if (!value || !value[0]) - goto opterr; - listmode = simple_strtoul(value, &value, 0) & S_IRWXUGO; - if (*value) - goto opterr; - } + if (parse_options(s, data)) { + printk(KERN_WARNING "usbdevfs: mount parameter error\n"); + return NULL; } + /* fill superblock */ s->s_blocksize = 1024; s->s_blocksize_bits = 10; @@ -554,12 +618,6 @@ s->s_op = &usbdevfs_sops; INIT_LIST_HEAD(&s->u.usbdevfs_sb.slist); INIT_LIST_HEAD(&s->u.usbdevfs_sb.ilist); - s->u.usbdevfs_sb.devuid = devuid; - s->u.usbdevfs_sb.devgid = devgid; - s->u.usbdevfs_sb.devmode = devmode; - s->u.usbdevfs_sb.busuid = busuid; - s->u.usbdevfs_sb.busgid = busgid; - s->u.usbdevfs_sb.busmode = busmode; root_inode = iget(s, IROOT); if (!root_inode) goto out_no_root; @@ -570,9 +628,9 @@ for (i = 0; i < NRSPECIAL; i++) { if (!(inode = iget(s, IROOT+1+i))) continue; - inode->i_uid = listuid; - inode->i_gid = listgid; - inode->i_mode = listmode | S_IFREG; + inode->i_uid = s->u.usbdevfs_sb.listuid; + inode->i_gid = s->u.usbdevfs_sb.listgid; + inode->i_mode = s->u.usbdevfs_sb.listmode | S_IFREG; special[i].inode = inode; list_add_tail(&inode->u.usbdev_i.slist, &s->u.usbdevfs_sb.ilist); list_add_tail(&inode->u.usbdev_i.dlist, &special[i].inodes); @@ -590,10 +648,6 @@ printk("usbdevfs_read_super: get root inode failed\n"); iput(root_inode); return NULL; - - opterr: - printk(KERN_WARNING "usbdevfs: mount parameter error\n"); - return NULL; } static DECLARE_FSTYPE(usbdevice_fs_type, "usbdevfs", usbdevfs_read_super, FS_SINGLE); diff -ur 2.4.4-clean/include/linux/usbdev_fs_sb.h linux/include/linux/usbdev_fs_sb.h --- 2.4.4-clean/include/linux/usbdev_fs_sb.h Mon Jan 10 14:32:48 2000 +++ linux/include/linux/usbdev_fs_sb.h Mon May 21 03:23:31 2001 @@ -7,4 +7,7 @@ uid_t busuid; gid_t busgid; umode_t busmode; + uid_t listuid; + gid_t listgid; + umode_t listmode; }; _______________________________________________ [EMAIL PROTECTED] To unsubscribe, use the last form field at: http://lists.sourceforge.net/lists/listinfo/linux-usb-devel