diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-03 18:45:10 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-03 18:45:10 -0400 |
commit | a3da2c6913469ecb2224d891c45470b37b4d67f4 (patch) | |
tree | cbedea8d0c8c101cfffccdbaf273e7adf92a4e46 /drivers/block | |
parent | ff826b2b5b269ad440afa686ede879ccabfda387 (diff) | |
parent | 6d9359280753d2955f86d6411047516a9431eb51 (diff) |
Merge branch 'for-linus' of git://git.kernel.dk/linux-block
Pull block bits from Jens Axboe:
"As vacation is coming up, thought I'd better get rid of my pending
changes in my for-linus branch for this iteration. It contains:
- Two patches for mtip32xx. Killing a non-compliant sysfs interface
and moving it to debugfs, where it belongs.
- A few patches from Asias. Two legit bug fixes, and one killing an
interface that is no longer in use.
- A patch from Jan, making the annoying partition ioctl warning a bit
less annoying, by restricting it to !CAP_SYS_RAWIO only.
- Three bug fixes for drbd from Lars Ellenberg.
- A fix for an old regression for umem, it hasn't really worked since
the plugging scheme was changed in 3.0.
- A few fixes from Tejun.
- A splice fix from Eric Dumazet, fixing an issue with pipe
resizing."
* 'for-linus' of git://git.kernel.dk/linux-block:
scsi: Silence unnecessary warnings about ioctl to partition
block: Drop dead function blk_abort_queue()
block: Mitigate lock unbalance caused by lock switching
block: Avoid missed wakeup in request waitqueue
umem: fix up unplugging
splice: fix racy pipe->buffers uses
drbd: fix null pointer dereference with on-congestion policy when diskless
drbd: fix list corruption by failing but already aborted reads
drbd: fix access of unallocated pages and kernel panic
xen/blkfront: Add WARN to deal with misbehaving backends.
blkcg: drop local variable @q from blkg_destroy()
mtip32xx: Create debugfs entries for troubleshooting
mtip32xx: Remove 'registers' and 'flags' from sysfs
blkcg: fix blkg_alloc() failure path
block: blkcg_policy_cfq shouldn't be used if !CONFIG_CFQ_GROUP_IOSCHED
block: fix return value on cfq_init() failure
mtip32xx: Remove version.h header file inclusion
xen/blkback: Copy id field when doing BLKIF_DISCARD.
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/drbd/drbd_bitmap.c | 11 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_req.c | 66 | ||||
-rw-r--r-- | drivers/block/mtip32xx/mtip32xx.c | 166 | ||||
-rw-r--r-- | drivers/block/mtip32xx/mtip32xx.h | 5 | ||||
-rw-r--r-- | drivers/block/umem.c | 40 | ||||
-rw-r--r-- | drivers/block/xen-blkback/common.h | 2 | ||||
-rw-r--r-- | drivers/block/xen-blkfront.c | 58 |
7 files changed, 261 insertions, 87 deletions
diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c index b5c5ff53cb57..fcb956bb4b4c 100644 --- a/drivers/block/drbd/drbd_bitmap.c +++ b/drivers/block/drbd/drbd_bitmap.c | |||
@@ -1475,10 +1475,17 @@ void _drbd_bm_set_bits(struct drbd_conf *mdev, const unsigned long s, const unsi | |||
1475 | first_word = 0; | 1475 | first_word = 0; |
1476 | spin_lock_irq(&b->bm_lock); | 1476 | spin_lock_irq(&b->bm_lock); |
1477 | } | 1477 | } |
1478 | |||
1479 | /* last page (respectively only page, for first page == last page) */ | 1478 | /* last page (respectively only page, for first page == last page) */ |
1480 | last_word = MLPP(el >> LN2_BPL); | 1479 | last_word = MLPP(el >> LN2_BPL); |
1481 | bm_set_full_words_within_one_page(mdev->bitmap, last_page, first_word, last_word); | 1480 | |
1481 | /* consider bitmap->bm_bits = 32768, bitmap->bm_number_of_pages = 1. (or multiples). | ||
1482 | * ==> e = 32767, el = 32768, last_page = 2, | ||
1483 | * and now last_word = 0. | ||
1484 | * We do not want to touch last_page in this case, | ||
1485 | * as we did not allocate it, it is not present in bitmap->bm_pages. | ||
1486 | */ | ||
1487 | if (last_word) | ||
1488 | bm_set_full_words_within_one_page(mdev->bitmap, last_page, first_word, last_word); | ||
1482 | 1489 | ||
1483 | /* possibly trailing bits. | 1490 | /* possibly trailing bits. |
1484 | * example: (e & 63) == 63, el will be e+1. | 1491 | * example: (e & 63) == 63, el will be e+1. |
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index 9c5c84946b05..8e93a6ac9bb6 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c | |||
@@ -472,12 +472,17 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what, | |||
472 | req->rq_state |= RQ_LOCAL_COMPLETED; | 472 | req->rq_state |= RQ_LOCAL_COMPLETED; |
473 | req->rq_state &= ~RQ_LOCAL_PENDING; | 473 | req->rq_state &= ~RQ_LOCAL_PENDING; |
474 | 474 | ||
475 | D_ASSERT(!(req->rq_state & RQ_NET_MASK)); | 475 | if (req->rq_state & RQ_LOCAL_ABORTED) { |
476 | _req_may_be_done(req, m); | ||
477 | break; | ||
478 | } | ||
476 | 479 | ||
477 | __drbd_chk_io_error(mdev, false); | 480 | __drbd_chk_io_error(mdev, false); |
478 | 481 | ||
479 | goto_queue_for_net_read: | 482 | goto_queue_for_net_read: |
480 | 483 | ||
484 | D_ASSERT(!(req->rq_state & RQ_NET_MASK)); | ||
485 | |||
481 | /* no point in retrying if there is no good remote data, | 486 | /* no point in retrying if there is no good remote data, |
482 | * or we have no connection. */ | 487 | * or we have no connection. */ |
483 | if (mdev->state.pdsk != D_UP_TO_DATE) { | 488 | if (mdev->state.pdsk != D_UP_TO_DATE) { |
@@ -765,6 +770,40 @@ static int drbd_may_do_local_read(struct drbd_conf *mdev, sector_t sector, int s | |||
765 | return 0 == drbd_bm_count_bits(mdev, sbnr, ebnr); | 770 | return 0 == drbd_bm_count_bits(mdev, sbnr, ebnr); |
766 | } | 771 | } |
767 | 772 | ||
773 | static void maybe_pull_ahead(struct drbd_conf *mdev) | ||
774 | { | ||
775 | int congested = 0; | ||
776 | |||
777 | /* If I don't even have good local storage, we can not reasonably try | ||
778 | * to pull ahead of the peer. We also need the local reference to make | ||
779 | * sure mdev->act_log is there. | ||
780 | * Note: caller has to make sure that net_conf is there. | ||
781 | */ | ||
782 | if (!get_ldev_if_state(mdev, D_UP_TO_DATE)) | ||
783 | return; | ||
784 | |||
785 | if (mdev->net_conf->cong_fill && | ||
786 | atomic_read(&mdev->ap_in_flight) >= mdev->net_conf->cong_fill) { | ||
787 | dev_info(DEV, "Congestion-fill threshold reached\n"); | ||
788 | congested = 1; | ||
789 | } | ||
790 | |||
791 | if (mdev->act_log->used >= mdev->net_conf->cong_extents) { | ||
792 | dev_info(DEV, "Congestion-extents threshold reached\n"); | ||
793 | congested = 1; | ||
794 | } | ||
795 | |||
796 | if (congested) { | ||
797 | queue_barrier(mdev); /* last barrier, after mirrored writes */ | ||
798 | |||
799 | if (mdev->net_conf->on_congestion == OC_PULL_AHEAD) | ||
800 | _drbd_set_state(_NS(mdev, conn, C_AHEAD), 0, NULL); | ||
801 | else /*mdev->net_conf->on_congestion == OC_DISCONNECT */ | ||
802 | _drbd_set_state(_NS(mdev, conn, C_DISCONNECTING), 0, NULL); | ||
803 | } | ||
804 | put_ldev(mdev); | ||
805 | } | ||
806 | |||
768 | static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio, unsigned long start_time) | 807 | static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio, unsigned long start_time) |
769 | { | 808 | { |
770 | const int rw = bio_rw(bio); | 809 | const int rw = bio_rw(bio); |
@@ -972,29 +1011,8 @@ allocate_barrier: | |||
972 | _req_mod(req, queue_for_send_oos); | 1011 | _req_mod(req, queue_for_send_oos); |
973 | 1012 | ||
974 | if (remote && | 1013 | if (remote && |
975 | mdev->net_conf->on_congestion != OC_BLOCK && mdev->agreed_pro_version >= 96) { | 1014 | mdev->net_conf->on_congestion != OC_BLOCK && mdev->agreed_pro_version >= 96) |
976 | int congested = 0; | 1015 | maybe_pull_ahead(mdev); |
977 | |||
978 | if (mdev->net_conf->cong_fill && | ||
979 | atomic_read(&mdev->ap_in_flight) >= mdev->net_conf->cong_fill) { | ||
980 | dev_info(DEV, "Congestion-fill threshold reached\n"); | ||
981 | congested = 1; | ||
982 | } | ||
983 | |||
984 | if (mdev->act_log->used >= mdev->net_conf->cong_extents) { | ||
985 | dev_info(DEV, "Congestion-extents threshold reached\n"); | ||
986 | congested = 1; | ||
987 | } | ||
988 | |||
989 | if (congested) { | ||
990 | queue_barrier(mdev); /* last barrier, after mirrored writes */ | ||
991 | |||
992 | if (mdev->net_conf->on_congestion == OC_PULL_AHEAD) | ||
993 | _drbd_set_state(_NS(mdev, conn, C_AHEAD), 0, NULL); | ||
994 | else /*mdev->net_conf->on_congestion == OC_DISCONNECT */ | ||
995 | _drbd_set_state(_NS(mdev, conn, C_DISCONNECTING), 0, NULL); | ||
996 | } | ||
997 | } | ||
998 | 1016 | ||
999 | spin_unlock_irq(&mdev->req_lock); | 1017 | spin_unlock_irq(&mdev->req_lock); |
1000 | kfree(b); /* if someone else has beaten us to it... */ | 1018 | kfree(b); /* if someone else has beaten us to it... */ |
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index 264bc77dcb91..a8fddeb3d638 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/kthread.h> | 37 | #include <linux/kthread.h> |
38 | #include <../drivers/ata/ahci.h> | 38 | #include <../drivers/ata/ahci.h> |
39 | #include <linux/export.h> | 39 | #include <linux/export.h> |
40 | #include <linux/debugfs.h> | ||
40 | #include "mtip32xx.h" | 41 | #include "mtip32xx.h" |
41 | 42 | ||
42 | #define HW_CMD_SLOT_SZ (MTIP_MAX_COMMAND_SLOTS * 32) | 43 | #define HW_CMD_SLOT_SZ (MTIP_MAX_COMMAND_SLOTS * 32) |
@@ -85,6 +86,7 @@ static int instance; | |||
85 | * allocated in mtip_init(). | 86 | * allocated in mtip_init(). |
86 | */ | 87 | */ |
87 | static int mtip_major; | 88 | static int mtip_major; |
89 | static struct dentry *dfs_parent; | ||
88 | 90 | ||
89 | static DEFINE_SPINLOCK(rssd_index_lock); | 91 | static DEFINE_SPINLOCK(rssd_index_lock); |
90 | static DEFINE_IDA(rssd_index_ida); | 92 | static DEFINE_IDA(rssd_index_ida); |
@@ -2546,7 +2548,7 @@ static struct scatterlist *mtip_hw_get_scatterlist(struct driver_data *dd, | |||
2546 | } | 2548 | } |
2547 | 2549 | ||
2548 | /* | 2550 | /* |
2549 | * Sysfs register/status dump. | 2551 | * Sysfs status dump. |
2550 | * | 2552 | * |
2551 | * @dev Pointer to the device structure, passed by the kernrel. | 2553 | * @dev Pointer to the device structure, passed by the kernrel. |
2552 | * @attr Pointer to the device_attribute structure passed by the kernel. | 2554 | * @attr Pointer to the device_attribute structure passed by the kernel. |
@@ -2555,45 +2557,68 @@ static struct scatterlist *mtip_hw_get_scatterlist(struct driver_data *dd, | |||
2555 | * return value | 2557 | * return value |
2556 | * The size, in bytes, of the data copied into buf. | 2558 | * The size, in bytes, of the data copied into buf. |
2557 | */ | 2559 | */ |
2558 | static ssize_t mtip_hw_show_registers(struct device *dev, | 2560 | static ssize_t mtip_hw_show_status(struct device *dev, |
2559 | struct device_attribute *attr, | 2561 | struct device_attribute *attr, |
2560 | char *buf) | 2562 | char *buf) |
2561 | { | 2563 | { |
2562 | u32 group_allocated; | ||
2563 | struct driver_data *dd = dev_to_disk(dev)->private_data; | 2564 | struct driver_data *dd = dev_to_disk(dev)->private_data; |
2564 | int size = 0; | 2565 | int size = 0; |
2566 | |||
2567 | if (test_bit(MTIP_DDF_OVER_TEMP_BIT, &dd->dd_flag)) | ||
2568 | size += sprintf(buf, "%s", "thermal_shutdown\n"); | ||
2569 | else if (test_bit(MTIP_DDF_WRITE_PROTECT_BIT, &dd->dd_flag)) | ||
2570 | size += sprintf(buf, "%s", "write_protect\n"); | ||
2571 | else | ||
2572 | size += sprintf(buf, "%s", "online\n"); | ||
2573 | |||
2574 | return size; | ||
2575 | } | ||
2576 | |||
2577 | static DEVICE_ATTR(status, S_IRUGO, mtip_hw_show_status, NULL); | ||
2578 | |||
2579 | static ssize_t mtip_hw_read_registers(struct file *f, char __user *ubuf, | ||
2580 | size_t len, loff_t *offset) | ||
2581 | { | ||
2582 | struct driver_data *dd = (struct driver_data *)f->private_data; | ||
2583 | char buf[MTIP_DFS_MAX_BUF_SIZE]; | ||
2584 | u32 group_allocated; | ||
2585 | int size = *offset; | ||
2565 | int n; | 2586 | int n; |
2566 | 2587 | ||
2567 | size += sprintf(&buf[size], "Hardware\n--------\n"); | 2588 | if (!len || size) |
2568 | size += sprintf(&buf[size], "S ACTive : [ 0x"); | 2589 | return 0; |
2590 | |||
2591 | if (size < 0) | ||
2592 | return -EINVAL; | ||
2593 | |||
2594 | size += sprintf(&buf[size], "H/ S ACTive : [ 0x"); | ||
2569 | 2595 | ||
2570 | for (n = dd->slot_groups-1; n >= 0; n--) | 2596 | for (n = dd->slot_groups-1; n >= 0; n--) |
2571 | size += sprintf(&buf[size], "%08X ", | 2597 | size += sprintf(&buf[size], "%08X ", |
2572 | readl(dd->port->s_active[n])); | 2598 | readl(dd->port->s_active[n])); |
2573 | 2599 | ||
2574 | size += sprintf(&buf[size], "]\n"); | 2600 | size += sprintf(&buf[size], "]\n"); |
2575 | size += sprintf(&buf[size], "Command Issue : [ 0x"); | 2601 | size += sprintf(&buf[size], "H/ Command Issue : [ 0x"); |
2576 | 2602 | ||
2577 | for (n = dd->slot_groups-1; n >= 0; n--) | 2603 | for (n = dd->slot_groups-1; n >= 0; n--) |
2578 | size += sprintf(&buf[size], "%08X ", | 2604 | size += sprintf(&buf[size], "%08X ", |
2579 | readl(dd->port->cmd_issue[n])); | 2605 | readl(dd->port->cmd_issue[n])); |
2580 | 2606 | ||
2581 | size += sprintf(&buf[size], "]\n"); | 2607 | size += sprintf(&buf[size], "]\n"); |
2582 | size += sprintf(&buf[size], "Completed : [ 0x"); | 2608 | size += sprintf(&buf[size], "H/ Completed : [ 0x"); |
2583 | 2609 | ||
2584 | for (n = dd->slot_groups-1; n >= 0; n--) | 2610 | for (n = dd->slot_groups-1; n >= 0; n--) |
2585 | size += sprintf(&buf[size], "%08X ", | 2611 | size += sprintf(&buf[size], "%08X ", |
2586 | readl(dd->port->completed[n])); | 2612 | readl(dd->port->completed[n])); |
2587 | 2613 | ||
2588 | size += sprintf(&buf[size], "]\n"); | 2614 | size += sprintf(&buf[size], "]\n"); |
2589 | size += sprintf(&buf[size], "PORT IRQ STAT : [ 0x%08X ]\n", | 2615 | size += sprintf(&buf[size], "H/ PORT IRQ STAT : [ 0x%08X ]\n", |
2590 | readl(dd->port->mmio + PORT_IRQ_STAT)); | 2616 | readl(dd->port->mmio + PORT_IRQ_STAT)); |
2591 | size += sprintf(&buf[size], "HOST IRQ STAT : [ 0x%08X ]\n", | 2617 | size += sprintf(&buf[size], "H/ HOST IRQ STAT : [ 0x%08X ]\n", |
2592 | readl(dd->mmio + HOST_IRQ_STAT)); | 2618 | readl(dd->mmio + HOST_IRQ_STAT)); |
2593 | size += sprintf(&buf[size], "\n"); | 2619 | size += sprintf(&buf[size], "\n"); |
2594 | 2620 | ||
2595 | size += sprintf(&buf[size], "Local\n-----\n"); | 2621 | size += sprintf(&buf[size], "L/ Allocated : [ 0x"); |
2596 | size += sprintf(&buf[size], "Allocated : [ 0x"); | ||
2597 | 2622 | ||
2598 | for (n = dd->slot_groups-1; n >= 0; n--) { | 2623 | for (n = dd->slot_groups-1; n >= 0; n--) { |
2599 | if (sizeof(long) > sizeof(u32)) | 2624 | if (sizeof(long) > sizeof(u32)) |
@@ -2605,7 +2630,7 @@ static ssize_t mtip_hw_show_registers(struct device *dev, | |||
2605 | } | 2630 | } |
2606 | size += sprintf(&buf[size], "]\n"); | 2631 | size += sprintf(&buf[size], "]\n"); |
2607 | 2632 | ||
2608 | size += sprintf(&buf[size], "Commands in Q: [ 0x"); | 2633 | size += sprintf(&buf[size], "L/ Commands in Q : [ 0x"); |
2609 | 2634 | ||
2610 | for (n = dd->slot_groups-1; n >= 0; n--) { | 2635 | for (n = dd->slot_groups-1; n >= 0; n--) { |
2611 | if (sizeof(long) > sizeof(u32)) | 2636 | if (sizeof(long) > sizeof(u32)) |
@@ -2617,44 +2642,53 @@ static ssize_t mtip_hw_show_registers(struct device *dev, | |||
2617 | } | 2642 | } |
2618 | size += sprintf(&buf[size], "]\n"); | 2643 | size += sprintf(&buf[size], "]\n"); |
2619 | 2644 | ||
2620 | return size; | 2645 | *offset = size <= len ? size : len; |
2646 | size = copy_to_user(ubuf, buf, *offset); | ||
2647 | if (size) | ||
2648 | return -EFAULT; | ||
2649 | |||
2650 | return *offset; | ||
2621 | } | 2651 | } |
2622 | 2652 | ||
2623 | static ssize_t mtip_hw_show_status(struct device *dev, | 2653 | static ssize_t mtip_hw_read_flags(struct file *f, char __user *ubuf, |
2624 | struct device_attribute *attr, | 2654 | size_t len, loff_t *offset) |
2625 | char *buf) | ||
2626 | { | 2655 | { |
2627 | struct driver_data *dd = dev_to_disk(dev)->private_data; | 2656 | struct driver_data *dd = (struct driver_data *)f->private_data; |
2628 | int size = 0; | 2657 | char buf[MTIP_DFS_MAX_BUF_SIZE]; |
2658 | int size = *offset; | ||
2629 | 2659 | ||
2630 | if (test_bit(MTIP_DDF_OVER_TEMP_BIT, &dd->dd_flag)) | 2660 | if (!len || size) |
2631 | size += sprintf(buf, "%s", "thermal_shutdown\n"); | 2661 | return 0; |
2632 | else if (test_bit(MTIP_DDF_WRITE_PROTECT_BIT, &dd->dd_flag)) | ||
2633 | size += sprintf(buf, "%s", "write_protect\n"); | ||
2634 | else | ||
2635 | size += sprintf(buf, "%s", "online\n"); | ||
2636 | |||
2637 | return size; | ||
2638 | } | ||
2639 | 2662 | ||
2640 | static ssize_t mtip_hw_show_flags(struct device *dev, | 2663 | if (size < 0) |
2641 | struct device_attribute *attr, | 2664 | return -EINVAL; |
2642 | char *buf) | ||
2643 | { | ||
2644 | struct driver_data *dd = dev_to_disk(dev)->private_data; | ||
2645 | int size = 0; | ||
2646 | 2665 | ||
2647 | size += sprintf(&buf[size], "Flag in port struct : [ %08lX ]\n", | 2666 | size += sprintf(&buf[size], "Flag-port : [ %08lX ]\n", |
2648 | dd->port->flags); | 2667 | dd->port->flags); |
2649 | size += sprintf(&buf[size], "Flag in dd struct : [ %08lX ]\n", | 2668 | size += sprintf(&buf[size], "Flag-dd : [ %08lX ]\n", |
2650 | dd->dd_flag); | 2669 | dd->dd_flag); |
2651 | 2670 | ||
2652 | return size; | 2671 | *offset = size <= len ? size : len; |
2672 | size = copy_to_user(ubuf, buf, *offset); | ||
2673 | if (size) | ||
2674 | return -EFAULT; | ||
2675 | |||
2676 | return *offset; | ||
2653 | } | 2677 | } |
2654 | 2678 | ||
2655 | static DEVICE_ATTR(registers, S_IRUGO, mtip_hw_show_registers, NULL); | 2679 | static const struct file_operations mtip_regs_fops = { |
2656 | static DEVICE_ATTR(status, S_IRUGO, mtip_hw_show_status, NULL); | 2680 | .owner = THIS_MODULE, |
2657 | static DEVICE_ATTR(flags, S_IRUGO, mtip_hw_show_flags, NULL); | 2681 | .open = simple_open, |
2682 | .read = mtip_hw_read_registers, | ||
2683 | .llseek = no_llseek, | ||
2684 | }; | ||
2685 | |||
2686 | static const struct file_operations mtip_flags_fops = { | ||
2687 | .owner = THIS_MODULE, | ||
2688 | .open = simple_open, | ||
2689 | .read = mtip_hw_read_flags, | ||
2690 | .llseek = no_llseek, | ||
2691 | }; | ||
2658 | 2692 | ||
2659 | /* | 2693 | /* |
2660 | * Create the sysfs related attributes. | 2694 | * Create the sysfs related attributes. |
@@ -2671,15 +2705,9 @@ static int mtip_hw_sysfs_init(struct driver_data *dd, struct kobject *kobj) | |||
2671 | if (!kobj || !dd) | 2705 | if (!kobj || !dd) |
2672 | return -EINVAL; | 2706 | return -EINVAL; |
2673 | 2707 | ||
2674 | if (sysfs_create_file(kobj, &dev_attr_registers.attr)) | ||
2675 | dev_warn(&dd->pdev->dev, | ||
2676 | "Error creating 'registers' sysfs entry\n"); | ||
2677 | if (sysfs_create_file(kobj, &dev_attr_status.attr)) | 2708 | if (sysfs_create_file(kobj, &dev_attr_status.attr)) |
2678 | dev_warn(&dd->pdev->dev, | 2709 | dev_warn(&dd->pdev->dev, |
2679 | "Error creating 'status' sysfs entry\n"); | 2710 | "Error creating 'status' sysfs entry\n"); |
2680 | if (sysfs_create_file(kobj, &dev_attr_flags.attr)) | ||
2681 | dev_warn(&dd->pdev->dev, | ||
2682 | "Error creating 'flags' sysfs entry\n"); | ||
2683 | return 0; | 2711 | return 0; |
2684 | } | 2712 | } |
2685 | 2713 | ||
@@ -2698,13 +2726,39 @@ static int mtip_hw_sysfs_exit(struct driver_data *dd, struct kobject *kobj) | |||
2698 | if (!kobj || !dd) | 2726 | if (!kobj || !dd) |
2699 | return -EINVAL; | 2727 | return -EINVAL; |
2700 | 2728 | ||
2701 | sysfs_remove_file(kobj, &dev_attr_registers.attr); | ||
2702 | sysfs_remove_file(kobj, &dev_attr_status.attr); | 2729 | sysfs_remove_file(kobj, &dev_attr_status.attr); |
2703 | sysfs_remove_file(kobj, &dev_attr_flags.attr); | ||
2704 | 2730 | ||
2705 | return 0; | 2731 | return 0; |
2706 | } | 2732 | } |
2707 | 2733 | ||
2734 | static int mtip_hw_debugfs_init(struct driver_data *dd) | ||
2735 | { | ||
2736 | if (!dfs_parent) | ||
2737 | return -1; | ||
2738 | |||
2739 | dd->dfs_node = debugfs_create_dir(dd->disk->disk_name, dfs_parent); | ||
2740 | if (IS_ERR_OR_NULL(dd->dfs_node)) { | ||
2741 | dev_warn(&dd->pdev->dev, | ||
2742 | "Error creating node %s under debugfs\n", | ||
2743 | dd->disk->disk_name); | ||
2744 | dd->dfs_node = NULL; | ||
2745 | return -1; | ||
2746 | } | ||
2747 | |||
2748 | debugfs_create_file("flags", S_IRUGO, dd->dfs_node, dd, | ||
2749 | &mtip_flags_fops); | ||
2750 | debugfs_create_file("registers", S_IRUGO, dd->dfs_node, dd, | ||
2751 | &mtip_regs_fops); | ||
2752 | |||
2753 | return 0; | ||
2754 | } | ||
2755 | |||
2756 | static void mtip_hw_debugfs_exit(struct driver_data *dd) | ||
2757 | { | ||
2758 | debugfs_remove_recursive(dd->dfs_node); | ||
2759 | } | ||
2760 | |||
2761 | |||
2708 | /* | 2762 | /* |
2709 | * Perform any init/resume time hardware setup | 2763 | * Perform any init/resume time hardware setup |
2710 | * | 2764 | * |
@@ -3730,6 +3784,7 @@ skip_create_disk: | |||
3730 | mtip_hw_sysfs_init(dd, kobj); | 3784 | mtip_hw_sysfs_init(dd, kobj); |
3731 | kobject_put(kobj); | 3785 | kobject_put(kobj); |
3732 | } | 3786 | } |
3787 | mtip_hw_debugfs_init(dd); | ||
3733 | 3788 | ||
3734 | if (dd->mtip_svc_handler) { | 3789 | if (dd->mtip_svc_handler) { |
3735 | set_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag); | 3790 | set_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag); |
@@ -3755,6 +3810,8 @@ start_service_thread: | |||
3755 | return rv; | 3810 | return rv; |
3756 | 3811 | ||
3757 | kthread_run_error: | 3812 | kthread_run_error: |
3813 | mtip_hw_debugfs_exit(dd); | ||
3814 | |||
3758 | /* Delete our gendisk. This also removes the device from /dev */ | 3815 | /* Delete our gendisk. This also removes the device from /dev */ |
3759 | del_gendisk(dd->disk); | 3816 | del_gendisk(dd->disk); |
3760 | 3817 | ||
@@ -3805,6 +3862,7 @@ static int mtip_block_remove(struct driver_data *dd) | |||
3805 | kobject_put(kobj); | 3862 | kobject_put(kobj); |
3806 | } | 3863 | } |
3807 | } | 3864 | } |
3865 | mtip_hw_debugfs_exit(dd); | ||
3808 | 3866 | ||
3809 | /* | 3867 | /* |
3810 | * Delete our gendisk structure. This also removes the device | 3868 | * Delete our gendisk structure. This also removes the device |
@@ -4152,10 +4210,20 @@ static int __init mtip_init(void) | |||
4152 | } | 4210 | } |
4153 | mtip_major = error; | 4211 | mtip_major = error; |
4154 | 4212 | ||
4213 | if (!dfs_parent) { | ||
4214 | dfs_parent = debugfs_create_dir("rssd", NULL); | ||
4215 | if (IS_ERR_OR_NULL(dfs_parent)) { | ||
4216 | printk(KERN_WARNING "Error creating debugfs parent\n"); | ||
4217 | dfs_parent = NULL; | ||
4218 | } | ||
4219 | } | ||
4220 | |||
4155 | /* Register our PCI operations. */ | 4221 | /* Register our PCI operations. */ |
4156 | error = pci_register_driver(&mtip_pci_driver); | 4222 | error = pci_register_driver(&mtip_pci_driver); |
4157 | if (error) | 4223 | if (error) { |
4224 | debugfs_remove(dfs_parent); | ||
4158 | unregister_blkdev(mtip_major, MTIP_DRV_NAME); | 4225 | unregister_blkdev(mtip_major, MTIP_DRV_NAME); |
4226 | } | ||
4159 | 4227 | ||
4160 | return error; | 4228 | return error; |
4161 | } | 4229 | } |
@@ -4172,6 +4240,8 @@ static int __init mtip_init(void) | |||
4172 | */ | 4240 | */ |
4173 | static void __exit mtip_exit(void) | 4241 | static void __exit mtip_exit(void) |
4174 | { | 4242 | { |
4243 | debugfs_remove_recursive(dfs_parent); | ||
4244 | |||
4175 | /* Release the allocated major block device number. */ | 4245 | /* Release the allocated major block device number. */ |
4176 | unregister_blkdev(mtip_major, MTIP_DRV_NAME); | 4246 | unregister_blkdev(mtip_major, MTIP_DRV_NAME); |
4177 | 4247 | ||
diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h index b2c88da26b2a..f51fc23d17bb 100644 --- a/drivers/block/mtip32xx/mtip32xx.h +++ b/drivers/block/mtip32xx/mtip32xx.h | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <linux/ata.h> | 26 | #include <linux/ata.h> |
27 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
28 | #include <linux/genhd.h> | 28 | #include <linux/genhd.h> |
29 | #include <linux/version.h> | ||
30 | 29 | ||
31 | /* Offset of Subsystem Device ID in pci confoguration space */ | 30 | /* Offset of Subsystem Device ID in pci confoguration space */ |
32 | #define PCI_SUBSYSTEM_DEVICEID 0x2E | 31 | #define PCI_SUBSYSTEM_DEVICEID 0x2E |
@@ -111,6 +110,8 @@ | |||
111 | #define dbg_printk(format, arg...) | 110 | #define dbg_printk(format, arg...) |
112 | #endif | 111 | #endif |
113 | 112 | ||
113 | #define MTIP_DFS_MAX_BUF_SIZE 1024 | ||
114 | |||
114 | #define __force_bit2int (unsigned int __force) | 115 | #define __force_bit2int (unsigned int __force) |
115 | 116 | ||
116 | enum { | 117 | enum { |
@@ -447,6 +448,8 @@ struct driver_data { | |||
447 | unsigned long dd_flag; /* NOTE: use atomic bit operations on this */ | 448 | unsigned long dd_flag; /* NOTE: use atomic bit operations on this */ |
448 | 449 | ||
449 | struct task_struct *mtip_svc_handler; /* task_struct of svc thd */ | 450 | struct task_struct *mtip_svc_handler; /* task_struct of svc thd */ |
451 | |||
452 | struct dentry *dfs_node; | ||
450 | }; | 453 | }; |
451 | 454 | ||
452 | #endif | 455 | #endif |
diff --git a/drivers/block/umem.c b/drivers/block/umem.c index aa2712060bfb..9a72277a31df 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c | |||
@@ -513,6 +513,44 @@ static void process_page(unsigned long data) | |||
513 | } | 513 | } |
514 | } | 514 | } |
515 | 515 | ||
516 | struct mm_plug_cb { | ||
517 | struct blk_plug_cb cb; | ||
518 | struct cardinfo *card; | ||
519 | }; | ||
520 | |||
521 | static void mm_unplug(struct blk_plug_cb *cb) | ||
522 | { | ||
523 | struct mm_plug_cb *mmcb = container_of(cb, struct mm_plug_cb, cb); | ||
524 | |||
525 | spin_lock_irq(&mmcb->card->lock); | ||
526 | activate(mmcb->card); | ||
527 | spin_unlock_irq(&mmcb->card->lock); | ||
528 | kfree(mmcb); | ||
529 | } | ||
530 | |||
531 | static int mm_check_plugged(struct cardinfo *card) | ||
532 | { | ||
533 | struct blk_plug *plug = current->plug; | ||
534 | struct mm_plug_cb *mmcb; | ||
535 | |||
536 | if (!plug) | ||
537 | return 0; | ||
538 | |||
539 | list_for_each_entry(mmcb, &plug->cb_list, cb.list) { | ||
540 | if (mmcb->cb.callback == mm_unplug && mmcb->card == card) | ||
541 | return 1; | ||
542 | } | ||
543 | /* Not currently on the callback list */ | ||
544 | mmcb = kmalloc(sizeof(*mmcb), GFP_ATOMIC); | ||
545 | if (!mmcb) | ||
546 | return 0; | ||
547 | |||
548 | mmcb->card = card; | ||
549 | mmcb->cb.callback = mm_unplug; | ||
550 | list_add(&mmcb->cb.list, &plug->cb_list); | ||
551 | return 1; | ||
552 | } | ||
553 | |||
516 | static void mm_make_request(struct request_queue *q, struct bio *bio) | 554 | static void mm_make_request(struct request_queue *q, struct bio *bio) |
517 | { | 555 | { |
518 | struct cardinfo *card = q->queuedata; | 556 | struct cardinfo *card = q->queuedata; |
@@ -523,6 +561,8 @@ static void mm_make_request(struct request_queue *q, struct bio *bio) | |||
523 | *card->biotail = bio; | 561 | *card->biotail = bio; |
524 | bio->bi_next = NULL; | 562 | bio->bi_next = NULL; |
525 | card->biotail = &bio->bi_next; | 563 | card->biotail = &bio->bi_next; |
564 | if (bio->bi_rw & REQ_SYNC || !mm_check_plugged(card)) | ||
565 | activate(card); | ||
526 | spin_unlock_irq(&card->lock); | 566 | spin_unlock_irq(&card->lock); |
527 | 567 | ||
528 | return; | 568 | return; |
diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index 773cf27dc23f..9ad3b5ec1dc1 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h | |||
@@ -257,6 +257,7 @@ static inline void blkif_get_x86_32_req(struct blkif_request *dst, | |||
257 | break; | 257 | break; |
258 | case BLKIF_OP_DISCARD: | 258 | case BLKIF_OP_DISCARD: |
259 | dst->u.discard.flag = src->u.discard.flag; | 259 | dst->u.discard.flag = src->u.discard.flag; |
260 | dst->u.discard.id = src->u.discard.id; | ||
260 | dst->u.discard.sector_number = src->u.discard.sector_number; | 261 | dst->u.discard.sector_number = src->u.discard.sector_number; |
261 | dst->u.discard.nr_sectors = src->u.discard.nr_sectors; | 262 | dst->u.discard.nr_sectors = src->u.discard.nr_sectors; |
262 | break; | 263 | break; |
@@ -287,6 +288,7 @@ static inline void blkif_get_x86_64_req(struct blkif_request *dst, | |||
287 | break; | 288 | break; |
288 | case BLKIF_OP_DISCARD: | 289 | case BLKIF_OP_DISCARD: |
289 | dst->u.discard.flag = src->u.discard.flag; | 290 | dst->u.discard.flag = src->u.discard.flag; |
291 | dst->u.discard.id = src->u.discard.id; | ||
290 | dst->u.discard.sector_number = src->u.discard.sector_number; | 292 | dst->u.discard.sector_number = src->u.discard.sector_number; |
291 | dst->u.discard.nr_sectors = src->u.discard.nr_sectors; | 293 | dst->u.discard.nr_sectors = src->u.discard.nr_sectors; |
292 | break; | 294 | break; |
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 60eed4bdd2e4..e4fb3374dcd2 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c | |||
@@ -141,14 +141,36 @@ static int get_id_from_freelist(struct blkfront_info *info) | |||
141 | return free; | 141 | return free; |
142 | } | 142 | } |
143 | 143 | ||
144 | static void add_id_to_freelist(struct blkfront_info *info, | 144 | static int add_id_to_freelist(struct blkfront_info *info, |
145 | unsigned long id) | 145 | unsigned long id) |
146 | { | 146 | { |
147 | if (info->shadow[id].req.u.rw.id != id) | ||
148 | return -EINVAL; | ||
149 | if (info->shadow[id].request == NULL) | ||
150 | return -EINVAL; | ||
147 | info->shadow[id].req.u.rw.id = info->shadow_free; | 151 | info->shadow[id].req.u.rw.id = info->shadow_free; |
148 | info->shadow[id].request = NULL; | 152 | info->shadow[id].request = NULL; |
149 | info->shadow_free = id; | 153 | info->shadow_free = id; |
154 | return 0; | ||
150 | } | 155 | } |
151 | 156 | ||
157 | static const char *op_name(int op) | ||
158 | { | ||
159 | static const char *const names[] = { | ||
160 | [BLKIF_OP_READ] = "read", | ||
161 | [BLKIF_OP_WRITE] = "write", | ||
162 | [BLKIF_OP_WRITE_BARRIER] = "barrier", | ||
163 | [BLKIF_OP_FLUSH_DISKCACHE] = "flush", | ||
164 | [BLKIF_OP_DISCARD] = "discard" }; | ||
165 | |||
166 | if (op < 0 || op >= ARRAY_SIZE(names)) | ||
167 | return "unknown"; | ||
168 | |||
169 | if (!names[op]) | ||
170 | return "reserved"; | ||
171 | |||
172 | return names[op]; | ||
173 | } | ||
152 | static int xlbd_reserve_minors(unsigned int minor, unsigned int nr) | 174 | static int xlbd_reserve_minors(unsigned int minor, unsigned int nr) |
153 | { | 175 | { |
154 | unsigned int end = minor + nr; | 176 | unsigned int end = minor + nr; |
@@ -746,20 +768,36 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) | |||
746 | 768 | ||
747 | bret = RING_GET_RESPONSE(&info->ring, i); | 769 | bret = RING_GET_RESPONSE(&info->ring, i); |
748 | id = bret->id; | 770 | id = bret->id; |
771 | /* | ||
772 | * The backend has messed up and given us an id that we would | ||
773 | * never have given to it (we stamp it up to BLK_RING_SIZE - | ||
774 | * look in get_id_from_freelist. | ||
775 | */ | ||
776 | if (id >= BLK_RING_SIZE) { | ||
777 | WARN(1, "%s: response to %s has incorrect id (%ld)\n", | ||
778 | info->gd->disk_name, op_name(bret->operation), id); | ||
779 | /* We can't safely get the 'struct request' as | ||
780 | * the id is busted. */ | ||
781 | continue; | ||
782 | } | ||
749 | req = info->shadow[id].request; | 783 | req = info->shadow[id].request; |
750 | 784 | ||
751 | if (bret->operation != BLKIF_OP_DISCARD) | 785 | if (bret->operation != BLKIF_OP_DISCARD) |
752 | blkif_completion(&info->shadow[id]); | 786 | blkif_completion(&info->shadow[id]); |
753 | 787 | ||
754 | add_id_to_freelist(info, id); | 788 | if (add_id_to_freelist(info, id)) { |
789 | WARN(1, "%s: response to %s (id %ld) couldn't be recycled!\n", | ||
790 | info->gd->disk_name, op_name(bret->operation), id); | ||
791 | continue; | ||
792 | } | ||
755 | 793 | ||
756 | error = (bret->status == BLKIF_RSP_OKAY) ? 0 : -EIO; | 794 | error = (bret->status == BLKIF_RSP_OKAY) ? 0 : -EIO; |
757 | switch (bret->operation) { | 795 | switch (bret->operation) { |
758 | case BLKIF_OP_DISCARD: | 796 | case BLKIF_OP_DISCARD: |
759 | if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) { | 797 | if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) { |
760 | struct request_queue *rq = info->rq; | 798 | struct request_queue *rq = info->rq; |
761 | printk(KERN_WARNING "blkfront: %s: discard op failed\n", | 799 | printk(KERN_WARNING "blkfront: %s: %s op failed\n", |
762 | info->gd->disk_name); | 800 | info->gd->disk_name, op_name(bret->operation)); |
763 | error = -EOPNOTSUPP; | 801 | error = -EOPNOTSUPP; |
764 | info->feature_discard = 0; | 802 | info->feature_discard = 0; |
765 | info->feature_secdiscard = 0; | 803 | info->feature_secdiscard = 0; |
@@ -771,18 +809,14 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) | |||
771 | case BLKIF_OP_FLUSH_DISKCACHE: | 809 | case BLKIF_OP_FLUSH_DISKCACHE: |
772 | case BLKIF_OP_WRITE_BARRIER: | 810 | case BLKIF_OP_WRITE_BARRIER: |
773 | if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) { | 811 | if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) { |
774 | printk(KERN_WARNING "blkfront: %s: write %s op failed\n", | 812 | printk(KERN_WARNING "blkfront: %s: %s op failed\n", |
775 | info->flush_op == BLKIF_OP_WRITE_BARRIER ? | 813 | info->gd->disk_name, op_name(bret->operation)); |
776 | "barrier" : "flush disk cache", | ||
777 | info->gd->disk_name); | ||
778 | error = -EOPNOTSUPP; | 814 | error = -EOPNOTSUPP; |
779 | } | 815 | } |
780 | if (unlikely(bret->status == BLKIF_RSP_ERROR && | 816 | if (unlikely(bret->status == BLKIF_RSP_ERROR && |
781 | info->shadow[id].req.u.rw.nr_segments == 0)) { | 817 | info->shadow[id].req.u.rw.nr_segments == 0)) { |
782 | printk(KERN_WARNING "blkfront: %s: empty write %s op failed\n", | 818 | printk(KERN_WARNING "blkfront: %s: empty %s op failed\n", |
783 | info->flush_op == BLKIF_OP_WRITE_BARRIER ? | 819 | info->gd->disk_name, op_name(bret->operation)); |
784 | "barrier" : "flush disk cache", | ||
785 | info->gd->disk_name); | ||
786 | error = -EOPNOTSUPP; | 820 | error = -EOPNOTSUPP; |
787 | } | 821 | } |
788 | if (unlikely(error)) { | 822 | if (unlikely(error)) { |