diff options
53 files changed, 1018 insertions, 461 deletions
diff --git a/arch/s390/include/asm/ccwgroup.h b/arch/s390/include/asm/ccwgroup.h index 23723ce5ca7a..6e670f88d125 100644 --- a/arch/s390/include/asm/ccwgroup.h +++ b/arch/s390/include/asm/ccwgroup.h | |||
| @@ -23,6 +23,7 @@ struct ccwgroup_device { | |||
| 23 | unsigned int count; | 23 | unsigned int count; |
| 24 | struct device dev; | 24 | struct device dev; |
| 25 | struct ccw_device *cdev[0]; | 25 | struct ccw_device *cdev[0]; |
| 26 | struct work_struct ungroup_work; | ||
| 26 | }; | 27 | }; |
| 27 | 28 | ||
| 28 | /** | 29 | /** |
diff --git a/arch/s390/pci/pci_sysfs.c b/arch/s390/pci/pci_sysfs.c index cf8a12ff733b..ab4a91393005 100644 --- a/arch/s390/pci/pci_sysfs.c +++ b/arch/s390/pci/pci_sysfs.c | |||
| @@ -48,29 +48,27 @@ static ssize_t show_pfgid(struct device *dev, struct device_attribute *attr, | |||
| 48 | } | 48 | } |
| 49 | static DEVICE_ATTR(pfgid, S_IRUGO, show_pfgid, NULL); | 49 | static DEVICE_ATTR(pfgid, S_IRUGO, show_pfgid, NULL); |
| 50 | 50 | ||
| 51 | static void recover_callback(struct device *dev) | 51 | static ssize_t store_recover(struct device *dev, struct device_attribute *attr, |
| 52 | const char *buf, size_t count) | ||
| 52 | { | 53 | { |
| 53 | struct pci_dev *pdev = to_pci_dev(dev); | 54 | struct pci_dev *pdev = to_pci_dev(dev); |
| 54 | struct zpci_dev *zdev = get_zdev(pdev); | 55 | struct zpci_dev *zdev = get_zdev(pdev); |
| 55 | int ret; | 56 | int ret; |
| 56 | 57 | ||
| 58 | if (!device_remove_file_self(dev, attr)) | ||
| 59 | return count; | ||
| 60 | |||
| 57 | pci_stop_and_remove_bus_device(pdev); | 61 | pci_stop_and_remove_bus_device(pdev); |
| 58 | ret = zpci_disable_device(zdev); | 62 | ret = zpci_disable_device(zdev); |
| 59 | if (ret) | 63 | if (ret) |
| 60 | return; | 64 | return ret; |
| 61 | 65 | ||
| 62 | ret = zpci_enable_device(zdev); | 66 | ret = zpci_enable_device(zdev); |
| 63 | if (ret) | 67 | if (ret) |
| 64 | return; | 68 | return ret; |
| 65 | 69 | ||
| 66 | pci_rescan_bus(zdev->bus); | 70 | pci_rescan_bus(zdev->bus); |
| 67 | } | 71 | return count; |
| 68 | |||
| 69 | static ssize_t store_recover(struct device *dev, struct device_attribute *attr, | ||
| 70 | const char *buf, size_t count) | ||
| 71 | { | ||
| 72 | int rc = device_schedule_callback(dev, recover_callback); | ||
| 73 | return rc ? rc : count; | ||
| 74 | } | 72 | } |
| 75 | static DEVICE_ATTR(recover, S_IWUSR, NULL, store_recover); | 73 | static DEVICE_ATTR(recover, S_IWUSR, NULL, store_recover); |
| 76 | 74 | ||
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 8453fe1342ea..26237934ac87 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
| @@ -127,6 +127,7 @@ config X86 | |||
| 127 | select HAVE_DEBUG_STACKOVERFLOW | 127 | select HAVE_DEBUG_STACKOVERFLOW |
| 128 | select HAVE_IRQ_EXIT_ON_IRQ_STACK if X86_64 | 128 | select HAVE_IRQ_EXIT_ON_IRQ_STACK if X86_64 |
| 129 | select HAVE_CC_STACKPROTECTOR | 129 | select HAVE_CC_STACKPROTECTOR |
| 130 | select GENERIC_CPU_AUTOPROBE | ||
| 130 | 131 | ||
| 131 | config INSTRUCTION_DECODER | 132 | config INSTRUCTION_DECODER |
| 132 | def_bool y | 133 | def_bool y |
| @@ -195,9 +196,6 @@ config ARCH_HAS_CPU_RELAX | |||
| 195 | config ARCH_HAS_CACHE_LINE_SIZE | 196 | config ARCH_HAS_CACHE_LINE_SIZE |
| 196 | def_bool y | 197 | def_bool y |
| 197 | 198 | ||
| 198 | config ARCH_HAS_CPU_AUTOPROBE | ||
| 199 | def_bool y | ||
| 200 | |||
| 201 | config HAVE_SETUP_PER_CPU_AREA | 199 | config HAVE_SETUP_PER_CPU_AREA |
| 202 | def_bool y | 200 | def_bool y |
| 203 | 201 | ||
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 63211ef5046a..e265ff95d16d 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h | |||
| @@ -546,6 +546,13 @@ static __always_inline __pure bool _static_cpu_has_safe(u16 bit) | |||
| 546 | #define static_cpu_has_bug(bit) static_cpu_has((bit)) | 546 | #define static_cpu_has_bug(bit) static_cpu_has((bit)) |
| 547 | #define boot_cpu_has_bug(bit) cpu_has_bug(&boot_cpu_data, (bit)) | 547 | #define boot_cpu_has_bug(bit) cpu_has_bug(&boot_cpu_data, (bit)) |
| 548 | 548 | ||
| 549 | #define MAX_CPU_FEATURES (NCAPINTS * 32) | ||
| 550 | #define cpu_have_feature boot_cpu_has | ||
| 551 | |||
| 552 | #define CPU_FEATURE_TYPEFMT "x86,ven%04Xfam%04Xmod%04X" | ||
| 553 | #define CPU_FEATURE_TYPEVAL boot_cpu_data.x86_vendor, boot_cpu_data.x86, \ | ||
| 554 | boot_cpu_data.x86_model | ||
| 555 | |||
| 549 | #endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */ | 556 | #endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */ |
| 550 | 557 | ||
| 551 | #endif /* _ASM_X86_CPUFEATURE_H */ | 558 | #endif /* _ASM_X86_CPUFEATURE_H */ |
diff --git a/arch/x86/kernel/cpu/match.c b/arch/x86/kernel/cpu/match.c index 36565373af87..afa9f0d487ea 100644 --- a/arch/x86/kernel/cpu/match.c +++ b/arch/x86/kernel/cpu/match.c | |||
| @@ -47,45 +47,3 @@ const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match) | |||
| 47 | return NULL; | 47 | return NULL; |
| 48 | } | 48 | } |
| 49 | EXPORT_SYMBOL(x86_match_cpu); | 49 | EXPORT_SYMBOL(x86_match_cpu); |
| 50 | |||
| 51 | ssize_t arch_print_cpu_modalias(struct device *dev, | ||
| 52 | struct device_attribute *attr, | ||
| 53 | char *bufptr) | ||
| 54 | { | ||
| 55 | int size = PAGE_SIZE; | ||
| 56 | int i, n; | ||
| 57 | char *buf = bufptr; | ||
| 58 | |||
| 59 | n = snprintf(buf, size, "x86cpu:vendor:%04X:family:%04X:" | ||
| 60 | "model:%04X:feature:", | ||
| 61 | boot_cpu_data.x86_vendor, | ||
| 62 | boot_cpu_data.x86, | ||
| 63 | boot_cpu_data.x86_model); | ||
| 64 | size -= n; | ||
| 65 | buf += n; | ||
| 66 | size -= 1; | ||
| 67 | for (i = 0; i < NCAPINTS*32; i++) { | ||
| 68 | if (boot_cpu_has(i)) { | ||
| 69 | n = snprintf(buf, size, ",%04X", i); | ||
| 70 | if (n >= size) { | ||
| 71 | WARN(1, "x86 features overflow page\n"); | ||
| 72 | break; | ||
| 73 | } | ||
| 74 | size -= n; | ||
| 75 | buf += n; | ||
| 76 | } | ||
| 77 | } | ||
| 78 | *buf++ = '\n'; | ||
| 79 | return buf - bufptr; | ||
| 80 | } | ||
| 81 | |||
| 82 | int arch_cpu_uevent(struct device *dev, struct kobj_uevent_env *env) | ||
| 83 | { | ||
| 84 | char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL); | ||
| 85 | if (buf) { | ||
| 86 | arch_print_cpu_modalias(NULL, NULL, buf); | ||
| 87 | add_uevent_var(env, "MODALIAS=%s", buf); | ||
| 88 | kfree(buf); | ||
| 89 | } | ||
| 90 | return 0; | ||
| 91 | } | ||
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index ec36e7772e57..8fa8deab6449 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig | |||
| @@ -185,6 +185,9 @@ config GENERIC_CPU_DEVICES | |||
| 185 | bool | 185 | bool |
| 186 | default n | 186 | default n |
| 187 | 187 | ||
| 188 | config GENERIC_CPU_AUTOPROBE | ||
| 189 | bool | ||
| 190 | |||
| 188 | config SOC_BUS | 191 | config SOC_BUS |
| 189 | bool | 192 | bool |
| 190 | 193 | ||
diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c index ecc1929d7f6a..b84ca8f13f9e 100644 --- a/drivers/base/attribute_container.c +++ b/drivers/base/attribute_container.c | |||
| @@ -12,7 +12,6 @@ | |||
| 12 | */ | 12 | */ |
| 13 | 13 | ||
| 14 | #include <linux/attribute_container.h> | 14 | #include <linux/attribute_container.h> |
| 15 | #include <linux/init.h> | ||
| 16 | #include <linux/device.h> | 15 | #include <linux/device.h> |
| 17 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
| 18 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
diff --git a/drivers/base/core.c b/drivers/base/core.c index 2b567177ef78..0dd65281cc65 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
| @@ -23,7 +23,6 @@ | |||
| 23 | #include <linux/genhd.h> | 23 | #include <linux/genhd.h> |
| 24 | #include <linux/kallsyms.h> | 24 | #include <linux/kallsyms.h> |
| 25 | #include <linux/mutex.h> | 25 | #include <linux/mutex.h> |
| 26 | #include <linux/async.h> | ||
| 27 | #include <linux/pm_runtime.h> | 26 | #include <linux/pm_runtime.h> |
| 28 | #include <linux/netdevice.h> | 27 | #include <linux/netdevice.h> |
| 29 | #include <linux/sysfs.h> | 28 | #include <linux/sysfs.h> |
| @@ -571,6 +570,23 @@ void device_remove_file(struct device *dev, | |||
| 571 | EXPORT_SYMBOL_GPL(device_remove_file); | 570 | EXPORT_SYMBOL_GPL(device_remove_file); |
| 572 | 571 | ||
| 573 | /** | 572 | /** |
| 573 | * device_remove_file_self - remove sysfs attribute file from its own method. | ||
| 574 | * @dev: device. | ||
| 575 | * @attr: device attribute descriptor. | ||
| 576 | * | ||
| 577 | * See kernfs_remove_self() for details. | ||
| 578 | */ | ||
| 579 | bool device_remove_file_self(struct device *dev, | ||
| 580 | const struct device_attribute *attr) | ||
| 581 | { | ||
| 582 | if (dev) | ||
| 583 | return sysfs_remove_file_self(&dev->kobj, &attr->attr); | ||
| 584 | else | ||
| 585 | return false; | ||
| 586 | } | ||
| 587 | EXPORT_SYMBOL_GPL(device_remove_file_self); | ||
| 588 | |||
| 589 | /** | ||
| 574 | * device_create_bin_file - create sysfs binary attribute file for device. | 590 | * device_create_bin_file - create sysfs binary attribute file for device. |
| 575 | * @dev: device. | 591 | * @dev: device. |
| 576 | * @attr: device binary attribute descriptor. | 592 | * @attr: device binary attribute descriptor. |
| @@ -2003,7 +2019,6 @@ void device_shutdown(void) | |||
| 2003 | spin_lock(&devices_kset->list_lock); | 2019 | spin_lock(&devices_kset->list_lock); |
| 2004 | } | 2020 | } |
| 2005 | spin_unlock(&devices_kset->list_lock); | 2021 | spin_unlock(&devices_kset->list_lock); |
| 2006 | async_synchronize_full(); | ||
| 2007 | } | 2022 | } |
| 2008 | 2023 | ||
| 2009 | /* | 2024 | /* |
| @@ -2058,7 +2073,6 @@ create_syslog_header(const struct device *dev, char *hdr, size_t hdrlen) | |||
| 2058 | 2073 | ||
| 2059 | return pos; | 2074 | return pos; |
| 2060 | } | 2075 | } |
| 2061 | EXPORT_SYMBOL(create_syslog_header); | ||
| 2062 | 2076 | ||
| 2063 | int dev_vprintk_emit(int level, const struct device *dev, | 2077 | int dev_vprintk_emit(int level, const struct device *dev, |
| 2064 | const char *fmt, va_list args) | 2078 | const char *fmt, va_list args) |
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index f48370dfc908..006b1bc5297d 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <linux/percpu.h> | 15 | #include <linux/percpu.h> |
| 16 | #include <linux/acpi.h> | 16 | #include <linux/acpi.h> |
| 17 | #include <linux/of.h> | 17 | #include <linux/of.h> |
| 18 | #include <linux/cpufeature.h> | ||
| 18 | 19 | ||
| 19 | #include "base.h" | 20 | #include "base.h" |
| 20 | 21 | ||
| @@ -286,6 +287,41 @@ static void cpu_device_release(struct device *dev) | |||
| 286 | */ | 287 | */ |
| 287 | } | 288 | } |
| 288 | 289 | ||
| 290 | #ifdef CONFIG_GENERIC_CPU_AUTOPROBE | ||
| 291 | static ssize_t print_cpu_modalias(struct device *dev, | ||
| 292 | struct device_attribute *attr, | ||
| 293 | char *buf) | ||
| 294 | { | ||
| 295 | ssize_t n; | ||
| 296 | u32 i; | ||
| 297 | |||
| 298 | n = sprintf(buf, "cpu:type:" CPU_FEATURE_TYPEFMT ":feature:", | ||
| 299 | CPU_FEATURE_TYPEVAL); | ||
| 300 | |||
| 301 | for (i = 0; i < MAX_CPU_FEATURES; i++) | ||
| 302 | if (cpu_have_feature(i)) { | ||
| 303 | if (PAGE_SIZE < n + sizeof(",XXXX\n")) { | ||
| 304 | WARN(1, "CPU features overflow page\n"); | ||
| 305 | break; | ||
| 306 | } | ||
| 307 | n += sprintf(&buf[n], ",%04X", i); | ||
| 308 | } | ||
| 309 | buf[n++] = '\n'; | ||
| 310 | return n; | ||
| 311 | } | ||
| 312 | |||
| 313 | static int cpu_uevent(struct device *dev, struct kobj_uevent_env *env) | ||
| 314 | { | ||
| 315 | char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL); | ||
| 316 | if (buf) { | ||
| 317 | print_cpu_modalias(NULL, NULL, buf); | ||
| 318 | add_uevent_var(env, "MODALIAS=%s", buf); | ||
| 319 | kfree(buf); | ||
| 320 | } | ||
| 321 | return 0; | ||
| 322 | } | ||
| 323 | #endif | ||
| 324 | |||
| 289 | /* | 325 | /* |
| 290 | * register_cpu - Setup a sysfs device for a CPU. | 326 | * register_cpu - Setup a sysfs device for a CPU. |
| 291 | * @cpu - cpu->hotpluggable field set to 1 will generate a control file in | 327 | * @cpu - cpu->hotpluggable field set to 1 will generate a control file in |
| @@ -306,8 +342,8 @@ int register_cpu(struct cpu *cpu, int num) | |||
| 306 | cpu->dev.offline_disabled = !cpu->hotpluggable; | 342 | cpu->dev.offline_disabled = !cpu->hotpluggable; |
| 307 | cpu->dev.offline = !cpu_online(num); | 343 | cpu->dev.offline = !cpu_online(num); |
| 308 | cpu->dev.of_node = of_get_cpu_node(num, NULL); | 344 | cpu->dev.of_node = of_get_cpu_node(num, NULL); |
| 309 | #ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE | 345 | #ifdef CONFIG_GENERIC_CPU_AUTOPROBE |
| 310 | cpu->dev.bus->uevent = arch_cpu_uevent; | 346 | cpu->dev.bus->uevent = cpu_uevent; |
| 311 | #endif | 347 | #endif |
| 312 | cpu->dev.groups = common_cpu_attr_groups; | 348 | cpu->dev.groups = common_cpu_attr_groups; |
| 313 | if (cpu->hotpluggable) | 349 | if (cpu->hotpluggable) |
| @@ -330,8 +366,8 @@ struct device *get_cpu_device(unsigned cpu) | |||
| 330 | } | 366 | } |
| 331 | EXPORT_SYMBOL_GPL(get_cpu_device); | 367 | EXPORT_SYMBOL_GPL(get_cpu_device); |
| 332 | 368 | ||
| 333 | #ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE | 369 | #ifdef CONFIG_GENERIC_CPU_AUTOPROBE |
| 334 | static DEVICE_ATTR(modalias, 0444, arch_print_cpu_modalias, NULL); | 370 | static DEVICE_ATTR(modalias, 0444, print_cpu_modalias, NULL); |
| 335 | #endif | 371 | #endif |
| 336 | 372 | ||
| 337 | static struct attribute *cpu_root_attrs[] = { | 373 | static struct attribute *cpu_root_attrs[] = { |
| @@ -344,7 +380,7 @@ static struct attribute *cpu_root_attrs[] = { | |||
| 344 | &cpu_attrs[2].attr.attr, | 380 | &cpu_attrs[2].attr.attr, |
| 345 | &dev_attr_kernel_max.attr, | 381 | &dev_attr_kernel_max.attr, |
| 346 | &dev_attr_offline.attr, | 382 | &dev_attr_offline.attr, |
| 347 | #ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE | 383 | #ifdef CONFIG_GENERIC_CPU_AUTOPROBE |
| 348 | &dev_attr_modalias.attr, | 384 | &dev_attr_modalias.attr, |
| 349 | #endif | 385 | #endif |
| 350 | NULL | 386 | NULL |
diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c index 61d6d62cc0d3..ea77701deda4 100644 --- a/drivers/base/dma-buf.c +++ b/drivers/base/dma-buf.c | |||
| @@ -251,9 +251,8 @@ EXPORT_SYMBOL_GPL(dma_buf_put); | |||
| 251 | * @dmabuf: [in] buffer to attach device to. | 251 | * @dmabuf: [in] buffer to attach device to. |
| 252 | * @dev: [in] device to be attached. | 252 | * @dev: [in] device to be attached. |
| 253 | * | 253 | * |
| 254 | * Returns struct dma_buf_attachment * for this attachment; may return negative | 254 | * Returns struct dma_buf_attachment * for this attachment; returns ERR_PTR on |
| 255 | * error codes. | 255 | * error. |
| 256 | * | ||
| 257 | */ | 256 | */ |
| 258 | struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, | 257 | struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, |
| 259 | struct device *dev) | 258 | struct device *dev) |
| @@ -319,9 +318,8 @@ EXPORT_SYMBOL_GPL(dma_buf_detach); | |||
| 319 | * @attach: [in] attachment whose scatterlist is to be returned | 318 | * @attach: [in] attachment whose scatterlist is to be returned |
| 320 | * @direction: [in] direction of DMA transfer | 319 | * @direction: [in] direction of DMA transfer |
| 321 | * | 320 | * |
| 322 | * Returns sg_table containing the scatterlist to be returned; may return NULL | 321 | * Returns sg_table containing the scatterlist to be returned; returns ERR_PTR |
| 323 | * or ERR_PTR. | 322 | * on error. |
| 324 | * | ||
| 325 | */ | 323 | */ |
| 326 | struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach, | 324 | struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach, |
| 327 | enum dma_data_direction direction) | 325 | enum dma_data_direction direction) |
| @@ -334,6 +332,8 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach, | |||
| 334 | return ERR_PTR(-EINVAL); | 332 | return ERR_PTR(-EINVAL); |
| 335 | 333 | ||
| 336 | sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction); | 334 | sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction); |
| 335 | if (!sg_table) | ||
| 336 | sg_table = ERR_PTR(-ENOMEM); | ||
| 337 | 337 | ||
| 338 | return sg_table; | 338 | return sg_table; |
| 339 | } | 339 | } |
| @@ -544,6 +544,8 @@ EXPORT_SYMBOL_GPL(dma_buf_mmap); | |||
| 544 | * These calls are optional in drivers. The intended use for them | 544 | * These calls are optional in drivers. The intended use for them |
| 545 | * is for mapping objects linear in kernel space for high use objects. | 545 | * is for mapping objects linear in kernel space for high use objects. |
| 546 | * Please attempt to use kmap/kunmap before thinking about these interfaces. | 546 | * Please attempt to use kmap/kunmap before thinking about these interfaces. |
| 547 | * | ||
| 548 | * Returns NULL on error. | ||
| 547 | */ | 549 | */ |
| 548 | void *dma_buf_vmap(struct dma_buf *dmabuf) | 550 | void *dma_buf_vmap(struct dma_buf *dmabuf) |
| 549 | { | 551 | { |
| @@ -566,7 +568,9 @@ void *dma_buf_vmap(struct dma_buf *dmabuf) | |||
| 566 | BUG_ON(dmabuf->vmap_ptr); | 568 | BUG_ON(dmabuf->vmap_ptr); |
| 567 | 569 | ||
| 568 | ptr = dmabuf->ops->vmap(dmabuf); | 570 | ptr = dmabuf->ops->vmap(dmabuf); |
| 569 | if (IS_ERR_OR_NULL(ptr)) | 571 | if (WARN_ON_ONCE(IS_ERR(ptr))) |
| 572 | ptr = NULL; | ||
| 573 | if (!ptr) | ||
| 570 | goto out_unlock; | 574 | goto out_unlock; |
| 571 | 575 | ||
| 572 | dmabuf->vmap_ptr = ptr; | 576 | dmabuf->vmap_ptr = ptr; |
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index c30df50e4440..d276e33880be 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
| @@ -649,7 +649,9 @@ static ssize_t firmware_loading_store(struct device *dev, | |||
| 649 | * see the mapped 'buf->data' once the loading | 649 | * see the mapped 'buf->data' once the loading |
| 650 | * is completed. | 650 | * is completed. |
| 651 | * */ | 651 | * */ |
| 652 | fw_map_pages_buf(fw_buf); | 652 | if (fw_map_pages_buf(fw_buf)) |
| 653 | dev_err(dev, "%s: map pages failed\n", | ||
| 654 | __func__); | ||
| 653 | list_del_init(&fw_buf->pending_list); | 655 | list_del_init(&fw_buf->pending_list); |
| 654 | complete_all(&fw_buf->completion); | 656 | complete_all(&fw_buf->completion); |
| 655 | break; | 657 | break; |
| @@ -900,7 +902,8 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, | |||
| 900 | dev_set_uevent_suppress(f_dev, false); | 902 | dev_set_uevent_suppress(f_dev, false); |
| 901 | dev_dbg(f_dev, "firmware: requesting %s\n", buf->fw_id); | 903 | dev_dbg(f_dev, "firmware: requesting %s\n", buf->fw_id); |
| 902 | if (timeout != MAX_SCHEDULE_TIMEOUT) | 904 | if (timeout != MAX_SCHEDULE_TIMEOUT) |
| 903 | schedule_delayed_work(&fw_priv->timeout_work, timeout); | 905 | queue_delayed_work(system_power_efficient_wq, |
| 906 | &fw_priv->timeout_work, timeout); | ||
| 904 | 907 | ||
| 905 | kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD); | 908 | kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD); |
| 906 | } | 909 | } |
| @@ -908,6 +911,8 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, | |||
| 908 | wait_for_completion(&buf->completion); | 911 | wait_for_completion(&buf->completion); |
| 909 | 912 | ||
| 910 | cancel_delayed_work_sync(&fw_priv->timeout_work); | 913 | cancel_delayed_work_sync(&fw_priv->timeout_work); |
| 914 | if (!buf->data) | ||
| 915 | retval = -ENOMEM; | ||
| 911 | 916 | ||
| 912 | device_remove_file(f_dev, &dev_attr_loading); | 917 | device_remove_file(f_dev, &dev_attr_loading); |
| 913 | err_del_bin_attr: | 918 | err_del_bin_attr: |
| @@ -1570,8 +1575,8 @@ static void device_uncache_fw_images_work(struct work_struct *work) | |||
| 1570 | */ | 1575 | */ |
| 1571 | static void device_uncache_fw_images_delay(unsigned long delay) | 1576 | static void device_uncache_fw_images_delay(unsigned long delay) |
| 1572 | { | 1577 | { |
| 1573 | schedule_delayed_work(&fw_cache.work, | 1578 | queue_delayed_work(system_power_efficient_wq, &fw_cache.work, |
| 1574 | msecs_to_jiffies(delay)); | 1579 | msecs_to_jiffies(delay)); |
| 1575 | } | 1580 | } |
| 1576 | 1581 | ||
| 1577 | static int fw_pm_notify(struct notifier_block *notify_block, | 1582 | static int fw_pm_notify(struct notifier_block *notify_block, |
diff --git a/drivers/base/node.c b/drivers/base/node.c index bc9f43bf7e29..8f7ed9933a7c 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c | |||
| @@ -599,7 +599,11 @@ int register_one_node(int nid) | |||
| 599 | 599 | ||
| 600 | void unregister_one_node(int nid) | 600 | void unregister_one_node(int nid) |
| 601 | { | 601 | { |
| 602 | if (!node_devices[nid]) | ||
| 603 | return; | ||
| 604 | |||
| 602 | unregister_node(node_devices[nid]); | 605 | unregister_node(node_devices[nid]); |
| 606 | kfree(node_devices[nid]); | ||
| 603 | node_devices[nid] = NULL; | 607 | node_devices[nid] = NULL; |
| 604 | } | 608 | } |
| 605 | 609 | ||
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index bc78848dd59a..e714709704e4 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
| @@ -481,11 +481,10 @@ static int platform_drv_probe(struct device *_dev) | |||
| 481 | struct platform_device *dev = to_platform_device(_dev); | 481 | struct platform_device *dev = to_platform_device(_dev); |
| 482 | int ret; | 482 | int ret; |
| 483 | 483 | ||
| 484 | if (ACPI_HANDLE(_dev)) | 484 | acpi_dev_pm_attach(_dev, true); |
| 485 | acpi_dev_pm_attach(_dev, true); | ||
| 486 | 485 | ||
| 487 | ret = drv->probe(dev); | 486 | ret = drv->probe(dev); |
| 488 | if (ret && ACPI_HANDLE(_dev)) | 487 | if (ret) |
| 489 | acpi_dev_pm_detach(_dev, true); | 488 | acpi_dev_pm_detach(_dev, true); |
| 490 | 489 | ||
| 491 | if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER) { | 490 | if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER) { |
| @@ -508,8 +507,7 @@ static int platform_drv_remove(struct device *_dev) | |||
| 508 | int ret; | 507 | int ret; |
| 509 | 508 | ||
| 510 | ret = drv->remove(dev); | 509 | ret = drv->remove(dev); |
| 511 | if (ACPI_HANDLE(_dev)) | 510 | acpi_dev_pm_detach(_dev, true); |
| 512 | acpi_dev_pm_detach(_dev, true); | ||
| 513 | 511 | ||
| 514 | return ret; | 512 | return ret; |
| 515 | } | 513 | } |
| @@ -520,8 +518,7 @@ static void platform_drv_shutdown(struct device *_dev) | |||
| 520 | struct platform_device *dev = to_platform_device(_dev); | 518 | struct platform_device *dev = to_platform_device(_dev); |
| 521 | 519 | ||
| 522 | drv->shutdown(dev); | 520 | drv->shutdown(dev); |
| 523 | if (ACPI_HANDLE(_dev)) | 521 | acpi_dev_pm_detach(_dev, true); |
| 524 | acpi_dev_pm_detach(_dev, true); | ||
| 525 | } | 522 | } |
| 526 | 523 | ||
| 527 | /** | 524 | /** |
diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c index e870bbe9ec4e..b99e6c06ee67 100644 --- a/drivers/base/power/clock_ops.c +++ b/drivers/base/power/clock_ops.c | |||
| @@ -6,7 +6,6 @@ | |||
| 6 | * This file is released under the GPLv2. | 6 | * This file is released under the GPLv2. |
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #include <linux/init.h> | ||
| 10 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
| 11 | #include <linux/device.h> | 10 | #include <linux/device.h> |
| 12 | #include <linux/io.h> | 11 | #include <linux/io.h> |
diff --git a/drivers/base/power/common.c b/drivers/base/power/common.c index 5da914041305..df2e5eeaeb05 100644 --- a/drivers/base/power/common.c +++ b/drivers/base/power/common.c | |||
| @@ -6,7 +6,6 @@ | |||
| 6 | * This file is released under the GPLv2. | 6 | * This file is released under the GPLv2. |
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #include <linux/init.h> | ||
| 10 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
| 11 | #include <linux/device.h> | 10 | #include <linux/device.h> |
| 12 | #include <linux/export.h> | 11 | #include <linux/export.h> |
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index dc127e5dec4b..6f54962aae1d 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c | |||
| @@ -6,7 +6,6 @@ | |||
| 6 | * This file is released under the GPLv2. | 6 | * This file is released under the GPLv2. |
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #include <linux/init.h> | ||
| 10 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
| 11 | #include <linux/io.h> | 10 | #include <linux/io.h> |
| 12 | #include <linux/pm_runtime.h> | 11 | #include <linux/pm_runtime.h> |
diff --git a/drivers/base/power/domain_governor.c b/drivers/base/power/domain_governor.c index 28dee3053f1f..a089e3bcdfbc 100644 --- a/drivers/base/power/domain_governor.c +++ b/drivers/base/power/domain_governor.c | |||
| @@ -6,7 +6,6 @@ | |||
| 6 | * This file is released under the GPLv2. | 6 | * This file is released under the GPLv2. |
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #include <linux/init.h> | ||
| 10 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
| 11 | #include <linux/pm_domain.h> | 10 | #include <linux/pm_domain.h> |
| 12 | #include <linux/pm_qos.h> | 11 | #include <linux/pm_qos.h> |
diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c index fa4187418440..25538675d59e 100644 --- a/drivers/base/power/opp.c +++ b/drivers/base/power/opp.c | |||
| @@ -14,7 +14,6 @@ | |||
| 14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
| 15 | #include <linux/errno.h> | 15 | #include <linux/errno.h> |
| 16 | #include <linux/err.h> | 16 | #include <linux/err.h> |
| 17 | #include <linux/init.h> | ||
| 18 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
| 19 | #include <linux/cpufreq.h> | 18 | #include <linux/cpufreq.h> |
| 20 | #include <linux/device.h> | 19 | #include <linux/device.h> |
diff --git a/drivers/base/regmap/regmap-i2c.c b/drivers/base/regmap/regmap-i2c.c index fa6bf5279d28..ebd189529760 100644 --- a/drivers/base/regmap/regmap-i2c.c +++ b/drivers/base/regmap/regmap-i2c.c | |||
| @@ -13,7 +13,6 @@ | |||
| 13 | #include <linux/regmap.h> | 13 | #include <linux/regmap.h> |
| 14 | #include <linux/i2c.h> | 14 | #include <linux/i2c.h> |
| 15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| 16 | #include <linux/init.h> | ||
| 17 | 16 | ||
| 18 | static int regmap_i2c_write(void *context, const void *data, size_t count) | 17 | static int regmap_i2c_write(void *context, const void *data, size_t count) |
| 19 | { | 18 | { |
diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c index de45a1e1548f..1e03e7f8bacb 100644 --- a/drivers/base/regmap/regmap-mmio.c +++ b/drivers/base/regmap/regmap-mmio.c | |||
| @@ -18,7 +18,6 @@ | |||
| 18 | 18 | ||
| 19 | #include <linux/clk.h> | 19 | #include <linux/clk.h> |
| 20 | #include <linux/err.h> | 20 | #include <linux/err.h> |
| 21 | #include <linux/init.h> | ||
| 22 | #include <linux/io.h> | 21 | #include <linux/io.h> |
| 23 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| 24 | #include <linux/regmap.h> | 23 | #include <linux/regmap.h> |
diff --git a/drivers/base/regmap/regmap-spi.c b/drivers/base/regmap/regmap-spi.c index 37f12ae7aada..0eb3097c0d76 100644 --- a/drivers/base/regmap/regmap-spi.c +++ b/drivers/base/regmap/regmap-spi.c | |||
| @@ -12,7 +12,6 @@ | |||
| 12 | 12 | ||
| 13 | #include <linux/regmap.h> | 13 | #include <linux/regmap.h> |
| 14 | #include <linux/spi/spi.h> | 14 | #include <linux/spi/spi.h> |
| 15 | #include <linux/init.h> | ||
| 16 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| 17 | 16 | ||
| 18 | #include "internal.h" | 17 | #include "internal.h" |
diff --git a/drivers/base/topology.c b/drivers/base/topology.c index 94ffee378f10..ad9d17762664 100644 --- a/drivers/base/topology.c +++ b/drivers/base/topology.c | |||
| @@ -23,7 +23,6 @@ | |||
| 23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 24 | * | 24 | * |
| 25 | */ | 25 | */ |
| 26 | #include <linux/init.h> | ||
| 27 | #include <linux/mm.h> | 26 | #include <linux/mm.h> |
| 28 | #include <linux/cpu.h> | 27 | #include <linux/cpu.h> |
| 29 | #include <linux/module.h> | 28 | #include <linux/module.h> |
diff --git a/drivers/firmware/google/gsmi.c b/drivers/firmware/google/gsmi.c index e5a67b24587a..f1ab05ea56bb 100644 --- a/drivers/firmware/google/gsmi.c +++ b/drivers/firmware/google/gsmi.c | |||
| @@ -892,13 +892,6 @@ static __init int gsmi_init(void) | |||
| 892 | goto out_remove_sysfs_files; | 892 | goto out_remove_sysfs_files; |
| 893 | } | 893 | } |
| 894 | 894 | ||
| 895 | ret = efivars_sysfs_init(); | ||
| 896 | if (ret) { | ||
| 897 | printk(KERN_INFO "gsmi: Failed to create efivars files\n"); | ||
| 898 | efivars_unregister(&efivars); | ||
| 899 | goto out_remove_sysfs_files; | ||
| 900 | } | ||
| 901 | |||
| 902 | register_reboot_notifier(&gsmi_reboot_notifier); | 895 | register_reboot_notifier(&gsmi_reboot_notifier); |
| 903 | register_die_notifier(&gsmi_die_notifier); | 896 | register_die_notifier(&gsmi_die_notifier); |
| 904 | atomic_notifier_chain_register(&panic_notifier_list, | 897 | atomic_notifier_chain_register(&panic_notifier_list, |
diff --git a/drivers/firmware/google/memconsole.c b/drivers/firmware/google/memconsole.c index 2a90ba613613..2f569aaed4c7 100644 --- a/drivers/firmware/google/memconsole.c +++ b/drivers/firmware/google/memconsole.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <linux/kobject.h> | 15 | #include <linux/kobject.h> |
| 16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| 17 | #include <linux/dmi.h> | 17 | #include <linux/dmi.h> |
| 18 | #include <linux/io.h> | ||
| 18 | #include <asm/bios_ebda.h> | 19 | #include <asm/bios_ebda.h> |
| 19 | 20 | ||
| 20 | #define BIOS_MEMCONSOLE_V1_MAGIC 0xDEADBABE | 21 | #define BIOS_MEMCONSOLE_V1_MAGIC 0xDEADBABE |
| @@ -41,15 +42,25 @@ struct biosmemcon_ebda { | |||
| 41 | }; | 42 | }; |
| 42 | } __packed; | 43 | } __packed; |
| 43 | 44 | ||
| 44 | static char *memconsole_baseaddr; | 45 | static u32 memconsole_baseaddr; |
| 45 | static size_t memconsole_length; | 46 | static size_t memconsole_length; |
| 46 | 47 | ||
| 47 | static ssize_t memconsole_read(struct file *filp, struct kobject *kobp, | 48 | static ssize_t memconsole_read(struct file *filp, struct kobject *kobp, |
| 48 | struct bin_attribute *bin_attr, char *buf, | 49 | struct bin_attribute *bin_attr, char *buf, |
| 49 | loff_t pos, size_t count) | 50 | loff_t pos, size_t count) |
| 50 | { | 51 | { |
| 51 | return memory_read_from_buffer(buf, count, &pos, memconsole_baseaddr, | 52 | char *memconsole; |
| 52 | memconsole_length); | 53 | ssize_t ret; |
| 54 | |||
| 55 | memconsole = ioremap_cache(memconsole_baseaddr, memconsole_length); | ||
| 56 | if (!memconsole) { | ||
| 57 | pr_err("memconsole: ioremap_cache failed\n"); | ||
| 58 | return -ENOMEM; | ||
| 59 | } | ||
| 60 | ret = memory_read_from_buffer(buf, count, &pos, memconsole, | ||
| 61 | memconsole_length); | ||
| 62 | iounmap(memconsole); | ||
| 63 | return ret; | ||
| 53 | } | 64 | } |
| 54 | 65 | ||
| 55 | static struct bin_attribute memconsole_bin_attr = { | 66 | static struct bin_attribute memconsole_bin_attr = { |
| @@ -58,43 +69,42 @@ static struct bin_attribute memconsole_bin_attr = { | |||
| 58 | }; | 69 | }; |
| 59 | 70 | ||
| 60 | 71 | ||
| 61 | static void found_v1_header(struct biosmemcon_ebda *hdr) | 72 | static void __init found_v1_header(struct biosmemcon_ebda *hdr) |
| 62 | { | 73 | { |
| 63 | printk(KERN_INFO "BIOS console v1 EBDA structure found at %p\n", hdr); | 74 | pr_info("BIOS console v1 EBDA structure found at %p\n", hdr); |
| 64 | printk(KERN_INFO "BIOS console buffer at 0x%.8x, " | 75 | pr_info("BIOS console buffer at 0x%.8x, " |
| 65 | "start = %d, end = %d, num = %d\n", | 76 | "start = %d, end = %d, num = %d\n", |
| 66 | hdr->v1.buffer_addr, hdr->v1.start, | 77 | hdr->v1.buffer_addr, hdr->v1.start, |
| 67 | hdr->v1.end, hdr->v1.num_chars); | 78 | hdr->v1.end, hdr->v1.num_chars); |
| 68 | 79 | ||
| 69 | memconsole_length = hdr->v1.num_chars; | 80 | memconsole_length = hdr->v1.num_chars; |
| 70 | memconsole_baseaddr = phys_to_virt(hdr->v1.buffer_addr); | 81 | memconsole_baseaddr = hdr->v1.buffer_addr; |
| 71 | } | 82 | } |
| 72 | 83 | ||
| 73 | static void found_v2_header(struct biosmemcon_ebda *hdr) | 84 | static void __init found_v2_header(struct biosmemcon_ebda *hdr) |
| 74 | { | 85 | { |
| 75 | printk(KERN_INFO "BIOS console v2 EBDA structure found at %p\n", hdr); | 86 | pr_info("BIOS console v2 EBDA structure found at %p\n", hdr); |
| 76 | printk(KERN_INFO "BIOS console buffer at 0x%.8x, " | 87 | pr_info("BIOS console buffer at 0x%.8x, " |
| 77 | "start = %d, end = %d, num_bytes = %d\n", | 88 | "start = %d, end = %d, num_bytes = %d\n", |
| 78 | hdr->v2.buffer_addr, hdr->v2.start, | 89 | hdr->v2.buffer_addr, hdr->v2.start, |
| 79 | hdr->v2.end, hdr->v2.num_bytes); | 90 | hdr->v2.end, hdr->v2.num_bytes); |
| 80 | 91 | ||
| 81 | memconsole_length = hdr->v2.end - hdr->v2.start; | 92 | memconsole_length = hdr->v2.end - hdr->v2.start; |
| 82 | memconsole_baseaddr = phys_to_virt(hdr->v2.buffer_addr | 93 | memconsole_baseaddr = hdr->v2.buffer_addr + hdr->v2.start; |
| 83 | + hdr->v2.start); | ||
| 84 | } | 94 | } |
| 85 | 95 | ||
| 86 | /* | 96 | /* |
| 87 | * Search through the EBDA for the BIOS Memory Console, and | 97 | * Search through the EBDA for the BIOS Memory Console, and |
| 88 | * set the global variables to point to it. Return true if found. | 98 | * set the global variables to point to it. Return true if found. |
| 89 | */ | 99 | */ |
| 90 | static bool found_memconsole(void) | 100 | static bool __init found_memconsole(void) |
| 91 | { | 101 | { |
| 92 | unsigned int address; | 102 | unsigned int address; |
| 93 | size_t length, cur; | 103 | size_t length, cur; |
| 94 | 104 | ||
| 95 | address = get_bios_ebda(); | 105 | address = get_bios_ebda(); |
| 96 | if (!address) { | 106 | if (!address) { |
| 97 | printk(KERN_INFO "BIOS EBDA non-existent.\n"); | 107 | pr_info("BIOS EBDA non-existent.\n"); |
| 98 | return false; | 108 | return false; |
| 99 | } | 109 | } |
| 100 | 110 | ||
| @@ -122,7 +132,7 @@ static bool found_memconsole(void) | |||
| 122 | } | 132 | } |
| 123 | } | 133 | } |
| 124 | 134 | ||
| 125 | printk(KERN_INFO "BIOS console EBDA structure not found!\n"); | 135 | pr_info("BIOS console EBDA structure not found!\n"); |
| 126 | return false; | 136 | return false; |
| 127 | } | 137 | } |
| 128 | 138 | ||
| @@ -139,8 +149,6 @@ MODULE_DEVICE_TABLE(dmi, memconsole_dmi_table); | |||
| 139 | 149 | ||
| 140 | static int __init memconsole_init(void) | 150 | static int __init memconsole_init(void) |
| 141 | { | 151 | { |
| 142 | int ret; | ||
| 143 | |||
| 144 | if (!dmi_check_system(memconsole_dmi_table)) | 152 | if (!dmi_check_system(memconsole_dmi_table)) |
| 145 | return -ENODEV; | 153 | return -ENODEV; |
| 146 | 154 | ||
| @@ -148,10 +156,7 @@ static int __init memconsole_init(void) | |||
| 148 | return -ENODEV; | 156 | return -ENODEV; |
| 149 | 157 | ||
| 150 | memconsole_bin_attr.size = memconsole_length; | 158 | memconsole_bin_attr.size = memconsole_length; |
| 151 | 159 | return sysfs_create_bin_file(firmware_kobj, &memconsole_bin_attr); | |
| 152 | ret = sysfs_create_bin_file(firmware_kobj, &memconsole_bin_attr); | ||
| 153 | |||
| 154 | return ret; | ||
| 155 | } | 160 | } |
| 156 | 161 | ||
| 157 | static void __exit memconsole_exit(void) | 162 | static void __exit memconsole_exit(void) |
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index 56805c39c906..bb516fdd195d 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c | |||
| @@ -471,7 +471,7 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev, | |||
| 471 | get_dma_buf(dma_buf); | 471 | get_dma_buf(dma_buf); |
| 472 | 472 | ||
| 473 | sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); | 473 | sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); |
| 474 | if (IS_ERR_OR_NULL(sgt)) { | 474 | if (IS_ERR(sgt)) { |
| 475 | ret = PTR_ERR(sgt); | 475 | ret = PTR_ERR(sgt); |
| 476 | goto fail_detach; | 476 | goto fail_detach; |
| 477 | } | 477 | } |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c index 59827cc5e770..c786cd4f457b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c | |||
| @@ -224,7 +224,7 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev, | |||
| 224 | get_dma_buf(dma_buf); | 224 | get_dma_buf(dma_buf); |
| 225 | 225 | ||
| 226 | sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); | 226 | sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); |
| 227 | if (IS_ERR_OR_NULL(sgt)) { | 227 | if (IS_ERR(sgt)) { |
| 228 | ret = PTR_ERR(sgt); | 228 | ret = PTR_ERR(sgt); |
| 229 | goto err_buf_detach; | 229 | goto err_buf_detach; |
| 230 | } | 230 | } |
diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c index 33d3871d1e13..880be0782dd9 100644 --- a/drivers/media/v4l2-core/videobuf2-dma-contig.c +++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c | |||
| @@ -719,7 +719,7 @@ static int vb2_dc_map_dmabuf(void *mem_priv) | |||
| 719 | 719 | ||
| 720 | /* get the associated scatterlist for this buffer */ | 720 | /* get the associated scatterlist for this buffer */ |
| 721 | sgt = dma_buf_map_attachment(buf->db_attach, buf->dma_dir); | 721 | sgt = dma_buf_map_attachment(buf->db_attach, buf->dma_dir); |
| 722 | if (IS_ERR_OR_NULL(sgt)) { | 722 | if (IS_ERR(sgt)) { |
| 723 | pr_err("Error getting dmabuf scatterlist\n"); | 723 | pr_err("Error getting dmabuf scatterlist\n"); |
| 724 | return -EINVAL; | 724 | return -EINVAL; |
| 725 | } | 725 | } |
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 276ef9c18802..4e0acefb7565 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c | |||
| @@ -351,28 +351,17 @@ static struct device_attribute dev_rescan_attr = __ATTR(rescan, | |||
| 351 | (S_IWUSR|S_IWGRP), | 351 | (S_IWUSR|S_IWGRP), |
| 352 | NULL, dev_rescan_store); | 352 | NULL, dev_rescan_store); |
| 353 | 353 | ||
| 354 | static void remove_callback(struct device *dev) | ||
| 355 | { | ||
| 356 | pci_stop_and_remove_bus_device_locked(to_pci_dev(dev)); | ||
| 357 | } | ||
| 358 | |||
| 359 | static ssize_t | 354 | static ssize_t |
| 360 | remove_store(struct device *dev, struct device_attribute *dummy, | 355 | remove_store(struct device *dev, struct device_attribute *attr, |
| 361 | const char *buf, size_t count) | 356 | const char *buf, size_t count) |
| 362 | { | 357 | { |
| 363 | int ret = 0; | ||
| 364 | unsigned long val; | 358 | unsigned long val; |
| 365 | 359 | ||
| 366 | if (kstrtoul(buf, 0, &val) < 0) | 360 | if (kstrtoul(buf, 0, &val) < 0) |
| 367 | return -EINVAL; | 361 | return -EINVAL; |
| 368 | 362 | ||
| 369 | /* An attribute cannot be unregistered by one of its own methods, | 363 | if (val && device_remove_file_self(dev, attr)) |
| 370 | * so we have to use this roundabout approach. | 364 | pci_stop_and_remove_bus_device_locked(to_pci_dev(dev)); |
| 371 | */ | ||
| 372 | if (val) | ||
| 373 | ret = device_schedule_callback(dev, remove_callback); | ||
| 374 | if (ret) | ||
| 375 | count = ret; | ||
| 376 | return count; | 365 | return count; |
| 377 | } | 366 | } |
| 378 | static struct device_attribute dev_remove_attr = __ATTR(remove, | 367 | static struct device_attribute dev_remove_attr = __ATTR(remove, |
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index ebf41e228e55..ee0e85abe1fd 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c | |||
| @@ -304,12 +304,6 @@ dcssblk_load_segment(char *name, struct segment_info **seg_info) | |||
| 304 | return rc; | 304 | return rc; |
| 305 | } | 305 | } |
| 306 | 306 | ||
| 307 | static void dcssblk_unregister_callback(struct device *dev) | ||
| 308 | { | ||
| 309 | device_unregister(dev); | ||
| 310 | put_device(dev); | ||
| 311 | } | ||
| 312 | |||
| 313 | /* | 307 | /* |
| 314 | * device attribute for switching shared/nonshared (exclusive) | 308 | * device attribute for switching shared/nonshared (exclusive) |
| 315 | * operation (show + store) | 309 | * operation (show + store) |
| @@ -397,7 +391,13 @@ removeseg: | |||
| 397 | blk_cleanup_queue(dev_info->dcssblk_queue); | 391 | blk_cleanup_queue(dev_info->dcssblk_queue); |
| 398 | dev_info->gd->queue = NULL; | 392 | dev_info->gd->queue = NULL; |
| 399 | put_disk(dev_info->gd); | 393 | put_disk(dev_info->gd); |
| 400 | rc = device_schedule_callback(dev, dcssblk_unregister_callback); | 394 | up_write(&dcssblk_devices_sem); |
| 395 | |||
| 396 | if (device_remove_file_self(dev, attr)) { | ||
| 397 | device_unregister(dev); | ||
| 398 | put_device(dev); | ||
| 399 | } | ||
| 400 | return rc; | ||
| 401 | out: | 401 | out: |
| 402 | up_write(&dcssblk_devices_sem); | 402 | up_write(&dcssblk_devices_sem); |
| 403 | return rc; | 403 | return rc; |
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index fd3367a1dc7a..dfd7bc681c25 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c | |||
| @@ -168,14 +168,12 @@ static ssize_t ccwgroup_online_show(struct device *dev, | |||
| 168 | * Provide an 'ungroup' attribute so the user can remove group devices no | 168 | * Provide an 'ungroup' attribute so the user can remove group devices no |
| 169 | * longer needed or accidentially created. Saves memory :) | 169 | * longer needed or accidentially created. Saves memory :) |
| 170 | */ | 170 | */ |
| 171 | static void ccwgroup_ungroup_callback(struct device *dev) | 171 | static void ccwgroup_ungroup(struct ccwgroup_device *gdev) |
| 172 | { | 172 | { |
| 173 | struct ccwgroup_device *gdev = to_ccwgroupdev(dev); | ||
| 174 | |||
| 175 | mutex_lock(&gdev->reg_mutex); | 173 | mutex_lock(&gdev->reg_mutex); |
| 176 | if (device_is_registered(&gdev->dev)) { | 174 | if (device_is_registered(&gdev->dev)) { |
| 177 | __ccwgroup_remove_symlinks(gdev); | 175 | __ccwgroup_remove_symlinks(gdev); |
| 178 | device_unregister(dev); | 176 | device_unregister(&gdev->dev); |
| 179 | __ccwgroup_remove_cdev_refs(gdev); | 177 | __ccwgroup_remove_cdev_refs(gdev); |
| 180 | } | 178 | } |
| 181 | mutex_unlock(&gdev->reg_mutex); | 179 | mutex_unlock(&gdev->reg_mutex); |
| @@ -195,10 +193,9 @@ static ssize_t ccwgroup_ungroup_store(struct device *dev, | |||
| 195 | rc = -EINVAL; | 193 | rc = -EINVAL; |
| 196 | goto out; | 194 | goto out; |
| 197 | } | 195 | } |
| 198 | /* Note that we cannot unregister the device from one of its | 196 | |
| 199 | * attribute methods, so we have to use this roundabout approach. | 197 | if (device_remove_file_self(dev, attr)) |
| 200 | */ | 198 | ccwgroup_ungroup(gdev); |
| 201 | rc = device_schedule_callback(dev, ccwgroup_ungroup_callback); | ||
| 202 | out: | 199 | out: |
| 203 | if (rc) { | 200 | if (rc) { |
| 204 | if (rc != -EAGAIN) | 201 | if (rc != -EAGAIN) |
| @@ -224,6 +221,14 @@ static const struct attribute_group *ccwgroup_attr_groups[] = { | |||
| 224 | NULL, | 221 | NULL, |
| 225 | }; | 222 | }; |
| 226 | 223 | ||
| 224 | static void ccwgroup_ungroup_workfn(struct work_struct *work) | ||
| 225 | { | ||
| 226 | struct ccwgroup_device *gdev = | ||
| 227 | container_of(work, struct ccwgroup_device, ungroup_work); | ||
| 228 | |||
| 229 | ccwgroup_ungroup(gdev); | ||
| 230 | } | ||
| 231 | |||
| 227 | static void ccwgroup_release(struct device *dev) | 232 | static void ccwgroup_release(struct device *dev) |
| 228 | { | 233 | { |
| 229 | kfree(to_ccwgroupdev(dev)); | 234 | kfree(to_ccwgroupdev(dev)); |
| @@ -323,6 +328,7 @@ int ccwgroup_create_dev(struct device *parent, struct ccwgroup_driver *gdrv, | |||
| 323 | atomic_set(&gdev->onoff, 0); | 328 | atomic_set(&gdev->onoff, 0); |
| 324 | mutex_init(&gdev->reg_mutex); | 329 | mutex_init(&gdev->reg_mutex); |
| 325 | mutex_lock(&gdev->reg_mutex); | 330 | mutex_lock(&gdev->reg_mutex); |
| 331 | INIT_WORK(&gdev->ungroup_work, ccwgroup_ungroup_workfn); | ||
| 326 | gdev->count = num_devices; | 332 | gdev->count = num_devices; |
| 327 | gdev->dev.bus = &ccwgroup_bus_type; | 333 | gdev->dev.bus = &ccwgroup_bus_type; |
| 328 | gdev->dev.parent = parent; | 334 | gdev->dev.parent = parent; |
| @@ -404,10 +410,10 @@ EXPORT_SYMBOL(ccwgroup_create_dev); | |||
| 404 | static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action, | 410 | static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action, |
| 405 | void *data) | 411 | void *data) |
| 406 | { | 412 | { |
| 407 | struct device *dev = data; | 413 | struct ccwgroup_device *gdev = to_ccwgroupdev(data); |
| 408 | 414 | ||
| 409 | if (action == BUS_NOTIFY_UNBIND_DRIVER) | 415 | if (action == BUS_NOTIFY_UNBIND_DRIVER) |
| 410 | device_schedule_callback(dev, ccwgroup_ungroup_callback); | 416 | schedule_work(&gdev->ungroup_work); |
| 411 | 417 | ||
| 412 | return NOTIFY_OK; | 418 | return NOTIFY_OK; |
| 413 | } | 419 | } |
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 9117d0bf408e..8ead24c3453a 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c | |||
| @@ -649,23 +649,12 @@ store_rescan_field (struct device *dev, struct device_attribute *attr, | |||
| 649 | } | 649 | } |
| 650 | static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field); | 650 | static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field); |
| 651 | 651 | ||
| 652 | static void sdev_store_delete_callback(struct device *dev) | ||
| 653 | { | ||
| 654 | scsi_remove_device(to_scsi_device(dev)); | ||
| 655 | } | ||
| 656 | |||
| 657 | static ssize_t | 652 | static ssize_t |
| 658 | sdev_store_delete(struct device *dev, struct device_attribute *attr, | 653 | sdev_store_delete(struct device *dev, struct device_attribute *attr, |
| 659 | const char *buf, size_t count) | 654 | const char *buf, size_t count) |
| 660 | { | 655 | { |
| 661 | int rc; | 656 | if (device_remove_file_self(dev, attr)) |
| 662 | 657 | scsi_remove_device(to_scsi_device(dev)); | |
| 663 | /* An attribute cannot be unregistered by one of its own methods, | ||
| 664 | * so we have to use this roundabout approach. | ||
| 665 | */ | ||
| 666 | rc = device_schedule_callback(dev, sdev_store_delete_callback); | ||
| 667 | if (rc) | ||
| 668 | count = rc; | ||
| 669 | return count; | 658 | return count; |
| 670 | }; | 659 | }; |
| 671 | static DEVICE_ATTR(delete, S_IWUSR, NULL, sdev_store_delete); | 660 | static DEVICE_ATTR(delete, S_IWUSR, NULL, sdev_store_delete); |
diff --git a/fs/Kconfig b/fs/Kconfig index 7385e54be4b9..312393f32948 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
| @@ -96,6 +96,7 @@ endif # BLOCK | |||
| 96 | menu "Pseudo filesystems" | 96 | menu "Pseudo filesystems" |
| 97 | 97 | ||
| 98 | source "fs/proc/Kconfig" | 98 | source "fs/proc/Kconfig" |
| 99 | source "fs/kernfs/Kconfig" | ||
| 99 | source "fs/sysfs/Kconfig" | 100 | source "fs/sysfs/Kconfig" |
| 100 | 101 | ||
| 101 | config TMPFS | 102 | config TMPFS |
diff --git a/fs/Makefile b/fs/Makefile index 47ac07bb4acc..f9cb9876e466 100644 --- a/fs/Makefile +++ b/fs/Makefile | |||
| @@ -52,7 +52,8 @@ obj-$(CONFIG_FHANDLE) += fhandle.o | |||
| 52 | obj-y += quota/ | 52 | obj-y += quota/ |
| 53 | 53 | ||
| 54 | obj-$(CONFIG_PROC_FS) += proc/ | 54 | obj-$(CONFIG_PROC_FS) += proc/ |
| 55 | obj-$(CONFIG_SYSFS) += sysfs/ kernfs/ | 55 | obj-$(CONFIG_KERNFS) += kernfs/ |
| 56 | obj-$(CONFIG_SYSFS) += sysfs/ | ||
| 56 | obj-$(CONFIG_CONFIGFS_FS) += configfs/ | 57 | obj-$(CONFIG_CONFIGFS_FS) += configfs/ |
| 57 | obj-y += devpts/ | 58 | obj-y += devpts/ |
| 58 | 59 | ||
diff --git a/fs/kernfs/Kconfig b/fs/kernfs/Kconfig new file mode 100644 index 000000000000..397b5f7a7a16 --- /dev/null +++ b/fs/kernfs/Kconfig | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | # | ||
| 2 | # KERNFS should be selected by its users | ||
| 3 | # | ||
| 4 | |||
| 5 | config KERNFS | ||
| 6 | bool | ||
| 7 | default n | ||
diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c index bd6e18be6e1a..0bd05ab26003 100644 --- a/fs/kernfs/dir.c +++ b/fs/kernfs/dir.c | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | * This file is released under the GPLv2. | 8 | * This file is released under the GPLv2. |
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | #include <linux/sched.h> | ||
| 11 | #include <linux/fs.h> | 12 | #include <linux/fs.h> |
| 12 | #include <linux/namei.h> | 13 | #include <linux/namei.h> |
| 13 | #include <linux/idr.h> | 14 | #include <linux/idr.h> |
| @@ -18,9 +19,161 @@ | |||
| 18 | #include "kernfs-internal.h" | 19 | #include "kernfs-internal.h" |
| 19 | 20 | ||
| 20 | DEFINE_MUTEX(kernfs_mutex); | 21 | DEFINE_MUTEX(kernfs_mutex); |
| 22 | static DEFINE_SPINLOCK(kernfs_rename_lock); /* kn->parent and ->name */ | ||
| 23 | static char kernfs_pr_cont_buf[PATH_MAX]; /* protected by rename_lock */ | ||
| 21 | 24 | ||
| 22 | #define rb_to_kn(X) rb_entry((X), struct kernfs_node, rb) | 25 | #define rb_to_kn(X) rb_entry((X), struct kernfs_node, rb) |
| 23 | 26 | ||
| 27 | static bool kernfs_active(struct kernfs_node *kn) | ||
| 28 | { | ||
| 29 | lockdep_assert_held(&kernfs_mutex); | ||
| 30 | return atomic_read(&kn->active) >= 0; | ||
| 31 | } | ||
| 32 | |||
| 33 | static bool kernfs_lockdep(struct kernfs_node *kn) | ||
| 34 | { | ||
| 35 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
| 36 | return kn->flags & KERNFS_LOCKDEP; | ||
| 37 | #else | ||
| 38 | return false; | ||
| 39 | #endif | ||
| 40 | } | ||
| 41 | |||
| 42 | static int kernfs_name_locked(struct kernfs_node *kn, char *buf, size_t buflen) | ||
| 43 | { | ||
| 44 | return strlcpy(buf, kn->parent ? kn->name : "/", buflen); | ||
| 45 | } | ||
| 46 | |||
| 47 | static char * __must_check kernfs_path_locked(struct kernfs_node *kn, char *buf, | ||
| 48 | size_t buflen) | ||
| 49 | { | ||
| 50 | char *p = buf + buflen; | ||
| 51 | int len; | ||
| 52 | |||
| 53 | *--p = '\0'; | ||
| 54 | |||
| 55 | do { | ||
| 56 | len = strlen(kn->name); | ||
| 57 | if (p - buf < len + 1) { | ||
| 58 | buf[0] = '\0'; | ||
| 59 | p = NULL; | ||
| 60 | break; | ||
| 61 | } | ||
| 62 | p -= len; | ||
| 63 | memcpy(p, kn->name, len); | ||
| 64 | *--p = '/'; | ||
| 65 | kn = kn->parent; | ||
| 66 | } while (kn && kn->parent); | ||
| 67 | |||
| 68 | return p; | ||
| 69 | } | ||
| 70 | |||
| 71 | /** | ||
| 72 | * kernfs_name - obtain the name of a given node | ||
| 73 | * @kn: kernfs_node of interest | ||
| 74 | * @buf: buffer to copy @kn's name into | ||
| 75 | * @buflen: size of @buf | ||
| 76 | * | ||
| 77 | * Copies the name of @kn into @buf of @buflen bytes. The behavior is | ||
| 78 | * similar to strlcpy(). It returns the length of @kn's name and if @buf | ||
| 79 | * isn't long enough, it's filled upto @buflen-1 and nul terminated. | ||
| 80 | * | ||
| 81 | * This function can be called from any context. | ||
| 82 | */ | ||
| 83 | int kernfs_name(struct kernfs_node *kn, char *buf, size_t buflen) | ||
| 84 | { | ||
| 85 | unsigned long flags; | ||
| 86 | int ret; | ||
| 87 | |||
| 88 | spin_lock_irqsave(&kernfs_rename_lock, flags); | ||
| 89 | ret = kernfs_name_locked(kn, buf, buflen); | ||
| 90 | spin_unlock_irqrestore(&kernfs_rename_lock, flags); | ||
| 91 | return ret; | ||
| 92 | } | ||
| 93 | |||
| 94 | /** | ||
| 95 | * kernfs_path - build full path of a given node | ||
| 96 | * @kn: kernfs_node of interest | ||
| 97 | * @buf: buffer to copy @kn's name into | ||
| 98 | * @buflen: size of @buf | ||
| 99 | * | ||
| 100 | * Builds and returns the full path of @kn in @buf of @buflen bytes. The | ||
| 101 | * path is built from the end of @buf so the returned pointer usually | ||
| 102 | * doesn't match @buf. If @buf isn't long enough, @buf is nul terminated | ||
| 103 | * and %NULL is returned. | ||
| 104 | */ | ||
| 105 | char *kernfs_path(struct kernfs_node *kn, char *buf, size_t buflen) | ||
| 106 | { | ||
| 107 | unsigned long flags; | ||
| 108 | char *p; | ||
| 109 | |||
| 110 | spin_lock_irqsave(&kernfs_rename_lock, flags); | ||
| 111 | p = kernfs_path_locked(kn, buf, buflen); | ||
| 112 | spin_unlock_irqrestore(&kernfs_rename_lock, flags); | ||
| 113 | return p; | ||
| 114 | } | ||
| 115 | |||
| 116 | /** | ||
| 117 | * pr_cont_kernfs_name - pr_cont name of a kernfs_node | ||
| 118 | * @kn: kernfs_node of interest | ||
| 119 | * | ||
| 120 | * This function can be called from any context. | ||
| 121 | */ | ||
| 122 | void pr_cont_kernfs_name(struct kernfs_node *kn) | ||
| 123 | { | ||
| 124 | unsigned long flags; | ||
| 125 | |||
| 126 | spin_lock_irqsave(&kernfs_rename_lock, flags); | ||
| 127 | |||
| 128 | kernfs_name_locked(kn, kernfs_pr_cont_buf, sizeof(kernfs_pr_cont_buf)); | ||
| 129 | pr_cont("%s", kernfs_pr_cont_buf); | ||
| 130 | |||
| 131 | spin_unlock_irqrestore(&kernfs_rename_lock, flags); | ||
| 132 | } | ||
| 133 | |||
| 134 | /** | ||
| 135 | * pr_cont_kernfs_path - pr_cont path of a kernfs_node | ||
| 136 | * @kn: kernfs_node of interest | ||
| 137 | * | ||
| 138 | * This function can be called from any context. | ||
| 139 | */ | ||
| 140 | void pr_cont_kernfs_path(struct kernfs_node *kn) | ||
| 141 | { | ||
| 142 | unsigned long flags; | ||
| 143 | char *p; | ||
| 144 | |||
| 145 | spin_lock_irqsave(&kernfs_rename_lock, flags); | ||
| 146 | |||
| 147 | p = kernfs_path_locked(kn, kernfs_pr_cont_buf, | ||
| 148 | sizeof(kernfs_pr_cont_buf)); | ||
| 149 | if (p) | ||
| 150 | pr_cont("%s", p); | ||
| 151 | else | ||
| 152 | pr_cont("<name too long>"); | ||
| 153 | |||
| 154 | spin_unlock_irqrestore(&kernfs_rename_lock, flags); | ||
| 155 | } | ||
| 156 | |||
| 157 | /** | ||
| 158 | * kernfs_get_parent - determine the parent node and pin it | ||
| 159 | * @kn: kernfs_node of interest | ||
| 160 | * | ||
| 161 | * Determines @kn's parent, pins and returns it. This function can be | ||
| 162 | * called from any context. | ||
| 163 | */ | ||
| 164 | struct kernfs_node *kernfs_get_parent(struct kernfs_node *kn) | ||
| 165 | { | ||
| 166 | struct kernfs_node *parent; | ||
| 167 | unsigned long flags; | ||
| 168 | |||
| 169 | spin_lock_irqsave(&kernfs_rename_lock, flags); | ||
| 170 | parent = kn->parent; | ||
| 171 | kernfs_get(parent); | ||
| 172 | spin_unlock_irqrestore(&kernfs_rename_lock, flags); | ||
| 173 | |||
| 174 | return parent; | ||
| 175 | } | ||
| 176 | |||
| 24 | /** | 177 | /** |
| 25 | * kernfs_name_hash | 178 | * kernfs_name_hash |
| 26 | * @name: Null terminated string to hash | 179 | * @name: Null terminated string to hash |
| @@ -37,7 +190,7 @@ static unsigned int kernfs_name_hash(const char *name, const void *ns) | |||
| 37 | hash = (end_name_hash(hash) ^ hash_ptr((void *)ns, 31)); | 190 | hash = (end_name_hash(hash) ^ hash_ptr((void *)ns, 31)); |
| 38 | hash &= 0x7fffffffU; | 191 | hash &= 0x7fffffffU; |
| 39 | /* Reserve hash numbers 0, 1 and INT_MAX for magic directory entries */ | 192 | /* Reserve hash numbers 0, 1 and INT_MAX for magic directory entries */ |
| 40 | if (hash < 1) | 193 | if (hash < 2) |
| 41 | hash += 2; | 194 | hash += 2; |
| 42 | if (hash >= INT_MAX) | 195 | if (hash >= INT_MAX) |
| 43 | hash = INT_MAX - 1; | 196 | hash = INT_MAX - 1; |
| @@ -105,18 +258,24 @@ static int kernfs_link_sibling(struct kernfs_node *kn) | |||
| 105 | * kernfs_unlink_sibling - unlink kernfs_node from sibling rbtree | 258 | * kernfs_unlink_sibling - unlink kernfs_node from sibling rbtree |
| 106 | * @kn: kernfs_node of interest | 259 | * @kn: kernfs_node of interest |
| 107 | * | 260 | * |
| 108 | * Unlink @kn from its sibling rbtree which starts from | 261 | * Try to unlink @kn from its sibling rbtree which starts from |
| 109 | * kn->parent->dir.children. | 262 | * kn->parent->dir.children. Returns %true if @kn was actually |
| 263 | * removed, %false if @kn wasn't on the rbtree. | ||
| 110 | * | 264 | * |
| 111 | * Locking: | 265 | * Locking: |
| 112 | * mutex_lock(kernfs_mutex) | 266 | * mutex_lock(kernfs_mutex) |
| 113 | */ | 267 | */ |
| 114 | static void kernfs_unlink_sibling(struct kernfs_node *kn) | 268 | static bool kernfs_unlink_sibling(struct kernfs_node *kn) |
| 115 | { | 269 | { |
| 270 | if (RB_EMPTY_NODE(&kn->rb)) | ||
| 271 | return false; | ||
| 272 | |||
| 116 | if (kernfs_type(kn) == KERNFS_DIR) | 273 | if (kernfs_type(kn) == KERNFS_DIR) |
| 117 | kn->parent->dir.subdirs--; | 274 | kn->parent->dir.subdirs--; |
| 118 | 275 | ||
| 119 | rb_erase(&kn->rb, &kn->parent->dir.children); | 276 | rb_erase(&kn->rb, &kn->parent->dir.children); |
| 277 | RB_CLEAR_NODE(&kn->rb); | ||
| 278 | return true; | ||
| 120 | } | 279 | } |
| 121 | 280 | ||
| 122 | /** | 281 | /** |
| @@ -137,7 +296,7 @@ struct kernfs_node *kernfs_get_active(struct kernfs_node *kn) | |||
| 137 | if (!atomic_inc_unless_negative(&kn->active)) | 296 | if (!atomic_inc_unless_negative(&kn->active)) |
| 138 | return NULL; | 297 | return NULL; |
| 139 | 298 | ||
| 140 | if (kn->flags & KERNFS_LOCKDEP) | 299 | if (kernfs_lockdep(kn)) |
| 141 | rwsem_acquire_read(&kn->dep_map, 0, 1, _RET_IP_); | 300 | rwsem_acquire_read(&kn->dep_map, 0, 1, _RET_IP_); |
| 142 | return kn; | 301 | return kn; |
| 143 | } | 302 | } |
| @@ -151,59 +310,57 @@ struct kernfs_node *kernfs_get_active(struct kernfs_node *kn) | |||
| 151 | */ | 310 | */ |
| 152 | void kernfs_put_active(struct kernfs_node *kn) | 311 | void kernfs_put_active(struct kernfs_node *kn) |
| 153 | { | 312 | { |
| 313 | struct kernfs_root *root = kernfs_root(kn); | ||
| 154 | int v; | 314 | int v; |
| 155 | 315 | ||
| 156 | if (unlikely(!kn)) | 316 | if (unlikely(!kn)) |
| 157 | return; | 317 | return; |
| 158 | 318 | ||
| 159 | if (kn->flags & KERNFS_LOCKDEP) | 319 | if (kernfs_lockdep(kn)) |
| 160 | rwsem_release(&kn->dep_map, 1, _RET_IP_); | 320 | rwsem_release(&kn->dep_map, 1, _RET_IP_); |
| 161 | v = atomic_dec_return(&kn->active); | 321 | v = atomic_dec_return(&kn->active); |
| 162 | if (likely(v != KN_DEACTIVATED_BIAS)) | 322 | if (likely(v != KN_DEACTIVATED_BIAS)) |
| 163 | return; | 323 | return; |
| 164 | 324 | ||
| 165 | /* | 325 | wake_up_all(&root->deactivate_waitq); |
| 166 | * atomic_dec_return() is a mb(), we'll always see the updated | ||
| 167 | * kn->u.completion. | ||
| 168 | */ | ||
| 169 | complete(kn->u.completion); | ||
| 170 | } | 326 | } |
| 171 | 327 | ||
| 172 | /** | 328 | /** |
| 173 | * kernfs_deactivate - deactivate kernfs_node | 329 | * kernfs_drain - drain kernfs_node |
| 174 | * @kn: kernfs_node to deactivate | 330 | * @kn: kernfs_node to drain |
| 175 | * | 331 | * |
| 176 | * Deny new active references and drain existing ones. | 332 | * Drain existing usages and nuke all existing mmaps of @kn. Mutiple |
| 333 | * removers may invoke this function concurrently on @kn and all will | ||
| 334 | * return after draining is complete. | ||
| 177 | */ | 335 | */ |
| 178 | static void kernfs_deactivate(struct kernfs_node *kn) | 336 | static void kernfs_drain(struct kernfs_node *kn) |
| 337 | __releases(&kernfs_mutex) __acquires(&kernfs_mutex) | ||
| 179 | { | 338 | { |
| 180 | DECLARE_COMPLETION_ONSTACK(wait); | 339 | struct kernfs_root *root = kernfs_root(kn); |
| 181 | int v; | ||
| 182 | 340 | ||
| 183 | BUG_ON(!(kn->flags & KERNFS_REMOVED)); | 341 | lockdep_assert_held(&kernfs_mutex); |
| 184 | 342 | WARN_ON_ONCE(kernfs_active(kn)); | |
| 185 | if (!(kernfs_type(kn) & KERNFS_ACTIVE_REF)) | ||
| 186 | return; | ||
| 187 | 343 | ||
| 188 | kn->u.completion = (void *)&wait; | 344 | mutex_unlock(&kernfs_mutex); |
| 189 | 345 | ||
| 190 | if (kn->flags & KERNFS_LOCKDEP) | 346 | if (kernfs_lockdep(kn)) { |
| 191 | rwsem_acquire(&kn->dep_map, 0, 0, _RET_IP_); | 347 | rwsem_acquire(&kn->dep_map, 0, 0, _RET_IP_); |
| 192 | /* atomic_add_return() is a mb(), put_active() will always see | 348 | if (atomic_read(&kn->active) != KN_DEACTIVATED_BIAS) |
| 193 | * the updated kn->u.completion. | ||
| 194 | */ | ||
| 195 | v = atomic_add_return(KN_DEACTIVATED_BIAS, &kn->active); | ||
| 196 | |||
| 197 | if (v != KN_DEACTIVATED_BIAS) { | ||
| 198 | if (kn->flags & KERNFS_LOCKDEP) | ||
| 199 | lock_contended(&kn->dep_map, _RET_IP_); | 349 | lock_contended(&kn->dep_map, _RET_IP_); |
| 200 | wait_for_completion(&wait); | ||
| 201 | } | 350 | } |
| 202 | 351 | ||
| 203 | if (kn->flags & KERNFS_LOCKDEP) { | 352 | /* but everyone should wait for draining */ |
| 353 | wait_event(root->deactivate_waitq, | ||
| 354 | atomic_read(&kn->active) == KN_DEACTIVATED_BIAS); | ||
| 355 | |||
| 356 | if (kernfs_lockdep(kn)) { | ||
| 204 | lock_acquired(&kn->dep_map, _RET_IP_); | 357 | lock_acquired(&kn->dep_map, _RET_IP_); |
| 205 | rwsem_release(&kn->dep_map, 1, _RET_IP_); | 358 | rwsem_release(&kn->dep_map, 1, _RET_IP_); |
| 206 | } | 359 | } |
| 360 | |||
| 361 | kernfs_unmap_bin_file(kn); | ||
| 362 | |||
| 363 | mutex_lock(&kernfs_mutex); | ||
| 207 | } | 364 | } |
| 208 | 365 | ||
| 209 | /** | 366 | /** |
| @@ -234,13 +391,15 @@ void kernfs_put(struct kernfs_node *kn) | |||
| 234 | return; | 391 | return; |
| 235 | root = kernfs_root(kn); | 392 | root = kernfs_root(kn); |
| 236 | repeat: | 393 | repeat: |
| 237 | /* Moving/renaming is always done while holding reference. | 394 | /* |
| 395 | * Moving/renaming is always done while holding reference. | ||
| 238 | * kn->parent won't change beneath us. | 396 | * kn->parent won't change beneath us. |
| 239 | */ | 397 | */ |
| 240 | parent = kn->parent; | 398 | parent = kn->parent; |
| 241 | 399 | ||
| 242 | WARN(!(kn->flags & KERNFS_REMOVED), "kernfs: free using entry: %s/%s\n", | 400 | WARN_ONCE(atomic_read(&kn->active) != KN_DEACTIVATED_BIAS, |
| 243 | parent ? parent->name : "", kn->name); | 401 | "kernfs_put: %s/%s: released with incorrect active_ref %d\n", |
| 402 | parent ? parent->name : "", kn->name, atomic_read(&kn->active)); | ||
| 244 | 403 | ||
| 245 | if (kernfs_type(kn) == KERNFS_LINK) | 404 | if (kernfs_type(kn) == KERNFS_LINK) |
| 246 | kernfs_put(kn->symlink.target_kn); | 405 | kernfs_put(kn->symlink.target_kn); |
| @@ -282,8 +441,8 @@ static int kernfs_dop_revalidate(struct dentry *dentry, unsigned int flags) | |||
| 282 | kn = dentry->d_fsdata; | 441 | kn = dentry->d_fsdata; |
| 283 | mutex_lock(&kernfs_mutex); | 442 | mutex_lock(&kernfs_mutex); |
| 284 | 443 | ||
| 285 | /* The kernfs node has been deleted */ | 444 | /* The kernfs node has been deactivated */ |
| 286 | if (kn->flags & KERNFS_REMOVED) | 445 | if (!kernfs_active(kn)) |
| 287 | goto out_bad; | 446 | goto out_bad; |
| 288 | 447 | ||
| 289 | /* The kernfs node has been moved? */ | 448 | /* The kernfs node has been moved? */ |
| @@ -328,6 +487,24 @@ const struct dentry_operations kernfs_dops = { | |||
| 328 | .d_release = kernfs_dop_release, | 487 | .d_release = kernfs_dop_release, |
| 329 | }; | 488 | }; |
| 330 | 489 | ||
| 490 | /** | ||
| 491 | * kernfs_node_from_dentry - determine kernfs_node associated with a dentry | ||
| 492 | * @dentry: the dentry in question | ||
| 493 | * | ||
| 494 | * Return the kernfs_node associated with @dentry. If @dentry is not a | ||
| 495 | * kernfs one, %NULL is returned. | ||
| 496 | * | ||
| 497 | * While the returned kernfs_node will stay accessible as long as @dentry | ||
| 498 | * is accessible, the returned node can be in any state and the caller is | ||
| 499 | * fully responsible for determining what's accessible. | ||
| 500 | */ | ||
| 501 | struct kernfs_node *kernfs_node_from_dentry(struct dentry *dentry) | ||
| 502 | { | ||
| 503 | if (dentry->d_sb->s_op == &kernfs_sops) | ||
| 504 | return dentry->d_fsdata; | ||
| 505 | return NULL; | ||
| 506 | } | ||
| 507 | |||
| 331 | static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root, | 508 | static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root, |
| 332 | const char *name, umode_t mode, | 509 | const char *name, umode_t mode, |
| 333 | unsigned flags) | 510 | unsigned flags) |
| @@ -352,11 +529,12 @@ static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root, | |||
| 352 | kn->ino = ret; | 529 | kn->ino = ret; |
| 353 | 530 | ||
| 354 | atomic_set(&kn->count, 1); | 531 | atomic_set(&kn->count, 1); |
| 355 | atomic_set(&kn->active, 0); | 532 | atomic_set(&kn->active, KN_DEACTIVATED_BIAS); |
| 533 | RB_CLEAR_NODE(&kn->rb); | ||
| 356 | 534 | ||
| 357 | kn->name = name; | 535 | kn->name = name; |
| 358 | kn->mode = mode; | 536 | kn->mode = mode; |
| 359 | kn->flags = flags | KERNFS_REMOVED; | 537 | kn->flags = flags; |
| 360 | 538 | ||
| 361 | return kn; | 539 | return kn; |
| 362 | 540 | ||
| @@ -382,69 +560,44 @@ struct kernfs_node *kernfs_new_node(struct kernfs_node *parent, | |||
| 382 | } | 560 | } |
| 383 | 561 | ||
| 384 | /** | 562 | /** |
| 385 | * kernfs_addrm_start - prepare for kernfs_node add/remove | ||
| 386 | * @acxt: pointer to kernfs_addrm_cxt to be used | ||
| 387 | * | ||
| 388 | * This function is called when the caller is about to add or remove | ||
| 389 | * kernfs_node. This function acquires kernfs_mutex. @acxt is used | ||
| 390 | * to keep and pass context to other addrm functions. | ||
| 391 | * | ||
| 392 | * LOCKING: | ||
| 393 | * Kernel thread context (may sleep). kernfs_mutex is locked on | ||
| 394 | * return. | ||
| 395 | */ | ||
| 396 | void kernfs_addrm_start(struct kernfs_addrm_cxt *acxt) | ||
| 397 | __acquires(kernfs_mutex) | ||
| 398 | { | ||
| 399 | memset(acxt, 0, sizeof(*acxt)); | ||
| 400 | |||
| 401 | mutex_lock(&kernfs_mutex); | ||
| 402 | } | ||
| 403 | |||
| 404 | /** | ||
| 405 | * kernfs_add_one - add kernfs_node to parent without warning | 563 | * kernfs_add_one - add kernfs_node to parent without warning |
| 406 | * @acxt: addrm context to use | ||
| 407 | * @kn: kernfs_node to be added | 564 | * @kn: kernfs_node to be added |
| 408 | * | 565 | * |
| 409 | * The caller must already have initialized @kn->parent. This | 566 | * The caller must already have initialized @kn->parent. This |
| 410 | * function increments nlink of the parent's inode if @kn is a | 567 | * function increments nlink of the parent's inode if @kn is a |
| 411 | * directory and link into the children list of the parent. | 568 | * directory and link into the children list of the parent. |
| 412 | * | 569 | * |
| 413 | * This function should be called between calls to | ||
| 414 | * kernfs_addrm_start() and kernfs_addrm_finish() and should be passed | ||
| 415 | * the same @acxt as passed to kernfs_addrm_start(). | ||
| 416 | * | ||
| 417 | * LOCKING: | ||
| 418 | * Determined by kernfs_addrm_start(). | ||
| 419 | * | ||
| 420 | * RETURNS: | 570 | * RETURNS: |
| 421 | * 0 on success, -EEXIST if entry with the given name already | 571 | * 0 on success, -EEXIST if entry with the given name already |
| 422 | * exists. | 572 | * exists. |
| 423 | */ | 573 | */ |
| 424 | int kernfs_add_one(struct kernfs_addrm_cxt *acxt, struct kernfs_node *kn) | 574 | int kernfs_add_one(struct kernfs_node *kn) |
| 425 | { | 575 | { |
| 426 | struct kernfs_node *parent = kn->parent; | 576 | struct kernfs_node *parent = kn->parent; |
| 427 | bool has_ns = kernfs_ns_enabled(parent); | ||
| 428 | struct kernfs_iattrs *ps_iattr; | 577 | struct kernfs_iattrs *ps_iattr; |
| 578 | bool has_ns; | ||
| 429 | int ret; | 579 | int ret; |
| 430 | 580 | ||
| 431 | if (has_ns != (bool)kn->ns) { | 581 | mutex_lock(&kernfs_mutex); |
| 432 | WARN(1, KERN_WARNING "kernfs: ns %s in '%s' for '%s'\n", | 582 | |
| 433 | has_ns ? "required" : "invalid", parent->name, kn->name); | 583 | ret = -EINVAL; |
| 434 | return -EINVAL; | 584 | has_ns = kernfs_ns_enabled(parent); |
| 435 | } | 585 | if (WARN(has_ns != (bool)kn->ns, KERN_WARNING "kernfs: ns %s in '%s' for '%s'\n", |
| 586 | has_ns ? "required" : "invalid", parent->name, kn->name)) | ||
| 587 | goto out_unlock; | ||
| 436 | 588 | ||
| 437 | if (kernfs_type(parent) != KERNFS_DIR) | 589 | if (kernfs_type(parent) != KERNFS_DIR) |
| 438 | return -EINVAL; | 590 | goto out_unlock; |
| 439 | 591 | ||
| 440 | if (parent->flags & KERNFS_REMOVED) | 592 | ret = -ENOENT; |
| 441 | return -ENOENT; | 593 | if ((parent->flags & KERNFS_ACTIVATED) && !kernfs_active(parent)) |
| 594 | goto out_unlock; | ||
| 442 | 595 | ||
| 443 | kn->hash = kernfs_name_hash(kn->name, kn->ns); | 596 | kn->hash = kernfs_name_hash(kn->name, kn->ns); |
| 444 | 597 | ||
| 445 | ret = kernfs_link_sibling(kn); | 598 | ret = kernfs_link_sibling(kn); |
| 446 | if (ret) | 599 | if (ret) |
| 447 | return ret; | 600 | goto out_unlock; |
| 448 | 601 | ||
| 449 | /* Update timestamps on the parent */ | 602 | /* Update timestamps on the parent */ |
| 450 | ps_iattr = parent->iattr; | 603 | ps_iattr = parent->iattr; |
| @@ -453,82 +606,22 @@ int kernfs_add_one(struct kernfs_addrm_cxt *acxt, struct kernfs_node *kn) | |||
| 453 | ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME; | 606 | ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME; |
| 454 | } | 607 | } |
| 455 | 608 | ||
| 456 | /* Mark the entry added into directory tree */ | 609 | mutex_unlock(&kernfs_mutex); |
| 457 | kn->flags &= ~KERNFS_REMOVED; | ||
| 458 | |||
| 459 | return 0; | ||
| 460 | } | ||
| 461 | |||
| 462 | /** | ||
| 463 | * kernfs_remove_one - remove kernfs_node from parent | ||
| 464 | * @acxt: addrm context to use | ||
| 465 | * @kn: kernfs_node to be removed | ||
| 466 | * | ||
| 467 | * Mark @kn removed and drop nlink of parent inode if @kn is a | ||
| 468 | * directory. @kn is unlinked from the children list. | ||
| 469 | * | ||
| 470 | * This function should be called between calls to | ||
| 471 | * kernfs_addrm_start() and kernfs_addrm_finish() and should be | ||
| 472 | * passed the same @acxt as passed to kernfs_addrm_start(). | ||
| 473 | * | ||
| 474 | * LOCKING: | ||
| 475 | * Determined by kernfs_addrm_start(). | ||
| 476 | */ | ||
| 477 | static void kernfs_remove_one(struct kernfs_addrm_cxt *acxt, | ||
| 478 | struct kernfs_node *kn) | ||
| 479 | { | ||
| 480 | struct kernfs_iattrs *ps_iattr; | ||
| 481 | 610 | ||
| 482 | /* | 611 | /* |
| 483 | * Removal can be called multiple times on the same node. Only the | 612 | * Activate the new node unless CREATE_DEACTIVATED is requested. |
| 484 | * first invocation is effective and puts the base ref. | 613 | * If not activated here, the kernfs user is responsible for |
| 614 | * activating the node with kernfs_activate(). A node which hasn't | ||
| 615 | * been activated is not visible to userland and its removal won't | ||
| 616 | * trigger deactivation. | ||
| 485 | */ | 617 | */ |
| 486 | if (kn->flags & KERNFS_REMOVED) | 618 | if (!(kernfs_root(kn)->flags & KERNFS_ROOT_CREATE_DEACTIVATED)) |
| 487 | return; | 619 | kernfs_activate(kn); |
| 488 | 620 | return 0; | |
| 489 | if (kn->parent) { | ||
| 490 | kernfs_unlink_sibling(kn); | ||
| 491 | |||
| 492 | /* Update timestamps on the parent */ | ||
| 493 | ps_iattr = kn->parent->iattr; | ||
| 494 | if (ps_iattr) { | ||
| 495 | ps_iattr->ia_iattr.ia_ctime = CURRENT_TIME; | ||
| 496 | ps_iattr->ia_iattr.ia_mtime = CURRENT_TIME; | ||
| 497 | } | ||
| 498 | } | ||
| 499 | |||
| 500 | kn->flags |= KERNFS_REMOVED; | ||
| 501 | kn->u.removed_list = acxt->removed; | ||
| 502 | acxt->removed = kn; | ||
| 503 | } | ||
| 504 | 621 | ||
| 505 | /** | 622 | out_unlock: |
| 506 | * kernfs_addrm_finish - finish up kernfs_node add/remove | ||
| 507 | * @acxt: addrm context to finish up | ||
| 508 | * | ||
| 509 | * Finish up kernfs_node add/remove. Resources acquired by | ||
| 510 | * kernfs_addrm_start() are released and removed kernfs_nodes are | ||
| 511 | * cleaned up. | ||
| 512 | * | ||
| 513 | * LOCKING: | ||
| 514 | * kernfs_mutex is released. | ||
| 515 | */ | ||
| 516 | void kernfs_addrm_finish(struct kernfs_addrm_cxt *acxt) | ||
| 517 | __releases(kernfs_mutex) | ||
| 518 | { | ||
| 519 | /* release resources acquired by kernfs_addrm_start() */ | ||
| 520 | mutex_unlock(&kernfs_mutex); | 623 | mutex_unlock(&kernfs_mutex); |
| 521 | 624 | return ret; | |
| 522 | /* kill removed kernfs_nodes */ | ||
| 523 | while (acxt->removed) { | ||
| 524 | struct kernfs_node *kn = acxt->removed; | ||
| 525 | |||
| 526 | acxt->removed = kn->u.removed_list; | ||
| 527 | |||
| 528 | kernfs_deactivate(kn); | ||
| 529 | kernfs_unmap_bin_file(kn); | ||
| 530 | kernfs_put(kn); | ||
| 531 | } | ||
| 532 | } | 625 | } |
| 533 | 626 | ||
| 534 | /** | 627 | /** |
| @@ -599,13 +692,15 @@ EXPORT_SYMBOL_GPL(kernfs_find_and_get_ns); | |||
| 599 | 692 | ||
| 600 | /** | 693 | /** |
| 601 | * kernfs_create_root - create a new kernfs hierarchy | 694 | * kernfs_create_root - create a new kernfs hierarchy |
| 602 | * @kdops: optional directory syscall operations for the hierarchy | 695 | * @scops: optional syscall operations for the hierarchy |
| 696 | * @flags: KERNFS_ROOT_* flags | ||
| 603 | * @priv: opaque data associated with the new directory | 697 | * @priv: opaque data associated with the new directory |
| 604 | * | 698 | * |
| 605 | * Returns the root of the new hierarchy on success, ERR_PTR() value on | 699 | * Returns the root of the new hierarchy on success, ERR_PTR() value on |
| 606 | * failure. | 700 | * failure. |
| 607 | */ | 701 | */ |
| 608 | struct kernfs_root *kernfs_create_root(struct kernfs_dir_ops *kdops, void *priv) | 702 | struct kernfs_root *kernfs_create_root(struct kernfs_syscall_ops *scops, |
| 703 | unsigned int flags, void *priv) | ||
| 609 | { | 704 | { |
| 610 | struct kernfs_root *root; | 705 | struct kernfs_root *root; |
| 611 | struct kernfs_node *kn; | 706 | struct kernfs_node *kn; |
| @@ -624,12 +719,16 @@ struct kernfs_root *kernfs_create_root(struct kernfs_dir_ops *kdops, void *priv) | |||
| 624 | return ERR_PTR(-ENOMEM); | 719 | return ERR_PTR(-ENOMEM); |
| 625 | } | 720 | } |
| 626 | 721 | ||
| 627 | kn->flags &= ~KERNFS_REMOVED; | ||
| 628 | kn->priv = priv; | 722 | kn->priv = priv; |
| 629 | kn->dir.root = root; | 723 | kn->dir.root = root; |
| 630 | 724 | ||
| 631 | root->dir_ops = kdops; | 725 | root->syscall_ops = scops; |
| 726 | root->flags = flags; | ||
| 632 | root->kn = kn; | 727 | root->kn = kn; |
| 728 | init_waitqueue_head(&root->deactivate_waitq); | ||
| 729 | |||
| 730 | if (!(root->flags & KERNFS_ROOT_CREATE_DEACTIVATED)) | ||
| 731 | kernfs_activate(kn); | ||
| 633 | 732 | ||
| 634 | return root; | 733 | return root; |
| 635 | } | 734 | } |
| @@ -660,7 +759,6 @@ struct kernfs_node *kernfs_create_dir_ns(struct kernfs_node *parent, | |||
| 660 | const char *name, umode_t mode, | 759 | const char *name, umode_t mode, |
| 661 | void *priv, const void *ns) | 760 | void *priv, const void *ns) |
| 662 | { | 761 | { |
| 663 | struct kernfs_addrm_cxt acxt; | ||
| 664 | struct kernfs_node *kn; | 762 | struct kernfs_node *kn; |
| 665 | int rc; | 763 | int rc; |
| 666 | 764 | ||
| @@ -674,10 +772,7 @@ struct kernfs_node *kernfs_create_dir_ns(struct kernfs_node *parent, | |||
| 674 | kn->priv = priv; | 772 | kn->priv = priv; |
| 675 | 773 | ||
| 676 | /* link in */ | 774 | /* link in */ |
| 677 | kernfs_addrm_start(&acxt); | 775 | rc = kernfs_add_one(kn); |
| 678 | rc = kernfs_add_one(&acxt, kn); | ||
| 679 | kernfs_addrm_finish(&acxt); | ||
| 680 | |||
| 681 | if (!rc) | 776 | if (!rc) |
| 682 | return kn; | 777 | return kn; |
| 683 | 778 | ||
| @@ -703,7 +798,7 @@ static struct dentry *kernfs_iop_lookup(struct inode *dir, | |||
| 703 | kn = kernfs_find_ns(parent, dentry->d_name.name, ns); | 798 | kn = kernfs_find_ns(parent, dentry->d_name.name, ns); |
| 704 | 799 | ||
| 705 | /* no such entry */ | 800 | /* no such entry */ |
| 706 | if (!kn) { | 801 | if (!kn || !kernfs_active(kn)) { |
| 707 | ret = NULL; | 802 | ret = NULL; |
| 708 | goto out_unlock; | 803 | goto out_unlock; |
| 709 | } | 804 | } |
| @@ -728,23 +823,37 @@ static int kernfs_iop_mkdir(struct inode *dir, struct dentry *dentry, | |||
| 728 | umode_t mode) | 823 | umode_t mode) |
| 729 | { | 824 | { |
| 730 | struct kernfs_node *parent = dir->i_private; | 825 | struct kernfs_node *parent = dir->i_private; |
| 731 | struct kernfs_dir_ops *kdops = kernfs_root(parent)->dir_ops; | 826 | struct kernfs_syscall_ops *scops = kernfs_root(parent)->syscall_ops; |
| 827 | int ret; | ||
| 732 | 828 | ||
| 733 | if (!kdops || !kdops->mkdir) | 829 | if (!scops || !scops->mkdir) |
| 734 | return -EPERM; | 830 | return -EPERM; |
| 735 | 831 | ||
| 736 | return kdops->mkdir(parent, dentry->d_name.name, mode); | 832 | if (!kernfs_get_active(parent)) |
| 833 | return -ENODEV; | ||
| 834 | |||
| 835 | ret = scops->mkdir(parent, dentry->d_name.name, mode); | ||
| 836 | |||
| 837 | kernfs_put_active(parent); | ||
| 838 | return ret; | ||
| 737 | } | 839 | } |
| 738 | 840 | ||
| 739 | static int kernfs_iop_rmdir(struct inode *dir, struct dentry *dentry) | 841 | static int kernfs_iop_rmdir(struct inode *dir, struct dentry *dentry) |
| 740 | { | 842 | { |
| 741 | struct kernfs_node *kn = dentry->d_fsdata; | 843 | struct kernfs_node *kn = dentry->d_fsdata; |
| 742 | struct kernfs_dir_ops *kdops = kernfs_root(kn)->dir_ops; | 844 | struct kernfs_syscall_ops *scops = kernfs_root(kn)->syscall_ops; |
| 845 | int ret; | ||
| 743 | 846 | ||
| 744 | if (!kdops || !kdops->rmdir) | 847 | if (!scops || !scops->rmdir) |
| 745 | return -EPERM; | 848 | return -EPERM; |
| 746 | 849 | ||
| 747 | return kdops->rmdir(kn); | 850 | if (!kernfs_get_active(kn)) |
| 851 | return -ENODEV; | ||
| 852 | |||
| 853 | ret = scops->rmdir(kn); | ||
| 854 | |||
| 855 | kernfs_put_active(kn); | ||
| 856 | return ret; | ||
| 748 | } | 857 | } |
| 749 | 858 | ||
| 750 | static int kernfs_iop_rename(struct inode *old_dir, struct dentry *old_dentry, | 859 | static int kernfs_iop_rename(struct inode *old_dir, struct dentry *old_dentry, |
| @@ -752,12 +861,25 @@ static int kernfs_iop_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 752 | { | 861 | { |
| 753 | struct kernfs_node *kn = old_dentry->d_fsdata; | 862 | struct kernfs_node *kn = old_dentry->d_fsdata; |
| 754 | struct kernfs_node *new_parent = new_dir->i_private; | 863 | struct kernfs_node *new_parent = new_dir->i_private; |
| 755 | struct kernfs_dir_ops *kdops = kernfs_root(kn)->dir_ops; | 864 | struct kernfs_syscall_ops *scops = kernfs_root(kn)->syscall_ops; |
| 865 | int ret; | ||
| 756 | 866 | ||
| 757 | if (!kdops || !kdops->rename) | 867 | if (!scops || !scops->rename) |
| 758 | return -EPERM; | 868 | return -EPERM; |
| 759 | 869 | ||
| 760 | return kdops->rename(kn, new_parent, new_dentry->d_name.name); | 870 | if (!kernfs_get_active(kn)) |
| 871 | return -ENODEV; | ||
| 872 | |||
| 873 | if (!kernfs_get_active(new_parent)) { | ||
| 874 | kernfs_put_active(kn); | ||
| 875 | return -ENODEV; | ||
| 876 | } | ||
| 877 | |||
| 878 | ret = scops->rename(kn, new_parent, new_dentry->d_name.name); | ||
| 879 | |||
| 880 | kernfs_put_active(new_parent); | ||
| 881 | kernfs_put_active(kn); | ||
| 882 | return ret; | ||
| 761 | } | 883 | } |
| 762 | 884 | ||
| 763 | const struct inode_operations kernfs_dir_iops = { | 885 | const struct inode_operations kernfs_dir_iops = { |
| @@ -830,23 +952,104 @@ static struct kernfs_node *kernfs_next_descendant_post(struct kernfs_node *pos, | |||
| 830 | return pos->parent; | 952 | return pos->parent; |
| 831 | } | 953 | } |
| 832 | 954 | ||
| 833 | static void __kernfs_remove(struct kernfs_addrm_cxt *acxt, | 955 | /** |
| 834 | struct kernfs_node *kn) | 956 | * kernfs_activate - activate a node which started deactivated |
| 957 | * @kn: kernfs_node whose subtree is to be activated | ||
| 958 | * | ||
| 959 | * If the root has KERNFS_ROOT_CREATE_DEACTIVATED set, a newly created node | ||
| 960 | * needs to be explicitly activated. A node which hasn't been activated | ||
| 961 | * isn't visible to userland and deactivation is skipped during its | ||
| 962 | * removal. This is useful to construct atomic init sequences where | ||
| 963 | * creation of multiple nodes should either succeed or fail atomically. | ||
| 964 | * | ||
| 965 | * The caller is responsible for ensuring that this function is not called | ||
| 966 | * after kernfs_remove*() is invoked on @kn. | ||
| 967 | */ | ||
| 968 | void kernfs_activate(struct kernfs_node *kn) | ||
| 835 | { | 969 | { |
| 836 | struct kernfs_node *pos, *next; | 970 | struct kernfs_node *pos; |
| 837 | 971 | ||
| 838 | if (!kn) | 972 | mutex_lock(&kernfs_mutex); |
| 973 | |||
| 974 | pos = NULL; | ||
| 975 | while ((pos = kernfs_next_descendant_post(pos, kn))) { | ||
| 976 | if (!pos || (pos->flags & KERNFS_ACTIVATED)) | ||
| 977 | continue; | ||
| 978 | |||
| 979 | WARN_ON_ONCE(pos->parent && RB_EMPTY_NODE(&pos->rb)); | ||
| 980 | WARN_ON_ONCE(atomic_read(&pos->active) != KN_DEACTIVATED_BIAS); | ||
| 981 | |||
| 982 | atomic_sub(KN_DEACTIVATED_BIAS, &pos->active); | ||
| 983 | pos->flags |= KERNFS_ACTIVATED; | ||
| 984 | } | ||
| 985 | |||
| 986 | mutex_unlock(&kernfs_mutex); | ||
| 987 | } | ||
| 988 | |||
| 989 | static void __kernfs_remove(struct kernfs_node *kn) | ||
| 990 | { | ||
| 991 | struct kernfs_node *pos; | ||
| 992 | |||
| 993 | lockdep_assert_held(&kernfs_mutex); | ||
| 994 | |||
| 995 | /* | ||
| 996 | * Short-circuit if non-root @kn has already finished removal. | ||
| 997 | * This is for kernfs_remove_self() which plays with active ref | ||
| 998 | * after removal. | ||
| 999 | */ | ||
| 1000 | if (!kn || (kn->parent && RB_EMPTY_NODE(&kn->rb))) | ||
| 839 | return; | 1001 | return; |
| 840 | 1002 | ||
| 841 | pr_debug("kernfs %s: removing\n", kn->name); | 1003 | pr_debug("kernfs %s: removing\n", kn->name); |
| 842 | 1004 | ||
| 843 | next = NULL; | 1005 | /* prevent any new usage under @kn by deactivating all nodes */ |
| 1006 | pos = NULL; | ||
| 1007 | while ((pos = kernfs_next_descendant_post(pos, kn))) | ||
| 1008 | if (kernfs_active(pos)) | ||
| 1009 | atomic_add(KN_DEACTIVATED_BIAS, &pos->active); | ||
| 1010 | |||
| 1011 | /* deactivate and unlink the subtree node-by-node */ | ||
| 844 | do { | 1012 | do { |
| 845 | pos = next; | 1013 | pos = kernfs_leftmost_descendant(kn); |
| 846 | next = kernfs_next_descendant_post(pos, kn); | 1014 | |
| 847 | if (pos) | 1015 | /* |
| 848 | kernfs_remove_one(acxt, pos); | 1016 | * kernfs_drain() drops kernfs_mutex temporarily and @pos's |
| 849 | } while (next); | 1017 | * base ref could have been put by someone else by the time |
| 1018 | * the function returns. Make sure it doesn't go away | ||
| 1019 | * underneath us. | ||
| 1020 | */ | ||
| 1021 | kernfs_get(pos); | ||
| 1022 | |||
| 1023 | /* | ||
| 1024 | * Drain iff @kn was activated. This avoids draining and | ||
| 1025 | * its lockdep annotations for nodes which have never been | ||
| 1026 | * activated and allows embedding kernfs_remove() in create | ||
| 1027 | * error paths without worrying about draining. | ||
| 1028 | */ | ||
| 1029 | if (kn->flags & KERNFS_ACTIVATED) | ||
| 1030 | kernfs_drain(pos); | ||
| 1031 | else | ||
| 1032 | WARN_ON_ONCE(atomic_read(&kn->active) != KN_DEACTIVATED_BIAS); | ||
| 1033 | |||
| 1034 | /* | ||
| 1035 | * kernfs_unlink_sibling() succeeds once per node. Use it | ||
| 1036 | * to decide who's responsible for cleanups. | ||
| 1037 | */ | ||
| 1038 | if (!pos->parent || kernfs_unlink_sibling(pos)) { | ||
| 1039 | struct kernfs_iattrs *ps_iattr = | ||
| 1040 | pos->parent ? pos->parent->iattr : NULL; | ||
| 1041 | |||
| 1042 | /* update timestamps on the parent */ | ||
| 1043 | if (ps_iattr) { | ||
| 1044 | ps_iattr->ia_iattr.ia_ctime = CURRENT_TIME; | ||
| 1045 | ps_iattr->ia_iattr.ia_mtime = CURRENT_TIME; | ||
| 1046 | } | ||
| 1047 | |||
| 1048 | kernfs_put(pos); | ||
| 1049 | } | ||
| 1050 | |||
| 1051 | kernfs_put(pos); | ||
| 1052 | } while (pos != kn); | ||
| 850 | } | 1053 | } |
| 851 | 1054 | ||
| 852 | /** | 1055 | /** |
| @@ -857,11 +1060,140 @@ static void __kernfs_remove(struct kernfs_addrm_cxt *acxt, | |||
| 857 | */ | 1060 | */ |
| 858 | void kernfs_remove(struct kernfs_node *kn) | 1061 | void kernfs_remove(struct kernfs_node *kn) |
| 859 | { | 1062 | { |
| 860 | struct kernfs_addrm_cxt acxt; | 1063 | mutex_lock(&kernfs_mutex); |
| 1064 | __kernfs_remove(kn); | ||
| 1065 | mutex_unlock(&kernfs_mutex); | ||
| 1066 | } | ||
| 861 | 1067 | ||
| 862 | kernfs_addrm_start(&acxt); | 1068 | /** |
| 863 | __kernfs_remove(&acxt, kn); | 1069 | * kernfs_break_active_protection - break out of active protection |
| 864 | kernfs_addrm_finish(&acxt); | 1070 | * @kn: the self kernfs_node |
| 1071 | * | ||
| 1072 | * The caller must be running off of a kernfs operation which is invoked | ||
| 1073 | * with an active reference - e.g. one of kernfs_ops. Each invocation of | ||
| 1074 | * this function must also be matched with an invocation of | ||
| 1075 | * kernfs_unbreak_active_protection(). | ||
| 1076 | * | ||
| 1077 | * This function releases the active reference of @kn the caller is | ||
| 1078 | * holding. Once this function is called, @kn may be removed at any point | ||
| 1079 | * and the caller is solely responsible for ensuring that the objects it | ||
| 1080 | * dereferences are accessible. | ||
| 1081 | */ | ||
| 1082 | void kernfs_break_active_protection(struct kernfs_node *kn) | ||
| 1083 | { | ||
| 1084 | /* | ||
| 1085 | * Take out ourself out of the active ref dependency chain. If | ||
| 1086 | * we're called without an active ref, lockdep will complain. | ||
| 1087 | */ | ||
| 1088 | kernfs_put_active(kn); | ||
| 1089 | } | ||
| 1090 | |||
| 1091 | /** | ||
| 1092 | * kernfs_unbreak_active_protection - undo kernfs_break_active_protection() | ||
| 1093 | * @kn: the self kernfs_node | ||
| 1094 | * | ||
| 1095 | * If kernfs_break_active_protection() was called, this function must be | ||
| 1096 | * invoked before finishing the kernfs operation. Note that while this | ||
| 1097 | * function restores the active reference, it doesn't and can't actually | ||
| 1098 | * restore the active protection - @kn may already or be in the process of | ||
| 1099 | * being removed. Once kernfs_break_active_protection() is invoked, that | ||
| 1100 | * protection is irreversibly gone for the kernfs operation instance. | ||
| 1101 | * | ||
| 1102 | * While this function may be called at any point after | ||
| 1103 | * kernfs_break_active_protection() is invoked, its most useful location | ||
| 1104 | * would be right before the enclosing kernfs operation returns. | ||
| 1105 | */ | ||
| 1106 | void kernfs_unbreak_active_protection(struct kernfs_node *kn) | ||
| 1107 | { | ||
| 1108 | /* | ||
| 1109 | * @kn->active could be in any state; however, the increment we do | ||
| 1110 | * here will be undone as soon as the enclosing kernfs operation | ||
| 1111 | * finishes and this temporary bump can't break anything. If @kn | ||
| 1112 | * is alive, nothing changes. If @kn is being deactivated, the | ||
| 1113 | * soon-to-follow put will either finish deactivation or restore | ||
| 1114 | * deactivated state. If @kn is already removed, the temporary | ||
| 1115 | * bump is guaranteed to be gone before @kn is released. | ||
| 1116 | */ | ||
| 1117 | atomic_inc(&kn->active); | ||
| 1118 | if (kernfs_lockdep(kn)) | ||
| 1119 | rwsem_acquire(&kn->dep_map, 0, 1, _RET_IP_); | ||
| 1120 | } | ||
| 1121 | |||
| 1122 | /** | ||
| 1123 | * kernfs_remove_self - remove a kernfs_node from its own method | ||
| 1124 | * @kn: the self kernfs_node to remove | ||
| 1125 | * | ||
| 1126 | * The caller must be running off of a kernfs operation which is invoked | ||
| 1127 | * with an active reference - e.g. one of kernfs_ops. This can be used to | ||
| 1128 | * implement a file operation which deletes itself. | ||
| 1129 | * | ||
| 1130 | * For example, the "delete" file for a sysfs device directory can be | ||
| 1131 | * implemented by invoking kernfs_remove_self() on the "delete" file | ||
| 1132 | * itself. This function breaks the circular dependency of trying to | ||
| 1133 | * deactivate self while holding an active ref itself. It isn't necessary | ||
| 1134 | * to modify the usual removal path to use kernfs_remove_self(). The | ||
| 1135 | * "delete" implementation can simply invoke kernfs_remove_self() on self | ||
| 1136 | * before proceeding with the usual removal path. kernfs will ignore later | ||
| 1137 | * kernfs_remove() on self. | ||
| 1138 | * | ||
| 1139 | * kernfs_remove_self() can be called multiple times concurrently on the | ||
| 1140 | * same kernfs_node. Only the first one actually performs removal and | ||
| 1141 | * returns %true. All others will wait until the kernfs operation which | ||
| 1142 | * won self-removal finishes and return %false. Note that the losers wait | ||
| 1143 | * for the completion of not only the winning kernfs_remove_self() but also | ||
| 1144 | * the whole kernfs_ops which won the arbitration. This can be used to | ||
| 1145 | * guarantee, for example, all concurrent writes to a "delete" file to | ||
| 1146 | * finish only after the whole operation is complete. | ||
| 1147 | */ | ||
| 1148 | bool kernfs_remove_self(struct kernfs_node *kn) | ||
| 1149 | { | ||
| 1150 | bool ret; | ||
| 1151 | |||
| 1152 | mutex_lock(&kernfs_mutex); | ||
| 1153 | kernfs_break_active_protection(kn); | ||
| 1154 | |||
| 1155 | /* | ||
| 1156 | * SUICIDAL is used to arbitrate among competing invocations. Only | ||
| 1157 | * the first one will actually perform removal. When the removal | ||
| 1158 | * is complete, SUICIDED is set and the active ref is restored | ||
| 1159 | * while holding kernfs_mutex. The ones which lost arbitration | ||
| 1160 | * waits for SUICDED && drained which can happen only after the | ||
| 1161 | * enclosing kernfs operation which executed the winning instance | ||
| 1162 | * of kernfs_remove_self() finished. | ||
| 1163 | */ | ||
| 1164 | if (!(kn->flags & KERNFS_SUICIDAL)) { | ||
| 1165 | kn->flags |= KERNFS_SUICIDAL; | ||
| 1166 | __kernfs_remove(kn); | ||
| 1167 | kn->flags |= KERNFS_SUICIDED; | ||
| 1168 | ret = true; | ||
| 1169 | } else { | ||
| 1170 | wait_queue_head_t *waitq = &kernfs_root(kn)->deactivate_waitq; | ||
| 1171 | DEFINE_WAIT(wait); | ||
| 1172 | |||
| 1173 | while (true) { | ||
| 1174 | prepare_to_wait(waitq, &wait, TASK_UNINTERRUPTIBLE); | ||
| 1175 | |||
| 1176 | if ((kn->flags & KERNFS_SUICIDED) && | ||
| 1177 | atomic_read(&kn->active) == KN_DEACTIVATED_BIAS) | ||
| 1178 | break; | ||
| 1179 | |||
| 1180 | mutex_unlock(&kernfs_mutex); | ||
| 1181 | schedule(); | ||
| 1182 | mutex_lock(&kernfs_mutex); | ||
| 1183 | } | ||
| 1184 | finish_wait(waitq, &wait); | ||
| 1185 | WARN_ON_ONCE(!RB_EMPTY_NODE(&kn->rb)); | ||
| 1186 | ret = false; | ||
| 1187 | } | ||
| 1188 | |||
| 1189 | /* | ||
| 1190 | * This must be done while holding kernfs_mutex; otherwise, waiting | ||
| 1191 | * for SUICIDED && deactivated could finish prematurely. | ||
| 1192 | */ | ||
| 1193 | kernfs_unbreak_active_protection(kn); | ||
| 1194 | |||
| 1195 | mutex_unlock(&kernfs_mutex); | ||
| 1196 | return ret; | ||
| 865 | } | 1197 | } |
| 866 | 1198 | ||
| 867 | /** | 1199 | /** |
| @@ -876,7 +1208,6 @@ void kernfs_remove(struct kernfs_node *kn) | |||
| 876 | int kernfs_remove_by_name_ns(struct kernfs_node *parent, const char *name, | 1208 | int kernfs_remove_by_name_ns(struct kernfs_node *parent, const char *name, |
| 877 | const void *ns) | 1209 | const void *ns) |
| 878 | { | 1210 | { |
| 879 | struct kernfs_addrm_cxt acxt; | ||
| 880 | struct kernfs_node *kn; | 1211 | struct kernfs_node *kn; |
| 881 | 1212 | ||
| 882 | if (!parent) { | 1213 | if (!parent) { |
| @@ -885,13 +1216,13 @@ int kernfs_remove_by_name_ns(struct kernfs_node *parent, const char *name, | |||
| 885 | return -ENOENT; | 1216 | return -ENOENT; |
| 886 | } | 1217 | } |
| 887 | 1218 | ||
| 888 | kernfs_addrm_start(&acxt); | 1219 | mutex_lock(&kernfs_mutex); |
| 889 | 1220 | ||
| 890 | kn = kernfs_find_ns(parent, name, ns); | 1221 | kn = kernfs_find_ns(parent, name, ns); |
| 891 | if (kn) | 1222 | if (kn) |
| 892 | __kernfs_remove(&acxt, kn); | 1223 | __kernfs_remove(kn); |
| 893 | 1224 | ||
| 894 | kernfs_addrm_finish(&acxt); | 1225 | mutex_unlock(&kernfs_mutex); |
| 895 | 1226 | ||
| 896 | if (kn) | 1227 | if (kn) |
| 897 | return 0; | 1228 | return 0; |
| @@ -909,12 +1240,18 @@ int kernfs_remove_by_name_ns(struct kernfs_node *parent, const char *name, | |||
| 909 | int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent, | 1240 | int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent, |
| 910 | const char *new_name, const void *new_ns) | 1241 | const char *new_name, const void *new_ns) |
| 911 | { | 1242 | { |
| 1243 | struct kernfs_node *old_parent; | ||
| 1244 | const char *old_name = NULL; | ||
| 912 | int error; | 1245 | int error; |
| 913 | 1246 | ||
| 1247 | /* can't move or rename root */ | ||
| 1248 | if (!kn->parent) | ||
| 1249 | return -EINVAL; | ||
| 1250 | |||
| 914 | mutex_lock(&kernfs_mutex); | 1251 | mutex_lock(&kernfs_mutex); |
| 915 | 1252 | ||
| 916 | error = -ENOENT; | 1253 | error = -ENOENT; |
| 917 | if ((kn->flags | new_parent->flags) & KERNFS_REMOVED) | 1254 | if (!kernfs_active(kn) || !kernfs_active(new_parent)) |
| 918 | goto out; | 1255 | goto out; |
| 919 | 1256 | ||
| 920 | error = 0; | 1257 | error = 0; |
| @@ -932,13 +1269,8 @@ int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent, | |||
| 932 | new_name = kstrdup(new_name, GFP_KERNEL); | 1269 | new_name = kstrdup(new_name, GFP_KERNEL); |
| 933 | if (!new_name) | 1270 | if (!new_name) |
| 934 | goto out; | 1271 | goto out; |
| 935 | 1272 | } else { | |
| 936 | if (kn->flags & KERNFS_STATIC_NAME) | 1273 | new_name = NULL; |
| 937 | kn->flags &= ~KERNFS_STATIC_NAME; | ||
| 938 | else | ||
| 939 | kfree(kn->name); | ||
| 940 | |||
| 941 | kn->name = new_name; | ||
| 942 | } | 1274 | } |
| 943 | 1275 | ||
| 944 | /* | 1276 | /* |
| @@ -946,12 +1278,29 @@ int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent, | |||
| 946 | */ | 1278 | */ |
| 947 | kernfs_unlink_sibling(kn); | 1279 | kernfs_unlink_sibling(kn); |
| 948 | kernfs_get(new_parent); | 1280 | kernfs_get(new_parent); |
| 949 | kernfs_put(kn->parent); | 1281 | |
| 1282 | /* rename_lock protects ->parent and ->name accessors */ | ||
| 1283 | spin_lock_irq(&kernfs_rename_lock); | ||
| 1284 | |||
| 1285 | old_parent = kn->parent; | ||
| 1286 | kn->parent = new_parent; | ||
| 1287 | |||
| 950 | kn->ns = new_ns; | 1288 | kn->ns = new_ns; |
| 1289 | if (new_name) { | ||
| 1290 | if (!(kn->flags & KERNFS_STATIC_NAME)) | ||
| 1291 | old_name = kn->name; | ||
| 1292 | kn->flags &= ~KERNFS_STATIC_NAME; | ||
| 1293 | kn->name = new_name; | ||
| 1294 | } | ||
| 1295 | |||
| 1296 | spin_unlock_irq(&kernfs_rename_lock); | ||
| 1297 | |||
| 951 | kn->hash = kernfs_name_hash(kn->name, kn->ns); | 1298 | kn->hash = kernfs_name_hash(kn->name, kn->ns); |
| 952 | kn->parent = new_parent; | ||
| 953 | kernfs_link_sibling(kn); | 1299 | kernfs_link_sibling(kn); |
| 954 | 1300 | ||
| 1301 | kernfs_put(old_parent); | ||
| 1302 | kfree(old_name); | ||
| 1303 | |||
| 955 | error = 0; | 1304 | error = 0; |
| 956 | out: | 1305 | out: |
| 957 | mutex_unlock(&kernfs_mutex); | 1306 | mutex_unlock(&kernfs_mutex); |
| @@ -974,7 +1323,7 @@ static struct kernfs_node *kernfs_dir_pos(const void *ns, | |||
| 974 | struct kernfs_node *parent, loff_t hash, struct kernfs_node *pos) | 1323 | struct kernfs_node *parent, loff_t hash, struct kernfs_node *pos) |
| 975 | { | 1324 | { |
| 976 | if (pos) { | 1325 | if (pos) { |
| 977 | int valid = !(pos->flags & KERNFS_REMOVED) && | 1326 | int valid = kernfs_active(pos) && |
| 978 | pos->parent == parent && hash == pos->hash; | 1327 | pos->parent == parent && hash == pos->hash; |
| 979 | kernfs_put(pos); | 1328 | kernfs_put(pos); |
| 980 | if (!valid) | 1329 | if (!valid) |
| @@ -993,8 +1342,8 @@ static struct kernfs_node *kernfs_dir_pos(const void *ns, | |||
| 993 | break; | 1342 | break; |
| 994 | } | 1343 | } |
| 995 | } | 1344 | } |
| 996 | /* Skip over entries in the wrong namespace */ | 1345 | /* Skip over entries which are dying/dead or in the wrong namespace */ |
| 997 | while (pos && pos->ns != ns) { | 1346 | while (pos && (!kernfs_active(pos) || pos->ns != ns)) { |
| 998 | struct rb_node *node = rb_next(&pos->rb); | 1347 | struct rb_node *node = rb_next(&pos->rb); |
| 999 | if (!node) | 1348 | if (!node) |
| 1000 | pos = NULL; | 1349 | pos = NULL; |
| @@ -1008,14 +1357,15 @@ static struct kernfs_node *kernfs_dir_next_pos(const void *ns, | |||
| 1008 | struct kernfs_node *parent, ino_t ino, struct kernfs_node *pos) | 1357 | struct kernfs_node *parent, ino_t ino, struct kernfs_node *pos) |
| 1009 | { | 1358 | { |
| 1010 | pos = kernfs_dir_pos(ns, parent, ino, pos); | 1359 | pos = kernfs_dir_pos(ns, parent, ino, pos); |
| 1011 | if (pos) | 1360 | if (pos) { |
| 1012 | do { | 1361 | do { |
| 1013 | struct rb_node *node = rb_next(&pos->rb); | 1362 | struct rb_node *node = rb_next(&pos->rb); |
| 1014 | if (!node) | 1363 | if (!node) |
| 1015 | pos = NULL; | 1364 | pos = NULL; |
| 1016 | else | 1365 | else |
| 1017 | pos = rb_to_kn(node); | 1366 | pos = rb_to_kn(node); |
| 1018 | } while (pos && pos->ns != ns); | 1367 | } while (pos && (!kernfs_active(pos) || pos->ns != ns)); |
| 1368 | } | ||
| 1019 | return pos; | 1369 | return pos; |
| 1020 | } | 1370 | } |
| 1021 | 1371 | ||
diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c index dbf397bfdff2..8034706a7af8 100644 --- a/fs/kernfs/file.c +++ b/fs/kernfs/file.c | |||
| @@ -252,10 +252,18 @@ static ssize_t kernfs_fop_write(struct file *file, const char __user *user_buf, | |||
| 252 | size_t count, loff_t *ppos) | 252 | size_t count, loff_t *ppos) |
| 253 | { | 253 | { |
| 254 | struct kernfs_open_file *of = kernfs_of(file); | 254 | struct kernfs_open_file *of = kernfs_of(file); |
| 255 | ssize_t len = min_t(size_t, count, PAGE_SIZE); | ||
| 256 | const struct kernfs_ops *ops; | 255 | const struct kernfs_ops *ops; |
| 256 | size_t len; | ||
| 257 | char *buf; | 257 | char *buf; |
| 258 | 258 | ||
| 259 | if (of->atomic_write_len) { | ||
| 260 | len = count; | ||
| 261 | if (len > of->atomic_write_len) | ||
| 262 | return -E2BIG; | ||
| 263 | } else { | ||
| 264 | len = min_t(size_t, count, PAGE_SIZE); | ||
| 265 | } | ||
| 266 | |||
| 259 | buf = kmalloc(len + 1, GFP_KERNEL); | 267 | buf = kmalloc(len + 1, GFP_KERNEL); |
| 260 | if (!buf) | 268 | if (!buf) |
| 261 | return -ENOMEM; | 269 | return -ENOMEM; |
| @@ -653,6 +661,12 @@ static int kernfs_fop_open(struct inode *inode, struct file *file) | |||
| 653 | of->file = file; | 661 | of->file = file; |
| 654 | 662 | ||
| 655 | /* | 663 | /* |
| 664 | * Write path needs to atomic_write_len outside active reference. | ||
| 665 | * Cache it in open_file. See kernfs_fop_write() for details. | ||
| 666 | */ | ||
| 667 | of->atomic_write_len = ops->atomic_write_len; | ||
| 668 | |||
| 669 | /* | ||
| 656 | * Always instantiate seq_file even if read access doesn't use | 670 | * Always instantiate seq_file even if read access doesn't use |
| 657 | * seq_file or is not requested. This unifies private data access | 671 | * seq_file or is not requested. This unifies private data access |
| 658 | * and readable regular files are the vast majority anyway. | 672 | * and readable regular files are the vast majority anyway. |
| @@ -820,7 +834,6 @@ struct kernfs_node *__kernfs_create_file(struct kernfs_node *parent, | |||
| 820 | bool name_is_static, | 834 | bool name_is_static, |
| 821 | struct lock_class_key *key) | 835 | struct lock_class_key *key) |
| 822 | { | 836 | { |
| 823 | struct kernfs_addrm_cxt acxt; | ||
| 824 | struct kernfs_node *kn; | 837 | struct kernfs_node *kn; |
| 825 | unsigned flags; | 838 | unsigned flags; |
| 826 | int rc; | 839 | int rc; |
| @@ -855,10 +868,7 @@ struct kernfs_node *__kernfs_create_file(struct kernfs_node *parent, | |||
| 855 | if (ops->mmap) | 868 | if (ops->mmap) |
| 856 | kn->flags |= KERNFS_HAS_MMAP; | 869 | kn->flags |= KERNFS_HAS_MMAP; |
| 857 | 870 | ||
| 858 | kernfs_addrm_start(&acxt); | 871 | rc = kernfs_add_one(kn); |
| 859 | rc = kernfs_add_one(&acxt, kn); | ||
| 860 | kernfs_addrm_finish(&acxt); | ||
| 861 | |||
| 862 | if (rc) { | 872 | if (rc) { |
| 863 | kernfs_put(kn); | 873 | kernfs_put(kn); |
| 864 | return ERR_PTR(rc); | 874 | return ERR_PTR(rc); |
diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index eb536b76374a..8be13b2a079b 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h | |||
| @@ -26,7 +26,8 @@ struct kernfs_iattrs { | |||
| 26 | struct simple_xattrs xattrs; | 26 | struct simple_xattrs xattrs; |
| 27 | }; | 27 | }; |
| 28 | 28 | ||
| 29 | #define KN_DEACTIVATED_BIAS INT_MIN | 29 | /* +1 to avoid triggering overflow warning when negating it */ |
| 30 | #define KN_DEACTIVATED_BIAS (INT_MIN + 1) | ||
| 30 | 31 | ||
| 31 | /* KERNFS_TYPE_MASK and types are defined in include/linux/kernfs.h */ | 32 | /* KERNFS_TYPE_MASK and types are defined in include/linux/kernfs.h */ |
| 32 | 33 | ||
| @@ -45,13 +46,6 @@ static inline struct kernfs_root *kernfs_root(struct kernfs_node *kn) | |||
| 45 | } | 46 | } |
| 46 | 47 | ||
| 47 | /* | 48 | /* |
| 48 | * Context structure to be used while adding/removing nodes. | ||
| 49 | */ | ||
| 50 | struct kernfs_addrm_cxt { | ||
| 51 | struct kernfs_node *removed; | ||
| 52 | }; | ||
| 53 | |||
| 54 | /* | ||
| 55 | * mount.c | 49 | * mount.c |
| 56 | */ | 50 | */ |
| 57 | struct kernfs_super_info { | 51 | struct kernfs_super_info { |
| @@ -71,6 +65,7 @@ struct kernfs_super_info { | |||
| 71 | }; | 65 | }; |
| 72 | #define kernfs_info(SB) ((struct kernfs_super_info *)(SB->s_fs_info)) | 66 | #define kernfs_info(SB) ((struct kernfs_super_info *)(SB->s_fs_info)) |
| 73 | 67 | ||
| 68 | extern const struct super_operations kernfs_sops; | ||
| 74 | extern struct kmem_cache *kernfs_node_cache; | 69 | extern struct kmem_cache *kernfs_node_cache; |
| 75 | 70 | ||
| 76 | /* | 71 | /* |
| @@ -100,9 +95,7 @@ extern const struct inode_operations kernfs_dir_iops; | |||
| 100 | 95 | ||
| 101 | struct kernfs_node *kernfs_get_active(struct kernfs_node *kn); | 96 | struct kernfs_node *kernfs_get_active(struct kernfs_node *kn); |
| 102 | void kernfs_put_active(struct kernfs_node *kn); | 97 | void kernfs_put_active(struct kernfs_node *kn); |
| 103 | void kernfs_addrm_start(struct kernfs_addrm_cxt *acxt); | 98 | int kernfs_add_one(struct kernfs_node *kn); |
| 104 | int kernfs_add_one(struct kernfs_addrm_cxt *acxt, struct kernfs_node *kn); | ||
| 105 | void kernfs_addrm_finish(struct kernfs_addrm_cxt *acxt); | ||
| 106 | struct kernfs_node *kernfs_new_node(struct kernfs_node *parent, | 99 | struct kernfs_node *kernfs_new_node(struct kernfs_node *parent, |
| 107 | const char *name, umode_t mode, | 100 | const char *name, umode_t mode, |
| 108 | unsigned flags); | 101 | unsigned flags); |
diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c index 0f4152defe7b..6a5f04ac8704 100644 --- a/fs/kernfs/mount.c +++ b/fs/kernfs/mount.c | |||
| @@ -19,12 +19,49 @@ | |||
| 19 | 19 | ||
| 20 | struct kmem_cache *kernfs_node_cache; | 20 | struct kmem_cache *kernfs_node_cache; |
| 21 | 21 | ||
| 22 | static const struct super_operations kernfs_sops = { | 22 | static int kernfs_sop_remount_fs(struct super_block *sb, int *flags, char *data) |
| 23 | { | ||
| 24 | struct kernfs_root *root = kernfs_info(sb)->root; | ||
| 25 | struct kernfs_syscall_ops *scops = root->syscall_ops; | ||
| 26 | |||
| 27 | if (scops && scops->remount_fs) | ||
| 28 | return scops->remount_fs(root, flags, data); | ||
| 29 | return 0; | ||
| 30 | } | ||
| 31 | |||
| 32 | static int kernfs_sop_show_options(struct seq_file *sf, struct dentry *dentry) | ||
| 33 | { | ||
| 34 | struct kernfs_root *root = kernfs_root(dentry->d_fsdata); | ||
| 35 | struct kernfs_syscall_ops *scops = root->syscall_ops; | ||
| 36 | |||
| 37 | if (scops && scops->show_options) | ||
| 38 | return scops->show_options(sf, root); | ||
| 39 | return 0; | ||
| 40 | } | ||
| 41 | |||
| 42 | const struct super_operations kernfs_sops = { | ||
| 23 | .statfs = simple_statfs, | 43 | .statfs = simple_statfs, |
| 24 | .drop_inode = generic_delete_inode, | 44 | .drop_inode = generic_delete_inode, |
| 25 | .evict_inode = kernfs_evict_inode, | 45 | .evict_inode = kernfs_evict_inode, |
| 46 | |||
| 47 | .remount_fs = kernfs_sop_remount_fs, | ||
| 48 | .show_options = kernfs_sop_show_options, | ||
| 26 | }; | 49 | }; |
| 27 | 50 | ||
| 51 | /** | ||
| 52 | * kernfs_root_from_sb - determine kernfs_root associated with a super_block | ||
| 53 | * @sb: the super_block in question | ||
| 54 | * | ||
| 55 | * Return the kernfs_root associated with @sb. If @sb is not a kernfs one, | ||
| 56 | * %NULL is returned. | ||
| 57 | */ | ||
| 58 | struct kernfs_root *kernfs_root_from_sb(struct super_block *sb) | ||
| 59 | { | ||
| 60 | if (sb->s_op == &kernfs_sops) | ||
| 61 | return kernfs_info(sb)->root; | ||
| 62 | return NULL; | ||
| 63 | } | ||
| 64 | |||
| 28 | static int kernfs_fill_super(struct super_block *sb) | 65 | static int kernfs_fill_super(struct super_block *sb) |
| 29 | { | 66 | { |
| 30 | struct kernfs_super_info *info = kernfs_info(sb); | 67 | struct kernfs_super_info *info = kernfs_info(sb); |
diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c index 4d457055acb9..8a198898e39a 100644 --- a/fs/kernfs/symlink.c +++ b/fs/kernfs/symlink.c | |||
| @@ -27,7 +27,6 @@ struct kernfs_node *kernfs_create_link(struct kernfs_node *parent, | |||
| 27 | struct kernfs_node *target) | 27 | struct kernfs_node *target) |
| 28 | { | 28 | { |
| 29 | struct kernfs_node *kn; | 29 | struct kernfs_node *kn; |
| 30 | struct kernfs_addrm_cxt acxt; | ||
| 31 | int error; | 30 | int error; |
| 32 | 31 | ||
| 33 | kn = kernfs_new_node(parent, name, S_IFLNK|S_IRWXUGO, KERNFS_LINK); | 32 | kn = kernfs_new_node(parent, name, S_IFLNK|S_IRWXUGO, KERNFS_LINK); |
| @@ -39,10 +38,7 @@ struct kernfs_node *kernfs_create_link(struct kernfs_node *parent, | |||
| 39 | kn->symlink.target_kn = target; | 38 | kn->symlink.target_kn = target; |
| 40 | kernfs_get(target); /* ref owned by symlink */ | 39 | kernfs_get(target); /* ref owned by symlink */ |
| 41 | 40 | ||
| 42 | kernfs_addrm_start(&acxt); | 41 | error = kernfs_add_one(kn); |
| 43 | error = kernfs_add_one(&acxt, kn); | ||
| 44 | kernfs_addrm_finish(&acxt); | ||
| 45 | |||
| 46 | if (!error) | 42 | if (!error) |
| 47 | return kn; | 43 | return kn; |
| 48 | 44 | ||
diff --git a/fs/sysfs/Kconfig b/fs/sysfs/Kconfig index 8c41feacbac5..b2756014508c 100644 --- a/fs/sysfs/Kconfig +++ b/fs/sysfs/Kconfig | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | config SYSFS | 1 | config SYSFS |
| 2 | bool "sysfs file system support" if EXPERT | 2 | bool "sysfs file system support" if EXPERT |
| 3 | default y | 3 | default y |
| 4 | select KERNFS | ||
| 4 | help | 5 | help |
| 5 | The sysfs filesystem is a virtual filesystem that the kernel uses to | 6 | The sysfs filesystem is a virtual filesystem that the kernel uses to |
| 6 | export internal kernel objects, their attributes, and their | 7 | export internal kernel objects, their attributes, and their |
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index ee0d761c3179..0b45ff42f374 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
| @@ -19,39 +19,18 @@ | |||
| 19 | 19 | ||
| 20 | DEFINE_SPINLOCK(sysfs_symlink_target_lock); | 20 | DEFINE_SPINLOCK(sysfs_symlink_target_lock); |
| 21 | 21 | ||
| 22 | /** | ||
| 23 | * sysfs_pathname - return full path to sysfs dirent | ||
| 24 | * @kn: kernfs_node whose path we want | ||
| 25 | * @path: caller allocated buffer of size PATH_MAX | ||
| 26 | * | ||
| 27 | * Gives the name "/" to the sysfs_root entry; any path returned | ||
| 28 | * is relative to wherever sysfs is mounted. | ||
| 29 | */ | ||
| 30 | static char *sysfs_pathname(struct kernfs_node *kn, char *path) | ||
| 31 | { | ||
| 32 | if (kn->parent) { | ||
| 33 | sysfs_pathname(kn->parent, path); | ||
| 34 | strlcat(path, "/", PATH_MAX); | ||
| 35 | } | ||
| 36 | strlcat(path, kn->name, PATH_MAX); | ||
| 37 | return path; | ||
| 38 | } | ||
| 39 | |||
| 40 | void sysfs_warn_dup(struct kernfs_node *parent, const char *name) | 22 | void sysfs_warn_dup(struct kernfs_node *parent, const char *name) |
| 41 | { | 23 | { |
| 42 | char *path; | 24 | char *buf, *path = NULL; |
| 43 | 25 | ||
| 44 | path = kzalloc(PATH_MAX, GFP_KERNEL); | 26 | buf = kzalloc(PATH_MAX, GFP_KERNEL); |
| 45 | if (path) { | 27 | if (buf) |
| 46 | sysfs_pathname(parent, path); | 28 | path = kernfs_path(parent, buf, PATH_MAX); |
| 47 | strlcat(path, "/", PATH_MAX); | ||
| 48 | strlcat(path, name, PATH_MAX); | ||
| 49 | } | ||
| 50 | 29 | ||
| 51 | WARN(1, KERN_WARNING "sysfs: cannot create duplicate filename '%s'\n", | 30 | WARN(1, KERN_WARNING "sysfs: cannot create duplicate filename '%s/%s'\n", |
| 52 | path ? path : name); | 31 | path, name); |
| 53 | 32 | ||
| 54 | kfree(path); | 33 | kfree(buf); |
| 55 | } | 34 | } |
| 56 | 35 | ||
| 57 | /** | 36 | /** |
| @@ -122,9 +101,13 @@ void sysfs_remove_dir(struct kobject *kobj) | |||
| 122 | int sysfs_rename_dir_ns(struct kobject *kobj, const char *new_name, | 101 | int sysfs_rename_dir_ns(struct kobject *kobj, const char *new_name, |
| 123 | const void *new_ns) | 102 | const void *new_ns) |
| 124 | { | 103 | { |
| 125 | struct kernfs_node *parent = kobj->sd->parent; | 104 | struct kernfs_node *parent; |
| 105 | int ret; | ||
| 126 | 106 | ||
| 127 | return kernfs_rename_ns(kobj->sd, parent, new_name, new_ns); | 107 | parent = kernfs_get_parent(kobj->sd); |
| 108 | ret = kernfs_rename_ns(kobj->sd, parent, new_name, new_ns); | ||
| 109 | kernfs_put(parent); | ||
| 110 | return ret; | ||
| 128 | } | 111 | } |
| 129 | 112 | ||
| 130 | int sysfs_move_dir_ns(struct kobject *kobj, struct kobject *new_parent_kobj, | 113 | int sysfs_move_dir_ns(struct kobject *kobj, struct kobject *new_parent_kobj, |
| @@ -133,7 +116,6 @@ int sysfs_move_dir_ns(struct kobject *kobj, struct kobject *new_parent_kobj, | |||
| 133 | struct kernfs_node *kn = kobj->sd; | 116 | struct kernfs_node *kn = kobj->sd; |
| 134 | struct kernfs_node *new_parent; | 117 | struct kernfs_node *new_parent; |
| 135 | 118 | ||
| 136 | BUG_ON(!kn->parent); | ||
| 137 | new_parent = new_parent_kobj && new_parent_kobj->sd ? | 119 | new_parent = new_parent_kobj && new_parent_kobj->sd ? |
| 138 | new_parent_kobj->sd : sysfs_root_kn; | 120 | new_parent_kobj->sd : sysfs_root_kn; |
| 139 | 121 | ||
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 810cf6e613e5..1b8b91b67fdb 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
| @@ -372,6 +372,29 @@ void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr, | |||
| 372 | } | 372 | } |
| 373 | EXPORT_SYMBOL_GPL(sysfs_remove_file_ns); | 373 | EXPORT_SYMBOL_GPL(sysfs_remove_file_ns); |
| 374 | 374 | ||
| 375 | /** | ||
| 376 | * sysfs_remove_file_self - remove an object attribute from its own method | ||
| 377 | * @kobj: object we're acting for | ||
| 378 | * @attr: attribute descriptor | ||
| 379 | * | ||
| 380 | * See kernfs_remove_self() for details. | ||
| 381 | */ | ||
| 382 | bool sysfs_remove_file_self(struct kobject *kobj, const struct attribute *attr) | ||
| 383 | { | ||
| 384 | struct kernfs_node *parent = kobj->sd; | ||
| 385 | struct kernfs_node *kn; | ||
| 386 | bool ret; | ||
| 387 | |||
| 388 | kn = kernfs_find_and_get(parent, attr->name); | ||
| 389 | if (WARN_ON_ONCE(!kn)) | ||
| 390 | return false; | ||
| 391 | |||
| 392 | ret = kernfs_remove_self(kn); | ||
| 393 | |||
| 394 | kernfs_put(kn); | ||
| 395 | return ret; | ||
| 396 | } | ||
| 397 | |||
| 375 | void sysfs_remove_files(struct kobject *kobj, const struct attribute **ptr) | 398 | void sysfs_remove_files(struct kobject *kobj, const struct attribute **ptr) |
| 376 | { | 399 | { |
| 377 | int i; | 400 | int i; |
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index 6b579387c67a..aa0406895b53 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c | |||
| @@ -70,8 +70,11 @@ static int create_files(struct kernfs_node *parent, struct kobject *kobj, | |||
| 70 | if (grp->bin_attrs) { | 70 | if (grp->bin_attrs) { |
| 71 | for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++) { | 71 | for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++) { |
| 72 | if (update) | 72 | if (update) |
| 73 | sysfs_remove_bin_file(kobj, *bin_attr); | 73 | kernfs_remove_by_name(parent, |
| 74 | error = sysfs_create_bin_file(kobj, *bin_attr); | 74 | (*bin_attr)->attr.name); |
| 75 | error = sysfs_add_file_mode_ns(parent, | ||
| 76 | &(*bin_attr)->attr, true, | ||
| 77 | (*bin_attr)->attr.mode, NULL); | ||
| 75 | if (error) | 78 | if (error) |
| 76 | break; | 79 | break; |
| 77 | } | 80 | } |
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 3eaf5c6622eb..a66ad6196f59 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c | |||
| @@ -63,7 +63,7 @@ int __init sysfs_init(void) | |||
| 63 | { | 63 | { |
| 64 | int err; | 64 | int err; |
| 65 | 65 | ||
| 66 | sysfs_root = kernfs_create_root(NULL, NULL); | 66 | sysfs_root = kernfs_create_root(NULL, 0, NULL); |
| 67 | if (IS_ERR(sysfs_root)) | 67 | if (IS_ERR(sysfs_root)) |
| 68 | return PTR_ERR(sysfs_root); | 68 | return PTR_ERR(sysfs_root); |
| 69 | 69 | ||
diff --git a/include/linux/cpu.h b/include/linux/cpu.h index 03e235ad1bba..03e962e23eaf 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h | |||
| @@ -46,13 +46,6 @@ extern ssize_t arch_cpu_release(const char *, size_t); | |||
| 46 | #endif | 46 | #endif |
| 47 | struct notifier_block; | 47 | struct notifier_block; |
| 48 | 48 | ||
| 49 | #ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE | ||
| 50 | extern int arch_cpu_uevent(struct device *dev, struct kobj_uevent_env *env); | ||
| 51 | extern ssize_t arch_print_cpu_modalias(struct device *dev, | ||
| 52 | struct device_attribute *attr, | ||
| 53 | char *bufptr); | ||
| 54 | #endif | ||
| 55 | |||
| 56 | /* | 49 | /* |
| 57 | * CPU notifier priorities. | 50 | * CPU notifier priorities. |
| 58 | */ | 51 | */ |
diff --git a/include/linux/cpufeature.h b/include/linux/cpufeature.h new file mode 100644 index 000000000000..c4d4eb8ac9fe --- /dev/null +++ b/include/linux/cpufeature.h | |||
| @@ -0,0 +1,60 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org> | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License version 2 as | ||
| 6 | * published by the Free Software Foundation. | ||
| 7 | */ | ||
| 8 | |||
| 9 | #ifndef __LINUX_CPUFEATURE_H | ||
| 10 | #define __LINUX_CPUFEATURE_H | ||
| 11 | |||
| 12 | #ifdef CONFIG_GENERIC_CPU_AUTOPROBE | ||
| 13 | |||
| 14 | #include <linux/mod_devicetable.h> | ||
| 15 | #include <asm/cpufeature.h> | ||
| 16 | |||
| 17 | /* | ||
| 18 | * Macros imported from <asm/cpufeature.h>: | ||
| 19 | * - cpu_feature(x) ordinal value of feature called 'x' | ||
| 20 | * - cpu_have_feature(u32 n) whether feature #n is available | ||
| 21 | * - MAX_CPU_FEATURES upper bound for feature ordinal values | ||
| 22 | * Optional: | ||
| 23 | * - CPU_FEATURE_TYPEFMT format string fragment for printing the cpu type | ||
| 24 | * - CPU_FEATURE_TYPEVAL set of values matching the format string above | ||
| 25 | */ | ||
| 26 | |||
| 27 | #ifndef CPU_FEATURE_TYPEFMT | ||
| 28 | #define CPU_FEATURE_TYPEFMT "%s" | ||
| 29 | #endif | ||
| 30 | |||
| 31 | #ifndef CPU_FEATURE_TYPEVAL | ||
| 32 | #define CPU_FEATURE_TYPEVAL ELF_PLATFORM | ||
| 33 | #endif | ||
| 34 | |||
| 35 | /* | ||
| 36 | * Use module_cpu_feature_match(feature, module_init_function) to | ||
| 37 | * declare that | ||
| 38 | * a) the module shall be probed upon discovery of CPU feature 'feature' | ||
| 39 | * (typically at boot time using udev) | ||
| 40 | * b) the module must not be loaded if CPU feature 'feature' is not present | ||
| 41 | * (not even by manual insmod). | ||
| 42 | * | ||
| 43 | * For a list of legal values for 'feature', please consult the file | ||
| 44 | * 'asm/cpufeature.h' of your favorite architecture. | ||
| 45 | */ | ||
| 46 | #define module_cpu_feature_match(x, __init) \ | ||
| 47 | static struct cpu_feature const cpu_feature_match_ ## x[] = \ | ||
| 48 | { { .feature = cpu_feature(x) }, { } }; \ | ||
| 49 | MODULE_DEVICE_TABLE(cpu, cpu_feature_match_ ## x); \ | ||
| 50 | \ | ||
| 51 | static int cpu_feature_match_ ## x ## _init(void) \ | ||
| 52 | { \ | ||
| 53 | if (!cpu_have_feature(cpu_feature(x))) \ | ||
| 54 | return -ENODEV; \ | ||
| 55 | return __init(); \ | ||
| 56 | } \ | ||
| 57 | module_init(cpu_feature_match_ ## x ## _init) | ||
| 58 | |||
| 59 | #endif | ||
| 60 | #endif | ||
diff --git a/include/linux/device.h b/include/linux/device.h index ec1b6e21f0ef..233bbbeb768d 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
| @@ -560,6 +560,8 @@ extern int device_create_file(struct device *device, | |||
| 560 | const struct device_attribute *entry); | 560 | const struct device_attribute *entry); |
| 561 | extern void device_remove_file(struct device *dev, | 561 | extern void device_remove_file(struct device *dev, |
| 562 | const struct device_attribute *attr); | 562 | const struct device_attribute *attr); |
| 563 | extern bool device_remove_file_self(struct device *dev, | ||
| 564 | const struct device_attribute *attr); | ||
| 563 | extern int __must_check device_create_bin_file(struct device *dev, | 565 | extern int __must_check device_create_bin_file(struct device *dev, |
| 564 | const struct bin_attribute *attr); | 566 | const struct bin_attribute *attr); |
| 565 | extern void device_remove_bin_file(struct device *dev, | 567 | extern void device_remove_bin_file(struct device *dev, |
diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h index d267623c28cf..b0122dc6f96a 100644 --- a/include/linux/kernfs.h +++ b/include/linux/kernfs.h | |||
| @@ -15,7 +15,7 @@ | |||
| 15 | #include <linux/lockdep.h> | 15 | #include <linux/lockdep.h> |
| 16 | #include <linux/rbtree.h> | 16 | #include <linux/rbtree.h> |
| 17 | #include <linux/atomic.h> | 17 | #include <linux/atomic.h> |
| 18 | #include <linux/completion.h> | 18 | #include <linux/wait.h> |
| 19 | 19 | ||
| 20 | struct file; | 20 | struct file; |
| 21 | struct dentry; | 21 | struct dentry; |
| @@ -35,16 +35,22 @@ enum kernfs_node_type { | |||
| 35 | }; | 35 | }; |
| 36 | 36 | ||
| 37 | #define KERNFS_TYPE_MASK 0x000f | 37 | #define KERNFS_TYPE_MASK 0x000f |
| 38 | #define KERNFS_ACTIVE_REF KERNFS_FILE | ||
| 39 | #define KERNFS_FLAG_MASK ~KERNFS_TYPE_MASK | 38 | #define KERNFS_FLAG_MASK ~KERNFS_TYPE_MASK |
| 40 | 39 | ||
| 41 | enum kernfs_node_flag { | 40 | enum kernfs_node_flag { |
| 42 | KERNFS_REMOVED = 0x0010, | 41 | KERNFS_ACTIVATED = 0x0010, |
| 43 | KERNFS_NS = 0x0020, | 42 | KERNFS_NS = 0x0020, |
| 44 | KERNFS_HAS_SEQ_SHOW = 0x0040, | 43 | KERNFS_HAS_SEQ_SHOW = 0x0040, |
| 45 | KERNFS_HAS_MMAP = 0x0080, | 44 | KERNFS_HAS_MMAP = 0x0080, |
| 46 | KERNFS_LOCKDEP = 0x0100, | 45 | KERNFS_LOCKDEP = 0x0100, |
| 47 | KERNFS_STATIC_NAME = 0x0200, | 46 | KERNFS_STATIC_NAME = 0x0200, |
| 47 | KERNFS_SUICIDAL = 0x0400, | ||
| 48 | KERNFS_SUICIDED = 0x0800, | ||
| 49 | }; | ||
| 50 | |||
| 51 | /* @flags for kernfs_create_root() */ | ||
| 52 | enum kernfs_root_flag { | ||
| 53 | KERNFS_ROOT_CREATE_DEACTIVATED = 0x0001, | ||
| 48 | }; | 54 | }; |
| 49 | 55 | ||
| 50 | /* type-specific structures for kernfs_node union members */ | 56 | /* type-specific structures for kernfs_node union members */ |
| @@ -85,17 +91,17 @@ struct kernfs_node { | |||
| 85 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 91 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
| 86 | struct lockdep_map dep_map; | 92 | struct lockdep_map dep_map; |
| 87 | #endif | 93 | #endif |
| 88 | /* the following two fields are published */ | 94 | /* |
| 95 | * Use kernfs_get_parent() and kernfs_name/path() instead of | ||
| 96 | * accessing the following two fields directly. If the node is | ||
| 97 | * never moved to a different parent, it is safe to access the | ||
| 98 | * parent directly. | ||
| 99 | */ | ||
| 89 | struct kernfs_node *parent; | 100 | struct kernfs_node *parent; |
| 90 | const char *name; | 101 | const char *name; |
| 91 | 102 | ||
| 92 | struct rb_node rb; | 103 | struct rb_node rb; |
| 93 | 104 | ||
| 94 | union { | ||
| 95 | struct completion *completion; | ||
| 96 | struct kernfs_node *removed_list; | ||
| 97 | } u; | ||
| 98 | |||
| 99 | const void *ns; /* namespace tag */ | 105 | const void *ns; /* namespace tag */ |
| 100 | unsigned int hash; /* ns + name hash */ | 106 | unsigned int hash; /* ns + name hash */ |
| 101 | union { | 107 | union { |
| @@ -113,12 +119,16 @@ struct kernfs_node { | |||
| 113 | }; | 119 | }; |
| 114 | 120 | ||
| 115 | /* | 121 | /* |
| 116 | * kernfs_dir_ops may be specified on kernfs_create_root() to support | 122 | * kernfs_syscall_ops may be specified on kernfs_create_root() to support |
| 117 | * directory manipulation syscalls. These optional callbacks are invoked | 123 | * syscalls. These optional callbacks are invoked on the matching syscalls |
| 118 | * on the matching syscalls and can perform any kernfs operations which | 124 | * and can perform any kernfs operations which don't necessarily have to be |
| 119 | * don't necessarily have to be the exact operation requested. | 125 | * the exact operation requested. An active reference is held for each |
| 126 | * kernfs_node parameter. | ||
| 120 | */ | 127 | */ |
| 121 | struct kernfs_dir_ops { | 128 | struct kernfs_syscall_ops { |
| 129 | int (*remount_fs)(struct kernfs_root *root, int *flags, char *data); | ||
| 130 | int (*show_options)(struct seq_file *sf, struct kernfs_root *root); | ||
| 131 | |||
| 122 | int (*mkdir)(struct kernfs_node *parent, const char *name, | 132 | int (*mkdir)(struct kernfs_node *parent, const char *name, |
| 123 | umode_t mode); | 133 | umode_t mode); |
| 124 | int (*rmdir)(struct kernfs_node *kn); | 134 | int (*rmdir)(struct kernfs_node *kn); |
| @@ -129,22 +139,26 @@ struct kernfs_dir_ops { | |||
| 129 | struct kernfs_root { | 139 | struct kernfs_root { |
| 130 | /* published fields */ | 140 | /* published fields */ |
| 131 | struct kernfs_node *kn; | 141 | struct kernfs_node *kn; |
| 142 | unsigned int flags; /* KERNFS_ROOT_* flags */ | ||
| 132 | 143 | ||
| 133 | /* private fields, do not use outside kernfs proper */ | 144 | /* private fields, do not use outside kernfs proper */ |
| 134 | struct ida ino_ida; | 145 | struct ida ino_ida; |
| 135 | struct kernfs_dir_ops *dir_ops; | 146 | struct kernfs_syscall_ops *syscall_ops; |
| 147 | wait_queue_head_t deactivate_waitq; | ||
| 136 | }; | 148 | }; |
| 137 | 149 | ||
| 138 | struct kernfs_open_file { | 150 | struct kernfs_open_file { |
| 139 | /* published fields */ | 151 | /* published fields */ |
| 140 | struct kernfs_node *kn; | 152 | struct kernfs_node *kn; |
| 141 | struct file *file; | 153 | struct file *file; |
| 154 | void *priv; | ||
| 142 | 155 | ||
| 143 | /* private fields, do not use outside kernfs proper */ | 156 | /* private fields, do not use outside kernfs proper */ |
| 144 | struct mutex mutex; | 157 | struct mutex mutex; |
| 145 | int event; | 158 | int event; |
| 146 | struct list_head list; | 159 | struct list_head list; |
| 147 | 160 | ||
| 161 | size_t atomic_write_len; | ||
| 148 | bool mmapped; | 162 | bool mmapped; |
| 149 | const struct vm_operations_struct *vm_ops; | 163 | const struct vm_operations_struct *vm_ops; |
| 150 | }; | 164 | }; |
| @@ -171,9 +185,13 @@ struct kernfs_ops { | |||
| 171 | loff_t off); | 185 | loff_t off); |
| 172 | 186 | ||
| 173 | /* | 187 | /* |
| 174 | * write() is bounced through kernel buffer and a write larger than | 188 | * write() is bounced through kernel buffer. If atomic_write_len |
| 175 | * PAGE_SIZE results in partial operation of PAGE_SIZE. | 189 | * is not set, a write larger than PAGE_SIZE results in partial |
| 190 | * operations of PAGE_SIZE chunks. If atomic_write_len is set, | ||
| 191 | * writes upto the specified size are executed atomically but | ||
| 192 | * larger ones are rejected with -E2BIG. | ||
| 176 | */ | 193 | */ |
| 194 | size_t atomic_write_len; | ||
| 177 | ssize_t (*write)(struct kernfs_open_file *of, char *buf, size_t bytes, | 195 | ssize_t (*write)(struct kernfs_open_file *of, char *buf, size_t bytes, |
| 178 | loff_t off); | 196 | loff_t off); |
| 179 | 197 | ||
| @@ -184,7 +202,7 @@ struct kernfs_ops { | |||
| 184 | #endif | 202 | #endif |
| 185 | }; | 203 | }; |
| 186 | 204 | ||
| 187 | #ifdef CONFIG_SYSFS | 205 | #ifdef CONFIG_KERNFS |
| 188 | 206 | ||
| 189 | static inline enum kernfs_node_type kernfs_type(struct kernfs_node *kn) | 207 | static inline enum kernfs_node_type kernfs_type(struct kernfs_node *kn) |
| 190 | { | 208 | { |
| @@ -217,13 +235,22 @@ static inline bool kernfs_ns_enabled(struct kernfs_node *kn) | |||
| 217 | return kn->flags & KERNFS_NS; | 235 | return kn->flags & KERNFS_NS; |
| 218 | } | 236 | } |
| 219 | 237 | ||
| 238 | int kernfs_name(struct kernfs_node *kn, char *buf, size_t buflen); | ||
| 239 | char * __must_check kernfs_path(struct kernfs_node *kn, char *buf, | ||
| 240 | size_t buflen); | ||
| 241 | void pr_cont_kernfs_name(struct kernfs_node *kn); | ||
| 242 | void pr_cont_kernfs_path(struct kernfs_node *kn); | ||
| 243 | struct kernfs_node *kernfs_get_parent(struct kernfs_node *kn); | ||
| 220 | struct kernfs_node *kernfs_find_and_get_ns(struct kernfs_node *parent, | 244 | struct kernfs_node *kernfs_find_and_get_ns(struct kernfs_node *parent, |
| 221 | const char *name, const void *ns); | 245 | const char *name, const void *ns); |
| 222 | void kernfs_get(struct kernfs_node *kn); | 246 | void kernfs_get(struct kernfs_node *kn); |
| 223 | void kernfs_put(struct kernfs_node *kn); | 247 | void kernfs_put(struct kernfs_node *kn); |
| 224 | 248 | ||
| 225 | struct kernfs_root *kernfs_create_root(struct kernfs_dir_ops *kdops, | 249 | struct kernfs_node *kernfs_node_from_dentry(struct dentry *dentry); |
| 226 | void *priv); | 250 | struct kernfs_root *kernfs_root_from_sb(struct super_block *sb); |
| 251 | |||
| 252 | struct kernfs_root *kernfs_create_root(struct kernfs_syscall_ops *scops, | ||
| 253 | unsigned int flags, void *priv); | ||
| 227 | void kernfs_destroy_root(struct kernfs_root *root); | 254 | void kernfs_destroy_root(struct kernfs_root *root); |
| 228 | 255 | ||
| 229 | struct kernfs_node *kernfs_create_dir_ns(struct kernfs_node *parent, | 256 | struct kernfs_node *kernfs_create_dir_ns(struct kernfs_node *parent, |
| @@ -239,7 +266,11 @@ struct kernfs_node *__kernfs_create_file(struct kernfs_node *parent, | |||
| 239 | struct kernfs_node *kernfs_create_link(struct kernfs_node *parent, | 266 | struct kernfs_node *kernfs_create_link(struct kernfs_node *parent, |
| 240 | const char *name, | 267 | const char *name, |
| 241 | struct kernfs_node *target); | 268 | struct kernfs_node *target); |
| 269 | void kernfs_activate(struct kernfs_node *kn); | ||
| 242 | void kernfs_remove(struct kernfs_node *kn); | 270 | void kernfs_remove(struct kernfs_node *kn); |
| 271 | void kernfs_break_active_protection(struct kernfs_node *kn); | ||
| 272 | void kernfs_unbreak_active_protection(struct kernfs_node *kn); | ||
| 273 | bool kernfs_remove_self(struct kernfs_node *kn); | ||
| 243 | int kernfs_remove_by_name_ns(struct kernfs_node *parent, const char *name, | 274 | int kernfs_remove_by_name_ns(struct kernfs_node *parent, const char *name, |
| 244 | const void *ns); | 275 | const void *ns); |
| 245 | int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent, | 276 | int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent, |
| @@ -255,7 +286,7 @@ void kernfs_kill_sb(struct super_block *sb); | |||
| 255 | 286 | ||
| 256 | void kernfs_init(void); | 287 | void kernfs_init(void); |
| 257 | 288 | ||
| 258 | #else /* CONFIG_SYSFS */ | 289 | #else /* CONFIG_KERNFS */ |
| 259 | 290 | ||
| 260 | static inline enum kernfs_node_type kernfs_type(struct kernfs_node *kn) | 291 | static inline enum kernfs_node_type kernfs_type(struct kernfs_node *kn) |
| 261 | { return 0; } /* whatever */ | 292 | { return 0; } /* whatever */ |
| @@ -265,6 +296,19 @@ static inline void kernfs_enable_ns(struct kernfs_node *kn) { } | |||
| 265 | static inline bool kernfs_ns_enabled(struct kernfs_node *kn) | 296 | static inline bool kernfs_ns_enabled(struct kernfs_node *kn) |
| 266 | { return false; } | 297 | { return false; } |
| 267 | 298 | ||
| 299 | static inline int kernfs_name(struct kernfs_node *kn, char *buf, size_t buflen) | ||
| 300 | { return -ENOSYS; } | ||
| 301 | |||
| 302 | static inline char * __must_check kernfs_path(struct kernfs_node *kn, char *buf, | ||
| 303 | size_t buflen) | ||
| 304 | { return NULL; } | ||
| 305 | |||
| 306 | static inline void pr_cont_kernfs_name(struct kernfs_node *kn) { } | ||
| 307 | static inline void pr_cont_kernfs_path(struct kernfs_node *kn) { } | ||
| 308 | |||
| 309 | static inline struct kernfs_node *kernfs_get_parent(struct kernfs_node *kn) | ||
| 310 | { return NULL; } | ||
| 311 | |||
| 268 | static inline struct kernfs_node * | 312 | static inline struct kernfs_node * |
| 269 | kernfs_find_and_get_ns(struct kernfs_node *parent, const char *name, | 313 | kernfs_find_and_get_ns(struct kernfs_node *parent, const char *name, |
| 270 | const void *ns) | 314 | const void *ns) |
| @@ -273,8 +317,15 @@ kernfs_find_and_get_ns(struct kernfs_node *parent, const char *name, | |||
| 273 | static inline void kernfs_get(struct kernfs_node *kn) { } | 317 | static inline void kernfs_get(struct kernfs_node *kn) { } |
| 274 | static inline void kernfs_put(struct kernfs_node *kn) { } | 318 | static inline void kernfs_put(struct kernfs_node *kn) { } |
| 275 | 319 | ||
| 320 | static inline struct kernfs_node *kernfs_node_from_dentry(struct dentry *dentry) | ||
| 321 | { return NULL; } | ||
| 322 | |||
| 323 | static inline struct kernfs_root *kernfs_root_from_sb(struct super_block *sb) | ||
| 324 | { return NULL; } | ||
| 325 | |||
| 276 | static inline struct kernfs_root * | 326 | static inline struct kernfs_root * |
| 277 | kernfs_create_root(struct kernfs_dir_ops *kdops, void *priv) | 327 | kernfs_create_root(struct kernfs_syscall_ops *scops, unsigned int flags, |
| 328 | void *priv) | ||
| 278 | { return ERR_PTR(-ENOSYS); } | 329 | { return ERR_PTR(-ENOSYS); } |
| 279 | 330 | ||
| 280 | static inline void kernfs_destroy_root(struct kernfs_root *root) { } | 331 | static inline void kernfs_destroy_root(struct kernfs_root *root) { } |
| @@ -296,8 +347,13 @@ kernfs_create_link(struct kernfs_node *parent, const char *name, | |||
| 296 | struct kernfs_node *target) | 347 | struct kernfs_node *target) |
| 297 | { return ERR_PTR(-ENOSYS); } | 348 | { return ERR_PTR(-ENOSYS); } |
| 298 | 349 | ||
| 350 | static inline void kernfs_activate(struct kernfs_node *kn) { } | ||
| 351 | |||
| 299 | static inline void kernfs_remove(struct kernfs_node *kn) { } | 352 | static inline void kernfs_remove(struct kernfs_node *kn) { } |
| 300 | 353 | ||
| 354 | static inline bool kernfs_remove_self(struct kernfs_node *kn) | ||
| 355 | { return false; } | ||
| 356 | |||
| 301 | static inline int kernfs_remove_by_name_ns(struct kernfs_node *kn, | 357 | static inline int kernfs_remove_by_name_ns(struct kernfs_node *kn, |
| 302 | const char *name, const void *ns) | 358 | const char *name, const void *ns) |
| 303 | { return -ENOSYS; } | 359 | { return -ENOSYS; } |
| @@ -325,7 +381,7 @@ static inline void kernfs_kill_sb(struct super_block *sb) { } | |||
| 325 | 381 | ||
| 326 | static inline void kernfs_init(void) { } | 382 | static inline void kernfs_init(void) { } |
| 327 | 383 | ||
| 328 | #endif /* CONFIG_SYSFS */ | 384 | #endif /* CONFIG_KERNFS */ |
| 329 | 385 | ||
| 330 | static inline struct kernfs_node * | 386 | static inline struct kernfs_node * |
| 331 | kernfs_find_and_get(struct kernfs_node *kn, const char *name) | 387 | kernfs_find_and_get(struct kernfs_node *kn, const char *name) |
| @@ -367,6 +423,13 @@ static inline int kernfs_remove_by_name(struct kernfs_node *parent, | |||
| 367 | return kernfs_remove_by_name_ns(parent, name, NULL); | 423 | return kernfs_remove_by_name_ns(parent, name, NULL); |
| 368 | } | 424 | } |
| 369 | 425 | ||
| 426 | static inline int kernfs_rename(struct kernfs_node *kn, | ||
| 427 | struct kernfs_node *new_parent, | ||
| 428 | const char *new_name) | ||
| 429 | { | ||
| 430 | return kernfs_rename_ns(kn, new_parent, new_name, NULL); | ||
| 431 | } | ||
| 432 | |||
| 370 | static inline struct dentry * | 433 | static inline struct dentry * |
| 371 | kernfs_mount(struct file_system_type *fs_type, int flags, | 434 | kernfs_mount(struct file_system_type *fs_type, int flags, |
| 372 | struct kernfs_root *root, bool *new_sb_created) | 435 | struct kernfs_root *root, bool *new_sb_created) |
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index 50f67eff27ef..9a165a213d93 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h | |||
| @@ -572,6 +572,15 @@ struct x86_cpu_id { | |||
| 572 | #define X86_MODEL_ANY 0 | 572 | #define X86_MODEL_ANY 0 |
| 573 | #define X86_FEATURE_ANY 0 /* Same as FPU, you can't test for that */ | 573 | #define X86_FEATURE_ANY 0 /* Same as FPU, you can't test for that */ |
| 574 | 574 | ||
| 575 | /* | ||
| 576 | * Generic table type for matching CPU features. | ||
| 577 | * @feature: the bit number of the feature (0 - 65535) | ||
| 578 | */ | ||
| 579 | |||
| 580 | struct cpu_feature { | ||
| 581 | __u16 feature; | ||
| 582 | }; | ||
| 583 | |||
| 575 | #define IPACK_ANY_FORMAT 0xff | 584 | #define IPACK_ANY_FORMAT 0xff |
| 576 | #define IPACK_ANY_ID (~0) | 585 | #define IPACK_ANY_ID (~0) |
| 577 | struct ipack_device_id { | 586 | struct ipack_device_id { |
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 30b2ebee6439..e0bf210ddffd 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h | |||
| @@ -198,6 +198,7 @@ int __must_check sysfs_chmod_file(struct kobject *kobj, | |||
| 198 | const struct attribute *attr, umode_t mode); | 198 | const struct attribute *attr, umode_t mode); |
| 199 | void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr, | 199 | void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr, |
| 200 | const void *ns); | 200 | const void *ns); |
| 201 | bool sysfs_remove_file_self(struct kobject *kobj, const struct attribute *attr); | ||
| 201 | void sysfs_remove_files(struct kobject *kobj, const struct attribute **attr); | 202 | void sysfs_remove_files(struct kobject *kobj, const struct attribute **attr); |
| 202 | 203 | ||
| 203 | int __must_check sysfs_create_bin_file(struct kobject *kobj, | 204 | int __must_check sysfs_create_bin_file(struct kobject *kobj, |
| @@ -246,6 +247,11 @@ void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr); | |||
| 246 | 247 | ||
| 247 | int __must_check sysfs_init(void); | 248 | int __must_check sysfs_init(void); |
| 248 | 249 | ||
| 250 | static inline void sysfs_enable_ns(struct kernfs_node *kn) | ||
| 251 | { | ||
| 252 | return kernfs_enable_ns(kn); | ||
| 253 | } | ||
| 254 | |||
| 249 | #else /* CONFIG_SYSFS */ | 255 | #else /* CONFIG_SYSFS */ |
| 250 | 256 | ||
| 251 | static inline int sysfs_schedule_callback(struct kobject *kobj, | 257 | static inline int sysfs_schedule_callback(struct kobject *kobj, |
| @@ -301,6 +307,12 @@ static inline void sysfs_remove_file_ns(struct kobject *kobj, | |||
| 301 | { | 307 | { |
| 302 | } | 308 | } |
| 303 | 309 | ||
| 310 | static inline bool sysfs_remove_file_self(struct kobject *kobj, | ||
| 311 | const struct attribute *attr) | ||
| 312 | { | ||
| 313 | return false; | ||
| 314 | } | ||
| 315 | |||
| 304 | static inline void sysfs_remove_files(struct kobject *kobj, | 316 | static inline void sysfs_remove_files(struct kobject *kobj, |
| 305 | const struct attribute **attr) | 317 | const struct attribute **attr) |
| 306 | { | 318 | { |
| @@ -418,6 +430,10 @@ static inline int __must_check sysfs_init(void) | |||
| 418 | return 0; | 430 | return 0; |
| 419 | } | 431 | } |
| 420 | 432 | ||
| 433 | static inline void sysfs_enable_ns(struct kernfs_node *kn) | ||
| 434 | { | ||
| 435 | } | ||
| 436 | |||
| 421 | #endif /* CONFIG_SYSFS */ | 437 | #endif /* CONFIG_SYSFS */ |
| 422 | 438 | ||
| 423 | static inline int __must_check sysfs_create_file(struct kobject *kobj, | 439 | static inline int __must_check sysfs_create_file(struct kobject *kobj, |
diff --git a/lib/kobject.c b/lib/kobject.c index cb14aeac4cca..58751bb80a7c 100644 --- a/lib/kobject.c +++ b/lib/kobject.c | |||
| @@ -94,7 +94,7 @@ static int create_dir(struct kobject *kobj) | |||
| 94 | BUG_ON(ops->type >= KOBJ_NS_TYPES); | 94 | BUG_ON(ops->type >= KOBJ_NS_TYPES); |
| 95 | BUG_ON(!kobj_ns_type_registered(ops->type)); | 95 | BUG_ON(!kobj_ns_type_registered(ops->type)); |
| 96 | 96 | ||
| 97 | kernfs_enable_ns(kobj->sd); | 97 | sysfs_enable_ns(kobj->sd); |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | return 0; | 100 | return 0; |
diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c index bb5d115ca671..f282516acc7b 100644 --- a/scripts/mod/devicetable-offsets.c +++ b/scripts/mod/devicetable-offsets.c | |||
| @@ -174,6 +174,9 @@ int main(void) | |||
| 174 | DEVID_FIELD(x86_cpu_id, model); | 174 | DEVID_FIELD(x86_cpu_id, model); |
| 175 | DEVID_FIELD(x86_cpu_id, vendor); | 175 | DEVID_FIELD(x86_cpu_id, vendor); |
| 176 | 176 | ||
| 177 | DEVID(cpu_feature); | ||
| 178 | DEVID_FIELD(cpu_feature, feature); | ||
| 179 | |||
| 177 | DEVID(mei_cl_device_id); | 180 | DEVID(mei_cl_device_id); |
| 178 | DEVID_FIELD(mei_cl_device_id, name); | 181 | DEVID_FIELD(mei_cl_device_id, name); |
| 179 | 182 | ||
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 25e5cb0aaef6..25f6f5970552 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c | |||
| @@ -1110,7 +1110,7 @@ static int do_amba_entry(const char *filename, | |||
| 1110 | } | 1110 | } |
| 1111 | ADD_TO_DEVTABLE("amba", amba_id, do_amba_entry); | 1111 | ADD_TO_DEVTABLE("amba", amba_id, do_amba_entry); |
| 1112 | 1112 | ||
| 1113 | /* LOOKS like x86cpu:vendor:VVVV:family:FFFF:model:MMMM:feature:*,FEAT,* | 1113 | /* LOOKS like cpu:type:x86,venVVVVfamFFFFmodMMMM:feature:*,FEAT,* |
| 1114 | * All fields are numbers. It would be nicer to use strings for vendor | 1114 | * All fields are numbers. It would be nicer to use strings for vendor |
| 1115 | * and feature, but getting those out of the build system here is too | 1115 | * and feature, but getting those out of the build system here is too |
| 1116 | * complicated. | 1116 | * complicated. |
| @@ -1124,10 +1124,10 @@ static int do_x86cpu_entry(const char *filename, void *symval, | |||
| 1124 | DEF_FIELD(symval, x86_cpu_id, model); | 1124 | DEF_FIELD(symval, x86_cpu_id, model); |
| 1125 | DEF_FIELD(symval, x86_cpu_id, vendor); | 1125 | DEF_FIELD(symval, x86_cpu_id, vendor); |
| 1126 | 1126 | ||
| 1127 | strcpy(alias, "x86cpu:"); | 1127 | strcpy(alias, "cpu:type:x86,"); |
| 1128 | ADD(alias, "vendor:", vendor != X86_VENDOR_ANY, vendor); | 1128 | ADD(alias, "ven", vendor != X86_VENDOR_ANY, vendor); |
| 1129 | ADD(alias, ":family:", family != X86_FAMILY_ANY, family); | 1129 | ADD(alias, "fam", family != X86_FAMILY_ANY, family); |
| 1130 | ADD(alias, ":model:", model != X86_MODEL_ANY, model); | 1130 | ADD(alias, "mod", model != X86_MODEL_ANY, model); |
| 1131 | strcat(alias, ":feature:*"); | 1131 | strcat(alias, ":feature:*"); |
| 1132 | if (feature != X86_FEATURE_ANY) | 1132 | if (feature != X86_FEATURE_ANY) |
| 1133 | sprintf(alias + strlen(alias), "%04X*", feature); | 1133 | sprintf(alias + strlen(alias), "%04X*", feature); |
| @@ -1135,6 +1135,16 @@ static int do_x86cpu_entry(const char *filename, void *symval, | |||
| 1135 | } | 1135 | } |
| 1136 | ADD_TO_DEVTABLE("x86cpu", x86_cpu_id, do_x86cpu_entry); | 1136 | ADD_TO_DEVTABLE("x86cpu", x86_cpu_id, do_x86cpu_entry); |
| 1137 | 1137 | ||
| 1138 | /* LOOKS like cpu:type:*:feature:*FEAT* */ | ||
| 1139 | static int do_cpu_entry(const char *filename, void *symval, char *alias) | ||
| 1140 | { | ||
| 1141 | DEF_FIELD(symval, cpu_feature, feature); | ||
| 1142 | |||
| 1143 | sprintf(alias, "cpu:type:*:feature:*%04X*", feature); | ||
| 1144 | return 1; | ||
| 1145 | } | ||
| 1146 | ADD_TO_DEVTABLE("cpu", cpu_feature, do_cpu_entry); | ||
| 1147 | |||
| 1138 | /* Looks like: mei:S */ | 1148 | /* Looks like: mei:S */ |
| 1139 | static int do_mei_entry(const char *filename, void *symval, | 1149 | static int do_mei_entry(const char *filename, void *symval, |
| 1140 | char *alias) | 1150 | char *alias) |
