diff options
| author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-12 16:40:20 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-12 16:40:20 -0400 |
| commit | dc690d8ef842b464f1c429a376ca16cb8dbee6ae (patch) | |
| tree | 77955849af5a15755f5e55e24ae4b9c520583a72 | |
| parent | 57399ec9077a4b962b81037aaa279fab52f5e989 (diff) | |
| parent | 91a6902958f052358899f58683d44e36228d85c2 (diff) | |
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6: (61 commits)
sysfs: add parameter "struct bin_attribute *" in .read/.write methods for sysfs binary attributes
sysfs: make directory dentries and inodes reclaimable
sysfs: implement sysfs_get_dentry()
sysfs: move sysfs_drop_dentry() to dir.c and make it static
sysfs: restructure add/remove paths and fix inode update
sysfs: use sysfs_mutex to protect the sysfs_dirent tree
sysfs: consolidate sysfs spinlocks
sysfs: make kobj point to sysfs_dirent instead of dentry
sysfs: implement sysfs_find_dirent() and sysfs_get_dirent()
sysfs: implement SYSFS_FLAG_REMOVED flag
sysfs: rename sysfs_dirent->s_type to s_flags and make room for flags
sysfs: make sysfs_drop_dentry() access inodes using ilookup()
sysfs: Fix oops in sysfs_drop_dentry on x86_64
sysfs: use singly-linked list for sysfs_dirent tree
sysfs: slim down sysfs_dirent->s_active
sysfs: move s_active functions to fs/sysfs/dir.c
sysfs: fix root sysfs_dirent -> root dentry association
sysfs: use iget_locked() instead of new_inode()
sysfs: reorganize sysfs_new_indoe() and sysfs_create()
sysfs: fix parent refcounting during rename and move
...
93 files changed, 2822 insertions, 1494 deletions
diff --git a/Documentation/firmware_class/firmware_sample_firmware_class.c b/Documentation/firmware_class/firmware_sample_firmware_class.c index 4994f1f28f8c..fba943aacf93 100644 --- a/Documentation/firmware_class/firmware_sample_firmware_class.c +++ b/Documentation/firmware_class/firmware_sample_firmware_class.c | |||
| @@ -78,6 +78,7 @@ static CLASS_DEVICE_ATTR(loading, 0644, | |||
| 78 | firmware_loading_show, firmware_loading_store); | 78 | firmware_loading_show, firmware_loading_store); |
| 79 | 79 | ||
| 80 | static ssize_t firmware_data_read(struct kobject *kobj, | 80 | static ssize_t firmware_data_read(struct kobject *kobj, |
| 81 | struct bin_attribute *bin_attr, | ||
| 81 | char *buffer, loff_t offset, size_t count) | 82 | char *buffer, loff_t offset, size_t count) |
| 82 | { | 83 | { |
| 83 | struct class_device *class_dev = to_class_dev(kobj); | 84 | struct class_device *class_dev = to_class_dev(kobj); |
| @@ -88,6 +89,7 @@ static ssize_t firmware_data_read(struct kobject *kobj, | |||
| 88 | return count; | 89 | return count; |
| 89 | } | 90 | } |
| 90 | static ssize_t firmware_data_write(struct kobject *kobj, | 91 | static ssize_t firmware_data_write(struct kobject *kobj, |
| 92 | struct bin_attribute *bin_attr, | ||
| 91 | char *buffer, loff_t offset, size_t count) | 93 | char *buffer, loff_t offset, size_t count) |
| 92 | { | 94 | { |
| 93 | struct class_device *class_dev = to_class_dev(kobj); | 95 | struct class_device *class_dev = to_class_dev(kobj); |
diff --git a/Documentation/sysfs-rules.txt b/Documentation/sysfs-rules.txt new file mode 100644 index 000000000000..42861bb0bc9b --- /dev/null +++ b/Documentation/sysfs-rules.txt | |||
| @@ -0,0 +1,166 @@ | |||
| 1 | Rules on how to access information in the Linux kernel sysfs | ||
| 2 | |||
| 3 | The kernel exported sysfs exports internal kernel implementation-details | ||
| 4 | and depends on internal kernel structures and layout. It is agreed upon | ||
| 5 | by the kernel developers that the Linux kernel does not provide a stable | ||
| 6 | internal API. As sysfs is a direct export of kernel internal | ||
| 7 | structures, the sysfs interface can not provide a stable interface eighter, | ||
| 8 | it may always change along with internal kernel changes. | ||
| 9 | |||
| 10 | To minimize the risk of breaking users of sysfs, which are in most cases | ||
| 11 | low-level userspace applications, with a new kernel release, the users | ||
| 12 | of sysfs must follow some rules to use an as abstract-as-possible way to | ||
| 13 | access this filesystem. The current udev and HAL programs already | ||
| 14 | implement this and users are encouraged to plug, if possible, into the | ||
| 15 | abstractions these programs provide instead of accessing sysfs | ||
| 16 | directly. | ||
| 17 | |||
| 18 | But if you really do want or need to access sysfs directly, please follow | ||
| 19 | the following rules and then your programs should work with future | ||
| 20 | versions of the sysfs interface. | ||
| 21 | |||
| 22 | - Do not use libsysfs | ||
| 23 | It makes assumptions about sysfs which are not true. Its API does not | ||
| 24 | offer any abstraction, it exposes all the kernel driver-core | ||
| 25 | implementation details in its own API. Therefore it is not better than | ||
| 26 | reading directories and opening the files yourself. | ||
| 27 | Also, it is not actively maintained, in the sense of reflecting the | ||
| 28 | current kernel-development. The goal of providing a stable interface | ||
| 29 | to sysfs has failed, it causes more problems, than it solves. It | ||
| 30 | violates many of the rules in this document. | ||
| 31 | |||
| 32 | - sysfs is always at /sys | ||
| 33 | Parsing /proc/mounts is a waste of time. Other mount points are a | ||
| 34 | system configuration bug you should not try to solve. For test cases, | ||
| 35 | possibly support a SYSFS_PATH environment variable to overwrite the | ||
| 36 | applications behavior, but never try to search for sysfs. Never try | ||
| 37 | to mount it, if you are not an early boot script. | ||
| 38 | |||
| 39 | - devices are only "devices" | ||
| 40 | There is no such thing like class-, bus-, physical devices, | ||
| 41 | interfaces, and such that you can rely on in userspace. Everything is | ||
| 42 | just simply a "device". Class-, bus-, physical, ... types are just | ||
| 43 | kernel implementation details, which should not be expected by | ||
| 44 | applications that look for devices in sysfs. | ||
| 45 | |||
| 46 | The properties of a device are: | ||
| 47 | o devpath (/devices/pci0000:00/0000:00:1d.1/usb2/2-2/2-2:1.0) | ||
| 48 | - identical to the DEVPATH value in the event sent from the kernel | ||
| 49 | at device creation and removal | ||
| 50 | - the unique key to the device at that point in time | ||
| 51 | - the kernels path to the device-directory without the leading | ||
| 52 | /sys, and always starting with with a slash | ||
| 53 | - all elements of a devpath must be real directories. Symlinks | ||
| 54 | pointing to /sys/devices must always be resolved to their real | ||
| 55 | target, and the target path must be used to access the device. | ||
| 56 | That way the devpath to the device matches the devpath of the | ||
| 57 | kernel used at event time. | ||
| 58 | - using or exposing symlink values as elements in a devpath string | ||
| 59 | is a bug in the application | ||
| 60 | |||
| 61 | o kernel name (sda, tty, 0000:00:1f.2, ...) | ||
| 62 | - a directory name, identical to the last element of the devpath | ||
| 63 | - applications need to handle spaces and characters like '!' in | ||
| 64 | the name | ||
| 65 | |||
| 66 | o subsystem (block, tty, pci, ...) | ||
| 67 | - simple string, never a path or a link | ||
| 68 | - retrieved by reading the "subsystem"-link and using only the | ||
| 69 | last element of the target path | ||
| 70 | |||
| 71 | o driver (tg3, ata_piix, uhci_hcd) | ||
| 72 | - a simple string, which may contain spaces, never a path or a | ||
| 73 | link | ||
| 74 | - it is retrieved by reading the "driver"-link and using only the | ||
| 75 | last element of the target path | ||
| 76 | - devices which do not have "driver"-link, just do not have a | ||
| 77 | driver; copying the driver value in a child device context, is a | ||
| 78 | bug in the application | ||
| 79 | |||
| 80 | o attributes | ||
| 81 | - the files in the device directory or files below a subdirectories | ||
| 82 | of the same device directory | ||
| 83 | - accessing attributes reached by a symlink pointing to another device, | ||
| 84 | like the "device"-link, is a bug in the application | ||
| 85 | |||
| 86 | Everything else is just a kernel driver-core implementation detail, | ||
| 87 | that should not be assumed to be stable across kernel releases. | ||
| 88 | |||
| 89 | - Properties of parent devices never belong into a child device. | ||
| 90 | Always look at the parent devices themselves for determining device | ||
| 91 | context properties. If the device 'eth0' or 'sda' does not have a | ||
| 92 | "driver"-link, then this device does not have a driver. Its value is empty. | ||
| 93 | Never copy any property of the parent-device into a child-device. Parent | ||
| 94 | device-properties may change dynamically without any notice to the | ||
| 95 | child device. | ||
| 96 | |||
| 97 | - Hierarchy in a single device-tree | ||
| 98 | There is only one valid place in sysfs where hierarchy can be examined | ||
| 99 | and this is below: /sys/devices. | ||
| 100 | It is planned, that all device directories will end up in the tree | ||
| 101 | below this directory. | ||
| 102 | |||
| 103 | - Classification by subsystem | ||
| 104 | There are currently three places for classification of devices: | ||
| 105 | /sys/block, /sys/class and /sys/bus. It is planned that these will | ||
| 106 | not contain any device-directories themselves, but only flat lists of | ||
| 107 | symlinks pointing to the unified /sys/devices tree. | ||
| 108 | All three places have completely different rules on how to access | ||
| 109 | device information. It is planned to merge all three | ||
| 110 | classification-directories into one place at /sys/subsystem, | ||
| 111 | following the layout of the bus-directories. All buses and | ||
| 112 | classes, including the converted block-subsystem, will show up | ||
| 113 | there. | ||
| 114 | The devices belonging to a subsystem will create a symlink in the | ||
| 115 | "devices" directory at /sys/subsystem/<name>/devices. | ||
| 116 | |||
| 117 | If /sys/subsystem exists, /sys/bus, /sys/class and /sys/block can be | ||
| 118 | ignored. If it does not exist, you have always to scan all three | ||
| 119 | places, as the kernel is free to move a subsystem from one place to | ||
| 120 | the other, as long as the devices are still reachable by the same | ||
| 121 | subsystem name. | ||
| 122 | |||
| 123 | Assuming /sys/class/<subsystem> and /sys/bus/<subsystem>, or | ||
| 124 | /sys/block and /sys/class/block are not interchangeable, is a bug in | ||
| 125 | the application. | ||
| 126 | |||
| 127 | - Block | ||
| 128 | The converted block-subsystem at /sys/class/block, or | ||
| 129 | /sys/subsystem/block will contain the links for disks and partitions | ||
| 130 | at the same level, never in a hierarchy. Assuming the block-subsytem to | ||
| 131 | contain only disks and not partition-devices in the same flat list is | ||
| 132 | a bug in the application. | ||
| 133 | |||
| 134 | - "device"-link and <subsystem>:<kernel name>-links | ||
| 135 | Never depend on the "device"-link. The "device"-link is a workaround | ||
| 136 | for the old layout, where class-devices are not created in | ||
| 137 | /sys/devices/ like the bus-devices. If the link-resolving of a | ||
| 138 | device-directory does not end in /sys/devices/, you can use the | ||
| 139 | "device"-link to find the parent devices in /sys/devices/. That is the | ||
| 140 | single valid use of the "device"-link, it must never appear in any | ||
| 141 | path as an element. Assuming the existence of the "device"-link for | ||
| 142 | a device in /sys/devices/ is a bug in the application. | ||
| 143 | Accessing /sys/class/net/eth0/device is a bug in the application. | ||
| 144 | |||
| 145 | Never depend on the class-specific links back to the /sys/class | ||
| 146 | directory. These links are also a workaround for the design mistake | ||
| 147 | that class-devices are not created in /sys/devices. If a device | ||
| 148 | directory does not contain directories for child devices, these links | ||
| 149 | may be used to find the child devices in /sys/class. That is the single | ||
| 150 | valid use of these links, they must never appear in any path as an | ||
| 151 | element. Assuming the existence of these links for devices which are | ||
| 152 | real child device directories in the /sys/devices tree, is a bug in | ||
| 153 | the application. | ||
| 154 | |||
| 155 | It is planned to remove all these links when when all class-device | ||
| 156 | directories live in /sys/devices. | ||
| 157 | |||
| 158 | - Position of devices along device chain can change. | ||
| 159 | Never depend on a specific parent device position in the devpath, | ||
| 160 | or the chain of parent devices. The kernel is free to insert devices into | ||
| 161 | the chain. You must always request the parent device you are looking for | ||
| 162 | by its subsystem value. You need to walk up the chain until you find | ||
| 163 | the device that matches the expected subsystem. Depending on a specific | ||
| 164 | position of a parent device, or exposing relative paths, using "../" to | ||
| 165 | access the chain of parents, is a bug in the application. | ||
| 166 | |||
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c index cfe6f4650bc9..ae21755872ed 100644 --- a/arch/arm/common/locomo.c +++ b/arch/arm/common/locomo.c | |||
| @@ -60,6 +60,9 @@ struct locomo { | |||
| 60 | unsigned int irq; | 60 | unsigned int irq; |
| 61 | spinlock_t lock; | 61 | spinlock_t lock; |
| 62 | void __iomem *base; | 62 | void __iomem *base; |
| 63 | #ifdef CONFIG_PM | ||
| 64 | void *saved_state; | ||
| 65 | #endif | ||
| 63 | }; | 66 | }; |
| 64 | 67 | ||
| 65 | struct locomo_dev_info { | 68 | struct locomo_dev_info { |
| @@ -565,7 +568,7 @@ static int locomo_suspend(struct platform_device *dev, pm_message_t state) | |||
| 565 | if (!save) | 568 | if (!save) |
| 566 | return -ENOMEM; | 569 | return -ENOMEM; |
| 567 | 570 | ||
| 568 | dev->dev.power.saved_state = (void *) save; | 571 | lchip->saved_state = save; |
| 569 | 572 | ||
| 570 | spin_lock_irqsave(&lchip->lock, flags); | 573 | spin_lock_irqsave(&lchip->lock, flags); |
| 571 | 574 | ||
| @@ -605,8 +608,8 @@ static int locomo_resume(struct platform_device *dev) | |||
| 605 | struct locomo_save_data *save; | 608 | struct locomo_save_data *save; |
| 606 | unsigned long r; | 609 | unsigned long r; |
| 607 | unsigned long flags; | 610 | unsigned long flags; |
| 608 | 611 | ||
| 609 | save = (struct locomo_save_data *) dev->dev.power.saved_state; | 612 | save = lchip->saved_state; |
| 610 | if (!save) | 613 | if (!save) |
| 611 | return 0; | 614 | return 0; |
| 612 | 615 | ||
| @@ -628,6 +631,8 @@ static int locomo_resume(struct platform_device *dev) | |||
| 628 | locomo_writel(0x1, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KCMD); | 631 | locomo_writel(0x1, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KCMD); |
| 629 | 632 | ||
| 630 | spin_unlock_irqrestore(&lchip->lock, flags); | 633 | spin_unlock_irqrestore(&lchip->lock, flags); |
| 634 | |||
| 635 | lchip->saved_state = NULL; | ||
| 631 | kfree(save); | 636 | kfree(save); |
| 632 | 637 | ||
| 633 | return 0; | 638 | return 0; |
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c index 798bbfccafb7..eb06d0b2cb74 100644 --- a/arch/arm/common/sa1111.c +++ b/arch/arm/common/sa1111.c | |||
| @@ -51,6 +51,9 @@ struct sa1111 { | |||
| 51 | int irq; | 51 | int irq; |
| 52 | spinlock_t lock; | 52 | spinlock_t lock; |
| 53 | void __iomem *base; | 53 | void __iomem *base; |
| 54 | #ifdef CONFIG_PM | ||
| 55 | void *saved_state; | ||
| 56 | #endif | ||
| 54 | }; | 57 | }; |
| 55 | 58 | ||
| 56 | /* | 59 | /* |
| @@ -822,7 +825,7 @@ static int sa1111_suspend(struct platform_device *dev, pm_message_t state) | |||
| 822 | save = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL); | 825 | save = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL); |
| 823 | if (!save) | 826 | if (!save) |
| 824 | return -ENOMEM; | 827 | return -ENOMEM; |
| 825 | dev->dev.power.saved_state = save; | 828 | sachip->saved_state = save; |
| 826 | 829 | ||
| 827 | spin_lock_irqsave(&sachip->lock, flags); | 830 | spin_lock_irqsave(&sachip->lock, flags); |
| 828 | 831 | ||
| @@ -878,7 +881,7 @@ static int sa1111_resume(struct platform_device *dev) | |||
| 878 | unsigned long flags, id; | 881 | unsigned long flags, id; |
| 879 | void __iomem *base; | 882 | void __iomem *base; |
| 880 | 883 | ||
| 881 | save = (struct sa1111_save_data *)dev->dev.power.saved_state; | 884 | save = sachip->saved_state; |
| 882 | if (!save) | 885 | if (!save) |
| 883 | return 0; | 886 | return 0; |
| 884 | 887 | ||
| @@ -923,7 +926,7 @@ static int sa1111_resume(struct platform_device *dev) | |||
| 923 | 926 | ||
| 924 | spin_unlock_irqrestore(&sachip->lock, flags); | 927 | spin_unlock_irqrestore(&sachip->lock, flags); |
| 925 | 928 | ||
| 926 | dev->dev.power.saved_state = NULL; | 929 | sachip->saved_state = NULL; |
| 927 | kfree(save); | 930 | kfree(save); |
| 928 | 931 | ||
| 929 | return 0; | 932 | return 0; |
| @@ -958,8 +961,8 @@ static int sa1111_remove(struct platform_device *pdev) | |||
| 958 | platform_set_drvdata(pdev, NULL); | 961 | platform_set_drvdata(pdev, NULL); |
| 959 | 962 | ||
| 960 | #ifdef CONFIG_PM | 963 | #ifdef CONFIG_PM |
| 961 | kfree(pdev->dev.power.saved_state); | 964 | kfree(sachip->saved_state); |
| 962 | pdev->dev.power.saved_state = NULL; | 965 | sachip->saved_state = NULL; |
| 963 | #endif | 966 | #endif |
| 964 | } | 967 | } |
| 965 | 968 | ||
diff --git a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c index 4cbf9468f654..3a0a1ee2542d 100644 --- a/arch/arm/mach-sa1100/neponset.c +++ b/arch/arm/mach-sa1100/neponset.c | |||
| @@ -185,28 +185,21 @@ static int __devinit neponset_probe(struct platform_device *dev) | |||
| 185 | /* | 185 | /* |
| 186 | * LDM power management. | 186 | * LDM power management. |
| 187 | */ | 187 | */ |
| 188 | static unsigned int neponset_saved_state; | ||
| 189 | |||
| 188 | static int neponset_suspend(struct platform_device *dev, pm_message_t state) | 190 | static int neponset_suspend(struct platform_device *dev, pm_message_t state) |
| 189 | { | 191 | { |
| 190 | /* | 192 | /* |
| 191 | * Save state. | 193 | * Save state. |
| 192 | */ | 194 | */ |
| 193 | if (!dev->dev.power.saved_state) | 195 | neponset_saved_state = NCR_0; |
| 194 | dev->dev.power.saved_state = kmalloc(sizeof(unsigned int), GFP_KERNEL); | ||
| 195 | if (!dev->dev.power.saved_state) | ||
| 196 | return -ENOMEM; | ||
| 197 | |||
| 198 | *(unsigned int *)dev->dev.power.saved_state = NCR_0; | ||
| 199 | 196 | ||
| 200 | return 0; | 197 | return 0; |
| 201 | } | 198 | } |
| 202 | 199 | ||
| 203 | static int neponset_resume(struct platform_device *dev) | 200 | static int neponset_resume(struct platform_device *dev) |
| 204 | { | 201 | { |
| 205 | if (dev->dev.power.saved_state) { | 202 | NCR_0 = neponset_saved_state; |
| 206 | NCR_0 = *(unsigned int *)dev->dev.power.saved_state; | ||
| 207 | kfree(dev->dev.power.saved_state); | ||
| 208 | dev->dev.power.saved_state = NULL; | ||
| 209 | } | ||
| 210 | 203 | ||
| 211 | return 0; | 204 | return 0; |
| 212 | } | 205 | } |
diff --git a/arch/ppc/syslib/mv64x60.c b/arch/ppc/syslib/mv64x60.c index 8485a68cd475..032f4b7f4225 100644 --- a/arch/ppc/syslib/mv64x60.c +++ b/arch/ppc/syslib/mv64x60.c | |||
| @@ -2415,7 +2415,6 @@ static struct bin_attribute mv64xxx_hs_reg_attr = { /* Hotswap register */ | |||
| 2415 | .attr = { | 2415 | .attr = { |
| 2416 | .name = "hs_reg", | 2416 | .name = "hs_reg", |
| 2417 | .mode = S_IRUGO | S_IWUSR, | 2417 | .mode = S_IRUGO | S_IWUSR, |
| 2418 | .owner = THIS_MODULE, | ||
| 2419 | }, | 2418 | }, |
| 2420 | .size = VAL_LEN_MAX, | 2419 | .size = VAL_LEN_MAX, |
| 2421 | .read = mv64xxx_hs_reg_read, | 2420 | .read = mv64xxx_hs_reg_read, |
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 82b131ddd7ff..9a13b24ee1ab 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c | |||
| @@ -312,7 +312,6 @@ static struct bin_attribute ipl_parameter_attr = { | |||
| 312 | .attr = { | 312 | .attr = { |
| 313 | .name = "binary_parameter", | 313 | .name = "binary_parameter", |
| 314 | .mode = S_IRUGO, | 314 | .mode = S_IRUGO, |
| 315 | .owner = THIS_MODULE, | ||
| 316 | }, | 315 | }, |
| 317 | .size = PAGE_SIZE, | 316 | .size = PAGE_SIZE, |
| 318 | .read = &ipl_parameter_read, | 317 | .read = &ipl_parameter_read, |
| @@ -336,7 +335,6 @@ static struct bin_attribute ipl_scp_data_attr = { | |||
| 336 | .attr = { | 335 | .attr = { |
| 337 | .name = "scp_data", | 336 | .name = "scp_data", |
| 338 | .mode = S_IRUGO, | 337 | .mode = S_IRUGO, |
| 339 | .owner = THIS_MODULE, | ||
| 340 | }, | 338 | }, |
| 341 | .size = PAGE_SIZE, | 339 | .size = PAGE_SIZE, |
| 342 | .read = &ipl_scp_data_read, | 340 | .read = &ipl_scp_data_read, |
diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c index 1ec0654665cf..7370d7cf5988 100644 --- a/drivers/base/attribute_container.c +++ b/drivers/base/attribute_container.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
| 19 | #include <linux/list.h> | 19 | #include <linux/list.h> |
| 20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
| 21 | #include <linux/mutex.h> | ||
| 21 | 22 | ||
| 22 | #include "base.h" | 23 | #include "base.h" |
| 23 | 24 | ||
diff --git a/drivers/base/base.h b/drivers/base/base.h index 5512d84452f2..47eb02d9f1af 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h | |||
| @@ -44,6 +44,6 @@ struct class_device_attribute *to_class_dev_attr(struct attribute *_attr) | |||
| 44 | 44 | ||
| 45 | extern char *make_class_name(const char *name, struct kobject *kobj); | 45 | extern char *make_class_name(const char *name, struct kobject *kobj); |
| 46 | 46 | ||
| 47 | extern void devres_release_all(struct device *dev); | 47 | extern int devres_release_all(struct device *dev); |
| 48 | 48 | ||
| 49 | extern struct kset devices_subsys; | 49 | extern struct kset devices_subsys; |
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index dca734819e50..61c67526a656 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c | |||
| @@ -138,12 +138,24 @@ void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr) | |||
| 138 | } | 138 | } |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | static struct kobj_type ktype_bus = { | 141 | static struct kobj_type bus_ktype = { |
| 142 | .sysfs_ops = &bus_sysfs_ops, | 142 | .sysfs_ops = &bus_sysfs_ops, |
| 143 | }; | ||
| 144 | |||
| 145 | static int bus_uevent_filter(struct kset *kset, struct kobject *kobj) | ||
| 146 | { | ||
| 147 | struct kobj_type *ktype = get_ktype(kobj); | ||
| 143 | 148 | ||
| 149 | if (ktype == &bus_ktype) | ||
| 150 | return 1; | ||
| 151 | return 0; | ||
| 152 | } | ||
| 153 | |||
| 154 | static struct kset_uevent_ops bus_uevent_ops = { | ||
| 155 | .filter = bus_uevent_filter, | ||
| 144 | }; | 156 | }; |
| 145 | 157 | ||
| 146 | static decl_subsys(bus, &ktype_bus, NULL); | 158 | static decl_subsys(bus, &bus_ktype, &bus_uevent_ops); |
| 147 | 159 | ||
| 148 | 160 | ||
| 149 | #ifdef CONFIG_HOTPLUG | 161 | #ifdef CONFIG_HOTPLUG |
| @@ -562,7 +574,6 @@ static int add_probe_files(struct bus_type *bus) | |||
| 562 | 574 | ||
| 563 | bus->drivers_probe_attr.attr.name = "drivers_probe"; | 575 | bus->drivers_probe_attr.attr.name = "drivers_probe"; |
| 564 | bus->drivers_probe_attr.attr.mode = S_IWUSR; | 576 | bus->drivers_probe_attr.attr.mode = S_IWUSR; |
| 565 | bus->drivers_probe_attr.attr.owner = bus->owner; | ||
| 566 | bus->drivers_probe_attr.store = store_drivers_probe; | 577 | bus->drivers_probe_attr.store = store_drivers_probe; |
| 567 | retval = bus_create_file(bus, &bus->drivers_probe_attr); | 578 | retval = bus_create_file(bus, &bus->drivers_probe_attr); |
| 568 | if (retval) | 579 | if (retval) |
| @@ -570,7 +581,6 @@ static int add_probe_files(struct bus_type *bus) | |||
| 570 | 581 | ||
| 571 | bus->drivers_autoprobe_attr.attr.name = "drivers_autoprobe"; | 582 | bus->drivers_autoprobe_attr.attr.name = "drivers_autoprobe"; |
| 572 | bus->drivers_autoprobe_attr.attr.mode = S_IWUSR | S_IRUGO; | 583 | bus->drivers_autoprobe_attr.attr.mode = S_IWUSR | S_IRUGO; |
| 573 | bus->drivers_autoprobe_attr.attr.owner = bus->owner; | ||
| 574 | bus->drivers_autoprobe_attr.show = show_drivers_autoprobe; | 584 | bus->drivers_autoprobe_attr.show = show_drivers_autoprobe; |
| 575 | bus->drivers_autoprobe_attr.store = store_drivers_autoprobe; | 585 | bus->drivers_autoprobe_attr.store = store_drivers_autoprobe; |
| 576 | retval = bus_create_file(bus, &bus->drivers_autoprobe_attr); | 586 | retval = bus_create_file(bus, &bus->drivers_autoprobe_attr); |
| @@ -610,7 +620,8 @@ int bus_add_driver(struct device_driver *drv) | |||
| 610 | if (error) | 620 | if (error) |
| 611 | goto out_put_bus; | 621 | goto out_put_bus; |
| 612 | drv->kobj.kset = &bus->drivers; | 622 | drv->kobj.kset = &bus->drivers; |
| 613 | if ((error = kobject_register(&drv->kobj))) | 623 | error = kobject_register(&drv->kobj); |
| 624 | if (error) | ||
| 614 | goto out_put_bus; | 625 | goto out_put_bus; |
| 615 | 626 | ||
| 616 | if (drv->bus->drivers_autoprobe) { | 627 | if (drv->bus->drivers_autoprobe) { |
| @@ -760,7 +771,8 @@ static int bus_add_attrs(struct bus_type * bus) | |||
| 760 | 771 | ||
| 761 | if (bus->bus_attrs) { | 772 | if (bus->bus_attrs) { |
| 762 | for (i = 0; attr_name(bus->bus_attrs[i]); i++) { | 773 | for (i = 0; attr_name(bus->bus_attrs[i]); i++) { |
| 763 | if ((error = bus_create_file(bus,&bus->bus_attrs[i]))) | 774 | error = bus_create_file(bus,&bus->bus_attrs[i]); |
| 775 | if (error) | ||
| 764 | goto Err; | 776 | goto Err; |
| 765 | } | 777 | } |
| 766 | } | 778 | } |
diff --git a/drivers/base/class.c b/drivers/base/class.c index 8c506dbe3913..4d2222618b78 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c | |||
| @@ -312,9 +312,6 @@ static void class_dev_release(struct kobject * kobj) | |||
| 312 | 312 | ||
| 313 | pr_debug("device class '%s': release.\n", cd->class_id); | 313 | pr_debug("device class '%s': release.\n", cd->class_id); |
| 314 | 314 | ||
| 315 | kfree(cd->devt_attr); | ||
| 316 | cd->devt_attr = NULL; | ||
| 317 | |||
| 318 | if (cd->release) | 315 | if (cd->release) |
| 319 | cd->release(cd); | 316 | cd->release(cd); |
| 320 | else if (cls->release) | 317 | else if (cls->release) |
| @@ -547,6 +544,9 @@ static ssize_t show_dev(struct class_device *class_dev, char *buf) | |||
| 547 | return print_dev_t(buf, class_dev->devt); | 544 | return print_dev_t(buf, class_dev->devt); |
| 548 | } | 545 | } |
| 549 | 546 | ||
| 547 | static struct class_device_attribute class_devt_attr = | ||
| 548 | __ATTR(dev, S_IRUGO, show_dev, NULL); | ||
| 549 | |||
| 550 | static ssize_t store_uevent(struct class_device *class_dev, | 550 | static ssize_t store_uevent(struct class_device *class_dev, |
| 551 | const char *buf, size_t count) | 551 | const char *buf, size_t count) |
| 552 | { | 552 | { |
| @@ -554,6 +554,9 @@ static ssize_t store_uevent(struct class_device *class_dev, | |||
| 554 | return count; | 554 | return count; |
| 555 | } | 555 | } |
| 556 | 556 | ||
| 557 | static struct class_device_attribute class_uevent_attr = | ||
| 558 | __ATTR(uevent, S_IWUSR, NULL, store_uevent); | ||
| 559 | |||
| 557 | void class_device_initialize(struct class_device *class_dev) | 560 | void class_device_initialize(struct class_device *class_dev) |
| 558 | { | 561 | { |
| 559 | kobj_set_kset_s(class_dev, class_obj_subsys); | 562 | kobj_set_kset_s(class_dev, class_obj_subsys); |
| @@ -603,32 +606,15 @@ int class_device_add(struct class_device *class_dev) | |||
| 603 | &parent_class->subsys.kobj, "subsystem"); | 606 | &parent_class->subsys.kobj, "subsystem"); |
| 604 | if (error) | 607 | if (error) |
| 605 | goto out3; | 608 | goto out3; |
| 606 | class_dev->uevent_attr.attr.name = "uevent"; | 609 | |
| 607 | class_dev->uevent_attr.attr.mode = S_IWUSR; | 610 | error = class_device_create_file(class_dev, &class_uevent_attr); |
| 608 | class_dev->uevent_attr.attr.owner = parent_class->owner; | ||
| 609 | class_dev->uevent_attr.store = store_uevent; | ||
| 610 | error = class_device_create_file(class_dev, &class_dev->uevent_attr); | ||
| 611 | if (error) | 611 | if (error) |
| 612 | goto out3; | 612 | goto out3; |
| 613 | 613 | ||
| 614 | if (MAJOR(class_dev->devt)) { | 614 | if (MAJOR(class_dev->devt)) { |
| 615 | struct class_device_attribute *attr; | 615 | error = class_device_create_file(class_dev, &class_devt_attr); |
| 616 | attr = kzalloc(sizeof(*attr), GFP_KERNEL); | 616 | if (error) |
| 617 | if (!attr) { | ||
| 618 | error = -ENOMEM; | ||
| 619 | goto out4; | ||
| 620 | } | ||
| 621 | attr->attr.name = "dev"; | ||
| 622 | attr->attr.mode = S_IRUGO; | ||
| 623 | attr->attr.owner = parent_class->owner; | ||
| 624 | attr->show = show_dev; | ||
| 625 | error = class_device_create_file(class_dev, attr); | ||
| 626 | if (error) { | ||
| 627 | kfree(attr); | ||
| 628 | goto out4; | 617 | goto out4; |
| 629 | } | ||
| 630 | |||
| 631 | class_dev->devt_attr = attr; | ||
| 632 | } | 618 | } |
| 633 | 619 | ||
| 634 | error = class_device_add_attrs(class_dev); | 620 | error = class_device_add_attrs(class_dev); |
| @@ -671,10 +657,10 @@ int class_device_add(struct class_device *class_dev) | |||
| 671 | out6: | 657 | out6: |
| 672 | class_device_remove_attrs(class_dev); | 658 | class_device_remove_attrs(class_dev); |
| 673 | out5: | 659 | out5: |
| 674 | if (class_dev->devt_attr) | 660 | if (MAJOR(class_dev->devt)) |
| 675 | class_device_remove_file(class_dev, class_dev->devt_attr); | 661 | class_device_remove_file(class_dev, &class_devt_attr); |
| 676 | out4: | 662 | out4: |
| 677 | class_device_remove_file(class_dev, &class_dev->uevent_attr); | 663 | class_device_remove_file(class_dev, &class_uevent_attr); |
| 678 | out3: | 664 | out3: |
| 679 | kobject_del(&class_dev->kobj); | 665 | kobject_del(&class_dev->kobj); |
| 680 | out2: | 666 | out2: |
| @@ -774,9 +760,9 @@ void class_device_del(struct class_device *class_dev) | |||
| 774 | sysfs_remove_link(&class_dev->kobj, "device"); | 760 | sysfs_remove_link(&class_dev->kobj, "device"); |
| 775 | } | 761 | } |
| 776 | sysfs_remove_link(&class_dev->kobj, "subsystem"); | 762 | sysfs_remove_link(&class_dev->kobj, "subsystem"); |
| 777 | class_device_remove_file(class_dev, &class_dev->uevent_attr); | 763 | class_device_remove_file(class_dev, &class_uevent_attr); |
| 778 | if (class_dev->devt_attr) | 764 | if (MAJOR(class_dev->devt)) |
| 779 | class_device_remove_file(class_dev, class_dev->devt_attr); | 765 | class_device_remove_file(class_dev, &class_devt_attr); |
| 780 | class_device_remove_attrs(class_dev); | 766 | class_device_remove_attrs(class_dev); |
| 781 | class_device_remove_groups(class_dev); | 767 | class_device_remove_groups(class_dev); |
| 782 | 768 | ||
diff --git a/drivers/base/core.c b/drivers/base/core.c index dd40d78a023d..0455aa78fa13 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
| @@ -310,6 +310,9 @@ static ssize_t store_uevent(struct device *dev, struct device_attribute *attr, | |||
| 310 | return count; | 310 | return count; |
| 311 | } | 311 | } |
| 312 | 312 | ||
| 313 | static struct device_attribute uevent_attr = | ||
| 314 | __ATTR(uevent, S_IRUGO | S_IWUSR, show_uevent, store_uevent); | ||
| 315 | |||
| 313 | static int device_add_attributes(struct device *dev, | 316 | static int device_add_attributes(struct device *dev, |
| 314 | struct device_attribute *attrs) | 317 | struct device_attribute *attrs) |
| 315 | { | 318 | { |
| @@ -423,6 +426,9 @@ static ssize_t show_dev(struct device *dev, struct device_attribute *attr, | |||
| 423 | return print_dev_t(buf, dev->devt); | 426 | return print_dev_t(buf, dev->devt); |
| 424 | } | 427 | } |
| 425 | 428 | ||
| 429 | static struct device_attribute devt_attr = | ||
| 430 | __ATTR(dev, S_IRUGO, show_dev, NULL); | ||
| 431 | |||
| 426 | /* | 432 | /* |
| 427 | * devices_subsys - structure to be registered with kobject core. | 433 | * devices_subsys - structure to be registered with kobject core. |
| 428 | */ | 434 | */ |
| @@ -681,35 +687,14 @@ int device_add(struct device *dev) | |||
| 681 | blocking_notifier_call_chain(&dev->bus->bus_notifier, | 687 | blocking_notifier_call_chain(&dev->bus->bus_notifier, |
| 682 | BUS_NOTIFY_ADD_DEVICE, dev); | 688 | BUS_NOTIFY_ADD_DEVICE, dev); |
| 683 | 689 | ||
| 684 | dev->uevent_attr.attr.name = "uevent"; | 690 | error = device_create_file(dev, &uevent_attr); |
| 685 | dev->uevent_attr.attr.mode = S_IRUGO | S_IWUSR; | ||
| 686 | if (dev->driver) | ||
| 687 | dev->uevent_attr.attr.owner = dev->driver->owner; | ||
| 688 | dev->uevent_attr.store = store_uevent; | ||
| 689 | dev->uevent_attr.show = show_uevent; | ||
| 690 | error = device_create_file(dev, &dev->uevent_attr); | ||
| 691 | if (error) | 691 | if (error) |
| 692 | goto attrError; | 692 | goto attrError; |
| 693 | 693 | ||
| 694 | if (MAJOR(dev->devt)) { | 694 | if (MAJOR(dev->devt)) { |
| 695 | struct device_attribute *attr; | 695 | error = device_create_file(dev, &devt_attr); |
| 696 | attr = kzalloc(sizeof(*attr), GFP_KERNEL); | 696 | if (error) |
| 697 | if (!attr) { | ||
| 698 | error = -ENOMEM; | ||
| 699 | goto ueventattrError; | ||
| 700 | } | ||
| 701 | attr->attr.name = "dev"; | ||
| 702 | attr->attr.mode = S_IRUGO; | ||
| 703 | if (dev->driver) | ||
| 704 | attr->attr.owner = dev->driver->owner; | ||
| 705 | attr->show = show_dev; | ||
| 706 | error = device_create_file(dev, attr); | ||
| 707 | if (error) { | ||
| 708 | kfree(attr); | ||
| 709 | goto ueventattrError; | 697 | goto ueventattrError; |
| 710 | } | ||
| 711 | |||
| 712 | dev->devt_attr = attr; | ||
| 713 | } | 698 | } |
| 714 | 699 | ||
| 715 | if (dev->class) { | 700 | if (dev->class) { |
| @@ -733,11 +718,14 @@ int device_add(struct device *dev) | |||
| 733 | } | 718 | } |
| 734 | } | 719 | } |
| 735 | 720 | ||
| 736 | if ((error = device_add_attrs(dev))) | 721 | error = device_add_attrs(dev); |
| 722 | if (error) | ||
| 737 | goto AttrsError; | 723 | goto AttrsError; |
| 738 | if ((error = device_pm_add(dev))) | 724 | error = device_pm_add(dev); |
| 725 | if (error) | ||
| 739 | goto PMError; | 726 | goto PMError; |
| 740 | if ((error = bus_add_device(dev))) | 727 | error = bus_add_device(dev); |
| 728 | if (error) | ||
| 741 | goto BusError; | 729 | goto BusError; |
| 742 | kobject_uevent(&dev->kobj, KOBJ_ADD); | 730 | kobject_uevent(&dev->kobj, KOBJ_ADD); |
| 743 | bus_attach_device(dev); | 731 | bus_attach_device(dev); |
| @@ -767,10 +755,8 @@ int device_add(struct device *dev) | |||
| 767 | BUS_NOTIFY_DEL_DEVICE, dev); | 755 | BUS_NOTIFY_DEL_DEVICE, dev); |
| 768 | device_remove_attrs(dev); | 756 | device_remove_attrs(dev); |
| 769 | AttrsError: | 757 | AttrsError: |
| 770 | if (dev->devt_attr) { | 758 | if (MAJOR(dev->devt)) |
| 771 | device_remove_file(dev, dev->devt_attr); | 759 | device_remove_file(dev, &devt_attr); |
| 772 | kfree(dev->devt_attr); | ||
| 773 | } | ||
| 774 | 760 | ||
| 775 | if (dev->class) { | 761 | if (dev->class) { |
| 776 | sysfs_remove_link(&dev->kobj, "subsystem"); | 762 | sysfs_remove_link(&dev->kobj, "subsystem"); |
| @@ -792,7 +778,7 @@ int device_add(struct device *dev) | |||
| 792 | } | 778 | } |
| 793 | } | 779 | } |
| 794 | ueventattrError: | 780 | ueventattrError: |
| 795 | device_remove_file(dev, &dev->uevent_attr); | 781 | device_remove_file(dev, &uevent_attr); |
| 796 | attrError: | 782 | attrError: |
| 797 | kobject_uevent(&dev->kobj, KOBJ_REMOVE); | 783 | kobject_uevent(&dev->kobj, KOBJ_REMOVE); |
| 798 | kobject_del(&dev->kobj); | 784 | kobject_del(&dev->kobj); |
| @@ -869,10 +855,8 @@ void device_del(struct device * dev) | |||
| 869 | 855 | ||
| 870 | if (parent) | 856 | if (parent) |
| 871 | klist_del(&dev->knode_parent); | 857 | klist_del(&dev->knode_parent); |
| 872 | if (dev->devt_attr) { | 858 | if (MAJOR(dev->devt)) |
| 873 | device_remove_file(dev, dev->devt_attr); | 859 | device_remove_file(dev, &devt_attr); |
| 874 | kfree(dev->devt_attr); | ||
| 875 | } | ||
| 876 | if (dev->class) { | 860 | if (dev->class) { |
| 877 | sysfs_remove_link(&dev->kobj, "subsystem"); | 861 | sysfs_remove_link(&dev->kobj, "subsystem"); |
| 878 | /* If this is not a "fake" compatible device, remove the | 862 | /* If this is not a "fake" compatible device, remove the |
| @@ -926,7 +910,7 @@ void device_del(struct device * dev) | |||
| 926 | up(&dev->class->sem); | 910 | up(&dev->class->sem); |
| 927 | } | 911 | } |
| 928 | } | 912 | } |
| 929 | device_remove_file(dev, &dev->uevent_attr); | 913 | device_remove_file(dev, &uevent_attr); |
| 930 | device_remove_attrs(dev); | 914 | device_remove_attrs(dev); |
| 931 | bus_remove_device(dev); | 915 | bus_remove_device(dev); |
| 932 | 916 | ||
diff --git a/drivers/base/dd.c b/drivers/base/dd.c index b0088b0efecd..7ac474db88c5 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c | |||
| @@ -281,24 +281,16 @@ int driver_attach(struct device_driver * drv) | |||
| 281 | return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach); | 281 | return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach); |
| 282 | } | 282 | } |
| 283 | 283 | ||
| 284 | /** | 284 | /* |
| 285 | * device_release_driver - manually detach device from driver. | ||
| 286 | * @dev: device. | ||
| 287 | * | ||
| 288 | * Manually detach device from driver. | ||
| 289 | * | ||
| 290 | * __device_release_driver() must be called with @dev->sem held. | 285 | * __device_release_driver() must be called with @dev->sem held. |
| 291 | * When called for a USB interface, @dev->parent->sem must be held | 286 | * When called for a USB interface, @dev->parent->sem must be held as well. |
| 292 | * as well. | ||
| 293 | */ | 287 | */ |
| 294 | |||
| 295 | static void __device_release_driver(struct device * dev) | 288 | static void __device_release_driver(struct device * dev) |
| 296 | { | 289 | { |
| 297 | struct device_driver * drv; | 290 | struct device_driver * drv; |
| 298 | 291 | ||
| 299 | drv = dev->driver; | 292 | drv = get_driver(dev->driver); |
| 300 | if (drv) { | 293 | if (drv) { |
| 301 | get_driver(drv); | ||
| 302 | driver_sysfs_remove(dev); | 294 | driver_sysfs_remove(dev); |
| 303 | sysfs_remove_link(&dev->kobj, "driver"); | 295 | sysfs_remove_link(&dev->kobj, "driver"); |
| 304 | klist_remove(&dev->knode_driver); | 296 | klist_remove(&dev->knode_driver); |
| @@ -318,6 +310,13 @@ static void __device_release_driver(struct device * dev) | |||
| 318 | } | 310 | } |
| 319 | } | 311 | } |
| 320 | 312 | ||
| 313 | /** | ||
| 314 | * device_release_driver - manually detach device from driver. | ||
| 315 | * @dev: device. | ||
| 316 | * | ||
| 317 | * Manually detach device from driver. | ||
| 318 | * When called for a USB interface, @dev->parent->sem must be held. | ||
| 319 | */ | ||
| 321 | void device_release_driver(struct device * dev) | 320 | void device_release_driver(struct device * dev) |
| 322 | { | 321 | { |
| 323 | /* | 322 | /* |
diff --git a/drivers/base/devres.c b/drivers/base/devres.c index e1c0730a3b99..e8beb8e5b626 100644 --- a/drivers/base/devres.c +++ b/drivers/base/devres.c | |||
| @@ -10,6 +10,8 @@ | |||
| 10 | #include <linux/device.h> | 10 | #include <linux/device.h> |
| 11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
| 12 | 12 | ||
| 13 | #include "base.h" | ||
| 14 | |||
| 13 | struct devres_node { | 15 | struct devres_node { |
| 14 | struct list_head entry; | 16 | struct list_head entry; |
| 15 | dr_release_t release; | 17 | dr_release_t release; |
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 89a5f4a54913..53f0ee6f3016 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
| @@ -175,7 +175,7 @@ static ssize_t firmware_loading_store(struct device *dev, | |||
| 175 | static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store); | 175 | static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store); |
| 176 | 176 | ||
| 177 | static ssize_t | 177 | static ssize_t |
| 178 | firmware_data_read(struct kobject *kobj, | 178 | firmware_data_read(struct kobject *kobj, struct bin_attribute *bin_attr, |
| 179 | char *buffer, loff_t offset, size_t count) | 179 | char *buffer, loff_t offset, size_t count) |
| 180 | { | 180 | { |
| 181 | struct device *dev = to_dev(kobj); | 181 | struct device *dev = to_dev(kobj); |
| @@ -240,7 +240,7 @@ fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size) | |||
| 240 | * the driver as a firmware image. | 240 | * the driver as a firmware image. |
| 241 | **/ | 241 | **/ |
| 242 | static ssize_t | 242 | static ssize_t |
| 243 | firmware_data_write(struct kobject *kobj, | 243 | firmware_data_write(struct kobject *kobj, struct bin_attribute *bin_attr, |
| 244 | char *buffer, loff_t offset, size_t count) | 244 | char *buffer, loff_t offset, size_t count) |
| 245 | { | 245 | { |
| 246 | struct device *dev = to_dev(kobj); | 246 | struct device *dev = to_dev(kobj); |
| @@ -271,7 +271,7 @@ out: | |||
| 271 | } | 271 | } |
| 272 | 272 | ||
| 273 | static struct bin_attribute firmware_attr_data_tmpl = { | 273 | static struct bin_attribute firmware_attr_data_tmpl = { |
| 274 | .attr = {.name = "data", .mode = 0644, .owner = THIS_MODULE}, | 274 | .attr = {.name = "data", .mode = 0644}, |
| 275 | .size = 0, | 275 | .size = 0, |
| 276 | .read = firmware_data_read, | 276 | .read = firmware_data_read, |
| 277 | .write = firmware_data_write, | 277 | .write = firmware_data_write, |
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 05dc8764e765..eb9f38d0aa58 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
| @@ -20,64 +20,44 @@ | |||
| 20 | */ | 20 | */ |
| 21 | 21 | ||
| 22 | #include <linux/device.h> | 22 | #include <linux/device.h> |
| 23 | #include <linux/mutex.h> | ||
| 24 | |||
| 23 | #include "power.h" | 25 | #include "power.h" |
| 24 | 26 | ||
| 25 | LIST_HEAD(dpm_active); | 27 | LIST_HEAD(dpm_active); |
| 26 | LIST_HEAD(dpm_off); | 28 | LIST_HEAD(dpm_off); |
| 27 | LIST_HEAD(dpm_off_irq); | 29 | LIST_HEAD(dpm_off_irq); |
| 28 | 30 | ||
| 29 | DECLARE_MUTEX(dpm_sem); | 31 | DEFINE_MUTEX(dpm_mtx); |
| 30 | DECLARE_MUTEX(dpm_list_sem); | 32 | DEFINE_MUTEX(dpm_list_mtx); |
| 31 | 33 | ||
| 32 | int (*platform_enable_wakeup)(struct device *dev, int is_on); | 34 | int (*platform_enable_wakeup)(struct device *dev, int is_on); |
| 33 | 35 | ||
| 34 | 36 | int device_pm_add(struct device *dev) | |
| 35 | /** | ||
| 36 | * device_pm_set_parent - Specify power dependency. | ||
| 37 | * @dev: Device who needs power. | ||
| 38 | * @parent: Device that supplies power. | ||
| 39 | * | ||
| 40 | * This function is used to manually describe a power-dependency | ||
| 41 | * relationship. It may be used to specify a transversal relationship | ||
| 42 | * (where the power supplier is not the physical (or electrical) | ||
| 43 | * ancestor of a specific device. | ||
| 44 | * The effect of this is that the supplier will not be powered down | ||
| 45 | * before the power dependent. | ||
| 46 | */ | ||
| 47 | |||
| 48 | void device_pm_set_parent(struct device * dev, struct device * parent) | ||
| 49 | { | ||
| 50 | put_device(dev->power.pm_parent); | ||
| 51 | dev->power.pm_parent = get_device(parent); | ||
| 52 | } | ||
| 53 | EXPORT_SYMBOL_GPL(device_pm_set_parent); | ||
| 54 | |||
| 55 | int device_pm_add(struct device * dev) | ||
| 56 | { | 37 | { |
| 57 | int error; | 38 | int error; |
| 58 | 39 | ||
| 59 | pr_debug("PM: Adding info for %s:%s\n", | 40 | pr_debug("PM: Adding info for %s:%s\n", |
| 60 | dev->bus ? dev->bus->name : "No Bus", | 41 | dev->bus ? dev->bus->name : "No Bus", |
| 61 | kobject_name(&dev->kobj)); | 42 | kobject_name(&dev->kobj)); |
| 62 | down(&dpm_list_sem); | 43 | mutex_lock(&dpm_list_mtx); |
| 63 | list_add_tail(&dev->power.entry, &dpm_active); | 44 | list_add_tail(&dev->power.entry, &dpm_active); |
| 64 | device_pm_set_parent(dev, dev->parent); | 45 | error = dpm_sysfs_add(dev); |
| 65 | if ((error = dpm_sysfs_add(dev))) | 46 | if (error) |
| 66 | list_del(&dev->power.entry); | 47 | list_del(&dev->power.entry); |
| 67 | up(&dpm_list_sem); | 48 | mutex_unlock(&dpm_list_mtx); |
| 68 | return error; | 49 | return error; |
| 69 | } | 50 | } |
| 70 | 51 | ||
| 71 | void device_pm_remove(struct device * dev) | 52 | void device_pm_remove(struct device *dev) |
| 72 | { | 53 | { |
| 73 | pr_debug("PM: Removing info for %s:%s\n", | 54 | pr_debug("PM: Removing info for %s:%s\n", |
| 74 | dev->bus ? dev->bus->name : "No Bus", | 55 | dev->bus ? dev->bus->name : "No Bus", |
| 75 | kobject_name(&dev->kobj)); | 56 | kobject_name(&dev->kobj)); |
| 76 | down(&dpm_list_sem); | 57 | mutex_lock(&dpm_list_mtx); |
| 77 | dpm_sysfs_remove(dev); | 58 | dpm_sysfs_remove(dev); |
| 78 | put_device(dev->power.pm_parent); | ||
| 79 | list_del_init(&dev->power.entry); | 59 | list_del_init(&dev->power.entry); |
| 80 | up(&dpm_list_sem); | 60 | mutex_unlock(&dpm_list_mtx); |
| 81 | } | 61 | } |
| 82 | 62 | ||
| 83 | 63 | ||
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index fb3d35a9e101..2760f25b3ac5 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h | |||
| @@ -14,12 +14,12 @@ extern void device_shutdown(void); | |||
| 14 | /* | 14 | /* |
| 15 | * Used to synchronize global power management operations. | 15 | * Used to synchronize global power management operations. |
| 16 | */ | 16 | */ |
| 17 | extern struct semaphore dpm_sem; | 17 | extern struct mutex dpm_mtx; |
| 18 | 18 | ||
| 19 | /* | 19 | /* |
| 20 | * Used to serialize changes to the dpm_* lists. | 20 | * Used to serialize changes to the dpm_* lists. |
| 21 | */ | 21 | */ |
| 22 | extern struct semaphore dpm_list_sem; | 22 | extern struct mutex dpm_list_mtx; |
| 23 | 23 | ||
| 24 | /* | 24 | /* |
| 25 | * The PM lists. | 25 | * The PM lists. |
diff --git a/drivers/base/power/resume.c b/drivers/base/power/resume.c index a2c64188d713..00fd84ae6e66 100644 --- a/drivers/base/power/resume.c +++ b/drivers/base/power/resume.c | |||
| @@ -29,14 +29,6 @@ int resume_device(struct device * dev) | |||
| 29 | 29 | ||
| 30 | down(&dev->sem); | 30 | down(&dev->sem); |
| 31 | 31 | ||
| 32 | if (dev->power.pm_parent | ||
| 33 | && dev->power.pm_parent->power.power_state.event) { | ||
| 34 | dev_err(dev, "PM: resume from %d, parent %s still %d\n", | ||
| 35 | dev->power.power_state.event, | ||
| 36 | dev->power.pm_parent->bus_id, | ||
| 37 | dev->power.pm_parent->power.power_state.event); | ||
| 38 | } | ||
| 39 | |||
| 40 | if (dev->bus && dev->bus->resume) { | 32 | if (dev->bus && dev->bus->resume) { |
| 41 | dev_dbg(dev,"resuming\n"); | 33 | dev_dbg(dev,"resuming\n"); |
| 42 | error = dev->bus->resume(dev); | 34 | error = dev->bus->resume(dev); |
| @@ -80,7 +72,7 @@ static int resume_device_early(struct device * dev) | |||
| 80 | */ | 72 | */ |
| 81 | void dpm_resume(void) | 73 | void dpm_resume(void) |
| 82 | { | 74 | { |
| 83 | down(&dpm_list_sem); | 75 | mutex_lock(&dpm_list_mtx); |
| 84 | while(!list_empty(&dpm_off)) { | 76 | while(!list_empty(&dpm_off)) { |
| 85 | struct list_head * entry = dpm_off.next; | 77 | struct list_head * entry = dpm_off.next; |
| 86 | struct device * dev = to_device(entry); | 78 | struct device * dev = to_device(entry); |
| @@ -88,13 +80,12 @@ void dpm_resume(void) | |||
| 88 | get_device(dev); | 80 | get_device(dev); |
| 89 | list_move_tail(entry, &dpm_active); | 81 | list_move_tail(entry, &dpm_active); |
| 90 | 82 | ||
| 91 | up(&dpm_list_sem); | 83 | mutex_unlock(&dpm_list_mtx); |
| 92 | if (!dev->power.prev_state.event) | 84 | resume_device(dev); |
| 93 | resume_device(dev); | 85 | mutex_lock(&dpm_list_mtx); |
| 94 | down(&dpm_list_sem); | ||
| 95 | put_device(dev); | 86 | put_device(dev); |
| 96 | } | 87 | } |
| 97 | up(&dpm_list_sem); | 88 | mutex_unlock(&dpm_list_mtx); |
| 98 | } | 89 | } |
| 99 | 90 | ||
| 100 | 91 | ||
| @@ -108,9 +99,9 @@ void dpm_resume(void) | |||
| 108 | void device_resume(void) | 99 | void device_resume(void) |
| 109 | { | 100 | { |
| 110 | might_sleep(); | 101 | might_sleep(); |
| 111 | down(&dpm_sem); | 102 | mutex_lock(&dpm_mtx); |
| 112 | dpm_resume(); | 103 | dpm_resume(); |
| 113 | up(&dpm_sem); | 104 | mutex_unlock(&dpm_mtx); |
| 114 | } | 105 | } |
| 115 | 106 | ||
| 116 | EXPORT_SYMBOL_GPL(device_resume); | 107 | EXPORT_SYMBOL_GPL(device_resume); |
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 96370ec1d673..df6174d85866 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c | |||
| @@ -32,9 +32,9 @@ static void runtime_resume(struct device * dev) | |||
| 32 | 32 | ||
| 33 | void dpm_runtime_resume(struct device * dev) | 33 | void dpm_runtime_resume(struct device * dev) |
| 34 | { | 34 | { |
| 35 | down(&dpm_sem); | 35 | mutex_lock(&dpm_mtx); |
| 36 | runtime_resume(dev); | 36 | runtime_resume(dev); |
| 37 | up(&dpm_sem); | 37 | mutex_unlock(&dpm_mtx); |
| 38 | } | 38 | } |
| 39 | EXPORT_SYMBOL(dpm_runtime_resume); | 39 | EXPORT_SYMBOL(dpm_runtime_resume); |
| 40 | 40 | ||
| @@ -49,7 +49,7 @@ int dpm_runtime_suspend(struct device * dev, pm_message_t state) | |||
| 49 | { | 49 | { |
| 50 | int error = 0; | 50 | int error = 0; |
| 51 | 51 | ||
| 52 | down(&dpm_sem); | 52 | mutex_lock(&dpm_mtx); |
| 53 | if (dev->power.power_state.event == state.event) | 53 | if (dev->power.power_state.event == state.event) |
| 54 | goto Done; | 54 | goto Done; |
| 55 | 55 | ||
| @@ -59,7 +59,7 @@ int dpm_runtime_suspend(struct device * dev, pm_message_t state) | |||
| 59 | if (!(error = suspend_device(dev, state))) | 59 | if (!(error = suspend_device(dev, state))) |
| 60 | dev->power.power_state = state; | 60 | dev->power.power_state = state; |
| 61 | Done: | 61 | Done: |
| 62 | up(&dpm_sem); | 62 | mutex_unlock(&dpm_mtx); |
| 63 | return error; | 63 | return error; |
| 64 | } | 64 | } |
| 65 | EXPORT_SYMBOL(dpm_runtime_suspend); | 65 | EXPORT_SYMBOL(dpm_runtime_suspend); |
| @@ -78,8 +78,8 @@ EXPORT_SYMBOL(dpm_runtime_suspend); | |||
| 78 | */ | 78 | */ |
| 79 | void dpm_set_power_state(struct device * dev, pm_message_t state) | 79 | void dpm_set_power_state(struct device * dev, pm_message_t state) |
| 80 | { | 80 | { |
| 81 | down(&dpm_sem); | 81 | mutex_lock(&dpm_mtx); |
| 82 | dev->power.power_state = state; | 82 | dev->power.power_state = state; |
| 83 | up(&dpm_sem); | 83 | mutex_unlock(&dpm_mtx); |
| 84 | } | 84 | } |
| 85 | #endif /* 0 */ | 85 | #endif /* 0 */ |
diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c index 42d2b86ba765..26df9b231737 100644 --- a/drivers/base/power/suspend.c +++ b/drivers/base/power/suspend.c | |||
| @@ -40,6 +40,14 @@ static inline char *suspend_verb(u32 event) | |||
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | 42 | ||
| 43 | static void | ||
| 44 | suspend_device_dbg(struct device *dev, pm_message_t state, char *info) | ||
| 45 | { | ||
| 46 | dev_dbg(dev, "%s%s%s\n", info, suspend_verb(state.event), | ||
| 47 | ((state.event == PM_EVENT_SUSPEND) && device_may_wakeup(dev)) ? | ||
| 48 | ", may wakeup" : ""); | ||
| 49 | } | ||
| 50 | |||
| 43 | /** | 51 | /** |
| 44 | * suspend_device - Save state of one device. | 52 | * suspend_device - Save state of one device. |
| 45 | * @dev: Device. | 53 | * @dev: Device. |
| @@ -55,49 +63,21 @@ int suspend_device(struct device * dev, pm_message_t state) | |||
| 55 | dev_dbg(dev, "PM: suspend %d-->%d\n", | 63 | dev_dbg(dev, "PM: suspend %d-->%d\n", |
| 56 | dev->power.power_state.event, state.event); | 64 | dev->power.power_state.event, state.event); |
| 57 | } | 65 | } |
| 58 | if (dev->power.pm_parent | ||
| 59 | && dev->power.pm_parent->power.power_state.event) { | ||
| 60 | dev_err(dev, | ||
| 61 | "PM: suspend %d->%d, parent %s already %d\n", | ||
| 62 | dev->power.power_state.event, state.event, | ||
| 63 | dev->power.pm_parent->bus_id, | ||
| 64 | dev->power.pm_parent->power.power_state.event); | ||
| 65 | } | ||
| 66 | |||
| 67 | dev->power.prev_state = dev->power.power_state; | ||
| 68 | 66 | ||
| 69 | if (dev->class && dev->class->suspend && !dev->power.power_state.event) { | 67 | if (dev->class && dev->class->suspend) { |
| 70 | dev_dbg(dev, "class %s%s\n", | 68 | suspend_device_dbg(dev, state, "class "); |
| 71 | suspend_verb(state.event), | ||
| 72 | ((state.event == PM_EVENT_SUSPEND) | ||
| 73 | && device_may_wakeup(dev)) | ||
| 74 | ? ", may wakeup" | ||
| 75 | : "" | ||
| 76 | ); | ||
| 77 | error = dev->class->suspend(dev, state); | 69 | error = dev->class->suspend(dev, state); |
| 78 | suspend_report_result(dev->class->suspend, error); | 70 | suspend_report_result(dev->class->suspend, error); |
| 79 | } | 71 | } |
| 80 | 72 | ||
| 81 | if (!error && dev->type && dev->type->suspend && !dev->power.power_state.event) { | 73 | if (!error && dev->type && dev->type->suspend) { |
| 82 | dev_dbg(dev, "%s%s\n", | 74 | suspend_device_dbg(dev, state, "type "); |
| 83 | suspend_verb(state.event), | ||
| 84 | ((state.event == PM_EVENT_SUSPEND) | ||
| 85 | && device_may_wakeup(dev)) | ||
| 86 | ? ", may wakeup" | ||
| 87 | : "" | ||
| 88 | ); | ||
| 89 | error = dev->type->suspend(dev, state); | 75 | error = dev->type->suspend(dev, state); |
| 90 | suspend_report_result(dev->type->suspend, error); | 76 | suspend_report_result(dev->type->suspend, error); |
| 91 | } | 77 | } |
| 92 | 78 | ||
| 93 | if (!error && dev->bus && dev->bus->suspend && !dev->power.power_state.event) { | 79 | if (!error && dev->bus && dev->bus->suspend) { |
| 94 | dev_dbg(dev, "%s%s\n", | 80 | suspend_device_dbg(dev, state, ""); |
| 95 | suspend_verb(state.event), | ||
| 96 | ((state.event == PM_EVENT_SUSPEND) | ||
| 97 | && device_may_wakeup(dev)) | ||
| 98 | ? ", may wakeup" | ||
| 99 | : "" | ||
| 100 | ); | ||
| 101 | error = dev->bus->suspend(dev, state); | 81 | error = dev->bus->suspend(dev, state); |
| 102 | suspend_report_result(dev->bus->suspend, error); | 82 | suspend_report_result(dev->bus->suspend, error); |
| 103 | } | 83 | } |
| @@ -108,21 +88,15 @@ int suspend_device(struct device * dev, pm_message_t state) | |||
| 108 | 88 | ||
| 109 | /* | 89 | /* |
| 110 | * This is called with interrupts off, only a single CPU | 90 | * This is called with interrupts off, only a single CPU |
| 111 | * running. We can't do down() on a semaphore (and we don't | 91 | * running. We can't acquire a mutex or semaphore (and we don't |
| 112 | * need the protection) | 92 | * need the protection) |
| 113 | */ | 93 | */ |
| 114 | static int suspend_device_late(struct device *dev, pm_message_t state) | 94 | static int suspend_device_late(struct device *dev, pm_message_t state) |
| 115 | { | 95 | { |
| 116 | int error = 0; | 96 | int error = 0; |
| 117 | 97 | ||
| 118 | if (dev->bus && dev->bus->suspend_late && !dev->power.power_state.event) { | 98 | if (dev->bus && dev->bus->suspend_late) { |
| 119 | dev_dbg(dev, "LATE %s%s\n", | 99 | suspend_device_dbg(dev, state, "LATE "); |
| 120 | suspend_verb(state.event), | ||
| 121 | ((state.event == PM_EVENT_SUSPEND) | ||
| 122 | && device_may_wakeup(dev)) | ||
| 123 | ? ", may wakeup" | ||
| 124 | : "" | ||
| 125 | ); | ||
| 126 | error = dev->bus->suspend_late(dev, state); | 100 | error = dev->bus->suspend_late(dev, state); |
| 127 | suspend_report_result(dev->bus->suspend_late, error); | 101 | suspend_report_result(dev->bus->suspend_late, error); |
| 128 | } | 102 | } |
| @@ -153,18 +127,18 @@ int device_suspend(pm_message_t state) | |||
| 153 | int error = 0; | 127 | int error = 0; |
| 154 | 128 | ||
| 155 | might_sleep(); | 129 | might_sleep(); |
| 156 | down(&dpm_sem); | 130 | mutex_lock(&dpm_mtx); |
| 157 | down(&dpm_list_sem); | 131 | mutex_lock(&dpm_list_mtx); |
| 158 | while (!list_empty(&dpm_active) && error == 0) { | 132 | while (!list_empty(&dpm_active) && error == 0) { |
| 159 | struct list_head * entry = dpm_active.prev; | 133 | struct list_head * entry = dpm_active.prev; |
| 160 | struct device * dev = to_device(entry); | 134 | struct device * dev = to_device(entry); |
| 161 | 135 | ||
| 162 | get_device(dev); | 136 | get_device(dev); |
| 163 | up(&dpm_list_sem); | 137 | mutex_unlock(&dpm_list_mtx); |
| 164 | 138 | ||
| 165 | error = suspend_device(dev, state); | 139 | error = suspend_device(dev, state); |
| 166 | 140 | ||
| 167 | down(&dpm_list_sem); | 141 | mutex_lock(&dpm_list_mtx); |
| 168 | 142 | ||
| 169 | /* Check if the device got removed */ | 143 | /* Check if the device got removed */ |
| 170 | if (!list_empty(&dev->power.entry)) { | 144 | if (!list_empty(&dev->power.entry)) { |
| @@ -179,11 +153,11 @@ int device_suspend(pm_message_t state) | |||
| 179 | error == -EAGAIN ? " (please convert to suspend_late)" : ""); | 153 | error == -EAGAIN ? " (please convert to suspend_late)" : ""); |
| 180 | put_device(dev); | 154 | put_device(dev); |
| 181 | } | 155 | } |
| 182 | up(&dpm_list_sem); | 156 | mutex_unlock(&dpm_list_mtx); |
| 183 | if (error) | 157 | if (error) |
| 184 | dpm_resume(); | 158 | dpm_resume(); |
| 185 | 159 | ||
| 186 | up(&dpm_sem); | 160 | mutex_unlock(&dpm_mtx); |
| 187 | return error; | 161 | return error; |
| 188 | } | 162 | } |
| 189 | 163 | ||
diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 29f1291966c1..18febe26caa1 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c | |||
| @@ -21,7 +21,7 @@ | |||
| 21 | #include <linux/string.h> | 21 | #include <linux/string.h> |
| 22 | #include <linux/pm.h> | 22 | #include <linux/pm.h> |
| 23 | #include <linux/device.h> | 23 | #include <linux/device.h> |
| 24 | #include <asm/semaphore.h> | 24 | #include <linux/mutex.h> |
| 25 | 25 | ||
| 26 | #include "base.h" | 26 | #include "base.h" |
| 27 | 27 | ||
| @@ -155,7 +155,7 @@ EXPORT_SYMBOL_GPL(sysdev_class_unregister); | |||
| 155 | 155 | ||
| 156 | 156 | ||
| 157 | static LIST_HEAD(sysdev_drivers); | 157 | static LIST_HEAD(sysdev_drivers); |
| 158 | static DECLARE_MUTEX(sysdev_drivers_lock); | 158 | static DEFINE_MUTEX(sysdev_drivers_lock); |
| 159 | 159 | ||
| 160 | /** | 160 | /** |
| 161 | * sysdev_driver_register - Register auxillary driver | 161 | * sysdev_driver_register - Register auxillary driver |
| @@ -172,7 +172,7 @@ static DECLARE_MUTEX(sysdev_drivers_lock); | |||
| 172 | int sysdev_driver_register(struct sysdev_class * cls, | 172 | int sysdev_driver_register(struct sysdev_class * cls, |
| 173 | struct sysdev_driver * drv) | 173 | struct sysdev_driver * drv) |
| 174 | { | 174 | { |
| 175 | down(&sysdev_drivers_lock); | 175 | mutex_lock(&sysdev_drivers_lock); |
| 176 | if (cls && kset_get(&cls->kset)) { | 176 | if (cls && kset_get(&cls->kset)) { |
| 177 | list_add_tail(&drv->entry, &cls->drivers); | 177 | list_add_tail(&drv->entry, &cls->drivers); |
| 178 | 178 | ||
| @@ -184,7 +184,7 @@ int sysdev_driver_register(struct sysdev_class * cls, | |||
| 184 | } | 184 | } |
| 185 | } else | 185 | } else |
| 186 | list_add_tail(&drv->entry, &sysdev_drivers); | 186 | list_add_tail(&drv->entry, &sysdev_drivers); |
| 187 | up(&sysdev_drivers_lock); | 187 | mutex_unlock(&sysdev_drivers_lock); |
| 188 | return 0; | 188 | return 0; |
| 189 | } | 189 | } |
| 190 | 190 | ||
| @@ -197,7 +197,7 @@ int sysdev_driver_register(struct sysdev_class * cls, | |||
| 197 | void sysdev_driver_unregister(struct sysdev_class * cls, | 197 | void sysdev_driver_unregister(struct sysdev_class * cls, |
| 198 | struct sysdev_driver * drv) | 198 | struct sysdev_driver * drv) |
| 199 | { | 199 | { |
| 200 | down(&sysdev_drivers_lock); | 200 | mutex_lock(&sysdev_drivers_lock); |
| 201 | list_del_init(&drv->entry); | 201 | list_del_init(&drv->entry); |
| 202 | if (cls) { | 202 | if (cls) { |
| 203 | if (drv->remove) { | 203 | if (drv->remove) { |
| @@ -207,7 +207,7 @@ void sysdev_driver_unregister(struct sysdev_class * cls, | |||
| 207 | } | 207 | } |
| 208 | kset_put(&cls->kset); | 208 | kset_put(&cls->kset); |
| 209 | } | 209 | } |
| 210 | up(&sysdev_drivers_lock); | 210 | mutex_unlock(&sysdev_drivers_lock); |
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | EXPORT_SYMBOL_GPL(sysdev_driver_register); | 213 | EXPORT_SYMBOL_GPL(sysdev_driver_register); |
| @@ -246,7 +246,7 @@ int sysdev_register(struct sys_device * sysdev) | |||
| 246 | if (!error) { | 246 | if (!error) { |
| 247 | struct sysdev_driver * drv; | 247 | struct sysdev_driver * drv; |
| 248 | 248 | ||
| 249 | down(&sysdev_drivers_lock); | 249 | mutex_lock(&sysdev_drivers_lock); |
| 250 | /* Generic notification is implicit, because it's that | 250 | /* Generic notification is implicit, because it's that |
| 251 | * code that should have called us. | 251 | * code that should have called us. |
| 252 | */ | 252 | */ |
| @@ -262,7 +262,7 @@ int sysdev_register(struct sys_device * sysdev) | |||
| 262 | if (drv->add) | 262 | if (drv->add) |
| 263 | drv->add(sysdev); | 263 | drv->add(sysdev); |
| 264 | } | 264 | } |
| 265 | up(&sysdev_drivers_lock); | 265 | mutex_unlock(&sysdev_drivers_lock); |
| 266 | } | 266 | } |
| 267 | return error; | 267 | return error; |
| 268 | } | 268 | } |
| @@ -271,7 +271,7 @@ void sysdev_unregister(struct sys_device * sysdev) | |||
| 271 | { | 271 | { |
| 272 | struct sysdev_driver * drv; | 272 | struct sysdev_driver * drv; |
| 273 | 273 | ||
| 274 | down(&sysdev_drivers_lock); | 274 | mutex_lock(&sysdev_drivers_lock); |
| 275 | list_for_each_entry(drv, &sysdev_drivers, entry) { | 275 | list_for_each_entry(drv, &sysdev_drivers, entry) { |
| 276 | if (drv->remove) | 276 | if (drv->remove) |
| 277 | drv->remove(sysdev); | 277 | drv->remove(sysdev); |
| @@ -281,7 +281,7 @@ void sysdev_unregister(struct sys_device * sysdev) | |||
| 281 | if (drv->remove) | 281 | if (drv->remove) |
| 282 | drv->remove(sysdev); | 282 | drv->remove(sysdev); |
| 283 | } | 283 | } |
| 284 | up(&sysdev_drivers_lock); | 284 | mutex_unlock(&sysdev_drivers_lock); |
| 285 | 285 | ||
| 286 | kobject_unregister(&sysdev->kobj); | 286 | kobject_unregister(&sysdev->kobj); |
| 287 | } | 287 | } |
| @@ -308,7 +308,7 @@ void sysdev_shutdown(void) | |||
| 308 | 308 | ||
| 309 | pr_debug("Shutting Down System Devices\n"); | 309 | pr_debug("Shutting Down System Devices\n"); |
| 310 | 310 | ||
| 311 | down(&sysdev_drivers_lock); | 311 | mutex_lock(&sysdev_drivers_lock); |
| 312 | list_for_each_entry_reverse(cls, &system_subsys.list, | 312 | list_for_each_entry_reverse(cls, &system_subsys.list, |
| 313 | kset.kobj.entry) { | 313 | kset.kobj.entry) { |
| 314 | struct sys_device * sysdev; | 314 | struct sys_device * sysdev; |
| @@ -337,7 +337,7 @@ void sysdev_shutdown(void) | |||
| 337 | cls->shutdown(sysdev); | 337 | cls->shutdown(sysdev); |
| 338 | } | 338 | } |
| 339 | } | 339 | } |
| 340 | up(&sysdev_drivers_lock); | 340 | mutex_unlock(&sysdev_drivers_lock); |
| 341 | } | 341 | } |
| 342 | 342 | ||
| 343 | static void __sysdev_resume(struct sys_device *dev) | 343 | static void __sysdev_resume(struct sys_device *dev) |
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index f1b9dd7d47d6..ce64e86d6ffb 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c | |||
| @@ -146,8 +146,7 @@ static void pkt_kobj_release(struct kobject *kobj) | |||
| 146 | **********************************************************/ | 146 | **********************************************************/ |
| 147 | 147 | ||
| 148 | #define DEF_ATTR(_obj,_name,_mode) \ | 148 | #define DEF_ATTR(_obj,_name,_mode) \ |
| 149 | static struct attribute _obj = { \ | 149 | static struct attribute _obj = { .name = _name, .mode = _mode } |
| 150 | .name = _name, .owner = THIS_MODULE, .mode = _mode } | ||
| 151 | 150 | ||
| 152 | /********************************************************** | 151 | /********************************************************** |
| 153 | /sys/class/pktcdvd/pktcdvd[0-7]/ | 152 | /sys/class/pktcdvd/pktcdvd[0-7]/ |
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 8e222f2b80cc..b5df7e61aeb2 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
| @@ -2171,52 +2171,42 @@ static int create_files(struct bmc_device *bmc) | |||
| 2171 | int err; | 2171 | int err; |
| 2172 | 2172 | ||
| 2173 | bmc->device_id_attr.attr.name = "device_id"; | 2173 | bmc->device_id_attr.attr.name = "device_id"; |
| 2174 | bmc->device_id_attr.attr.owner = THIS_MODULE; | ||
| 2175 | bmc->device_id_attr.attr.mode = S_IRUGO; | 2174 | bmc->device_id_attr.attr.mode = S_IRUGO; |
| 2176 | bmc->device_id_attr.show = device_id_show; | 2175 | bmc->device_id_attr.show = device_id_show; |
| 2177 | 2176 | ||
| 2178 | bmc->provides_dev_sdrs_attr.attr.name = "provides_device_sdrs"; | 2177 | bmc->provides_dev_sdrs_attr.attr.name = "provides_device_sdrs"; |
| 2179 | bmc->provides_dev_sdrs_attr.attr.owner = THIS_MODULE; | ||
| 2180 | bmc->provides_dev_sdrs_attr.attr.mode = S_IRUGO; | 2178 | bmc->provides_dev_sdrs_attr.attr.mode = S_IRUGO; |
| 2181 | bmc->provides_dev_sdrs_attr.show = provides_dev_sdrs_show; | 2179 | bmc->provides_dev_sdrs_attr.show = provides_dev_sdrs_show; |
| 2182 | 2180 | ||
| 2183 | bmc->revision_attr.attr.name = "revision"; | 2181 | bmc->revision_attr.attr.name = "revision"; |
| 2184 | bmc->revision_attr.attr.owner = THIS_MODULE; | ||
| 2185 | bmc->revision_attr.attr.mode = S_IRUGO; | 2182 | bmc->revision_attr.attr.mode = S_IRUGO; |
| 2186 | bmc->revision_attr.show = revision_show; | 2183 | bmc->revision_attr.show = revision_show; |
| 2187 | 2184 | ||
| 2188 | bmc->firmware_rev_attr.attr.name = "firmware_revision"; | 2185 | bmc->firmware_rev_attr.attr.name = "firmware_revision"; |
| 2189 | bmc->firmware_rev_attr.attr.owner = THIS_MODULE; | ||
| 2190 | bmc->firmware_rev_attr.attr.mode = S_IRUGO; | 2186 | bmc->firmware_rev_attr.attr.mode = S_IRUGO; |
| 2191 | bmc->firmware_rev_attr.show = firmware_rev_show; | 2187 | bmc->firmware_rev_attr.show = firmware_rev_show; |
| 2192 | 2188 | ||
| 2193 | bmc->version_attr.attr.name = "ipmi_version"; | 2189 | bmc->version_attr.attr.name = "ipmi_version"; |
| 2194 | bmc->version_attr.attr.owner = THIS_MODULE; | ||
| 2195 | bmc->version_attr.attr.mode = S_IRUGO; | 2190 | bmc->version_attr.attr.mode = S_IRUGO; |
| 2196 | bmc->version_attr.show = ipmi_version_show; | 2191 | bmc->version_attr.show = ipmi_version_show; |
| 2197 | 2192 | ||
| 2198 | bmc->add_dev_support_attr.attr.name = "additional_device_support"; | 2193 | bmc->add_dev_support_attr.attr.name = "additional_device_support"; |
| 2199 | bmc->add_dev_support_attr.attr.owner = THIS_MODULE; | ||
| 2200 | bmc->add_dev_support_attr.attr.mode = S_IRUGO; | 2194 | bmc->add_dev_support_attr.attr.mode = S_IRUGO; |
| 2201 | bmc->add_dev_support_attr.show = add_dev_support_show; | 2195 | bmc->add_dev_support_attr.show = add_dev_support_show; |
| 2202 | 2196 | ||
| 2203 | bmc->manufacturer_id_attr.attr.name = "manufacturer_id"; | 2197 | bmc->manufacturer_id_attr.attr.name = "manufacturer_id"; |
| 2204 | bmc->manufacturer_id_attr.attr.owner = THIS_MODULE; | ||
| 2205 | bmc->manufacturer_id_attr.attr.mode = S_IRUGO; | 2198 | bmc->manufacturer_id_attr.attr.mode = S_IRUGO; |
| 2206 | bmc->manufacturer_id_attr.show = manufacturer_id_show; | 2199 | bmc->manufacturer_id_attr.show = manufacturer_id_show; |
| 2207 | 2200 | ||
| 2208 | bmc->product_id_attr.attr.name = "product_id"; | 2201 | bmc->product_id_attr.attr.name = "product_id"; |
| 2209 | bmc->product_id_attr.attr.owner = THIS_MODULE; | ||
| 2210 | bmc->product_id_attr.attr.mode = S_IRUGO; | 2202 | bmc->product_id_attr.attr.mode = S_IRUGO; |
| 2211 | bmc->product_id_attr.show = product_id_show; | 2203 | bmc->product_id_attr.show = product_id_show; |
| 2212 | 2204 | ||
| 2213 | bmc->guid_attr.attr.name = "guid"; | 2205 | bmc->guid_attr.attr.name = "guid"; |
| 2214 | bmc->guid_attr.attr.owner = THIS_MODULE; | ||
| 2215 | bmc->guid_attr.attr.mode = S_IRUGO; | 2206 | bmc->guid_attr.attr.mode = S_IRUGO; |
| 2216 | bmc->guid_attr.show = guid_show; | 2207 | bmc->guid_attr.show = guid_show; |
| 2217 | 2208 | ||
| 2218 | bmc->aux_firmware_rev_attr.attr.name = "aux_firmware_revision"; | 2209 | bmc->aux_firmware_rev_attr.attr.name = "aux_firmware_revision"; |
| 2219 | bmc->aux_firmware_rev_attr.attr.owner = THIS_MODULE; | ||
| 2220 | bmc->aux_firmware_rev_attr.attr.mode = S_IRUGO; | 2210 | bmc->aux_firmware_rev_attr.attr.mode = S_IRUGO; |
| 2221 | bmc->aux_firmware_rev_attr.show = aux_firmware_rev_show; | 2211 | bmc->aux_firmware_rev_attr.show = aux_firmware_rev_show; |
| 2222 | 2212 | ||
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index d2f0cbd8b8f3..917b9bab9ccb 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c | |||
| @@ -25,8 +25,7 @@ static spinlock_t cpufreq_stats_lock; | |||
| 25 | 25 | ||
| 26 | #define CPUFREQ_STATDEVICE_ATTR(_name,_mode,_show) \ | 26 | #define CPUFREQ_STATDEVICE_ATTR(_name,_mode,_show) \ |
| 27 | static struct freq_attr _attr_##_name = {\ | 27 | static struct freq_attr _attr_##_name = {\ |
| 28 | .attr = {.name = __stringify(_name), .owner = THIS_MODULE, \ | 28 | .attr = {.name = __stringify(_name), .mode = _mode, }, \ |
| 29 | .mode = _mode, }, \ | ||
| 30 | .show = _show,\ | 29 | .show = _show,\ |
| 31 | }; | 30 | }; |
| 32 | 31 | ||
diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c index 860345c7799a..a648970338b0 100644 --- a/drivers/cpufreq/cpufreq_userspace.c +++ b/drivers/cpufreq/cpufreq_userspace.c | |||
| @@ -120,7 +120,7 @@ store_speed (struct cpufreq_policy *policy, const char *buf, size_t count) | |||
| 120 | 120 | ||
| 121 | static struct freq_attr freq_attr_scaling_setspeed = | 121 | static struct freq_attr freq_attr_scaling_setspeed = |
| 122 | { | 122 | { |
| 123 | .attr = { .name = "scaling_setspeed", .mode = 0644, .owner = THIS_MODULE }, | 123 | .attr = { .name = "scaling_setspeed", .mode = 0644 }, |
| 124 | .show = show_speed, | 124 | .show = show_speed, |
| 125 | .store = store_speed, | 125 | .store = store_speed, |
| 126 | }; | 126 | }; |
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c index e7490925fdcf..5409f3afb3f8 100644 --- a/drivers/cpufreq/freq_table.c +++ b/drivers/cpufreq/freq_table.c | |||
| @@ -199,7 +199,6 @@ static ssize_t show_available_freqs (struct cpufreq_policy *policy, char *buf) | |||
| 199 | struct freq_attr cpufreq_freq_attr_scaling_available_freqs = { | 199 | struct freq_attr cpufreq_freq_attr_scaling_available_freqs = { |
| 200 | .attr = { .name = "scaling_available_frequencies", | 200 | .attr = { .name = "scaling_available_frequencies", |
| 201 | .mode = 0444, | 201 | .mode = 0444, |
| 202 | .owner=THIS_MODULE | ||
| 203 | }, | 202 | }, |
| 204 | .show = show_available_freqs, | 203 | .show = show_available_freqs, |
| 205 | }; | 204 | }; |
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 88f462122a30..05f02a326f1c 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig | |||
| @@ -84,4 +84,13 @@ config DCDBAS | |||
| 84 | Say Y or M here to enable the driver for use by Dell systems | 84 | Say Y or M here to enable the driver for use by Dell systems |
| 85 | management software such as Dell OpenManage. | 85 | management software such as Dell OpenManage. |
| 86 | 86 | ||
| 87 | config DMIID | ||
| 88 | bool "Export DMI identification via sysfs to userspace" | ||
| 89 | depends on DMI | ||
| 90 | default y | ||
| 91 | help | ||
| 92 | Say Y here if you want to query SMBIOS/DMI system identification | ||
| 93 | information from userspace through /sys/class/dmi/id/ or if you want | ||
| 94 | DMI-based module auto-loading. | ||
| 95 | |||
| 87 | endmenu | 96 | endmenu |
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile index 98e395f4bb29..8d4ebc805a50 100644 --- a/drivers/firmware/Makefile +++ b/drivers/firmware/Makefile | |||
| @@ -7,3 +7,4 @@ obj-$(CONFIG_EFI_VARS) += efivars.o | |||
| 7 | obj-$(CONFIG_EFI_PCDP) += pcdp.o | 7 | obj-$(CONFIG_EFI_PCDP) += pcdp.o |
| 8 | obj-$(CONFIG_DELL_RBU) += dell_rbu.o | 8 | obj-$(CONFIG_DELL_RBU) += dell_rbu.o |
| 9 | obj-$(CONFIG_DCDBAS) += dcdbas.o | 9 | obj-$(CONFIG_DCDBAS) += dcdbas.o |
| 10 | obj-$(CONFIG_DMIID) += dmi-id.o | ||
diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c index 1865b56fb141..18cdcb3ae1ca 100644 --- a/drivers/firmware/dcdbas.c +++ b/drivers/firmware/dcdbas.c | |||
| @@ -149,8 +149,9 @@ static ssize_t smi_data_buf_size_store(struct device *dev, | |||
| 149 | return count; | 149 | return count; |
| 150 | } | 150 | } |
| 151 | 151 | ||
| 152 | static ssize_t smi_data_read(struct kobject *kobj, char *buf, loff_t pos, | 152 | static ssize_t smi_data_read(struct kobject *kobj, |
| 153 | size_t count) | 153 | struct bin_attribute *bin_attr, |
| 154 | char *buf, loff_t pos, size_t count) | ||
| 154 | { | 155 | { |
| 155 | size_t max_read; | 156 | size_t max_read; |
| 156 | ssize_t ret; | 157 | ssize_t ret; |
| @@ -170,8 +171,9 @@ out: | |||
| 170 | return ret; | 171 | return ret; |
| 171 | } | 172 | } |
| 172 | 173 | ||
| 173 | static ssize_t smi_data_write(struct kobject *kobj, char *buf, loff_t pos, | 174 | static ssize_t smi_data_write(struct kobject *kobj, |
| 174 | size_t count) | 175 | struct bin_attribute *bin_attr, |
| 176 | char *buf, loff_t pos, size_t count) | ||
| 175 | { | 177 | { |
| 176 | ssize_t ret; | 178 | ssize_t ret; |
| 177 | 179 | ||
diff --git a/drivers/firmware/dcdbas.h b/drivers/firmware/dcdbas.h index 58a85182b3e8..dcdba0f1b32c 100644 --- a/drivers/firmware/dcdbas.h +++ b/drivers/firmware/dcdbas.h | |||
| @@ -67,8 +67,7 @@ | |||
| 67 | #define DCDBAS_BIN_ATTR_RW(_name) \ | 67 | #define DCDBAS_BIN_ATTR_RW(_name) \ |
| 68 | struct bin_attribute bin_attr_##_name = { \ | 68 | struct bin_attribute bin_attr_##_name = { \ |
| 69 | .attr = { .name = __stringify(_name), \ | 69 | .attr = { .name = __stringify(_name), \ |
| 70 | .mode = 0600, \ | 70 | .mode = 0600 }, \ |
| 71 | .owner = THIS_MODULE }, \ | ||
| 72 | .read = _name##_read, \ | 71 | .read = _name##_read, \ |
| 73 | .write = _name##_write, \ | 72 | .write = _name##_write, \ |
| 74 | } | 73 | } |
diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c index fc702e40bd43..477a3d0e3caf 100644 --- a/drivers/firmware/dell_rbu.c +++ b/drivers/firmware/dell_rbu.c | |||
| @@ -543,8 +543,9 @@ static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count) | |||
| 543 | return ret_count; | 543 | return ret_count; |
| 544 | } | 544 | } |
| 545 | 545 | ||
| 546 | static ssize_t read_rbu_data(struct kobject *kobj, char *buffer, | 546 | static ssize_t read_rbu_data(struct kobject *kobj, |
| 547 | loff_t pos, size_t count) | 547 | struct bin_attribute *bin_attr, |
| 548 | char *buffer, loff_t pos, size_t count) | ||
| 548 | { | 549 | { |
| 549 | ssize_t ret_count = 0; | 550 | ssize_t ret_count = 0; |
| 550 | 551 | ||
| @@ -591,8 +592,9 @@ static void callbackfn_rbu(const struct firmware *fw, void *context) | |||
| 591 | spin_unlock(&rbu_data.lock); | 592 | spin_unlock(&rbu_data.lock); |
| 592 | } | 593 | } |
| 593 | 594 | ||
| 594 | static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer, | 595 | static ssize_t read_rbu_image_type(struct kobject *kobj, |
| 595 | loff_t pos, size_t count) | 596 | struct bin_attribute *bin_attr, |
| 597 | char *buffer, loff_t pos, size_t count) | ||
| 596 | { | 598 | { |
| 597 | int size = 0; | 599 | int size = 0; |
| 598 | if (!pos) | 600 | if (!pos) |
| @@ -600,8 +602,9 @@ static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer, | |||
| 600 | return size; | 602 | return size; |
| 601 | } | 603 | } |
| 602 | 604 | ||
| 603 | static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer, | 605 | static ssize_t write_rbu_image_type(struct kobject *kobj, |
| 604 | loff_t pos, size_t count) | 606 | struct bin_attribute *bin_attr, |
| 607 | char *buffer, loff_t pos, size_t count) | ||
| 605 | { | 608 | { |
| 606 | int rc = count; | 609 | int rc = count; |
| 607 | int req_firm_rc = 0; | 610 | int req_firm_rc = 0; |
| @@ -660,8 +663,9 @@ static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer, | |||
| 660 | return rc; | 663 | return rc; |
| 661 | } | 664 | } |
| 662 | 665 | ||
| 663 | static ssize_t read_rbu_packet_size(struct kobject *kobj, char *buffer, | 666 | static ssize_t read_rbu_packet_size(struct kobject *kobj, |
| 664 | loff_t pos, size_t count) | 667 | struct bin_attribute *bin_attr, |
| 668 | char *buffer, loff_t pos, size_t count) | ||
| 665 | { | 669 | { |
| 666 | int size = 0; | 670 | int size = 0; |
| 667 | if (!pos) { | 671 | if (!pos) { |
| @@ -672,8 +676,9 @@ static ssize_t read_rbu_packet_size(struct kobject *kobj, char *buffer, | |||
| 672 | return size; | 676 | return size; |
| 673 | } | 677 | } |
| 674 | 678 | ||
| 675 | static ssize_t write_rbu_packet_size(struct kobject *kobj, char *buffer, | 679 | static ssize_t write_rbu_packet_size(struct kobject *kobj, |
| 676 | loff_t pos, size_t count) | 680 | struct bin_attribute *bin_attr, |
| 681 | char *buffer, loff_t pos, size_t count) | ||
| 677 | { | 682 | { |
| 678 | unsigned long temp; | 683 | unsigned long temp; |
| 679 | spin_lock(&rbu_data.lock); | 684 | spin_lock(&rbu_data.lock); |
| @@ -687,18 +692,18 @@ static ssize_t write_rbu_packet_size(struct kobject *kobj, char *buffer, | |||
| 687 | } | 692 | } |
| 688 | 693 | ||
| 689 | static struct bin_attribute rbu_data_attr = { | 694 | static struct bin_attribute rbu_data_attr = { |
| 690 | .attr = {.name = "data",.owner = THIS_MODULE,.mode = 0444}, | 695 | .attr = {.name = "data", .mode = 0444}, |
| 691 | .read = read_rbu_data, | 696 | .read = read_rbu_data, |
| 692 | }; | 697 | }; |
| 693 | 698 | ||
| 694 | static struct bin_attribute rbu_image_type_attr = { | 699 | static struct bin_attribute rbu_image_type_attr = { |
| 695 | .attr = {.name = "image_type",.owner = THIS_MODULE,.mode = 0644}, | 700 | .attr = {.name = "image_type", .mode = 0644}, |
| 696 | .read = read_rbu_image_type, | 701 | .read = read_rbu_image_type, |
| 697 | .write = write_rbu_image_type, | 702 | .write = write_rbu_image_type, |
| 698 | }; | 703 | }; |
| 699 | 704 | ||
| 700 | static struct bin_attribute rbu_packet_size_attr = { | 705 | static struct bin_attribute rbu_packet_size_attr = { |
| 701 | .attr = {.name = "packet_size",.owner = THIS_MODULE,.mode = 0644}, | 706 | .attr = {.name = "packet_size", .mode = 0644}, |
| 702 | .read = read_rbu_packet_size, | 707 | .read = read_rbu_packet_size, |
| 703 | .write = write_rbu_packet_size, | 708 | .write = write_rbu_packet_size, |
| 704 | }; | 709 | }; |
diff --git a/drivers/firmware/dmi-id.c b/drivers/firmware/dmi-id.c new file mode 100644 index 000000000000..59c3b5aa89f4 --- /dev/null +++ b/drivers/firmware/dmi-id.c | |||
| @@ -0,0 +1,222 @@ | |||
| 1 | /* | ||
| 2 | * Export SMBIOS/DMI info via sysfs to userspace | ||
| 3 | * | ||
| 4 | * Copyright 2007, Lennart Poettering | ||
| 5 | * | ||
| 6 | * Licensed under GPLv2 | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/module.h> | ||
| 10 | #include <linux/kernel.h> | ||
| 11 | #include <linux/init.h> | ||
| 12 | #include <linux/dmi.h> | ||
| 13 | #include <linux/device.h> | ||
| 14 | #include <linux/autoconf.h> | ||
| 15 | |||
| 16 | #define DEFINE_DMI_ATTR(_name, _mode, _show) \ | ||
| 17 | static struct device_attribute sys_dmi_##_name##_attr = \ | ||
| 18 | __ATTR(_name, _mode, _show, NULL); | ||
| 19 | |||
| 20 | #define DEFINE_DMI_ATTR_WITH_SHOW(_name, _mode, _field) \ | ||
| 21 | static ssize_t sys_dmi_##_name##_show(struct device *dev, \ | ||
| 22 | struct device_attribute *attr, \ | ||
| 23 | char *page) \ | ||
| 24 | { \ | ||
| 25 | ssize_t len; \ | ||
| 26 | len = scnprintf(page, PAGE_SIZE, "%s\n", dmi_get_system_info(_field)); \ | ||
| 27 | page[len-1] = '\n'; \ | ||
| 28 | return len; \ | ||
| 29 | } \ | ||
| 30 | DEFINE_DMI_ATTR(_name, _mode, sys_dmi_##_name##_show); | ||
| 31 | |||
| 32 | DEFINE_DMI_ATTR_WITH_SHOW(bios_vendor, 0444, DMI_BIOS_VENDOR); | ||
| 33 | DEFINE_DMI_ATTR_WITH_SHOW(bios_version, 0444, DMI_BIOS_VERSION); | ||
| 34 | DEFINE_DMI_ATTR_WITH_SHOW(bios_date, 0444, DMI_BIOS_DATE); | ||
| 35 | DEFINE_DMI_ATTR_WITH_SHOW(sys_vendor, 0444, DMI_SYS_VENDOR); | ||
| 36 | DEFINE_DMI_ATTR_WITH_SHOW(product_name, 0444, DMI_PRODUCT_NAME); | ||
| 37 | DEFINE_DMI_ATTR_WITH_SHOW(product_version, 0444, DMI_PRODUCT_VERSION); | ||
| 38 | DEFINE_DMI_ATTR_WITH_SHOW(product_serial, 0400, DMI_PRODUCT_SERIAL); | ||
| 39 | DEFINE_DMI_ATTR_WITH_SHOW(product_uuid, 0400, DMI_PRODUCT_UUID); | ||
| 40 | DEFINE_DMI_ATTR_WITH_SHOW(board_vendor, 0444, DMI_BOARD_VENDOR); | ||
| 41 | DEFINE_DMI_ATTR_WITH_SHOW(board_name, 0444, DMI_BOARD_NAME); | ||
| 42 | DEFINE_DMI_ATTR_WITH_SHOW(board_version, 0444, DMI_BOARD_VERSION); | ||
| 43 | DEFINE_DMI_ATTR_WITH_SHOW(board_serial, 0400, DMI_BOARD_SERIAL); | ||
| 44 | DEFINE_DMI_ATTR_WITH_SHOW(board_asset_tag, 0444, DMI_BOARD_ASSET_TAG); | ||
| 45 | DEFINE_DMI_ATTR_WITH_SHOW(chassis_vendor, 0444, DMI_CHASSIS_VENDOR); | ||
| 46 | DEFINE_DMI_ATTR_WITH_SHOW(chassis_type, 0444, DMI_CHASSIS_TYPE); | ||
| 47 | DEFINE_DMI_ATTR_WITH_SHOW(chassis_version, 0444, DMI_CHASSIS_VERSION); | ||
| 48 | DEFINE_DMI_ATTR_WITH_SHOW(chassis_serial, 0400, DMI_CHASSIS_SERIAL); | ||
| 49 | DEFINE_DMI_ATTR_WITH_SHOW(chassis_asset_tag, 0444, DMI_CHASSIS_ASSET_TAG); | ||
| 50 | |||
| 51 | static void ascii_filter(char *d, const char *s) | ||
| 52 | { | ||
| 53 | /* Filter out characters we don't want to see in the modalias string */ | ||
| 54 | for (; *s; s++) | ||
| 55 | if (*s > ' ' && *s < 127 && *s != ':') | ||
| 56 | *(d++) = *s; | ||
| 57 | |||
| 58 | *d = 0; | ||
| 59 | } | ||
| 60 | |||
| 61 | static ssize_t get_modalias(char *buffer, size_t buffer_size) | ||
| 62 | { | ||
| 63 | static const struct mafield { | ||
| 64 | const char *prefix; | ||
| 65 | int field; | ||
| 66 | } fields[] = { | ||
| 67 | { "bvn", DMI_BIOS_VENDOR }, | ||
| 68 | { "bvr", DMI_BIOS_VERSION }, | ||
| 69 | { "bd", DMI_BIOS_DATE }, | ||
| 70 | { "svn", DMI_SYS_VENDOR }, | ||
| 71 | { "pn", DMI_PRODUCT_NAME }, | ||
| 72 | { "pvr", DMI_PRODUCT_VERSION }, | ||
| 73 | { "rvn", DMI_BOARD_VENDOR }, | ||
| 74 | { "rn", DMI_BOARD_NAME }, | ||
| 75 | { "rvr", DMI_BOARD_VERSION }, | ||
| 76 | { "cvn", DMI_CHASSIS_VENDOR }, | ||
| 77 | { "ct", DMI_CHASSIS_TYPE }, | ||
| 78 | { "cvr", DMI_CHASSIS_VERSION }, | ||
| 79 | { NULL, DMI_NONE } | ||
| 80 | }; | ||
| 81 | |||
| 82 | ssize_t l, left; | ||
| 83 | char *p; | ||
| 84 | const struct mafield *f; | ||
| 85 | |||
| 86 | strcpy(buffer, "dmi"); | ||
| 87 | p = buffer + 3; left = buffer_size - 4; | ||
| 88 | |||
| 89 | for (f = fields; f->prefix && left > 0; f++) { | ||
| 90 | const char *c; | ||
| 91 | char *t; | ||
| 92 | |||
| 93 | c = dmi_get_system_info(f->field); | ||
| 94 | if (!c) | ||
| 95 | continue; | ||
| 96 | |||
| 97 | t = kmalloc(strlen(c) + 1, GFP_KERNEL); | ||
| 98 | if (!t) | ||
| 99 | break; | ||
| 100 | ascii_filter(t, c); | ||
| 101 | l = scnprintf(p, left, ":%s%s", f->prefix, t); | ||
| 102 | kfree(t); | ||
| 103 | |||
| 104 | p += l; | ||
| 105 | left -= l; | ||
| 106 | } | ||
| 107 | |||
| 108 | p[0] = ':'; | ||
| 109 | p[1] = 0; | ||
| 110 | |||
| 111 | return p - buffer + 1; | ||
| 112 | } | ||
| 113 | |||
| 114 | static ssize_t sys_dmi_modalias_show(struct device *dev, | ||
| 115 | struct device_attribute *attr, char *page) | ||
| 116 | { | ||
| 117 | ssize_t r; | ||
| 118 | r = get_modalias(page, PAGE_SIZE-1); | ||
| 119 | page[r] = '\n'; | ||
| 120 | page[r+1] = 0; | ||
| 121 | return r+1; | ||
| 122 | } | ||
| 123 | |||
| 124 | DEFINE_DMI_ATTR(modalias, 0444, sys_dmi_modalias_show); | ||
| 125 | |||
| 126 | static struct attribute *sys_dmi_attributes[DMI_STRING_MAX+2]; | ||
| 127 | |||
| 128 | static struct attribute_group sys_dmi_attribute_group = { | ||
| 129 | .attrs = sys_dmi_attributes, | ||
| 130 | }; | ||
| 131 | |||
| 132 | static struct attribute_group* sys_dmi_attribute_groups[] = { | ||
| 133 | &sys_dmi_attribute_group, | ||
| 134 | NULL | ||
| 135 | }; | ||
| 136 | |||
| 137 | static int dmi_dev_uevent(struct device *dev, char **envp, | ||
| 138 | int num_envp, char *buffer, int buffer_size) | ||
| 139 | { | ||
| 140 | strcpy(buffer, "MODALIAS="); | ||
| 141 | get_modalias(buffer+9, buffer_size-9); | ||
| 142 | envp[0] = buffer; | ||
| 143 | envp[1] = NULL; | ||
| 144 | |||
| 145 | return 0; | ||
| 146 | } | ||
| 147 | |||
| 148 | static struct class dmi_class = { | ||
| 149 | .name = "dmi", | ||
| 150 | .dev_release = (void(*)(struct device *)) kfree, | ||
| 151 | .dev_uevent = dmi_dev_uevent, | ||
| 152 | }; | ||
| 153 | |||
| 154 | static struct device *dmi_dev; | ||
| 155 | |||
| 156 | /* Initialization */ | ||
| 157 | |||
| 158 | #define ADD_DMI_ATTR(_name, _field) \ | ||
| 159 | if (dmi_get_system_info(_field)) \ | ||
| 160 | sys_dmi_attributes[i++] = & sys_dmi_##_name##_attr.attr; | ||
| 161 | |||
| 162 | extern int dmi_available; | ||
| 163 | |||
| 164 | static int __init dmi_id_init(void) | ||
| 165 | { | ||
| 166 | int ret, i; | ||
| 167 | |||
| 168 | if (!dmi_available) | ||
| 169 | return -ENODEV; | ||
| 170 | |||
| 171 | /* Not necessarily all DMI fields are available on all | ||
| 172 | * systems, hence let's built an attribute table of just | ||
| 173 | * what's available */ | ||
| 174 | i = 0; | ||
| 175 | ADD_DMI_ATTR(bios_vendor, DMI_BIOS_VENDOR); | ||
| 176 | ADD_DMI_ATTR(bios_version, DMI_BIOS_VERSION); | ||
| 177 | ADD_DMI_ATTR(bios_date, DMI_BIOS_DATE); | ||
| 178 | ADD_DMI_ATTR(sys_vendor, DMI_SYS_VENDOR); | ||
| 179 | ADD_DMI_ATTR(product_name, DMI_PRODUCT_NAME); | ||
| 180 | ADD_DMI_ATTR(product_version, DMI_PRODUCT_VERSION); | ||
| 181 | ADD_DMI_ATTR(product_serial, DMI_PRODUCT_SERIAL); | ||
| 182 | ADD_DMI_ATTR(product_uuid, DMI_PRODUCT_UUID); | ||
| 183 | ADD_DMI_ATTR(board_vendor, DMI_BOARD_VENDOR); | ||
| 184 | ADD_DMI_ATTR(board_name, DMI_BOARD_NAME); | ||
| 185 | ADD_DMI_ATTR(board_version, DMI_BOARD_VERSION); | ||
| 186 | ADD_DMI_ATTR(board_serial, DMI_BOARD_SERIAL); | ||
| 187 | ADD_DMI_ATTR(board_asset_tag, DMI_BOARD_ASSET_TAG); | ||
| 188 | ADD_DMI_ATTR(chassis_vendor, DMI_CHASSIS_VENDOR); | ||
| 189 | ADD_DMI_ATTR(chassis_type, DMI_CHASSIS_TYPE); | ||
| 190 | ADD_DMI_ATTR(chassis_version, DMI_CHASSIS_VERSION); | ||
| 191 | ADD_DMI_ATTR(chassis_serial, DMI_CHASSIS_SERIAL); | ||
| 192 | ADD_DMI_ATTR(chassis_asset_tag, DMI_CHASSIS_ASSET_TAG); | ||
| 193 | sys_dmi_attributes[i++] = &sys_dmi_modalias_attr.attr; | ||
| 194 | |||
| 195 | ret = class_register(&dmi_class); | ||
| 196 | if (ret) | ||
| 197 | return ret; | ||
| 198 | |||
| 199 | dmi_dev = kzalloc(sizeof(*dmi_dev), GFP_KERNEL); | ||
| 200 | if (!dmi_dev) { | ||
| 201 | ret = -ENOMEM; | ||
| 202 | goto fail_class_unregister; | ||
| 203 | } | ||
| 204 | |||
| 205 | dmi_dev->class = &dmi_class; | ||
| 206 | strcpy(dmi_dev->bus_id, "id"); | ||
| 207 | dmi_dev->groups = sys_dmi_attribute_groups; | ||
| 208 | |||
| 209 | ret = device_register(dmi_dev); | ||
| 210 | if (ret) | ||
| 211 | goto fail_class_unregister; | ||
| 212 | |||
| 213 | return 0; | ||
| 214 | |||
| 215 | fail_class_unregister: | ||
| 216 | |||
| 217 | class_unregister(&dmi_class); | ||
| 218 | |||
| 219 | return ret; | ||
| 220 | } | ||
| 221 | |||
| 222 | arch_initcall(dmi_id_init); | ||
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 37deee6c0c1c..f7318b3b51f2 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c | |||
| @@ -84,6 +84,7 @@ static int __init dmi_checksum(u8 *buf) | |||
| 84 | 84 | ||
| 85 | static char *dmi_ident[DMI_STRING_MAX]; | 85 | static char *dmi_ident[DMI_STRING_MAX]; |
| 86 | static LIST_HEAD(dmi_devices); | 86 | static LIST_HEAD(dmi_devices); |
| 87 | int dmi_available; | ||
| 87 | 88 | ||
| 88 | /* | 89 | /* |
| 89 | * Save a DMI string | 90 | * Save a DMI string |
| @@ -102,6 +103,51 @@ static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string) | |||
| 102 | dmi_ident[slot] = p; | 103 | dmi_ident[slot] = p; |
| 103 | } | 104 | } |
| 104 | 105 | ||
| 106 | static void __init dmi_save_uuid(struct dmi_header *dm, int slot, int index) | ||
| 107 | { | ||
| 108 | u8 *d = (u8*) dm + index; | ||
| 109 | char *s; | ||
| 110 | int is_ff = 1, is_00 = 1, i; | ||
| 111 | |||
| 112 | if (dmi_ident[slot]) | ||
| 113 | return; | ||
| 114 | |||
| 115 | for (i = 0; i < 16 && (is_ff || is_00); i++) { | ||
| 116 | if(d[i] != 0x00) is_ff = 0; | ||
| 117 | if(d[i] != 0xFF) is_00 = 0; | ||
| 118 | } | ||
| 119 | |||
| 120 | if (is_ff || is_00) | ||
| 121 | return; | ||
| 122 | |||
| 123 | s = dmi_alloc(16*2+4+1); | ||
| 124 | if (!s) | ||
| 125 | return; | ||
| 126 | |||
| 127 | sprintf(s, | ||
| 128 | "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X", | ||
| 129 | d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], | ||
| 130 | d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); | ||
| 131 | |||
| 132 | dmi_ident[slot] = s; | ||
| 133 | } | ||
| 134 | |||
| 135 | static void __init dmi_save_type(struct dmi_header *dm, int slot, int index) | ||
| 136 | { | ||
| 137 | u8 *d = (u8*) dm + index; | ||
| 138 | char *s; | ||
| 139 | |||
| 140 | if (dmi_ident[slot]) | ||
| 141 | return; | ||
| 142 | |||
| 143 | s = dmi_alloc(4); | ||
| 144 | if (!s) | ||
| 145 | return; | ||
| 146 | |||
| 147 | sprintf(s, "%u", *d & 0x7F); | ||
| 148 | dmi_ident[slot] = s; | ||
| 149 | } | ||
| 150 | |||
| 105 | static void __init dmi_save_devices(struct dmi_header *dm) | 151 | static void __init dmi_save_devices(struct dmi_header *dm) |
| 106 | { | 152 | { |
| 107 | int i, count = (dm->length - sizeof(struct dmi_header)) / 2; | 153 | int i, count = (dm->length - sizeof(struct dmi_header)) / 2; |
| @@ -192,11 +238,21 @@ static void __init dmi_decode(struct dmi_header *dm) | |||
| 192 | dmi_save_ident(dm, DMI_PRODUCT_NAME, 5); | 238 | dmi_save_ident(dm, DMI_PRODUCT_NAME, 5); |
| 193 | dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6); | 239 | dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6); |
| 194 | dmi_save_ident(dm, DMI_PRODUCT_SERIAL, 7); | 240 | dmi_save_ident(dm, DMI_PRODUCT_SERIAL, 7); |
| 241 | dmi_save_uuid(dm, DMI_PRODUCT_UUID, 8); | ||
| 195 | break; | 242 | break; |
| 196 | case 2: /* Base Board Information */ | 243 | case 2: /* Base Board Information */ |
| 197 | dmi_save_ident(dm, DMI_BOARD_VENDOR, 4); | 244 | dmi_save_ident(dm, DMI_BOARD_VENDOR, 4); |
| 198 | dmi_save_ident(dm, DMI_BOARD_NAME, 5); | 245 | dmi_save_ident(dm, DMI_BOARD_NAME, 5); |
| 199 | dmi_save_ident(dm, DMI_BOARD_VERSION, 6); | 246 | dmi_save_ident(dm, DMI_BOARD_VERSION, 6); |
| 247 | dmi_save_ident(dm, DMI_BOARD_SERIAL, 7); | ||
| 248 | dmi_save_ident(dm, DMI_BOARD_ASSET_TAG, 8); | ||
| 249 | break; | ||
| 250 | case 3: /* Chassis Information */ | ||
| 251 | dmi_save_ident(dm, DMI_CHASSIS_VENDOR, 4); | ||
| 252 | dmi_save_type(dm, DMI_CHASSIS_TYPE, 5); | ||
| 253 | dmi_save_ident(dm, DMI_CHASSIS_VERSION, 6); | ||
| 254 | dmi_save_ident(dm, DMI_CHASSIS_SERIAL, 7); | ||
| 255 | dmi_save_ident(dm, DMI_CHASSIS_ASSET_TAG, 8); | ||
| 200 | break; | 256 | break; |
| 201 | case 10: /* Onboard Devices Information */ | 257 | case 10: /* Onboard Devices Information */ |
| 202 | dmi_save_devices(dm); | 258 | dmi_save_devices(dm); |
| @@ -243,18 +299,20 @@ void __init dmi_scan_machine(void) | |||
| 243 | if (efi.smbios == EFI_INVALID_TABLE_ADDR) | 299 | if (efi.smbios == EFI_INVALID_TABLE_ADDR) |
| 244 | goto out; | 300 | goto out; |
| 245 | 301 | ||
| 246 | /* This is called as a core_initcall() because it isn't | 302 | /* This is called as a core_initcall() because it isn't |
| 247 | * needed during early boot. This also means we can | 303 | * needed during early boot. This also means we can |
| 248 | * iounmap the space when we're done with it. | 304 | * iounmap the space when we're done with it. |
| 249 | */ | 305 | */ |
| 250 | p = dmi_ioremap(efi.smbios, 32); | 306 | p = dmi_ioremap(efi.smbios, 32); |
| 251 | if (p == NULL) | 307 | if (p == NULL) |
| 252 | goto out; | 308 | goto out; |
| 253 | 309 | ||
| 254 | rc = dmi_present(p + 0x10); /* offset of _DMI_ string */ | 310 | rc = dmi_present(p + 0x10); /* offset of _DMI_ string */ |
| 255 | dmi_iounmap(p, 32); | 311 | dmi_iounmap(p, 32); |
| 256 | if (!rc) | 312 | if (!rc) { |
| 313 | dmi_available = 1; | ||
| 257 | return; | 314 | return; |
| 315 | } | ||
| 258 | } | 316 | } |
| 259 | else { | 317 | else { |
| 260 | /* | 318 | /* |
| @@ -268,8 +326,10 @@ void __init dmi_scan_machine(void) | |||
| 268 | 326 | ||
| 269 | for (q = p; q < p + 0x10000; q += 16) { | 327 | for (q = p; q < p + 0x10000; q += 16) { |
| 270 | rc = dmi_present(q); | 328 | rc = dmi_present(q); |
| 271 | if (!rc) | 329 | if (!rc) { |
| 330 | dmi_available = 1; | ||
| 272 | return; | 331 | return; |
| 332 | } | ||
| 273 | } | 333 | } |
| 274 | } | 334 | } |
| 275 | out: printk(KERN_INFO "DMI not present or invalid.\n"); | 335 | out: printk(KERN_INFO "DMI not present or invalid.\n"); |
| @@ -404,3 +464,4 @@ int dmi_get_year(int field) | |||
| 404 | 464 | ||
| 405 | return year; | 465 | return year; |
| 406 | } | 466 | } |
| 467 | |||
diff --git a/drivers/firmware/edd.c b/drivers/firmware/edd.c index d8806e4f1829..15232271d848 100644 --- a/drivers/firmware/edd.c +++ b/drivers/firmware/edd.c | |||
| @@ -74,7 +74,7 @@ static struct edd_device *edd_devices[EDD_MBR_SIG_MAX]; | |||
| 74 | 74 | ||
| 75 | #define EDD_DEVICE_ATTR(_name,_mode,_show,_test) \ | 75 | #define EDD_DEVICE_ATTR(_name,_mode,_show,_test) \ |
| 76 | struct edd_attribute edd_attr_##_name = { \ | 76 | struct edd_attribute edd_attr_##_name = { \ |
| 77 | .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \ | 77 | .attr = {.name = __stringify(_name), .mode = _mode }, \ |
| 78 | .show = _show, \ | 78 | .show = _show, \ |
| 79 | .test = _test, \ | 79 | .test = _test, \ |
| 80 | }; | 80 | }; |
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index 1324984a4c35..bfd2d67df689 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c | |||
| @@ -131,21 +131,21 @@ struct efivar_attribute { | |||
| 131 | 131 | ||
| 132 | #define EFI_ATTR(_name, _mode, _show, _store) \ | 132 | #define EFI_ATTR(_name, _mode, _show, _store) \ |
| 133 | struct subsys_attribute efi_attr_##_name = { \ | 133 | struct subsys_attribute efi_attr_##_name = { \ |
| 134 | .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \ | 134 | .attr = {.name = __stringify(_name), .mode = _mode}, \ |
| 135 | .show = _show, \ | 135 | .show = _show, \ |
| 136 | .store = _store, \ | 136 | .store = _store, \ |
| 137 | }; | 137 | }; |
| 138 | 138 | ||
| 139 | #define EFIVAR_ATTR(_name, _mode, _show, _store) \ | 139 | #define EFIVAR_ATTR(_name, _mode, _show, _store) \ |
| 140 | struct efivar_attribute efivar_attr_##_name = { \ | 140 | struct efivar_attribute efivar_attr_##_name = { \ |
| 141 | .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \ | 141 | .attr = {.name = __stringify(_name), .mode = _mode}, \ |
| 142 | .show = _show, \ | 142 | .show = _show, \ |
| 143 | .store = _store, \ | 143 | .store = _store, \ |
| 144 | }; | 144 | }; |
| 145 | 145 | ||
| 146 | #define VAR_SUBSYS_ATTR(_name, _mode, _show, _store) \ | 146 | #define VAR_SUBSYS_ATTR(_name, _mode, _show, _store) \ |
| 147 | struct subsys_attribute var_subsys_attr_##_name = { \ | 147 | struct subsys_attribute var_subsys_attr_##_name = { \ |
| 148 | .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \ | 148 | .attr = {.name = __stringify(_name), .mode = _mode}, \ |
| 149 | .show = _show, \ | 149 | .show = _show, \ |
| 150 | .store = _store, \ | 150 | .store = _store, \ |
| 151 | }; | 151 | }; |
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c index 48f857ae8748..d3da1fb05b9b 100644 --- a/drivers/i2c/chips/eeprom.c +++ b/drivers/i2c/chips/eeprom.c | |||
| @@ -112,7 +112,8 @@ exit: | |||
| 112 | mutex_unlock(&data->update_lock); | 112 | mutex_unlock(&data->update_lock); |
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | static ssize_t eeprom_read(struct kobject *kobj, char *buf, loff_t off, size_t count) | 115 | static ssize_t eeprom_read(struct kobject *kobj, struct bin_attribute *bin_attr, |
| 116 | char *buf, loff_t off, size_t count) | ||
| 116 | { | 117 | { |
| 117 | struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); | 118 | struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); |
| 118 | struct eeprom_data *data = i2c_get_clientdata(client); | 119 | struct eeprom_data *data = i2c_get_clientdata(client); |
| @@ -145,7 +146,6 @@ static struct bin_attribute eeprom_attr = { | |||
| 145 | .attr = { | 146 | .attr = { |
| 146 | .name = "eeprom", | 147 | .name = "eeprom", |
| 147 | .mode = S_IRUGO, | 148 | .mode = S_IRUGO, |
| 148 | .owner = THIS_MODULE, | ||
| 149 | }, | 149 | }, |
| 150 | .size = EEPROM_SIZE, | 150 | .size = EEPROM_SIZE, |
| 151 | .read = eeprom_read, | 151 | .read = eeprom_read, |
diff --git a/drivers/i2c/chips/max6875.c b/drivers/i2c/chips/max6875.c index e9e9e5171b53..64692f666372 100644 --- a/drivers/i2c/chips/max6875.c +++ b/drivers/i2c/chips/max6875.c | |||
| @@ -126,8 +126,9 @@ exit_up: | |||
| 126 | mutex_unlock(&data->update_lock); | 126 | mutex_unlock(&data->update_lock); |
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | static ssize_t max6875_read(struct kobject *kobj, char *buf, loff_t off, | 129 | static ssize_t max6875_read(struct kobject *kobj, |
| 130 | size_t count) | 130 | struct bin_attribute *bin_attr, |
| 131 | char *buf, loff_t off, size_t count) | ||
| 131 | { | 132 | { |
| 132 | struct i2c_client *client = kobj_to_i2c_client(kobj); | 133 | struct i2c_client *client = kobj_to_i2c_client(kobj); |
| 133 | struct max6875_data *data = i2c_get_clientdata(client); | 134 | struct max6875_data *data = i2c_get_clientdata(client); |
| @@ -153,7 +154,6 @@ static struct bin_attribute user_eeprom_attr = { | |||
| 153 | .attr = { | 154 | .attr = { |
| 154 | .name = "eeprom", | 155 | .name = "eeprom", |
| 155 | .mode = S_IRUGO, | 156 | .mode = S_IRUGO, |
| 156 | .owner = THIS_MODULE, | ||
| 157 | }, | 157 | }, |
| 158 | .size = USER_EEPROM_SIZE, | 158 | .size = USER_EEPROM_SIZE, |
| 159 | .read = max6875_read, | 159 | .read = max6875_read, |
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c index 08c299ebf4a8..bf9b99292048 100644 --- a/drivers/infiniband/core/sysfs.c +++ b/drivers/infiniband/core/sysfs.c | |||
| @@ -479,7 +479,6 @@ alloc_group_attrs(ssize_t (*show)(struct ib_port *, | |||
| 479 | 479 | ||
| 480 | element->attr.attr.name = element->name; | 480 | element->attr.attr.name = element->name; |
| 481 | element->attr.attr.mode = S_IRUGO; | 481 | element->attr.attr.mode = S_IRUGO; |
| 482 | element->attr.attr.owner = THIS_MODULE; | ||
| 483 | element->attr.show = show; | 482 | element->attr.show = show; |
| 484 | element->index = i; | 483 | element->index = i; |
| 485 | 484 | ||
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index 27a68835b5ba..1317bdd8cc7c 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h | |||
| @@ -119,7 +119,6 @@ static struct psmouse_attribute psmouse_attr_##_name = { \ | |||
| 119 | .attr = { \ | 119 | .attr = { \ |
| 120 | .name = __stringify(_name), \ | 120 | .name = __stringify(_name), \ |
| 121 | .mode = _mode, \ | 121 | .mode = _mode, \ |
| 122 | .owner = THIS_MODULE, \ | ||
| 123 | }, \ | 122 | }, \ |
| 124 | .show = psmouse_attr_show_helper, \ | 123 | .show = psmouse_attr_show_helper, \ |
| 125 | .store = psmouse_attr_set_helper, \ | 124 | .store = psmouse_attr_set_helper, \ |
diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c index 11ced17f438a..4fcb245ba184 100644 --- a/drivers/macintosh/windfarm_core.c +++ b/drivers/macintosh/windfarm_core.c | |||
| @@ -212,7 +212,6 @@ int wf_register_control(struct wf_control *new_ct) | |||
| 212 | list_add(&new_ct->link, &wf_controls); | 212 | list_add(&new_ct->link, &wf_controls); |
| 213 | 213 | ||
| 214 | new_ct->attr.attr.name = new_ct->name; | 214 | new_ct->attr.attr.name = new_ct->name; |
| 215 | new_ct->attr.attr.owner = THIS_MODULE; | ||
| 216 | new_ct->attr.attr.mode = 0644; | 215 | new_ct->attr.attr.mode = 0644; |
| 217 | new_ct->attr.show = wf_show_control; | 216 | new_ct->attr.show = wf_show_control; |
| 218 | new_ct->attr.store = wf_store_control; | 217 | new_ct->attr.store = wf_store_control; |
| @@ -325,7 +324,6 @@ int wf_register_sensor(struct wf_sensor *new_sr) | |||
| 325 | list_add(&new_sr->link, &wf_sensors); | 324 | list_add(&new_sr->link, &wf_sensors); |
| 326 | 325 | ||
| 327 | new_sr->attr.attr.name = new_sr->name; | 326 | new_sr->attr.attr.name = new_sr->name; |
| 328 | new_sr->attr.attr.owner = THIS_MODULE; | ||
| 329 | new_sr->attr.attr.mode = 0444; | 327 | new_sr->attr.attr.mode = 0444; |
| 330 | new_sr->attr.show = wf_show_sensor; | 328 | new_sr->attr.show = wf_show_sensor; |
| 331 | new_sr->attr.store = NULL; | 329 | new_sr->attr.store = NULL; |
diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c index 4f9060a2a2f2..7798f590e5aa 100644 --- a/drivers/misc/asus-laptop.c +++ b/drivers/misc/asus-laptop.c | |||
| @@ -737,8 +737,7 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) | |||
| 737 | struct device_attribute dev_attr_##_name = { \ | 737 | struct device_attribute dev_attr_##_name = { \ |
| 738 | .attr = { \ | 738 | .attr = { \ |
| 739 | .name = __stringify(_name), \ | 739 | .name = __stringify(_name), \ |
| 740 | .mode = 0, \ | 740 | .mode = 0 }, \ |
| 741 | .owner = THIS_MODULE }, \ | ||
| 742 | .show = NULL, \ | 741 | .show = NULL, \ |
| 743 | .store = NULL, \ | 742 | .store = NULL, \ |
| 744 | } | 743 | } |
diff --git a/drivers/misc/msi-laptop.c b/drivers/misc/msi-laptop.c index 41e901f53e7c..932a415197b3 100644 --- a/drivers/misc/msi-laptop.c +++ b/drivers/misc/msi-laptop.c | |||
| @@ -23,6 +23,8 @@ | |||
| 23 | * msi-laptop.c - MSI S270 laptop support. This laptop is sold under | 23 | * msi-laptop.c - MSI S270 laptop support. This laptop is sold under |
| 24 | * various brands, including "Cytron/TCM/Medion/Tchibo MD96100". | 24 | * various brands, including "Cytron/TCM/Medion/Tchibo MD96100". |
| 25 | * | 25 | * |
| 26 | * Driver also supports S271, S420 models. | ||
| 27 | * | ||
| 26 | * This driver exports a few files in /sys/devices/platform/msi-laptop-pf/: | 28 | * This driver exports a few files in /sys/devices/platform/msi-laptop-pf/: |
| 27 | * | 29 | * |
| 28 | * lcd_level - Screen brightness: contains a single integer in the | 30 | * lcd_level - Screen brightness: contains a single integer in the |
| @@ -281,25 +283,56 @@ static struct platform_device *msipf_device; | |||
| 281 | 283 | ||
| 282 | /* Initialization */ | 284 | /* Initialization */ |
| 283 | 285 | ||
| 286 | static int dmi_check_cb(struct dmi_system_id *id) | ||
| 287 | { | ||
| 288 | printk("msi-laptop: Identified laptop model '%s'.\n", id->ident); | ||
| 289 | return 0; | ||
| 290 | } | ||
| 291 | |||
| 284 | static struct dmi_system_id __initdata msi_dmi_table[] = { | 292 | static struct dmi_system_id __initdata msi_dmi_table[] = { |
| 285 | { | 293 | { |
| 286 | .ident = "MSI S270", | 294 | .ident = "MSI S270", |
| 287 | .matches = { | 295 | .matches = { |
| 288 | DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD"), | 296 | DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD"), |
| 289 | DMI_MATCH(DMI_PRODUCT_NAME, "MS-1013"), | 297 | DMI_MATCH(DMI_PRODUCT_NAME, "MS-1013"), |
| 290 | } | 298 | DMI_MATCH(DMI_PRODUCT_VERSION, "0131"), |
| 299 | DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR INT'L CO.,LTD") | ||
| 300 | }, | ||
| 301 | .callback = dmi_check_cb | ||
| 302 | }, | ||
| 303 | { | ||
| 304 | .ident = "MSI S271", | ||
| 305 | .matches = { | ||
| 306 | DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), | ||
| 307 | DMI_MATCH(DMI_PRODUCT_NAME, "MS-1058"), | ||
| 308 | DMI_MATCH(DMI_PRODUCT_VERSION, "0581"), | ||
| 309 | DMI_MATCH(DMI_BOARD_NAME, "MS-1058") | ||
| 310 | }, | ||
| 311 | .callback = dmi_check_cb | ||
| 312 | }, | ||
| 313 | { | ||
| 314 | .ident = "MSI S420", | ||
| 315 | .matches = { | ||
| 316 | DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), | ||
| 317 | DMI_MATCH(DMI_PRODUCT_NAME, "MS-1412"), | ||
| 318 | DMI_MATCH(DMI_BOARD_VENDOR, "MSI"), | ||
| 319 | DMI_MATCH(DMI_BOARD_NAME, "MS-1412") | ||
| 320 | }, | ||
| 321 | .callback = dmi_check_cb | ||
| 291 | }, | 322 | }, |
| 292 | { | 323 | { |
| 293 | .ident = "Medion MD96100", | 324 | .ident = "Medion MD96100", |
| 294 | .matches = { | 325 | .matches = { |
| 295 | DMI_MATCH(DMI_SYS_VENDOR, "NOTEBOOK"), | 326 | DMI_MATCH(DMI_SYS_VENDOR, "NOTEBOOK"), |
| 296 | DMI_MATCH(DMI_PRODUCT_NAME, "SAM2000"), | 327 | DMI_MATCH(DMI_PRODUCT_NAME, "SAM2000"), |
| 297 | } | 328 | DMI_MATCH(DMI_PRODUCT_VERSION, "0131"), |
| 329 | DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR INT'L CO.,LTD") | ||
| 330 | }, | ||
| 331 | .callback = dmi_check_cb | ||
| 298 | }, | 332 | }, |
| 299 | { } | 333 | { } |
| 300 | }; | 334 | }; |
| 301 | 335 | ||
| 302 | |||
| 303 | static int __init msi_init(void) | 336 | static int __init msi_init(void) |
| 304 | { | 337 | { |
| 305 | int ret; | 338 | int ret; |
| @@ -394,3 +427,8 @@ MODULE_AUTHOR("Lennart Poettering"); | |||
| 394 | MODULE_DESCRIPTION("MSI Laptop Support"); | 427 | MODULE_DESCRIPTION("MSI Laptop Support"); |
| 395 | MODULE_VERSION(MSI_DRIVER_VERSION); | 428 | MODULE_VERSION(MSI_DRIVER_VERSION); |
| 396 | MODULE_LICENSE("GPL"); | 429 | MODULE_LICENSE("GPL"); |
| 430 | |||
| 431 | MODULE_ALIAS("dmi:*:svnMICRO-STARINT'LCO.,LTD:pnMS-1013:pvr0131*:cvnMICRO-STARINT'LCO.,LTD:ct10:*"); | ||
| 432 | MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1058:pvr0581:rvnMSI:rnMS-1058:*:ct10:*"); | ||
| 433 | MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1412:*:rvnMSI:rnMS-1412:*:cvnMICRO-STARINT'LCO.,LTD:ct10:*"); | ||
| 434 | MODULE_ALIAS("dmi:*:svnNOTEBOOK:pnSAM2000:pvr0131*:cvnMICRO-STARINT'LCO.,LTD:ct10:*"); | ||
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 6ec3d500f334..d96eb7229548 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c | |||
| @@ -1337,7 +1337,7 @@ const char * buf, size_t count) | |||
| 1337 | 1337 | ||
| 1338 | #define ATTR(_name, _mode) \ | 1338 | #define ATTR(_name, _mode) \ |
| 1339 | struct attribute veth_##_name##_attr = { \ | 1339 | struct attribute veth_##_name##_attr = { \ |
| 1340 | .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE \ | 1340 | .name = __stringify(_name), .mode = _mode, \ |
| 1341 | }; | 1341 | }; |
| 1342 | 1342 | ||
| 1343 | static ATTR(active, 0644); | 1343 | static ATTR(active, 0644); |
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c index 924ef0609460..fc4bde259dc7 100644 --- a/drivers/parisc/pdc_stable.c +++ b/drivers/parisc/pdc_stable.c | |||
| @@ -121,14 +121,14 @@ struct pdcspath_entry pdcspath_entry_##_name = { \ | |||
| 121 | 121 | ||
| 122 | #define PDCS_ATTR(_name, _mode, _show, _store) \ | 122 | #define PDCS_ATTR(_name, _mode, _show, _store) \ |
| 123 | struct subsys_attribute pdcs_attr_##_name = { \ | 123 | struct subsys_attribute pdcs_attr_##_name = { \ |
| 124 | .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \ | 124 | .attr = {.name = __stringify(_name), .mode = _mode}, \ |
| 125 | .show = _show, \ | 125 | .show = _show, \ |
| 126 | .store = _store, \ | 126 | .store = _store, \ |
| 127 | }; | 127 | }; |
| 128 | 128 | ||
| 129 | #define PATHS_ATTR(_name, _mode, _show, _store) \ | 129 | #define PATHS_ATTR(_name, _mode, _show, _store) \ |
| 130 | struct pdcspath_attribute paths_attr_##_name = { \ | 130 | struct pdcspath_attribute paths_attr_##_name = { \ |
| 131 | .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \ | 131 | .attr = {.name = __stringify(_name), .mode = _mode}, \ |
| 132 | .show = _show, \ | 132 | .show = _show, \ |
| 133 | .store = _store, \ | 133 | .store = _store, \ |
| 134 | }; | 134 | }; |
diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c index e7322c25d377..70db38c0ced9 100644 --- a/drivers/pci/hotplug/acpiphp_ibm.c +++ b/drivers/pci/hotplug/acpiphp_ibm.c | |||
| @@ -106,7 +106,8 @@ static int ibm_get_attention_status(struct hotplug_slot *slot, u8 *status); | |||
| 106 | static void ibm_handle_events(acpi_handle handle, u32 event, void *context); | 106 | static void ibm_handle_events(acpi_handle handle, u32 event, void *context); |
| 107 | static int ibm_get_table_from_acpi(char **bufp); | 107 | static int ibm_get_table_from_acpi(char **bufp); |
| 108 | static ssize_t ibm_read_apci_table(struct kobject *kobj, | 108 | static ssize_t ibm_read_apci_table(struct kobject *kobj, |
| 109 | char *buffer, loff_t pos, size_t size); | 109 | struct bin_attribute *bin_attr, |
| 110 | char *buffer, loff_t pos, size_t size); | ||
| 110 | static acpi_status __init ibm_find_acpi_device(acpi_handle handle, | 111 | static acpi_status __init ibm_find_acpi_device(acpi_handle handle, |
| 111 | u32 lvl, void *context, void **rv); | 112 | u32 lvl, void *context, void **rv); |
| 112 | static int __init ibm_acpiphp_init(void); | 113 | static int __init ibm_acpiphp_init(void); |
| @@ -117,7 +118,6 @@ static struct notification ibm_note; | |||
| 117 | static struct bin_attribute ibm_apci_table_attr = { | 118 | static struct bin_attribute ibm_apci_table_attr = { |
| 118 | .attr = { | 119 | .attr = { |
| 119 | .name = "apci_table", | 120 | .name = "apci_table", |
| 120 | .owner = THIS_MODULE, | ||
| 121 | .mode = S_IRUGO, | 121 | .mode = S_IRUGO, |
| 122 | }, | 122 | }, |
| 123 | .read = ibm_read_apci_table, | 123 | .read = ibm_read_apci_table, |
| @@ -358,7 +358,8 @@ read_table_done: | |||
| 358 | * our solution is to only allow reading the table in all at once | 358 | * our solution is to only allow reading the table in all at once |
| 359 | **/ | 359 | **/ |
| 360 | static ssize_t ibm_read_apci_table(struct kobject *kobj, | 360 | static ssize_t ibm_read_apci_table(struct kobject *kobj, |
| 361 | char *buffer, loff_t pos, size_t size) | 361 | struct bin_attribute *bin_attr, |
| 362 | char *buffer, loff_t pos, size_t size) | ||
| 362 | { | 363 | { |
| 363 | int bytes_read = -EINVAL; | 364 | int bytes_read = -EINVAL; |
| 364 | char *table = NULL; | 365 | char *table = NULL; |
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 284e83a527f9..6543cbe83be5 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c | |||
| @@ -213,7 +213,8 @@ struct device_attribute pci_dev_attrs[] = { | |||
| 213 | }; | 213 | }; |
| 214 | 214 | ||
| 215 | static ssize_t | 215 | static ssize_t |
| 216 | pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count) | 216 | pci_read_config(struct kobject *kobj, struct bin_attribute *bin_attr, |
| 217 | char *buf, loff_t off, size_t count) | ||
| 217 | { | 218 | { |
| 218 | struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj)); | 219 | struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj)); |
| 219 | unsigned int size = 64; | 220 | unsigned int size = 64; |
| @@ -285,7 +286,8 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count) | |||
| 285 | } | 286 | } |
| 286 | 287 | ||
| 287 | static ssize_t | 288 | static ssize_t |
| 288 | pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count) | 289 | pci_write_config(struct kobject *kobj, struct bin_attribute *bin_attr, |
| 290 | char *buf, loff_t off, size_t count) | ||
| 289 | { | 291 | { |
| 290 | struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj)); | 292 | struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj)); |
| 291 | unsigned int size = count; | 293 | unsigned int size = count; |
| @@ -352,7 +354,8 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count) | |||
| 352 | * callback routine (pci_legacy_read). | 354 | * callback routine (pci_legacy_read). |
| 353 | */ | 355 | */ |
| 354 | ssize_t | 356 | ssize_t |
| 355 | pci_read_legacy_io(struct kobject *kobj, char *buf, loff_t off, size_t count) | 357 | pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr, |
| 358 | char *buf, loff_t off, size_t count) | ||
| 356 | { | 359 | { |
| 357 | struct pci_bus *bus = to_pci_bus(container_of(kobj, | 360 | struct pci_bus *bus = to_pci_bus(container_of(kobj, |
| 358 | struct class_device, | 361 | struct class_device, |
| @@ -376,7 +379,8 @@ pci_read_legacy_io(struct kobject *kobj, char *buf, loff_t off, size_t count) | |||
| 376 | * callback routine (pci_legacy_write). | 379 | * callback routine (pci_legacy_write). |
| 377 | */ | 380 | */ |
| 378 | ssize_t | 381 | ssize_t |
| 379 | pci_write_legacy_io(struct kobject *kobj, char *buf, loff_t off, size_t count) | 382 | pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr, |
| 383 | char *buf, loff_t off, size_t count) | ||
| 380 | { | 384 | { |
| 381 | struct pci_bus *bus = to_pci_bus(container_of(kobj, | 385 | struct pci_bus *bus = to_pci_bus(container_of(kobj, |
| 382 | struct class_device, | 386 | struct class_device, |
| @@ -499,7 +503,6 @@ static int pci_create_resource_files(struct pci_dev *pdev) | |||
| 499 | sprintf(res_attr_name, "resource%d", i); | 503 | sprintf(res_attr_name, "resource%d", i); |
| 500 | res_attr->attr.name = res_attr_name; | 504 | res_attr->attr.name = res_attr_name; |
| 501 | res_attr->attr.mode = S_IRUSR | S_IWUSR; | 505 | res_attr->attr.mode = S_IRUSR | S_IWUSR; |
| 502 | res_attr->attr.owner = THIS_MODULE; | ||
| 503 | res_attr->size = pci_resource_len(pdev, i); | 506 | res_attr->size = pci_resource_len(pdev, i); |
| 504 | res_attr->mmap = pci_mmap_resource; | 507 | res_attr->mmap = pci_mmap_resource; |
| 505 | res_attr->private = &pdev->resource[i]; | 508 | res_attr->private = &pdev->resource[i]; |
| @@ -529,7 +532,8 @@ static inline void pci_remove_resource_files(struct pci_dev *dev) { return; } | |||
| 529 | * writing anything except 0 enables it | 532 | * writing anything except 0 enables it |
| 530 | */ | 533 | */ |
| 531 | static ssize_t | 534 | static ssize_t |
| 532 | pci_write_rom(struct kobject *kobj, char *buf, loff_t off, size_t count) | 535 | pci_write_rom(struct kobject *kobj, struct bin_attribute *bin_attr, |
| 536 | char *buf, loff_t off, size_t count) | ||
| 533 | { | 537 | { |
| 534 | struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj)); | 538 | struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj)); |
| 535 | 539 | ||
| @@ -552,7 +556,8 @@ pci_write_rom(struct kobject *kobj, char *buf, loff_t off, size_t count) | |||
| 552 | * device corresponding to @kobj. | 556 | * device corresponding to @kobj. |
| 553 | */ | 557 | */ |
| 554 | static ssize_t | 558 | static ssize_t |
| 555 | pci_read_rom(struct kobject *kobj, char *buf, loff_t off, size_t count) | 559 | pci_read_rom(struct kobject *kobj, struct bin_attribute *bin_attr, |
| 560 | char *buf, loff_t off, size_t count) | ||
| 556 | { | 561 | { |
| 557 | struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj)); | 562 | struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj)); |
| 558 | void __iomem *rom; | 563 | void __iomem *rom; |
| @@ -582,7 +587,6 @@ static struct bin_attribute pci_config_attr = { | |||
| 582 | .attr = { | 587 | .attr = { |
| 583 | .name = "config", | 588 | .name = "config", |
| 584 | .mode = S_IRUGO | S_IWUSR, | 589 | .mode = S_IRUGO | S_IWUSR, |
| 585 | .owner = THIS_MODULE, | ||
| 586 | }, | 590 | }, |
| 587 | .size = 256, | 591 | .size = 256, |
| 588 | .read = pci_read_config, | 592 | .read = pci_read_config, |
| @@ -593,7 +597,6 @@ static struct bin_attribute pcie_config_attr = { | |||
| 593 | .attr = { | 597 | .attr = { |
| 594 | .name = "config", | 598 | .name = "config", |
| 595 | .mode = S_IRUGO | S_IWUSR, | 599 | .mode = S_IRUGO | S_IWUSR, |
| 596 | .owner = THIS_MODULE, | ||
| 597 | }, | 600 | }, |
| 598 | .size = 4096, | 601 | .size = 4096, |
| 599 | .read = pci_read_config, | 602 | .read = pci_read_config, |
| @@ -628,7 +631,6 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) | |||
| 628 | rom_attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE); | 631 | rom_attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE); |
| 629 | rom_attr->attr.name = "rom"; | 632 | rom_attr->attr.name = "rom"; |
| 630 | rom_attr->attr.mode = S_IRUSR; | 633 | rom_attr->attr.mode = S_IRUSR; |
| 631 | rom_attr->attr.owner = THIS_MODULE; | ||
| 632 | rom_attr->read = pci_read_rom; | 634 | rom_attr->read = pci_read_rom; |
| 633 | rom_attr->write = pci_write_rom; | 635 | rom_attr->write = pci_write_rom; |
| 634 | retval = sysfs_create_bin_file(&pdev->dev.kobj, rom_attr); | 636 | retval = sysfs_create_bin_file(&pdev->dev.kobj, rom_attr); |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index e48fcf089621..08783bd381f5 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
| @@ -39,7 +39,6 @@ static void pci_create_legacy_files(struct pci_bus *b) | |||
| 39 | b->legacy_io->attr.name = "legacy_io"; | 39 | b->legacy_io->attr.name = "legacy_io"; |
| 40 | b->legacy_io->size = 0xffff; | 40 | b->legacy_io->size = 0xffff; |
| 41 | b->legacy_io->attr.mode = S_IRUSR | S_IWUSR; | 41 | b->legacy_io->attr.mode = S_IRUSR | S_IWUSR; |
| 42 | b->legacy_io->attr.owner = THIS_MODULE; | ||
| 43 | b->legacy_io->read = pci_read_legacy_io; | 42 | b->legacy_io->read = pci_read_legacy_io; |
| 44 | b->legacy_io->write = pci_write_legacy_io; | 43 | b->legacy_io->write = pci_write_legacy_io; |
| 45 | class_device_create_bin_file(&b->class_dev, b->legacy_io); | 44 | class_device_create_bin_file(&b->class_dev, b->legacy_io); |
| @@ -49,7 +48,6 @@ static void pci_create_legacy_files(struct pci_bus *b) | |||
| 49 | b->legacy_mem->attr.name = "legacy_mem"; | 48 | b->legacy_mem->attr.name = "legacy_mem"; |
| 50 | b->legacy_mem->size = 1024*1024; | 49 | b->legacy_mem->size = 1024*1024; |
| 51 | b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR; | 50 | b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR; |
| 52 | b->legacy_mem->attr.owner = THIS_MODULE; | ||
| 53 | b->legacy_mem->mmap = pci_mmap_legacy_mem; | 51 | b->legacy_mem->mmap = pci_mmap_legacy_mem; |
| 54 | class_device_create_bin_file(&b->class_dev, b->legacy_mem); | 52 | class_device_create_bin_file(&b->class_dev, b->legacy_mem); |
| 55 | } | 53 | } |
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c index a2bb46526b56..b4409002b7f8 100644 --- a/drivers/pcmcia/socket_sysfs.c +++ b/drivers/pcmcia/socket_sysfs.c | |||
| @@ -283,7 +283,9 @@ static ssize_t pccard_extract_cis(struct pcmcia_socket *s, char *buf, loff_t off | |||
| 283 | return (ret); | 283 | return (ret); |
| 284 | } | 284 | } |
| 285 | 285 | ||
| 286 | static ssize_t pccard_show_cis(struct kobject *kobj, char *buf, loff_t off, size_t count) | 286 | static ssize_t pccard_show_cis(struct kobject *kobj, |
| 287 | struct bin_attribute *bin_attr, | ||
| 288 | char *buf, loff_t off, size_t count) | ||
| 287 | { | 289 | { |
| 288 | unsigned int size = 0x200; | 290 | unsigned int size = 0x200; |
| 289 | 291 | ||
| @@ -311,7 +313,9 @@ static ssize_t pccard_show_cis(struct kobject *kobj, char *buf, loff_t off, size | |||
| 311 | return (count); | 313 | return (count); |
| 312 | } | 314 | } |
| 313 | 315 | ||
| 314 | static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, size_t count) | 316 | static ssize_t pccard_store_cis(struct kobject *kobj, |
| 317 | struct bin_attribute *bin_attr, | ||
| 318 | char *buf, loff_t off, size_t count) | ||
| 315 | { | 319 | { |
| 316 | struct pcmcia_socket *s = to_socket(container_of(kobj, struct device, kobj)); | 320 | struct pcmcia_socket *s = to_socket(container_of(kobj, struct device, kobj)); |
| 317 | cisdump_t *cis; | 321 | cisdump_t *cis; |
| @@ -366,7 +370,7 @@ static struct device_attribute *pccard_socket_attributes[] = { | |||
| 366 | }; | 370 | }; |
| 367 | 371 | ||
| 368 | static struct bin_attribute pccard_cis_attr = { | 372 | static struct bin_attribute pccard_cis_attr = { |
| 369 | .attr = { .name = "cis", .mode = S_IRUGO | S_IWUSR, .owner = THIS_MODULE}, | 373 | .attr = { .name = "cis", .mode = S_IRUGO | S_IWUSR }, |
| 370 | .size = 0x200, | 374 | .size = 0x200, |
| 371 | .read = pccard_show_cis, | 375 | .read = pccard_show_cis, |
| 372 | .write = pccard_store_cis, | 376 | .write = pccard_store_cis, |
diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c index eed91434417d..659e31164cf0 100644 --- a/drivers/rapidio/rio-sysfs.c +++ b/drivers/rapidio/rio-sysfs.c | |||
| @@ -67,7 +67,8 @@ struct device_attribute rio_dev_attrs[] = { | |||
| 67 | }; | 67 | }; |
| 68 | 68 | ||
| 69 | static ssize_t | 69 | static ssize_t |
| 70 | rio_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count) | 70 | rio_read_config(struct kobject *kobj, struct bin_attribute *bin_attr, |
| 71 | char *buf, loff_t off, size_t count) | ||
| 71 | { | 72 | { |
| 72 | struct rio_dev *dev = | 73 | struct rio_dev *dev = |
| 73 | to_rio_dev(container_of(kobj, struct device, kobj)); | 74 | to_rio_dev(container_of(kobj, struct device, kobj)); |
| @@ -137,7 +138,8 @@ rio_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count) | |||
| 137 | } | 138 | } |
| 138 | 139 | ||
| 139 | static ssize_t | 140 | static ssize_t |
| 140 | rio_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count) | 141 | rio_write_config(struct kobject *kobj, struct bin_attribute *bin_attr, |
| 142 | char *buf, loff_t off, size_t count) | ||
| 141 | { | 143 | { |
| 142 | struct rio_dev *dev = | 144 | struct rio_dev *dev = |
| 143 | to_rio_dev(container_of(kobj, struct device, kobj)); | 145 | to_rio_dev(container_of(kobj, struct device, kobj)); |
| @@ -197,7 +199,6 @@ static struct bin_attribute rio_config_attr = { | |||
| 197 | .attr = { | 199 | .attr = { |
| 198 | .name = "config", | 200 | .name = "config", |
| 199 | .mode = S_IRUGO | S_IWUSR, | 201 | .mode = S_IRUGO | S_IWUSR, |
| 200 | .owner = THIS_MODULE, | ||
| 201 | }, | 202 | }, |
| 202 | .size = 0x200000, | 203 | .size = 0x200000, |
| 203 | .read = rio_read_config, | 204 | .read = rio_read_config, |
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index afa64c7fa2e2..f98a83a11aae 100644 --- a/drivers/rtc/rtc-ds1553.c +++ b/drivers/rtc/rtc-ds1553.c | |||
| @@ -258,8 +258,9 @@ static const struct rtc_class_ops ds1553_rtc_ops = { | |||
| 258 | .ioctl = ds1553_rtc_ioctl, | 258 | .ioctl = ds1553_rtc_ioctl, |
| 259 | }; | 259 | }; |
| 260 | 260 | ||
| 261 | static ssize_t ds1553_nvram_read(struct kobject *kobj, char *buf, | 261 | static ssize_t ds1553_nvram_read(struct kobject *kobj, |
| 262 | loff_t pos, size_t size) | 262 | struct bin_attribute *bin_attr, |
| 263 | char *buf, loff_t pos, size_t size) | ||
| 263 | { | 264 | { |
| 264 | struct platform_device *pdev = | 265 | struct platform_device *pdev = |
| 265 | to_platform_device(container_of(kobj, struct device, kobj)); | 266 | to_platform_device(container_of(kobj, struct device, kobj)); |
| @@ -272,8 +273,9 @@ static ssize_t ds1553_nvram_read(struct kobject *kobj, char *buf, | |||
| 272 | return count; | 273 | return count; |
| 273 | } | 274 | } |
| 274 | 275 | ||
| 275 | static ssize_t ds1553_nvram_write(struct kobject *kobj, char *buf, | 276 | static ssize_t ds1553_nvram_write(struct kobject *kobj, |
| 276 | loff_t pos, size_t size) | 277 | struct bin_attribute *bin_attr, |
| 278 | char *buf, loff_t pos, size_t size) | ||
| 277 | { | 279 | { |
| 278 | struct platform_device *pdev = | 280 | struct platform_device *pdev = |
| 279 | to_platform_device(container_of(kobj, struct device, kobj)); | 281 | to_platform_device(container_of(kobj, struct device, kobj)); |
| @@ -290,7 +292,6 @@ static struct bin_attribute ds1553_nvram_attr = { | |||
| 290 | .attr = { | 292 | .attr = { |
| 291 | .name = "nvram", | 293 | .name = "nvram", |
| 292 | .mode = S_IRUGO | S_IWUGO, | 294 | .mode = S_IRUGO | S_IWUGO, |
| 293 | .owner = THIS_MODULE, | ||
| 294 | }, | 295 | }, |
| 295 | .size = RTC_OFFSET, | 296 | .size = RTC_OFFSET, |
| 296 | .read = ds1553_nvram_read, | 297 | .read = ds1553_nvram_read, |
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index d68288b389dc..d1778ae8bca5 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c | |||
| @@ -127,8 +127,9 @@ static const struct rtc_class_ops ds1742_rtc_ops = { | |||
| 127 | .set_time = ds1742_rtc_set_time, | 127 | .set_time = ds1742_rtc_set_time, |
| 128 | }; | 128 | }; |
| 129 | 129 | ||
| 130 | static ssize_t ds1742_nvram_read(struct kobject *kobj, char *buf, | 130 | static ssize_t ds1742_nvram_read(struct kobject *kobj, |
| 131 | loff_t pos, size_t size) | 131 | struct bin_attribute *bin_attr, |
| 132 | char *buf, loff_t pos, size_t size) | ||
| 132 | { | 133 | { |
| 133 | struct platform_device *pdev = | 134 | struct platform_device *pdev = |
| 134 | to_platform_device(container_of(kobj, struct device, kobj)); | 135 | to_platform_device(container_of(kobj, struct device, kobj)); |
| @@ -141,8 +142,9 @@ static ssize_t ds1742_nvram_read(struct kobject *kobj, char *buf, | |||
| 141 | return count; | 142 | return count; |
| 142 | } | 143 | } |
| 143 | 144 | ||
| 144 | static ssize_t ds1742_nvram_write(struct kobject *kobj, char *buf, | 145 | static ssize_t ds1742_nvram_write(struct kobject *kobj, |
| 145 | loff_t pos, size_t size) | 146 | struct bin_attribute *bin_attr, |
| 147 | char *buf, loff_t pos, size_t size) | ||
| 146 | { | 148 | { |
| 147 | struct platform_device *pdev = | 149 | struct platform_device *pdev = |
| 148 | to_platform_device(container_of(kobj, struct device, kobj)); | 150 | to_platform_device(container_of(kobj, struct device, kobj)); |
| @@ -159,7 +161,6 @@ static struct bin_attribute ds1742_nvram_attr = { | |||
| 159 | .attr = { | 161 | .attr = { |
| 160 | .name = "nvram", | 162 | .name = "nvram", |
| 161 | .mode = S_IRUGO | S_IWUGO, | 163 | .mode = S_IRUGO | S_IWUGO, |
| 162 | .owner = THIS_MODULE, | ||
| 163 | }, | 164 | }, |
| 164 | .read = ds1742_nvram_read, | 165 | .read = ds1742_nvram_read, |
| 165 | .write = ds1742_nvram_write, | 166 | .write = ds1742_nvram_write, |
diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c index ac289e6eadfe..b57d93d986c0 100644 --- a/drivers/s390/cio/chp.c +++ b/drivers/s390/cio/chp.c | |||
| @@ -141,8 +141,9 @@ static int s390_vary_chpid(struct chp_id chpid, int on) | |||
| 141 | /* | 141 | /* |
| 142 | * Channel measurement related functions | 142 | * Channel measurement related functions |
| 143 | */ | 143 | */ |
| 144 | static ssize_t chp_measurement_chars_read(struct kobject *kobj, char *buf, | 144 | static ssize_t chp_measurement_chars_read(struct kobject *kobj, |
| 145 | loff_t off, size_t count) | 145 | struct bin_attribute *bin_attr, |
| 146 | char *buf, loff_t off, size_t count) | ||
| 146 | { | 147 | { |
| 147 | struct channel_path *chp; | 148 | struct channel_path *chp; |
| 148 | unsigned int size; | 149 | unsigned int size; |
| @@ -165,7 +166,6 @@ static struct bin_attribute chp_measurement_chars_attr = { | |||
| 165 | .attr = { | 166 | .attr = { |
| 166 | .name = "measurement_chars", | 167 | .name = "measurement_chars", |
| 167 | .mode = S_IRUSR, | 168 | .mode = S_IRUSR, |
| 168 | .owner = THIS_MODULE, | ||
| 169 | }, | 169 | }, |
| 170 | .size = sizeof(struct cmg_chars), | 170 | .size = sizeof(struct cmg_chars), |
| 171 | .read = chp_measurement_chars_read, | 171 | .read = chp_measurement_chars_read, |
| @@ -193,8 +193,9 @@ static void chp_measurement_copy_block(struct cmg_entry *buf, | |||
| 193 | } while (reference_buf.values[0] != buf->values[0]); | 193 | } while (reference_buf.values[0] != buf->values[0]); |
| 194 | } | 194 | } |
| 195 | 195 | ||
| 196 | static ssize_t chp_measurement_read(struct kobject *kobj, char *buf, | 196 | static ssize_t chp_measurement_read(struct kobject *kobj, |
| 197 | loff_t off, size_t count) | 197 | struct bin_attribute *bin_attr, |
| 198 | char *buf, loff_t off, size_t count) | ||
| 198 | { | 199 | { |
| 199 | struct channel_path *chp; | 200 | struct channel_path *chp; |
| 200 | struct channel_subsystem *css; | 201 | struct channel_subsystem *css; |
| @@ -217,7 +218,6 @@ static struct bin_attribute chp_measurement_attr = { | |||
| 217 | .attr = { | 218 | .attr = { |
| 218 | .name = "measurement", | 219 | .name = "measurement", |
| 219 | .mode = S_IRUSR, | 220 | .mode = S_IRUSR, |
| 220 | .owner = THIS_MODULE, | ||
| 221 | }, | 221 | }, |
| 222 | .size = sizeof(struct cmg_entry), | 222 | .size = sizeof(struct cmg_entry), |
| 223 | .read = chp_measurement_read, | 223 | .read = chp_measurement_read, |
diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c index 65ffc21afc37..bb0287ad1aac 100644 --- a/drivers/s390/net/qeth_sys.c +++ b/drivers/s390/net/qeth_sys.c | |||
| @@ -991,7 +991,7 @@ static struct attribute_group qeth_osn_device_attr_group = { | |||
| 991 | 991 | ||
| 992 | #define QETH_DEVICE_ATTR(_id,_name,_mode,_show,_store) \ | 992 | #define QETH_DEVICE_ATTR(_id,_name,_mode,_show,_store) \ |
| 993 | struct device_attribute dev_attr_##_id = { \ | 993 | struct device_attribute dev_attr_##_id = { \ |
| 994 | .attr = {.name=__stringify(_name), .mode=_mode, .owner=THIS_MODULE },\ | 994 | .attr = {.name=__stringify(_name), .mode=_mode, },\ |
| 995 | .show = _show, \ | 995 | .show = _show, \ |
| 996 | .store = _store, \ | 996 | .store = _store, \ |
| 997 | }; | 997 | }; |
diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c index 03bfed61bffc..06c0dce3b839 100644 --- a/drivers/scsi/arcmsr/arcmsr_attr.c +++ b/drivers/scsi/arcmsr/arcmsr_attr.c | |||
| @@ -59,8 +59,9 @@ | |||
| 59 | struct class_device_attribute *arcmsr_host_attrs[]; | 59 | struct class_device_attribute *arcmsr_host_attrs[]; |
| 60 | 60 | ||
| 61 | static ssize_t | 61 | static ssize_t |
| 62 | arcmsr_sysfs_iop_message_read(struct kobject *kobj, char *buf, loff_t off, | 62 | arcmsr_sysfs_iop_message_read(struct kobject *kobj, |
| 63 | size_t count) | 63 | struct bin_attribute *bin_attr, |
| 64 | char *buf, loff_t off, size_t count) | ||
| 64 | { | 65 | { |
| 65 | struct class_device *cdev = container_of(kobj,struct class_device,kobj); | 66 | struct class_device *cdev = container_of(kobj,struct class_device,kobj); |
| 66 | struct Scsi_Host *host = class_to_shost(cdev); | 67 | struct Scsi_Host *host = class_to_shost(cdev); |
| @@ -105,8 +106,9 @@ arcmsr_sysfs_iop_message_read(struct kobject *kobj, char *buf, loff_t off, | |||
| 105 | } | 106 | } |
| 106 | 107 | ||
| 107 | static ssize_t | 108 | static ssize_t |
| 108 | arcmsr_sysfs_iop_message_write(struct kobject *kobj, char *buf, loff_t off, | 109 | arcmsr_sysfs_iop_message_write(struct kobject *kobj, |
| 109 | size_t count) | 110 | struct bin_attribute *bin_attr, |
| 111 | char *buf, loff_t off, size_t count) | ||
| 110 | { | 112 | { |
| 111 | struct class_device *cdev = container_of(kobj,struct class_device,kobj); | 113 | struct class_device *cdev = container_of(kobj,struct class_device,kobj); |
| 112 | struct Scsi_Host *host = class_to_shost(cdev); | 114 | struct Scsi_Host *host = class_to_shost(cdev); |
| @@ -152,8 +154,9 @@ arcmsr_sysfs_iop_message_write(struct kobject *kobj, char *buf, loff_t off, | |||
| 152 | } | 154 | } |
| 153 | 155 | ||
| 154 | static ssize_t | 156 | static ssize_t |
| 155 | arcmsr_sysfs_iop_message_clear(struct kobject *kobj, char *buf, loff_t off, | 157 | arcmsr_sysfs_iop_message_clear(struct kobject *kobj, |
| 156 | size_t count) | 158 | struct bin_attribute *bin_attr, |
| 159 | char *buf, loff_t off, size_t count) | ||
| 157 | { | 160 | { |
| 158 | struct class_device *cdev = container_of(kobj,struct class_device,kobj); | 161 | struct class_device *cdev = container_of(kobj,struct class_device,kobj); |
| 159 | struct Scsi_Host *host = class_to_shost(cdev); | 162 | struct Scsi_Host *host = class_to_shost(cdev); |
| @@ -188,7 +191,6 @@ static struct bin_attribute arcmsr_sysfs_message_read_attr = { | |||
| 188 | .attr = { | 191 | .attr = { |
| 189 | .name = "mu_read", | 192 | .name = "mu_read", |
| 190 | .mode = S_IRUSR , | 193 | .mode = S_IRUSR , |
| 191 | .owner = THIS_MODULE, | ||
| 192 | }, | 194 | }, |
| 193 | .size = 1032, | 195 | .size = 1032, |
| 194 | .read = arcmsr_sysfs_iop_message_read, | 196 | .read = arcmsr_sysfs_iop_message_read, |
| @@ -198,7 +200,6 @@ static struct bin_attribute arcmsr_sysfs_message_write_attr = { | |||
| 198 | .attr = { | 200 | .attr = { |
| 199 | .name = "mu_write", | 201 | .name = "mu_write", |
| 200 | .mode = S_IWUSR, | 202 | .mode = S_IWUSR, |
| 201 | .owner = THIS_MODULE, | ||
| 202 | }, | 203 | }, |
| 203 | .size = 1032, | 204 | .size = 1032, |
| 204 | .write = arcmsr_sysfs_iop_message_write, | 205 | .write = arcmsr_sysfs_iop_message_write, |
| @@ -208,7 +209,6 @@ static struct bin_attribute arcmsr_sysfs_message_clear_attr = { | |||
| 208 | .attr = { | 209 | .attr = { |
| 209 | .name = "mu_clear", | 210 | .name = "mu_clear", |
| 210 | .mode = S_IWUSR, | 211 | .mode = S_IWUSR, |
| 211 | .owner = THIS_MODULE, | ||
| 212 | }, | 212 | }, |
| 213 | .size = 1, | 213 | .size = 1, |
| 214 | .write = arcmsr_sysfs_iop_message_clear, | 214 | .write = arcmsr_sysfs_iop_message_clear, |
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index fa6ff295e568..4a3083ea59d5 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c | |||
| @@ -2465,6 +2465,7 @@ restart: | |||
| 2465 | /** | 2465 | /** |
| 2466 | * ipr_read_trace - Dump the adapter trace | 2466 | * ipr_read_trace - Dump the adapter trace |
| 2467 | * @kobj: kobject struct | 2467 | * @kobj: kobject struct |
| 2468 | * @bin_attr: bin_attribute struct | ||
| 2468 | * @buf: buffer | 2469 | * @buf: buffer |
| 2469 | * @off: offset | 2470 | * @off: offset |
| 2470 | * @count: buffer size | 2471 | * @count: buffer size |
| @@ -2472,8 +2473,9 @@ restart: | |||
| 2472 | * Return value: | 2473 | * Return value: |
| 2473 | * number of bytes printed to buffer | 2474 | * number of bytes printed to buffer |
| 2474 | **/ | 2475 | **/ |
| 2475 | static ssize_t ipr_read_trace(struct kobject *kobj, char *buf, | 2476 | static ssize_t ipr_read_trace(struct kobject *kobj, |
| 2476 | loff_t off, size_t count) | 2477 | struct bin_attribute *bin_attr, |
| 2478 | char *buf, loff_t off, size_t count) | ||
| 2477 | { | 2479 | { |
| 2478 | struct class_device *cdev = container_of(kobj,struct class_device,kobj); | 2480 | struct class_device *cdev = container_of(kobj,struct class_device,kobj); |
| 2479 | struct Scsi_Host *shost = class_to_shost(cdev); | 2481 | struct Scsi_Host *shost = class_to_shost(cdev); |
| @@ -3166,6 +3168,7 @@ static struct class_device_attribute *ipr_ioa_attrs[] = { | |||
| 3166 | /** | 3168 | /** |
| 3167 | * ipr_read_dump - Dump the adapter | 3169 | * ipr_read_dump - Dump the adapter |
| 3168 | * @kobj: kobject struct | 3170 | * @kobj: kobject struct |
| 3171 | * @bin_attr: bin_attribute struct | ||
| 3169 | * @buf: buffer | 3172 | * @buf: buffer |
| 3170 | * @off: offset | 3173 | * @off: offset |
| 3171 | * @count: buffer size | 3174 | * @count: buffer size |
| @@ -3173,8 +3176,9 @@ static struct class_device_attribute *ipr_ioa_attrs[] = { | |||
| 3173 | * Return value: | 3176 | * Return value: |
| 3174 | * number of bytes printed to buffer | 3177 | * number of bytes printed to buffer |
| 3175 | **/ | 3178 | **/ |
| 3176 | static ssize_t ipr_read_dump(struct kobject *kobj, char *buf, | 3179 | static ssize_t ipr_read_dump(struct kobject *kobj, |
| 3177 | loff_t off, size_t count) | 3180 | struct bin_attribute *bin_attr, |
| 3181 | char *buf, loff_t off, size_t count) | ||
| 3178 | { | 3182 | { |
| 3179 | struct class_device *cdev = container_of(kobj,struct class_device,kobj); | 3183 | struct class_device *cdev = container_of(kobj,struct class_device,kobj); |
| 3180 | struct Scsi_Host *shost = class_to_shost(cdev); | 3184 | struct Scsi_Host *shost = class_to_shost(cdev); |
| @@ -3327,6 +3331,7 @@ static int ipr_free_dump(struct ipr_ioa_cfg *ioa_cfg) | |||
| 3327 | /** | 3331 | /** |
| 3328 | * ipr_write_dump - Setup dump state of adapter | 3332 | * ipr_write_dump - Setup dump state of adapter |
| 3329 | * @kobj: kobject struct | 3333 | * @kobj: kobject struct |
| 3334 | * @bin_attr: bin_attribute struct | ||
| 3330 | * @buf: buffer | 3335 | * @buf: buffer |
| 3331 | * @off: offset | 3336 | * @off: offset |
| 3332 | * @count: buffer size | 3337 | * @count: buffer size |
| @@ -3334,8 +3339,9 @@ static int ipr_free_dump(struct ipr_ioa_cfg *ioa_cfg) | |||
| 3334 | * Return value: | 3339 | * Return value: |
| 3335 | * number of bytes printed to buffer | 3340 | * number of bytes printed to buffer |
| 3336 | **/ | 3341 | **/ |
| 3337 | static ssize_t ipr_write_dump(struct kobject *kobj, char *buf, | 3342 | static ssize_t ipr_write_dump(struct kobject *kobj, |
| 3338 | loff_t off, size_t count) | 3343 | struct bin_attribute *bin_attr, |
| 3344 | char *buf, loff_t off, size_t count) | ||
| 3339 | { | 3345 | { |
| 3340 | struct class_device *cdev = container_of(kobj,struct class_device,kobj); | 3346 | struct class_device *cdev = container_of(kobj,struct class_device,kobj); |
| 3341 | struct Scsi_Host *shost = class_to_shost(cdev); | 3347 | struct Scsi_Host *shost = class_to_shost(cdev); |
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index e34442e405e8..23e90c5f8f35 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c | |||
| @@ -38,8 +38,10 @@ static int sas_disable_routing(struct domain_device *dev, u8 *sas_addr); | |||
| 38 | 38 | ||
| 39 | #if 0 | 39 | #if 0 |
| 40 | /* FIXME: smp needs to migrate into the sas class */ | 40 | /* FIXME: smp needs to migrate into the sas class */ |
| 41 | static ssize_t smp_portal_read(struct kobject *, char *, loff_t, size_t); | 41 | static ssize_t smp_portal_read(struct kobject *, struct bin_attribute *, |
| 42 | static ssize_t smp_portal_write(struct kobject *, char *, loff_t, size_t); | 42 | char *, loff_t, size_t); |
| 43 | static ssize_t smp_portal_write(struct kobject *, struct bin_attribute *, | ||
| 44 | char *, loff_t, size_t); | ||
| 43 | #endif | 45 | #endif |
| 44 | 46 | ||
| 45 | /* ---------- SMP task management ---------- */ | 47 | /* ---------- SMP task management ---------- */ |
| @@ -1368,7 +1370,6 @@ static void sas_ex_smp_hook(struct domain_device *dev) | |||
| 1368 | memset(bin_attr, 0, sizeof(*bin_attr)); | 1370 | memset(bin_attr, 0, sizeof(*bin_attr)); |
| 1369 | 1371 | ||
| 1370 | bin_attr->attr.name = SMP_BIN_ATTR_NAME; | 1372 | bin_attr->attr.name = SMP_BIN_ATTR_NAME; |
| 1371 | bin_attr->attr.owner = THIS_MODULE; | ||
| 1372 | bin_attr->attr.mode = 0600; | 1373 | bin_attr->attr.mode = 0600; |
| 1373 | 1374 | ||
| 1374 | bin_attr->size = 0; | 1375 | bin_attr->size = 0; |
| @@ -1846,8 +1847,9 @@ out: | |||
| 1846 | #if 0 | 1847 | #if 0 |
| 1847 | /* ---------- SMP portal ---------- */ | 1848 | /* ---------- SMP portal ---------- */ |
| 1848 | 1849 | ||
| 1849 | static ssize_t smp_portal_write(struct kobject *kobj, char *buf, loff_t offs, | 1850 | static ssize_t smp_portal_write(struct kobject *kobj, |
| 1850 | size_t size) | 1851 | struct bin_attribute *bin_attr, |
| 1852 | char *buf, loff_t offs, size_t size) | ||
| 1851 | { | 1853 | { |
| 1852 | struct domain_device *dev = to_dom_device(kobj); | 1854 | struct domain_device *dev = to_dom_device(kobj); |
| 1853 | struct expander_device *ex = &dev->ex_dev; | 1855 | struct expander_device *ex = &dev->ex_dev; |
| @@ -1873,8 +1875,9 @@ static ssize_t smp_portal_write(struct kobject *kobj, char *buf, loff_t offs, | |||
| 1873 | return size; | 1875 | return size; |
| 1874 | } | 1876 | } |
| 1875 | 1877 | ||
| 1876 | static ssize_t smp_portal_read(struct kobject *kobj, char *buf, loff_t offs, | 1878 | static ssize_t smp_portal_read(struct kobject *kobj, |
| 1877 | size_t size) | 1879 | struct bin_attribute *bin_attr, |
| 1880 | char *buf, loff_t offs, size_t size) | ||
| 1878 | { | 1881 | { |
| 1879 | struct domain_device *dev = to_dom_device(kobj); | 1882 | struct domain_device *dev = to_dom_device(kobj); |
| 1880 | struct expander_device *ex = &dev->ex_dev; | 1883 | struct expander_device *ex = &dev->ex_dev; |
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 95fe77e816f8..5dfda9778c80 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
| @@ -1133,7 +1133,8 @@ struct class_device_attribute *lpfc_host_attrs[] = { | |||
| 1133 | }; | 1133 | }; |
| 1134 | 1134 | ||
| 1135 | static ssize_t | 1135 | static ssize_t |
| 1136 | sysfs_ctlreg_write(struct kobject *kobj, char *buf, loff_t off, size_t count) | 1136 | sysfs_ctlreg_write(struct kobject *kobj, struct bin_attribute *bin_attr, |
| 1137 | char *buf, loff_t off, size_t count) | ||
| 1137 | { | 1138 | { |
| 1138 | size_t buf_off; | 1139 | size_t buf_off; |
| 1139 | struct Scsi_Host *host = class_to_shost(container_of(kobj, | 1140 | struct Scsi_Host *host = class_to_shost(container_of(kobj, |
| @@ -1165,7 +1166,8 @@ sysfs_ctlreg_write(struct kobject *kobj, char *buf, loff_t off, size_t count) | |||
| 1165 | } | 1166 | } |
| 1166 | 1167 | ||
| 1167 | static ssize_t | 1168 | static ssize_t |
| 1168 | sysfs_ctlreg_read(struct kobject *kobj, char *buf, loff_t off, size_t count) | 1169 | sysfs_ctlreg_read(struct kobject *kobj, struct bin_attribute *bin_attr, |
| 1170 | char *buf, loff_t off, size_t count) | ||
| 1169 | { | 1171 | { |
| 1170 | size_t buf_off; | 1172 | size_t buf_off; |
| 1171 | uint32_t * tmp_ptr; | 1173 | uint32_t * tmp_ptr; |
| @@ -1200,7 +1202,6 @@ static struct bin_attribute sysfs_ctlreg_attr = { | |||
| 1200 | .attr = { | 1202 | .attr = { |
| 1201 | .name = "ctlreg", | 1203 | .name = "ctlreg", |
| 1202 | .mode = S_IRUSR | S_IWUSR, | 1204 | .mode = S_IRUSR | S_IWUSR, |
| 1203 | .owner = THIS_MODULE, | ||
| 1204 | }, | 1205 | }, |
| 1205 | .size = 256, | 1206 | .size = 256, |
| 1206 | .read = sysfs_ctlreg_read, | 1207 | .read = sysfs_ctlreg_read, |
| @@ -1222,7 +1223,8 @@ sysfs_mbox_idle (struct lpfc_hba * phba) | |||
| 1222 | } | 1223 | } |
| 1223 | 1224 | ||
| 1224 | static ssize_t | 1225 | static ssize_t |
| 1225 | sysfs_mbox_write(struct kobject *kobj, char *buf, loff_t off, size_t count) | 1226 | sysfs_mbox_write(struct kobject *kobj, struct bin_attribute *bin_attr, |
| 1227 | char *buf, loff_t off, size_t count) | ||
| 1226 | { | 1228 | { |
| 1227 | struct Scsi_Host * host = | 1229 | struct Scsi_Host * host = |
| 1228 | class_to_shost(container_of(kobj, struct class_device, kobj)); | 1230 | class_to_shost(container_of(kobj, struct class_device, kobj)); |
| @@ -1274,7 +1276,8 @@ sysfs_mbox_write(struct kobject *kobj, char *buf, loff_t off, size_t count) | |||
| 1274 | } | 1276 | } |
| 1275 | 1277 | ||
| 1276 | static ssize_t | 1278 | static ssize_t |
| 1277 | sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count) | 1279 | sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr, |
| 1280 | char *buf, loff_t off, size_t count) | ||
| 1278 | { | 1281 | { |
| 1279 | struct Scsi_Host *host = | 1282 | struct Scsi_Host *host = |
| 1280 | class_to_shost(container_of(kobj, struct class_device, | 1283 | class_to_shost(container_of(kobj, struct class_device, |
| @@ -1422,7 +1425,6 @@ static struct bin_attribute sysfs_mbox_attr = { | |||
| 1422 | .attr = { | 1425 | .attr = { |
| 1423 | .name = "mbox", | 1426 | .name = "mbox", |
| 1424 | .mode = S_IRUSR | S_IWUSR, | 1427 | .mode = S_IRUSR | S_IWUSR, |
| 1425 | .owner = THIS_MODULE, | ||
| 1426 | }, | 1428 | }, |
| 1427 | .size = MAILBOX_CMD_SIZE, | 1429 | .size = MAILBOX_CMD_SIZE, |
| 1428 | .read = sysfs_mbox_read, | 1430 | .read = sysfs_mbox_read, |
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 8081b637d97e..942db9de785e 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
| @@ -11,8 +11,9 @@ | |||
| 11 | /* SYSFS attributes --------------------------------------------------------- */ | 11 | /* SYSFS attributes --------------------------------------------------------- */ |
| 12 | 12 | ||
| 13 | static ssize_t | 13 | static ssize_t |
| 14 | qla2x00_sysfs_read_fw_dump(struct kobject *kobj, char *buf, loff_t off, | 14 | qla2x00_sysfs_read_fw_dump(struct kobject *kobj, |
| 15 | size_t count) | 15 | struct bin_attribute *bin_attr, |
| 16 | char *buf, loff_t off, size_t count) | ||
| 16 | { | 17 | { |
| 17 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, | 18 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, |
| 18 | struct device, kobj))); | 19 | struct device, kobj))); |
| @@ -31,8 +32,9 @@ qla2x00_sysfs_read_fw_dump(struct kobject *kobj, char *buf, loff_t off, | |||
| 31 | } | 32 | } |
| 32 | 33 | ||
| 33 | static ssize_t | 34 | static ssize_t |
| 34 | qla2x00_sysfs_write_fw_dump(struct kobject *kobj, char *buf, loff_t off, | 35 | qla2x00_sysfs_write_fw_dump(struct kobject *kobj, |
| 35 | size_t count) | 36 | struct bin_attribute *bin_attr, |
| 37 | char *buf, loff_t off, size_t count) | ||
| 36 | { | 38 | { |
| 37 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, | 39 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, |
| 38 | struct device, kobj))); | 40 | struct device, kobj))); |
| @@ -73,7 +75,6 @@ static struct bin_attribute sysfs_fw_dump_attr = { | |||
| 73 | .attr = { | 75 | .attr = { |
| 74 | .name = "fw_dump", | 76 | .name = "fw_dump", |
| 75 | .mode = S_IRUSR | S_IWUSR, | 77 | .mode = S_IRUSR | S_IWUSR, |
| 76 | .owner = THIS_MODULE, | ||
| 77 | }, | 78 | }, |
| 78 | .size = 0, | 79 | .size = 0, |
| 79 | .read = qla2x00_sysfs_read_fw_dump, | 80 | .read = qla2x00_sysfs_read_fw_dump, |
| @@ -81,8 +82,9 @@ static struct bin_attribute sysfs_fw_dump_attr = { | |||
| 81 | }; | 82 | }; |
| 82 | 83 | ||
| 83 | static ssize_t | 84 | static ssize_t |
| 84 | qla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf, loff_t off, | 85 | qla2x00_sysfs_read_nvram(struct kobject *kobj, |
| 85 | size_t count) | 86 | struct bin_attribute *bin_attr, |
| 87 | char *buf, loff_t off, size_t count) | ||
| 86 | { | 88 | { |
| 87 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, | 89 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, |
| 88 | struct device, kobj))); | 90 | struct device, kobj))); |
| @@ -101,8 +103,9 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf, loff_t off, | |||
| 101 | } | 103 | } |
| 102 | 104 | ||
| 103 | static ssize_t | 105 | static ssize_t |
| 104 | qla2x00_sysfs_write_nvram(struct kobject *kobj, char *buf, loff_t off, | 106 | qla2x00_sysfs_write_nvram(struct kobject *kobj, |
| 105 | size_t count) | 107 | struct bin_attribute *bin_attr, |
| 108 | char *buf, loff_t off, size_t count) | ||
| 106 | { | 109 | { |
| 107 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, | 110 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, |
| 108 | struct device, kobj))); | 111 | struct device, kobj))); |
| @@ -149,7 +152,6 @@ static struct bin_attribute sysfs_nvram_attr = { | |||
| 149 | .attr = { | 152 | .attr = { |
| 150 | .name = "nvram", | 153 | .name = "nvram", |
| 151 | .mode = S_IRUSR | S_IWUSR, | 154 | .mode = S_IRUSR | S_IWUSR, |
| 152 | .owner = THIS_MODULE, | ||
| 153 | }, | 155 | }, |
| 154 | .size = 512, | 156 | .size = 512, |
| 155 | .read = qla2x00_sysfs_read_nvram, | 157 | .read = qla2x00_sysfs_read_nvram, |
| @@ -157,8 +159,9 @@ static struct bin_attribute sysfs_nvram_attr = { | |||
| 157 | }; | 159 | }; |
| 158 | 160 | ||
| 159 | static ssize_t | 161 | static ssize_t |
| 160 | qla2x00_sysfs_read_optrom(struct kobject *kobj, char *buf, loff_t off, | 162 | qla2x00_sysfs_read_optrom(struct kobject *kobj, |
| 161 | size_t count) | 163 | struct bin_attribute *bin_attr, |
| 164 | char *buf, loff_t off, size_t count) | ||
| 162 | { | 165 | { |
| 163 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, | 166 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, |
| 164 | struct device, kobj))); | 167 | struct device, kobj))); |
| @@ -176,8 +179,9 @@ qla2x00_sysfs_read_optrom(struct kobject *kobj, char *buf, loff_t off, | |||
| 176 | } | 179 | } |
| 177 | 180 | ||
| 178 | static ssize_t | 181 | static ssize_t |
| 179 | qla2x00_sysfs_write_optrom(struct kobject *kobj, char *buf, loff_t off, | 182 | qla2x00_sysfs_write_optrom(struct kobject *kobj, |
| 180 | size_t count) | 183 | struct bin_attribute *bin_attr, |
| 184 | char *buf, loff_t off, size_t count) | ||
| 181 | { | 185 | { |
| 182 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, | 186 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, |
| 183 | struct device, kobj))); | 187 | struct device, kobj))); |
| @@ -198,7 +202,6 @@ static struct bin_attribute sysfs_optrom_attr = { | |||
| 198 | .attr = { | 202 | .attr = { |
| 199 | .name = "optrom", | 203 | .name = "optrom", |
| 200 | .mode = S_IRUSR | S_IWUSR, | 204 | .mode = S_IRUSR | S_IWUSR, |
| 201 | .owner = THIS_MODULE, | ||
| 202 | }, | 205 | }, |
| 203 | .size = OPTROM_SIZE_24XX, | 206 | .size = OPTROM_SIZE_24XX, |
| 204 | .read = qla2x00_sysfs_read_optrom, | 207 | .read = qla2x00_sysfs_read_optrom, |
| @@ -206,8 +209,9 @@ static struct bin_attribute sysfs_optrom_attr = { | |||
| 206 | }; | 209 | }; |
| 207 | 210 | ||
| 208 | static ssize_t | 211 | static ssize_t |
| 209 | qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, char *buf, loff_t off, | 212 | qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, |
| 210 | size_t count) | 213 | struct bin_attribute *bin_attr, |
| 214 | char *buf, loff_t off, size_t count) | ||
| 211 | { | 215 | { |
| 212 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, | 216 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, |
| 213 | struct device, kobj))); | 217 | struct device, kobj))); |
| @@ -279,15 +283,15 @@ static struct bin_attribute sysfs_optrom_ctl_attr = { | |||
| 279 | .attr = { | 283 | .attr = { |
| 280 | .name = "optrom_ctl", | 284 | .name = "optrom_ctl", |
| 281 | .mode = S_IWUSR, | 285 | .mode = S_IWUSR, |
| 282 | .owner = THIS_MODULE, | ||
| 283 | }, | 286 | }, |
| 284 | .size = 0, | 287 | .size = 0, |
| 285 | .write = qla2x00_sysfs_write_optrom_ctl, | 288 | .write = qla2x00_sysfs_write_optrom_ctl, |
| 286 | }; | 289 | }; |
| 287 | 290 | ||
| 288 | static ssize_t | 291 | static ssize_t |
| 289 | qla2x00_sysfs_read_vpd(struct kobject *kobj, char *buf, loff_t off, | 292 | qla2x00_sysfs_read_vpd(struct kobject *kobj, |
| 290 | size_t count) | 293 | struct bin_attribute *bin_attr, |
| 294 | char *buf, loff_t off, size_t count) | ||
| 291 | { | 295 | { |
| 292 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, | 296 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, |
| 293 | struct device, kobj))); | 297 | struct device, kobj))); |
| @@ -305,8 +309,9 @@ qla2x00_sysfs_read_vpd(struct kobject *kobj, char *buf, loff_t off, | |||
| 305 | } | 309 | } |
| 306 | 310 | ||
| 307 | static ssize_t | 311 | static ssize_t |
| 308 | qla2x00_sysfs_write_vpd(struct kobject *kobj, char *buf, loff_t off, | 312 | qla2x00_sysfs_write_vpd(struct kobject *kobj, |
| 309 | size_t count) | 313 | struct bin_attribute *bin_attr, |
| 314 | char *buf, loff_t off, size_t count) | ||
| 310 | { | 315 | { |
| 311 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, | 316 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, |
| 312 | struct device, kobj))); | 317 | struct device, kobj))); |
| @@ -327,7 +332,6 @@ static struct bin_attribute sysfs_vpd_attr = { | |||
| 327 | .attr = { | 332 | .attr = { |
| 328 | .name = "vpd", | 333 | .name = "vpd", |
| 329 | .mode = S_IRUSR | S_IWUSR, | 334 | .mode = S_IRUSR | S_IWUSR, |
| 330 | .owner = THIS_MODULE, | ||
| 331 | }, | 335 | }, |
| 332 | .size = 0, | 336 | .size = 0, |
| 333 | .read = qla2x00_sysfs_read_vpd, | 337 | .read = qla2x00_sysfs_read_vpd, |
| @@ -335,8 +339,9 @@ static struct bin_attribute sysfs_vpd_attr = { | |||
| 335 | }; | 339 | }; |
| 336 | 340 | ||
| 337 | static ssize_t | 341 | static ssize_t |
| 338 | qla2x00_sysfs_read_sfp(struct kobject *kobj, char *buf, loff_t off, | 342 | qla2x00_sysfs_read_sfp(struct kobject *kobj, |
| 339 | size_t count) | 343 | struct bin_attribute *bin_attr, |
| 344 | char *buf, loff_t off, size_t count) | ||
| 340 | { | 345 | { |
| 341 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, | 346 | struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, |
| 342 | struct device, kobj))); | 347 | struct device, kobj))); |
| @@ -375,7 +380,6 @@ static struct bin_attribute sysfs_sfp_attr = { | |||
| 375 | .attr = { | 380 | .attr = { |
| 376 | .name = "sfp", | 381 | .name = "sfp", |
| 377 | .mode = S_IRUSR | S_IWUSR, | 382 | .mode = S_IRUSR | S_IWUSR, |
| 378 | .owner = THIS_MODULE, | ||
| 379 | }, | 383 | }, |
| 380 | .size = SFP_DEV_SIZE * 2, | 384 | .size = SFP_DEV_SIZE * 2, |
| 381 | .read = qla2x00_sysfs_read_sfp, | 385 | .read = qla2x00_sysfs_read_sfp, |
diff --git a/drivers/spi/at25.c b/drivers/spi/at25.c index 8efa07e8b8c2..e007833cca59 100644 --- a/drivers/spi/at25.c +++ b/drivers/spi/at25.c | |||
| @@ -111,7 +111,8 @@ at25_ee_read( | |||
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | static ssize_t | 113 | static ssize_t |
| 114 | at25_bin_read(struct kobject *kobj, char *buf, loff_t off, size_t count) | 114 | at25_bin_read(struct kobject *kobj, struct bin_attribute *bin_attr, |
| 115 | char *buf, loff_t off, size_t count) | ||
| 115 | { | 116 | { |
| 116 | struct device *dev; | 117 | struct device *dev; |
| 117 | struct at25_data *at25; | 118 | struct at25_data *at25; |
| @@ -236,7 +237,8 @@ at25_ee_write(struct at25_data *at25, char *buf, loff_t off, size_t count) | |||
| 236 | } | 237 | } |
| 237 | 238 | ||
| 238 | static ssize_t | 239 | static ssize_t |
| 239 | at25_bin_write(struct kobject *kobj, char *buf, loff_t off, size_t count) | 240 | at25_bin_write(struct kobject *kobj, struct bin_attribute *bin_attr, |
| 241 | char *buf, loff_t off, size_t count) | ||
| 240 | { | 242 | { |
| 241 | struct device *dev; | 243 | struct device *dev; |
| 242 | struct at25_data *at25; | 244 | struct at25_data *at25; |
| @@ -314,7 +316,6 @@ static int at25_probe(struct spi_device *spi) | |||
| 314 | */ | 316 | */ |
| 315 | at25->bin.attr.name = "eeprom"; | 317 | at25->bin.attr.name = "eeprom"; |
| 316 | at25->bin.attr.mode = S_IRUSR; | 318 | at25->bin.attr.mode = S_IRUSR; |
| 317 | at25->bin.attr.owner = THIS_MODULE; | ||
| 318 | at25->bin.read = at25_bin_read; | 319 | at25->bin.read = at25_bin_read; |
| 319 | 320 | ||
| 320 | at25->bin.size = at25->chip.byte_len; | 321 | at25->bin.size = at25->chip.byte_len; |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 24f10a19dbdb..a9cf8b30bccc 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
| @@ -1109,11 +1109,6 @@ void usb_root_hub_lost_power(struct usb_device *rhdev) | |||
| 1109 | 1109 | ||
| 1110 | dev_warn(&rhdev->dev, "root hub lost power or was reset\n"); | 1110 | dev_warn(&rhdev->dev, "root hub lost power or was reset\n"); |
| 1111 | 1111 | ||
| 1112 | /* Make sure no potential wakeup events get lost, | ||
| 1113 | * by forcing the root hub to be resumed. | ||
| 1114 | */ | ||
| 1115 | rhdev->dev.power.prev_state.event = PM_EVENT_ON; | ||
| 1116 | |||
| 1117 | spin_lock_irqsave(&device_state_lock, flags); | 1112 | spin_lock_irqsave(&device_state_lock, flags); |
| 1118 | hub = hdev_to_hub(rhdev); | 1113 | hub = hdev_to_hub(rhdev); |
| 1119 | for (port1 = 1; port1 <= rhdev->maxchild; ++port1) { | 1114 | for (port1 = 1; port1 <= rhdev->maxchild; ++port1) { |
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 2ce050193018..2349e71b0083 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c | |||
| @@ -2102,7 +2102,9 @@ static ssize_t radeon_show_one_edid(char *buf, loff_t off, size_t count, const u | |||
| 2102 | } | 2102 | } |
| 2103 | 2103 | ||
| 2104 | 2104 | ||
| 2105 | static ssize_t radeon_show_edid1(struct kobject *kobj, char *buf, loff_t off, size_t count) | 2105 | static ssize_t radeon_show_edid1(struct kobject *kobj, |
| 2106 | struct bin_attribute *bin_attr, | ||
| 2107 | char *buf, loff_t off, size_t count) | ||
| 2106 | { | 2108 | { |
| 2107 | struct device *dev = container_of(kobj, struct device, kobj); | 2109 | struct device *dev = container_of(kobj, struct device, kobj); |
| 2108 | struct pci_dev *pdev = to_pci_dev(dev); | 2110 | struct pci_dev *pdev = to_pci_dev(dev); |
| @@ -2113,7 +2115,9 @@ static ssize_t radeon_show_edid1(struct kobject *kobj, char *buf, loff_t off, si | |||
| 2113 | } | 2115 | } |
| 2114 | 2116 | ||
| 2115 | 2117 | ||
| 2116 | static ssize_t radeon_show_edid2(struct kobject *kobj, char *buf, loff_t off, size_t count) | 2118 | static ssize_t radeon_show_edid2(struct kobject *kobj, |
| 2119 | struct bin_attribute *bin_attr, | ||
| 2120 | char *buf, loff_t off, size_t count) | ||
| 2117 | { | 2121 | { |
| 2118 | struct device *dev = container_of(kobj, struct device, kobj); | 2122 | struct device *dev = container_of(kobj, struct device, kobj); |
| 2119 | struct pci_dev *pdev = to_pci_dev(dev); | 2123 | struct pci_dev *pdev = to_pci_dev(dev); |
| @@ -2126,7 +2130,6 @@ static ssize_t radeon_show_edid2(struct kobject *kobj, char *buf, loff_t off, si | |||
| 2126 | static struct bin_attribute edid1_attr = { | 2130 | static struct bin_attribute edid1_attr = { |
| 2127 | .attr = { | 2131 | .attr = { |
| 2128 | .name = "edid1", | 2132 | .name = "edid1", |
| 2129 | .owner = THIS_MODULE, | ||
| 2130 | .mode = 0444, | 2133 | .mode = 0444, |
| 2131 | }, | 2134 | }, |
| 2132 | .size = EDID_LENGTH, | 2135 | .size = EDID_LENGTH, |
| @@ -2136,7 +2139,6 @@ static struct bin_attribute edid1_attr = { | |||
| 2136 | static struct bin_attribute edid2_attr = { | 2139 | static struct bin_attribute edid2_attr = { |
| 2137 | .attr = { | 2140 | .attr = { |
| 2138 | .name = "edid2", | 2141 | .name = "edid2", |
| 2139 | .owner = THIS_MODULE, | ||
| 2140 | .mode = 0444, | 2142 | .mode = 0444, |
| 2141 | }, | 2143 | }, |
| 2142 | .size = EDID_LENGTH, | 2144 | .size = EDID_LENGTH, |
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index c65e81ff3578..7e06223bca94 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c | |||
| @@ -172,7 +172,7 @@ static struct class backlight_class = { | |||
| 172 | 172 | ||
| 173 | #define DECLARE_ATTR(_name,_mode,_show,_store) \ | 173 | #define DECLARE_ATTR(_name,_mode,_show,_store) \ |
| 174 | { \ | 174 | { \ |
| 175 | .attr = { .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \ | 175 | .attr = { .name = __stringify(_name), .mode = _mode }, \ |
| 176 | .show = _show, \ | 176 | .show = _show, \ |
| 177 | .store = _store, \ | 177 | .store = _store, \ |
| 178 | } | 178 | } |
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index 6ef8f0a7a137..648b53c1fdea 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c | |||
| @@ -157,7 +157,7 @@ static struct class lcd_class = { | |||
| 157 | 157 | ||
| 158 | #define DECLARE_ATTR(_name,_mode,_show,_store) \ | 158 | #define DECLARE_ATTR(_name,_mode,_show,_store) \ |
| 159 | { \ | 159 | { \ |
| 160 | .attr = { .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \ | 160 | .attr = { .name = __stringify(_name), .mode = _mode }, \ |
| 161 | .show = _show, \ | 161 | .show = _show, \ |
| 162 | .store = _store, \ | 162 | .store = _store, \ |
| 163 | } | 163 | } |
diff --git a/drivers/w1/slaves/w1_ds2433.c b/drivers/w1/slaves/w1_ds2433.c index 8ea17a53eed8..cab56005dd49 100644 --- a/drivers/w1/slaves/w1_ds2433.c +++ b/drivers/w1/slaves/w1_ds2433.c | |||
| @@ -91,8 +91,9 @@ static int w1_f23_refresh_block(struct w1_slave *sl, struct w1_f23_data *data, | |||
| 91 | } | 91 | } |
| 92 | #endif /* CONFIG_W1_SLAVE_DS2433_CRC */ | 92 | #endif /* CONFIG_W1_SLAVE_DS2433_CRC */ |
| 93 | 93 | ||
| 94 | static ssize_t w1_f23_read_bin(struct kobject *kobj, char *buf, loff_t off, | 94 | static ssize_t w1_f23_read_bin(struct kobject *kobj, |
| 95 | size_t count) | 95 | struct bin_attribute *bin_attr, |
| 96 | char *buf, loff_t off, size_t count) | ||
| 96 | { | 97 | { |
| 97 | struct w1_slave *sl = kobj_to_w1_slave(kobj); | 98 | struct w1_slave *sl = kobj_to_w1_slave(kobj); |
| 98 | #ifdef CONFIG_W1_SLAVE_DS2433_CRC | 99 | #ifdef CONFIG_W1_SLAVE_DS2433_CRC |
| @@ -199,8 +200,9 @@ static int w1_f23_write(struct w1_slave *sl, int addr, int len, const u8 *data) | |||
| 199 | return 0; | 200 | return 0; |
| 200 | } | 201 | } |
| 201 | 202 | ||
| 202 | static ssize_t w1_f23_write_bin(struct kobject *kobj, char *buf, loff_t off, | 203 | static ssize_t w1_f23_write_bin(struct kobject *kobj, |
| 203 | size_t count) | 204 | struct bin_attribute *bin_attr, |
| 205 | char *buf, loff_t off, size_t count) | ||
| 204 | { | 206 | { |
| 205 | struct w1_slave *sl = kobj_to_w1_slave(kobj); | 207 | struct w1_slave *sl = kobj_to_w1_slave(kobj); |
| 206 | int addr, len, idx; | 208 | int addr, len, idx; |
| @@ -252,7 +254,6 @@ static struct bin_attribute w1_f23_bin_attr = { | |||
| 252 | .attr = { | 254 | .attr = { |
| 253 | .name = "eeprom", | 255 | .name = "eeprom", |
| 254 | .mode = S_IRUGO | S_IWUSR, | 256 | .mode = S_IRUGO | S_IWUSR, |
| 255 | .owner = THIS_MODULE, | ||
| 256 | }, | 257 | }, |
| 257 | .size = W1_EEPROM_SIZE, | 258 | .size = W1_EEPROM_SIZE, |
| 258 | .read = w1_f23_read_bin, | 259 | .read = w1_f23_read_bin, |
diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c index 1a6937dc190b..4318935678c5 100644 --- a/drivers/w1/slaves/w1_therm.c +++ b/drivers/w1/slaves/w1_therm.c | |||
| @@ -42,13 +42,13 @@ static u8 bad_roms[][9] = { | |||
| 42 | {} | 42 | {} |
| 43 | }; | 43 | }; |
| 44 | 44 | ||
| 45 | static ssize_t w1_therm_read_bin(struct kobject *, char *, loff_t, size_t); | 45 | static ssize_t w1_therm_read_bin(struct kobject *, struct bin_attribute *, |
| 46 | char *, loff_t, size_t); | ||
| 46 | 47 | ||
| 47 | static struct bin_attribute w1_therm_bin_attr = { | 48 | static struct bin_attribute w1_therm_bin_attr = { |
| 48 | .attr = { | 49 | .attr = { |
| 49 | .name = "w1_slave", | 50 | .name = "w1_slave", |
| 50 | .mode = S_IRUGO, | 51 | .mode = S_IRUGO, |
| 51 | .owner = THIS_MODULE, | ||
| 52 | }, | 52 | }, |
| 53 | .size = W1_SLAVE_DATA_SIZE, | 53 | .size = W1_SLAVE_DATA_SIZE, |
| 54 | .read = w1_therm_read_bin, | 54 | .read = w1_therm_read_bin, |
| @@ -159,7 +159,9 @@ static int w1_therm_check_rom(u8 rom[9]) | |||
| 159 | return 0; | 159 | return 0; |
| 160 | } | 160 | } |
| 161 | 161 | ||
| 162 | static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count) | 162 | static ssize_t w1_therm_read_bin(struct kobject *kobj, |
| 163 | struct bin_attribute *bin_attr, | ||
| 164 | char *buf, loff_t off, size_t count) | ||
| 163 | { | 165 | { |
| 164 | struct w1_slave *sl = kobj_to_w1_slave(kobj); | 166 | struct w1_slave *sl = kobj_to_w1_slave(kobj); |
| 165 | struct w1_master *dev = sl->master; | 167 | struct w1_master *dev = sl->master; |
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 7d6876dbcc96..f5c5b760ed7b 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c | |||
| @@ -105,7 +105,9 @@ static ssize_t w1_slave_read_name(struct device *dev, struct device_attribute *a | |||
| 105 | return sprintf(buf, "%s\n", sl->name); | 105 | return sprintf(buf, "%s\n", sl->name); |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | static ssize_t w1_slave_read_id(struct kobject *kobj, char *buf, loff_t off, size_t count) | 108 | static ssize_t w1_slave_read_id(struct kobject *kobj, |
| 109 | struct bin_attribute *bin_attr, | ||
| 110 | char *buf, loff_t off, size_t count) | ||
| 109 | { | 111 | { |
| 110 | struct w1_slave *sl = kobj_to_w1_slave(kobj); | 112 | struct w1_slave *sl = kobj_to_w1_slave(kobj); |
| 111 | 113 | ||
| @@ -128,7 +130,6 @@ static struct bin_attribute w1_slave_attr_bin_id = { | |||
| 128 | .attr = { | 130 | .attr = { |
| 129 | .name = "id", | 131 | .name = "id", |
| 130 | .mode = S_IRUGO, | 132 | .mode = S_IRUGO, |
| 131 | .owner = THIS_MODULE, | ||
| 132 | }, | 133 | }, |
| 133 | .size = 8, | 134 | .size = 8, |
| 134 | .read = w1_slave_read_id, | 135 | .read = w1_slave_read_id, |
| @@ -136,7 +137,9 @@ static struct bin_attribute w1_slave_attr_bin_id = { | |||
| 136 | 137 | ||
| 137 | /* Default family */ | 138 | /* Default family */ |
| 138 | 139 | ||
| 139 | static ssize_t w1_default_write(struct kobject *kobj, char *buf, loff_t off, size_t count) | 140 | static ssize_t w1_default_write(struct kobject *kobj, |
| 141 | struct bin_attribute *bin_attr, | ||
| 142 | char *buf, loff_t off, size_t count) | ||
| 140 | { | 143 | { |
| 141 | struct w1_slave *sl = kobj_to_w1_slave(kobj); | 144 | struct w1_slave *sl = kobj_to_w1_slave(kobj); |
| 142 | 145 | ||
| @@ -153,7 +156,9 @@ out_up: | |||
| 153 | return count; | 156 | return count; |
| 154 | } | 157 | } |
| 155 | 158 | ||
| 156 | static ssize_t w1_default_read(struct kobject *kobj, char *buf, loff_t off, size_t count) | 159 | static ssize_t w1_default_read(struct kobject *kobj, |
| 160 | struct bin_attribute *bin_attr, | ||
| 161 | char *buf, loff_t off, size_t count) | ||
| 157 | { | 162 | { |
| 158 | struct w1_slave *sl = kobj_to_w1_slave(kobj); | 163 | struct w1_slave *sl = kobj_to_w1_slave(kobj); |
| 159 | 164 | ||
| @@ -167,7 +172,6 @@ static struct bin_attribute w1_default_attr = { | |||
| 167 | .attr = { | 172 | .attr = { |
| 168 | .name = "rw", | 173 | .name = "rw", |
| 169 | .mode = S_IRUGO | S_IWUSR, | 174 | .mode = S_IRUGO | S_IWUSR, |
| 170 | .owner = THIS_MODULE, | ||
| 171 | }, | 175 | }, |
| 172 | .size = PAGE_SIZE, | 176 | .size = PAGE_SIZE, |
| 173 | .read = w1_default_read, | 177 | .read = w1_default_read, |
diff --git a/drivers/zorro/zorro-sysfs.c b/drivers/zorro/zorro-sysfs.c index c3ba0ec334c4..9130f1c12c26 100644 --- a/drivers/zorro/zorro-sysfs.c +++ b/drivers/zorro/zorro-sysfs.c | |||
| @@ -49,8 +49,9 @@ static ssize_t zorro_show_resource(struct device *dev, struct device_attribute * | |||
| 49 | 49 | ||
| 50 | static DEVICE_ATTR(resource, S_IRUGO, zorro_show_resource, NULL); | 50 | static DEVICE_ATTR(resource, S_IRUGO, zorro_show_resource, NULL); |
| 51 | 51 | ||
| 52 | static ssize_t zorro_read_config(struct kobject *kobj, char *buf, loff_t off, | 52 | static ssize_t zorro_read_config(struct kobject *kobj, |
| 53 | size_t count) | 53 | struct bin_attribute *bin_attr, |
| 54 | char *buf, loff_t off, size_t count) | ||
| 54 | { | 55 | { |
| 55 | struct zorro_dev *z = to_zorro_dev(container_of(kobj, struct device, | 56 | struct zorro_dev *z = to_zorro_dev(container_of(kobj, struct device, |
| 56 | kobj)); | 57 | kobj)); |
| @@ -78,7 +79,6 @@ static struct bin_attribute zorro_config_attr = { | |||
| 78 | .attr = { | 79 | .attr = { |
| 79 | .name = "config", | 80 | .name = "config", |
| 80 | .mode = S_IRUGO | S_IWUSR, | 81 | .mode = S_IRUGO | S_IWUSR, |
| 81 | .owner = THIS_MODULE | ||
| 82 | }, | 82 | }, |
| 83 | .size = sizeof(struct ConfigDev), | 83 | .size = sizeof(struct ConfigDev), |
| 84 | .read = zorro_read_config, | 84 | .read = zorro_read_config, |
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index ec8896b264de..1d533a2ec3a6 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c | |||
| @@ -368,6 +368,69 @@ void debugfs_remove(struct dentry *dentry) | |||
| 368 | } | 368 | } |
| 369 | EXPORT_SYMBOL_GPL(debugfs_remove); | 369 | EXPORT_SYMBOL_GPL(debugfs_remove); |
| 370 | 370 | ||
| 371 | /** | ||
| 372 | * debugfs_rename - rename a file/directory in the debugfs filesystem | ||
| 373 | * @old_dir: a pointer to the parent dentry for the renamed object. This | ||
| 374 | * should be a directory dentry. | ||
| 375 | * @old_dentry: dentry of an object to be renamed. | ||
| 376 | * @new_dir: a pointer to the parent dentry where the object should be | ||
| 377 | * moved. This should be a directory dentry. | ||
| 378 | * @new_name: a pointer to a string containing the target name. | ||
| 379 | * | ||
| 380 | * This function renames a file/directory in debugfs. The target must not | ||
| 381 | * exist for rename to succeed. | ||
| 382 | * | ||
| 383 | * This function will return a pointer to old_dentry (which is updated to | ||
| 384 | * reflect renaming) if it succeeds. If an error occurs, %NULL will be | ||
| 385 | * returned. | ||
| 386 | * | ||
| 387 | * If debugfs is not enabled in the kernel, the value -%ENODEV will be | ||
| 388 | * returned. | ||
| 389 | */ | ||
| 390 | struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, | ||
| 391 | struct dentry *new_dir, const char *new_name) | ||
| 392 | { | ||
| 393 | int error; | ||
| 394 | struct dentry *dentry = NULL, *trap; | ||
| 395 | const char *old_name; | ||
| 396 | |||
| 397 | trap = lock_rename(new_dir, old_dir); | ||
| 398 | /* Source or destination directories don't exist? */ | ||
| 399 | if (!old_dir->d_inode || !new_dir->d_inode) | ||
| 400 | goto exit; | ||
| 401 | /* Source does not exist, cyclic rename, or mountpoint? */ | ||
| 402 | if (!old_dentry->d_inode || old_dentry == trap || | ||
| 403 | d_mountpoint(old_dentry)) | ||
| 404 | goto exit; | ||
| 405 | dentry = lookup_one_len(new_name, new_dir, strlen(new_name)); | ||
| 406 | /* Lookup failed, cyclic rename or target exists? */ | ||
| 407 | if (IS_ERR(dentry) || dentry == trap || dentry->d_inode) | ||
| 408 | goto exit; | ||
| 409 | |||
| 410 | old_name = fsnotify_oldname_init(old_dentry->d_name.name); | ||
| 411 | |||
| 412 | error = simple_rename(old_dir->d_inode, old_dentry, new_dir->d_inode, | ||
| 413 | dentry); | ||
| 414 | if (error) { | ||
| 415 | fsnotify_oldname_free(old_name); | ||
| 416 | goto exit; | ||
| 417 | } | ||
| 418 | d_move(old_dentry, dentry); | ||
| 419 | fsnotify_move(old_dir->d_inode, new_dir->d_inode, old_name, | ||
| 420 | old_dentry->d_name.name, S_ISDIR(old_dentry->d_inode->i_mode), | ||
| 421 | NULL, old_dentry->d_inode); | ||
| 422 | fsnotify_oldname_free(old_name); | ||
| 423 | unlock_rename(new_dir, old_dir); | ||
| 424 | dput(dentry); | ||
| 425 | return old_dentry; | ||
| 426 | exit: | ||
| 427 | if (dentry && !IS_ERR(dentry)) | ||
| 428 | dput(dentry); | ||
| 429 | unlock_rename(new_dir, old_dir); | ||
| 430 | return NULL; | ||
| 431 | } | ||
| 432 | EXPORT_SYMBOL_GPL(debugfs_rename); | ||
| 433 | |||
| 371 | static decl_subsys(debug, NULL, NULL); | 434 | static decl_subsys(debug, NULL, NULL); |
| 372 | 435 | ||
| 373 | static int __init debugfs_init(void) | 436 | static int __init debugfs_init(void) |
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 606128f5c927..02ca6f1e55d7 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c | |||
| @@ -840,8 +840,6 @@ static int __init ecryptfs_init(void) | |||
| 840 | goto out; | 840 | goto out; |
| 841 | } | 841 | } |
| 842 | kobj_set_kset_s(&ecryptfs_subsys, fs_subsys); | 842 | kobj_set_kset_s(&ecryptfs_subsys, fs_subsys); |
| 843 | sysfs_attr_version.attr.owner = THIS_MODULE; | ||
| 844 | sysfs_attr_version_str.attr.owner = THIS_MODULE; | ||
| 845 | rc = do_sysfs_registration(); | 843 | rc = do_sysfs_registration(); |
| 846 | if (rc) { | 844 | if (rc) { |
| 847 | printk(KERN_ERR "sysfs registration failed\n"); | 845 | printk(KERN_ERR "sysfs registration failed\n"); |
diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index 2b205f5d5790..e9e042b93dbf 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c | |||
| @@ -74,7 +74,6 @@ struct mlog_attribute { | |||
| 74 | #define define_mask(_name) { \ | 74 | #define define_mask(_name) { \ |
| 75 | .attr = { \ | 75 | .attr = { \ |
| 76 | .name = #_name, \ | 76 | .name = #_name, \ |
| 77 | .owner = THIS_MODULE, \ | ||
| 78 | .mode = S_IRUGO | S_IWUSR, \ | 77 | .mode = S_IRUGO | S_IWUSR, \ |
| 79 | }, \ | 78 | }, \ |
| 80 | .mask = ML_##_name, \ | 79 | .mask = ML_##_name, \ |
diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 9a3a058f3553..98e0b85a9bb2 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c | |||
| @@ -397,7 +397,6 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len, | |||
| 397 | static struct attribute addpartattr = { | 397 | static struct attribute addpartattr = { |
| 398 | .name = "whole_disk", | 398 | .name = "whole_disk", |
| 399 | .mode = S_IRUSR | S_IRGRP | S_IROTH, | 399 | .mode = S_IRUSR | S_IRGRP | S_IROTH, |
| 400 | .owner = THIS_MODULE, | ||
| 401 | }; | 400 | }; |
| 402 | 401 | ||
| 403 | sysfs_create_file(&p->kobj, &addpartattr); | 402 | sysfs_create_file(&p->kobj, &addpartattr); |
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index d3b9f5f07db1..135353f8a296 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c | |||
| @@ -20,29 +20,41 @@ | |||
| 20 | 20 | ||
| 21 | #include "sysfs.h" | 21 | #include "sysfs.h" |
| 22 | 22 | ||
| 23 | struct bin_buffer { | ||
| 24 | struct mutex mutex; | ||
| 25 | void *buffer; | ||
| 26 | int mmapped; | ||
| 27 | }; | ||
| 28 | |||
| 23 | static int | 29 | static int |
| 24 | fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count) | 30 | fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count) |
| 25 | { | 31 | { |
| 26 | struct bin_attribute * attr = to_bin_attr(dentry); | 32 | struct sysfs_dirent *attr_sd = dentry->d_fsdata; |
| 27 | struct kobject * kobj = to_kobj(dentry->d_parent); | 33 | struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr; |
| 34 | struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj; | ||
| 35 | int rc; | ||
| 36 | |||
| 37 | /* need attr_sd for attr, its parent for kobj */ | ||
| 38 | if (!sysfs_get_active_two(attr_sd)) | ||
| 39 | return -ENODEV; | ||
| 28 | 40 | ||
| 29 | if (!attr->read) | 41 | rc = -EIO; |
| 30 | return -EIO; | 42 | if (attr->read) |
| 43 | rc = attr->read(kobj, attr, buffer, off, count); | ||
| 31 | 44 | ||
| 32 | return attr->read(kobj, buffer, off, count); | 45 | sysfs_put_active_two(attr_sd); |
| 46 | |||
| 47 | return rc; | ||
| 33 | } | 48 | } |
| 34 | 49 | ||
| 35 | static ssize_t | 50 | static ssize_t |
| 36 | read(struct file * file, char __user * userbuf, size_t count, loff_t * off) | 51 | read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off) |
| 37 | { | 52 | { |
| 38 | char *buffer = file->private_data; | 53 | struct bin_buffer *bb = file->private_data; |
| 39 | struct dentry *dentry = file->f_path.dentry; | 54 | struct dentry *dentry = file->f_path.dentry; |
| 40 | int size = dentry->d_inode->i_size; | 55 | int size = dentry->d_inode->i_size; |
| 41 | loff_t offs = *off; | 56 | loff_t offs = *off; |
| 42 | int ret; | 57 | int count = min_t(size_t, bytes, PAGE_SIZE); |
| 43 | |||
| 44 | if (count > PAGE_SIZE) | ||
| 45 | count = PAGE_SIZE; | ||
| 46 | 58 | ||
| 47 | if (size) { | 59 | if (size) { |
| 48 | if (offs > size) | 60 | if (offs > size) |
| @@ -51,43 +63,56 @@ read(struct file * file, char __user * userbuf, size_t count, loff_t * off) | |||
| 51 | count = size - offs; | 63 | count = size - offs; |
| 52 | } | 64 | } |
| 53 | 65 | ||
| 54 | ret = fill_read(dentry, buffer, offs, count); | 66 | mutex_lock(&bb->mutex); |
| 55 | if (ret < 0) | 67 | |
| 56 | return ret; | 68 | count = fill_read(dentry, bb->buffer, offs, count); |
| 57 | count = ret; | 69 | if (count < 0) |
| 70 | goto out_unlock; | ||
| 58 | 71 | ||
| 59 | if (copy_to_user(userbuf, buffer, count)) | 72 | if (copy_to_user(userbuf, bb->buffer, count)) { |
| 60 | return -EFAULT; | 73 | count = -EFAULT; |
| 74 | goto out_unlock; | ||
| 75 | } | ||
| 61 | 76 | ||
| 62 | pr_debug("offs = %lld, *off = %lld, count = %zd\n", offs, *off, count); | 77 | pr_debug("offs = %lld, *off = %lld, count = %d\n", offs, *off, count); |
| 63 | 78 | ||
| 64 | *off = offs + count; | 79 | *off = offs + count; |
| 65 | 80 | ||
| 81 | out_unlock: | ||
| 82 | mutex_unlock(&bb->mutex); | ||
| 66 | return count; | 83 | return count; |
| 67 | } | 84 | } |
| 68 | 85 | ||
| 69 | static int | 86 | static int |
| 70 | flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count) | 87 | flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count) |
| 71 | { | 88 | { |
| 72 | struct bin_attribute *attr = to_bin_attr(dentry); | 89 | struct sysfs_dirent *attr_sd = dentry->d_fsdata; |
| 73 | struct kobject *kobj = to_kobj(dentry->d_parent); | 90 | struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr; |
| 91 | struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj; | ||
| 92 | int rc; | ||
| 93 | |||
| 94 | /* need attr_sd for attr, its parent for kobj */ | ||
| 95 | if (!sysfs_get_active_two(attr_sd)) | ||
| 96 | return -ENODEV; | ||
| 97 | |||
| 98 | rc = -EIO; | ||
| 99 | if (attr->write) | ||
| 100 | rc = attr->write(kobj, attr, buffer, offset, count); | ||
| 74 | 101 | ||
| 75 | if (!attr->write) | 102 | sysfs_put_active_two(attr_sd); |
| 76 | return -EIO; | ||
| 77 | 103 | ||
| 78 | return attr->write(kobj, buffer, offset, count); | 104 | return rc; |
| 79 | } | 105 | } |
| 80 | 106 | ||
| 81 | static ssize_t write(struct file * file, const char __user * userbuf, | 107 | static ssize_t write(struct file *file, const char __user *userbuf, |
| 82 | size_t count, loff_t * off) | 108 | size_t bytes, loff_t *off) |
| 83 | { | 109 | { |
| 84 | char *buffer = file->private_data; | 110 | struct bin_buffer *bb = file->private_data; |
| 85 | struct dentry *dentry = file->f_path.dentry; | 111 | struct dentry *dentry = file->f_path.dentry; |
| 86 | int size = dentry->d_inode->i_size; | 112 | int size = dentry->d_inode->i_size; |
| 87 | loff_t offs = *off; | 113 | loff_t offs = *off; |
| 114 | int count = min_t(size_t, bytes, PAGE_SIZE); | ||
| 88 | 115 | ||
| 89 | if (count > PAGE_SIZE) | ||
| 90 | count = PAGE_SIZE; | ||
| 91 | if (size) { | 116 | if (size) { |
| 92 | if (offs > size) | 117 | if (offs > size) |
| 93 | return 0; | 118 | return 0; |
| @@ -95,72 +120,100 @@ static ssize_t write(struct file * file, const char __user * userbuf, | |||
| 95 | count = size - offs; | 120 | count = size - offs; |
| 96 | } | 121 | } |
| 97 | 122 | ||
| 98 | if (copy_from_user(buffer, userbuf, count)) | 123 | mutex_lock(&bb->mutex); |
| 99 | return -EFAULT; | ||
| 100 | 124 | ||
| 101 | count = flush_write(dentry, buffer, offs, count); | 125 | if (copy_from_user(bb->buffer, userbuf, count)) { |
| 126 | count = -EFAULT; | ||
| 127 | goto out_unlock; | ||
| 128 | } | ||
| 129 | |||
| 130 | count = flush_write(dentry, bb->buffer, offs, count); | ||
| 102 | if (count > 0) | 131 | if (count > 0) |
| 103 | *off = offs + count; | 132 | *off = offs + count; |
| 133 | |||
| 134 | out_unlock: | ||
| 135 | mutex_unlock(&bb->mutex); | ||
| 104 | return count; | 136 | return count; |
| 105 | } | 137 | } |
| 106 | 138 | ||
| 107 | static int mmap(struct file *file, struct vm_area_struct *vma) | 139 | static int mmap(struct file *file, struct vm_area_struct *vma) |
| 108 | { | 140 | { |
| 109 | struct dentry *dentry = file->f_path.dentry; | 141 | struct bin_buffer *bb = file->private_data; |
| 110 | struct bin_attribute *attr = to_bin_attr(dentry); | 142 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; |
| 111 | struct kobject *kobj = to_kobj(dentry->d_parent); | 143 | struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr; |
| 144 | struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj; | ||
| 145 | int rc; | ||
| 146 | |||
| 147 | mutex_lock(&bb->mutex); | ||
| 148 | |||
| 149 | /* need attr_sd for attr, its parent for kobj */ | ||
| 150 | if (!sysfs_get_active_two(attr_sd)) | ||
| 151 | return -ENODEV; | ||
| 112 | 152 | ||
| 113 | if (!attr->mmap) | 153 | rc = -EINVAL; |
| 114 | return -EINVAL; | 154 | if (attr->mmap) |
| 155 | rc = attr->mmap(kobj, attr, vma); | ||
| 115 | 156 | ||
| 116 | return attr->mmap(kobj, attr, vma); | 157 | if (rc == 0 && !bb->mmapped) |
| 158 | bb->mmapped = 1; | ||
| 159 | else | ||
| 160 | sysfs_put_active_two(attr_sd); | ||
| 161 | |||
| 162 | mutex_unlock(&bb->mutex); | ||
| 163 | |||
| 164 | return rc; | ||
| 117 | } | 165 | } |
| 118 | 166 | ||
| 119 | static int open(struct inode * inode, struct file * file) | 167 | static int open(struct inode * inode, struct file * file) |
| 120 | { | 168 | { |
| 121 | struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent); | 169 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; |
| 122 | struct bin_attribute * attr = to_bin_attr(file->f_path.dentry); | 170 | struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr; |
| 123 | int error = -EINVAL; | 171 | struct bin_buffer *bb = NULL; |
| 124 | 172 | int error; | |
| 125 | if (!kobj || !attr) | ||
| 126 | goto Done; | ||
| 127 | 173 | ||
| 128 | /* Grab the module reference for this attribute if we have one */ | 174 | /* need attr_sd for attr */ |
| 129 | error = -ENODEV; | 175 | if (!sysfs_get_active(attr_sd)) |
| 130 | if (!try_module_get(attr->attr.owner)) | 176 | return -ENODEV; |
| 131 | goto Done; | ||
| 132 | 177 | ||
| 133 | error = -EACCES; | 178 | error = -EACCES; |
| 134 | if ((file->f_mode & FMODE_WRITE) && !(attr->write || attr->mmap)) | 179 | if ((file->f_mode & FMODE_WRITE) && !(attr->write || attr->mmap)) |
| 135 | goto Error; | 180 | goto err_out; |
| 136 | if ((file->f_mode & FMODE_READ) && !(attr->read || attr->mmap)) | 181 | if ((file->f_mode & FMODE_READ) && !(attr->read || attr->mmap)) |
| 137 | goto Error; | 182 | goto err_out; |
| 138 | 183 | ||
| 139 | error = -ENOMEM; | 184 | error = -ENOMEM; |
| 140 | file->private_data = kmalloc(PAGE_SIZE, GFP_KERNEL); | 185 | bb = kzalloc(sizeof(*bb), GFP_KERNEL); |
| 141 | if (!file->private_data) | 186 | if (!bb) |
| 142 | goto Error; | 187 | goto err_out; |
| 143 | 188 | ||
| 144 | error = 0; | 189 | bb->buffer = kmalloc(PAGE_SIZE, GFP_KERNEL); |
| 145 | goto Done; | 190 | if (!bb->buffer) |
| 146 | 191 | goto err_out; | |
| 147 | Error: | 192 | |
| 148 | module_put(attr->attr.owner); | 193 | mutex_init(&bb->mutex); |
| 149 | Done: | 194 | file->private_data = bb; |
| 150 | if (error) | 195 | |
| 151 | kobject_put(kobj); | 196 | /* open succeeded, put active reference and pin attr_sd */ |
| 197 | sysfs_put_active(attr_sd); | ||
| 198 | sysfs_get(attr_sd); | ||
| 199 | return 0; | ||
| 200 | |||
| 201 | err_out: | ||
| 202 | sysfs_put_active(attr_sd); | ||
| 203 | kfree(bb); | ||
| 152 | return error; | 204 | return error; |
| 153 | } | 205 | } |
| 154 | 206 | ||
| 155 | static int release(struct inode * inode, struct file * file) | 207 | static int release(struct inode * inode, struct file * file) |
| 156 | { | 208 | { |
| 157 | struct kobject * kobj = to_kobj(file->f_path.dentry->d_parent); | 209 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; |
| 158 | struct bin_attribute * attr = to_bin_attr(file->f_path.dentry); | 210 | struct bin_buffer *bb = file->private_data; |
| 159 | u8 * buffer = file->private_data; | 211 | |
| 160 | 212 | if (bb->mmapped) | |
| 161 | kobject_put(kobj); | 213 | sysfs_put_active_two(attr_sd); |
| 162 | module_put(attr->attr.owner); | 214 | sysfs_put(attr_sd); |
| 163 | kfree(buffer); | 215 | kfree(bb->buffer); |
| 216 | kfree(bb); | ||
| 164 | return 0; | 217 | return 0; |
| 165 | } | 218 | } |
| 166 | 219 | ||
| @@ -181,9 +234,9 @@ const struct file_operations bin_fops = { | |||
| 181 | 234 | ||
| 182 | int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr) | 235 | int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr) |
| 183 | { | 236 | { |
| 184 | BUG_ON(!kobj || !kobj->dentry || !attr); | 237 | BUG_ON(!kobj || !kobj->sd || !attr); |
| 185 | 238 | ||
| 186 | return sysfs_add_file(kobj->dentry, &attr->attr, SYSFS_KOBJ_BIN_ATTR); | 239 | return sysfs_add_file(kobj->sd, &attr->attr, SYSFS_KOBJ_BIN_ATTR); |
| 187 | } | 240 | } |
| 188 | 241 | ||
| 189 | 242 | ||
| @@ -195,7 +248,7 @@ int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr) | |||
| 195 | 248 | ||
| 196 | void sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr) | 249 | void sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr) |
| 197 | { | 250 | { |
| 198 | if (sysfs_hash_and_remove(kobj->dentry, attr->attr.name) < 0) { | 251 | if (sysfs_hash_and_remove(kobj->sd, attr->attr.name) < 0) { |
| 199 | printk(KERN_ERR "%s: " | 252 | printk(KERN_ERR "%s: " |
| 200 | "bad dentry or inode or no such file: \"%s\"\n", | 253 | "bad dentry or inode or no such file: \"%s\"\n", |
| 201 | __FUNCTION__, attr->attr.name); | 254 | __FUNCTION__, attr->attr.name); |
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index c4342a019972..aee966c44aac 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
| @@ -9,21 +9,337 @@ | |||
| 9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
| 10 | #include <linux/kobject.h> | 10 | #include <linux/kobject.h> |
| 11 | #include <linux/namei.h> | 11 | #include <linux/namei.h> |
| 12 | #include <linux/idr.h> | ||
| 13 | #include <linux/completion.h> | ||
| 12 | #include <asm/semaphore.h> | 14 | #include <asm/semaphore.h> |
| 13 | #include "sysfs.h" | 15 | #include "sysfs.h" |
| 14 | 16 | ||
| 15 | DECLARE_RWSEM(sysfs_rename_sem); | 17 | DEFINE_MUTEX(sysfs_mutex); |
| 16 | spinlock_t sysfs_lock = SPIN_LOCK_UNLOCKED; | 18 | spinlock_t sysfs_assoc_lock = SPIN_LOCK_UNLOCKED; |
| 19 | |||
| 20 | static spinlock_t sysfs_ino_lock = SPIN_LOCK_UNLOCKED; | ||
| 21 | static DEFINE_IDA(sysfs_ino_ida); | ||
| 22 | |||
| 23 | /** | ||
| 24 | * sysfs_link_sibling - link sysfs_dirent into sibling list | ||
| 25 | * @sd: sysfs_dirent of interest | ||
| 26 | * | ||
| 27 | * Link @sd into its sibling list which starts from | ||
| 28 | * sd->s_parent->s_children. | ||
| 29 | * | ||
| 30 | * Locking: | ||
| 31 | * mutex_lock(sysfs_mutex) | ||
| 32 | */ | ||
| 33 | void sysfs_link_sibling(struct sysfs_dirent *sd) | ||
| 34 | { | ||
| 35 | struct sysfs_dirent *parent_sd = sd->s_parent; | ||
| 36 | |||
| 37 | BUG_ON(sd->s_sibling); | ||
| 38 | sd->s_sibling = parent_sd->s_children; | ||
| 39 | parent_sd->s_children = sd; | ||
| 40 | } | ||
| 41 | |||
| 42 | /** | ||
| 43 | * sysfs_unlink_sibling - unlink sysfs_dirent from sibling list | ||
| 44 | * @sd: sysfs_dirent of interest | ||
| 45 | * | ||
| 46 | * Unlink @sd from its sibling list which starts from | ||
| 47 | * sd->s_parent->s_children. | ||
| 48 | * | ||
| 49 | * Locking: | ||
| 50 | * mutex_lock(sysfs_mutex) | ||
| 51 | */ | ||
| 52 | void sysfs_unlink_sibling(struct sysfs_dirent *sd) | ||
| 53 | { | ||
| 54 | struct sysfs_dirent **pos; | ||
| 55 | |||
| 56 | for (pos = &sd->s_parent->s_children; *pos; pos = &(*pos)->s_sibling) { | ||
| 57 | if (*pos == sd) { | ||
| 58 | *pos = sd->s_sibling; | ||
| 59 | sd->s_sibling = NULL; | ||
| 60 | break; | ||
| 61 | } | ||
| 62 | } | ||
| 63 | } | ||
| 64 | |||
| 65 | /** | ||
| 66 | * sysfs_get_dentry - get dentry for the given sysfs_dirent | ||
| 67 | * @sd: sysfs_dirent of interest | ||
| 68 | * | ||
| 69 | * Get dentry for @sd. Dentry is looked up if currently not | ||
| 70 | * present. This function climbs sysfs_dirent tree till it | ||
| 71 | * reaches a sysfs_dirent with valid dentry attached and descends | ||
| 72 | * down from there looking up dentry for each step. | ||
| 73 | * | ||
| 74 | * LOCKING: | ||
| 75 | * Kernel thread context (may sleep) | ||
| 76 | * | ||
| 77 | * RETURNS: | ||
| 78 | * Pointer to found dentry on success, ERR_PTR() value on error. | ||
| 79 | */ | ||
| 80 | struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd) | ||
| 81 | { | ||
| 82 | struct sysfs_dirent *cur; | ||
| 83 | struct dentry *parent_dentry, *dentry; | ||
| 84 | int i, depth; | ||
| 85 | |||
| 86 | /* Find the first parent which has valid s_dentry and get the | ||
| 87 | * dentry. | ||
| 88 | */ | ||
| 89 | mutex_lock(&sysfs_mutex); | ||
| 90 | restart0: | ||
| 91 | spin_lock(&sysfs_assoc_lock); | ||
| 92 | restart1: | ||
| 93 | spin_lock(&dcache_lock); | ||
| 94 | |||
| 95 | dentry = NULL; | ||
| 96 | depth = 0; | ||
| 97 | cur = sd; | ||
| 98 | while (!cur->s_dentry || !cur->s_dentry->d_inode) { | ||
| 99 | if (cur->s_flags & SYSFS_FLAG_REMOVED) { | ||
| 100 | dentry = ERR_PTR(-ENOENT); | ||
| 101 | depth = 0; | ||
| 102 | break; | ||
| 103 | } | ||
| 104 | cur = cur->s_parent; | ||
| 105 | depth++; | ||
| 106 | } | ||
| 107 | if (!IS_ERR(dentry)) | ||
| 108 | dentry = dget_locked(cur->s_dentry); | ||
| 109 | |||
| 110 | spin_unlock(&dcache_lock); | ||
| 111 | spin_unlock(&sysfs_assoc_lock); | ||
| 112 | |||
| 113 | /* from the found dentry, look up depth times */ | ||
| 114 | while (depth--) { | ||
| 115 | /* find and get depth'th ancestor */ | ||
| 116 | for (cur = sd, i = 0; cur && i < depth; i++) | ||
| 117 | cur = cur->s_parent; | ||
| 118 | |||
| 119 | /* This can happen if tree structure was modified due | ||
| 120 | * to move/rename. Restart. | ||
| 121 | */ | ||
| 122 | if (i != depth) { | ||
| 123 | dput(dentry); | ||
| 124 | goto restart0; | ||
| 125 | } | ||
| 126 | |||
| 127 | sysfs_get(cur); | ||
| 128 | |||
| 129 | mutex_unlock(&sysfs_mutex); | ||
| 130 | |||
| 131 | /* look it up */ | ||
| 132 | parent_dentry = dentry; | ||
| 133 | dentry = lookup_one_len_kern(cur->s_name, parent_dentry, | ||
| 134 | strlen(cur->s_name)); | ||
| 135 | dput(parent_dentry); | ||
| 136 | |||
| 137 | if (IS_ERR(dentry)) { | ||
| 138 | sysfs_put(cur); | ||
| 139 | return dentry; | ||
| 140 | } | ||
| 141 | |||
| 142 | mutex_lock(&sysfs_mutex); | ||
| 143 | spin_lock(&sysfs_assoc_lock); | ||
| 144 | |||
| 145 | /* This, again, can happen if tree structure has | ||
| 146 | * changed and we looked up the wrong thing. Restart. | ||
| 147 | */ | ||
| 148 | if (cur->s_dentry != dentry) { | ||
| 149 | dput(dentry); | ||
| 150 | sysfs_put(cur); | ||
| 151 | goto restart1; | ||
| 152 | } | ||
| 153 | |||
| 154 | spin_unlock(&sysfs_assoc_lock); | ||
| 155 | |||
| 156 | sysfs_put(cur); | ||
| 157 | } | ||
| 158 | |||
| 159 | mutex_unlock(&sysfs_mutex); | ||
| 160 | return dentry; | ||
| 161 | } | ||
| 162 | |||
| 163 | /** | ||
| 164 | * sysfs_get_active - get an active reference to sysfs_dirent | ||
| 165 | * @sd: sysfs_dirent to get an active reference to | ||
| 166 | * | ||
| 167 | * Get an active reference of @sd. This function is noop if @sd | ||
| 168 | * is NULL. | ||
| 169 | * | ||
| 170 | * RETURNS: | ||
| 171 | * Pointer to @sd on success, NULL on failure. | ||
| 172 | */ | ||
| 173 | struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd) | ||
| 174 | { | ||
| 175 | if (unlikely(!sd)) | ||
| 176 | return NULL; | ||
| 177 | |||
| 178 | while (1) { | ||
| 179 | int v, t; | ||
| 180 | |||
| 181 | v = atomic_read(&sd->s_active); | ||
| 182 | if (unlikely(v < 0)) | ||
| 183 | return NULL; | ||
| 184 | |||
| 185 | t = atomic_cmpxchg(&sd->s_active, v, v + 1); | ||
| 186 | if (likely(t == v)) | ||
| 187 | return sd; | ||
| 188 | if (t < 0) | ||
| 189 | return NULL; | ||
| 190 | |||
| 191 | cpu_relax(); | ||
| 192 | } | ||
| 193 | } | ||
| 194 | |||
| 195 | /** | ||
| 196 | * sysfs_put_active - put an active reference to sysfs_dirent | ||
| 197 | * @sd: sysfs_dirent to put an active reference to | ||
| 198 | * | ||
| 199 | * Put an active reference to @sd. This function is noop if @sd | ||
| 200 | * is NULL. | ||
| 201 | */ | ||
| 202 | void sysfs_put_active(struct sysfs_dirent *sd) | ||
| 203 | { | ||
| 204 | struct completion *cmpl; | ||
| 205 | int v; | ||
| 206 | |||
| 207 | if (unlikely(!sd)) | ||
| 208 | return; | ||
| 209 | |||
| 210 | v = atomic_dec_return(&sd->s_active); | ||
| 211 | if (likely(v != SD_DEACTIVATED_BIAS)) | ||
| 212 | return; | ||
| 213 | |||
| 214 | /* atomic_dec_return() is a mb(), we'll always see the updated | ||
| 215 | * sd->s_sibling. | ||
| 216 | */ | ||
| 217 | cmpl = (void *)sd->s_sibling; | ||
| 218 | complete(cmpl); | ||
| 219 | } | ||
| 220 | |||
| 221 | /** | ||
| 222 | * sysfs_get_active_two - get active references to sysfs_dirent and parent | ||
| 223 | * @sd: sysfs_dirent of interest | ||
| 224 | * | ||
| 225 | * Get active reference to @sd and its parent. Parent's active | ||
| 226 | * reference is grabbed first. This function is noop if @sd is | ||
| 227 | * NULL. | ||
| 228 | * | ||
| 229 | * RETURNS: | ||
| 230 | * Pointer to @sd on success, NULL on failure. | ||
| 231 | */ | ||
| 232 | struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd) | ||
| 233 | { | ||
| 234 | if (sd) { | ||
| 235 | if (sd->s_parent && unlikely(!sysfs_get_active(sd->s_parent))) | ||
| 236 | return NULL; | ||
| 237 | if (unlikely(!sysfs_get_active(sd))) { | ||
| 238 | sysfs_put_active(sd->s_parent); | ||
| 239 | return NULL; | ||
| 240 | } | ||
| 241 | } | ||
| 242 | return sd; | ||
| 243 | } | ||
| 244 | |||
| 245 | /** | ||
| 246 | * sysfs_put_active_two - put active references to sysfs_dirent and parent | ||
| 247 | * @sd: sysfs_dirent of interest | ||
| 248 | * | ||
| 249 | * Put active references to @sd and its parent. This function is | ||
| 250 | * noop if @sd is NULL. | ||
| 251 | */ | ||
| 252 | void sysfs_put_active_two(struct sysfs_dirent *sd) | ||
| 253 | { | ||
| 254 | if (sd) { | ||
| 255 | sysfs_put_active(sd); | ||
| 256 | sysfs_put_active(sd->s_parent); | ||
| 257 | } | ||
| 258 | } | ||
| 259 | |||
| 260 | /** | ||
| 261 | * sysfs_deactivate - deactivate sysfs_dirent | ||
| 262 | * @sd: sysfs_dirent to deactivate | ||
| 263 | * | ||
| 264 | * Deny new active references and drain existing ones. | ||
| 265 | */ | ||
| 266 | static void sysfs_deactivate(struct sysfs_dirent *sd) | ||
| 267 | { | ||
| 268 | DECLARE_COMPLETION_ONSTACK(wait); | ||
| 269 | int v; | ||
| 270 | |||
| 271 | BUG_ON(sd->s_sibling || !(sd->s_flags & SYSFS_FLAG_REMOVED)); | ||
| 272 | sd->s_sibling = (void *)&wait; | ||
| 273 | |||
| 274 | /* atomic_add_return() is a mb(), put_active() will always see | ||
| 275 | * the updated sd->s_sibling. | ||
| 276 | */ | ||
| 277 | v = atomic_add_return(SD_DEACTIVATED_BIAS, &sd->s_active); | ||
| 278 | |||
| 279 | if (v != SD_DEACTIVATED_BIAS) | ||
| 280 | wait_for_completion(&wait); | ||
| 281 | |||
| 282 | sd->s_sibling = NULL; | ||
| 283 | } | ||
| 284 | |||
| 285 | static int sysfs_alloc_ino(ino_t *pino) | ||
| 286 | { | ||
| 287 | int ino, rc; | ||
| 288 | |||
| 289 | retry: | ||
| 290 | spin_lock(&sysfs_ino_lock); | ||
| 291 | rc = ida_get_new_above(&sysfs_ino_ida, 2, &ino); | ||
| 292 | spin_unlock(&sysfs_ino_lock); | ||
| 293 | |||
| 294 | if (rc == -EAGAIN) { | ||
| 295 | if (ida_pre_get(&sysfs_ino_ida, GFP_KERNEL)) | ||
| 296 | goto retry; | ||
| 297 | rc = -ENOMEM; | ||
| 298 | } | ||
| 299 | |||
| 300 | *pino = ino; | ||
| 301 | return rc; | ||
| 302 | } | ||
| 303 | |||
| 304 | static void sysfs_free_ino(ino_t ino) | ||
| 305 | { | ||
| 306 | spin_lock(&sysfs_ino_lock); | ||
| 307 | ida_remove(&sysfs_ino_ida, ino); | ||
| 308 | spin_unlock(&sysfs_ino_lock); | ||
| 309 | } | ||
| 310 | |||
| 311 | void release_sysfs_dirent(struct sysfs_dirent * sd) | ||
| 312 | { | ||
| 313 | struct sysfs_dirent *parent_sd; | ||
| 314 | |||
| 315 | repeat: | ||
| 316 | /* Moving/renaming is always done while holding reference. | ||
| 317 | * sd->s_parent won't change beneath us. | ||
| 318 | */ | ||
| 319 | parent_sd = sd->s_parent; | ||
| 320 | |||
| 321 | if (sysfs_type(sd) == SYSFS_KOBJ_LINK) | ||
| 322 | sysfs_put(sd->s_elem.symlink.target_sd); | ||
| 323 | if (sysfs_type(sd) & SYSFS_COPY_NAME) | ||
| 324 | kfree(sd->s_name); | ||
| 325 | kfree(sd->s_iattr); | ||
| 326 | sysfs_free_ino(sd->s_ino); | ||
| 327 | kmem_cache_free(sysfs_dir_cachep, sd); | ||
| 328 | |||
| 329 | sd = parent_sd; | ||
| 330 | if (sd && atomic_dec_and_test(&sd->s_count)) | ||
| 331 | goto repeat; | ||
| 332 | } | ||
| 17 | 333 | ||
| 18 | static void sysfs_d_iput(struct dentry * dentry, struct inode * inode) | 334 | static void sysfs_d_iput(struct dentry * dentry, struct inode * inode) |
| 19 | { | 335 | { |
| 20 | struct sysfs_dirent * sd = dentry->d_fsdata; | 336 | struct sysfs_dirent * sd = dentry->d_fsdata; |
| 21 | 337 | ||
| 22 | if (sd) { | 338 | if (sd) { |
| 23 | /* sd->s_dentry is protected with sysfs_lock. This | 339 | /* sd->s_dentry is protected with sysfs_assoc_lock. |
| 24 | * allows sysfs_drop_dentry() to dereference it. | 340 | * This allows sysfs_drop_dentry() to dereference it. |
| 25 | */ | 341 | */ |
| 26 | spin_lock(&sysfs_lock); | 342 | spin_lock(&sysfs_assoc_lock); |
| 27 | 343 | ||
| 28 | /* The dentry might have been deleted or another | 344 | /* The dentry might have been deleted or another |
| 29 | * lookup could have happened updating sd->s_dentry to | 345 | * lookup could have happened updating sd->s_dentry to |
| @@ -32,7 +348,7 @@ static void sysfs_d_iput(struct dentry * dentry, struct inode * inode) | |||
| 32 | */ | 348 | */ |
| 33 | if (sd->s_dentry == dentry) | 349 | if (sd->s_dentry == dentry) |
| 34 | sd->s_dentry = NULL; | 350 | sd->s_dentry = NULL; |
| 35 | spin_unlock(&sysfs_lock); | 351 | spin_unlock(&sysfs_assoc_lock); |
| 36 | sysfs_put(sd); | 352 | sysfs_put(sd); |
| 37 | } | 353 | } |
| 38 | iput(inode); | 354 | iput(inode); |
| @@ -42,260 +358,402 @@ static struct dentry_operations sysfs_dentry_ops = { | |||
| 42 | .d_iput = sysfs_d_iput, | 358 | .d_iput = sysfs_d_iput, |
| 43 | }; | 359 | }; |
| 44 | 360 | ||
| 45 | static unsigned int sysfs_inode_counter; | 361 | struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) |
| 46 | ino_t sysfs_get_inum(void) | ||
| 47 | { | 362 | { |
| 48 | if (unlikely(sysfs_inode_counter < 3)) | 363 | char *dup_name = NULL; |
| 49 | sysfs_inode_counter = 3; | 364 | struct sysfs_dirent *sd = NULL; |
| 50 | return sysfs_inode_counter++; | ||
| 51 | } | ||
| 52 | 365 | ||
| 53 | /* | 366 | if (type & SYSFS_COPY_NAME) { |
| 54 | * Allocates a new sysfs_dirent and links it to the parent sysfs_dirent | 367 | name = dup_name = kstrdup(name, GFP_KERNEL); |
| 55 | */ | 368 | if (!name) |
| 56 | static struct sysfs_dirent * __sysfs_new_dirent(void * element) | 369 | goto err_out; |
| 57 | { | 370 | } |
| 58 | struct sysfs_dirent * sd; | ||
| 59 | 371 | ||
| 60 | sd = kmem_cache_zalloc(sysfs_dir_cachep, GFP_KERNEL); | 372 | sd = kmem_cache_zalloc(sysfs_dir_cachep, GFP_KERNEL); |
| 61 | if (!sd) | 373 | if (!sd) |
| 62 | return NULL; | 374 | goto err_out; |
| 375 | |||
| 376 | if (sysfs_alloc_ino(&sd->s_ino)) | ||
| 377 | goto err_out; | ||
| 63 | 378 | ||
| 64 | sd->s_ino = sysfs_get_inum(); | ||
| 65 | atomic_set(&sd->s_count, 1); | 379 | atomic_set(&sd->s_count, 1); |
| 380 | atomic_set(&sd->s_active, 0); | ||
| 66 | atomic_set(&sd->s_event, 1); | 381 | atomic_set(&sd->s_event, 1); |
| 67 | INIT_LIST_HEAD(&sd->s_children); | 382 | |
| 68 | INIT_LIST_HEAD(&sd->s_sibling); | 383 | sd->s_name = name; |
| 69 | sd->s_element = element; | 384 | sd->s_mode = mode; |
| 385 | sd->s_flags = type; | ||
| 70 | 386 | ||
| 71 | return sd; | 387 | return sd; |
| 388 | |||
| 389 | err_out: | ||
| 390 | kfree(dup_name); | ||
| 391 | kmem_cache_free(sysfs_dir_cachep, sd); | ||
| 392 | return NULL; | ||
| 72 | } | 393 | } |
| 73 | 394 | ||
| 74 | static void __sysfs_list_dirent(struct sysfs_dirent *parent_sd, | 395 | /** |
| 75 | struct sysfs_dirent *sd) | 396 | * sysfs_attach_dentry - associate sysfs_dirent with dentry |
| 397 | * @sd: target sysfs_dirent | ||
| 398 | * @dentry: dentry to associate | ||
| 399 | * | ||
| 400 | * Associate @sd with @dentry. This is protected by | ||
| 401 | * sysfs_assoc_lock to avoid race with sysfs_d_iput(). | ||
| 402 | * | ||
| 403 | * LOCKING: | ||
| 404 | * mutex_lock(sysfs_mutex) | ||
| 405 | */ | ||
| 406 | static void sysfs_attach_dentry(struct sysfs_dirent *sd, struct dentry *dentry) | ||
| 76 | { | 407 | { |
| 77 | if (sd) | 408 | dentry->d_op = &sysfs_dentry_ops; |
| 78 | list_add(&sd->s_sibling, &parent_sd->s_children); | 409 | dentry->d_fsdata = sysfs_get(sd); |
| 410 | |||
| 411 | /* protect sd->s_dentry against sysfs_d_iput */ | ||
| 412 | spin_lock(&sysfs_assoc_lock); | ||
| 413 | sd->s_dentry = dentry; | ||
| 414 | spin_unlock(&sysfs_assoc_lock); | ||
| 415 | |||
| 416 | d_rehash(dentry); | ||
| 79 | } | 417 | } |
| 80 | 418 | ||
| 81 | static struct sysfs_dirent * sysfs_new_dirent(struct sysfs_dirent *parent_sd, | 419 | static int sysfs_ilookup_test(struct inode *inode, void *arg) |
| 82 | void * element) | ||
| 83 | { | 420 | { |
| 84 | struct sysfs_dirent *sd; | 421 | struct sysfs_dirent *sd = arg; |
| 85 | sd = __sysfs_new_dirent(element); | 422 | return inode->i_ino == sd->s_ino; |
| 86 | __sysfs_list_dirent(parent_sd, sd); | ||
| 87 | return sd; | ||
| 88 | } | 423 | } |
| 89 | 424 | ||
| 90 | /* | 425 | /** |
| 426 | * sysfs_addrm_start - prepare for sysfs_dirent add/remove | ||
| 427 | * @acxt: pointer to sysfs_addrm_cxt to be used | ||
| 428 | * @parent_sd: parent sysfs_dirent | ||
| 91 | * | 429 | * |
| 92 | * Return -EEXIST if there is already a sysfs element with the same name for | 430 | * This function is called when the caller is about to add or |
| 93 | * the same parent. | 431 | * remove sysfs_dirent under @parent_sd. This function acquires |
| 432 | * sysfs_mutex, grabs inode for @parent_sd if available and lock | ||
| 433 | * i_mutex of it. @acxt is used to keep and pass context to | ||
| 434 | * other addrm functions. | ||
| 94 | * | 435 | * |
| 95 | * called with parent inode's i_mutex held | 436 | * LOCKING: |
| 437 | * Kernel thread context (may sleep). sysfs_mutex is locked on | ||
| 438 | * return. i_mutex of parent inode is locked on return if | ||
| 439 | * available. | ||
| 96 | */ | 440 | */ |
| 97 | int sysfs_dirent_exist(struct sysfs_dirent *parent_sd, | 441 | void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, |
| 98 | const unsigned char *new) | 442 | struct sysfs_dirent *parent_sd) |
| 99 | { | 443 | { |
| 100 | struct sysfs_dirent * sd; | 444 | struct inode *inode; |
| 101 | 445 | ||
| 102 | list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { | 446 | memset(acxt, 0, sizeof(*acxt)); |
| 103 | if (sd->s_element) { | 447 | acxt->parent_sd = parent_sd; |
| 104 | const unsigned char *existing = sysfs_get_name(sd); | ||
| 105 | if (strcmp(existing, new)) | ||
| 106 | continue; | ||
| 107 | else | ||
| 108 | return -EEXIST; | ||
| 109 | } | ||
| 110 | } | ||
| 111 | 448 | ||
| 112 | return 0; | 449 | /* Lookup parent inode. inode initialization and I_NEW |
| 450 | * clearing are protected by sysfs_mutex. By grabbing it and | ||
| 451 | * looking up with _nowait variant, inode state can be | ||
| 452 | * determined reliably. | ||
| 453 | */ | ||
| 454 | mutex_lock(&sysfs_mutex); | ||
| 455 | |||
| 456 | inode = ilookup5_nowait(sysfs_sb, parent_sd->s_ino, sysfs_ilookup_test, | ||
| 457 | parent_sd); | ||
| 458 | |||
| 459 | if (inode && !(inode->i_state & I_NEW)) { | ||
| 460 | /* parent inode available */ | ||
| 461 | acxt->parent_inode = inode; | ||
| 462 | |||
| 463 | /* sysfs_mutex is below i_mutex in lock hierarchy. | ||
| 464 | * First, trylock i_mutex. If fails, unlock | ||
| 465 | * sysfs_mutex and lock them in order. | ||
| 466 | */ | ||
| 467 | if (!mutex_trylock(&inode->i_mutex)) { | ||
| 468 | mutex_unlock(&sysfs_mutex); | ||
| 469 | mutex_lock(&inode->i_mutex); | ||
| 470 | mutex_lock(&sysfs_mutex); | ||
| 471 | } | ||
| 472 | } else | ||
| 473 | iput(inode); | ||
| 113 | } | 474 | } |
| 114 | 475 | ||
| 476 | /** | ||
| 477 | * sysfs_add_one - add sysfs_dirent to parent | ||
| 478 | * @acxt: addrm context to use | ||
| 479 | * @sd: sysfs_dirent to be added | ||
| 480 | * | ||
| 481 | * Get @acxt->parent_sd and set sd->s_parent to it and increment | ||
| 482 | * nlink of parent inode if @sd is a directory. @sd is NOT | ||
| 483 | * linked into the children list of the parent. The caller | ||
| 484 | * should invoke sysfs_link_sibling() after this function | ||
| 485 | * completes if @sd needs to be on the children list. | ||
| 486 | * | ||
| 487 | * This function should be called between calls to | ||
| 488 | * sysfs_addrm_start() and sysfs_addrm_finish() and should be | ||
| 489 | * passed the same @acxt as passed to sysfs_addrm_start(). | ||
| 490 | * | ||
| 491 | * LOCKING: | ||
| 492 | * Determined by sysfs_addrm_start(). | ||
| 493 | */ | ||
| 494 | void sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) | ||
| 495 | { | ||
| 496 | sd->s_parent = sysfs_get(acxt->parent_sd); | ||
| 497 | |||
| 498 | if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode) | ||
| 499 | inc_nlink(acxt->parent_inode); | ||
| 500 | |||
| 501 | acxt->cnt++; | ||
| 502 | } | ||
| 115 | 503 | ||
| 116 | static struct sysfs_dirent * | 504 | /** |
| 117 | __sysfs_make_dirent(struct dentry *dentry, void *element, mode_t mode, int type) | 505 | * sysfs_remove_one - remove sysfs_dirent from parent |
| 506 | * @acxt: addrm context to use | ||
| 507 | * @sd: sysfs_dirent to be added | ||
| 508 | * | ||
| 509 | * Mark @sd removed and drop nlink of parent inode if @sd is a | ||
| 510 | * directory. @sd is NOT unlinked from the children list of the | ||
| 511 | * parent. The caller is repsonsible for removing @sd from the | ||
| 512 | * children list before calling this function. | ||
| 513 | * | ||
| 514 | * This function should be called between calls to | ||
| 515 | * sysfs_addrm_start() and sysfs_addrm_finish() and should be | ||
| 516 | * passed the same @acxt as passed to sysfs_addrm_start(). | ||
| 517 | * | ||
| 518 | * LOCKING: | ||
| 519 | * Determined by sysfs_addrm_start(). | ||
| 520 | */ | ||
| 521 | void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) | ||
| 118 | { | 522 | { |
| 119 | struct sysfs_dirent * sd; | 523 | BUG_ON(sd->s_sibling || (sd->s_flags & SYSFS_FLAG_REMOVED)); |
| 120 | 524 | ||
| 121 | sd = __sysfs_new_dirent(element); | 525 | sd->s_flags |= SYSFS_FLAG_REMOVED; |
| 122 | if (!sd) | 526 | sd->s_sibling = acxt->removed; |
| 123 | goto out; | 527 | acxt->removed = sd; |
| 124 | 528 | ||
| 125 | sd->s_mode = mode; | 529 | if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode) |
| 126 | sd->s_type = type; | 530 | drop_nlink(acxt->parent_inode); |
| 127 | sd->s_dentry = dentry; | ||
| 128 | if (dentry) { | ||
| 129 | dentry->d_fsdata = sysfs_get(sd); | ||
| 130 | dentry->d_op = &sysfs_dentry_ops; | ||
| 131 | } | ||
| 132 | 531 | ||
| 133 | out: | 532 | acxt->cnt++; |
| 134 | return sd; | ||
| 135 | } | 533 | } |
| 136 | 534 | ||
| 137 | int sysfs_make_dirent(struct sysfs_dirent * parent_sd, struct dentry * dentry, | 535 | /** |
| 138 | void * element, umode_t mode, int type) | 536 | * sysfs_drop_dentry - drop dentry for the specified sysfs_dirent |
| 537 | * @sd: target sysfs_dirent | ||
| 538 | * | ||
| 539 | * Drop dentry for @sd. @sd must have been unlinked from its | ||
| 540 | * parent on entry to this function such that it can't be looked | ||
| 541 | * up anymore. | ||
| 542 | * | ||
| 543 | * @sd->s_dentry which is protected with sysfs_assoc_lock points | ||
| 544 | * to the currently associated dentry but we're not holding a | ||
| 545 | * reference to it and racing with dput(). Grab dcache_lock and | ||
| 546 | * verify dentry before dropping it. If @sd->s_dentry is NULL or | ||
| 547 | * dput() beats us, no need to bother. | ||
| 548 | */ | ||
| 549 | static void sysfs_drop_dentry(struct sysfs_dirent *sd) | ||
| 139 | { | 550 | { |
| 140 | struct sysfs_dirent *sd; | 551 | struct dentry *dentry = NULL; |
| 552 | struct inode *inode; | ||
| 553 | |||
| 554 | /* We're not holding a reference to ->s_dentry dentry but the | ||
| 555 | * field will stay valid as long as sysfs_assoc_lock is held. | ||
| 556 | */ | ||
| 557 | spin_lock(&sysfs_assoc_lock); | ||
| 558 | spin_lock(&dcache_lock); | ||
| 559 | |||
| 560 | /* drop dentry if it's there and dput() didn't kill it yet */ | ||
| 561 | if (sd->s_dentry && sd->s_dentry->d_inode) { | ||
| 562 | dentry = dget_locked(sd->s_dentry); | ||
| 563 | spin_lock(&dentry->d_lock); | ||
| 564 | __d_drop(dentry); | ||
| 565 | spin_unlock(&dentry->d_lock); | ||
| 566 | } | ||
| 141 | 567 | ||
| 142 | sd = __sysfs_make_dirent(dentry, element, mode, type); | 568 | spin_unlock(&dcache_lock); |
| 143 | __sysfs_list_dirent(parent_sd, sd); | 569 | spin_unlock(&sysfs_assoc_lock); |
| 144 | 570 | ||
| 145 | return sd ? 0 : -ENOMEM; | 571 | /* dentries for shadowed inodes are pinned, unpin */ |
| 572 | if (dentry && sysfs_is_shadowed_inode(dentry->d_inode)) | ||
| 573 | dput(dentry); | ||
| 574 | dput(dentry); | ||
| 575 | |||
| 576 | /* adjust nlink and update timestamp */ | ||
| 577 | inode = ilookup(sysfs_sb, sd->s_ino); | ||
| 578 | if (inode) { | ||
| 579 | mutex_lock(&inode->i_mutex); | ||
| 580 | |||
| 581 | inode->i_ctime = CURRENT_TIME; | ||
| 582 | drop_nlink(inode); | ||
| 583 | if (sysfs_type(sd) == SYSFS_DIR) | ||
| 584 | drop_nlink(inode); | ||
| 585 | |||
| 586 | mutex_unlock(&inode->i_mutex); | ||
| 587 | iput(inode); | ||
| 588 | } | ||
| 146 | } | 589 | } |
| 147 | 590 | ||
| 148 | static int init_dir(struct inode * inode) | 591 | /** |
| 592 | * sysfs_addrm_finish - finish up sysfs_dirent add/remove | ||
| 593 | * @acxt: addrm context to finish up | ||
| 594 | * | ||
| 595 | * Finish up sysfs_dirent add/remove. Resources acquired by | ||
| 596 | * sysfs_addrm_start() are released and removed sysfs_dirents are | ||
| 597 | * cleaned up. Timestamps on the parent inode are updated. | ||
| 598 | * | ||
| 599 | * LOCKING: | ||
| 600 | * All mutexes acquired by sysfs_addrm_start() are released. | ||
| 601 | * | ||
| 602 | * RETURNS: | ||
| 603 | * Number of added/removed sysfs_dirents since sysfs_addrm_start(). | ||
| 604 | */ | ||
| 605 | int sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt) | ||
| 149 | { | 606 | { |
| 150 | inode->i_op = &sysfs_dir_inode_operations; | 607 | /* release resources acquired by sysfs_addrm_start() */ |
| 151 | inode->i_fop = &sysfs_dir_operations; | 608 | mutex_unlock(&sysfs_mutex); |
| 609 | if (acxt->parent_inode) { | ||
| 610 | struct inode *inode = acxt->parent_inode; | ||
| 152 | 611 | ||
| 153 | /* directory inodes start off with i_nlink == 2 (for "." entry) */ | 612 | /* if added/removed, update timestamps on the parent */ |
| 154 | inc_nlink(inode); | 613 | if (acxt->cnt) |
| 155 | return 0; | 614 | inode->i_ctime = inode->i_mtime = CURRENT_TIME; |
| 615 | |||
| 616 | mutex_unlock(&inode->i_mutex); | ||
| 617 | iput(inode); | ||
| 618 | } | ||
| 619 | |||
| 620 | /* kill removed sysfs_dirents */ | ||
| 621 | while (acxt->removed) { | ||
| 622 | struct sysfs_dirent *sd = acxt->removed; | ||
| 623 | |||
| 624 | acxt->removed = sd->s_sibling; | ||
| 625 | sd->s_sibling = NULL; | ||
| 626 | |||
| 627 | sysfs_drop_dentry(sd); | ||
| 628 | sysfs_deactivate(sd); | ||
| 629 | sysfs_put(sd); | ||
| 630 | } | ||
| 631 | |||
| 632 | return acxt->cnt; | ||
| 156 | } | 633 | } |
| 157 | 634 | ||
| 158 | static int init_file(struct inode * inode) | 635 | /** |
| 636 | * sysfs_find_dirent - find sysfs_dirent with the given name | ||
| 637 | * @parent_sd: sysfs_dirent to search under | ||
| 638 | * @name: name to look for | ||
| 639 | * | ||
| 640 | * Look for sysfs_dirent with name @name under @parent_sd. | ||
| 641 | * | ||
| 642 | * LOCKING: | ||
| 643 | * mutex_lock(sysfs_mutex) | ||
| 644 | * | ||
| 645 | * RETURNS: | ||
| 646 | * Pointer to sysfs_dirent if found, NULL if not. | ||
| 647 | */ | ||
| 648 | struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, | ||
| 649 | const unsigned char *name) | ||
| 159 | { | 650 | { |
| 160 | inode->i_size = PAGE_SIZE; | 651 | struct sysfs_dirent *sd; |
| 161 | inode->i_fop = &sysfs_file_operations; | 652 | |
| 162 | return 0; | 653 | for (sd = parent_sd->s_children; sd; sd = sd->s_sibling) |
| 654 | if (sysfs_type(sd) && !strcmp(sd->s_name, name)) | ||
| 655 | return sd; | ||
| 656 | return NULL; | ||
| 163 | } | 657 | } |
| 164 | 658 | ||
| 165 | static int init_symlink(struct inode * inode) | 659 | /** |
| 660 | * sysfs_get_dirent - find and get sysfs_dirent with the given name | ||
| 661 | * @parent_sd: sysfs_dirent to search under | ||
| 662 | * @name: name to look for | ||
| 663 | * | ||
| 664 | * Look for sysfs_dirent with name @name under @parent_sd and get | ||
| 665 | * it if found. | ||
| 666 | * | ||
| 667 | * LOCKING: | ||
| 668 | * Kernel thread context (may sleep). Grabs sysfs_mutex. | ||
| 669 | * | ||
| 670 | * RETURNS: | ||
| 671 | * Pointer to sysfs_dirent if found, NULL if not. | ||
| 672 | */ | ||
| 673 | struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, | ||
| 674 | const unsigned char *name) | ||
| 166 | { | 675 | { |
| 167 | inode->i_op = &sysfs_symlink_inode_operations; | 676 | struct sysfs_dirent *sd; |
| 168 | return 0; | 677 | |
| 678 | mutex_lock(&sysfs_mutex); | ||
| 679 | sd = sysfs_find_dirent(parent_sd, name); | ||
| 680 | sysfs_get(sd); | ||
| 681 | mutex_unlock(&sysfs_mutex); | ||
| 682 | |||
| 683 | return sd; | ||
| 169 | } | 684 | } |
| 170 | 685 | ||
| 171 | static int create_dir(struct kobject * k, struct dentry * p, | 686 | static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, |
| 172 | const char * n, struct dentry ** d) | 687 | const char *name, struct sysfs_dirent **p_sd) |
| 173 | { | 688 | { |
| 174 | int error; | ||
| 175 | umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; | 689 | umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; |
| 690 | struct sysfs_addrm_cxt acxt; | ||
| 691 | struct sysfs_dirent *sd; | ||
| 176 | 692 | ||
| 177 | mutex_lock(&p->d_inode->i_mutex); | 693 | /* allocate */ |
| 178 | *d = lookup_one_len(n, p, strlen(n)); | 694 | sd = sysfs_new_dirent(name, mode, SYSFS_DIR); |
| 179 | if (!IS_ERR(*d)) { | 695 | if (!sd) |
| 180 | if (sysfs_dirent_exist(p->d_fsdata, n)) | 696 | return -ENOMEM; |
| 181 | error = -EEXIST; | 697 | sd->s_elem.dir.kobj = kobj; |
| 182 | else | ||
| 183 | error = sysfs_make_dirent(p->d_fsdata, *d, k, mode, | ||
| 184 | SYSFS_DIR); | ||
| 185 | if (!error) { | ||
| 186 | error = sysfs_create(*d, mode, init_dir); | ||
| 187 | if (!error) { | ||
| 188 | inc_nlink(p->d_inode); | ||
| 189 | (*d)->d_op = &sysfs_dentry_ops; | ||
| 190 | d_rehash(*d); | ||
| 191 | } | ||
| 192 | } | ||
| 193 | if (error && (error != -EEXIST)) { | ||
| 194 | struct sysfs_dirent *sd = (*d)->d_fsdata; | ||
| 195 | if (sd) { | ||
| 196 | list_del_init(&sd->s_sibling); | ||
| 197 | sysfs_put(sd); | ||
| 198 | } | ||
| 199 | d_drop(*d); | ||
| 200 | } | ||
| 201 | dput(*d); | ||
| 202 | } else | ||
| 203 | error = PTR_ERR(*d); | ||
| 204 | mutex_unlock(&p->d_inode->i_mutex); | ||
| 205 | return error; | ||
| 206 | } | ||
| 207 | 698 | ||
| 699 | /* link in */ | ||
| 700 | sysfs_addrm_start(&acxt, parent_sd); | ||
| 701 | if (!sysfs_find_dirent(parent_sd, name)) { | ||
| 702 | sysfs_add_one(&acxt, sd); | ||
| 703 | sysfs_link_sibling(sd); | ||
| 704 | } | ||
| 705 | if (sysfs_addrm_finish(&acxt)) { | ||
| 706 | *p_sd = sd; | ||
| 707 | return 0; | ||
| 708 | } | ||
| 208 | 709 | ||
| 209 | int sysfs_create_subdir(struct kobject * k, const char * n, struct dentry ** d) | 710 | sysfs_put(sd); |
| 711 | return -EEXIST; | ||
| 712 | } | ||
| 713 | |||
| 714 | int sysfs_create_subdir(struct kobject *kobj, const char *name, | ||
| 715 | struct sysfs_dirent **p_sd) | ||
| 210 | { | 716 | { |
| 211 | return create_dir(k,k->dentry,n,d); | 717 | return create_dir(kobj, kobj->sd, name, p_sd); |
| 212 | } | 718 | } |
| 213 | 719 | ||
| 214 | /** | 720 | /** |
| 215 | * sysfs_create_dir - create a directory for an object. | 721 | * sysfs_create_dir - create a directory for an object. |
| 216 | * @kobj: object we're creating directory for. | 722 | * @kobj: object we're creating directory for. |
| 217 | * @shadow_parent: parent parent object. | 723 | * @shadow_parent: parent object. |
| 218 | */ | 724 | */ |
| 219 | 725 | int sysfs_create_dir(struct kobject *kobj, | |
| 220 | int sysfs_create_dir(struct kobject * kobj, struct dentry *shadow_parent) | 726 | struct sysfs_dirent *shadow_parent_sd) |
| 221 | { | 727 | { |
| 222 | struct dentry * dentry = NULL; | 728 | struct sysfs_dirent *parent_sd, *sd; |
| 223 | struct dentry * parent; | ||
| 224 | int error = 0; | 729 | int error = 0; |
| 225 | 730 | ||
| 226 | BUG_ON(!kobj); | 731 | BUG_ON(!kobj); |
| 227 | 732 | ||
| 228 | if (shadow_parent) | 733 | if (shadow_parent_sd) |
| 229 | parent = shadow_parent; | 734 | parent_sd = shadow_parent_sd; |
| 230 | else if (kobj->parent) | 735 | else if (kobj->parent) |
| 231 | parent = kobj->parent->dentry; | 736 | parent_sd = kobj->parent->sd; |
| 232 | else if (sysfs_mount && sysfs_mount->mnt_sb) | 737 | else if (sysfs_mount && sysfs_mount->mnt_sb) |
| 233 | parent = sysfs_mount->mnt_sb->s_root; | 738 | parent_sd = sysfs_mount->mnt_sb->s_root->d_fsdata; |
| 234 | else | 739 | else |
| 235 | return -EFAULT; | 740 | return -EFAULT; |
| 236 | 741 | ||
| 237 | error = create_dir(kobj,parent,kobject_name(kobj),&dentry); | 742 | error = create_dir(kobj, parent_sd, kobject_name(kobj), &sd); |
| 238 | if (!error) | 743 | if (!error) |
| 239 | kobj->dentry = dentry; | 744 | kobj->sd = sd; |
| 240 | return error; | 745 | return error; |
| 241 | } | 746 | } |
| 242 | 747 | ||
| 243 | /* attaches attribute's sysfs_dirent to the dentry corresponding to the | 748 | static int sysfs_count_nlink(struct sysfs_dirent *sd) |
| 244 | * attribute file | ||
| 245 | */ | ||
| 246 | static int sysfs_attach_attr(struct sysfs_dirent * sd, struct dentry * dentry) | ||
| 247 | { | 749 | { |
| 248 | struct attribute * attr = NULL; | 750 | struct sysfs_dirent *child; |
| 249 | struct bin_attribute * bin_attr = NULL; | 751 | int nr = 0; |
| 250 | int (* init) (struct inode *) = NULL; | ||
| 251 | int error = 0; | ||
| 252 | |||
| 253 | if (sd->s_type & SYSFS_KOBJ_BIN_ATTR) { | ||
| 254 | bin_attr = sd->s_element; | ||
| 255 | attr = &bin_attr->attr; | ||
| 256 | } else { | ||
| 257 | attr = sd->s_element; | ||
| 258 | init = init_file; | ||
| 259 | } | ||
| 260 | 752 | ||
| 261 | dentry->d_fsdata = sysfs_get(sd); | 753 | for (child = sd->s_children; child; child = child->s_sibling) |
| 262 | /* protect sd->s_dentry against sysfs_d_iput */ | 754 | if (sysfs_type(child) == SYSFS_DIR) |
| 263 | spin_lock(&sysfs_lock); | 755 | nr++; |
| 264 | sd->s_dentry = dentry; | 756 | return nr + 2; |
| 265 | spin_unlock(&sysfs_lock); | ||
| 266 | error = sysfs_create(dentry, (attr->mode & S_IALLUGO) | S_IFREG, init); | ||
| 267 | if (error) { | ||
| 268 | sysfs_put(sd); | ||
| 269 | return error; | ||
| 270 | } | ||
| 271 | |||
| 272 | if (bin_attr) { | ||
| 273 | dentry->d_inode->i_size = bin_attr->size; | ||
| 274 | dentry->d_inode->i_fop = &bin_fops; | ||
| 275 | } | ||
| 276 | dentry->d_op = &sysfs_dentry_ops; | ||
| 277 | d_rehash(dentry); | ||
| 278 | |||
| 279 | return 0; | ||
| 280 | } | ||
| 281 | |||
| 282 | static int sysfs_attach_link(struct sysfs_dirent * sd, struct dentry * dentry) | ||
| 283 | { | ||
| 284 | int err = 0; | ||
| 285 | |||
| 286 | dentry->d_fsdata = sysfs_get(sd); | ||
| 287 | /* protect sd->s_dentry against sysfs_d_iput */ | ||
| 288 | spin_lock(&sysfs_lock); | ||
| 289 | sd->s_dentry = dentry; | ||
| 290 | spin_unlock(&sysfs_lock); | ||
| 291 | err = sysfs_create(dentry, S_IFLNK|S_IRWXUGO, init_symlink); | ||
| 292 | if (!err) { | ||
| 293 | dentry->d_op = &sysfs_dentry_ops; | ||
| 294 | d_rehash(dentry); | ||
| 295 | } else | ||
| 296 | sysfs_put(sd); | ||
| 297 | |||
| 298 | return err; | ||
| 299 | } | 757 | } |
| 300 | 758 | ||
| 301 | static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, | 759 | static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, |
| @@ -303,24 +761,60 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, | |||
| 303 | { | 761 | { |
| 304 | struct sysfs_dirent * parent_sd = dentry->d_parent->d_fsdata; | 762 | struct sysfs_dirent * parent_sd = dentry->d_parent->d_fsdata; |
| 305 | struct sysfs_dirent * sd; | 763 | struct sysfs_dirent * sd; |
| 306 | int err = 0; | 764 | struct bin_attribute *bin_attr; |
| 765 | struct inode *inode; | ||
| 766 | int found = 0; | ||
| 307 | 767 | ||
| 308 | list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { | 768 | for (sd = parent_sd->s_children; sd; sd = sd->s_sibling) { |
| 309 | if (sd->s_type & SYSFS_NOT_PINNED) { | 769 | if (sysfs_type(sd) && |
| 310 | const unsigned char * name = sysfs_get_name(sd); | 770 | !strcmp(sd->s_name, dentry->d_name.name)) { |
| 771 | found = 1; | ||
| 772 | break; | ||
| 773 | } | ||
| 774 | } | ||
| 311 | 775 | ||
| 312 | if (strcmp(name, dentry->d_name.name)) | 776 | /* no such entry */ |
| 313 | continue; | 777 | if (!found) |
| 778 | return NULL; | ||
| 314 | 779 | ||
| 315 | if (sd->s_type & SYSFS_KOBJ_LINK) | 780 | /* attach dentry and inode */ |
| 316 | err = sysfs_attach_link(sd, dentry); | 781 | inode = sysfs_get_inode(sd); |
| 317 | else | 782 | if (!inode) |
| 318 | err = sysfs_attach_attr(sd, dentry); | 783 | return ERR_PTR(-ENOMEM); |
| 784 | |||
| 785 | mutex_lock(&sysfs_mutex); | ||
| 786 | |||
| 787 | if (inode->i_state & I_NEW) { | ||
| 788 | /* initialize inode according to type */ | ||
| 789 | switch (sysfs_type(sd)) { | ||
| 790 | case SYSFS_DIR: | ||
| 791 | inode->i_op = &sysfs_dir_inode_operations; | ||
| 792 | inode->i_fop = &sysfs_dir_operations; | ||
| 793 | inode->i_nlink = sysfs_count_nlink(sd); | ||
| 794 | break; | ||
| 795 | case SYSFS_KOBJ_ATTR: | ||
| 796 | inode->i_size = PAGE_SIZE; | ||
| 797 | inode->i_fop = &sysfs_file_operations; | ||
| 798 | break; | ||
| 799 | case SYSFS_KOBJ_BIN_ATTR: | ||
| 800 | bin_attr = sd->s_elem.bin_attr.bin_attr; | ||
| 801 | inode->i_size = bin_attr->size; | ||
| 802 | inode->i_fop = &bin_fops; | ||
| 319 | break; | 803 | break; |
| 804 | case SYSFS_KOBJ_LINK: | ||
| 805 | inode->i_op = &sysfs_symlink_inode_operations; | ||
| 806 | break; | ||
| 807 | default: | ||
| 808 | BUG(); | ||
| 320 | } | 809 | } |
| 321 | } | 810 | } |
| 322 | 811 | ||
| 323 | return ERR_PTR(err); | 812 | sysfs_instantiate(dentry, inode); |
| 813 | sysfs_attach_dentry(sd, dentry); | ||
| 814 | |||
| 815 | mutex_unlock(&sysfs_mutex); | ||
| 816 | |||
| 817 | return NULL; | ||
| 324 | } | 818 | } |
| 325 | 819 | ||
| 326 | const struct inode_operations sysfs_dir_inode_operations = { | 820 | const struct inode_operations sysfs_dir_inode_operations = { |
| @@ -328,58 +822,46 @@ const struct inode_operations sysfs_dir_inode_operations = { | |||
| 328 | .setattr = sysfs_setattr, | 822 | .setattr = sysfs_setattr, |
| 329 | }; | 823 | }; |
| 330 | 824 | ||
| 331 | static void remove_dir(struct dentry * d) | 825 | static void remove_dir(struct sysfs_dirent *sd) |
| 332 | { | 826 | { |
| 333 | struct dentry * parent = dget(d->d_parent); | 827 | struct sysfs_addrm_cxt acxt; |
| 334 | struct sysfs_dirent * sd; | ||
| 335 | |||
| 336 | mutex_lock(&parent->d_inode->i_mutex); | ||
| 337 | d_delete(d); | ||
| 338 | sd = d->d_fsdata; | ||
| 339 | list_del_init(&sd->s_sibling); | ||
| 340 | sysfs_put(sd); | ||
| 341 | if (d->d_inode) | ||
| 342 | simple_rmdir(parent->d_inode,d); | ||
| 343 | |||
| 344 | pr_debug(" o %s removing done (%d)\n",d->d_name.name, | ||
| 345 | atomic_read(&d->d_count)); | ||
| 346 | 828 | ||
| 347 | mutex_unlock(&parent->d_inode->i_mutex); | 829 | sysfs_addrm_start(&acxt, sd->s_parent); |
| 348 | dput(parent); | 830 | sysfs_unlink_sibling(sd); |
| 831 | sysfs_remove_one(&acxt, sd); | ||
| 832 | sysfs_addrm_finish(&acxt); | ||
| 349 | } | 833 | } |
| 350 | 834 | ||
| 351 | void sysfs_remove_subdir(struct dentry * d) | 835 | void sysfs_remove_subdir(struct sysfs_dirent *sd) |
| 352 | { | 836 | { |
| 353 | remove_dir(d); | 837 | remove_dir(sd); |
| 354 | } | 838 | } |
| 355 | 839 | ||
| 356 | 840 | ||
| 357 | static void __sysfs_remove_dir(struct dentry *dentry) | 841 | static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd) |
| 358 | { | 842 | { |
| 359 | struct sysfs_dirent * parent_sd; | 843 | struct sysfs_addrm_cxt acxt; |
| 360 | struct sysfs_dirent * sd, * tmp; | 844 | struct sysfs_dirent **pos; |
| 361 | 845 | ||
| 362 | dget(dentry); | 846 | if (!dir_sd) |
| 363 | if (!dentry) | ||
| 364 | return; | 847 | return; |
| 365 | 848 | ||
| 366 | pr_debug("sysfs %s: removing dir\n",dentry->d_name.name); | 849 | pr_debug("sysfs %s: removing dir\n", dir_sd->s_name); |
| 367 | mutex_lock(&dentry->d_inode->i_mutex); | 850 | sysfs_addrm_start(&acxt, dir_sd); |
| 368 | parent_sd = dentry->d_fsdata; | 851 | pos = &dir_sd->s_children; |
| 369 | list_for_each_entry_safe(sd, tmp, &parent_sd->s_children, s_sibling) { | 852 | while (*pos) { |
| 370 | if (!sd->s_element || !(sd->s_type & SYSFS_NOT_PINNED)) | 853 | struct sysfs_dirent *sd = *pos; |
| 371 | continue; | 854 | |
| 372 | list_del_init(&sd->s_sibling); | 855 | if (sysfs_type(sd) && sysfs_type(sd) != SYSFS_DIR) { |
| 373 | sysfs_drop_dentry(sd, dentry); | 856 | *pos = sd->s_sibling; |
| 374 | sysfs_put(sd); | 857 | sd->s_sibling = NULL; |
| 858 | sysfs_remove_one(&acxt, sd); | ||
| 859 | } else | ||
| 860 | pos = &(*pos)->s_sibling; | ||
| 375 | } | 861 | } |
| 376 | mutex_unlock(&dentry->d_inode->i_mutex); | 862 | sysfs_addrm_finish(&acxt); |
| 377 | 863 | ||
| 378 | remove_dir(dentry); | 864 | remove_dir(dir_sd); |
| 379 | /** | ||
| 380 | * Drop reference from dget() on entrance. | ||
| 381 | */ | ||
| 382 | dput(dentry); | ||
| 383 | } | 865 | } |
| 384 | 866 | ||
| 385 | /** | 867 | /** |
| @@ -393,102 +875,166 @@ static void __sysfs_remove_dir(struct dentry *dentry) | |||
| 393 | 875 | ||
| 394 | void sysfs_remove_dir(struct kobject * kobj) | 876 | void sysfs_remove_dir(struct kobject * kobj) |
| 395 | { | 877 | { |
| 396 | __sysfs_remove_dir(kobj->dentry); | 878 | struct sysfs_dirent *sd = kobj->sd; |
| 397 | kobj->dentry = NULL; | 879 | |
| 880 | spin_lock(&sysfs_assoc_lock); | ||
| 881 | kobj->sd = NULL; | ||
| 882 | spin_unlock(&sysfs_assoc_lock); | ||
| 883 | |||
| 884 | __sysfs_remove_dir(sd); | ||
| 398 | } | 885 | } |
| 399 | 886 | ||
| 400 | int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent, | 887 | int sysfs_rename_dir(struct kobject *kobj, struct sysfs_dirent *new_parent_sd, |
| 401 | const char *new_name) | 888 | const char *new_name) |
| 402 | { | 889 | { |
| 403 | int error = 0; | 890 | struct sysfs_dirent *sd = kobj->sd; |
| 404 | struct dentry * new_dentry; | 891 | struct dentry *new_parent = NULL; |
| 892 | struct dentry *old_dentry = NULL, *new_dentry = NULL; | ||
| 893 | const char *dup_name = NULL; | ||
| 894 | int error; | ||
| 405 | 895 | ||
| 406 | if (!new_parent) | 896 | /* get dentries */ |
| 407 | return -EFAULT; | 897 | old_dentry = sysfs_get_dentry(sd); |
| 898 | if (IS_ERR(old_dentry)) { | ||
| 899 | error = PTR_ERR(old_dentry); | ||
| 900 | goto out_dput; | ||
| 901 | } | ||
| 408 | 902 | ||
| 409 | down_write(&sysfs_rename_sem); | 903 | new_parent = sysfs_get_dentry(new_parent_sd); |
| 904 | if (IS_ERR(new_parent)) { | ||
| 905 | error = PTR_ERR(new_parent); | ||
| 906 | goto out_dput; | ||
| 907 | } | ||
| 908 | |||
| 909 | /* lock new_parent and get dentry for new name */ | ||
| 410 | mutex_lock(&new_parent->d_inode->i_mutex); | 910 | mutex_lock(&new_parent->d_inode->i_mutex); |
| 411 | 911 | ||
| 412 | new_dentry = lookup_one_len(new_name, new_parent, strlen(new_name)); | 912 | new_dentry = lookup_one_len(new_name, new_parent, strlen(new_name)); |
| 413 | if (!IS_ERR(new_dentry)) { | 913 | if (IS_ERR(new_dentry)) { |
| 414 | /* By allowing two different directories with the | 914 | error = PTR_ERR(new_dentry); |
| 415 | * same d_parent we allow this routine to move | 915 | goto out_unlock; |
| 416 | * between different shadows of the same directory | ||
| 417 | */ | ||
| 418 | if (kobj->dentry->d_parent->d_inode != new_parent->d_inode) | ||
| 419 | return -EINVAL; | ||
| 420 | else if (new_dentry->d_parent->d_inode != new_parent->d_inode) | ||
| 421 | error = -EINVAL; | ||
| 422 | else if (new_dentry == kobj->dentry) | ||
| 423 | error = -EINVAL; | ||
| 424 | else if (!new_dentry->d_inode) { | ||
| 425 | error = kobject_set_name(kobj, "%s", new_name); | ||
| 426 | if (!error) { | ||
| 427 | struct sysfs_dirent *sd, *parent_sd; | ||
| 428 | |||
| 429 | d_add(new_dentry, NULL); | ||
| 430 | d_move(kobj->dentry, new_dentry); | ||
| 431 | |||
| 432 | sd = kobj->dentry->d_fsdata; | ||
| 433 | parent_sd = new_parent->d_fsdata; | ||
| 434 | |||
| 435 | list_del_init(&sd->s_sibling); | ||
| 436 | list_add(&sd->s_sibling, &parent_sd->s_children); | ||
| 437 | } | ||
| 438 | else | ||
| 439 | d_drop(new_dentry); | ||
| 440 | } else | ||
| 441 | error = -EEXIST; | ||
| 442 | dput(new_dentry); | ||
| 443 | } | 916 | } |
| 444 | mutex_unlock(&new_parent->d_inode->i_mutex); | ||
| 445 | up_write(&sysfs_rename_sem); | ||
| 446 | 917 | ||
| 918 | /* By allowing two different directories with the same | ||
| 919 | * d_parent we allow this routine to move between different | ||
| 920 | * shadows of the same directory | ||
| 921 | */ | ||
| 922 | error = -EINVAL; | ||
| 923 | if (old_dentry->d_parent->d_inode != new_parent->d_inode || | ||
| 924 | new_dentry->d_parent->d_inode != new_parent->d_inode || | ||
| 925 | old_dentry == new_dentry) | ||
| 926 | goto out_unlock; | ||
| 927 | |||
| 928 | error = -EEXIST; | ||
| 929 | if (new_dentry->d_inode) | ||
| 930 | goto out_unlock; | ||
| 931 | |||
| 932 | /* rename kobject and sysfs_dirent */ | ||
| 933 | error = -ENOMEM; | ||
| 934 | new_name = dup_name = kstrdup(new_name, GFP_KERNEL); | ||
| 935 | if (!new_name) | ||
| 936 | goto out_drop; | ||
| 937 | |||
| 938 | error = kobject_set_name(kobj, "%s", new_name); | ||
| 939 | if (error) | ||
| 940 | goto out_drop; | ||
| 941 | |||
| 942 | dup_name = sd->s_name; | ||
| 943 | sd->s_name = new_name; | ||
| 944 | |||
| 945 | /* move under the new parent */ | ||
| 946 | d_add(new_dentry, NULL); | ||
| 947 | d_move(sd->s_dentry, new_dentry); | ||
| 948 | |||
| 949 | mutex_lock(&sysfs_mutex); | ||
| 950 | |||
| 951 | sysfs_unlink_sibling(sd); | ||
| 952 | sysfs_get(new_parent_sd); | ||
| 953 | sysfs_put(sd->s_parent); | ||
| 954 | sd->s_parent = new_parent_sd; | ||
| 955 | sysfs_link_sibling(sd); | ||
| 956 | |||
| 957 | mutex_unlock(&sysfs_mutex); | ||
| 958 | |||
| 959 | error = 0; | ||
| 960 | goto out_unlock; | ||
| 961 | |||
| 962 | out_drop: | ||
| 963 | d_drop(new_dentry); | ||
| 964 | out_unlock: | ||
| 965 | mutex_unlock(&new_parent->d_inode->i_mutex); | ||
| 966 | out_dput: | ||
| 967 | kfree(dup_name); | ||
| 968 | dput(new_parent); | ||
| 969 | dput(old_dentry); | ||
| 970 | dput(new_dentry); | ||
| 447 | return error; | 971 | return error; |
| 448 | } | 972 | } |
| 449 | 973 | ||
| 450 | int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent) | 974 | int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj) |
| 451 | { | 975 | { |
| 452 | struct dentry *old_parent_dentry, *new_parent_dentry, *new_dentry; | 976 | struct sysfs_dirent *sd = kobj->sd; |
| 453 | struct sysfs_dirent *new_parent_sd, *sd; | 977 | struct sysfs_dirent *new_parent_sd; |
| 978 | struct dentry *old_parent, *new_parent = NULL; | ||
| 979 | struct dentry *old_dentry = NULL, *new_dentry = NULL; | ||
| 454 | int error; | 980 | int error; |
| 455 | 981 | ||
| 456 | old_parent_dentry = kobj->parent ? | 982 | BUG_ON(!sd->s_parent); |
| 457 | kobj->parent->dentry : sysfs_mount->mnt_sb->s_root; | 983 | new_parent_sd = new_parent_kobj->sd ? new_parent_kobj->sd : &sysfs_root; |
| 458 | new_parent_dentry = new_parent ? | 984 | |
| 459 | new_parent->dentry : sysfs_mount->mnt_sb->s_root; | 985 | /* get dentries */ |
| 986 | old_dentry = sysfs_get_dentry(sd); | ||
| 987 | if (IS_ERR(old_dentry)) { | ||
| 988 | error = PTR_ERR(old_dentry); | ||
| 989 | goto out_dput; | ||
| 990 | } | ||
| 991 | old_parent = sd->s_parent->s_dentry; | ||
| 992 | |||
| 993 | new_parent = sysfs_get_dentry(new_parent_sd); | ||
| 994 | if (IS_ERR(new_parent)) { | ||
| 995 | error = PTR_ERR(new_parent); | ||
| 996 | goto out_dput; | ||
| 997 | } | ||
| 460 | 998 | ||
| 461 | if (old_parent_dentry->d_inode == new_parent_dentry->d_inode) | 999 | if (old_parent->d_inode == new_parent->d_inode) { |
| 462 | return 0; /* nothing to move */ | 1000 | error = 0; |
| 1001 | goto out_dput; /* nothing to move */ | ||
| 1002 | } | ||
| 463 | again: | 1003 | again: |
| 464 | mutex_lock(&old_parent_dentry->d_inode->i_mutex); | 1004 | mutex_lock(&old_parent->d_inode->i_mutex); |
| 465 | if (!mutex_trylock(&new_parent_dentry->d_inode->i_mutex)) { | 1005 | if (!mutex_trylock(&new_parent->d_inode->i_mutex)) { |
| 466 | mutex_unlock(&old_parent_dentry->d_inode->i_mutex); | 1006 | mutex_unlock(&old_parent->d_inode->i_mutex); |
| 467 | goto again; | 1007 | goto again; |
| 468 | } | 1008 | } |
| 469 | 1009 | ||
| 470 | new_parent_sd = new_parent_dentry->d_fsdata; | 1010 | new_dentry = lookup_one_len(kobj->name, new_parent, strlen(kobj->name)); |
| 471 | sd = kobj->dentry->d_fsdata; | ||
| 472 | |||
| 473 | new_dentry = lookup_one_len(kobj->name, new_parent_dentry, | ||
| 474 | strlen(kobj->name)); | ||
| 475 | if (IS_ERR(new_dentry)) { | 1011 | if (IS_ERR(new_dentry)) { |
| 476 | error = PTR_ERR(new_dentry); | 1012 | error = PTR_ERR(new_dentry); |
| 477 | goto out; | 1013 | goto out_unlock; |
| 478 | } else | 1014 | } else |
| 479 | error = 0; | 1015 | error = 0; |
| 480 | d_add(new_dentry, NULL); | 1016 | d_add(new_dentry, NULL); |
| 481 | d_move(kobj->dentry, new_dentry); | 1017 | d_move(sd->s_dentry, new_dentry); |
| 482 | dput(new_dentry); | 1018 | dput(new_dentry); |
| 483 | 1019 | ||
| 484 | /* Remove from old parent's list and insert into new parent's list. */ | 1020 | /* Remove from old parent's list and insert into new parent's list. */ |
| 485 | list_del_init(&sd->s_sibling); | 1021 | mutex_lock(&sysfs_mutex); |
| 486 | list_add(&sd->s_sibling, &new_parent_sd->s_children); | 1022 | |
| 1023 | sysfs_unlink_sibling(sd); | ||
| 1024 | sysfs_get(new_parent_sd); | ||
| 1025 | sysfs_put(sd->s_parent); | ||
| 1026 | sd->s_parent = new_parent_sd; | ||
| 1027 | sysfs_link_sibling(sd); | ||
| 487 | 1028 | ||
| 488 | out: | 1029 | mutex_unlock(&sysfs_mutex); |
| 489 | mutex_unlock(&new_parent_dentry->d_inode->i_mutex); | ||
| 490 | mutex_unlock(&old_parent_dentry->d_inode->i_mutex); | ||
| 491 | 1030 | ||
| 1031 | out_unlock: | ||
| 1032 | mutex_unlock(&new_parent->d_inode->i_mutex); | ||
| 1033 | mutex_unlock(&old_parent->d_inode->i_mutex); | ||
| 1034 | out_dput: | ||
| 1035 | dput(new_parent); | ||
| 1036 | dput(old_dentry); | ||
| 1037 | dput(new_dentry); | ||
| 492 | return error; | 1038 | return error; |
| 493 | } | 1039 | } |
| 494 | 1040 | ||
| @@ -496,23 +1042,27 @@ static int sysfs_dir_open(struct inode *inode, struct file *file) | |||
| 496 | { | 1042 | { |
| 497 | struct dentry * dentry = file->f_path.dentry; | 1043 | struct dentry * dentry = file->f_path.dentry; |
| 498 | struct sysfs_dirent * parent_sd = dentry->d_fsdata; | 1044 | struct sysfs_dirent * parent_sd = dentry->d_fsdata; |
| 1045 | struct sysfs_dirent * sd; | ||
| 499 | 1046 | ||
| 500 | mutex_lock(&dentry->d_inode->i_mutex); | 1047 | sd = sysfs_new_dirent("_DIR_", 0, 0); |
| 501 | file->private_data = sysfs_new_dirent(parent_sd, NULL); | 1048 | if (sd) { |
| 502 | mutex_unlock(&dentry->d_inode->i_mutex); | 1049 | mutex_lock(&sysfs_mutex); |
| 503 | 1050 | sd->s_parent = sysfs_get(parent_sd); | |
| 504 | return file->private_data ? 0 : -ENOMEM; | 1051 | sysfs_link_sibling(sd); |
| 1052 | mutex_unlock(&sysfs_mutex); | ||
| 1053 | } | ||
| 505 | 1054 | ||
| 1055 | file->private_data = sd; | ||
| 1056 | return sd ? 0 : -ENOMEM; | ||
| 506 | } | 1057 | } |
| 507 | 1058 | ||
| 508 | static int sysfs_dir_close(struct inode *inode, struct file *file) | 1059 | static int sysfs_dir_close(struct inode *inode, struct file *file) |
| 509 | { | 1060 | { |
| 510 | struct dentry * dentry = file->f_path.dentry; | ||
| 511 | struct sysfs_dirent * cursor = file->private_data; | 1061 | struct sysfs_dirent * cursor = file->private_data; |
| 512 | 1062 | ||
| 513 | mutex_lock(&dentry->d_inode->i_mutex); | 1063 | mutex_lock(&sysfs_mutex); |
| 514 | list_del_init(&cursor->s_sibling); | 1064 | sysfs_unlink_sibling(cursor); |
| 515 | mutex_unlock(&dentry->d_inode->i_mutex); | 1065 | mutex_unlock(&sysfs_mutex); |
| 516 | 1066 | ||
| 517 | release_sysfs_dirent(cursor); | 1067 | release_sysfs_dirent(cursor); |
| 518 | 1068 | ||
| @@ -530,7 +1080,7 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
| 530 | struct dentry *dentry = filp->f_path.dentry; | 1080 | struct dentry *dentry = filp->f_path.dentry; |
| 531 | struct sysfs_dirent * parent_sd = dentry->d_fsdata; | 1081 | struct sysfs_dirent * parent_sd = dentry->d_fsdata; |
| 532 | struct sysfs_dirent *cursor = filp->private_data; | 1082 | struct sysfs_dirent *cursor = filp->private_data; |
| 533 | struct list_head *p, *q = &cursor->s_sibling; | 1083 | struct sysfs_dirent **pos; |
| 534 | ino_t ino; | 1084 | ino_t ino; |
| 535 | int i = filp->f_pos; | 1085 | int i = filp->f_pos; |
| 536 | 1086 | ||
| @@ -543,38 +1093,52 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
| 543 | i++; | 1093 | i++; |
| 544 | /* fallthrough */ | 1094 | /* fallthrough */ |
| 545 | case 1: | 1095 | case 1: |
| 546 | ino = parent_ino(dentry); | 1096 | if (parent_sd->s_parent) |
| 1097 | ino = parent_sd->s_parent->s_ino; | ||
| 1098 | else | ||
| 1099 | ino = parent_sd->s_ino; | ||
| 547 | if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0) | 1100 | if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0) |
| 548 | break; | 1101 | break; |
| 549 | filp->f_pos++; | 1102 | filp->f_pos++; |
| 550 | i++; | 1103 | i++; |
| 551 | /* fallthrough */ | 1104 | /* fallthrough */ |
| 552 | default: | 1105 | default: |
| 1106 | mutex_lock(&sysfs_mutex); | ||
| 1107 | |||
| 1108 | pos = &parent_sd->s_children; | ||
| 1109 | while (*pos != cursor) | ||
| 1110 | pos = &(*pos)->s_sibling; | ||
| 1111 | |||
| 1112 | /* unlink cursor */ | ||
| 1113 | *pos = cursor->s_sibling; | ||
| 1114 | |||
| 553 | if (filp->f_pos == 2) | 1115 | if (filp->f_pos == 2) |
| 554 | list_move(q, &parent_sd->s_children); | 1116 | pos = &parent_sd->s_children; |
| 555 | 1117 | ||
| 556 | for (p=q->next; p!= &parent_sd->s_children; p=p->next) { | 1118 | for ( ; *pos; pos = &(*pos)->s_sibling) { |
| 557 | struct sysfs_dirent *next; | 1119 | struct sysfs_dirent *next = *pos; |
| 558 | const char * name; | 1120 | const char * name; |
| 559 | int len; | 1121 | int len; |
| 560 | 1122 | ||
| 561 | next = list_entry(p, struct sysfs_dirent, | 1123 | if (!sysfs_type(next)) |
| 562 | s_sibling); | ||
| 563 | if (!next->s_element) | ||
| 564 | continue; | 1124 | continue; |
| 565 | 1125 | ||
| 566 | name = sysfs_get_name(next); | 1126 | name = next->s_name; |
| 567 | len = strlen(name); | 1127 | len = strlen(name); |
| 568 | ino = next->s_ino; | 1128 | ino = next->s_ino; |
| 569 | 1129 | ||
| 570 | if (filldir(dirent, name, len, filp->f_pos, ino, | 1130 | if (filldir(dirent, name, len, filp->f_pos, ino, |
| 571 | dt_type(next)) < 0) | 1131 | dt_type(next)) < 0) |
| 572 | return 0; | 1132 | break; |
| 573 | 1133 | ||
| 574 | list_move(q, p); | ||
| 575 | p = q; | ||
| 576 | filp->f_pos++; | 1134 | filp->f_pos++; |
| 577 | } | 1135 | } |
| 1136 | |||
| 1137 | /* put cursor back in */ | ||
| 1138 | cursor->s_sibling = *pos; | ||
| 1139 | *pos = cursor; | ||
| 1140 | |||
| 1141 | mutex_unlock(&sysfs_mutex); | ||
| 578 | } | 1142 | } |
| 579 | return 0; | 1143 | return 0; |
| 580 | } | 1144 | } |
| @@ -583,7 +1147,6 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin) | |||
| 583 | { | 1147 | { |
| 584 | struct dentry * dentry = file->f_path.dentry; | 1148 | struct dentry * dentry = file->f_path.dentry; |
| 585 | 1149 | ||
| 586 | mutex_lock(&dentry->d_inode->i_mutex); | ||
| 587 | switch (origin) { | 1150 | switch (origin) { |
| 588 | case 1: | 1151 | case 1: |
| 589 | offset += file->f_pos; | 1152 | offset += file->f_pos; |
| @@ -591,31 +1154,35 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin) | |||
| 591 | if (offset >= 0) | 1154 | if (offset >= 0) |
| 592 | break; | 1155 | break; |
| 593 | default: | 1156 | default: |
| 594 | mutex_unlock(&file->f_path.dentry->d_inode->i_mutex); | ||
| 595 | return -EINVAL; | 1157 | return -EINVAL; |
| 596 | } | 1158 | } |
| 597 | if (offset != file->f_pos) { | 1159 | if (offset != file->f_pos) { |
| 1160 | mutex_lock(&sysfs_mutex); | ||
| 1161 | |||
| 598 | file->f_pos = offset; | 1162 | file->f_pos = offset; |
| 599 | if (file->f_pos >= 2) { | 1163 | if (file->f_pos >= 2) { |
| 600 | struct sysfs_dirent *sd = dentry->d_fsdata; | 1164 | struct sysfs_dirent *sd = dentry->d_fsdata; |
| 601 | struct sysfs_dirent *cursor = file->private_data; | 1165 | struct sysfs_dirent *cursor = file->private_data; |
| 602 | struct list_head *p; | 1166 | struct sysfs_dirent **pos; |
| 603 | loff_t n = file->f_pos - 2; | 1167 | loff_t n = file->f_pos - 2; |
| 604 | 1168 | ||
| 605 | list_del(&cursor->s_sibling); | 1169 | sysfs_unlink_sibling(cursor); |
| 606 | p = sd->s_children.next; | 1170 | |
| 607 | while (n && p != &sd->s_children) { | 1171 | pos = &sd->s_children; |
| 608 | struct sysfs_dirent *next; | 1172 | while (n && *pos) { |
| 609 | next = list_entry(p, struct sysfs_dirent, | 1173 | struct sysfs_dirent *next = *pos; |
| 610 | s_sibling); | 1174 | if (sysfs_type(next)) |
| 611 | if (next->s_element) | ||
| 612 | n--; | 1175 | n--; |
| 613 | p = p->next; | 1176 | pos = &(*pos)->s_sibling; |
| 614 | } | 1177 | } |
| 615 | list_add_tail(&cursor->s_sibling, p); | 1178 | |
| 1179 | cursor->s_sibling = *pos; | ||
| 1180 | *pos = cursor; | ||
| 616 | } | 1181 | } |
| 1182 | |||
| 1183 | mutex_unlock(&sysfs_mutex); | ||
| 617 | } | 1184 | } |
| 618 | mutex_unlock(&dentry->d_inode->i_mutex); | 1185 | |
| 619 | return offset; | 1186 | return offset; |
| 620 | } | 1187 | } |
| 621 | 1188 | ||
| @@ -628,12 +1195,20 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin) | |||
| 628 | int sysfs_make_shadowed_dir(struct kobject *kobj, | 1195 | int sysfs_make_shadowed_dir(struct kobject *kobj, |
| 629 | void * (*follow_link)(struct dentry *, struct nameidata *)) | 1196 | void * (*follow_link)(struct dentry *, struct nameidata *)) |
| 630 | { | 1197 | { |
| 1198 | struct dentry *dentry; | ||
| 631 | struct inode *inode; | 1199 | struct inode *inode; |
| 632 | struct inode_operations *i_op; | 1200 | struct inode_operations *i_op; |
| 633 | 1201 | ||
| 634 | inode = kobj->dentry->d_inode; | 1202 | /* get dentry for @kobj->sd, dentry of a shadowed dir is pinned */ |
| 635 | if (inode->i_op != &sysfs_dir_inode_operations) | 1203 | dentry = sysfs_get_dentry(kobj->sd); |
| 1204 | if (IS_ERR(dentry)) | ||
| 1205 | return PTR_ERR(dentry); | ||
| 1206 | |||
| 1207 | inode = dentry->d_inode; | ||
| 1208 | if (inode->i_op != &sysfs_dir_inode_operations) { | ||
| 1209 | dput(dentry); | ||
| 636 | return -EINVAL; | 1210 | return -EINVAL; |
| 1211 | } | ||
| 637 | 1212 | ||
| 638 | i_op = kmalloc(sizeof(*i_op), GFP_KERNEL); | 1213 | i_op = kmalloc(sizeof(*i_op), GFP_KERNEL); |
| 639 | if (!i_op) | 1214 | if (!i_op) |
| @@ -658,54 +1233,72 @@ int sysfs_make_shadowed_dir(struct kobject *kobj, | |||
| 658 | * directory. | 1233 | * directory. |
| 659 | */ | 1234 | */ |
| 660 | 1235 | ||
| 661 | struct dentry *sysfs_create_shadow_dir(struct kobject *kobj) | 1236 | struct sysfs_dirent *sysfs_create_shadow_dir(struct kobject *kobj) |
| 662 | { | 1237 | { |
| 663 | struct sysfs_dirent *sd; | 1238 | struct sysfs_dirent *parent_sd = kobj->sd->s_parent; |
| 664 | struct dentry *parent, *dir, *shadow; | 1239 | struct dentry *dir, *parent, *shadow; |
| 665 | struct inode *inode; | 1240 | struct inode *inode; |
| 1241 | struct sysfs_dirent *sd; | ||
| 1242 | struct sysfs_addrm_cxt acxt; | ||
| 666 | 1243 | ||
| 667 | dir = kobj->dentry; | 1244 | dir = sysfs_get_dentry(kobj->sd); |
| 668 | inode = dir->d_inode; | 1245 | if (IS_ERR(dir)) { |
| 1246 | sd = (void *)dir; | ||
| 1247 | goto out; | ||
| 1248 | } | ||
| 669 | parent = dir->d_parent; | 1249 | parent = dir->d_parent; |
| 670 | shadow = ERR_PTR(-EINVAL); | 1250 | |
| 1251 | inode = dir->d_inode; | ||
| 1252 | sd = ERR_PTR(-EINVAL); | ||
| 671 | if (!sysfs_is_shadowed_inode(inode)) | 1253 | if (!sysfs_is_shadowed_inode(inode)) |
| 672 | goto out; | 1254 | goto out_dput; |
| 673 | 1255 | ||
| 674 | shadow = d_alloc(parent, &dir->d_name); | 1256 | shadow = d_alloc(parent, &dir->d_name); |
| 675 | if (!shadow) | 1257 | if (!shadow) |
| 676 | goto nomem; | 1258 | goto nomem; |
| 677 | 1259 | ||
| 678 | sd = __sysfs_make_dirent(shadow, kobj, inode->i_mode, SYSFS_DIR); | 1260 | sd = sysfs_new_dirent("_SHADOW_", inode->i_mode, SYSFS_DIR); |
| 679 | if (!sd) | 1261 | if (!sd) |
| 680 | goto nomem; | 1262 | goto nomem; |
| 1263 | sd->s_elem.dir.kobj = kobj; | ||
| 681 | 1264 | ||
| 1265 | sysfs_addrm_start(&acxt, parent_sd); | ||
| 1266 | |||
| 1267 | /* add but don't link into children list */ | ||
| 1268 | sysfs_add_one(&acxt, sd); | ||
| 1269 | |||
| 1270 | /* attach and instantiate dentry */ | ||
| 1271 | sysfs_attach_dentry(sd, shadow); | ||
| 682 | d_instantiate(shadow, igrab(inode)); | 1272 | d_instantiate(shadow, igrab(inode)); |
| 683 | inc_nlink(inode); | 1273 | inc_nlink(inode); /* tj: synchronization? */ |
| 684 | inc_nlink(parent->d_inode); | 1274 | |
| 685 | shadow->d_op = &sysfs_dentry_ops; | 1275 | sysfs_addrm_finish(&acxt); |
| 686 | 1276 | ||
| 687 | dget(shadow); /* Extra count - pin the dentry in core */ | 1277 | dget(shadow); /* Extra count - pin the dentry in core */ |
| 688 | 1278 | ||
| 689 | out: | 1279 | goto out_dput; |
| 690 | return shadow; | 1280 | |
| 691 | nomem: | 1281 | nomem: |
| 692 | dput(shadow); | 1282 | dput(shadow); |
| 693 | shadow = ERR_PTR(-ENOMEM); | 1283 | sd = ERR_PTR(-ENOMEM); |
| 694 | goto out; | 1284 | out_dput: |
| 1285 | dput(dir); | ||
| 1286 | out: | ||
| 1287 | return sd; | ||
| 695 | } | 1288 | } |
| 696 | 1289 | ||
| 697 | /** | 1290 | /** |
| 698 | * sysfs_remove_shadow_dir - remove an object's directory. | 1291 | * sysfs_remove_shadow_dir - remove an object's directory. |
| 699 | * @shadow: dentry of shadow directory | 1292 | * @shadow_sd: sysfs_dirent of shadow directory |
| 700 | * | 1293 | * |
| 701 | * The only thing special about this is that we remove any files in | 1294 | * The only thing special about this is that we remove any files in |
| 702 | * the directory before we remove the directory, and we've inlined | 1295 | * the directory before we remove the directory, and we've inlined |
| 703 | * what used to be sysfs_rmdir() below, instead of calling separately. | 1296 | * what used to be sysfs_rmdir() below, instead of calling separately. |
| 704 | */ | 1297 | */ |
| 705 | 1298 | ||
| 706 | void sysfs_remove_shadow_dir(struct dentry *shadow) | 1299 | void sysfs_remove_shadow_dir(struct sysfs_dirent *shadow_sd) |
| 707 | { | 1300 | { |
| 708 | __sysfs_remove_dir(shadow); | 1301 | __sysfs_remove_dir(shadow_sd); |
| 709 | } | 1302 | } |
| 710 | 1303 | ||
| 711 | const struct file_operations sysfs_dir_operations = { | 1304 | const struct file_operations sysfs_dir_operations = { |
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index b502c7197ec0..cc497994b2a8 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
| @@ -50,29 +50,15 @@ static struct sysfs_ops subsys_sysfs_ops = { | |||
| 50 | .store = subsys_attr_store, | 50 | .store = subsys_attr_store, |
| 51 | }; | 51 | }; |
| 52 | 52 | ||
| 53 | /** | 53 | struct sysfs_buffer { |
| 54 | * add_to_collection - add buffer to a collection | 54 | size_t count; |
| 55 | * @buffer: buffer to be added | 55 | loff_t pos; |
| 56 | * @node: inode of set to add to | 56 | char * page; |
| 57 | */ | 57 | struct sysfs_ops * ops; |
| 58 | 58 | struct semaphore sem; | |
| 59 | static inline void | 59 | int needs_read_fill; |
| 60 | add_to_collection(struct sysfs_buffer *buffer, struct inode *node) | 60 | int event; |
| 61 | { | 61 | }; |
| 62 | struct sysfs_buffer_collection *set = node->i_private; | ||
| 63 | |||
| 64 | mutex_lock(&node->i_mutex); | ||
| 65 | list_add(&buffer->associates, &set->associates); | ||
| 66 | mutex_unlock(&node->i_mutex); | ||
| 67 | } | ||
| 68 | |||
| 69 | static inline void | ||
| 70 | remove_from_collection(struct sysfs_buffer *buffer, struct inode *node) | ||
| 71 | { | ||
| 72 | mutex_lock(&node->i_mutex); | ||
| 73 | list_del(&buffer->associates); | ||
| 74 | mutex_unlock(&node->i_mutex); | ||
| 75 | } | ||
| 76 | 62 | ||
| 77 | /** | 63 | /** |
| 78 | * fill_read_buffer - allocate and fill buffer from object. | 64 | * fill_read_buffer - allocate and fill buffer from object. |
| @@ -87,9 +73,8 @@ remove_from_collection(struct sysfs_buffer *buffer, struct inode *node) | |||
| 87 | */ | 73 | */ |
| 88 | static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer) | 74 | static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer) |
| 89 | { | 75 | { |
| 90 | struct sysfs_dirent * sd = dentry->d_fsdata; | 76 | struct sysfs_dirent *attr_sd = dentry->d_fsdata; |
| 91 | struct attribute * attr = to_attr(dentry); | 77 | struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj; |
| 92 | struct kobject * kobj = to_kobj(dentry->d_parent); | ||
| 93 | struct sysfs_ops * ops = buffer->ops; | 78 | struct sysfs_ops * ops = buffer->ops; |
| 94 | int ret = 0; | 79 | int ret = 0; |
| 95 | ssize_t count; | 80 | ssize_t count; |
| @@ -99,8 +84,15 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer | |||
| 99 | if (!buffer->page) | 84 | if (!buffer->page) |
| 100 | return -ENOMEM; | 85 | return -ENOMEM; |
| 101 | 86 | ||
| 102 | buffer->event = atomic_read(&sd->s_event); | 87 | /* need attr_sd for attr and ops, its parent for kobj */ |
| 103 | count = ops->show(kobj,attr,buffer->page); | 88 | if (!sysfs_get_active_two(attr_sd)) |
| 89 | return -ENODEV; | ||
| 90 | |||
| 91 | buffer->event = atomic_read(&attr_sd->s_event); | ||
| 92 | count = ops->show(kobj, attr_sd->s_elem.attr.attr, buffer->page); | ||
| 93 | |||
| 94 | sysfs_put_active_two(attr_sd); | ||
| 95 | |||
| 104 | BUG_ON(count > (ssize_t)PAGE_SIZE); | 96 | BUG_ON(count > (ssize_t)PAGE_SIZE); |
| 105 | if (count >= 0) { | 97 | if (count >= 0) { |
| 106 | buffer->needs_read_fill = 0; | 98 | buffer->needs_read_fill = 0; |
| @@ -138,10 +130,7 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos) | |||
| 138 | 130 | ||
| 139 | down(&buffer->sem); | 131 | down(&buffer->sem); |
| 140 | if (buffer->needs_read_fill) { | 132 | if (buffer->needs_read_fill) { |
| 141 | if (buffer->orphaned) | 133 | retval = fill_read_buffer(file->f_path.dentry,buffer); |
| 142 | retval = -ENODEV; | ||
| 143 | else | ||
| 144 | retval = fill_read_buffer(file->f_path.dentry,buffer); | ||
| 145 | if (retval) | 134 | if (retval) |
| 146 | goto out; | 135 | goto out; |
| 147 | } | 136 | } |
| @@ -196,14 +185,23 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t | |||
| 196 | * passing the buffer that we acquired in fill_write_buffer(). | 185 | * passing the buffer that we acquired in fill_write_buffer(). |
| 197 | */ | 186 | */ |
| 198 | 187 | ||
| 199 | static int | 188 | static int |
| 200 | flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t count) | 189 | flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t count) |
| 201 | { | 190 | { |
| 202 | struct attribute * attr = to_attr(dentry); | 191 | struct sysfs_dirent *attr_sd = dentry->d_fsdata; |
| 203 | struct kobject * kobj = to_kobj(dentry->d_parent); | 192 | struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj; |
| 204 | struct sysfs_ops * ops = buffer->ops; | 193 | struct sysfs_ops * ops = buffer->ops; |
| 194 | int rc; | ||
| 195 | |||
| 196 | /* need attr_sd for attr and ops, its parent for kobj */ | ||
| 197 | if (!sysfs_get_active_two(attr_sd)) | ||
| 198 | return -ENODEV; | ||
| 199 | |||
| 200 | rc = ops->store(kobj, attr_sd->s_elem.attr.attr, buffer->page, count); | ||
| 205 | 201 | ||
| 206 | return ops->store(kobj,attr,buffer->page,count); | 202 | sysfs_put_active_two(attr_sd); |
| 203 | |||
| 204 | return rc; | ||
| 207 | } | 205 | } |
| 208 | 206 | ||
| 209 | 207 | ||
| @@ -231,37 +229,26 @@ sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t | |||
| 231 | ssize_t len; | 229 | ssize_t len; |
| 232 | 230 | ||
| 233 | down(&buffer->sem); | 231 | down(&buffer->sem); |
| 234 | if (buffer->orphaned) { | ||
| 235 | len = -ENODEV; | ||
| 236 | goto out; | ||
| 237 | } | ||
| 238 | len = fill_write_buffer(buffer, buf, count); | 232 | len = fill_write_buffer(buffer, buf, count); |
| 239 | if (len > 0) | 233 | if (len > 0) |
| 240 | len = flush_write_buffer(file->f_path.dentry, buffer, len); | 234 | len = flush_write_buffer(file->f_path.dentry, buffer, len); |
| 241 | if (len > 0) | 235 | if (len > 0) |
| 242 | *ppos += len; | 236 | *ppos += len; |
| 243 | out: | ||
| 244 | up(&buffer->sem); | 237 | up(&buffer->sem); |
| 245 | return len; | 238 | return len; |
| 246 | } | 239 | } |
| 247 | 240 | ||
| 248 | static int sysfs_open_file(struct inode *inode, struct file *file) | 241 | static int sysfs_open_file(struct inode *inode, struct file *file) |
| 249 | { | 242 | { |
| 250 | struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent); | 243 | struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; |
| 251 | struct attribute * attr = to_attr(file->f_path.dentry); | 244 | struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj; |
| 252 | struct sysfs_buffer_collection *set; | ||
| 253 | struct sysfs_buffer * buffer; | 245 | struct sysfs_buffer * buffer; |
| 254 | struct sysfs_ops * ops = NULL; | 246 | struct sysfs_ops * ops = NULL; |
| 255 | int error = 0; | 247 | int error; |
| 256 | |||
| 257 | if (!kobj || !attr) | ||
| 258 | goto Einval; | ||
| 259 | 248 | ||
| 260 | /* Grab the module reference for this attribute if we have one */ | 249 | /* need attr_sd for attr and ops, its parent for kobj */ |
| 261 | if (!try_module_get(attr->owner)) { | 250 | if (!sysfs_get_active_two(attr_sd)) |
| 262 | error = -ENODEV; | 251 | return -ENODEV; |
| 263 | goto Done; | ||
| 264 | } | ||
| 265 | 252 | ||
| 266 | /* if the kobject has no ktype, then we assume that it is a subsystem | 253 | /* if the kobject has no ktype, then we assume that it is a subsystem |
| 267 | * itself, and use ops for it. | 254 | * itself, and use ops for it. |
| @@ -273,33 +260,21 @@ static int sysfs_open_file(struct inode *inode, struct file *file) | |||
| 273 | else | 260 | else |
| 274 | ops = &subsys_sysfs_ops; | 261 | ops = &subsys_sysfs_ops; |
| 275 | 262 | ||
| 263 | error = -EACCES; | ||
| 264 | |||
| 276 | /* No sysfs operations, either from having no subsystem, | 265 | /* No sysfs operations, either from having no subsystem, |
| 277 | * or the subsystem have no operations. | 266 | * or the subsystem have no operations. |
| 278 | */ | 267 | */ |
| 279 | if (!ops) | 268 | if (!ops) |
| 280 | goto Eaccess; | 269 | goto err_out; |
| 281 | |||
| 282 | /* make sure we have a collection to add our buffers to */ | ||
| 283 | mutex_lock(&inode->i_mutex); | ||
| 284 | if (!(set = inode->i_private)) { | ||
| 285 | if (!(set = inode->i_private = kmalloc(sizeof(struct sysfs_buffer_collection), GFP_KERNEL))) { | ||
| 286 | error = -ENOMEM; | ||
| 287 | goto Done; | ||
| 288 | } else { | ||
| 289 | INIT_LIST_HEAD(&set->associates); | ||
| 290 | } | ||
| 291 | } | ||
| 292 | mutex_unlock(&inode->i_mutex); | ||
| 293 | 270 | ||
| 294 | /* File needs write support. | 271 | /* File needs write support. |
| 295 | * The inode's perms must say it's ok, | 272 | * The inode's perms must say it's ok, |
| 296 | * and we must have a store method. | 273 | * and we must have a store method. |
| 297 | */ | 274 | */ |
| 298 | if (file->f_mode & FMODE_WRITE) { | 275 | if (file->f_mode & FMODE_WRITE) { |
| 299 | |||
| 300 | if (!(inode->i_mode & S_IWUGO) || !ops->store) | 276 | if (!(inode->i_mode & S_IWUGO) || !ops->store) |
| 301 | goto Eaccess; | 277 | goto err_out; |
| 302 | |||
| 303 | } | 278 | } |
| 304 | 279 | ||
| 305 | /* File needs read support. | 280 | /* File needs read support. |
| @@ -308,48 +283,38 @@ static int sysfs_open_file(struct inode *inode, struct file *file) | |||
| 308 | */ | 283 | */ |
| 309 | if (file->f_mode & FMODE_READ) { | 284 | if (file->f_mode & FMODE_READ) { |
| 310 | if (!(inode->i_mode & S_IRUGO) || !ops->show) | 285 | if (!(inode->i_mode & S_IRUGO) || !ops->show) |
| 311 | goto Eaccess; | 286 | goto err_out; |
| 312 | } | 287 | } |
| 313 | 288 | ||
| 314 | /* No error? Great, allocate a buffer for the file, and store it | 289 | /* No error? Great, allocate a buffer for the file, and store it |
| 315 | * it in file->private_data for easy access. | 290 | * it in file->private_data for easy access. |
| 316 | */ | 291 | */ |
| 292 | error = -ENOMEM; | ||
| 317 | buffer = kzalloc(sizeof(struct sysfs_buffer), GFP_KERNEL); | 293 | buffer = kzalloc(sizeof(struct sysfs_buffer), GFP_KERNEL); |
| 318 | if (buffer) { | 294 | if (!buffer) |
| 319 | INIT_LIST_HEAD(&buffer->associates); | 295 | goto err_out; |
| 320 | init_MUTEX(&buffer->sem); | 296 | |
| 321 | buffer->needs_read_fill = 1; | 297 | init_MUTEX(&buffer->sem); |
| 322 | buffer->ops = ops; | 298 | buffer->needs_read_fill = 1; |
| 323 | add_to_collection(buffer, inode); | 299 | buffer->ops = ops; |
| 324 | file->private_data = buffer; | 300 | file->private_data = buffer; |
| 325 | } else | 301 | |
| 326 | error = -ENOMEM; | 302 | /* open succeeded, put active references and pin attr_sd */ |
| 327 | goto Done; | 303 | sysfs_put_active_two(attr_sd); |
| 328 | 304 | sysfs_get(attr_sd); | |
| 329 | Einval: | 305 | return 0; |
| 330 | error = -EINVAL; | 306 | |
| 331 | goto Done; | 307 | err_out: |
| 332 | Eaccess: | 308 | sysfs_put_active_two(attr_sd); |
| 333 | error = -EACCES; | ||
| 334 | module_put(attr->owner); | ||
| 335 | Done: | ||
| 336 | if (error) | ||
| 337 | kobject_put(kobj); | ||
| 338 | return error; | 309 | return error; |
| 339 | } | 310 | } |
| 340 | 311 | ||
| 341 | static int sysfs_release(struct inode * inode, struct file * filp) | 312 | static int sysfs_release(struct inode * inode, struct file * filp) |
| 342 | { | 313 | { |
| 343 | struct kobject * kobj = to_kobj(filp->f_path.dentry->d_parent); | 314 | struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata; |
| 344 | struct attribute * attr = to_attr(filp->f_path.dentry); | 315 | struct sysfs_buffer *buffer = filp->private_data; |
| 345 | struct module * owner = attr->owner; | ||
| 346 | struct sysfs_buffer * buffer = filp->private_data; | ||
| 347 | 316 | ||
| 348 | if (buffer) | 317 | sysfs_put(attr_sd); |
| 349 | remove_from_collection(buffer, inode); | ||
| 350 | kobject_put(kobj); | ||
| 351 | /* After this point, attr should not be accessed. */ | ||
| 352 | module_put(owner); | ||
| 353 | 318 | ||
| 354 | if (buffer) { | 319 | if (buffer) { |
| 355 | if (buffer->page) | 320 | if (buffer->page) |
| @@ -376,57 +341,43 @@ static int sysfs_release(struct inode * inode, struct file * filp) | |||
| 376 | static unsigned int sysfs_poll(struct file *filp, poll_table *wait) | 341 | static unsigned int sysfs_poll(struct file *filp, poll_table *wait) |
| 377 | { | 342 | { |
| 378 | struct sysfs_buffer * buffer = filp->private_data; | 343 | struct sysfs_buffer * buffer = filp->private_data; |
| 379 | struct kobject * kobj = to_kobj(filp->f_path.dentry->d_parent); | 344 | struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata; |
| 380 | struct sysfs_dirent * sd = filp->f_path.dentry->d_fsdata; | 345 | struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj; |
| 381 | int res = 0; | 346 | |
| 347 | /* need parent for the kobj, grab both */ | ||
| 348 | if (!sysfs_get_active_two(attr_sd)) | ||
| 349 | goto trigger; | ||
| 382 | 350 | ||
| 383 | poll_wait(filp, &kobj->poll, wait); | 351 | poll_wait(filp, &kobj->poll, wait); |
| 384 | 352 | ||
| 385 | if (buffer->event != atomic_read(&sd->s_event)) { | 353 | sysfs_put_active_two(attr_sd); |
| 386 | res = POLLERR|POLLPRI; | ||
| 387 | buffer->needs_read_fill = 1; | ||
| 388 | } | ||
| 389 | 354 | ||
| 390 | return res; | 355 | if (buffer->event != atomic_read(&attr_sd->s_event)) |
| 391 | } | 356 | goto trigger; |
| 392 | 357 | ||
| 358 | return 0; | ||
| 393 | 359 | ||
| 394 | static struct dentry *step_down(struct dentry *dir, const char * name) | 360 | trigger: |
| 395 | { | 361 | buffer->needs_read_fill = 1; |
| 396 | struct dentry * de; | 362 | return POLLERR|POLLPRI; |
| 397 | |||
| 398 | if (dir == NULL || dir->d_inode == NULL) | ||
| 399 | return NULL; | ||
| 400 | |||
| 401 | mutex_lock(&dir->d_inode->i_mutex); | ||
| 402 | de = lookup_one_len(name, dir, strlen(name)); | ||
| 403 | mutex_unlock(&dir->d_inode->i_mutex); | ||
| 404 | dput(dir); | ||
| 405 | if (IS_ERR(de)) | ||
| 406 | return NULL; | ||
| 407 | if (de->d_inode == NULL) { | ||
| 408 | dput(de); | ||
| 409 | return NULL; | ||
| 410 | } | ||
| 411 | return de; | ||
| 412 | } | 363 | } |
| 413 | 364 | ||
| 414 | void sysfs_notify(struct kobject * k, char *dir, char *attr) | 365 | void sysfs_notify(struct kobject *k, char *dir, char *attr) |
| 415 | { | 366 | { |
| 416 | struct dentry *de = k->dentry; | 367 | struct sysfs_dirent *sd = k->sd; |
| 417 | if (de) | 368 | |
| 418 | dget(de); | 369 | mutex_lock(&sysfs_mutex); |
| 419 | if (de && dir) | 370 | |
| 420 | de = step_down(de, dir); | 371 | if (sd && dir) |
| 421 | if (de && attr) | 372 | sd = sysfs_find_dirent(sd, dir); |
| 422 | de = step_down(de, attr); | 373 | if (sd && attr) |
| 423 | if (de) { | 374 | sd = sysfs_find_dirent(sd, attr); |
| 424 | struct sysfs_dirent * sd = de->d_fsdata; | 375 | if (sd) { |
| 425 | if (sd) | 376 | atomic_inc(&sd->s_event); |
| 426 | atomic_inc(&sd->s_event); | ||
| 427 | wake_up_interruptible(&k->poll); | 377 | wake_up_interruptible(&k->poll); |
| 428 | dput(de); | ||
| 429 | } | 378 | } |
| 379 | |||
| 380 | mutex_unlock(&sysfs_mutex); | ||
| 430 | } | 381 | } |
| 431 | EXPORT_SYMBOL_GPL(sysfs_notify); | 382 | EXPORT_SYMBOL_GPL(sysfs_notify); |
| 432 | 383 | ||
| @@ -440,19 +391,30 @@ const struct file_operations sysfs_file_operations = { | |||
| 440 | }; | 391 | }; |
| 441 | 392 | ||
| 442 | 393 | ||
| 443 | int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type) | 394 | int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr, |
| 395 | int type) | ||
| 444 | { | 396 | { |
| 445 | struct sysfs_dirent * parent_sd = dir->d_fsdata; | ||
| 446 | umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG; | 397 | umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG; |
| 447 | int error = -EEXIST; | 398 | struct sysfs_addrm_cxt acxt; |
| 399 | struct sysfs_dirent *sd; | ||
| 448 | 400 | ||
| 449 | mutex_lock(&dir->d_inode->i_mutex); | 401 | sd = sysfs_new_dirent(attr->name, mode, type); |
| 450 | if (!sysfs_dirent_exist(parent_sd, attr->name)) | 402 | if (!sd) |
| 451 | error = sysfs_make_dirent(parent_sd, NULL, (void *)attr, | 403 | return -ENOMEM; |
| 452 | mode, type); | 404 | sd->s_elem.attr.attr = (void *)attr; |
| 453 | mutex_unlock(&dir->d_inode->i_mutex); | ||
| 454 | 405 | ||
| 455 | return error; | 406 | sysfs_addrm_start(&acxt, dir_sd); |
| 407 | |||
| 408 | if (!sysfs_find_dirent(dir_sd, attr->name)) { | ||
| 409 | sysfs_add_one(&acxt, sd); | ||
| 410 | sysfs_link_sibling(sd); | ||
| 411 | } | ||
| 412 | |||
| 413 | if (sysfs_addrm_finish(&acxt)) | ||
| 414 | return 0; | ||
| 415 | |||
| 416 | sysfs_put(sd); | ||
| 417 | return -EEXIST; | ||
| 456 | } | 418 | } |
| 457 | 419 | ||
| 458 | 420 | ||
| @@ -464,9 +426,9 @@ int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type) | |||
| 464 | 426 | ||
| 465 | int sysfs_create_file(struct kobject * kobj, const struct attribute * attr) | 427 | int sysfs_create_file(struct kobject * kobj, const struct attribute * attr) |
| 466 | { | 428 | { |
| 467 | BUG_ON(!kobj || !kobj->dentry || !attr); | 429 | BUG_ON(!kobj || !kobj->sd || !attr); |
| 468 | 430 | ||
| 469 | return sysfs_add_file(kobj->dentry, attr, SYSFS_KOBJ_ATTR); | 431 | return sysfs_add_file(kobj->sd, attr, SYSFS_KOBJ_ATTR); |
| 470 | 432 | ||
| 471 | } | 433 | } |
| 472 | 434 | ||
| @@ -480,16 +442,16 @@ int sysfs_create_file(struct kobject * kobj, const struct attribute * attr) | |||
| 480 | int sysfs_add_file_to_group(struct kobject *kobj, | 442 | int sysfs_add_file_to_group(struct kobject *kobj, |
| 481 | const struct attribute *attr, const char *group) | 443 | const struct attribute *attr, const char *group) |
| 482 | { | 444 | { |
| 483 | struct dentry *dir; | 445 | struct sysfs_dirent *dir_sd; |
| 484 | int error; | 446 | int error; |
| 485 | 447 | ||
| 486 | dir = lookup_one_len(group, kobj->dentry, strlen(group)); | 448 | dir_sd = sysfs_get_dirent(kobj->sd, group); |
| 487 | if (IS_ERR(dir)) | 449 | if (!dir_sd) |
| 488 | error = PTR_ERR(dir); | 450 | return -ENOENT; |
| 489 | else { | 451 | |
| 490 | error = sysfs_add_file(dir, attr, SYSFS_KOBJ_ATTR); | 452 | error = sysfs_add_file(dir_sd, attr, SYSFS_KOBJ_ATTR); |
| 491 | dput(dir); | 453 | sysfs_put(dir_sd); |
| 492 | } | 454 | |
| 493 | return error; | 455 | return error; |
| 494 | } | 456 | } |
| 495 | EXPORT_SYMBOL_GPL(sysfs_add_file_to_group); | 457 | EXPORT_SYMBOL_GPL(sysfs_add_file_to_group); |
| @@ -502,30 +464,31 @@ EXPORT_SYMBOL_GPL(sysfs_add_file_to_group); | |||
| 502 | */ | 464 | */ |
| 503 | int sysfs_update_file(struct kobject * kobj, const struct attribute * attr) | 465 | int sysfs_update_file(struct kobject * kobj, const struct attribute * attr) |
| 504 | { | 466 | { |
| 505 | struct dentry * dir = kobj->dentry; | 467 | struct sysfs_dirent *victim_sd = NULL; |
| 506 | struct dentry * victim; | 468 | struct dentry *victim = NULL; |
| 507 | int res = -ENOENT; | 469 | int rc; |
| 508 | 470 | ||
| 509 | mutex_lock(&dir->d_inode->i_mutex); | 471 | rc = -ENOENT; |
| 510 | victim = lookup_one_len(attr->name, dir, strlen(attr->name)); | 472 | victim_sd = sysfs_get_dirent(kobj->sd, attr->name); |
| 511 | if (!IS_ERR(victim)) { | 473 | if (!victim_sd) |
| 512 | /* make sure dentry is really there */ | 474 | goto out; |
| 513 | if (victim->d_inode && | 475 | |
| 514 | (victim->d_parent->d_inode == dir->d_inode)) { | 476 | victim = sysfs_get_dentry(victim_sd); |
| 515 | victim->d_inode->i_mtime = CURRENT_TIME; | 477 | if (IS_ERR(victim)) { |
| 516 | fsnotify_modify(victim); | 478 | rc = PTR_ERR(victim); |
| 517 | res = 0; | 479 | victim = NULL; |
| 518 | } else | 480 | goto out; |
| 519 | d_drop(victim); | ||
| 520 | |||
| 521 | /** | ||
| 522 | * Drop the reference acquired from lookup_one_len() above. | ||
| 523 | */ | ||
| 524 | dput(victim); | ||
| 525 | } | 481 | } |
| 526 | mutex_unlock(&dir->d_inode->i_mutex); | ||
| 527 | 482 | ||
| 528 | return res; | 483 | mutex_lock(&victim->d_inode->i_mutex); |
| 484 | victim->d_inode->i_mtime = CURRENT_TIME; | ||
| 485 | fsnotify_modify(victim); | ||
| 486 | mutex_unlock(&victim->d_inode->i_mutex); | ||
| 487 | rc = 0; | ||
| 488 | out: | ||
| 489 | dput(victim); | ||
| 490 | sysfs_put(victim_sd); | ||
| 491 | return rc; | ||
| 529 | } | 492 | } |
| 530 | 493 | ||
| 531 | 494 | ||
| @@ -538,30 +501,34 @@ int sysfs_update_file(struct kobject * kobj, const struct attribute * attr) | |||
| 538 | */ | 501 | */ |
| 539 | int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) | 502 | int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) |
| 540 | { | 503 | { |
| 541 | struct dentry *dir = kobj->dentry; | 504 | struct sysfs_dirent *victim_sd = NULL; |
| 542 | struct dentry *victim; | 505 | struct dentry *victim = NULL; |
| 543 | struct inode * inode; | 506 | struct inode * inode; |
| 544 | struct iattr newattrs; | 507 | struct iattr newattrs; |
| 545 | int res = -ENOENT; | 508 | int rc; |
| 546 | 509 | ||
| 547 | mutex_lock(&dir->d_inode->i_mutex); | 510 | rc = -ENOENT; |
| 548 | victim = lookup_one_len(attr->name, dir, strlen(attr->name)); | 511 | victim_sd = sysfs_get_dirent(kobj->sd, attr->name); |
| 549 | if (!IS_ERR(victim)) { | 512 | if (!victim_sd) |
| 550 | if (victim->d_inode && | 513 | goto out; |
| 551 | (victim->d_parent->d_inode == dir->d_inode)) { | 514 | |
| 552 | inode = victim->d_inode; | 515 | victim = sysfs_get_dentry(victim_sd); |
| 553 | mutex_lock(&inode->i_mutex); | 516 | if (IS_ERR(victim)) { |
| 554 | newattrs.ia_mode = (mode & S_IALLUGO) | | 517 | rc = PTR_ERR(victim); |
| 555 | (inode->i_mode & ~S_IALLUGO); | 518 | victim = NULL; |
| 556 | newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; | 519 | goto out; |
| 557 | res = notify_change(victim, &newattrs); | ||
| 558 | mutex_unlock(&inode->i_mutex); | ||
| 559 | } | ||
| 560 | dput(victim); | ||
| 561 | } | 520 | } |
| 562 | mutex_unlock(&dir->d_inode->i_mutex); | ||
| 563 | 521 | ||
| 564 | return res; | 522 | inode = victim->d_inode; |
| 523 | mutex_lock(&inode->i_mutex); | ||
| 524 | newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); | ||
| 525 | newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; | ||
| 526 | rc = notify_change(victim, &newattrs); | ||
| 527 | mutex_unlock(&inode->i_mutex); | ||
| 528 | out: | ||
| 529 | dput(victim); | ||
| 530 | sysfs_put(victim_sd); | ||
| 531 | return rc; | ||
| 565 | } | 532 | } |
| 566 | EXPORT_SYMBOL_GPL(sysfs_chmod_file); | 533 | EXPORT_SYMBOL_GPL(sysfs_chmod_file); |
| 567 | 534 | ||
| @@ -576,7 +543,7 @@ EXPORT_SYMBOL_GPL(sysfs_chmod_file); | |||
| 576 | 543 | ||
| 577 | void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr) | 544 | void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr) |
| 578 | { | 545 | { |
| 579 | sysfs_hash_and_remove(kobj->dentry, attr->name); | 546 | sysfs_hash_and_remove(kobj->sd, attr->name); |
| 580 | } | 547 | } |
| 581 | 548 | ||
| 582 | 549 | ||
| @@ -589,12 +556,12 @@ void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr) | |||
| 589 | void sysfs_remove_file_from_group(struct kobject *kobj, | 556 | void sysfs_remove_file_from_group(struct kobject *kobj, |
| 590 | const struct attribute *attr, const char *group) | 557 | const struct attribute *attr, const char *group) |
| 591 | { | 558 | { |
| 592 | struct dentry *dir; | 559 | struct sysfs_dirent *dir_sd; |
| 593 | 560 | ||
| 594 | dir = lookup_one_len(group, kobj->dentry, strlen(group)); | 561 | dir_sd = sysfs_get_dirent(kobj->sd, group); |
| 595 | if (!IS_ERR(dir)) { | 562 | if (dir_sd) { |
| 596 | sysfs_hash_and_remove(dir, attr->name); | 563 | sysfs_hash_and_remove(dir_sd, attr->name); |
| 597 | dput(dir); | 564 | sysfs_put(dir_sd); |
| 598 | } | 565 | } |
| 599 | } | 566 | } |
| 600 | EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group); | 567 | EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group); |
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index 52eed2a7a5ef..f318b73c790c 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c | |||
| @@ -18,26 +18,25 @@ | |||
| 18 | #include "sysfs.h" | 18 | #include "sysfs.h" |
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | static void remove_files(struct dentry * dir, | 21 | static void remove_files(struct sysfs_dirent *dir_sd, |
| 22 | const struct attribute_group * grp) | 22 | const struct attribute_group *grp) |
| 23 | { | 23 | { |
| 24 | struct attribute *const* attr; | 24 | struct attribute *const* attr; |
| 25 | 25 | ||
| 26 | for (attr = grp->attrs; *attr; attr++) | 26 | for (attr = grp->attrs; *attr; attr++) |
| 27 | sysfs_hash_and_remove(dir,(*attr)->name); | 27 | sysfs_hash_and_remove(dir_sd, (*attr)->name); |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | static int create_files(struct dentry * dir, | 30 | static int create_files(struct sysfs_dirent *dir_sd, |
| 31 | const struct attribute_group * grp) | 31 | const struct attribute_group *grp) |
| 32 | { | 32 | { |
| 33 | struct attribute *const* attr; | 33 | struct attribute *const* attr; |
| 34 | int error = 0; | 34 | int error = 0; |
| 35 | 35 | ||
| 36 | for (attr = grp->attrs; *attr && !error; attr++) { | 36 | for (attr = grp->attrs; *attr && !error; attr++) |
| 37 | error = sysfs_add_file(dir, *attr, SYSFS_KOBJ_ATTR); | 37 | error = sysfs_add_file(dir_sd, *attr, SYSFS_KOBJ_ATTR); |
| 38 | } | ||
| 39 | if (error) | 38 | if (error) |
| 40 | remove_files(dir,grp); | 39 | remove_files(dir_sd, grp); |
| 41 | return error; | 40 | return error; |
| 42 | } | 41 | } |
| 43 | 42 | ||
| @@ -45,44 +44,44 @@ static int create_files(struct dentry * dir, | |||
| 45 | int sysfs_create_group(struct kobject * kobj, | 44 | int sysfs_create_group(struct kobject * kobj, |
| 46 | const struct attribute_group * grp) | 45 | const struct attribute_group * grp) |
| 47 | { | 46 | { |
| 48 | struct dentry * dir; | 47 | struct sysfs_dirent *sd; |
| 49 | int error; | 48 | int error; |
| 50 | 49 | ||
| 51 | BUG_ON(!kobj || !kobj->dentry); | 50 | BUG_ON(!kobj || !kobj->sd); |
| 52 | 51 | ||
| 53 | if (grp->name) { | 52 | if (grp->name) { |
| 54 | error = sysfs_create_subdir(kobj,grp->name,&dir); | 53 | error = sysfs_create_subdir(kobj, grp->name, &sd); |
| 55 | if (error) | 54 | if (error) |
| 56 | return error; | 55 | return error; |
| 57 | } else | 56 | } else |
| 58 | dir = kobj->dentry; | 57 | sd = kobj->sd; |
| 59 | dir = dget(dir); | 58 | sysfs_get(sd); |
| 60 | if ((error = create_files(dir,grp))) { | 59 | error = create_files(sd, grp); |
| 60 | if (error) { | ||
| 61 | if (grp->name) | 61 | if (grp->name) |
| 62 | sysfs_remove_subdir(dir); | 62 | sysfs_remove_subdir(sd); |
| 63 | } | 63 | } |
| 64 | dput(dir); | 64 | sysfs_put(sd); |
| 65 | return error; | 65 | return error; |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | void sysfs_remove_group(struct kobject * kobj, | 68 | void sysfs_remove_group(struct kobject * kobj, |
| 69 | const struct attribute_group * grp) | 69 | const struct attribute_group * grp) |
| 70 | { | 70 | { |
| 71 | struct dentry * dir; | 71 | struct sysfs_dirent *dir_sd = kobj->sd; |
| 72 | struct sysfs_dirent *sd; | ||
| 72 | 73 | ||
| 73 | if (grp->name) { | 74 | if (grp->name) { |
| 74 | dir = lookup_one_len_kern(grp->name, kobj->dentry, | 75 | sd = sysfs_get_dirent(dir_sd, grp->name); |
| 75 | strlen(grp->name)); | 76 | BUG_ON(!sd); |
| 76 | BUG_ON(IS_ERR(dir)); | 77 | } else |
| 77 | } | 78 | sd = sysfs_get(dir_sd); |
| 78 | else | ||
| 79 | dir = dget(kobj->dentry); | ||
| 80 | 79 | ||
| 81 | remove_files(dir,grp); | 80 | remove_files(sd, grp); |
| 82 | if (grp->name) | 81 | if (grp->name) |
| 83 | sysfs_remove_subdir(dir); | 82 | sysfs_remove_subdir(sd); |
| 84 | /* release the ref. taken in this routine */ | 83 | |
| 85 | dput(dir); | 84 | sysfs_put(sd); |
| 86 | } | 85 | } |
| 87 | 86 | ||
| 88 | 87 | ||
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 5266eec15f6e..3756e152285a 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c | |||
| @@ -133,187 +133,94 @@ static inline void set_inode_attr(struct inode * inode, struct iattr * iattr) | |||
| 133 | */ | 133 | */ |
| 134 | static struct lock_class_key sysfs_inode_imutex_key; | 134 | static struct lock_class_key sysfs_inode_imutex_key; |
| 135 | 135 | ||
| 136 | struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent * sd) | 136 | void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) |
| 137 | { | 137 | { |
| 138 | struct inode * inode = new_inode(sysfs_sb); | 138 | inode->i_blocks = 0; |
| 139 | if (inode) { | 139 | inode->i_mapping->a_ops = &sysfs_aops; |
| 140 | inode->i_blocks = 0; | 140 | inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; |
| 141 | inode->i_mapping->a_ops = &sysfs_aops; | 141 | inode->i_op = &sysfs_inode_operations; |
| 142 | inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; | 142 | inode->i_ino = sd->s_ino; |
| 143 | inode->i_op = &sysfs_inode_operations; | 143 | lockdep_set_class(&inode->i_mutex, &sysfs_inode_imutex_key); |
| 144 | inode->i_ino = sd->s_ino; | 144 | |
| 145 | lockdep_set_class(&inode->i_mutex, &sysfs_inode_imutex_key); | 145 | if (sd->s_iattr) { |
| 146 | 146 | /* sysfs_dirent has non-default attributes | |
| 147 | if (sd->s_iattr) { | 147 | * get them for the new inode from persistent copy |
| 148 | /* sysfs_dirent has non-default attributes | 148 | * in sysfs_dirent |
| 149 | * get them for the new inode from persistent copy | 149 | */ |
| 150 | * in sysfs_dirent | 150 | set_inode_attr(inode, sd->s_iattr); |
| 151 | */ | ||
| 152 | set_inode_attr(inode, sd->s_iattr); | ||
| 153 | } else | ||
| 154 | set_default_inode_attr(inode, mode); | ||
| 155 | } | ||
| 156 | return inode; | ||
| 157 | } | ||
| 158 | |||
| 159 | int sysfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *)) | ||
| 160 | { | ||
| 161 | int error = 0; | ||
| 162 | struct inode * inode = NULL; | ||
| 163 | if (dentry) { | ||
| 164 | if (!dentry->d_inode) { | ||
| 165 | struct sysfs_dirent * sd = dentry->d_fsdata; | ||
| 166 | if ((inode = sysfs_new_inode(mode, sd))) { | ||
| 167 | if (dentry->d_parent && dentry->d_parent->d_inode) { | ||
| 168 | struct inode *p_inode = dentry->d_parent->d_inode; | ||
| 169 | p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME; | ||
| 170 | } | ||
| 171 | goto Proceed; | ||
| 172 | } | ||
| 173 | else | ||
| 174 | error = -ENOMEM; | ||
| 175 | } else | ||
| 176 | error = -EEXIST; | ||
| 177 | } else | ||
| 178 | error = -ENOENT; | ||
| 179 | goto Done; | ||
| 180 | |||
| 181 | Proceed: | ||
| 182 | if (init) | ||
| 183 | error = init(inode); | ||
| 184 | if (!error) { | ||
| 185 | d_instantiate(dentry, inode); | ||
| 186 | if (S_ISDIR(mode)) | ||
| 187 | dget(dentry); /* pin only directory dentry in core */ | ||
| 188 | } else | 151 | } else |
| 189 | iput(inode); | 152 | set_default_inode_attr(inode, sd->s_mode); |
| 190 | Done: | ||
| 191 | return error; | ||
| 192 | } | 153 | } |
| 193 | 154 | ||
| 194 | /* | 155 | /** |
| 195 | * Get the name for corresponding element represented by the given sysfs_dirent | 156 | * sysfs_get_inode - get inode for sysfs_dirent |
| 157 | * @sd: sysfs_dirent to allocate inode for | ||
| 158 | * | ||
| 159 | * Get inode for @sd. If such inode doesn't exist, a new inode | ||
| 160 | * is allocated and basics are initialized. New inode is | ||
| 161 | * returned locked. | ||
| 162 | * | ||
| 163 | * LOCKING: | ||
| 164 | * Kernel thread context (may sleep). | ||
| 165 | * | ||
| 166 | * RETURNS: | ||
| 167 | * Pointer to allocated inode on success, NULL on failure. | ||
| 196 | */ | 168 | */ |
| 197 | const unsigned char * sysfs_get_name(struct sysfs_dirent *sd) | 169 | struct inode * sysfs_get_inode(struct sysfs_dirent *sd) |
| 198 | { | 170 | { |
| 199 | struct attribute * attr; | 171 | struct inode *inode; |
| 200 | struct bin_attribute * bin_attr; | ||
| 201 | struct sysfs_symlink * sl; | ||
| 202 | |||
| 203 | BUG_ON(!sd || !sd->s_element); | ||
| 204 | |||
| 205 | switch (sd->s_type) { | ||
| 206 | case SYSFS_DIR: | ||
| 207 | /* Always have a dentry so use that */ | ||
| 208 | return sd->s_dentry->d_name.name; | ||
| 209 | |||
| 210 | case SYSFS_KOBJ_ATTR: | ||
| 211 | attr = sd->s_element; | ||
| 212 | return attr->name; | ||
| 213 | |||
| 214 | case SYSFS_KOBJ_BIN_ATTR: | ||
| 215 | bin_attr = sd->s_element; | ||
| 216 | return bin_attr->attr.name; | ||
| 217 | 172 | ||
| 218 | case SYSFS_KOBJ_LINK: | 173 | inode = iget_locked(sysfs_sb, sd->s_ino); |
| 219 | sl = sd->s_element; | 174 | if (inode && (inode->i_state & I_NEW)) |
| 220 | return sl->link_name; | 175 | sysfs_init_inode(sd, inode); |
| 221 | } | ||
| 222 | return NULL; | ||
| 223 | } | ||
| 224 | 176 | ||
| 225 | static inline void orphan_all_buffers(struct inode *node) | 177 | return inode; |
| 226 | { | ||
| 227 | struct sysfs_buffer_collection *set; | ||
| 228 | struct sysfs_buffer *buf; | ||
| 229 | |||
| 230 | mutex_lock_nested(&node->i_mutex, I_MUTEX_CHILD); | ||
| 231 | set = node->i_private; | ||
| 232 | if (set) { | ||
| 233 | list_for_each_entry(buf, &set->associates, associates) { | ||
| 234 | down(&buf->sem); | ||
| 235 | buf->orphaned = 1; | ||
| 236 | up(&buf->sem); | ||
| 237 | } | ||
| 238 | } | ||
| 239 | mutex_unlock(&node->i_mutex); | ||
| 240 | } | 178 | } |
| 241 | 179 | ||
| 242 | 180 | /** | |
| 243 | /* | 181 | * sysfs_instantiate - instantiate dentry |
| 244 | * Unhashes the dentry corresponding to given sysfs_dirent | 182 | * @dentry: dentry to be instantiated |
| 245 | * Called with parent inode's i_mutex held. | 183 | * @inode: inode associated with @sd |
| 184 | * | ||
| 185 | * Unlock @inode if locked and instantiate @dentry with @inode. | ||
| 186 | * | ||
| 187 | * LOCKING: | ||
| 188 | * None. | ||
| 246 | */ | 189 | */ |
| 247 | void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent) | 190 | void sysfs_instantiate(struct dentry *dentry, struct inode *inode) |
| 248 | { | 191 | { |
| 249 | struct dentry *dentry = NULL; | 192 | BUG_ON(!dentry || dentry->d_inode); |
| 250 | struct inode *inode; | ||
| 251 | 193 | ||
| 252 | /* We're not holding a reference to ->s_dentry dentry but the | 194 | if (inode->i_state & I_NEW) |
| 253 | * field will stay valid as long as sysfs_lock is held. | 195 | unlock_new_inode(inode); |
| 254 | */ | ||
| 255 | spin_lock(&sysfs_lock); | ||
| 256 | spin_lock(&dcache_lock); | ||
| 257 | |||
| 258 | /* dget dentry if it's still alive */ | ||
| 259 | if (sd->s_dentry && sd->s_dentry->d_inode) | ||
| 260 | dentry = dget_locked(sd->s_dentry); | ||
| 261 | |||
| 262 | spin_unlock(&dcache_lock); | ||
| 263 | spin_unlock(&sysfs_lock); | ||
| 264 | |||
| 265 | /* drop dentry */ | ||
| 266 | if (dentry) { | ||
| 267 | spin_lock(&dcache_lock); | ||
| 268 | spin_lock(&dentry->d_lock); | ||
| 269 | if (!d_unhashed(dentry) && dentry->d_inode) { | ||
| 270 | inode = dentry->d_inode; | ||
| 271 | spin_lock(&inode->i_lock); | ||
| 272 | __iget(inode); | ||
| 273 | spin_unlock(&inode->i_lock); | ||
| 274 | dget_locked(dentry); | ||
| 275 | __d_drop(dentry); | ||
| 276 | spin_unlock(&dentry->d_lock); | ||
| 277 | spin_unlock(&dcache_lock); | ||
| 278 | simple_unlink(parent->d_inode, dentry); | ||
| 279 | orphan_all_buffers(inode); | ||
| 280 | iput(inode); | ||
| 281 | } else { | ||
| 282 | spin_unlock(&dentry->d_lock); | ||
| 283 | spin_unlock(&dcache_lock); | ||
| 284 | } | ||
| 285 | 196 | ||
| 286 | dput(dentry); | 197 | d_instantiate(dentry, inode); |
| 287 | } | ||
| 288 | } | 198 | } |
| 289 | 199 | ||
| 290 | int sysfs_hash_and_remove(struct dentry * dir, const char * name) | 200 | int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name) |
| 291 | { | 201 | { |
| 292 | struct sysfs_dirent * sd; | 202 | struct sysfs_addrm_cxt acxt; |
| 293 | struct sysfs_dirent * parent_sd; | 203 | struct sysfs_dirent **pos, *sd; |
| 294 | int found = 0; | ||
| 295 | 204 | ||
| 296 | if (!dir) | 205 | if (!dir_sd) |
| 297 | return -ENOENT; | 206 | return -ENOENT; |
| 298 | 207 | ||
| 299 | if (dir->d_inode == NULL) | 208 | sysfs_addrm_start(&acxt, dir_sd); |
| 300 | /* no inode means this hasn't been made visible yet */ | 209 | |
| 301 | return -ENOENT; | 210 | for (pos = &dir_sd->s_children; *pos; pos = &(*pos)->s_sibling) { |
| 211 | sd = *pos; | ||
| 302 | 212 | ||
| 303 | parent_sd = dir->d_fsdata; | 213 | if (!sysfs_type(sd)) |
| 304 | mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); | ||
| 305 | list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { | ||
| 306 | if (!sd->s_element) | ||
| 307 | continue; | 214 | continue; |
| 308 | if (!strcmp(sysfs_get_name(sd), name)) { | 215 | if (!strcmp(sd->s_name, name)) { |
| 309 | list_del_init(&sd->s_sibling); | 216 | *pos = sd->s_sibling; |
| 310 | sysfs_drop_dentry(sd, dir); | 217 | sd->s_sibling = NULL; |
| 311 | sysfs_put(sd); | 218 | sysfs_remove_one(&acxt, sd); |
| 312 | found = 1; | ||
| 313 | break; | 219 | break; |
| 314 | } | 220 | } |
| 315 | } | 221 | } |
| 316 | mutex_unlock(&dir->d_inode->i_mutex); | ||
| 317 | 222 | ||
| 318 | return found ? 0 : -ENOENT; | 223 | if (sysfs_addrm_finish(&acxt)) |
| 224 | return 0; | ||
| 225 | return -ENOENT; | ||
| 319 | } | 226 | } |
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 00ab9125d398..402cc356203c 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c | |||
| @@ -19,28 +19,18 @@ struct vfsmount *sysfs_mount; | |||
| 19 | struct super_block * sysfs_sb = NULL; | 19 | struct super_block * sysfs_sb = NULL; |
| 20 | struct kmem_cache *sysfs_dir_cachep; | 20 | struct kmem_cache *sysfs_dir_cachep; |
| 21 | 21 | ||
| 22 | static void sysfs_clear_inode(struct inode *inode); | ||
| 23 | |||
| 24 | static const struct super_operations sysfs_ops = { | 22 | static const struct super_operations sysfs_ops = { |
| 25 | .statfs = simple_statfs, | 23 | .statfs = simple_statfs, |
| 26 | .drop_inode = sysfs_delete_inode, | 24 | .drop_inode = sysfs_delete_inode, |
| 27 | .clear_inode = sysfs_clear_inode, | ||
| 28 | }; | 25 | }; |
| 29 | 26 | ||
| 30 | static struct sysfs_dirent sysfs_root = { | 27 | struct sysfs_dirent sysfs_root = { |
| 31 | .s_sibling = LIST_HEAD_INIT(sysfs_root.s_sibling), | 28 | .s_count = ATOMIC_INIT(1), |
| 32 | .s_children = LIST_HEAD_INIT(sysfs_root.s_children), | 29 | .s_flags = SYSFS_ROOT, |
| 33 | .s_element = NULL, | 30 | .s_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, |
| 34 | .s_type = SYSFS_ROOT, | ||
| 35 | .s_iattr = NULL, | ||
| 36 | .s_ino = 1, | 31 | .s_ino = 1, |
| 37 | }; | 32 | }; |
| 38 | 33 | ||
| 39 | static void sysfs_clear_inode(struct inode *inode) | ||
| 40 | { | ||
| 41 | kfree(inode->i_private); | ||
| 42 | } | ||
| 43 | |||
| 44 | static int sysfs_fill_super(struct super_block *sb, void *data, int silent) | 34 | static int sysfs_fill_super(struct super_block *sb, void *data, int silent) |
| 45 | { | 35 | { |
| 46 | struct inode *inode; | 36 | struct inode *inode; |
| @@ -53,24 +43,26 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 53 | sb->s_time_gran = 1; | 43 | sb->s_time_gran = 1; |
| 54 | sysfs_sb = sb; | 44 | sysfs_sb = sb; |
| 55 | 45 | ||
| 56 | inode = sysfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, | 46 | inode = new_inode(sysfs_sb); |
| 57 | &sysfs_root); | 47 | if (!inode) { |
| 58 | if (inode) { | ||
| 59 | inode->i_op = &sysfs_dir_inode_operations; | ||
| 60 | inode->i_fop = &sysfs_dir_operations; | ||
| 61 | /* directory inodes start off with i_nlink == 2 (for "." entry) */ | ||
| 62 | inc_nlink(inode); | ||
| 63 | } else { | ||
| 64 | pr_debug("sysfs: could not get root inode\n"); | 48 | pr_debug("sysfs: could not get root inode\n"); |
| 65 | return -ENOMEM; | 49 | return -ENOMEM; |
| 66 | } | 50 | } |
| 67 | 51 | ||
| 52 | sysfs_init_inode(&sysfs_root, inode); | ||
| 53 | |||
| 54 | inode->i_op = &sysfs_dir_inode_operations; | ||
| 55 | inode->i_fop = &sysfs_dir_operations; | ||
| 56 | /* directory inodes start off with i_nlink == 2 (for "." entry) */ | ||
| 57 | inc_nlink(inode); | ||
| 58 | |||
| 68 | root = d_alloc_root(inode); | 59 | root = d_alloc_root(inode); |
| 69 | if (!root) { | 60 | if (!root) { |
| 70 | pr_debug("%s: could not get root dentry!\n",__FUNCTION__); | 61 | pr_debug("%s: could not get root dentry!\n",__FUNCTION__); |
| 71 | iput(inode); | 62 | iput(inode); |
| 72 | return -ENOMEM; | 63 | return -ENOMEM; |
| 73 | } | 64 | } |
| 65 | sysfs_root.s_dentry = root; | ||
| 74 | root->d_fsdata = &sysfs_root; | 66 | root->d_fsdata = &sysfs_root; |
| 75 | sb->s_root = root; | 67 | sb->s_root = root; |
| 76 | return 0; | 68 | return 0; |
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index 7b9c5bfde920..2f86e0422290 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c | |||
| @@ -11,71 +11,39 @@ | |||
| 11 | 11 | ||
| 12 | #include "sysfs.h" | 12 | #include "sysfs.h" |
| 13 | 13 | ||
| 14 | static int object_depth(struct kobject * kobj) | 14 | static int object_depth(struct sysfs_dirent *sd) |
| 15 | { | 15 | { |
| 16 | struct kobject * p = kobj; | ||
| 17 | int depth = 0; | 16 | int depth = 0; |
| 18 | do { depth++; } while ((p = p->parent)); | 17 | |
| 18 | for (; sd->s_parent; sd = sd->s_parent) | ||
| 19 | depth++; | ||
| 20 | |||
| 19 | return depth; | 21 | return depth; |
| 20 | } | 22 | } |
| 21 | 23 | ||
| 22 | static int object_path_length(struct kobject * kobj) | 24 | static int object_path_length(struct sysfs_dirent * sd) |
| 23 | { | 25 | { |
| 24 | struct kobject * p = kobj; | ||
| 25 | int length = 1; | 26 | int length = 1; |
| 26 | do { | 27 | |
| 27 | length += strlen(kobject_name(p)) + 1; | 28 | for (; sd->s_parent; sd = sd->s_parent) |
| 28 | p = p->parent; | 29 | length += strlen(sd->s_name) + 1; |
| 29 | } while (p); | 30 | |
| 30 | return length; | 31 | return length; |
| 31 | } | 32 | } |
| 32 | 33 | ||
| 33 | static void fill_object_path(struct kobject * kobj, char * buffer, int length) | 34 | static void fill_object_path(struct sysfs_dirent *sd, char *buffer, int length) |
| 34 | { | 35 | { |
| 35 | struct kobject * p; | ||
| 36 | |||
| 37 | --length; | 36 | --length; |
| 38 | for (p = kobj; p; p = p->parent) { | 37 | for (; sd->s_parent; sd = sd->s_parent) { |
| 39 | int cur = strlen(kobject_name(p)); | 38 | int cur = strlen(sd->s_name); |
| 40 | 39 | ||
| 41 | /* back up enough to print this bus id with '/' */ | 40 | /* back up enough to print this bus id with '/' */ |
| 42 | length -= cur; | 41 | length -= cur; |
| 43 | strncpy(buffer + length,kobject_name(p),cur); | 42 | strncpy(buffer + length, sd->s_name, cur); |
| 44 | *(buffer + --length) = '/'; | 43 | *(buffer + --length) = '/'; |
| 45 | } | 44 | } |
| 46 | } | 45 | } |
| 47 | 46 | ||
| 48 | static int sysfs_add_link(struct dentry * parent, const char * name, struct kobject * target) | ||
| 49 | { | ||
| 50 | struct sysfs_dirent * parent_sd = parent->d_fsdata; | ||
| 51 | struct sysfs_symlink * sl; | ||
| 52 | int error = 0; | ||
| 53 | |||
| 54 | error = -ENOMEM; | ||
| 55 | sl = kmalloc(sizeof(*sl), GFP_KERNEL); | ||
| 56 | if (!sl) | ||
| 57 | goto exit1; | ||
| 58 | |||
| 59 | sl->link_name = kmalloc(strlen(name) + 1, GFP_KERNEL); | ||
| 60 | if (!sl->link_name) | ||
| 61 | goto exit2; | ||
| 62 | |||
| 63 | strcpy(sl->link_name, name); | ||
| 64 | sl->target_kobj = kobject_get(target); | ||
| 65 | |||
| 66 | error = sysfs_make_dirent(parent_sd, NULL, sl, S_IFLNK|S_IRWXUGO, | ||
| 67 | SYSFS_KOBJ_LINK); | ||
| 68 | if (!error) | ||
| 69 | return 0; | ||
| 70 | |||
| 71 | kobject_put(target); | ||
| 72 | kfree(sl->link_name); | ||
| 73 | exit2: | ||
| 74 | kfree(sl); | ||
| 75 | exit1: | ||
| 76 | return error; | ||
| 77 | } | ||
| 78 | |||
| 79 | /** | 47 | /** |
| 80 | * sysfs_create_link - create symlink between two objects. | 48 | * sysfs_create_link - create symlink between two objects. |
| 81 | * @kobj: object whose directory we're creating the link in. | 49 | * @kobj: object whose directory we're creating the link in. |
| @@ -84,24 +52,57 @@ exit1: | |||
| 84 | */ | 52 | */ |
| 85 | int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name) | 53 | int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name) |
| 86 | { | 54 | { |
| 87 | struct dentry *dentry = NULL; | 55 | struct sysfs_dirent *parent_sd = NULL; |
| 88 | int error = -EEXIST; | 56 | struct sysfs_dirent *target_sd = NULL; |
| 57 | struct sysfs_dirent *sd = NULL; | ||
| 58 | struct sysfs_addrm_cxt acxt; | ||
| 59 | int error; | ||
| 89 | 60 | ||
| 90 | BUG_ON(!name); | 61 | BUG_ON(!name); |
| 91 | 62 | ||
| 92 | if (!kobj) { | 63 | if (!kobj) { |
| 93 | if (sysfs_mount && sysfs_mount->mnt_sb) | 64 | if (sysfs_mount && sysfs_mount->mnt_sb) |
| 94 | dentry = sysfs_mount->mnt_sb->s_root; | 65 | parent_sd = sysfs_mount->mnt_sb->s_root->d_fsdata; |
| 95 | } else | 66 | } else |
| 96 | dentry = kobj->dentry; | 67 | parent_sd = kobj->sd; |
| 68 | |||
| 69 | error = -EFAULT; | ||
| 70 | if (!parent_sd) | ||
| 71 | goto out_put; | ||
| 72 | |||
| 73 | /* target->sd can go away beneath us but is protected with | ||
| 74 | * sysfs_assoc_lock. Fetch target_sd from it. | ||
| 75 | */ | ||
| 76 | spin_lock(&sysfs_assoc_lock); | ||
| 77 | if (target->sd) | ||
| 78 | target_sd = sysfs_get(target->sd); | ||
| 79 | spin_unlock(&sysfs_assoc_lock); | ||
| 80 | |||
| 81 | error = -ENOENT; | ||
| 82 | if (!target_sd) | ||
| 83 | goto out_put; | ||
| 84 | |||
| 85 | error = -ENOMEM; | ||
| 86 | sd = sysfs_new_dirent(name, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK); | ||
| 87 | if (!sd) | ||
| 88 | goto out_put; | ||
| 89 | sd->s_elem.symlink.target_sd = target_sd; | ||
| 97 | 90 | ||
| 98 | if (!dentry) | 91 | sysfs_addrm_start(&acxt, parent_sd); |
| 99 | return -EFAULT; | ||
| 100 | 92 | ||
| 101 | mutex_lock(&dentry->d_inode->i_mutex); | 93 | if (!sysfs_find_dirent(parent_sd, name)) { |
| 102 | if (!sysfs_dirent_exist(dentry->d_fsdata, name)) | 94 | sysfs_add_one(&acxt, sd); |
| 103 | error = sysfs_add_link(dentry, name, target); | 95 | sysfs_link_sibling(sd); |
| 104 | mutex_unlock(&dentry->d_inode->i_mutex); | 96 | } |
| 97 | |||
| 98 | if (sysfs_addrm_finish(&acxt)) | ||
| 99 | return 0; | ||
| 100 | |||
| 101 | error = -EEXIST; | ||
| 102 | /* fall through */ | ||
| 103 | out_put: | ||
| 104 | sysfs_put(target_sd); | ||
| 105 | sysfs_put(sd); | ||
| 105 | return error; | 106 | return error; |
| 106 | } | 107 | } |
| 107 | 108 | ||
| @@ -114,17 +115,17 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char | |||
| 114 | 115 | ||
| 115 | void sysfs_remove_link(struct kobject * kobj, const char * name) | 116 | void sysfs_remove_link(struct kobject * kobj, const char * name) |
| 116 | { | 117 | { |
| 117 | sysfs_hash_and_remove(kobj->dentry,name); | 118 | sysfs_hash_and_remove(kobj->sd, name); |
| 118 | } | 119 | } |
| 119 | 120 | ||
| 120 | static int sysfs_get_target_path(struct kobject * kobj, struct kobject * target, | 121 | static int sysfs_get_target_path(struct sysfs_dirent * parent_sd, |
| 121 | char *path) | 122 | struct sysfs_dirent * target_sd, char *path) |
| 122 | { | 123 | { |
| 123 | char * s; | 124 | char * s; |
| 124 | int depth, size; | 125 | int depth, size; |
| 125 | 126 | ||
| 126 | depth = object_depth(kobj); | 127 | depth = object_depth(parent_sd); |
| 127 | size = object_path_length(target) + depth * 3 - 1; | 128 | size = object_path_length(target_sd) + depth * 3 - 1; |
| 128 | if (size > PATH_MAX) | 129 | if (size > PATH_MAX) |
| 129 | return -ENAMETOOLONG; | 130 | return -ENAMETOOLONG; |
| 130 | 131 | ||
| @@ -133,7 +134,7 @@ static int sysfs_get_target_path(struct kobject * kobj, struct kobject * target, | |||
| 133 | for (s = path; depth--; s += 3) | 134 | for (s = path; depth--; s += 3) |
| 134 | strcpy(s,"../"); | 135 | strcpy(s,"../"); |
| 135 | 136 | ||
| 136 | fill_object_path(target, path, size); | 137 | fill_object_path(target_sd, path, size); |
| 137 | pr_debug("%s: path = '%s'\n", __FUNCTION__, path); | 138 | pr_debug("%s: path = '%s'\n", __FUNCTION__, path); |
| 138 | 139 | ||
| 139 | return 0; | 140 | return 0; |
| @@ -141,27 +142,16 @@ static int sysfs_get_target_path(struct kobject * kobj, struct kobject * target, | |||
| 141 | 142 | ||
| 142 | static int sysfs_getlink(struct dentry *dentry, char * path) | 143 | static int sysfs_getlink(struct dentry *dentry, char * path) |
| 143 | { | 144 | { |
| 144 | struct kobject *kobj, *target_kobj; | 145 | struct sysfs_dirent *sd = dentry->d_fsdata; |
| 145 | int error = 0; | 146 | struct sysfs_dirent *parent_sd = sd->s_parent; |
| 147 | struct sysfs_dirent *target_sd = sd->s_elem.symlink.target_sd; | ||
| 148 | int error; | ||
| 146 | 149 | ||
| 147 | kobj = sysfs_get_kobject(dentry->d_parent); | 150 | mutex_lock(&sysfs_mutex); |
| 148 | if (!kobj) | 151 | error = sysfs_get_target_path(parent_sd, target_sd, path); |
| 149 | return -EINVAL; | 152 | mutex_unlock(&sysfs_mutex); |
| 150 | 153 | ||
| 151 | target_kobj = sysfs_get_kobject(dentry); | ||
| 152 | if (!target_kobj) { | ||
| 153 | kobject_put(kobj); | ||
| 154 | return -EINVAL; | ||
| 155 | } | ||
| 156 | |||
| 157 | down_read(&sysfs_rename_sem); | ||
| 158 | error = sysfs_get_target_path(kobj, target_kobj, path); | ||
| 159 | up_read(&sysfs_rename_sem); | ||
| 160 | |||
| 161 | kobject_put(kobj); | ||
| 162 | kobject_put(target_kobj); | ||
| 163 | return error; | 154 | return error; |
| 164 | |||
| 165 | } | 155 | } |
| 166 | 156 | ||
| 167 | static void *sysfs_follow_link(struct dentry *dentry, struct nameidata *nd) | 157 | static void *sysfs_follow_link(struct dentry *dentry, struct nameidata *nd) |
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 502c949c402d..6a37f2386a8d 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h | |||
| @@ -1,9 +1,40 @@ | |||
| 1 | struct sysfs_elem_dir { | ||
| 2 | struct kobject * kobj; | ||
| 3 | }; | ||
| 4 | |||
| 5 | struct sysfs_elem_symlink { | ||
| 6 | struct sysfs_dirent * target_sd; | ||
| 7 | }; | ||
| 8 | |||
| 9 | struct sysfs_elem_attr { | ||
| 10 | struct attribute * attr; | ||
| 11 | }; | ||
| 12 | |||
| 13 | struct sysfs_elem_bin_attr { | ||
| 14 | struct bin_attribute * bin_attr; | ||
| 15 | }; | ||
| 16 | |||
| 17 | /* | ||
| 18 | * As long as s_count reference is held, the sysfs_dirent itself is | ||
| 19 | * accessible. Dereferencing s_elem or any other outer entity | ||
| 20 | * requires s_active reference. | ||
| 21 | */ | ||
| 1 | struct sysfs_dirent { | 22 | struct sysfs_dirent { |
| 2 | atomic_t s_count; | 23 | atomic_t s_count; |
| 3 | struct list_head s_sibling; | 24 | atomic_t s_active; |
| 4 | struct list_head s_children; | 25 | struct sysfs_dirent * s_parent; |
| 5 | void * s_element; | 26 | struct sysfs_dirent * s_sibling; |
| 6 | int s_type; | 27 | struct sysfs_dirent * s_children; |
| 28 | const char * s_name; | ||
| 29 | |||
| 30 | union { | ||
| 31 | struct sysfs_elem_dir dir; | ||
| 32 | struct sysfs_elem_symlink symlink; | ||
| 33 | struct sysfs_elem_attr attr; | ||
| 34 | struct sysfs_elem_bin_attr bin_attr; | ||
| 35 | } s_elem; | ||
| 36 | |||
| 37 | unsigned int s_flags; | ||
| 7 | umode_t s_mode; | 38 | umode_t s_mode; |
| 8 | ino_t s_ino; | 39 | ino_t s_ino; |
| 9 | struct dentry * s_dentry; | 40 | struct dentry * s_dentry; |
| @@ -11,30 +42,60 @@ struct sysfs_dirent { | |||
| 11 | atomic_t s_event; | 42 | atomic_t s_event; |
| 12 | }; | 43 | }; |
| 13 | 44 | ||
| 45 | #define SD_DEACTIVATED_BIAS INT_MIN | ||
| 46 | |||
| 47 | struct sysfs_addrm_cxt { | ||
| 48 | struct sysfs_dirent *parent_sd; | ||
| 49 | struct inode *parent_inode; | ||
| 50 | struct sysfs_dirent *removed; | ||
| 51 | int cnt; | ||
| 52 | }; | ||
| 53 | |||
| 14 | extern struct vfsmount * sysfs_mount; | 54 | extern struct vfsmount * sysfs_mount; |
| 55 | extern struct sysfs_dirent sysfs_root; | ||
| 15 | extern struct kmem_cache *sysfs_dir_cachep; | 56 | extern struct kmem_cache *sysfs_dir_cachep; |
| 16 | 57 | ||
| 17 | extern void sysfs_delete_inode(struct inode *inode); | 58 | extern struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd); |
| 18 | extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *); | 59 | extern void sysfs_link_sibling(struct sysfs_dirent *sd); |
| 19 | extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *)); | 60 | extern void sysfs_unlink_sibling(struct sysfs_dirent *sd); |
| 61 | extern struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd); | ||
| 62 | extern void sysfs_put_active(struct sysfs_dirent *sd); | ||
| 63 | extern struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd); | ||
| 64 | extern void sysfs_put_active_two(struct sysfs_dirent *sd); | ||
| 65 | extern void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, | ||
| 66 | struct sysfs_dirent *parent_sd); | ||
| 67 | extern void sysfs_add_one(struct sysfs_addrm_cxt *acxt, | ||
| 68 | struct sysfs_dirent *sd); | ||
| 69 | extern void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, | ||
| 70 | struct sysfs_dirent *sd); | ||
| 71 | extern int sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); | ||
| 20 | 72 | ||
| 21 | extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *); | 73 | extern void sysfs_delete_inode(struct inode *inode); |
| 22 | extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *, | 74 | extern void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode); |
| 23 | umode_t, int); | 75 | extern struct inode * sysfs_get_inode(struct sysfs_dirent *sd); |
| 24 | 76 | extern void sysfs_instantiate(struct dentry *dentry, struct inode *inode); | |
| 25 | extern int sysfs_add_file(struct dentry *, const struct attribute *, int); | 77 | |
| 26 | extern int sysfs_hash_and_remove(struct dentry * dir, const char * name); | 78 | extern void release_sysfs_dirent(struct sysfs_dirent * sd); |
| 79 | extern struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, | ||
| 80 | const unsigned char *name); | ||
| 81 | extern struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd, | ||
| 82 | const unsigned char *name); | ||
| 83 | extern struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, | ||
| 84 | int type); | ||
| 85 | |||
| 86 | extern int sysfs_add_file(struct sysfs_dirent *dir_sd, | ||
| 87 | const struct attribute *attr, int type); | ||
| 88 | extern int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name); | ||
| 27 | extern struct sysfs_dirent *sysfs_find(struct sysfs_dirent *dir, const char * name); | 89 | extern struct sysfs_dirent *sysfs_find(struct sysfs_dirent *dir, const char * name); |
| 28 | 90 | ||
| 29 | extern int sysfs_create_subdir(struct kobject *, const char *, struct dentry **); | 91 | extern int sysfs_create_subdir(struct kobject *kobj, const char *name, |
| 30 | extern void sysfs_remove_subdir(struct dentry *); | 92 | struct sysfs_dirent **p_sd); |
| 93 | extern void sysfs_remove_subdir(struct sysfs_dirent *sd); | ||
| 31 | 94 | ||
| 32 | extern const unsigned char * sysfs_get_name(struct sysfs_dirent *sd); | ||
| 33 | extern void sysfs_drop_dentry(struct sysfs_dirent *sd, struct dentry *parent); | ||
| 34 | extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); | 95 | extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); |
| 35 | 96 | ||
| 36 | extern spinlock_t sysfs_lock; | 97 | extern spinlock_t sysfs_assoc_lock; |
| 37 | extern struct rw_semaphore sysfs_rename_sem; | 98 | extern struct mutex sysfs_mutex; |
| 38 | extern struct super_block * sysfs_sb; | 99 | extern struct super_block * sysfs_sb; |
| 39 | extern const struct file_operations sysfs_dir_operations; | 100 | extern const struct file_operations sysfs_dir_operations; |
| 40 | extern const struct file_operations sysfs_file_operations; | 101 | extern const struct file_operations sysfs_file_operations; |
| @@ -42,73 +103,9 @@ extern const struct file_operations bin_fops; | |||
| 42 | extern const struct inode_operations sysfs_dir_inode_operations; | 103 | extern const struct inode_operations sysfs_dir_inode_operations; |
| 43 | extern const struct inode_operations sysfs_symlink_inode_operations; | 104 | extern const struct inode_operations sysfs_symlink_inode_operations; |
| 44 | 105 | ||
| 45 | struct sysfs_symlink { | 106 | static inline unsigned int sysfs_type(struct sysfs_dirent *sd) |
| 46 | char * link_name; | ||
| 47 | struct kobject * target_kobj; | ||
| 48 | }; | ||
| 49 | |||
| 50 | struct sysfs_buffer { | ||
| 51 | struct list_head associates; | ||
| 52 | size_t count; | ||
| 53 | loff_t pos; | ||
| 54 | char * page; | ||
| 55 | struct sysfs_ops * ops; | ||
| 56 | struct semaphore sem; | ||
| 57 | int orphaned; | ||
| 58 | int needs_read_fill; | ||
| 59 | int event; | ||
| 60 | }; | ||
| 61 | |||
| 62 | struct sysfs_buffer_collection { | ||
| 63 | struct list_head associates; | ||
| 64 | }; | ||
| 65 | |||
| 66 | static inline struct kobject * to_kobj(struct dentry * dentry) | ||
| 67 | { | ||
| 68 | struct sysfs_dirent * sd = dentry->d_fsdata; | ||
| 69 | return ((struct kobject *) sd->s_element); | ||
| 70 | } | ||
| 71 | |||
| 72 | static inline struct attribute * to_attr(struct dentry * dentry) | ||
| 73 | { | 107 | { |
| 74 | struct sysfs_dirent * sd = dentry->d_fsdata; | 108 | return sd->s_flags & SYSFS_TYPE_MASK; |
| 75 | return ((struct attribute *) sd->s_element); | ||
| 76 | } | ||
| 77 | |||
| 78 | static inline struct bin_attribute * to_bin_attr(struct dentry * dentry) | ||
| 79 | { | ||
| 80 | struct sysfs_dirent * sd = dentry->d_fsdata; | ||
| 81 | return ((struct bin_attribute *) sd->s_element); | ||
| 82 | } | ||
| 83 | |||
| 84 | static inline struct kobject *sysfs_get_kobject(struct dentry *dentry) | ||
| 85 | { | ||
| 86 | struct kobject * kobj = NULL; | ||
| 87 | |||
| 88 | spin_lock(&dcache_lock); | ||
| 89 | if (!d_unhashed(dentry)) { | ||
| 90 | struct sysfs_dirent * sd = dentry->d_fsdata; | ||
| 91 | if (sd->s_type & SYSFS_KOBJ_LINK) { | ||
| 92 | struct sysfs_symlink * sl = sd->s_element; | ||
| 93 | kobj = kobject_get(sl->target_kobj); | ||
| 94 | } else | ||
| 95 | kobj = kobject_get(sd->s_element); | ||
| 96 | } | ||
| 97 | spin_unlock(&dcache_lock); | ||
| 98 | |||
| 99 | return kobj; | ||
| 100 | } | ||
| 101 | |||
| 102 | static inline void release_sysfs_dirent(struct sysfs_dirent * sd) | ||
| 103 | { | ||
| 104 | if (sd->s_type & SYSFS_KOBJ_LINK) { | ||
| 105 | struct sysfs_symlink * sl = sd->s_element; | ||
| 106 | kfree(sl->link_name); | ||
| 107 | kobject_put(sl->target_kobj); | ||
| 108 | kfree(sl); | ||
| 109 | } | ||
| 110 | kfree(sd->s_iattr); | ||
| 111 | kmem_cache_free(sysfs_dir_cachep, sd); | ||
| 112 | } | 109 | } |
| 113 | 110 | ||
| 114 | static inline struct sysfs_dirent * sysfs_get(struct sysfs_dirent * sd) | 111 | static inline struct sysfs_dirent * sysfs_get(struct sysfs_dirent * sd) |
| @@ -122,7 +119,7 @@ static inline struct sysfs_dirent * sysfs_get(struct sysfs_dirent * sd) | |||
| 122 | 119 | ||
| 123 | static inline void sysfs_put(struct sysfs_dirent * sd) | 120 | static inline void sysfs_put(struct sysfs_dirent * sd) |
| 124 | { | 121 | { |
| 125 | if (atomic_dec_and_test(&sd->s_count)) | 122 | if (sd && atomic_dec_and_test(&sd->s_count)) |
| 126 | release_sysfs_dirent(sd); | 123 | release_sysfs_dirent(sd); |
| 127 | } | 124 | } |
| 128 | 125 | ||
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h index 5a9c49534d08..104e51e20e14 100644 --- a/include/linux/debugfs.h +++ b/include/linux/debugfs.h | |||
| @@ -38,6 +38,9 @@ struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent, | |||
| 38 | 38 | ||
| 39 | void debugfs_remove(struct dentry *dentry); | 39 | void debugfs_remove(struct dentry *dentry); |
| 40 | 40 | ||
| 41 | struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, | ||
| 42 | struct dentry *new_dir, const char *new_name); | ||
| 43 | |||
| 41 | struct dentry *debugfs_create_u8(const char *name, mode_t mode, | 44 | struct dentry *debugfs_create_u8(const char *name, mode_t mode, |
| 42 | struct dentry *parent, u8 *value); | 45 | struct dentry *parent, u8 *value); |
| 43 | struct dentry *debugfs_create_u16(const char *name, mode_t mode, | 46 | struct dentry *debugfs_create_u16(const char *name, mode_t mode, |
| @@ -85,6 +88,12 @@ static inline struct dentry *debugfs_create_symlink(const char *name, | |||
| 85 | static inline void debugfs_remove(struct dentry *dentry) | 88 | static inline void debugfs_remove(struct dentry *dentry) |
| 86 | { } | 89 | { } |
| 87 | 90 | ||
| 91 | static inline struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, | ||
| 92 | struct dentry *new_dir, char *new_name) | ||
| 93 | { | ||
| 94 | return ERR_PTR(-ENODEV); | ||
| 95 | } | ||
| 96 | |||
| 88 | static inline struct dentry *debugfs_create_u8(const char *name, mode_t mode, | 97 | static inline struct dentry *debugfs_create_u8(const char *name, mode_t mode, |
| 89 | struct dentry *parent, | 98 | struct dentry *parent, |
| 90 | u8 *value) | 99 | u8 *value) |
diff --git a/include/linux/device.h b/include/linux/device.h index 2e1a2988b7e1..be2debed70d2 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
| @@ -238,7 +238,6 @@ extern int __must_check class_device_create_file(struct class_device *, | |||
| 238 | * @devt: for internal use by the driver core only. | 238 | * @devt: for internal use by the driver core only. |
| 239 | * @node: for internal use by the driver core only. | 239 | * @node: for internal use by the driver core only. |
| 240 | * @kobj: for internal use by the driver core only. | 240 | * @kobj: for internal use by the driver core only. |
| 241 | * @devt_attr: for internal use by the driver core only. | ||
| 242 | * @groups: optional additional groups to be created | 241 | * @groups: optional additional groups to be created |
| 243 | * @dev: if set, a symlink to the struct device is created in the sysfs | 242 | * @dev: if set, a symlink to the struct device is created in the sysfs |
| 244 | * directory for this struct class device. | 243 | * directory for this struct class device. |
| @@ -263,8 +262,6 @@ struct class_device { | |||
| 263 | struct kobject kobj; | 262 | struct kobject kobj; |
| 264 | struct class * class; /* required */ | 263 | struct class * class; /* required */ |
| 265 | dev_t devt; /* dev_t, creates the sysfs "dev" */ | 264 | dev_t devt; /* dev_t, creates the sysfs "dev" */ |
| 266 | struct class_device_attribute *devt_attr; | ||
| 267 | struct class_device_attribute uevent_attr; | ||
| 268 | struct device * dev; /* not necessary, but nice to have */ | 265 | struct device * dev; /* not necessary, but nice to have */ |
| 269 | void * class_data; /* class-specific data */ | 266 | void * class_data; /* class-specific data */ |
| 270 | struct class_device *parent; /* parent of this child device, if there is one */ | 267 | struct class_device *parent; /* parent of this child device, if there is one */ |
| @@ -419,8 +416,6 @@ struct device { | |||
| 419 | struct device_type *type; | 416 | struct device_type *type; |
| 420 | unsigned is_registered:1; | 417 | unsigned is_registered:1; |
| 421 | unsigned uevent_suppress:1; | 418 | unsigned uevent_suppress:1; |
| 422 | struct device_attribute uevent_attr; | ||
| 423 | struct device_attribute *devt_attr; | ||
| 424 | 419 | ||
| 425 | struct semaphore sem; /* semaphore to synchronize calls to | 420 | struct semaphore sem; /* semaphore to synchronize calls to |
| 426 | * its driver. | 421 | * its driver. |
diff --git a/include/linux/dmi.h b/include/linux/dmi.h index 904bf3d2d90b..b8ac7b01c45e 100644 --- a/include/linux/dmi.h +++ b/include/linux/dmi.h | |||
| @@ -12,9 +12,17 @@ enum dmi_field { | |||
| 12 | DMI_PRODUCT_NAME, | 12 | DMI_PRODUCT_NAME, |
| 13 | DMI_PRODUCT_VERSION, | 13 | DMI_PRODUCT_VERSION, |
| 14 | DMI_PRODUCT_SERIAL, | 14 | DMI_PRODUCT_SERIAL, |
| 15 | DMI_PRODUCT_UUID, | ||
| 15 | DMI_BOARD_VENDOR, | 16 | DMI_BOARD_VENDOR, |
| 16 | DMI_BOARD_NAME, | 17 | DMI_BOARD_NAME, |
| 17 | DMI_BOARD_VERSION, | 18 | DMI_BOARD_VERSION, |
| 19 | DMI_BOARD_SERIAL, | ||
| 20 | DMI_BOARD_ASSET_TAG, | ||
| 21 | DMI_CHASSIS_VENDOR, | ||
| 22 | DMI_CHASSIS_TYPE, | ||
| 23 | DMI_CHASSIS_VERSION, | ||
| 24 | DMI_CHASSIS_SERIAL, | ||
| 25 | DMI_CHASSIS_ASSET_TAG, | ||
| 18 | DMI_STRING_MAX, | 26 | DMI_STRING_MAX, |
| 19 | }; | 27 | }; |
| 20 | 28 | ||
diff --git a/include/linux/idr.h b/include/linux/idr.h index 826803449db7..915572fa030b 100644 --- a/include/linux/idr.h +++ b/include/linux/idr.h | |||
| @@ -83,4 +83,33 @@ void idr_remove(struct idr *idp, int id); | |||
| 83 | void idr_destroy(struct idr *idp); | 83 | void idr_destroy(struct idr *idp); |
| 84 | void idr_init(struct idr *idp); | 84 | void idr_init(struct idr *idp); |
| 85 | 85 | ||
| 86 | |||
| 87 | /* | ||
| 88 | * IDA - IDR based id allocator, use when translation from id to | ||
| 89 | * pointer isn't necessary. | ||
| 90 | */ | ||
| 91 | #define IDA_CHUNK_SIZE 128 /* 128 bytes per chunk */ | ||
| 92 | #define IDA_BITMAP_LONGS (128 / sizeof(long) - 1) | ||
| 93 | #define IDA_BITMAP_BITS (IDA_BITMAP_LONGS * sizeof(long) * 8) | ||
| 94 | |||
| 95 | struct ida_bitmap { | ||
| 96 | long nr_busy; | ||
| 97 | unsigned long bitmap[IDA_BITMAP_LONGS]; | ||
| 98 | }; | ||
| 99 | |||
| 100 | struct ida { | ||
| 101 | struct idr idr; | ||
| 102 | struct ida_bitmap *free_bitmap; | ||
| 103 | }; | ||
| 104 | |||
| 105 | #define IDA_INIT(name) { .idr = IDR_INIT(name), .free_bitmap = NULL, } | ||
| 106 | #define DEFINE_IDA(name) struct ida name = IDA_INIT(name) | ||
| 107 | |||
| 108 | int ida_pre_get(struct ida *ida, gfp_t gfp_mask); | ||
| 109 | int ida_get_new_above(struct ida *ida, int starting_id, int *p_id); | ||
| 110 | int ida_get_new(struct ida *ida, int *p_id); | ||
| 111 | void ida_remove(struct ida *ida, int id); | ||
| 112 | void ida_destroy(struct ida *ida); | ||
| 113 | void ida_init(struct ida *ida); | ||
| 114 | |||
| 86 | #endif /* __IDR_H__ */ | 115 | #endif /* __IDR_H__ */ |
diff --git a/include/linux/kobject.h b/include/linux/kobject.h index c288e41ba331..06cbf41d32d2 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h | |||
| @@ -55,7 +55,7 @@ struct kobject { | |||
| 55 | struct kobject * parent; | 55 | struct kobject * parent; |
| 56 | struct kset * kset; | 56 | struct kset * kset; |
| 57 | struct kobj_type * ktype; | 57 | struct kobj_type * ktype; |
| 58 | struct dentry * dentry; | 58 | struct sysfs_dirent * sd; |
| 59 | wait_queue_head_t poll; | 59 | wait_queue_head_t poll; |
| 60 | }; | 60 | }; |
| 61 | 61 | ||
| @@ -71,13 +71,14 @@ extern void kobject_init(struct kobject *); | |||
| 71 | extern void kobject_cleanup(struct kobject *); | 71 | extern void kobject_cleanup(struct kobject *); |
| 72 | 72 | ||
| 73 | extern int __must_check kobject_add(struct kobject *); | 73 | extern int __must_check kobject_add(struct kobject *); |
| 74 | extern int __must_check kobject_shadow_add(struct kobject *, struct dentry *); | 74 | extern int __must_check kobject_shadow_add(struct kobject *kobj, |
| 75 | struct sysfs_dirent *shadow_parent); | ||
| 75 | extern void kobject_del(struct kobject *); | 76 | extern void kobject_del(struct kobject *); |
| 76 | 77 | ||
| 77 | extern int __must_check kobject_rename(struct kobject *, const char *new_name); | 78 | extern int __must_check kobject_rename(struct kobject *, const char *new_name); |
| 78 | extern int __must_check kobject_shadow_rename(struct kobject *kobj, | 79 | extern int __must_check kobject_shadow_rename(struct kobject *kobj, |
| 79 | struct dentry *new_parent, | 80 | struct sysfs_dirent *new_parent, |
| 80 | const char *new_name); | 81 | const char *new_name); |
| 81 | extern int __must_check kobject_move(struct kobject *, struct kobject *); | 82 | extern int __must_check kobject_move(struct kobject *, struct kobject *); |
| 82 | 83 | ||
| 83 | extern int __must_check kobject_register(struct kobject *); | 84 | extern int __must_check kobject_register(struct kobject *); |
diff --git a/include/linux/pm.h b/include/linux/pm.h index b2c4fde4e994..273781c82e4d 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h | |||
| @@ -267,15 +267,10 @@ struct dev_pm_info { | |||
| 267 | unsigned can_wakeup:1; | 267 | unsigned can_wakeup:1; |
| 268 | #ifdef CONFIG_PM | 268 | #ifdef CONFIG_PM |
| 269 | unsigned should_wakeup:1; | 269 | unsigned should_wakeup:1; |
| 270 | pm_message_t prev_state; | ||
| 271 | void * saved_state; | ||
| 272 | struct device * pm_parent; | ||
| 273 | struct list_head entry; | 270 | struct list_head entry; |
| 274 | #endif | 271 | #endif |
| 275 | }; | 272 | }; |
| 276 | 273 | ||
| 277 | extern void device_pm_set_parent(struct device * dev, struct device * parent); | ||
| 278 | |||
| 279 | extern int device_power_down(pm_message_t state); | 274 | extern int device_power_down(pm_message_t state); |
| 280 | extern void device_power_up(void); | 275 | extern void device_power_up(void); |
| 281 | extern void device_resume(void); | 276 | extern void device_resume(void); |
diff --git a/include/linux/sysdev.h b/include/linux/sysdev.h index e699ab279c2c..e285746588d6 100644 --- a/include/linux/sysdev.h +++ b/include/linux/sysdev.h | |||
| @@ -101,8 +101,7 @@ struct sysdev_attribute { | |||
| 101 | 101 | ||
| 102 | #define _SYSDEV_ATTR(_name,_mode,_show,_store) \ | 102 | #define _SYSDEV_ATTR(_name,_mode,_show,_store) \ |
| 103 | { \ | 103 | { \ |
| 104 | .attr = { .name = __stringify(_name), .mode = _mode, \ | 104 | .attr = { .name = __stringify(_name), .mode = _mode }, \ |
| 105 | .owner = THIS_MODULE }, \ | ||
| 106 | .show = _show, \ | 105 | .show = _show, \ |
| 107 | .store = _store, \ | 106 | .store = _store, \ |
| 108 | } | 107 | } |
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 7d5d1ec95c2e..be8228e50a27 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h | |||
| @@ -19,10 +19,15 @@ struct kobject; | |||
| 19 | struct module; | 19 | struct module; |
| 20 | struct nameidata; | 20 | struct nameidata; |
| 21 | struct dentry; | 21 | struct dentry; |
| 22 | struct sysfs_dirent; | ||
| 22 | 23 | ||
| 24 | /* FIXME | ||
| 25 | * The *owner field is no longer used, but leave around | ||
| 26 | * until the tree gets cleaned up fully. | ||
| 27 | */ | ||
| 23 | struct attribute { | 28 | struct attribute { |
| 24 | const char * name; | 29 | const char * name; |
| 25 | struct module * owner; | 30 | struct module * owner; |
| 26 | mode_t mode; | 31 | mode_t mode; |
| 27 | }; | 32 | }; |
| 28 | 33 | ||
| @@ -39,14 +44,14 @@ struct attribute_group { | |||
| 39 | */ | 44 | */ |
| 40 | 45 | ||
| 41 | #define __ATTR(_name,_mode,_show,_store) { \ | 46 | #define __ATTR(_name,_mode,_show,_store) { \ |
| 42 | .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \ | 47 | .attr = {.name = __stringify(_name), .mode = _mode }, \ |
| 43 | .show = _show, \ | 48 | .show = _show, \ |
| 44 | .store = _store, \ | 49 | .store = _store, \ |
| 45 | } | 50 | } |
| 46 | 51 | ||
| 47 | #define __ATTR_RO(_name) { \ | 52 | #define __ATTR_RO(_name) { \ |
| 48 | .attr = { .name = __stringify(_name), .mode = 0444, .owner = THIS_MODULE }, \ | 53 | .attr = { .name = __stringify(_name), .mode = 0444 }, \ |
| 49 | .show = _name##_show, \ | 54 | .show = _name##_show, \ |
| 50 | } | 55 | } |
| 51 | 56 | ||
| 52 | #define __ATTR_NULL { .attr = { .name = NULL } } | 57 | #define __ATTR_NULL { .attr = { .name = NULL } } |
| @@ -59,8 +64,10 @@ struct bin_attribute { | |||
| 59 | struct attribute attr; | 64 | struct attribute attr; |
| 60 | size_t size; | 65 | size_t size; |
| 61 | void *private; | 66 | void *private; |
| 62 | ssize_t (*read)(struct kobject *, char *, loff_t, size_t); | 67 | ssize_t (*read)(struct kobject *, struct bin_attribute *, |
| 63 | ssize_t (*write)(struct kobject *, char *, loff_t, size_t); | 68 | char *, loff_t, size_t); |
| 69 | ssize_t (*write)(struct kobject *, struct bin_attribute *, | ||
| 70 | char *, loff_t, size_t); | ||
| 64 | int (*mmap)(struct kobject *, struct bin_attribute *attr, | 71 | int (*mmap)(struct kobject *, struct bin_attribute *attr, |
| 65 | struct vm_area_struct *vma); | 72 | struct vm_area_struct *vma); |
| 66 | }; | 73 | }; |
| @@ -70,12 +77,16 @@ struct sysfs_ops { | |||
| 70 | ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t); | 77 | ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t); |
| 71 | }; | 78 | }; |
| 72 | 79 | ||
| 80 | #define SYSFS_TYPE_MASK 0x00ff | ||
| 73 | #define SYSFS_ROOT 0x0001 | 81 | #define SYSFS_ROOT 0x0001 |
| 74 | #define SYSFS_DIR 0x0002 | 82 | #define SYSFS_DIR 0x0002 |
| 75 | #define SYSFS_KOBJ_ATTR 0x0004 | 83 | #define SYSFS_KOBJ_ATTR 0x0004 |
| 76 | #define SYSFS_KOBJ_BIN_ATTR 0x0008 | 84 | #define SYSFS_KOBJ_BIN_ATTR 0x0008 |
| 77 | #define SYSFS_KOBJ_LINK 0x0020 | 85 | #define SYSFS_KOBJ_LINK 0x0020 |
| 78 | #define SYSFS_NOT_PINNED (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR | SYSFS_KOBJ_LINK) | 86 | #define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK) |
| 87 | |||
| 88 | #define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK | ||
| 89 | #define SYSFS_FLAG_REMOVED 0x0100 | ||
| 79 | 90 | ||
| 80 | #ifdef CONFIG_SYSFS | 91 | #ifdef CONFIG_SYSFS |
| 81 | 92 | ||
| @@ -83,13 +94,14 @@ extern int sysfs_schedule_callback(struct kobject *kobj, | |||
| 83 | void (*func)(void *), void *data, struct module *owner); | 94 | void (*func)(void *), void *data, struct module *owner); |
| 84 | 95 | ||
| 85 | extern int __must_check | 96 | extern int __must_check |
| 86 | sysfs_create_dir(struct kobject *, struct dentry *); | 97 | sysfs_create_dir(struct kobject *kobj, struct sysfs_dirent *shadow_parent_sd); |
| 87 | 98 | ||
| 88 | extern void | 99 | extern void |
| 89 | sysfs_remove_dir(struct kobject *); | 100 | sysfs_remove_dir(struct kobject *); |
| 90 | 101 | ||
| 91 | extern int __must_check | 102 | extern int __must_check |
| 92 | sysfs_rename_dir(struct kobject *, struct dentry *, const char *new_name); | 103 | sysfs_rename_dir(struct kobject *kobj, struct sysfs_dirent *new_parent_sd, |
| 104 | const char *new_name); | ||
| 93 | 105 | ||
| 94 | extern int __must_check | 106 | extern int __must_check |
| 95 | sysfs_move_dir(struct kobject *, struct kobject *); | 107 | sysfs_move_dir(struct kobject *, struct kobject *); |
| @@ -129,8 +141,8 @@ void sysfs_notify(struct kobject * k, char *dir, char *attr); | |||
| 129 | 141 | ||
| 130 | extern int sysfs_make_shadowed_dir(struct kobject *kobj, | 142 | extern int sysfs_make_shadowed_dir(struct kobject *kobj, |
| 131 | void * (*follow_link)(struct dentry *, struct nameidata *)); | 143 | void * (*follow_link)(struct dentry *, struct nameidata *)); |
| 132 | extern struct dentry *sysfs_create_shadow_dir(struct kobject *kobj); | 144 | extern struct sysfs_dirent *sysfs_create_shadow_dir(struct kobject *kobj); |
| 133 | extern void sysfs_remove_shadow_dir(struct dentry *dir); | 145 | extern void sysfs_remove_shadow_dir(struct sysfs_dirent *shadow_sd); |
| 134 | 146 | ||
| 135 | extern int __must_check sysfs_init(void); | 147 | extern int __must_check sysfs_init(void); |
| 136 | 148 | ||
| @@ -142,7 +154,8 @@ static inline int sysfs_schedule_callback(struct kobject *kobj, | |||
| 142 | return -ENOSYS; | 154 | return -ENOSYS; |
| 143 | } | 155 | } |
| 144 | 156 | ||
| 145 | static inline int sysfs_create_dir(struct kobject * k, struct dentry *shadow) | 157 | static inline int sysfs_create_dir(struct kobject *kobj, |
| 158 | struct sysfs_dirent *shadow_parent_sd) | ||
| 146 | { | 159 | { |
| 147 | return 0; | 160 | return 0; |
| 148 | } | 161 | } |
| @@ -152,9 +165,9 @@ static inline void sysfs_remove_dir(struct kobject * k) | |||
| 152 | ; | 165 | ; |
| 153 | } | 166 | } |
| 154 | 167 | ||
| 155 | static inline int sysfs_rename_dir(struct kobject * k, | 168 | static inline int sysfs_rename_dir(struct kobject *kobj, |
| 156 | struct dentry *new_parent, | 169 | struct sysfs_dirent *new_parent_sd, |
| 157 | const char *new_name) | 170 | const char *new_name) |
| 158 | { | 171 | { |
| 159 | return 0; | 172 | return 0; |
| 160 | } | 173 | } |
diff --git a/kernel/module.c b/kernel/module.c index 9bd93de01f4a..015d60cfd90e 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -488,8 +488,7 @@ static void free_modinfo_##field(struct module *mod) \ | |||
| 488 | mod->field = NULL; \ | 488 | mod->field = NULL; \ |
| 489 | } \ | 489 | } \ |
| 490 | static struct module_attribute modinfo_##field = { \ | 490 | static struct module_attribute modinfo_##field = { \ |
| 491 | .attr = { .name = __stringify(field), .mode = 0444, \ | 491 | .attr = { .name = __stringify(field), .mode = 0444 }, \ |
| 492 | .owner = THIS_MODULE }, \ | ||
| 493 | .show = show_modinfo_##field, \ | 492 | .show = show_modinfo_##field, \ |
| 494 | .setup = setup_modinfo_##field, \ | 493 | .setup = setup_modinfo_##field, \ |
| 495 | .test = modinfo_##field##_exists, \ | 494 | .test = modinfo_##field##_exists, \ |
| @@ -793,7 +792,7 @@ static ssize_t show_refcnt(struct module_attribute *mattr, | |||
| 793 | } | 792 | } |
| 794 | 793 | ||
| 795 | static struct module_attribute refcnt = { | 794 | static struct module_attribute refcnt = { |
| 796 | .attr = { .name = "refcnt", .mode = 0444, .owner = THIS_MODULE }, | 795 | .attr = { .name = "refcnt", .mode = 0444 }, |
| 797 | .show = show_refcnt, | 796 | .show = show_refcnt, |
| 798 | }; | 797 | }; |
| 799 | 798 | ||
| @@ -851,7 +850,7 @@ static ssize_t show_initstate(struct module_attribute *mattr, | |||
| 851 | } | 850 | } |
| 852 | 851 | ||
| 853 | static struct module_attribute initstate = { | 852 | static struct module_attribute initstate = { |
| 854 | .attr = { .name = "initstate", .mode = 0444, .owner = THIS_MODULE }, | 853 | .attr = { .name = "initstate", .mode = 0444 }, |
| 855 | .show = show_initstate, | 854 | .show = show_initstate, |
| 856 | }; | 855 | }; |
| 857 | 856 | ||
| @@ -1032,7 +1031,6 @@ static void add_sect_attrs(struct module *mod, unsigned int nsect, | |||
| 1032 | sattr->mattr.show = module_sect_show; | 1031 | sattr->mattr.show = module_sect_show; |
| 1033 | sattr->mattr.store = NULL; | 1032 | sattr->mattr.store = NULL; |
| 1034 | sattr->mattr.attr.name = sattr->name; | 1033 | sattr->mattr.attr.name = sattr->name; |
| 1035 | sattr->mattr.attr.owner = mod; | ||
| 1036 | sattr->mattr.attr.mode = S_IRUGO; | 1034 | sattr->mattr.attr.mode = S_IRUGO; |
| 1037 | *(gattr++) = &(sattr++)->mattr.attr; | 1035 | *(gattr++) = &(sattr++)->mattr.attr; |
| 1038 | } | 1036 | } |
| @@ -1090,7 +1088,6 @@ int module_add_modinfo_attrs(struct module *mod) | |||
| 1090 | if (!attr->test || | 1088 | if (!attr->test || |
| 1091 | (attr->test && attr->test(mod))) { | 1089 | (attr->test && attr->test(mod))) { |
| 1092 | memcpy(temp_attr, attr, sizeof(*temp_attr)); | 1090 | memcpy(temp_attr, attr, sizeof(*temp_attr)); |
| 1093 | temp_attr->attr.owner = mod; | ||
| 1094 | error = sysfs_create_file(&mod->mkobj.kobj,&temp_attr->attr); | 1091 | error = sysfs_create_file(&mod->mkobj.kobj,&temp_attr->attr); |
| 1095 | ++temp_attr; | 1092 | ++temp_attr; |
| 1096 | } | 1093 | } |
diff --git a/kernel/params.c b/kernel/params.c index e61c46c97ce7..effbaaedd7f3 100644 --- a/kernel/params.c +++ b/kernel/params.c | |||
| @@ -491,7 +491,6 @@ param_sysfs_setup(struct module_kobject *mk, | |||
| 491 | pattr->mattr.show = param_attr_show; | 491 | pattr->mattr.show = param_attr_show; |
| 492 | pattr->mattr.store = param_attr_store; | 492 | pattr->mattr.store = param_attr_store; |
| 493 | pattr->mattr.attr.name = (char *)&kp->name[name_skip]; | 493 | pattr->mattr.attr.name = (char *)&kp->name[name_skip]; |
| 494 | pattr->mattr.attr.owner = mk->mod; | ||
| 495 | pattr->mattr.attr.mode = kp->perm; | 494 | pattr->mattr.attr.mode = kp->perm; |
| 496 | *(gattr++) = &(pattr++)->mattr.attr; | 495 | *(gattr++) = &(pattr++)->mattr.attr; |
| 497 | } | 496 | } |
| @@ -70,6 +70,26 @@ static void free_layer(struct idr *idp, struct idr_layer *p) | |||
| 70 | spin_unlock_irqrestore(&idp->lock, flags); | 70 | spin_unlock_irqrestore(&idp->lock, flags); |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | static void idr_mark_full(struct idr_layer **pa, int id) | ||
| 74 | { | ||
| 75 | struct idr_layer *p = pa[0]; | ||
| 76 | int l = 0; | ||
| 77 | |||
| 78 | __set_bit(id & IDR_MASK, &p->bitmap); | ||
| 79 | /* | ||
| 80 | * If this layer is full mark the bit in the layer above to | ||
| 81 | * show that this part of the radix tree is full. This may | ||
| 82 | * complete the layer above and require walking up the radix | ||
| 83 | * tree. | ||
| 84 | */ | ||
| 85 | while (p->bitmap == IDR_FULL) { | ||
| 86 | if (!(p = pa[++l])) | ||
| 87 | break; | ||
| 88 | id = id >> IDR_BITS; | ||
| 89 | __set_bit((id & IDR_MASK), &p->bitmap); | ||
| 90 | } | ||
| 91 | } | ||
| 92 | |||
| 73 | /** | 93 | /** |
| 74 | * idr_pre_get - reserver resources for idr allocation | 94 | * idr_pre_get - reserver resources for idr allocation |
| 75 | * @idp: idr handle | 95 | * @idp: idr handle |
| @@ -95,15 +115,15 @@ int idr_pre_get(struct idr *idp, gfp_t gfp_mask) | |||
| 95 | } | 115 | } |
| 96 | EXPORT_SYMBOL(idr_pre_get); | 116 | EXPORT_SYMBOL(idr_pre_get); |
| 97 | 117 | ||
| 98 | static int sub_alloc(struct idr *idp, void *ptr, int *starting_id) | 118 | static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa) |
| 99 | { | 119 | { |
| 100 | int n, m, sh; | 120 | int n, m, sh; |
| 101 | struct idr_layer *p, *new; | 121 | struct idr_layer *p, *new; |
| 102 | struct idr_layer *pa[MAX_LEVEL]; | 122 | int l, id, oid; |
| 103 | int l, id; | ||
| 104 | long bm; | 123 | long bm; |
| 105 | 124 | ||
| 106 | id = *starting_id; | 125 | id = *starting_id; |
| 126 | restart: | ||
| 107 | p = idp->top; | 127 | p = idp->top; |
| 108 | l = idp->layers; | 128 | l = idp->layers; |
| 109 | pa[l--] = NULL; | 129 | pa[l--] = NULL; |
| @@ -117,12 +137,23 @@ static int sub_alloc(struct idr *idp, void *ptr, int *starting_id) | |||
| 117 | if (m == IDR_SIZE) { | 137 | if (m == IDR_SIZE) { |
| 118 | /* no space available go back to previous layer. */ | 138 | /* no space available go back to previous layer. */ |
| 119 | l++; | 139 | l++; |
| 140 | oid = id; | ||
| 120 | id = (id | ((1 << (IDR_BITS * l)) - 1)) + 1; | 141 | id = (id | ((1 << (IDR_BITS * l)) - 1)) + 1; |
| 142 | |||
| 143 | /* if already at the top layer, we need to grow */ | ||
| 121 | if (!(p = pa[l])) { | 144 | if (!(p = pa[l])) { |
| 122 | *starting_id = id; | 145 | *starting_id = id; |
| 123 | return -2; | 146 | return -2; |
| 124 | } | 147 | } |
| 125 | continue; | 148 | |
| 149 | /* If we need to go up one layer, continue the | ||
| 150 | * loop; otherwise, restart from the top. | ||
| 151 | */ | ||
| 152 | sh = IDR_BITS * (l + 1); | ||
| 153 | if (oid >> sh == id >> sh) | ||
| 154 | continue; | ||
| 155 | else | ||
| 156 | goto restart; | ||
| 126 | } | 157 | } |
| 127 | if (m != n) { | 158 | if (m != n) { |
| 128 | sh = IDR_BITS*l; | 159 | sh = IDR_BITS*l; |
| @@ -144,30 +175,13 @@ static int sub_alloc(struct idr *idp, void *ptr, int *starting_id) | |||
| 144 | pa[l--] = p; | 175 | pa[l--] = p; |
| 145 | p = p->ary[m]; | 176 | p = p->ary[m]; |
| 146 | } | 177 | } |
| 147 | /* | 178 | |
| 148 | * We have reached the leaf node, plant the | 179 | pa[l] = p; |
| 149 | * users pointer and return the raw id. | 180 | return id; |
| 150 | */ | ||
| 151 | p->ary[m] = (struct idr_layer *)ptr; | ||
| 152 | __set_bit(m, &p->bitmap); | ||
| 153 | p->count++; | ||
| 154 | /* | ||
| 155 | * If this layer is full mark the bit in the layer above | ||
| 156 | * to show that this part of the radix tree is full. | ||
| 157 | * This may complete the layer above and require walking | ||
| 158 | * up the radix tree. | ||
| 159 | */ | ||
| 160 | n = id; | ||
| 161 | while (p->bitmap == IDR_FULL) { | ||
| 162 | if (!(p = pa[++l])) | ||
| 163 | break; | ||
| 164 | n = n >> IDR_BITS; | ||
| 165 | __set_bit((n & IDR_MASK), &p->bitmap); | ||
| 166 | } | ||
| 167 | return(id); | ||
| 168 | } | 181 | } |
| 169 | 182 | ||
| 170 | static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id) | 183 | static int idr_get_empty_slot(struct idr *idp, int starting_id, |
| 184 | struct idr_layer **pa) | ||
| 171 | { | 185 | { |
| 172 | struct idr_layer *p, *new; | 186 | struct idr_layer *p, *new; |
| 173 | int layers, v, id; | 187 | int layers, v, id; |
| @@ -213,12 +227,31 @@ build_up: | |||
| 213 | } | 227 | } |
| 214 | idp->top = p; | 228 | idp->top = p; |
| 215 | idp->layers = layers; | 229 | idp->layers = layers; |
| 216 | v = sub_alloc(idp, ptr, &id); | 230 | v = sub_alloc(idp, &id, pa); |
| 217 | if (v == -2) | 231 | if (v == -2) |
| 218 | goto build_up; | 232 | goto build_up; |
| 219 | return(v); | 233 | return(v); |
| 220 | } | 234 | } |
| 221 | 235 | ||
| 236 | static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id) | ||
| 237 | { | ||
| 238 | struct idr_layer *pa[MAX_LEVEL]; | ||
| 239 | int id; | ||
| 240 | |||
| 241 | id = idr_get_empty_slot(idp, starting_id, pa); | ||
| 242 | if (id >= 0) { | ||
| 243 | /* | ||
| 244 | * Successfully found an empty slot. Install the user | ||
| 245 | * pointer and mark the slot full. | ||
| 246 | */ | ||
| 247 | pa[0]->ary[id & IDR_MASK] = (struct idr_layer *)ptr; | ||
| 248 | pa[0]->count++; | ||
| 249 | idr_mark_full(pa, id); | ||
| 250 | } | ||
| 251 | |||
| 252 | return id; | ||
| 253 | } | ||
| 254 | |||
| 222 | /** | 255 | /** |
| 223 | * idr_get_new_above - allocate new idr entry above or equal to a start id | 256 | * idr_get_new_above - allocate new idr entry above or equal to a start id |
| 224 | * @idp: idr handle | 257 | * @idp: idr handle |
| @@ -473,3 +506,248 @@ void idr_init(struct idr *idp) | |||
| 473 | spin_lock_init(&idp->lock); | 506 | spin_lock_init(&idp->lock); |
| 474 | } | 507 | } |
| 475 | EXPORT_SYMBOL(idr_init); | 508 | EXPORT_SYMBOL(idr_init); |
| 509 | |||
| 510 | |||
| 511 | /* | ||
| 512 | * IDA - IDR based ID allocator | ||
| 513 | * | ||
| 514 | * this is id allocator without id -> pointer translation. Memory | ||
| 515 | * usage is much lower than full blown idr because each id only | ||
| 516 | * occupies a bit. ida uses a custom leaf node which contains | ||
| 517 | * IDA_BITMAP_BITS slots. | ||
| 518 | * | ||
| 519 | * 2007-04-25 written by Tejun Heo <htejun@gmail.com> | ||
| 520 | */ | ||
| 521 | |||
| 522 | static void free_bitmap(struct ida *ida, struct ida_bitmap *bitmap) | ||
| 523 | { | ||
| 524 | unsigned long flags; | ||
| 525 | |||
| 526 | if (!ida->free_bitmap) { | ||
| 527 | spin_lock_irqsave(&ida->idr.lock, flags); | ||
| 528 | if (!ida->free_bitmap) { | ||
| 529 | ida->free_bitmap = bitmap; | ||
| 530 | bitmap = NULL; | ||
| 531 | } | ||
| 532 | spin_unlock_irqrestore(&ida->idr.lock, flags); | ||
| 533 | } | ||
| 534 | |||
| 535 | kfree(bitmap); | ||
| 536 | } | ||
| 537 | |||
| 538 | /** | ||
| 539 | * ida_pre_get - reserve resources for ida allocation | ||
| 540 | * @ida: ida handle | ||
| 541 | * @gfp_mask: memory allocation flag | ||
| 542 | * | ||
| 543 | * This function should be called prior to locking and calling the | ||
| 544 | * following function. It preallocates enough memory to satisfy the | ||
| 545 | * worst possible allocation. | ||
| 546 | * | ||
| 547 | * If the system is REALLY out of memory this function returns 0, | ||
| 548 | * otherwise 1. | ||
| 549 | */ | ||
| 550 | int ida_pre_get(struct ida *ida, gfp_t gfp_mask) | ||
| 551 | { | ||
| 552 | /* allocate idr_layers */ | ||
| 553 | if (!idr_pre_get(&ida->idr, gfp_mask)) | ||
| 554 | return 0; | ||
| 555 | |||
| 556 | /* allocate free_bitmap */ | ||
| 557 | if (!ida->free_bitmap) { | ||
| 558 | struct ida_bitmap *bitmap; | ||
| 559 | |||
| 560 | bitmap = kmalloc(sizeof(struct ida_bitmap), gfp_mask); | ||
| 561 | if (!bitmap) | ||
| 562 | return 0; | ||
| 563 | |||
| 564 | free_bitmap(ida, bitmap); | ||
| 565 | } | ||
| 566 | |||
| 567 | return 1; | ||
| 568 | } | ||
| 569 | EXPORT_SYMBOL(ida_pre_get); | ||
| 570 | |||
| 571 | /** | ||
| 572 | * ida_get_new_above - allocate new ID above or equal to a start id | ||
| 573 | * @ida: ida handle | ||
| 574 | * @staring_id: id to start search at | ||
| 575 | * @p_id: pointer to the allocated handle | ||
| 576 | * | ||
| 577 | * Allocate new ID above or equal to @ida. It should be called with | ||
| 578 | * any required locks. | ||
| 579 | * | ||
| 580 | * If memory is required, it will return -EAGAIN, you should unlock | ||
| 581 | * and go back to the ida_pre_get() call. If the ida is full, it will | ||
| 582 | * return -ENOSPC. | ||
| 583 | * | ||
| 584 | * @p_id returns a value in the range 0 ... 0x7fffffff. | ||
| 585 | */ | ||
| 586 | int ida_get_new_above(struct ida *ida, int starting_id, int *p_id) | ||
| 587 | { | ||
| 588 | struct idr_layer *pa[MAX_LEVEL]; | ||
| 589 | struct ida_bitmap *bitmap; | ||
| 590 | unsigned long flags; | ||
| 591 | int idr_id = starting_id / IDA_BITMAP_BITS; | ||
| 592 | int offset = starting_id % IDA_BITMAP_BITS; | ||
| 593 | int t, id; | ||
| 594 | |||
| 595 | restart: | ||
| 596 | /* get vacant slot */ | ||
| 597 | t = idr_get_empty_slot(&ida->idr, idr_id, pa); | ||
| 598 | if (t < 0) { | ||
| 599 | if (t == -1) | ||
| 600 | return -EAGAIN; | ||
| 601 | else /* will be -3 */ | ||
| 602 | return -ENOSPC; | ||
| 603 | } | ||
| 604 | |||
| 605 | if (t * IDA_BITMAP_BITS >= MAX_ID_BIT) | ||
| 606 | return -ENOSPC; | ||
| 607 | |||
| 608 | if (t != idr_id) | ||
| 609 | offset = 0; | ||
| 610 | idr_id = t; | ||
| 611 | |||
| 612 | /* if bitmap isn't there, create a new one */ | ||
| 613 | bitmap = (void *)pa[0]->ary[idr_id & IDR_MASK]; | ||
| 614 | if (!bitmap) { | ||
| 615 | spin_lock_irqsave(&ida->idr.lock, flags); | ||
| 616 | bitmap = ida->free_bitmap; | ||
| 617 | ida->free_bitmap = NULL; | ||
| 618 | spin_unlock_irqrestore(&ida->idr.lock, flags); | ||
| 619 | |||
| 620 | if (!bitmap) | ||
| 621 | return -EAGAIN; | ||
| 622 | |||
| 623 | memset(bitmap, 0, sizeof(struct ida_bitmap)); | ||
| 624 | pa[0]->ary[idr_id & IDR_MASK] = (void *)bitmap; | ||
| 625 | pa[0]->count++; | ||
| 626 | } | ||
| 627 | |||
| 628 | /* lookup for empty slot */ | ||
| 629 | t = find_next_zero_bit(bitmap->bitmap, IDA_BITMAP_BITS, offset); | ||
| 630 | if (t == IDA_BITMAP_BITS) { | ||
| 631 | /* no empty slot after offset, continue to the next chunk */ | ||
| 632 | idr_id++; | ||
| 633 | offset = 0; | ||
| 634 | goto restart; | ||
| 635 | } | ||
| 636 | |||
| 637 | id = idr_id * IDA_BITMAP_BITS + t; | ||
| 638 | if (id >= MAX_ID_BIT) | ||
| 639 | return -ENOSPC; | ||
| 640 | |||
| 641 | __set_bit(t, bitmap->bitmap); | ||
| 642 | if (++bitmap->nr_busy == IDA_BITMAP_BITS) | ||
| 643 | idr_mark_full(pa, idr_id); | ||
| 644 | |||
| 645 | *p_id = id; | ||
| 646 | |||
| 647 | /* Each leaf node can handle nearly a thousand slots and the | ||
| 648 | * whole idea of ida is to have small memory foot print. | ||
| 649 | * Throw away extra resources one by one after each successful | ||
| 650 | * allocation. | ||
| 651 | */ | ||
| 652 | if (ida->idr.id_free_cnt || ida->free_bitmap) { | ||
| 653 | struct idr_layer *p = alloc_layer(&ida->idr); | ||
| 654 | if (p) | ||
| 655 | kmem_cache_free(idr_layer_cache, p); | ||
| 656 | } | ||
| 657 | |||
| 658 | return 0; | ||
| 659 | } | ||
| 660 | EXPORT_SYMBOL(ida_get_new_above); | ||
| 661 | |||
| 662 | /** | ||
| 663 | * ida_get_new - allocate new ID | ||
| 664 | * @ida: idr handle | ||
| 665 | * @p_id: pointer to the allocated handle | ||
| 666 | * | ||
| 667 | * Allocate new ID. It should be called with any required locks. | ||
| 668 | * | ||
| 669 | * If memory is required, it will return -EAGAIN, you should unlock | ||
| 670 | * and go back to the idr_pre_get() call. If the idr is full, it will | ||
| 671 | * return -ENOSPC. | ||
| 672 | * | ||
| 673 | * @id returns a value in the range 0 ... 0x7fffffff. | ||
| 674 | */ | ||
| 675 | int ida_get_new(struct ida *ida, int *p_id) | ||
| 676 | { | ||
| 677 | return ida_get_new_above(ida, 0, p_id); | ||
| 678 | } | ||
| 679 | EXPORT_SYMBOL(ida_get_new); | ||
| 680 | |||
| 681 | /** | ||
| 682 | * ida_remove - remove the given ID | ||
| 683 | * @ida: ida handle | ||
| 684 | * @id: ID to free | ||
| 685 | */ | ||
| 686 | void ida_remove(struct ida *ida, int id) | ||
| 687 | { | ||
| 688 | struct idr_layer *p = ida->idr.top; | ||
| 689 | int shift = (ida->idr.layers - 1) * IDR_BITS; | ||
| 690 | int idr_id = id / IDA_BITMAP_BITS; | ||
| 691 | int offset = id % IDA_BITMAP_BITS; | ||
| 692 | int n; | ||
| 693 | struct ida_bitmap *bitmap; | ||
| 694 | |||
| 695 | /* clear full bits while looking up the leaf idr_layer */ | ||
| 696 | while ((shift > 0) && p) { | ||
| 697 | n = (idr_id >> shift) & IDR_MASK; | ||
| 698 | __clear_bit(n, &p->bitmap); | ||
| 699 | p = p->ary[n]; | ||
| 700 | shift -= IDR_BITS; | ||
| 701 | } | ||
| 702 | |||
| 703 | if (p == NULL) | ||
| 704 | goto err; | ||
| 705 | |||
| 706 | n = idr_id & IDR_MASK; | ||
| 707 | __clear_bit(n, &p->bitmap); | ||
| 708 | |||
| 709 | bitmap = (void *)p->ary[n]; | ||
| 710 | if (!test_bit(offset, bitmap->bitmap)) | ||
| 711 | goto err; | ||
| 712 | |||
| 713 | /* update bitmap and remove it if empty */ | ||
| 714 | __clear_bit(offset, bitmap->bitmap); | ||
| 715 | if (--bitmap->nr_busy == 0) { | ||
| 716 | __set_bit(n, &p->bitmap); /* to please idr_remove() */ | ||
| 717 | idr_remove(&ida->idr, idr_id); | ||
| 718 | free_bitmap(ida, bitmap); | ||
| 719 | } | ||
| 720 | |||
| 721 | return; | ||
| 722 | |||
| 723 | err: | ||
| 724 | printk(KERN_WARNING | ||
| 725 | "ida_remove called for id=%d which is not allocated.\n", id); | ||
| 726 | } | ||
| 727 | EXPORT_SYMBOL(ida_remove); | ||
| 728 | |||
| 729 | /** | ||
| 730 | * ida_destroy - release all cached layers within an ida tree | ||
| 731 | * ida: ida handle | ||
| 732 | */ | ||
| 733 | void ida_destroy(struct ida *ida) | ||
| 734 | { | ||
| 735 | idr_destroy(&ida->idr); | ||
| 736 | kfree(ida->free_bitmap); | ||
| 737 | } | ||
| 738 | EXPORT_SYMBOL(ida_destroy); | ||
| 739 | |||
| 740 | /** | ||
| 741 | * ida_init - initialize ida handle | ||
| 742 | * @ida: ida handle | ||
| 743 | * | ||
| 744 | * This function is use to set up the handle (@ida) that you will pass | ||
| 745 | * to the rest of the functions. | ||
| 746 | */ | ||
| 747 | void ida_init(struct ida *ida) | ||
| 748 | { | ||
| 749 | memset(ida, 0, sizeof(struct ida)); | ||
| 750 | idr_init(&ida->idr); | ||
| 751 | |||
| 752 | } | ||
| 753 | EXPORT_SYMBOL(ida_init); | ||
diff --git a/lib/kobject.c b/lib/kobject.c index ac1520651b9b..4b08e0ff95c8 100644 --- a/lib/kobject.c +++ b/lib/kobject.c | |||
| @@ -44,7 +44,7 @@ static int populate_dir(struct kobject * kobj) | |||
| 44 | return error; | 44 | return error; |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | static int create_dir(struct kobject * kobj, struct dentry *shadow_parent) | 47 | static int create_dir(struct kobject *kobj, struct sysfs_dirent *shadow_parent) |
| 48 | { | 48 | { |
| 49 | int error = 0; | 49 | int error = 0; |
| 50 | if (kobject_name(kobj)) { | 50 | if (kobject_name(kobj)) { |
| @@ -162,7 +162,7 @@ static void unlink(struct kobject * kobj) | |||
| 162 | * @shadow_parent: sysfs directory to add to. | 162 | * @shadow_parent: sysfs directory to add to. |
| 163 | */ | 163 | */ |
| 164 | 164 | ||
| 165 | int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent) | 165 | int kobject_shadow_add(struct kobject *kobj, struct sysfs_dirent *shadow_parent) |
| 166 | { | 166 | { |
| 167 | int error = 0; | 167 | int error = 0; |
| 168 | struct kobject * parent; | 168 | struct kobject * parent; |
| @@ -338,7 +338,7 @@ int kobject_rename(struct kobject * kobj, const char *new_name) | |||
| 338 | /* Note : if we want to send the new name alone, not the full path, | 338 | /* Note : if we want to send the new name alone, not the full path, |
| 339 | * we could probably use kobject_name(kobj); */ | 339 | * we could probably use kobject_name(kobj); */ |
| 340 | 340 | ||
| 341 | error = sysfs_rename_dir(kobj, kobj->parent->dentry, new_name); | 341 | error = sysfs_rename_dir(kobj, kobj->parent->sd, new_name); |
| 342 | 342 | ||
| 343 | /* This function is mostly/only used for network interface. | 343 | /* This function is mostly/only used for network interface. |
| 344 | * Some hotplug package track interfaces by their name and | 344 | * Some hotplug package track interfaces by their name and |
| @@ -361,8 +361,8 @@ out: | |||
| 361 | * @new_name: object's new name | 361 | * @new_name: object's new name |
| 362 | */ | 362 | */ |
| 363 | 363 | ||
| 364 | int kobject_shadow_rename(struct kobject * kobj, struct dentry *new_parent, | 364 | int kobject_shadow_rename(struct kobject *kobj, |
| 365 | const char *new_name) | 365 | struct sysfs_dirent *new_parent, const char *new_name) |
| 366 | { | 366 | { |
| 367 | int error = 0; | 367 | int error = 0; |
| 368 | 368 | ||
| @@ -597,10 +597,17 @@ int kset_add(struct kset * k) | |||
| 597 | 597 | ||
| 598 | int kset_register(struct kset * k) | 598 | int kset_register(struct kset * k) |
| 599 | { | 599 | { |
| 600 | int err; | ||
| 601 | |||
| 600 | if (!k) | 602 | if (!k) |
| 601 | return -EINVAL; | 603 | return -EINVAL; |
| 604 | |||
| 602 | kset_init(k); | 605 | kset_init(k); |
| 603 | return kset_add(k); | 606 | err = kset_add(k); |
| 607 | if (err) | ||
| 608 | return err; | ||
| 609 | kobject_uevent(&k->kobj, KOBJ_ADD); | ||
| 610 | return 0; | ||
| 604 | } | 611 | } |
| 605 | 612 | ||
| 606 | 613 | ||
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index 33c6c4a7c689..4f42263e0a8a 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c | |||
| @@ -360,8 +360,9 @@ static struct attribute_group bridge_group = { | |||
| 360 | * | 360 | * |
| 361 | * Returns the number of bytes read. | 361 | * Returns the number of bytes read. |
| 362 | */ | 362 | */ |
| 363 | static ssize_t brforward_read(struct kobject *kobj, char *buf, | 363 | static ssize_t brforward_read(struct kobject *kobj, |
| 364 | loff_t off, size_t count) | 364 | struct bin_attribute *bin_attr, |
| 365 | char *buf, loff_t off, size_t count) | ||
| 365 | { | 366 | { |
| 366 | struct device *dev = to_dev(kobj); | 367 | struct device *dev = to_dev(kobj); |
| 367 | struct net_bridge *br = to_bridge(dev); | 368 | struct net_bridge *br = to_bridge(dev); |
| @@ -383,8 +384,7 @@ static ssize_t brforward_read(struct kobject *kobj, char *buf, | |||
| 383 | 384 | ||
| 384 | static struct bin_attribute bridge_forward = { | 385 | static struct bin_attribute bridge_forward = { |
| 385 | .attr = { .name = SYSFS_BRIDGE_FDB, | 386 | .attr = { .name = SYSFS_BRIDGE_FDB, |
| 386 | .mode = S_IRUGO, | 387 | .mode = S_IRUGO, }, |
| 387 | .owner = THIS_MODULE, }, | ||
| 388 | .read = brforward_read, | 388 | .read = brforward_read, |
| 389 | }; | 389 | }; |
| 390 | 390 | ||
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c index 2da22927d8dd..79db51fcb476 100644 --- a/net/bridge/br_sysfs_if.c +++ b/net/bridge/br_sysfs_if.c | |||
| @@ -29,8 +29,7 @@ struct brport_attribute { | |||
| 29 | #define BRPORT_ATTR(_name,_mode,_show,_store) \ | 29 | #define BRPORT_ATTR(_name,_mode,_show,_store) \ |
| 30 | struct brport_attribute brport_attr_##_name = { \ | 30 | struct brport_attribute brport_attr_##_name = { \ |
| 31 | .attr = {.name = __stringify(_name), \ | 31 | .attr = {.name = __stringify(_name), \ |
| 32 | .mode = _mode, \ | 32 | .mode = _mode }, \ |
| 33 | .owner = THIS_MODULE, }, \ | ||
| 34 | .show = _show, \ | 33 | .show = _show, \ |
| 35 | .store = _store, \ | 34 | .store = _store, \ |
| 36 | }; | 35 | }; |
