diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-04-25 20:15:29 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-04-29 22:20:03 -0400 |
commit | fb28d58b72aa9215b26f1d5478462af394a4d253 (patch) | |
tree | 5452680dca9eab10d59d276e6b3cc53fab7a19a7 /drivers/usb/core | |
parent | 70f3c7586c708bce8f525246c8b27322edc00cc7 (diff) |
USB: remove CONFIG_USB_DEVICEFS
This option has been deprecated for many years now, and no userspace
tools use it anymore, so it should be safe to finally remove it.
Reported-by: Kay Sievers <kay@vrfy.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/core')
-rw-r--r-- | drivers/usb/core/Kconfig | 29 | ||||
-rw-r--r-- | drivers/usb/core/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/core/devio.c | 11 | ||||
-rw-r--r-- | drivers/usb/core/driver.c | 21 | ||||
-rw-r--r-- | drivers/usb/core/inode.c | 748 | ||||
-rw-r--r-- | drivers/usb/core/usb.c | 6 |
6 files changed, 2 insertions, 814 deletions
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig index 18d02e32a3d5..751031e8d8d2 100644 --- a/drivers/usb/core/Kconfig +++ b/drivers/usb/core/Kconfig | |||
@@ -27,35 +27,6 @@ config USB_ANNOUNCE_NEW_DEVICES | |||
27 | comment "Miscellaneous USB options" | 27 | comment "Miscellaneous USB options" |
28 | depends on USB | 28 | depends on USB |
29 | 29 | ||
30 | config USB_DEVICEFS | ||
31 | bool "USB device filesystem (DEPRECATED)" | ||
32 | depends on USB | ||
33 | ---help--- | ||
34 | If you say Y here (and to "/proc file system support" in the "File | ||
35 | systems" section, above), you will get a file /proc/bus/usb/devices | ||
36 | which lists the devices currently connected to your USB bus or | ||
37 | busses, and for every connected device a file named | ||
38 | "/proc/bus/usb/xxx/yyy", where xxx is the bus number and yyy the | ||
39 | device number; the latter files can be used by user space programs | ||
40 | to talk directly to the device. These files are "virtual", meaning | ||
41 | they are generated on the fly and not stored on the hard drive. | ||
42 | |||
43 | You may need to mount the usbfs file system to see the files, use | ||
44 | mount -t usbfs none /proc/bus/usb | ||
45 | |||
46 | For the format of the various /proc/bus/usb/ files, please read | ||
47 | <file:Documentation/usb/proc_usb_info.txt>. | ||
48 | |||
49 | Modern Linux systems do not use this. | ||
50 | |||
51 | Usbfs entries are files and not character devices; usbfs can't | ||
52 | handle Access Control Lists (ACL) which are the default way to | ||
53 | grant access to USB devices for untrusted users of a desktop | ||
54 | system. | ||
55 | |||
56 | The usbfs functionality is replaced by real device-nodes managed by | ||
57 | udev. These nodes lived in /dev/bus/usb and are used by libusb. | ||
58 | |||
59 | config USB_DEVICE_CLASS | 30 | config USB_DEVICE_CLASS |
60 | bool "USB device class-devices (DEPRECATED)" | 31 | bool "USB device class-devices (DEPRECATED)" |
61 | depends on USB | 32 | depends on USB |
diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile index 507a4e1b6360..c4ea846d3c02 100644 --- a/drivers/usb/core/Makefile +++ b/drivers/usb/core/Makefile | |||
@@ -9,6 +9,5 @@ usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o | |||
9 | usbcore-y += devio.o notify.o generic.o quirks.o devices.o | 9 | usbcore-y += devio.o notify.o generic.o quirks.o devices.o |
10 | 10 | ||
11 | usbcore-$(CONFIG_PCI) += hcd-pci.o | 11 | usbcore-$(CONFIG_PCI) += hcd-pci.o |
12 | usbcore-$(CONFIG_USB_DEVICEFS) += inode.o | ||
13 | 12 | ||
14 | obj-$(CONFIG_USB) += usbcore.o | 13 | obj-$(CONFIG_USB) += usbcore.o |
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 8df4b76465ac..90db6e2a573f 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c | |||
@@ -727,17 +727,6 @@ static int usbdev_open(struct inode *inode, struct file *file) | |||
727 | if (imajor(inode) == USB_DEVICE_MAJOR) | 727 | if (imajor(inode) == USB_DEVICE_MAJOR) |
728 | dev = usbdev_lookup_by_devt(inode->i_rdev); | 728 | dev = usbdev_lookup_by_devt(inode->i_rdev); |
729 | 729 | ||
730 | #ifdef CONFIG_USB_DEVICEFS | ||
731 | /* procfs file */ | ||
732 | if (!dev) { | ||
733 | dev = inode->i_private; | ||
734 | if (dev && dev->usbfs_dentry && | ||
735 | dev->usbfs_dentry->d_inode == inode) | ||
736 | usb_get_dev(dev); | ||
737 | else | ||
738 | dev = NULL; | ||
739 | } | ||
740 | #endif | ||
741 | mutex_unlock(&usbfs_mutex); | 730 | mutex_unlock(&usbfs_mutex); |
742 | 731 | ||
743 | if (!dev) | 732 | if (!dev) |
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 9a56635dc19c..112a7ae5095c 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -726,16 +726,6 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
726 | return -ENODEV; | 726 | return -ENODEV; |
727 | } | 727 | } |
728 | 728 | ||
729 | #ifdef CONFIG_USB_DEVICEFS | ||
730 | /* If this is available, userspace programs can directly read | ||
731 | * all the device descriptors we don't tell them about. Or | ||
732 | * act as usermode drivers. | ||
733 | */ | ||
734 | if (add_uevent_var(env, "DEVICE=/proc/bus/usb/%03d/%03d", | ||
735 | usb_dev->bus->busnum, usb_dev->devnum)) | ||
736 | return -ENOMEM; | ||
737 | #endif | ||
738 | |||
739 | /* per-device configurations are common */ | 729 | /* per-device configurations are common */ |
740 | if (add_uevent_var(env, "PRODUCT=%x/%x/%x", | 730 | if (add_uevent_var(env, "PRODUCT=%x/%x/%x", |
741 | le16_to_cpu(usb_dev->descriptor.idVendor), | 731 | le16_to_cpu(usb_dev->descriptor.idVendor), |
@@ -788,15 +778,13 @@ int usb_register_device_driver(struct usb_device_driver *new_udriver, | |||
788 | 778 | ||
789 | retval = driver_register(&new_udriver->drvwrap.driver); | 779 | retval = driver_register(&new_udriver->drvwrap.driver); |
790 | 780 | ||
791 | if (!retval) { | 781 | if (!retval) |
792 | pr_info("%s: registered new device driver %s\n", | 782 | pr_info("%s: registered new device driver %s\n", |
793 | usbcore_name, new_udriver->name); | 783 | usbcore_name, new_udriver->name); |
794 | usbfs_update_special(); | 784 | else |
795 | } else { | ||
796 | printk(KERN_ERR "%s: error %d registering device " | 785 | printk(KERN_ERR "%s: error %d registering device " |
797 | " driver %s\n", | 786 | " driver %s\n", |
798 | usbcore_name, retval, new_udriver->name); | 787 | usbcore_name, retval, new_udriver->name); |
799 | } | ||
800 | 788 | ||
801 | return retval; | 789 | return retval; |
802 | } | 790 | } |
@@ -815,7 +803,6 @@ void usb_deregister_device_driver(struct usb_device_driver *udriver) | |||
815 | usbcore_name, udriver->name); | 803 | usbcore_name, udriver->name); |
816 | 804 | ||
817 | driver_unregister(&udriver->drvwrap.driver); | 805 | driver_unregister(&udriver->drvwrap.driver); |
818 | usbfs_update_special(); | ||
819 | } | 806 | } |
820 | EXPORT_SYMBOL_GPL(usb_deregister_device_driver); | 807 | EXPORT_SYMBOL_GPL(usb_deregister_device_driver); |
821 | 808 | ||
@@ -856,8 +843,6 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner, | |||
856 | if (retval) | 843 | if (retval) |
857 | goto out; | 844 | goto out; |
858 | 845 | ||
859 | usbfs_update_special(); | ||
860 | |||
861 | retval = usb_create_newid_files(new_driver); | 846 | retval = usb_create_newid_files(new_driver); |
862 | if (retval) | 847 | if (retval) |
863 | goto out_newid; | 848 | goto out_newid; |
@@ -897,8 +882,6 @@ void usb_deregister(struct usb_driver *driver) | |||
897 | usb_remove_newid_files(driver); | 882 | usb_remove_newid_files(driver); |
898 | driver_unregister(&driver->drvwrap.driver); | 883 | driver_unregister(&driver->drvwrap.driver); |
899 | usb_free_dynids(driver); | 884 | usb_free_dynids(driver); |
900 | |||
901 | usbfs_update_special(); | ||
902 | } | 885 | } |
903 | EXPORT_SYMBOL_GPL(usb_deregister); | 886 | EXPORT_SYMBOL_GPL(usb_deregister); |
904 | 887 | ||
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c deleted file mode 100644 index d2b9af59cba9..000000000000 --- a/drivers/usb/core/inode.c +++ /dev/null | |||
@@ -1,748 +0,0 @@ | |||
1 | /*****************************************************************************/ | ||
2 | |||
3 | /* | ||
4 | * inode.c -- Inode/Dentry functions for the USB device file system. | ||
5 | * | ||
6 | * Copyright (C) 2000 Thomas Sailer (sailer@ife.ee.ethz.ch) | ||
7 | * Copyright (C) 2001,2002,2004 Greg Kroah-Hartman (greg@kroah.com) | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | * | ||
23 | * History: | ||
24 | * 0.1 04.01.2000 Created | ||
25 | * 0.2 10.12.2001 converted to use the vfs layer better | ||
26 | */ | ||
27 | |||
28 | /*****************************************************************************/ | ||
29 | |||
30 | #include <linux/module.h> | ||
31 | #include <linux/fs.h> | ||
32 | #include <linux/mount.h> | ||
33 | #include <linux/pagemap.h> | ||
34 | #include <linux/init.h> | ||
35 | #include <linux/proc_fs.h> | ||
36 | #include <linux/usb.h> | ||
37 | #include <linux/namei.h> | ||
38 | #include <linux/usbdevice_fs.h> | ||
39 | #include <linux/parser.h> | ||
40 | #include <linux/notifier.h> | ||
41 | #include <linux/seq_file.h> | ||
42 | #include <linux/usb/hcd.h> | ||
43 | #include <asm/byteorder.h> | ||
44 | #include "usb.h" | ||
45 | |||
46 | #define USBFS_DEFAULT_DEVMODE (S_IWUSR | S_IRUGO) | ||
47 | #define USBFS_DEFAULT_BUSMODE (S_IXUGO | S_IRUGO) | ||
48 | #define USBFS_DEFAULT_LISTMODE S_IRUGO | ||
49 | |||
50 | static const struct file_operations default_file_operations; | ||
51 | static struct vfsmount *usbfs_mount; | ||
52 | static int usbfs_mount_count; /* = 0 */ | ||
53 | |||
54 | static struct dentry *devices_usbfs_dentry; | ||
55 | static int num_buses; /* = 0 */ | ||
56 | |||
57 | static uid_t devuid; /* = 0 */ | ||
58 | static uid_t busuid; /* = 0 */ | ||
59 | static uid_t listuid; /* = 0 */ | ||
60 | static gid_t devgid; /* = 0 */ | ||
61 | static gid_t busgid; /* = 0 */ | ||
62 | static gid_t listgid; /* = 0 */ | ||
63 | static umode_t devmode = USBFS_DEFAULT_DEVMODE; | ||
64 | static umode_t busmode = USBFS_DEFAULT_BUSMODE; | ||
65 | static umode_t listmode = USBFS_DEFAULT_LISTMODE; | ||
66 | |||
67 | static int usbfs_show_options(struct seq_file *seq, struct dentry *root) | ||
68 | { | ||
69 | if (devuid != 0) | ||
70 | seq_printf(seq, ",devuid=%u", devuid); | ||
71 | if (devgid != 0) | ||
72 | seq_printf(seq, ",devgid=%u", devgid); | ||
73 | if (devmode != USBFS_DEFAULT_DEVMODE) | ||
74 | seq_printf(seq, ",devmode=%o", devmode); | ||
75 | if (busuid != 0) | ||
76 | seq_printf(seq, ",busuid=%u", busuid); | ||
77 | if (busgid != 0) | ||
78 | seq_printf(seq, ",busgid=%u", busgid); | ||
79 | if (busmode != USBFS_DEFAULT_BUSMODE) | ||
80 | seq_printf(seq, ",busmode=%o", busmode); | ||
81 | if (listuid != 0) | ||
82 | seq_printf(seq, ",listuid=%u", listuid); | ||
83 | if (listgid != 0) | ||
84 | seq_printf(seq, ",listgid=%u", listgid); | ||
85 | if (listmode != USBFS_DEFAULT_LISTMODE) | ||
86 | seq_printf(seq, ",listmode=%o", listmode); | ||
87 | |||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | enum { | ||
92 | Opt_devuid, Opt_devgid, Opt_devmode, | ||
93 | Opt_busuid, Opt_busgid, Opt_busmode, | ||
94 | Opt_listuid, Opt_listgid, Opt_listmode, | ||
95 | Opt_err, | ||
96 | }; | ||
97 | |||
98 | static const match_table_t tokens = { | ||
99 | {Opt_devuid, "devuid=%u"}, | ||
100 | {Opt_devgid, "devgid=%u"}, | ||
101 | {Opt_devmode, "devmode=%o"}, | ||
102 | {Opt_busuid, "busuid=%u"}, | ||
103 | {Opt_busgid, "busgid=%u"}, | ||
104 | {Opt_busmode, "busmode=%o"}, | ||
105 | {Opt_listuid, "listuid=%u"}, | ||
106 | {Opt_listgid, "listgid=%u"}, | ||
107 | {Opt_listmode, "listmode=%o"}, | ||
108 | {Opt_err, NULL} | ||
109 | }; | ||
110 | |||
111 | static int parse_options(struct super_block *s, char *data) | ||
112 | { | ||
113 | char *p; | ||
114 | int option; | ||
115 | |||
116 | /* (re)set to defaults. */ | ||
117 | devuid = 0; | ||
118 | busuid = 0; | ||
119 | listuid = 0; | ||
120 | devgid = 0; | ||
121 | busgid = 0; | ||
122 | listgid = 0; | ||
123 | devmode = USBFS_DEFAULT_DEVMODE; | ||
124 | busmode = USBFS_DEFAULT_BUSMODE; | ||
125 | listmode = USBFS_DEFAULT_LISTMODE; | ||
126 | |||
127 | while ((p = strsep(&data, ",")) != NULL) { | ||
128 | substring_t args[MAX_OPT_ARGS]; | ||
129 | int token; | ||
130 | if (!*p) | ||
131 | continue; | ||
132 | |||
133 | token = match_token(p, tokens, args); | ||
134 | switch (token) { | ||
135 | case Opt_devuid: | ||
136 | if (match_int(&args[0], &option)) | ||
137 | return -EINVAL; | ||
138 | devuid = option; | ||
139 | break; | ||
140 | case Opt_devgid: | ||
141 | if (match_int(&args[0], &option)) | ||
142 | return -EINVAL; | ||
143 | devgid = option; | ||
144 | break; | ||
145 | case Opt_devmode: | ||
146 | if (match_octal(&args[0], &option)) | ||
147 | return -EINVAL; | ||
148 | devmode = option & S_IRWXUGO; | ||
149 | break; | ||
150 | case Opt_busuid: | ||
151 | if (match_int(&args[0], &option)) | ||
152 | return -EINVAL; | ||
153 | busuid = option; | ||
154 | break; | ||
155 | case Opt_busgid: | ||
156 | if (match_int(&args[0], &option)) | ||
157 | return -EINVAL; | ||
158 | busgid = option; | ||
159 | break; | ||
160 | case Opt_busmode: | ||
161 | if (match_octal(&args[0], &option)) | ||
162 | return -EINVAL; | ||
163 | busmode = option & S_IRWXUGO; | ||
164 | break; | ||
165 | case Opt_listuid: | ||
166 | if (match_int(&args[0], &option)) | ||
167 | return -EINVAL; | ||
168 | listuid = option; | ||
169 | break; | ||
170 | case Opt_listgid: | ||
171 | if (match_int(&args[0], &option)) | ||
172 | return -EINVAL; | ||
173 | listgid = option; | ||
174 | break; | ||
175 | case Opt_listmode: | ||
176 | if (match_octal(&args[0], &option)) | ||
177 | return -EINVAL; | ||
178 | listmode = option & S_IRWXUGO; | ||
179 | break; | ||
180 | default: | ||
181 | printk(KERN_ERR "usbfs: unrecognised mount option " | ||
182 | "\"%s\" or missing value\n", p); | ||
183 | return -EINVAL; | ||
184 | } | ||
185 | } | ||
186 | |||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | static void update_special(struct dentry *special) | ||
191 | { | ||
192 | special->d_inode->i_uid = listuid; | ||
193 | special->d_inode->i_gid = listgid; | ||
194 | special->d_inode->i_mode = S_IFREG | listmode; | ||
195 | } | ||
196 | |||
197 | static void update_dev(struct dentry *dev) | ||
198 | { | ||
199 | dev->d_inode->i_uid = devuid; | ||
200 | dev->d_inode->i_gid = devgid; | ||
201 | dev->d_inode->i_mode = S_IFREG | devmode; | ||
202 | } | ||
203 | |||
204 | static void update_bus(struct dentry *bus) | ||
205 | { | ||
206 | struct dentry *dev = NULL; | ||
207 | |||
208 | bus->d_inode->i_uid = busuid; | ||
209 | bus->d_inode->i_gid = busgid; | ||
210 | bus->d_inode->i_mode = S_IFDIR | busmode; | ||
211 | |||
212 | mutex_lock(&bus->d_inode->i_mutex); | ||
213 | |||
214 | list_for_each_entry(dev, &bus->d_subdirs, d_u.d_child) | ||
215 | if (dev->d_inode) | ||
216 | update_dev(dev); | ||
217 | |||
218 | mutex_unlock(&bus->d_inode->i_mutex); | ||
219 | } | ||
220 | |||
221 | static void update_sb(struct super_block *sb) | ||
222 | { | ||
223 | struct dentry *root = sb->s_root; | ||
224 | struct dentry *bus = NULL; | ||
225 | |||
226 | if (!root) | ||
227 | return; | ||
228 | |||
229 | mutex_lock_nested(&root->d_inode->i_mutex, I_MUTEX_PARENT); | ||
230 | |||
231 | list_for_each_entry(bus, &root->d_subdirs, d_u.d_child) { | ||
232 | if (bus->d_inode) { | ||
233 | switch (S_IFMT & bus->d_inode->i_mode) { | ||
234 | case S_IFDIR: | ||
235 | update_bus(bus); | ||
236 | break; | ||
237 | case S_IFREG: | ||
238 | update_special(bus); | ||
239 | break; | ||
240 | default: | ||
241 | printk(KERN_WARNING "usbfs: Unknown node %s " | ||
242 | "mode %x found on remount!\n", | ||
243 | bus->d_name.name, bus->d_inode->i_mode); | ||
244 | break; | ||
245 | } | ||
246 | } | ||
247 | } | ||
248 | |||
249 | mutex_unlock(&root->d_inode->i_mutex); | ||
250 | } | ||
251 | |||
252 | static int remount(struct super_block *sb, int *flags, char *data) | ||
253 | { | ||
254 | /* If this is not a real mount, | ||
255 | * i.e. it's a simple_pin_fs from create_special_files, | ||
256 | * then ignore it. | ||
257 | */ | ||
258 | if (*flags & MS_KERNMOUNT) | ||
259 | return 0; | ||
260 | |||
261 | if (parse_options(sb, data)) { | ||
262 | printk(KERN_WARNING "usbfs: mount parameter error.\n"); | ||
263 | return -EINVAL; | ||
264 | } | ||
265 | |||
266 | if (usbfs_mount) | ||
267 | update_sb(usbfs_mount->mnt_sb); | ||
268 | |||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | static struct inode *usbfs_get_inode (struct super_block *sb, umode_t mode, dev_t dev) | ||
273 | { | ||
274 | struct inode *inode = new_inode(sb); | ||
275 | |||
276 | if (inode) { | ||
277 | inode->i_ino = get_next_ino(); | ||
278 | inode_init_owner(inode, NULL, mode); | ||
279 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | ||
280 | switch (mode & S_IFMT) { | ||
281 | default: | ||
282 | init_special_inode(inode, mode, dev); | ||
283 | break; | ||
284 | case S_IFREG: | ||
285 | inode->i_fop = &default_file_operations; | ||
286 | break; | ||
287 | case S_IFDIR: | ||
288 | inode->i_op = &simple_dir_inode_operations; | ||
289 | inode->i_fop = &simple_dir_operations; | ||
290 | |||
291 | /* directory inodes start off with i_nlink == 2 (for "." entry) */ | ||
292 | inc_nlink(inode); | ||
293 | break; | ||
294 | } | ||
295 | } | ||
296 | return inode; | ||
297 | } | ||
298 | |||
299 | /* SMP-safe */ | ||
300 | static int usbfs_mknod (struct inode *dir, struct dentry *dentry, umode_t mode, | ||
301 | dev_t dev) | ||
302 | { | ||
303 | struct inode *inode = usbfs_get_inode(dir->i_sb, mode, dev); | ||
304 | int error = -EPERM; | ||
305 | |||
306 | if (dentry->d_inode) | ||
307 | return -EEXIST; | ||
308 | |||
309 | if (inode) { | ||
310 | d_instantiate(dentry, inode); | ||
311 | dget(dentry); | ||
312 | error = 0; | ||
313 | } | ||
314 | return error; | ||
315 | } | ||
316 | |||
317 | static int usbfs_mkdir (struct inode *dir, struct dentry *dentry, umode_t mode) | ||
318 | { | ||
319 | int res; | ||
320 | |||
321 | mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR; | ||
322 | res = usbfs_mknod (dir, dentry, mode, 0); | ||
323 | if (!res) | ||
324 | inc_nlink(dir); | ||
325 | return res; | ||
326 | } | ||
327 | |||
328 | static int usbfs_create (struct inode *dir, struct dentry *dentry, umode_t mode) | ||
329 | { | ||
330 | mode = (mode & S_IALLUGO) | S_IFREG; | ||
331 | return usbfs_mknod (dir, dentry, mode, 0); | ||
332 | } | ||
333 | |||
334 | static inline int usbfs_positive (struct dentry *dentry) | ||
335 | { | ||
336 | return dentry->d_inode && !d_unhashed(dentry); | ||
337 | } | ||
338 | |||
339 | static int usbfs_empty (struct dentry *dentry) | ||
340 | { | ||
341 | struct list_head *list; | ||
342 | |||
343 | spin_lock(&dentry->d_lock); | ||
344 | list_for_each(list, &dentry->d_subdirs) { | ||
345 | struct dentry *de = list_entry(list, struct dentry, d_u.d_child); | ||
346 | |||
347 | spin_lock_nested(&de->d_lock, DENTRY_D_LOCK_NESTED); | ||
348 | if (usbfs_positive(de)) { | ||
349 | spin_unlock(&de->d_lock); | ||
350 | spin_unlock(&dentry->d_lock); | ||
351 | return 0; | ||
352 | } | ||
353 | spin_unlock(&de->d_lock); | ||
354 | } | ||
355 | spin_unlock(&dentry->d_lock); | ||
356 | return 1; | ||
357 | } | ||
358 | |||
359 | static int usbfs_unlink (struct inode *dir, struct dentry *dentry) | ||
360 | { | ||
361 | struct inode *inode = dentry->d_inode; | ||
362 | mutex_lock(&inode->i_mutex); | ||
363 | drop_nlink(dentry->d_inode); | ||
364 | dput(dentry); | ||
365 | mutex_unlock(&inode->i_mutex); | ||
366 | d_delete(dentry); | ||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | static int usbfs_rmdir(struct inode *dir, struct dentry *dentry) | ||
371 | { | ||
372 | int error = -ENOTEMPTY; | ||
373 | struct inode * inode = dentry->d_inode; | ||
374 | |||
375 | mutex_lock(&inode->i_mutex); | ||
376 | dentry_unhash(dentry); | ||
377 | if (usbfs_empty(dentry)) { | ||
378 | dont_mount(dentry); | ||
379 | drop_nlink(dentry->d_inode); | ||
380 | drop_nlink(dentry->d_inode); | ||
381 | dput(dentry); | ||
382 | inode->i_flags |= S_DEAD; | ||
383 | drop_nlink(dir); | ||
384 | error = 0; | ||
385 | } | ||
386 | mutex_unlock(&inode->i_mutex); | ||
387 | if (!error) | ||
388 | d_delete(dentry); | ||
389 | return error; | ||
390 | } | ||
391 | |||
392 | |||
393 | /* default file operations */ | ||
394 | static ssize_t default_read_file (struct file *file, char __user *buf, | ||
395 | size_t count, loff_t *ppos) | ||
396 | { | ||
397 | return 0; | ||
398 | } | ||
399 | |||
400 | static ssize_t default_write_file (struct file *file, const char __user *buf, | ||
401 | size_t count, loff_t *ppos) | ||
402 | { | ||
403 | return count; | ||
404 | } | ||
405 | |||
406 | static loff_t default_file_lseek (struct file *file, loff_t offset, int orig) | ||
407 | { | ||
408 | loff_t retval = -EINVAL; | ||
409 | |||
410 | mutex_lock(&file->f_path.dentry->d_inode->i_mutex); | ||
411 | switch(orig) { | ||
412 | case 0: | ||
413 | if (offset > 0) { | ||
414 | file->f_pos = offset; | ||
415 | retval = file->f_pos; | ||
416 | } | ||
417 | break; | ||
418 | case 1: | ||
419 | if ((offset + file->f_pos) > 0) { | ||
420 | file->f_pos += offset; | ||
421 | retval = file->f_pos; | ||
422 | } | ||
423 | break; | ||
424 | default: | ||
425 | break; | ||
426 | } | ||
427 | mutex_unlock(&file->f_path.dentry->d_inode->i_mutex); | ||
428 | return retval; | ||
429 | } | ||
430 | |||
431 | static const struct file_operations default_file_operations = { | ||
432 | .read = default_read_file, | ||
433 | .write = default_write_file, | ||
434 | .open = simple_open, | ||
435 | .llseek = default_file_lseek, | ||
436 | }; | ||
437 | |||
438 | static const struct super_operations usbfs_ops = { | ||
439 | .statfs = simple_statfs, | ||
440 | .drop_inode = generic_delete_inode, | ||
441 | .remount_fs = remount, | ||
442 | .show_options = usbfs_show_options, | ||
443 | }; | ||
444 | |||
445 | static int usbfs_fill_super(struct super_block *sb, void *data, int silent) | ||
446 | { | ||
447 | struct inode *inode; | ||
448 | |||
449 | sb->s_blocksize = PAGE_CACHE_SIZE; | ||
450 | sb->s_blocksize_bits = PAGE_CACHE_SHIFT; | ||
451 | sb->s_magic = USBDEVICE_SUPER_MAGIC; | ||
452 | sb->s_op = &usbfs_ops; | ||
453 | sb->s_time_gran = 1; | ||
454 | inode = usbfs_get_inode(sb, S_IFDIR | 0755, 0); | ||
455 | sb->s_root = d_make_root(inode); | ||
456 | if (!sb->s_root) { | ||
457 | dbg("%s: could not get root dentry!",__func__); | ||
458 | return -ENOMEM; | ||
459 | } | ||
460 | return 0; | ||
461 | } | ||
462 | |||
463 | /* | ||
464 | * fs_create_by_name - create a file, given a name | ||
465 | * @name: name of file | ||
466 | * @mode: type of file | ||
467 | * @parent: dentry of directory to create it in | ||
468 | * @dentry: resulting dentry of file | ||
469 | * | ||
470 | * This function handles both regular files and directories. | ||
471 | */ | ||
472 | static int fs_create_by_name (const char *name, umode_t mode, | ||
473 | struct dentry *parent, struct dentry **dentry) | ||
474 | { | ||
475 | int error = 0; | ||
476 | |||
477 | /* If the parent is not specified, we create it in the root. | ||
478 | * We need the root dentry to do this, which is in the super | ||
479 | * block. A pointer to that is in the struct vfsmount that we | ||
480 | * have around. | ||
481 | */ | ||
482 | if (!parent ) { | ||
483 | if (usbfs_mount) | ||
484 | parent = usbfs_mount->mnt_root; | ||
485 | } | ||
486 | |||
487 | if (!parent) { | ||
488 | dbg("Ah! can not find a parent!"); | ||
489 | return -EFAULT; | ||
490 | } | ||
491 | |||
492 | *dentry = NULL; | ||
493 | mutex_lock(&parent->d_inode->i_mutex); | ||
494 | *dentry = lookup_one_len(name, parent, strlen(name)); | ||
495 | if (!IS_ERR(*dentry)) { | ||
496 | if (S_ISDIR(mode)) | ||
497 | error = usbfs_mkdir (parent->d_inode, *dentry, mode); | ||
498 | else | ||
499 | error = usbfs_create (parent->d_inode, *dentry, mode); | ||
500 | } else | ||
501 | error = PTR_ERR(*dentry); | ||
502 | mutex_unlock(&parent->d_inode->i_mutex); | ||
503 | |||
504 | return error; | ||
505 | } | ||
506 | |||
507 | static struct dentry *fs_create_file (const char *name, umode_t mode, | ||
508 | struct dentry *parent, void *data, | ||
509 | const struct file_operations *fops, | ||
510 | uid_t uid, gid_t gid) | ||
511 | { | ||
512 | struct dentry *dentry; | ||
513 | int error; | ||
514 | |||
515 | dbg("creating file '%s'",name); | ||
516 | |||
517 | error = fs_create_by_name (name, mode, parent, &dentry); | ||
518 | if (error) { | ||
519 | dentry = NULL; | ||
520 | } else { | ||
521 | if (dentry->d_inode) { | ||
522 | if (data) | ||
523 | dentry->d_inode->i_private = data; | ||
524 | if (fops) | ||
525 | dentry->d_inode->i_fop = fops; | ||
526 | dentry->d_inode->i_uid = uid; | ||
527 | dentry->d_inode->i_gid = gid; | ||
528 | } | ||
529 | } | ||
530 | |||
531 | return dentry; | ||
532 | } | ||
533 | |||
534 | static void fs_remove_file (struct dentry *dentry) | ||
535 | { | ||
536 | struct dentry *parent = dentry->d_parent; | ||
537 | |||
538 | if (!parent || !parent->d_inode) | ||
539 | return; | ||
540 | |||
541 | mutex_lock_nested(&parent->d_inode->i_mutex, I_MUTEX_PARENT); | ||
542 | if (usbfs_positive(dentry)) { | ||
543 | if (dentry->d_inode) { | ||
544 | if (S_ISDIR(dentry->d_inode->i_mode)) | ||
545 | usbfs_rmdir(parent->d_inode, dentry); | ||
546 | else | ||
547 | usbfs_unlink(parent->d_inode, dentry); | ||
548 | dput(dentry); | ||
549 | } | ||
550 | } | ||
551 | mutex_unlock(&parent->d_inode->i_mutex); | ||
552 | } | ||
553 | |||
554 | /* --------------------------------------------------------------------- */ | ||
555 | |||
556 | static struct dentry *usb_mount(struct file_system_type *fs_type, | ||
557 | int flags, const char *dev_name, void *data) | ||
558 | { | ||
559 | return mount_single(fs_type, flags, data, usbfs_fill_super); | ||
560 | } | ||
561 | |||
562 | static struct file_system_type usb_fs_type = { | ||
563 | .owner = THIS_MODULE, | ||
564 | .name = "usbfs", | ||
565 | .mount = usb_mount, | ||
566 | .kill_sb = kill_litter_super, | ||
567 | }; | ||
568 | |||
569 | /* --------------------------------------------------------------------- */ | ||
570 | |||
571 | static int create_special_files (void) | ||
572 | { | ||
573 | struct dentry *parent; | ||
574 | int retval; | ||
575 | |||
576 | /* create the devices special file */ | ||
577 | retval = simple_pin_fs(&usb_fs_type, &usbfs_mount, &usbfs_mount_count); | ||
578 | if (retval) { | ||
579 | printk(KERN_ERR "Unable to get usbfs mount\n"); | ||
580 | goto exit; | ||
581 | } | ||
582 | |||
583 | parent = usbfs_mount->mnt_root; | ||
584 | devices_usbfs_dentry = fs_create_file ("devices", | ||
585 | listmode | S_IFREG, parent, | ||
586 | NULL, &usbfs_devices_fops, | ||
587 | listuid, listgid); | ||
588 | if (devices_usbfs_dentry == NULL) { | ||
589 | printk(KERN_ERR "Unable to create devices usbfs file\n"); | ||
590 | retval = -ENODEV; | ||
591 | goto error_clean_mounts; | ||
592 | } | ||
593 | |||
594 | goto exit; | ||
595 | |||
596 | error_clean_mounts: | ||
597 | simple_release_fs(&usbfs_mount, &usbfs_mount_count); | ||
598 | exit: | ||
599 | return retval; | ||
600 | } | ||
601 | |||
602 | static void remove_special_files (void) | ||
603 | { | ||
604 | if (devices_usbfs_dentry) | ||
605 | fs_remove_file (devices_usbfs_dentry); | ||
606 | devices_usbfs_dentry = NULL; | ||
607 | simple_release_fs(&usbfs_mount, &usbfs_mount_count); | ||
608 | } | ||
609 | |||
610 | void usbfs_update_special (void) | ||
611 | { | ||
612 | struct inode *inode; | ||
613 | |||
614 | if (devices_usbfs_dentry) { | ||
615 | inode = devices_usbfs_dentry->d_inode; | ||
616 | if (inode) | ||
617 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | ||
618 | } | ||
619 | } | ||
620 | |||
621 | static void usbfs_add_bus(struct usb_bus *bus) | ||
622 | { | ||
623 | struct dentry *parent; | ||
624 | char name[8]; | ||
625 | int retval; | ||
626 | |||
627 | /* create the special files if this is the first bus added */ | ||
628 | if (num_buses == 0) { | ||
629 | retval = create_special_files(); | ||
630 | if (retval) | ||
631 | return; | ||
632 | } | ||
633 | ++num_buses; | ||
634 | |||
635 | sprintf (name, "%03d", bus->busnum); | ||
636 | |||
637 | parent = usbfs_mount->mnt_root; | ||
638 | bus->usbfs_dentry = fs_create_file (name, busmode | S_IFDIR, parent, | ||
639 | bus, NULL, busuid, busgid); | ||
640 | if (bus->usbfs_dentry == NULL) { | ||
641 | printk(KERN_ERR "Error creating usbfs bus entry\n"); | ||
642 | return; | ||
643 | } | ||
644 | } | ||
645 | |||
646 | static void usbfs_remove_bus(struct usb_bus *bus) | ||
647 | { | ||
648 | if (bus->usbfs_dentry) { | ||
649 | fs_remove_file (bus->usbfs_dentry); | ||
650 | bus->usbfs_dentry = NULL; | ||
651 | } | ||
652 | |||
653 | --num_buses; | ||
654 | if (num_buses <= 0) { | ||
655 | remove_special_files(); | ||
656 | num_buses = 0; | ||
657 | } | ||
658 | } | ||
659 | |||
660 | static void usbfs_add_device(struct usb_device *dev) | ||
661 | { | ||
662 | char name[8]; | ||
663 | int i; | ||
664 | int i_size; | ||
665 | |||
666 | sprintf (name, "%03d", dev->devnum); | ||
667 | dev->usbfs_dentry = fs_create_file (name, devmode | S_IFREG, | ||
668 | dev->bus->usbfs_dentry, dev, | ||
669 | &usbdev_file_operations, | ||
670 | devuid, devgid); | ||
671 | if (dev->usbfs_dentry == NULL) { | ||
672 | printk(KERN_ERR "Error creating usbfs device entry\n"); | ||
673 | return; | ||
674 | } | ||
675 | |||
676 | /* Set the size of the device's file to be | ||
677 | * equal to the size of the device descriptors. */ | ||
678 | i_size = sizeof (struct usb_device_descriptor); | ||
679 | for (i = 0; i < dev->descriptor.bNumConfigurations; ++i) { | ||
680 | struct usb_config_descriptor *config = | ||
681 | (struct usb_config_descriptor *)dev->rawdescriptors[i]; | ||
682 | i_size += le16_to_cpu(config->wTotalLength); | ||
683 | } | ||
684 | if (dev->usbfs_dentry->d_inode) | ||
685 | dev->usbfs_dentry->d_inode->i_size = i_size; | ||
686 | } | ||
687 | |||
688 | static void usbfs_remove_device(struct usb_device *dev) | ||
689 | { | ||
690 | if (dev->usbfs_dentry) { | ||
691 | fs_remove_file (dev->usbfs_dentry); | ||
692 | dev->usbfs_dentry = NULL; | ||
693 | } | ||
694 | } | ||
695 | |||
696 | static int usbfs_notify(struct notifier_block *self, unsigned long action, void *dev) | ||
697 | { | ||
698 | switch (action) { | ||
699 | case USB_DEVICE_ADD: | ||
700 | usbfs_add_device(dev); | ||
701 | break; | ||
702 | case USB_DEVICE_REMOVE: | ||
703 | usbfs_remove_device(dev); | ||
704 | break; | ||
705 | case USB_BUS_ADD: | ||
706 | usbfs_add_bus(dev); | ||
707 | break; | ||
708 | case USB_BUS_REMOVE: | ||
709 | usbfs_remove_bus(dev); | ||
710 | } | ||
711 | |||
712 | usbfs_update_special(); | ||
713 | usbfs_conn_disc_event(); | ||
714 | return NOTIFY_OK; | ||
715 | } | ||
716 | |||
717 | static struct notifier_block usbfs_nb = { | ||
718 | .notifier_call = usbfs_notify, | ||
719 | }; | ||
720 | |||
721 | /* --------------------------------------------------------------------- */ | ||
722 | |||
723 | static struct proc_dir_entry *usbdir = NULL; | ||
724 | |||
725 | int __init usbfs_init(void) | ||
726 | { | ||
727 | int retval; | ||
728 | |||
729 | retval = register_filesystem(&usb_fs_type); | ||
730 | if (retval) | ||
731 | return retval; | ||
732 | |||
733 | usb_register_notify(&usbfs_nb); | ||
734 | |||
735 | /* create mount point for usbfs */ | ||
736 | usbdir = proc_mkdir("bus/usb", NULL); | ||
737 | |||
738 | return 0; | ||
739 | } | ||
740 | |||
741 | void usbfs_cleanup(void) | ||
742 | { | ||
743 | usb_unregister_notify(&usbfs_nb); | ||
744 | unregister_filesystem(&usb_fs_type); | ||
745 | if (usbdir) | ||
746 | remove_proc_entry("bus/usb", NULL); | ||
747 | } | ||
748 | |||
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index c74ba7bbc748..0ce862bfdd77 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c | |||
@@ -1030,9 +1030,6 @@ static int __init usb_init(void) | |||
1030 | retval = usb_devio_init(); | 1030 | retval = usb_devio_init(); |
1031 | if (retval) | 1031 | if (retval) |
1032 | goto usb_devio_init_failed; | 1032 | goto usb_devio_init_failed; |
1033 | retval = usbfs_init(); | ||
1034 | if (retval) | ||
1035 | goto fs_init_failed; | ||
1036 | retval = usb_hub_init(); | 1033 | retval = usb_hub_init(); |
1037 | if (retval) | 1034 | if (retval) |
1038 | goto hub_init_failed; | 1035 | goto hub_init_failed; |
@@ -1042,8 +1039,6 @@ static int __init usb_init(void) | |||
1042 | 1039 | ||
1043 | usb_hub_cleanup(); | 1040 | usb_hub_cleanup(); |
1044 | hub_init_failed: | 1041 | hub_init_failed: |
1045 | usbfs_cleanup(); | ||
1046 | fs_init_failed: | ||
1047 | usb_devio_cleanup(); | 1042 | usb_devio_cleanup(); |
1048 | usb_devio_init_failed: | 1043 | usb_devio_init_failed: |
1049 | usb_deregister(&usbfs_driver); | 1044 | usb_deregister(&usbfs_driver); |
@@ -1070,7 +1065,6 @@ static void __exit usb_exit(void) | |||
1070 | 1065 | ||
1071 | usb_deregister_device_driver(&usb_generic_driver); | 1066 | usb_deregister_device_driver(&usb_generic_driver); |
1072 | usb_major_cleanup(); | 1067 | usb_major_cleanup(); |
1073 | usbfs_cleanup(); | ||
1074 | usb_deregister(&usbfs_driver); | 1068 | usb_deregister(&usbfs_driver); |
1075 | usb_devio_cleanup(); | 1069 | usb_devio_cleanup(); |
1076 | usb_hub_cleanup(); | 1070 | usb_hub_cleanup(); |