diff options
| -rw-r--r-- | arch/s390/Kconfig.debug | 12 | ||||
| -rw-r--r-- | arch/s390/include/asm/page.h | 5 | ||||
| -rw-r--r-- | arch/s390/kernel/kprobes.c | 70 | ||||
| -rw-r--r-- | arch/s390/mm/gup.c | 7 | ||||
| -rw-r--r-- | drivers/s390/char/tape_core.c | 68 | ||||
| -rw-r--r-- | drivers/s390/char/vmlogrdr.c | 36 | ||||
| -rw-r--r-- | drivers/s390/cio/device.c | 11 | ||||
| -rw-r--r-- | kernel/sysctl.c | 2 | ||||
| -rw-r--r-- | kernel/trace/Kconfig | 2 |
9 files changed, 168 insertions, 45 deletions
diff --git a/arch/s390/Kconfig.debug b/arch/s390/Kconfig.debug index 45e0c6199f3..05221b13ffb 100644 --- a/arch/s390/Kconfig.debug +++ b/arch/s390/Kconfig.debug | |||
| @@ -6,6 +6,18 @@ config TRACE_IRQFLAGS_SUPPORT | |||
| 6 | 6 | ||
| 7 | source "lib/Kconfig.debug" | 7 | source "lib/Kconfig.debug" |
| 8 | 8 | ||
| 9 | config STRICT_DEVMEM | ||
| 10 | def_bool y | ||
| 11 | prompt "Filter access to /dev/mem" | ||
| 12 | ---help--- | ||
| 13 | This option restricts access to /dev/mem. If this option is | ||
| 14 | disabled, you allow userspace access to all memory, including | ||
| 15 | kernel and userspace memory. Accidental memory access is likely | ||
| 16 | to be disastrous. | ||
| 17 | Memory access is required for experts who want to debug the kernel. | ||
| 18 | |||
| 19 | If you are unsure, say Y. | ||
| 20 | |||
| 9 | config DEBUG_STRICT_USER_COPY_CHECKS | 21 | config DEBUG_STRICT_USER_COPY_CHECKS |
| 10 | bool "Strict user copy size checks" | 22 | bool "Strict user copy size checks" |
| 11 | ---help--- | 23 | ---help--- |
diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h index a8729ea7e9a..3c987e9ec8d 100644 --- a/arch/s390/include/asm/page.h +++ b/arch/s390/include/asm/page.h | |||
| @@ -130,6 +130,11 @@ struct page; | |||
| 130 | void arch_free_page(struct page *page, int order); | 130 | void arch_free_page(struct page *page, int order); |
| 131 | void arch_alloc_page(struct page *page, int order); | 131 | void arch_alloc_page(struct page *page, int order); |
| 132 | 132 | ||
| 133 | static inline int devmem_is_allowed(unsigned long pfn) | ||
| 134 | { | ||
| 135 | return 0; | ||
| 136 | } | ||
| 137 | |||
| 133 | #define HAVE_ARCH_FREE_PAGE | 138 | #define HAVE_ARCH_FREE_PAGE |
| 134 | #define HAVE_ARCH_ALLOC_PAGE | 139 | #define HAVE_ARCH_ALLOC_PAGE |
| 135 | 140 | ||
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c index d60fc439851..2564793ec2b 100644 --- a/arch/s390/kernel/kprobes.c +++ b/arch/s390/kernel/kprobes.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include <asm/sections.h> | 30 | #include <asm/sections.h> |
| 31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
| 32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
| 33 | #include <linux/hardirq.h> | ||
| 33 | 34 | ||
| 34 | DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; | 35 | DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; |
| 35 | DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); | 36 | DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); |
| @@ -212,7 +213,7 @@ static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs) | |||
| 212 | /* Set the PER control regs, turns on single step for this address */ | 213 | /* Set the PER control regs, turns on single step for this address */ |
| 213 | __ctl_load(kprobe_per_regs, 9, 11); | 214 | __ctl_load(kprobe_per_regs, 9, 11); |
| 214 | regs->psw.mask |= PSW_MASK_PER; | 215 | regs->psw.mask |= PSW_MASK_PER; |
| 215 | regs->psw.mask &= ~(PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK); | 216 | regs->psw.mask &= ~(PSW_MASK_IO | PSW_MASK_EXT); |
| 216 | } | 217 | } |
| 217 | 218 | ||
| 218 | static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb) | 219 | static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb) |
| @@ -239,7 +240,7 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs, | |||
| 239 | __get_cpu_var(current_kprobe) = p; | 240 | __get_cpu_var(current_kprobe) = p; |
| 240 | /* Save the interrupt and per flags */ | 241 | /* Save the interrupt and per flags */ |
| 241 | kcb->kprobe_saved_imask = regs->psw.mask & | 242 | kcb->kprobe_saved_imask = regs->psw.mask & |
| 242 | (PSW_MASK_PER | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK); | 243 | (PSW_MASK_PER | PSW_MASK_IO | PSW_MASK_EXT); |
| 243 | /* Save the control regs that govern PER */ | 244 | /* Save the control regs that govern PER */ |
| 244 | __ctl_store(kcb->kprobe_saved_ctl, 9, 11); | 245 | __ctl_store(kcb->kprobe_saved_ctl, 9, 11); |
| 245 | } | 246 | } |
| @@ -316,8 +317,6 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) | |||
| 316 | return 1; | 317 | return 1; |
| 317 | 318 | ||
| 318 | ss_probe: | 319 | ss_probe: |
| 319 | if (regs->psw.mask & (PSW_MASK_PER | PSW_MASK_IO)) | ||
| 320 | local_irq_disable(); | ||
| 321 | prepare_singlestep(p, regs); | 320 | prepare_singlestep(p, regs); |
| 322 | kcb->kprobe_status = KPROBE_HIT_SS; | 321 | kcb->kprobe_status = KPROBE_HIT_SS; |
| 323 | return 1; | 322 | return 1; |
| @@ -350,6 +349,7 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p, | |||
| 350 | struct hlist_node *node, *tmp; | 349 | struct hlist_node *node, *tmp; |
| 351 | unsigned long flags, orig_ret_address = 0; | 350 | unsigned long flags, orig_ret_address = 0; |
| 352 | unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline; | 351 | unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline; |
| 352 | kprobe_opcode_t *correct_ret_addr = NULL; | ||
| 353 | 353 | ||
| 354 | INIT_HLIST_HEAD(&empty_rp); | 354 | INIT_HLIST_HEAD(&empty_rp); |
| 355 | kretprobe_hash_lock(current, &head, &flags); | 355 | kretprobe_hash_lock(current, &head, &flags); |
| @@ -372,10 +372,32 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p, | |||
| 372 | /* another task is sharing our hash bucket */ | 372 | /* another task is sharing our hash bucket */ |
| 373 | continue; | 373 | continue; |
| 374 | 374 | ||
| 375 | if (ri->rp && ri->rp->handler) | 375 | orig_ret_address = (unsigned long)ri->ret_addr; |
| 376 | ri->rp->handler(ri, regs); | 376 | |
| 377 | if (orig_ret_address != trampoline_address) | ||
| 378 | /* | ||
| 379 | * This is the real return address. Any other | ||
| 380 | * instances associated with this task are for | ||
| 381 | * other calls deeper on the call stack | ||
| 382 | */ | ||
| 383 | break; | ||
| 384 | } | ||
| 385 | |||
| 386 | kretprobe_assert(ri, orig_ret_address, trampoline_address); | ||
| 387 | |||
| 388 | correct_ret_addr = ri->ret_addr; | ||
| 389 | hlist_for_each_entry_safe(ri, node, tmp, head, hlist) { | ||
| 390 | if (ri->task != current) | ||
| 391 | /* another task is sharing our hash bucket */ | ||
| 392 | continue; | ||
| 377 | 393 | ||
| 378 | orig_ret_address = (unsigned long)ri->ret_addr; | 394 | orig_ret_address = (unsigned long)ri->ret_addr; |
| 395 | |||
| 396 | if (ri->rp && ri->rp->handler) { | ||
| 397 | ri->ret_addr = correct_ret_addr; | ||
| 398 | ri->rp->handler(ri, regs); | ||
| 399 | } | ||
| 400 | |||
| 379 | recycle_rp_inst(ri, &empty_rp); | 401 | recycle_rp_inst(ri, &empty_rp); |
| 380 | 402 | ||
| 381 | if (orig_ret_address != trampoline_address) { | 403 | if (orig_ret_address != trampoline_address) { |
| @@ -387,7 +409,7 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p, | |||
| 387 | break; | 409 | break; |
| 388 | } | 410 | } |
| 389 | } | 411 | } |
| 390 | kretprobe_assert(ri, orig_ret_address, trampoline_address); | 412 | |
| 391 | regs->psw.addr = orig_ret_address | PSW_ADDR_AMODE; | 413 | regs->psw.addr = orig_ret_address | PSW_ADDR_AMODE; |
| 392 | 414 | ||
| 393 | reset_current_kprobe(); | 415 | reset_current_kprobe(); |
| @@ -465,8 +487,6 @@ static int __kprobes post_kprobe_handler(struct pt_regs *regs) | |||
| 465 | goto out; | 487 | goto out; |
| 466 | } | 488 | } |
| 467 | reset_current_kprobe(); | 489 | reset_current_kprobe(); |
| 468 | if (regs->psw.mask & (PSW_MASK_PER | PSW_MASK_IO)) | ||
| 469 | local_irq_enable(); | ||
| 470 | out: | 490 | out: |
| 471 | preempt_enable_no_resched(); | 491 | preempt_enable_no_resched(); |
| 472 | 492 | ||
| @@ -482,7 +502,7 @@ out: | |||
| 482 | return 1; | 502 | return 1; |
| 483 | } | 503 | } |
| 484 | 504 | ||
| 485 | int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) | 505 | static int __kprobes kprobe_trap_handler(struct pt_regs *regs, int trapnr) |
| 486 | { | 506 | { |
| 487 | struct kprobe *cur = kprobe_running(); | 507 | struct kprobe *cur = kprobe_running(); |
| 488 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 508 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
| @@ -508,8 +528,6 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) | |||
| 508 | restore_previous_kprobe(kcb); | 528 | restore_previous_kprobe(kcb); |
| 509 | else { | 529 | else { |
| 510 | reset_current_kprobe(); | 530 | reset_current_kprobe(); |
| 511 | if (regs->psw.mask & (PSW_MASK_PER | PSW_MASK_IO)) | ||
| 512 | local_irq_enable(); | ||
| 513 | } | 531 | } |
| 514 | preempt_enable_no_resched(); | 532 | preempt_enable_no_resched(); |
| 515 | break; | 533 | break; |
| @@ -553,6 +571,18 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) | |||
| 553 | return 0; | 571 | return 0; |
| 554 | } | 572 | } |
| 555 | 573 | ||
| 574 | int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) | ||
| 575 | { | ||
| 576 | int ret; | ||
| 577 | |||
| 578 | if (regs->psw.mask & (PSW_MASK_IO | PSW_MASK_EXT)) | ||
| 579 | local_irq_disable(); | ||
| 580 | ret = kprobe_trap_handler(regs, trapnr); | ||
| 581 | if (regs->psw.mask & (PSW_MASK_IO | PSW_MASK_EXT)) | ||
| 582 | local_irq_restore(regs->psw.mask & ~PSW_MASK_PER); | ||
| 583 | return ret; | ||
| 584 | } | ||
| 585 | |||
| 556 | /* | 586 | /* |
| 557 | * Wrapper routine to for handling exceptions. | 587 | * Wrapper routine to for handling exceptions. |
| 558 | */ | 588 | */ |
| @@ -560,8 +590,12 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, | |||
| 560 | unsigned long val, void *data) | 590 | unsigned long val, void *data) |
| 561 | { | 591 | { |
| 562 | struct die_args *args = (struct die_args *)data; | 592 | struct die_args *args = (struct die_args *)data; |
| 593 | struct pt_regs *regs = args->regs; | ||
| 563 | int ret = NOTIFY_DONE; | 594 | int ret = NOTIFY_DONE; |
| 564 | 595 | ||
| 596 | if (regs->psw.mask & (PSW_MASK_IO | PSW_MASK_EXT)) | ||
| 597 | local_irq_disable(); | ||
| 598 | |||
| 565 | switch (val) { | 599 | switch (val) { |
| 566 | case DIE_BPT: | 600 | case DIE_BPT: |
| 567 | if (kprobe_handler(args->regs)) | 601 | if (kprobe_handler(args->regs)) |
| @@ -572,16 +606,17 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, | |||
| 572 | ret = NOTIFY_STOP; | 606 | ret = NOTIFY_STOP; |
| 573 | break; | 607 | break; |
| 574 | case DIE_TRAP: | 608 | case DIE_TRAP: |
| 575 | /* kprobe_running() needs smp_processor_id() */ | 609 | if (!preemptible() && kprobe_running() && |
| 576 | preempt_disable(); | 610 | kprobe_trap_handler(args->regs, args->trapnr)) |
| 577 | if (kprobe_running() && | ||
| 578 | kprobe_fault_handler(args->regs, args->trapnr)) | ||
| 579 | ret = NOTIFY_STOP; | 611 | ret = NOTIFY_STOP; |
| 580 | preempt_enable(); | ||
| 581 | break; | 612 | break; |
| 582 | default: | 613 | default: |
| 583 | break; | 614 | break; |
| 584 | } | 615 | } |
| 616 | |||
| 617 | if (regs->psw.mask & (PSW_MASK_IO | PSW_MASK_EXT)) | ||
| 618 | local_irq_restore(regs->psw.mask & ~PSW_MASK_PER); | ||
| 619 | |||
| 585 | return ret; | 620 | return ret; |
| 586 | } | 621 | } |
| 587 | 622 | ||
| @@ -595,6 +630,7 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | |||
| 595 | 630 | ||
| 596 | /* setup return addr to the jprobe handler routine */ | 631 | /* setup return addr to the jprobe handler routine */ |
| 597 | regs->psw.addr = (unsigned long)(jp->entry) | PSW_ADDR_AMODE; | 632 | regs->psw.addr = (unsigned long)(jp->entry) | PSW_ADDR_AMODE; |
| 633 | regs->psw.mask &= ~(PSW_MASK_IO | PSW_MASK_EXT); | ||
| 598 | 634 | ||
| 599 | /* r14 is the function return address */ | 635 | /* r14 is the function return address */ |
| 600 | kcb->jprobe_saved_r14 = (unsigned long)regs->gprs[14]; | 636 | kcb->jprobe_saved_r14 = (unsigned long)regs->gprs[14]; |
diff --git a/arch/s390/mm/gup.c b/arch/s390/mm/gup.c index 38e641cdd97..45b405ca256 100644 --- a/arch/s390/mm/gup.c +++ b/arch/s390/mm/gup.c | |||
| @@ -20,18 +20,17 @@ | |||
| 20 | static inline int gup_pte_range(pmd_t *pmdp, pmd_t pmd, unsigned long addr, | 20 | static inline int gup_pte_range(pmd_t *pmdp, pmd_t pmd, unsigned long addr, |
| 21 | unsigned long end, int write, struct page **pages, int *nr) | 21 | unsigned long end, int write, struct page **pages, int *nr) |
| 22 | { | 22 | { |
| 23 | unsigned long mask, result; | 23 | unsigned long mask; |
| 24 | pte_t *ptep, pte; | 24 | pte_t *ptep, pte; |
| 25 | struct page *page; | 25 | struct page *page; |
| 26 | 26 | ||
| 27 | result = write ? 0 : _PAGE_RO; | 27 | mask = (write ? _PAGE_RO : 0) | _PAGE_INVALID | _PAGE_SPECIAL; |
| 28 | mask = result | _PAGE_INVALID | _PAGE_SPECIAL; | ||
| 29 | 28 | ||
| 30 | ptep = ((pte_t *) pmd_deref(pmd)) + pte_index(addr); | 29 | ptep = ((pte_t *) pmd_deref(pmd)) + pte_index(addr); |
| 31 | do { | 30 | do { |
| 32 | pte = *ptep; | 31 | pte = *ptep; |
| 33 | barrier(); | 32 | barrier(); |
| 34 | if ((pte_val(pte) & mask) != result) | 33 | if ((pte_val(pte) & mask) != 0) |
| 35 | return 0; | 34 | return 0; |
| 36 | VM_BUG_ON(!pfn_valid(pte_pfn(pte))); | 35 | VM_BUG_ON(!pfn_valid(pte_pfn(pte))); |
| 37 | page = pte_page(pte); | 36 | page = pte_page(pte); |
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c index 6c408670e08..b3a3e8e8656 100644 --- a/drivers/s390/char/tape_core.c +++ b/drivers/s390/char/tape_core.c | |||
| @@ -209,29 +209,79 @@ tape_state_set(struct tape_device *device, enum tape_state newstate) | |||
| 209 | wake_up(&device->state_change_wq); | 209 | wake_up(&device->state_change_wq); |
| 210 | } | 210 | } |
| 211 | 211 | ||
| 212 | struct tape_med_state_work_data { | ||
| 213 | struct tape_device *device; | ||
| 214 | enum tape_medium_state state; | ||
| 215 | struct work_struct work; | ||
| 216 | }; | ||
| 217 | |||
| 218 | static void | ||
| 219 | tape_med_state_work_handler(struct work_struct *work) | ||
| 220 | { | ||
| 221 | static char env_state_loaded[] = "MEDIUM_STATE=LOADED"; | ||
| 222 | static char env_state_unloaded[] = "MEDIUM_STATE=UNLOADED"; | ||
| 223 | struct tape_med_state_work_data *p = | ||
| 224 | container_of(work, struct tape_med_state_work_data, work); | ||
| 225 | struct tape_device *device = p->device; | ||
| 226 | char *envp[] = { NULL, NULL }; | ||
| 227 | |||
| 228 | switch (p->state) { | ||
| 229 | case MS_UNLOADED: | ||
| 230 | pr_info("%s: The tape cartridge has been successfully " | ||
| 231 | "unloaded\n", dev_name(&device->cdev->dev)); | ||
| 232 | envp[0] = env_state_unloaded; | ||
| 233 | kobject_uevent_env(&device->cdev->dev.kobj, KOBJ_CHANGE, envp); | ||
| 234 | break; | ||
| 235 | case MS_LOADED: | ||
| 236 | pr_info("%s: A tape cartridge has been mounted\n", | ||
| 237 | dev_name(&device->cdev->dev)); | ||
| 238 | envp[0] = env_state_loaded; | ||
| 239 | kobject_uevent_env(&device->cdev->dev.kobj, KOBJ_CHANGE, envp); | ||
| 240 | break; | ||
| 241 | default: | ||
| 242 | break; | ||
| 243 | } | ||
| 244 | tape_put_device(device); | ||
| 245 | kfree(p); | ||
| 246 | } | ||
| 247 | |||
| 248 | static void | ||
| 249 | tape_med_state_work(struct tape_device *device, enum tape_medium_state state) | ||
| 250 | { | ||
| 251 | struct tape_med_state_work_data *p; | ||
| 252 | |||
| 253 | p = kzalloc(sizeof(*p), GFP_ATOMIC); | ||
| 254 | if (p) { | ||
| 255 | INIT_WORK(&p->work, tape_med_state_work_handler); | ||
| 256 | p->device = tape_get_device(device); | ||
| 257 | p->state = state; | ||
| 258 | schedule_work(&p->work); | ||
| 259 | } | ||
| 260 | } | ||
| 261 | |||
| 212 | void | 262 | void |
| 213 | tape_med_state_set(struct tape_device *device, enum tape_medium_state newstate) | 263 | tape_med_state_set(struct tape_device *device, enum tape_medium_state newstate) |
| 214 | { | 264 | { |
| 215 | if (device->medium_state == newstate) | 265 | enum tape_medium_state oldstate; |
| 266 | |||
| 267 | oldstate = device->medium_state; | ||
| 268 | if (oldstate == newstate) | ||
| 216 | return; | 269 | return; |
| 270 | device->medium_state = newstate; | ||
| 217 | switch(newstate){ | 271 | switch(newstate){ |
| 218 | case MS_UNLOADED: | 272 | case MS_UNLOADED: |
| 219 | device->tape_generic_status |= GMT_DR_OPEN(~0); | 273 | device->tape_generic_status |= GMT_DR_OPEN(~0); |
| 220 | if (device->medium_state == MS_LOADED) | 274 | if (oldstate == MS_LOADED) |
| 221 | pr_info("%s: The tape cartridge has been successfully " | 275 | tape_med_state_work(device, MS_UNLOADED); |
| 222 | "unloaded\n", dev_name(&device->cdev->dev)); | ||
| 223 | break; | 276 | break; |
| 224 | case MS_LOADED: | 277 | case MS_LOADED: |
| 225 | device->tape_generic_status &= ~GMT_DR_OPEN(~0); | 278 | device->tape_generic_status &= ~GMT_DR_OPEN(~0); |
| 226 | if (device->medium_state == MS_UNLOADED) | 279 | if (oldstate == MS_UNLOADED) |
| 227 | pr_info("%s: A tape cartridge has been mounted\n", | 280 | tape_med_state_work(device, MS_LOADED); |
| 228 | dev_name(&device->cdev->dev)); | ||
| 229 | break; | 281 | break; |
| 230 | default: | 282 | default: |
| 231 | // print nothing | ||
| 232 | break; | 283 | break; |
| 233 | } | 284 | } |
| 234 | device->medium_state = newstate; | ||
| 235 | wake_up(&device->state_change_wq); | 285 | wake_up(&device->state_change_wq); |
| 236 | } | 286 | } |
| 237 | 287 | ||
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c index 9f661426e4a..1cc726b98ec 100644 --- a/drivers/s390/char/vmlogrdr.c +++ b/drivers/s390/char/vmlogrdr.c | |||
| @@ -249,27 +249,25 @@ static int vmlogrdr_recording(struct vmlogrdr_priv_t * logptr, | |||
| 249 | char cp_command[80]; | 249 | char cp_command[80]; |
| 250 | char cp_response[160]; | 250 | char cp_response[160]; |
| 251 | char *onoff, *qid_string; | 251 | char *onoff, *qid_string; |
| 252 | int rc; | ||
| 252 | 253 | ||
| 253 | memset(cp_command, 0x00, sizeof(cp_command)); | 254 | onoff = ((action == 1) ? "ON" : "OFF"); |
| 254 | memset(cp_response, 0x00, sizeof(cp_response)); | ||
| 255 | |||
| 256 | onoff = ((action == 1) ? "ON" : "OFF"); | ||
| 257 | qid_string = ((recording_class_AB == 1) ? " QID * " : ""); | 255 | qid_string = ((recording_class_AB == 1) ? " QID * " : ""); |
| 258 | 256 | ||
| 259 | /* | 257 | /* |
| 260 | * The recording commands needs to be called with option QID | 258 | * The recording commands needs to be called with option QID |
| 261 | * for guests that have previlege classes A or B. | 259 | * for guests that have previlege classes A or B. |
| 262 | * Purging has to be done as separate step, because recording | 260 | * Purging has to be done as separate step, because recording |
| 263 | * can't be switched on as long as records are on the queue. | 261 | * can't be switched on as long as records are on the queue. |
| 264 | * Doing both at the same time doesn't work. | 262 | * Doing both at the same time doesn't work. |
| 265 | */ | 263 | */ |
| 266 | 264 | if (purge && (action == 1)) { | |
| 267 | if (purge) { | 265 | memset(cp_command, 0x00, sizeof(cp_command)); |
| 266 | memset(cp_response, 0x00, sizeof(cp_response)); | ||
| 268 | snprintf(cp_command, sizeof(cp_command), | 267 | snprintf(cp_command, sizeof(cp_command), |
| 269 | "RECORDING %s PURGE %s", | 268 | "RECORDING %s PURGE %s", |
| 270 | logptr->recording_name, | 269 | logptr->recording_name, |
| 271 | qid_string); | 270 | qid_string); |
| 272 | |||
| 273 | cpcmd(cp_command, cp_response, sizeof(cp_response), NULL); | 271 | cpcmd(cp_command, cp_response, sizeof(cp_response), NULL); |
| 274 | } | 272 | } |
| 275 | 273 | ||
| @@ -279,19 +277,33 @@ static int vmlogrdr_recording(struct vmlogrdr_priv_t * logptr, | |||
| 279 | logptr->recording_name, | 277 | logptr->recording_name, |
| 280 | onoff, | 278 | onoff, |
| 281 | qid_string); | 279 | qid_string); |
| 282 | |||
| 283 | cpcmd(cp_command, cp_response, sizeof(cp_response), NULL); | 280 | cpcmd(cp_command, cp_response, sizeof(cp_response), NULL); |
| 284 | /* The recording command will usually answer with 'Command complete' | 281 | /* The recording command will usually answer with 'Command complete' |
| 285 | * on success, but when the specific service was never connected | 282 | * on success, but when the specific service was never connected |
| 286 | * before then there might be an additional informational message | 283 | * before then there might be an additional informational message |
| 287 | * 'HCPCRC8072I Recording entry not found' before the | 284 | * 'HCPCRC8072I Recording entry not found' before the |
| 288 | * 'Command complete'. So I use strstr rather then the strncmp. | 285 | * 'Command complete'. So I use strstr rather then the strncmp. |
| 289 | */ | 286 | */ |
| 290 | if (strstr(cp_response,"Command complete")) | 287 | if (strstr(cp_response,"Command complete")) |
| 291 | return 0; | 288 | rc = 0; |
| 292 | else | 289 | else |
| 293 | return -EIO; | 290 | rc = -EIO; |
| 291 | /* | ||
| 292 | * If we turn recording off, we have to purge any remaining records | ||
| 293 | * afterwards, as a large number of queued records may impact z/VM | ||
| 294 | * performance. | ||
| 295 | */ | ||
| 296 | if (purge && (action == 0)) { | ||
| 297 | memset(cp_command, 0x00, sizeof(cp_command)); | ||
| 298 | memset(cp_response, 0x00, sizeof(cp_response)); | ||
| 299 | snprintf(cp_command, sizeof(cp_command), | ||
| 300 | "RECORDING %s PURGE %s", | ||
| 301 | logptr->recording_name, | ||
| 302 | qid_string); | ||
| 303 | cpcmd(cp_command, cp_response, sizeof(cp_response), NULL); | ||
| 304 | } | ||
| 294 | 305 | ||
| 306 | return rc; | ||
| 295 | } | 307 | } |
| 296 | 308 | ||
| 297 | 309 | ||
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 2ff8a22d425..e8391b89eff 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
| @@ -1455,7 +1455,16 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process) | |||
| 1455 | break; | 1455 | break; |
| 1456 | case IO_SCH_UNREG_ATTACH: | 1456 | case IO_SCH_UNREG_ATTACH: |
| 1457 | case IO_SCH_UNREG: | 1457 | case IO_SCH_UNREG: |
| 1458 | if (cdev) | 1458 | if (!cdev) |
| 1459 | break; | ||
| 1460 | if (cdev->private->state == DEV_STATE_SENSE_ID) { | ||
| 1461 | /* | ||
| 1462 | * Note: delayed work triggered by this event | ||
| 1463 | * and repeated calls to sch_event are synchronized | ||
| 1464 | * by the above check for work_pending(cdev). | ||
| 1465 | */ | ||
| 1466 | dev_fsm_event(cdev, DEV_EVENT_NOTOPER); | ||
| 1467 | } else | ||
| 1459 | ccw_device_set_notoper(cdev); | 1468 | ccw_device_set_notoper(cdev); |
| 1460 | break; | 1469 | break; |
| 1461 | case IO_SCH_NOP: | 1470 | case IO_SCH_NOP: |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index b65bf634035..5abfa151855 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
| @@ -702,7 +702,6 @@ static struct ctl_table kern_table[] = { | |||
| 702 | .extra1 = &zero, | 702 | .extra1 = &zero, |
| 703 | .extra2 = &ten_thousand, | 703 | .extra2 = &ten_thousand, |
| 704 | }, | 704 | }, |
| 705 | #endif | ||
| 706 | { | 705 | { |
| 707 | .procname = "dmesg_restrict", | 706 | .procname = "dmesg_restrict", |
| 708 | .data = &dmesg_restrict, | 707 | .data = &dmesg_restrict, |
| @@ -712,6 +711,7 @@ static struct ctl_table kern_table[] = { | |||
| 712 | .extra1 = &zero, | 711 | .extra1 = &zero, |
| 713 | .extra2 = &one, | 712 | .extra2 = &one, |
| 714 | }, | 713 | }, |
| 714 | #endif | ||
| 715 | { | 715 | { |
| 716 | .procname = "ngroups_max", | 716 | .procname = "ngroups_max", |
| 717 | .data = &ngroups_max, | 717 | .data = &ngroups_max, |
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index e04b8bcdef8..ea37e2ff416 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig | |||
| @@ -126,7 +126,7 @@ if FTRACE | |||
| 126 | config FUNCTION_TRACER | 126 | config FUNCTION_TRACER |
| 127 | bool "Kernel Function Tracer" | 127 | bool "Kernel Function Tracer" |
| 128 | depends on HAVE_FUNCTION_TRACER | 128 | depends on HAVE_FUNCTION_TRACER |
| 129 | select FRAME_POINTER if (!ARM_UNWIND) | 129 | select FRAME_POINTER if !ARM_UNWIND && !S390 |
| 130 | select KALLSYMS | 130 | select KALLSYMS |
| 131 | select GENERIC_TRACER | 131 | select GENERIC_TRACER |
| 132 | select CONTEXT_SWITCH_TRACER | 132 | select CONTEXT_SWITCH_TRACER |
