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 | |
| 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.
| -rw-r--r-- | Documentation/ABI/testing/sysfs-block-rssd | 21 | ||||
| -rw-r--r-- | block/blk-cgroup.c | 9 | ||||
| -rw-r--r-- | block/blk-core.c | 25 | ||||
| -rw-r--r-- | block/blk-timeout.c | 41 | ||||
| -rw-r--r-- | block/cfq-iosched.c | 30 | ||||
| -rw-r--r-- | block/scsi_ioctl.c | 5 | ||||
| -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 | ||||
| -rw-r--r-- | fs/splice.c | 35 | ||||
| -rw-r--r-- | include/linux/blkdev.h | 1 | ||||
| -rw-r--r-- | include/linux/splice.h | 8 | ||||
| -rw-r--r-- | kernel/relay.c | 5 | ||||
| -rw-r--r-- | kernel/trace/trace.c | 6 | ||||
| -rw-r--r-- | mm/shmem.c | 3 | ||||
| -rw-r--r-- | net/core/skbuff.c | 1 |
20 files changed, 338 insertions, 200 deletions
diff --git a/Documentation/ABI/testing/sysfs-block-rssd b/Documentation/ABI/testing/sysfs-block-rssd index 679ce3543122..beef30c046b0 100644 --- a/Documentation/ABI/testing/sysfs-block-rssd +++ b/Documentation/ABI/testing/sysfs-block-rssd | |||
| @@ -1,26 +1,5 @@ | |||
| 1 | What: /sys/block/rssd*/registers | ||
| 2 | Date: March 2012 | ||
| 3 | KernelVersion: 3.3 | ||
| 4 | Contact: Asai Thambi S P <asamymuthupa@micron.com> | ||
| 5 | Description: This is a read-only file. Dumps below driver information and | ||
| 6 | hardware registers. | ||
| 7 | - S ACTive | ||
| 8 | - Command Issue | ||
| 9 | - Completed | ||
| 10 | - PORT IRQ STAT | ||
| 11 | - HOST IRQ STAT | ||
| 12 | - Allocated | ||
| 13 | - Commands in Q | ||
| 14 | |||
| 15 | What: /sys/block/rssd*/status | 1 | What: /sys/block/rssd*/status |
| 16 | Date: April 2012 | 2 | Date: April 2012 |
| 17 | KernelVersion: 3.4 | 3 | KernelVersion: 3.4 |
| 18 | Contact: Asai Thambi S P <asamymuthupa@micron.com> | 4 | Contact: Asai Thambi S P <asamymuthupa@micron.com> |
| 19 | Description: This is a read-only file. Indicates the status of the device. | 5 | Description: This is a read-only file. Indicates the status of the device. |
| 20 | |||
| 21 | What: /sys/block/rssd*/flags | ||
| 22 | Date: May 2012 | ||
| 23 | KernelVersion: 3.5 | ||
| 24 | Contact: Asai Thambi S P <asamymuthupa@micron.com> | ||
| 25 | Description: This is a read-only file. Dumps the flags in port and driver | ||
| 26 | data structure | ||
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index 02cf6335e9bd..e7dee617358e 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c | |||
| @@ -125,12 +125,8 @@ static struct blkcg_gq *blkg_alloc(struct blkcg *blkcg, struct request_queue *q) | |||
| 125 | 125 | ||
| 126 | blkg->pd[i] = pd; | 126 | blkg->pd[i] = pd; |
| 127 | pd->blkg = blkg; | 127 | pd->blkg = blkg; |
| 128 | } | ||
| 129 | |||
| 130 | /* invoke per-policy init */ | ||
| 131 | for (i = 0; i < BLKCG_MAX_POLS; i++) { | ||
| 132 | struct blkcg_policy *pol = blkcg_policy[i]; | ||
| 133 | 128 | ||
| 129 | /* invoke per-policy init */ | ||
| 134 | if (blkcg_policy_enabled(blkg->q, pol)) | 130 | if (blkcg_policy_enabled(blkg->q, pol)) |
| 135 | pol->pd_init_fn(blkg); | 131 | pol->pd_init_fn(blkg); |
| 136 | } | 132 | } |
| @@ -245,10 +241,9 @@ EXPORT_SYMBOL_GPL(blkg_lookup_create); | |||
| 245 | 241 | ||
| 246 | static void blkg_destroy(struct blkcg_gq *blkg) | 242 | static void blkg_destroy(struct blkcg_gq *blkg) |
| 247 | { | 243 | { |
| 248 | struct request_queue *q = blkg->q; | ||
| 249 | struct blkcg *blkcg = blkg->blkcg; | 244 | struct blkcg *blkcg = blkg->blkcg; |
| 250 | 245 | ||
| 251 | lockdep_assert_held(q->queue_lock); | 246 | lockdep_assert_held(blkg->q->queue_lock); |
| 252 | lockdep_assert_held(&blkcg->lock); | 247 | lockdep_assert_held(&blkcg->lock); |
| 253 | 248 | ||
| 254 | /* Something wrong if we are trying to remove same group twice */ | 249 | /* Something wrong if we are trying to remove same group twice */ |
diff --git a/block/blk-core.c b/block/blk-core.c index 3c923a7aeb56..93eb3e4f88ce 100644 --- a/block/blk-core.c +++ b/block/blk-core.c | |||
| @@ -361,9 +361,10 @@ EXPORT_SYMBOL(blk_put_queue); | |||
| 361 | */ | 361 | */ |
| 362 | void blk_drain_queue(struct request_queue *q, bool drain_all) | 362 | void blk_drain_queue(struct request_queue *q, bool drain_all) |
| 363 | { | 363 | { |
| 364 | int i; | ||
| 365 | |||
| 364 | while (true) { | 366 | while (true) { |
| 365 | bool drain = false; | 367 | bool drain = false; |
| 366 | int i; | ||
| 367 | 368 | ||
| 368 | spin_lock_irq(q->queue_lock); | 369 | spin_lock_irq(q->queue_lock); |
| 369 | 370 | ||
| @@ -408,6 +409,18 @@ void blk_drain_queue(struct request_queue *q, bool drain_all) | |||
| 408 | break; | 409 | break; |
| 409 | msleep(10); | 410 | msleep(10); |
| 410 | } | 411 | } |
| 412 | |||
| 413 | /* | ||
| 414 | * With queue marked dead, any woken up waiter will fail the | ||
| 415 | * allocation path, so the wakeup chaining is lost and we're | ||
| 416 | * left with hung waiters. We need to wake up those waiters. | ||
| 417 | */ | ||
| 418 | if (q->request_fn) { | ||
| 419 | spin_lock_irq(q->queue_lock); | ||
| 420 | for (i = 0; i < ARRAY_SIZE(q->rq.wait); i++) | ||
| 421 | wake_up_all(&q->rq.wait[i]); | ||
| 422 | spin_unlock_irq(q->queue_lock); | ||
| 423 | } | ||
| 411 | } | 424 | } |
| 412 | 425 | ||
| 413 | /** | 426 | /** |
| @@ -467,7 +480,6 @@ void blk_cleanup_queue(struct request_queue *q) | |||
| 467 | /* mark @q DEAD, no new request or merges will be allowed afterwards */ | 480 | /* mark @q DEAD, no new request or merges will be allowed afterwards */ |
| 468 | mutex_lock(&q->sysfs_lock); | 481 | mutex_lock(&q->sysfs_lock); |
| 469 | queue_flag_set_unlocked(QUEUE_FLAG_DEAD, q); | 482 | queue_flag_set_unlocked(QUEUE_FLAG_DEAD, q); |
| 470 | |||
| 471 | spin_lock_irq(lock); | 483 | spin_lock_irq(lock); |
| 472 | 484 | ||
| 473 | /* | 485 | /* |
| @@ -485,10 +497,6 @@ void blk_cleanup_queue(struct request_queue *q) | |||
| 485 | queue_flag_set(QUEUE_FLAG_NOMERGES, q); | 497 | queue_flag_set(QUEUE_FLAG_NOMERGES, q); |
| 486 | queue_flag_set(QUEUE_FLAG_NOXMERGES, q); | 498 | queue_flag_set(QUEUE_FLAG_NOXMERGES, q); |
| 487 | queue_flag_set(QUEUE_FLAG_DEAD, q); | 499 | queue_flag_set(QUEUE_FLAG_DEAD, q); |
| 488 | |||
| 489 | if (q->queue_lock != &q->__queue_lock) | ||
| 490 | q->queue_lock = &q->__queue_lock; | ||
| 491 | |||
| 492 | spin_unlock_irq(lock); | 500 | spin_unlock_irq(lock); |
| 493 | mutex_unlock(&q->sysfs_lock); | 501 | mutex_unlock(&q->sysfs_lock); |
| 494 | 502 | ||
| @@ -499,6 +507,11 @@ void blk_cleanup_queue(struct request_queue *q) | |||
| 499 | del_timer_sync(&q->backing_dev_info.laptop_mode_wb_timer); | 507 | del_timer_sync(&q->backing_dev_info.laptop_mode_wb_timer); |
| 500 | blk_sync_queue(q); | 508 | blk_sync_queue(q); |
| 501 | 509 | ||
| 510 | spin_lock_irq(lock); | ||
| 511 | if (q->queue_lock != &q->__queue_lock) | ||
| 512 | q->queue_lock = &q->__queue_lock; | ||
| 513 | spin_unlock_irq(lock); | ||
| 514 | |||
| 502 | /* @q is and will stay empty, shutdown and put */ | 515 | /* @q is and will stay empty, shutdown and put */ |
| 503 | blk_put_queue(q); | 516 | blk_put_queue(q); |
| 504 | } | 517 | } |
diff --git a/block/blk-timeout.c b/block/blk-timeout.c index 780354888958..6e4744cbfb56 100644 --- a/block/blk-timeout.c +++ b/block/blk-timeout.c | |||
| @@ -197,44 +197,3 @@ void blk_add_timer(struct request *req) | |||
| 197 | mod_timer(&q->timeout, expiry); | 197 | mod_timer(&q->timeout, expiry); |
| 198 | } | 198 | } |
| 199 | 199 | ||
| 200 | /** | ||
| 201 | * blk_abort_queue -- Abort all request on given queue | ||
| 202 | * @queue: pointer to queue | ||
| 203 | * | ||
| 204 | */ | ||
| 205 | void blk_abort_queue(struct request_queue *q) | ||
| 206 | { | ||
| 207 | unsigned long flags; | ||
| 208 | struct request *rq, *tmp; | ||
| 209 | LIST_HEAD(list); | ||
| 210 | |||
| 211 | /* | ||
| 212 | * Not a request based block device, nothing to abort | ||
| 213 | */ | ||
| 214 | if (!q->request_fn) | ||
| 215 | return; | ||
| 216 | |||
| 217 | spin_lock_irqsave(q->queue_lock, flags); | ||
| 218 | |||
| 219 | elv_abort_queue(q); | ||
| 220 | |||
| 221 | /* | ||
| 222 | * Splice entries to local list, to avoid deadlocking if entries | ||
| 223 | * get readded to the timeout list by error handling | ||
| 224 | */ | ||
| 225 | list_splice_init(&q->timeout_list, &list); | ||
| 226 | |||
| 227 | list_for_each_entry_safe(rq, tmp, &list, timeout_list) | ||
| 228 | blk_abort_request(rq); | ||
| 229 | |||
| 230 | /* | ||
| 231 | * Occasionally, blk_abort_request() will return without | ||
| 232 | * deleting the element from the list. Make sure we add those back | ||
| 233 | * instead of leaving them on the local stack list. | ||
| 234 | */ | ||
| 235 | list_splice(&list, &q->timeout_list); | ||
| 236 | |||
| 237 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
| 238 | |||
| 239 | } | ||
| 240 | EXPORT_SYMBOL_GPL(blk_abort_queue); | ||
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 673c977cc2bf..fb52df9744f5 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
| @@ -17,8 +17,6 @@ | |||
| 17 | #include "blk.h" | 17 | #include "blk.h" |
| 18 | #include "blk-cgroup.h" | 18 | #include "blk-cgroup.h" |
| 19 | 19 | ||
| 20 | static struct blkcg_policy blkcg_policy_cfq __maybe_unused; | ||
| 21 | |||
| 22 | /* | 20 | /* |
| 23 | * tunables | 21 | * tunables |
| 24 | */ | 22 | */ |
| @@ -418,11 +416,6 @@ static inline struct cfq_group *pd_to_cfqg(struct blkg_policy_data *pd) | |||
| 418 | return pd ? container_of(pd, struct cfq_group, pd) : NULL; | 416 | return pd ? container_of(pd, struct cfq_group, pd) : NULL; |
| 419 | } | 417 | } |
| 420 | 418 | ||
| 421 | static inline struct cfq_group *blkg_to_cfqg(struct blkcg_gq *blkg) | ||
| 422 | { | ||
| 423 | return pd_to_cfqg(blkg_to_pd(blkg, &blkcg_policy_cfq)); | ||
| 424 | } | ||
| 425 | |||
| 426 | static inline struct blkcg_gq *cfqg_to_blkg(struct cfq_group *cfqg) | 419 | static inline struct blkcg_gq *cfqg_to_blkg(struct cfq_group *cfqg) |
| 427 | { | 420 | { |
| 428 | return pd_to_blkg(&cfqg->pd); | 421 | return pd_to_blkg(&cfqg->pd); |
| @@ -572,6 +565,13 @@ static inline void cfqg_stats_update_avg_queue_size(struct cfq_group *cfqg) { } | |||
| 572 | 565 | ||
| 573 | #ifdef CONFIG_CFQ_GROUP_IOSCHED | 566 | #ifdef CONFIG_CFQ_GROUP_IOSCHED |
| 574 | 567 | ||
| 568 | static struct blkcg_policy blkcg_policy_cfq; | ||
| 569 | |||
| 570 | static inline struct cfq_group *blkg_to_cfqg(struct blkcg_gq *blkg) | ||
| 571 | { | ||
| 572 | return pd_to_cfqg(blkg_to_pd(blkg, &blkcg_policy_cfq)); | ||
| 573 | } | ||
| 574 | |||
| 575 | static inline void cfqg_get(struct cfq_group *cfqg) | 575 | static inline void cfqg_get(struct cfq_group *cfqg) |
| 576 | { | 576 | { |
| 577 | return blkg_get(cfqg_to_blkg(cfqg)); | 577 | return blkg_get(cfqg_to_blkg(cfqg)); |
| @@ -3951,10 +3951,11 @@ static void cfq_exit_queue(struct elevator_queue *e) | |||
| 3951 | 3951 | ||
| 3952 | cfq_shutdown_timer_wq(cfqd); | 3952 | cfq_shutdown_timer_wq(cfqd); |
| 3953 | 3953 | ||
| 3954 | #ifndef CONFIG_CFQ_GROUP_IOSCHED | 3954 | #ifdef CONFIG_CFQ_GROUP_IOSCHED |
| 3955 | blkcg_deactivate_policy(q, &blkcg_policy_cfq); | ||
| 3956 | #else | ||
| 3955 | kfree(cfqd->root_group); | 3957 | kfree(cfqd->root_group); |
| 3956 | #endif | 3958 | #endif |
| 3957 | blkcg_deactivate_policy(q, &blkcg_policy_cfq); | ||
| 3958 | kfree(cfqd); | 3959 | kfree(cfqd); |
| 3959 | } | 3960 | } |
| 3960 | 3961 | ||
| @@ -4194,14 +4195,15 @@ static int __init cfq_init(void) | |||
| 4194 | #ifdef CONFIG_CFQ_GROUP_IOSCHED | 4195 | #ifdef CONFIG_CFQ_GROUP_IOSCHED |
| 4195 | if (!cfq_group_idle) | 4196 | if (!cfq_group_idle) |
| 4196 | cfq_group_idle = 1; | 4197 | cfq_group_idle = 1; |
| 4197 | #else | ||
| 4198 | cfq_group_idle = 0; | ||
| 4199 | #endif | ||
| 4200 | 4198 | ||
| 4201 | ret = blkcg_policy_register(&blkcg_policy_cfq); | 4199 | ret = blkcg_policy_register(&blkcg_policy_cfq); |
| 4202 | if (ret) | 4200 | if (ret) |
| 4203 | return ret; | 4201 | return ret; |
| 4202 | #else | ||
| 4203 | cfq_group_idle = 0; | ||
| 4204 | #endif | ||
| 4204 | 4205 | ||
| 4206 | ret = -ENOMEM; | ||
| 4205 | cfq_pool = KMEM_CACHE(cfq_queue, 0); | 4207 | cfq_pool = KMEM_CACHE(cfq_queue, 0); |
| 4206 | if (!cfq_pool) | 4208 | if (!cfq_pool) |
| 4207 | goto err_pol_unreg; | 4209 | goto err_pol_unreg; |
| @@ -4215,13 +4217,17 @@ static int __init cfq_init(void) | |||
| 4215 | err_free_pool: | 4217 | err_free_pool: |
| 4216 | kmem_cache_destroy(cfq_pool); | 4218 | kmem_cache_destroy(cfq_pool); |
| 4217 | err_pol_unreg: | 4219 | err_pol_unreg: |
| 4220 | #ifdef CONFIG_CFQ_GROUP_IOSCHED | ||
| 4218 | blkcg_policy_unregister(&blkcg_policy_cfq); | 4221 | blkcg_policy_unregister(&blkcg_policy_cfq); |
| 4222 | #endif | ||
| 4219 | return ret; | 4223 | return ret; |
| 4220 | } | 4224 | } |
| 4221 | 4225 | ||
| 4222 | static void __exit cfq_exit(void) | 4226 | static void __exit cfq_exit(void) |
| 4223 | { | 4227 | { |
| 4228 | #ifdef CONFIG_CFQ_GROUP_IOSCHED | ||
| 4224 | blkcg_policy_unregister(&blkcg_policy_cfq); | 4229 | blkcg_policy_unregister(&blkcg_policy_cfq); |
| 4230 | #endif | ||
| 4225 | elv_unregister(&iosched_cfq); | 4231 | elv_unregister(&iosched_cfq); |
| 4226 | kmem_cache_destroy(cfq_pool); | 4232 | kmem_cache_destroy(cfq_pool); |
| 4227 | } | 4233 | } |
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index 260fa80ef575..9a87daa6f4fb 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c | |||
| @@ -721,11 +721,14 @@ int scsi_verify_blk_ioctl(struct block_device *bd, unsigned int cmd) | |||
| 721 | break; | 721 | break; |
| 722 | } | 722 | } |
| 723 | 723 | ||
| 724 | if (capable(CAP_SYS_RAWIO)) | ||
| 725 | return 0; | ||
| 726 | |||
| 724 | /* In particular, rule out all resets and host-specific ioctls. */ | 727 | /* In particular, rule out all resets and host-specific ioctls. */ |
| 725 | printk_ratelimited(KERN_WARNING | 728 | printk_ratelimited(KERN_WARNING |
| 726 | "%s: sending ioctl %x to a partition!\n", current->comm, cmd); | 729 | "%s: sending ioctl %x to a partition!\n", current->comm, cmd); |
| 727 | 730 | ||
| 728 | return capable(CAP_SYS_RAWIO) ? 0 : -ENOIOCTLCMD; | 731 | return -ENOIOCTLCMD; |
| 729 | } | 732 | } |
| 730 | EXPORT_SYMBOL(scsi_verify_blk_ioctl); | 733 | EXPORT_SYMBOL(scsi_verify_blk_ioctl); |
| 731 | 734 | ||
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)) { |
diff --git a/fs/splice.c b/fs/splice.c index c9f1318a3b82..7bf08fa22ec9 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
| @@ -273,13 +273,16 @@ void spd_release_page(struct splice_pipe_desc *spd, unsigned int i) | |||
| 273 | * Check if we need to grow the arrays holding pages and partial page | 273 | * Check if we need to grow the arrays holding pages and partial page |
| 274 | * descriptions. | 274 | * descriptions. |
| 275 | */ | 275 | */ |
| 276 | int splice_grow_spd(struct pipe_inode_info *pipe, struct splice_pipe_desc *spd) | 276 | int splice_grow_spd(const struct pipe_inode_info *pipe, struct splice_pipe_desc *spd) |
| 277 | { | 277 | { |
| 278 | if (pipe->buffers <= PIPE_DEF_BUFFERS) | 278 | unsigned int buffers = ACCESS_ONCE(pipe->buffers); |
| 279 | |||
| 280 | spd->nr_pages_max = buffers; | ||
| 281 | if (buffers <= PIPE_DEF_BUFFERS) | ||
| 279 | return 0; | 282 | return 0; |
| 280 | 283 | ||
| 281 | spd->pages = kmalloc(pipe->buffers * sizeof(struct page *), GFP_KERNEL); | 284 | spd->pages = kmalloc(buffers * sizeof(struct page *), GFP_KERNEL); |
| 282 | spd->partial = kmalloc(pipe->buffers * sizeof(struct partial_page), GFP_KERNEL); | 285 | spd->partial = kmalloc(buffers * sizeof(struct partial_page), GFP_KERNEL); |
| 283 | 286 | ||
| 284 | if (spd->pages && spd->partial) | 287 | if (spd->pages && spd->partial) |
| 285 | return 0; | 288 | return 0; |
| @@ -289,10 +292,9 @@ int splice_grow_spd(struct pipe_inode_info *pipe, struct splice_pipe_desc *spd) | |||
| 289 | return -ENOMEM; | 292 | return -ENOMEM; |
| 290 | } | 293 | } |
| 291 | 294 | ||
| 292 | void splice_shrink_spd(struct pipe_inode_info *pipe, | 295 | void splice_shrink_spd(struct splice_pipe_desc *spd) |
| 293 | struct splice_pipe_desc *spd) | ||
| 294 | { | 296 | { |
| 295 | if (pipe->buffers <= PIPE_DEF_BUFFERS) | 297 | if (spd->nr_pages_max <= PIPE_DEF_BUFFERS) |
| 296 | return; | 298 | return; |
| 297 | 299 | ||
| 298 | kfree(spd->pages); | 300 | kfree(spd->pages); |
| @@ -315,6 +317,7 @@ __generic_file_splice_read(struct file *in, loff_t *ppos, | |||
| 315 | struct splice_pipe_desc spd = { | 317 | struct splice_pipe_desc spd = { |
| 316 | .pages = pages, | 318 | .pages = pages, |
| 317 | .partial = partial, | 319 | .partial = partial, |
| 320 | .nr_pages_max = PIPE_DEF_BUFFERS, | ||
| 318 | .flags = flags, | 321 | .flags = flags, |
| 319 | .ops = &page_cache_pipe_buf_ops, | 322 | .ops = &page_cache_pipe_buf_ops, |
| 320 | .spd_release = spd_release_page, | 323 | .spd_release = spd_release_page, |
| @@ -326,7 +329,7 @@ __generic_file_splice_read(struct file *in, loff_t *ppos, | |||
| 326 | index = *ppos >> PAGE_CACHE_SHIFT; | 329 | index = *ppos >> PAGE_CACHE_SHIFT; |
| 327 | loff = *ppos & ~PAGE_CACHE_MASK; | 330 | loff = *ppos & ~PAGE_CACHE_MASK; |
| 328 | req_pages = (len + loff + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | 331 | req_pages = (len + loff + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; |
| 329 | nr_pages = min(req_pages, pipe->buffers); | 332 | nr_pages = min(req_pages, spd.nr_pages_max); |
| 330 | 333 | ||
| 331 | /* | 334 | /* |
| 332 | * Lookup the (hopefully) full range of pages we need. | 335 | * Lookup the (hopefully) full range of pages we need. |
| @@ -497,7 +500,7 @@ fill_it: | |||
| 497 | if (spd.nr_pages) | 500 | if (spd.nr_pages) |
| 498 | error = splice_to_pipe(pipe, &spd); | 501 | error = splice_to_pipe(pipe, &spd); |
| 499 | 502 | ||
| 500 | splice_shrink_spd(pipe, &spd); | 503 | splice_shrink_spd(&spd); |
| 501 | return error; | 504 | return error; |
| 502 | } | 505 | } |
| 503 | 506 | ||
| @@ -598,6 +601,7 @@ ssize_t default_file_splice_read(struct file *in, loff_t *ppos, | |||
| 598 | struct splice_pipe_desc spd = { | 601 | struct splice_pipe_desc spd = { |
| 599 | .pages = pages, | 602 | .pages = pages, |
| 600 | .partial = partial, | 603 | .partial = partial, |
| 604 | .nr_pages_max = PIPE_DEF_BUFFERS, | ||
| 601 | .flags = flags, | 605 | .flags = flags, |
| 602 | .ops = &default_pipe_buf_ops, | 606 | .ops = &default_pipe_buf_ops, |
| 603 | .spd_release = spd_release_page, | 607 | .spd_release = spd_release_page, |
| @@ -608,8 +612,8 @@ ssize_t default_file_splice_read(struct file *in, loff_t *ppos, | |||
| 608 | 612 | ||
| 609 | res = -ENOMEM; | 613 | res = -ENOMEM; |
| 610 | vec = __vec; | 614 | vec = __vec; |
| 611 | if (pipe->buffers > PIPE_DEF_BUFFERS) { | 615 | if (spd.nr_pages_max > PIPE_DEF_BUFFERS) { |
| 612 | vec = kmalloc(pipe->buffers * sizeof(struct iovec), GFP_KERNEL); | 616 | vec = kmalloc(spd.nr_pages_max * sizeof(struct iovec), GFP_KERNEL); |
| 613 | if (!vec) | 617 | if (!vec) |
| 614 | goto shrink_ret; | 618 | goto shrink_ret; |
| 615 | } | 619 | } |
| @@ -617,7 +621,7 @@ ssize_t default_file_splice_read(struct file *in, loff_t *ppos, | |||
| 617 | offset = *ppos & ~PAGE_CACHE_MASK; | 621 | offset = *ppos & ~PAGE_CACHE_MASK; |
| 618 | nr_pages = (len + offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | 622 | nr_pages = (len + offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; |
| 619 | 623 | ||
| 620 | for (i = 0; i < nr_pages && i < pipe->buffers && len; i++) { | 624 | for (i = 0; i < nr_pages && i < spd.nr_pages_max && len; i++) { |
| 621 | struct page *page; | 625 | struct page *page; |
| 622 | 626 | ||
| 623 | page = alloc_page(GFP_USER); | 627 | page = alloc_page(GFP_USER); |
| @@ -665,7 +669,7 @@ ssize_t default_file_splice_read(struct file *in, loff_t *ppos, | |||
| 665 | shrink_ret: | 669 | shrink_ret: |
| 666 | if (vec != __vec) | 670 | if (vec != __vec) |
| 667 | kfree(vec); | 671 | kfree(vec); |
| 668 | splice_shrink_spd(pipe, &spd); | 672 | splice_shrink_spd(&spd); |
| 669 | return res; | 673 | return res; |
| 670 | 674 | ||
| 671 | err: | 675 | err: |
| @@ -1614,6 +1618,7 @@ static long vmsplice_to_pipe(struct file *file, const struct iovec __user *iov, | |||
| 1614 | struct splice_pipe_desc spd = { | 1618 | struct splice_pipe_desc spd = { |
| 1615 | .pages = pages, | 1619 | .pages = pages, |
| 1616 | .partial = partial, | 1620 | .partial = partial, |
| 1621 | .nr_pages_max = PIPE_DEF_BUFFERS, | ||
| 1617 | .flags = flags, | 1622 | .flags = flags, |
| 1618 | .ops = &user_page_pipe_buf_ops, | 1623 | .ops = &user_page_pipe_buf_ops, |
| 1619 | .spd_release = spd_release_page, | 1624 | .spd_release = spd_release_page, |
| @@ -1629,13 +1634,13 @@ static long vmsplice_to_pipe(struct file *file, const struct iovec __user *iov, | |||
| 1629 | 1634 | ||
| 1630 | spd.nr_pages = get_iovec_page_array(iov, nr_segs, spd.pages, | 1635 | spd.nr_pages = get_iovec_page_array(iov, nr_segs, spd.pages, |
| 1631 | spd.partial, false, | 1636 | spd.partial, false, |
| 1632 | pipe->buffers); | 1637 | spd.nr_pages_max); |
| 1633 | if (spd.nr_pages <= 0) | 1638 | if (spd.nr_pages <= 0) |
| 1634 | ret = spd.nr_pages; | 1639 | ret = spd.nr_pages; |
| 1635 | else | 1640 | else |
| 1636 | ret = splice_to_pipe(pipe, &spd); | 1641 | ret = splice_to_pipe(pipe, &spd); |
| 1637 | 1642 | ||
| 1638 | splice_shrink_spd(pipe, &spd); | 1643 | splice_shrink_spd(&spd); |
| 1639 | return ret; | 1644 | return ret; |
| 1640 | } | 1645 | } |
| 1641 | 1646 | ||
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index ba43f408baa3..07954b05b86c 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h | |||
| @@ -827,7 +827,6 @@ extern bool __blk_end_request_err(struct request *rq, int error); | |||
| 827 | extern void blk_complete_request(struct request *); | 827 | extern void blk_complete_request(struct request *); |
| 828 | extern void __blk_complete_request(struct request *); | 828 | extern void __blk_complete_request(struct request *); |
| 829 | extern void blk_abort_request(struct request *); | 829 | extern void blk_abort_request(struct request *); |
| 830 | extern void blk_abort_queue(struct request_queue *); | ||
| 831 | extern void blk_unprep_request(struct request *); | 830 | extern void blk_unprep_request(struct request *); |
| 832 | 831 | ||
| 833 | /* | 832 | /* |
diff --git a/include/linux/splice.h b/include/linux/splice.h index 26e5b613deda..09a545a7dfa3 100644 --- a/include/linux/splice.h +++ b/include/linux/splice.h | |||
| @@ -51,7 +51,8 @@ struct partial_page { | |||
| 51 | struct splice_pipe_desc { | 51 | struct splice_pipe_desc { |
| 52 | struct page **pages; /* page map */ | 52 | struct page **pages; /* page map */ |
| 53 | struct partial_page *partial; /* pages[] may not be contig */ | 53 | struct partial_page *partial; /* pages[] may not be contig */ |
| 54 | int nr_pages; /* number of pages in map */ | 54 | int nr_pages; /* number of populated pages in map */ |
| 55 | unsigned int nr_pages_max; /* pages[] & partial[] arrays size */ | ||
| 55 | unsigned int flags; /* splice flags */ | 56 | unsigned int flags; /* splice flags */ |
| 56 | const struct pipe_buf_operations *ops;/* ops associated with output pipe */ | 57 | const struct pipe_buf_operations *ops;/* ops associated with output pipe */ |
| 57 | void (*spd_release)(struct splice_pipe_desc *, unsigned int); | 58 | void (*spd_release)(struct splice_pipe_desc *, unsigned int); |
| @@ -85,9 +86,8 @@ extern ssize_t splice_direct_to_actor(struct file *, struct splice_desc *, | |||
| 85 | /* | 86 | /* |
| 86 | * for dynamic pipe sizing | 87 | * for dynamic pipe sizing |
| 87 | */ | 88 | */ |
| 88 | extern int splice_grow_spd(struct pipe_inode_info *, struct splice_pipe_desc *); | 89 | extern int splice_grow_spd(const struct pipe_inode_info *, struct splice_pipe_desc *); |
| 89 | extern void splice_shrink_spd(struct pipe_inode_info *, | 90 | extern void splice_shrink_spd(struct splice_pipe_desc *); |
| 90 | struct splice_pipe_desc *); | ||
| 91 | extern void spd_release_page(struct splice_pipe_desc *, unsigned int); | 91 | extern void spd_release_page(struct splice_pipe_desc *, unsigned int); |
| 92 | 92 | ||
| 93 | extern const struct pipe_buf_operations page_cache_pipe_buf_ops; | 93 | extern const struct pipe_buf_operations page_cache_pipe_buf_ops; |
diff --git a/kernel/relay.c b/kernel/relay.c index ab56a1764d4d..e8cd2027abbd 100644 --- a/kernel/relay.c +++ b/kernel/relay.c | |||
| @@ -1235,6 +1235,7 @@ static ssize_t subbuf_splice_actor(struct file *in, | |||
| 1235 | struct splice_pipe_desc spd = { | 1235 | struct splice_pipe_desc spd = { |
| 1236 | .pages = pages, | 1236 | .pages = pages, |
| 1237 | .nr_pages = 0, | 1237 | .nr_pages = 0, |
| 1238 | .nr_pages_max = PIPE_DEF_BUFFERS, | ||
| 1238 | .partial = partial, | 1239 | .partial = partial, |
| 1239 | .flags = flags, | 1240 | .flags = flags, |
| 1240 | .ops = &relay_pipe_buf_ops, | 1241 | .ops = &relay_pipe_buf_ops, |
| @@ -1302,8 +1303,8 @@ static ssize_t subbuf_splice_actor(struct file *in, | |||
| 1302 | ret += padding; | 1303 | ret += padding; |
| 1303 | 1304 | ||
| 1304 | out: | 1305 | out: |
| 1305 | splice_shrink_spd(pipe, &spd); | 1306 | splice_shrink_spd(&spd); |
| 1306 | return ret; | 1307 | return ret; |
| 1307 | } | 1308 | } |
| 1308 | 1309 | ||
| 1309 | static ssize_t relay_file_splice_read(struct file *in, | 1310 | static ssize_t relay_file_splice_read(struct file *in, |
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 49249c28690d..a7fa0702be1c 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
| @@ -3609,6 +3609,7 @@ static ssize_t tracing_splice_read_pipe(struct file *filp, | |||
| 3609 | .pages = pages_def, | 3609 | .pages = pages_def, |
| 3610 | .partial = partial_def, | 3610 | .partial = partial_def, |
| 3611 | .nr_pages = 0, /* This gets updated below. */ | 3611 | .nr_pages = 0, /* This gets updated below. */ |
| 3612 | .nr_pages_max = PIPE_DEF_BUFFERS, | ||
| 3612 | .flags = flags, | 3613 | .flags = flags, |
| 3613 | .ops = &tracing_pipe_buf_ops, | 3614 | .ops = &tracing_pipe_buf_ops, |
| 3614 | .spd_release = tracing_spd_release_pipe, | 3615 | .spd_release = tracing_spd_release_pipe, |
| @@ -3680,7 +3681,7 @@ static ssize_t tracing_splice_read_pipe(struct file *filp, | |||
| 3680 | 3681 | ||
| 3681 | ret = splice_to_pipe(pipe, &spd); | 3682 | ret = splice_to_pipe(pipe, &spd); |
| 3682 | out: | 3683 | out: |
| 3683 | splice_shrink_spd(pipe, &spd); | 3684 | splice_shrink_spd(&spd); |
| 3684 | return ret; | 3685 | return ret; |
| 3685 | 3686 | ||
| 3686 | out_err: | 3687 | out_err: |
| @@ -4231,6 +4232,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, | |||
| 4231 | struct splice_pipe_desc spd = { | 4232 | struct splice_pipe_desc spd = { |
| 4232 | .pages = pages_def, | 4233 | .pages = pages_def, |
| 4233 | .partial = partial_def, | 4234 | .partial = partial_def, |
| 4235 | .nr_pages_max = PIPE_DEF_BUFFERS, | ||
| 4234 | .flags = flags, | 4236 | .flags = flags, |
| 4235 | .ops = &buffer_pipe_buf_ops, | 4237 | .ops = &buffer_pipe_buf_ops, |
| 4236 | .spd_release = buffer_spd_release, | 4238 | .spd_release = buffer_spd_release, |
| @@ -4318,7 +4320,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, | |||
| 4318 | } | 4320 | } |
| 4319 | 4321 | ||
| 4320 | ret = splice_to_pipe(pipe, &spd); | 4322 | ret = splice_to_pipe(pipe, &spd); |
| 4321 | splice_shrink_spd(pipe, &spd); | 4323 | splice_shrink_spd(&spd); |
| 4322 | out: | 4324 | out: |
| 4323 | return ret; | 4325 | return ret; |
| 4324 | } | 4326 | } |
diff --git a/mm/shmem.c b/mm/shmem.c index a15a466d0d1d..4ce02e0673db 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
| @@ -1594,6 +1594,7 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos, | |||
| 1594 | struct splice_pipe_desc spd = { | 1594 | struct splice_pipe_desc spd = { |
| 1595 | .pages = pages, | 1595 | .pages = pages, |
| 1596 | .partial = partial, | 1596 | .partial = partial, |
| 1597 | .nr_pages_max = PIPE_DEF_BUFFERS, | ||
| 1597 | .flags = flags, | 1598 | .flags = flags, |
| 1598 | .ops = &page_cache_pipe_buf_ops, | 1599 | .ops = &page_cache_pipe_buf_ops, |
| 1599 | .spd_release = spd_release_page, | 1600 | .spd_release = spd_release_page, |
| @@ -1682,7 +1683,7 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos, | |||
| 1682 | if (spd.nr_pages) | 1683 | if (spd.nr_pages) |
| 1683 | error = splice_to_pipe(pipe, &spd); | 1684 | error = splice_to_pipe(pipe, &spd); |
| 1684 | 1685 | ||
| 1685 | splice_shrink_spd(pipe, &spd); | 1686 | splice_shrink_spd(&spd); |
| 1686 | 1687 | ||
| 1687 | if (error > 0) { | 1688 | if (error > 0) { |
| 1688 | *ppos += error; | 1689 | *ppos += error; |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index d78671e9d545..46a3d23d259e 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
| @@ -1755,6 +1755,7 @@ int skb_splice_bits(struct sk_buff *skb, unsigned int offset, | |||
| 1755 | struct splice_pipe_desc spd = { | 1755 | struct splice_pipe_desc spd = { |
| 1756 | .pages = pages, | 1756 | .pages = pages, |
| 1757 | .partial = partial, | 1757 | .partial = partial, |
| 1758 | .nr_pages_max = MAX_SKB_FRAGS, | ||
| 1758 | .flags = flags, | 1759 | .flags = flags, |
| 1759 | .ops = &sock_pipe_buf_ops, | 1760 | .ops = &sock_pipe_buf_ops, |
| 1760 | .spd_release = sock_spd_release, | 1761 | .spd_release = sock_spd_release, |
