diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-10 20:04:23 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-10 20:04:23 -0400 |
| commit | ce40be7a820bb393ac4ac69865f018d2f4038cf0 (patch) | |
| tree | b1fe5a93346eb06f22b1c303d63ec5456d7212ab /include/linux | |
| parent | ba0a5a36f60e4c1152af3a2ae2813251974405bf (diff) | |
| parent | 02f3939e1a9357b7c370a4a69717cf9c02452737 (diff) | |
Merge branch 'for-3.7/core' of git://git.kernel.dk/linux-block
Pull block IO update from Jens Axboe:
"Core block IO bits for 3.7. Not a huge round this time, it contains:
- First series from Kent cleaning up and generalizing bio allocation
and freeing.
- WRITE_SAME support from Martin.
- Mikulas patches to prevent O_DIRECT crashes when someone changes
the block size of a device.
- Make bio_split() work on data-less bio's (like trim/discards).
- A few other minor fixups."
Fixed up silent semantic mis-merge as per Mikulas Patocka and Andrew
Morton. It is due to the VM no longer using a prio-tree (see commit
6b2dbba8b6ac: "mm: replace vma prio_tree with an interval tree").
So make set_blocksize() use mapping_mapped() instead of open-coding the
internal VM knowledge that has changed.
* 'for-3.7/core' of git://git.kernel.dk/linux-block: (26 commits)
block: makes bio_split support bio without data
scatterlist: refactor the sg_nents
scatterlist: add sg_nents
fs: fix include/percpu-rwsem.h export error
percpu-rw-semaphore: fix documentation typos
fs/block_dev.c:1644:5: sparse: symbol 'blkdev_mmap' was not declared
blockdev: turn a rw semaphore into a percpu rw semaphore
Fix a crash when block device is read and block size is changed at the same time
block: fix request_queue->flags initialization
block: lift the initial queue bypass mode on blk_register_queue() instead of blk_init_allocated_queue()
block: ioctl to zero block ranges
block: Make blkdev_issue_zeroout use WRITE SAME
block: Implement support for WRITE SAME
block: Consolidate command flag and queue limit checks for merges
block: Clean up special command handling logic
block/blk-tag.c: Remove useless kfree
block: remove the duplicated setting for congestion_threshold
block: reject invalid queue attribute values
block: Add bio_clone_bioset(), bio_clone_kmalloc()
block: Consolidate bio_alloc_bioset(), bio_kmalloc()
...
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/bio.h | 70 | ||||
| -rw-r--r-- | include/linux/blk_types.h | 36 | ||||
| -rw-r--r-- | include/linux/blkdev.h | 82 | ||||
| -rw-r--r-- | include/linux/fs.h | 6 | ||||
| -rw-r--r-- | include/linux/percpu-rwsem.h | 89 | ||||
| -rw-r--r-- | include/linux/scatterlist.h | 1 |
6 files changed, 249 insertions, 35 deletions
diff --git a/include/linux/bio.h b/include/linux/bio.h index 26435890dc87..820e7aaad4fd 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h | |||
| @@ -212,20 +212,41 @@ extern void bio_pair_release(struct bio_pair *dbio); | |||
| 212 | extern struct bio_set *bioset_create(unsigned int, unsigned int); | 212 | extern struct bio_set *bioset_create(unsigned int, unsigned int); |
| 213 | extern void bioset_free(struct bio_set *); | 213 | extern void bioset_free(struct bio_set *); |
| 214 | 214 | ||
| 215 | extern struct bio *bio_alloc(gfp_t, unsigned int); | ||
| 216 | extern struct bio *bio_kmalloc(gfp_t, unsigned int); | ||
| 217 | extern struct bio *bio_alloc_bioset(gfp_t, int, struct bio_set *); | 215 | extern struct bio *bio_alloc_bioset(gfp_t, int, struct bio_set *); |
| 218 | extern void bio_put(struct bio *); | 216 | extern void bio_put(struct bio *); |
| 219 | extern void bio_free(struct bio *, struct bio_set *); | 217 | |
| 218 | extern void __bio_clone(struct bio *, struct bio *); | ||
| 219 | extern struct bio *bio_clone_bioset(struct bio *, gfp_t, struct bio_set *bs); | ||
| 220 | |||
| 221 | extern struct bio_set *fs_bio_set; | ||
| 222 | |||
| 223 | static inline struct bio *bio_alloc(gfp_t gfp_mask, unsigned int nr_iovecs) | ||
| 224 | { | ||
| 225 | return bio_alloc_bioset(gfp_mask, nr_iovecs, fs_bio_set); | ||
| 226 | } | ||
| 227 | |||
| 228 | static inline struct bio *bio_clone(struct bio *bio, gfp_t gfp_mask) | ||
| 229 | { | ||
| 230 | return bio_clone_bioset(bio, gfp_mask, fs_bio_set); | ||
| 231 | } | ||
| 232 | |||
| 233 | static inline struct bio *bio_kmalloc(gfp_t gfp_mask, unsigned int nr_iovecs) | ||
| 234 | { | ||
| 235 | return bio_alloc_bioset(gfp_mask, nr_iovecs, NULL); | ||
| 236 | } | ||
| 237 | |||
| 238 | static inline struct bio *bio_clone_kmalloc(struct bio *bio, gfp_t gfp_mask) | ||
| 239 | { | ||
| 240 | return bio_clone_bioset(bio, gfp_mask, NULL); | ||
| 241 | |||
| 242 | } | ||
| 220 | 243 | ||
| 221 | extern void bio_endio(struct bio *, int); | 244 | extern void bio_endio(struct bio *, int); |
| 222 | struct request_queue; | 245 | struct request_queue; |
| 223 | extern int bio_phys_segments(struct request_queue *, struct bio *); | 246 | extern int bio_phys_segments(struct request_queue *, struct bio *); |
| 224 | 247 | ||
| 225 | extern void __bio_clone(struct bio *, struct bio *); | ||
| 226 | extern struct bio *bio_clone(struct bio *, gfp_t); | ||
| 227 | |||
| 228 | extern void bio_init(struct bio *); | 248 | extern void bio_init(struct bio *); |
| 249 | extern void bio_reset(struct bio *); | ||
| 229 | 250 | ||
| 230 | extern int bio_add_page(struct bio *, struct page *, unsigned int,unsigned int); | 251 | extern int bio_add_page(struct bio *, struct page *, unsigned int,unsigned int); |
| 231 | extern int bio_add_pc_page(struct request_queue *, struct bio *, struct page *, | 252 | extern int bio_add_pc_page(struct request_queue *, struct bio *, struct page *, |
| @@ -304,8 +325,6 @@ struct biovec_slab { | |||
| 304 | struct kmem_cache *slab; | 325 | struct kmem_cache *slab; |
| 305 | }; | 326 | }; |
| 306 | 327 | ||
| 307 | extern struct bio_set *fs_bio_set; | ||
| 308 | |||
| 309 | /* | 328 | /* |
| 310 | * a small number of entries is fine, not going to be performance critical. | 329 | * a small number of entries is fine, not going to be performance critical. |
| 311 | * basically we just need to survive | 330 | * basically we just need to survive |
| @@ -367,9 +386,31 @@ static inline char *__bio_kmap_irq(struct bio *bio, unsigned short idx, | |||
| 367 | /* | 386 | /* |
| 368 | * Check whether this bio carries any data or not. A NULL bio is allowed. | 387 | * Check whether this bio carries any data or not. A NULL bio is allowed. |
| 369 | */ | 388 | */ |
| 370 | static inline int bio_has_data(struct bio *bio) | 389 | static inline bool bio_has_data(struct bio *bio) |
| 371 | { | 390 | { |
| 372 | return bio && bio->bi_io_vec != NULL; | 391 | if (bio && bio->bi_vcnt) |
| 392 | return true; | ||
| 393 | |||
| 394 | return false; | ||
| 395 | } | ||
| 396 | |||
| 397 | static inline bool bio_is_rw(struct bio *bio) | ||
| 398 | { | ||
| 399 | if (!bio_has_data(bio)) | ||
| 400 | return false; | ||
| 401 | |||
| 402 | if (bio->bi_rw & REQ_WRITE_SAME) | ||
| 403 | return false; | ||
| 404 | |||
| 405 | return true; | ||
| 406 | } | ||
| 407 | |||
| 408 | static inline bool bio_mergeable(struct bio *bio) | ||
| 409 | { | ||
| 410 | if (bio->bi_rw & REQ_NOMERGE_FLAGS) | ||
| 411 | return false; | ||
| 412 | |||
| 413 | return true; | ||
| 373 | } | 414 | } |
| 374 | 415 | ||
| 375 | /* | 416 | /* |
| @@ -505,9 +546,8 @@ static inline struct bio *bio_list_get(struct bio_list *bl) | |||
| 505 | 546 | ||
| 506 | #define bio_integrity(bio) (bio->bi_integrity != NULL) | 547 | #define bio_integrity(bio) (bio->bi_integrity != NULL) |
| 507 | 548 | ||
| 508 | extern struct bio_integrity_payload *bio_integrity_alloc_bioset(struct bio *, gfp_t, unsigned int, struct bio_set *); | ||
| 509 | extern struct bio_integrity_payload *bio_integrity_alloc(struct bio *, gfp_t, unsigned int); | 549 | extern struct bio_integrity_payload *bio_integrity_alloc(struct bio *, gfp_t, unsigned int); |
| 510 | extern void bio_integrity_free(struct bio *, struct bio_set *); | 550 | extern void bio_integrity_free(struct bio *); |
| 511 | extern int bio_integrity_add_page(struct bio *, struct page *, unsigned int, unsigned int); | 551 | extern int bio_integrity_add_page(struct bio *, struct page *, unsigned int, unsigned int); |
| 512 | extern int bio_integrity_enabled(struct bio *bio); | 552 | extern int bio_integrity_enabled(struct bio *bio); |
| 513 | extern int bio_integrity_set_tag(struct bio *, void *, unsigned int); | 553 | extern int bio_integrity_set_tag(struct bio *, void *, unsigned int); |
| @@ -517,7 +557,7 @@ extern void bio_integrity_endio(struct bio *, int); | |||
| 517 | extern void bio_integrity_advance(struct bio *, unsigned int); | 557 | extern void bio_integrity_advance(struct bio *, unsigned int); |
| 518 | extern void bio_integrity_trim(struct bio *, unsigned int, unsigned int); | 558 | extern void bio_integrity_trim(struct bio *, unsigned int, unsigned int); |
| 519 | extern void bio_integrity_split(struct bio *, struct bio_pair *, int); | 559 | extern void bio_integrity_split(struct bio *, struct bio_pair *, int); |
| 520 | extern int bio_integrity_clone(struct bio *, struct bio *, gfp_t, struct bio_set *); | 560 | extern int bio_integrity_clone(struct bio *, struct bio *, gfp_t); |
| 521 | extern int bioset_integrity_create(struct bio_set *, int); | 561 | extern int bioset_integrity_create(struct bio_set *, int); |
| 522 | extern void bioset_integrity_free(struct bio_set *); | 562 | extern void bioset_integrity_free(struct bio_set *); |
| 523 | extern void bio_integrity_init(void); | 563 | extern void bio_integrity_init(void); |
| @@ -549,13 +589,13 @@ static inline int bio_integrity_prep(struct bio *bio) | |||
| 549 | return 0; | 589 | return 0; |
| 550 | } | 590 | } |
| 551 | 591 | ||
| 552 | static inline void bio_integrity_free(struct bio *bio, struct bio_set *bs) | 592 | static inline void bio_integrity_free(struct bio *bio) |
| 553 | { | 593 | { |
| 554 | return; | 594 | return; |
| 555 | } | 595 | } |
| 556 | 596 | ||
| 557 | static inline int bio_integrity_clone(struct bio *bio, struct bio *bio_src, | 597 | static inline int bio_integrity_clone(struct bio *bio, struct bio *bio_src, |
| 558 | gfp_t gfp_mask, struct bio_set *bs) | 598 | gfp_t gfp_mask) |
| 559 | { | 599 | { |
| 560 | return 0; | 600 | return 0; |
| 561 | } | 601 | } |
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 7b7ac9ccec7a..cdf11191e645 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h | |||
| @@ -59,12 +59,6 @@ struct bio { | |||
| 59 | unsigned int bi_seg_front_size; | 59 | unsigned int bi_seg_front_size; |
| 60 | unsigned int bi_seg_back_size; | 60 | unsigned int bi_seg_back_size; |
| 61 | 61 | ||
| 62 | unsigned int bi_max_vecs; /* max bvl_vecs we can hold */ | ||
| 63 | |||
| 64 | atomic_t bi_cnt; /* pin count */ | ||
| 65 | |||
| 66 | struct bio_vec *bi_io_vec; /* the actual vec list */ | ||
| 67 | |||
| 68 | bio_end_io_t *bi_end_io; | 62 | bio_end_io_t *bi_end_io; |
| 69 | 63 | ||
| 70 | void *bi_private; | 64 | void *bi_private; |
| @@ -80,7 +74,17 @@ struct bio { | |||
| 80 | struct bio_integrity_payload *bi_integrity; /* data integrity */ | 74 | struct bio_integrity_payload *bi_integrity; /* data integrity */ |
| 81 | #endif | 75 | #endif |
| 82 | 76 | ||
| 83 | bio_destructor_t *bi_destructor; /* destructor */ | 77 | /* |
| 78 | * Everything starting with bi_max_vecs will be preserved by bio_reset() | ||
| 79 | */ | ||
| 80 | |||
| 81 | unsigned int bi_max_vecs; /* max bvl_vecs we can hold */ | ||
| 82 | |||
| 83 | atomic_t bi_cnt; /* pin count */ | ||
| 84 | |||
| 85 | struct bio_vec *bi_io_vec; /* the actual vec list */ | ||
| 86 | |||
| 87 | struct bio_set *bi_pool; | ||
| 84 | 88 | ||
| 85 | /* | 89 | /* |
| 86 | * We can inline a number of vecs at the end of the bio, to avoid | 90 | * We can inline a number of vecs at the end of the bio, to avoid |
| @@ -90,6 +94,8 @@ struct bio { | |||
| 90 | struct bio_vec bi_inline_vecs[0]; | 94 | struct bio_vec bi_inline_vecs[0]; |
| 91 | }; | 95 | }; |
| 92 | 96 | ||
| 97 | #define BIO_RESET_BYTES offsetof(struct bio, bi_max_vecs) | ||
| 98 | |||
| 93 | /* | 99 | /* |
| 94 | * bio flags | 100 | * bio flags |
| 95 | */ | 101 | */ |
| @@ -105,6 +111,13 @@ struct bio { | |||
| 105 | #define BIO_FS_INTEGRITY 9 /* fs owns integrity data, not block layer */ | 111 | #define BIO_FS_INTEGRITY 9 /* fs owns integrity data, not block layer */ |
| 106 | #define BIO_QUIET 10 /* Make BIO Quiet */ | 112 | #define BIO_QUIET 10 /* Make BIO Quiet */ |
| 107 | #define BIO_MAPPED_INTEGRITY 11/* integrity metadata has been remapped */ | 113 | #define BIO_MAPPED_INTEGRITY 11/* integrity metadata has been remapped */ |
| 114 | |||
| 115 | /* | ||
| 116 | * Flags starting here get preserved by bio_reset() - this includes | ||
| 117 | * BIO_POOL_IDX() | ||
| 118 | */ | ||
| 119 | #define BIO_RESET_BITS 12 | ||
| 120 | |||
| 108 | #define bio_flagged(bio, flag) ((bio)->bi_flags & (1 << (flag))) | 121 | #define bio_flagged(bio, flag) ((bio)->bi_flags & (1 << (flag))) |
| 109 | 122 | ||
| 110 | /* | 123 | /* |
| @@ -134,6 +147,7 @@ enum rq_flag_bits { | |||
| 134 | __REQ_PRIO, /* boost priority in cfq */ | 147 | __REQ_PRIO, /* boost priority in cfq */ |
| 135 | __REQ_DISCARD, /* request to discard sectors */ | 148 | __REQ_DISCARD, /* request to discard sectors */ |
| 136 | __REQ_SECURE, /* secure discard (used with __REQ_DISCARD) */ | 149 | __REQ_SECURE, /* secure discard (used with __REQ_DISCARD) */ |
| 150 | __REQ_WRITE_SAME, /* write same block many times */ | ||
| 137 | 151 | ||
| 138 | __REQ_NOIDLE, /* don't anticipate more IO after this one */ | 152 | __REQ_NOIDLE, /* don't anticipate more IO after this one */ |
| 139 | __REQ_FUA, /* forced unit access */ | 153 | __REQ_FUA, /* forced unit access */ |
| @@ -172,15 +186,21 @@ enum rq_flag_bits { | |||
| 172 | #define REQ_META (1 << __REQ_META) | 186 | #define REQ_META (1 << __REQ_META) |
| 173 | #define REQ_PRIO (1 << __REQ_PRIO) | 187 | #define REQ_PRIO (1 << __REQ_PRIO) |
| 174 | #define REQ_DISCARD (1 << __REQ_DISCARD) | 188 | #define REQ_DISCARD (1 << __REQ_DISCARD) |
| 189 | #define REQ_WRITE_SAME (1 << __REQ_WRITE_SAME) | ||
| 175 | #define REQ_NOIDLE (1 << __REQ_NOIDLE) | 190 | #define REQ_NOIDLE (1 << __REQ_NOIDLE) |
| 176 | 191 | ||
| 177 | #define REQ_FAILFAST_MASK \ | 192 | #define REQ_FAILFAST_MASK \ |
| 178 | (REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER) | 193 | (REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER) |
| 179 | #define REQ_COMMON_MASK \ | 194 | #define REQ_COMMON_MASK \ |
| 180 | (REQ_WRITE | REQ_FAILFAST_MASK | REQ_SYNC | REQ_META | REQ_PRIO | \ | 195 | (REQ_WRITE | REQ_FAILFAST_MASK | REQ_SYNC | REQ_META | REQ_PRIO | \ |
| 181 | REQ_DISCARD | REQ_NOIDLE | REQ_FLUSH | REQ_FUA | REQ_SECURE) | 196 | REQ_DISCARD | REQ_WRITE_SAME | REQ_NOIDLE | REQ_FLUSH | REQ_FUA | \ |
| 197 | REQ_SECURE) | ||
| 182 | #define REQ_CLONE_MASK REQ_COMMON_MASK | 198 | #define REQ_CLONE_MASK REQ_COMMON_MASK |
| 183 | 199 | ||
| 200 | /* This mask is used for both bio and request merge checking */ | ||
| 201 | #define REQ_NOMERGE_FLAGS \ | ||
| 202 | (REQ_NOMERGE | REQ_STARTED | REQ_SOFTBARRIER | REQ_FLUSH | REQ_FUA) | ||
| 203 | |||
| 184 | #define REQ_RAHEAD (1 << __REQ_RAHEAD) | 204 | #define REQ_RAHEAD (1 << __REQ_RAHEAD) |
| 185 | #define REQ_THROTTLED (1 << __REQ_THROTTLED) | 205 | #define REQ_THROTTLED (1 << __REQ_THROTTLED) |
| 186 | 206 | ||
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 4a2ab7c85393..1756001210d2 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h | |||
| @@ -270,6 +270,7 @@ struct queue_limits { | |||
| 270 | unsigned int io_min; | 270 | unsigned int io_min; |
| 271 | unsigned int io_opt; | 271 | unsigned int io_opt; |
| 272 | unsigned int max_discard_sectors; | 272 | unsigned int max_discard_sectors; |
| 273 | unsigned int max_write_same_sectors; | ||
| 273 | unsigned int discard_granularity; | 274 | unsigned int discard_granularity; |
| 274 | unsigned int discard_alignment; | 275 | unsigned int discard_alignment; |
| 275 | 276 | ||
| @@ -540,8 +541,7 @@ static inline void queue_flag_clear(unsigned int flag, struct request_queue *q) | |||
| 540 | 541 | ||
| 541 | #define blk_account_rq(rq) \ | 542 | #define blk_account_rq(rq) \ |
| 542 | (((rq)->cmd_flags & REQ_STARTED) && \ | 543 | (((rq)->cmd_flags & REQ_STARTED) && \ |
| 543 | ((rq)->cmd_type == REQ_TYPE_FS || \ | 544 | ((rq)->cmd_type == REQ_TYPE_FS)) |
| 544 | ((rq)->cmd_flags & REQ_DISCARD))) | ||
| 545 | 545 | ||
| 546 | #define blk_pm_request(rq) \ | 546 | #define blk_pm_request(rq) \ |
| 547 | ((rq)->cmd_type == REQ_TYPE_PM_SUSPEND || \ | 547 | ((rq)->cmd_type == REQ_TYPE_PM_SUSPEND || \ |
| @@ -595,17 +595,39 @@ static inline void blk_clear_rl_full(struct request_list *rl, bool sync) | |||
| 595 | rl->flags &= ~flag; | 595 | rl->flags &= ~flag; |
| 596 | } | 596 | } |
| 597 | 597 | ||
| 598 | static inline bool rq_mergeable(struct request *rq) | ||
| 599 | { | ||
| 600 | if (rq->cmd_type != REQ_TYPE_FS) | ||
| 601 | return false; | ||
| 598 | 602 | ||
| 599 | /* | 603 | if (rq->cmd_flags & REQ_NOMERGE_FLAGS) |
| 600 | * mergeable request must not have _NOMERGE or _BARRIER bit set, nor may | 604 | return false; |
| 601 | * it already be started by driver. | 605 | |
| 602 | */ | 606 | return true; |
| 603 | #define RQ_NOMERGE_FLAGS \ | 607 | } |
| 604 | (REQ_NOMERGE | REQ_STARTED | REQ_SOFTBARRIER | REQ_FLUSH | REQ_FUA | REQ_DISCARD) | 608 | |
| 605 | #define rq_mergeable(rq) \ | 609 | static inline bool blk_check_merge_flags(unsigned int flags1, |
| 606 | (!((rq)->cmd_flags & RQ_NOMERGE_FLAGS) && \ | 610 | unsigned int flags2) |
| 607 | (((rq)->cmd_flags & REQ_DISCARD) || \ | 611 | { |
| 608 | (rq)->cmd_type == REQ_TYPE_FS)) | 612 | if ((flags1 & REQ_DISCARD) != (flags2 & REQ_DISCARD)) |
| 613 | return false; | ||
| 614 | |||
| 615 | if ((flags1 & REQ_SECURE) != (flags2 & REQ_SECURE)) | ||
| 616 | return false; | ||
| 617 | |||
| 618 | if ((flags1 & REQ_WRITE_SAME) != (flags2 & REQ_WRITE_SAME)) | ||
| 619 | return false; | ||
| 620 | |||
| 621 | return true; | ||
| 622 | } | ||
| 623 | |||
| 624 | static inline bool blk_write_same_mergeable(struct bio *a, struct bio *b) | ||
| 625 | { | ||
| 626 | if (bio_data(a) == bio_data(b)) | ||
| 627 | return true; | ||
| 628 | |||
| 629 | return false; | ||
| 630 | } | ||
| 609 | 631 | ||
| 610 | /* | 632 | /* |
| 611 | * q->prep_rq_fn return values | 633 | * q->prep_rq_fn return values |
| @@ -802,6 +824,28 @@ static inline unsigned int blk_rq_cur_sectors(const struct request *rq) | |||
| 802 | return blk_rq_cur_bytes(rq) >> 9; | 824 | return blk_rq_cur_bytes(rq) >> 9; |
| 803 | } | 825 | } |
| 804 | 826 | ||
| 827 | static inline unsigned int blk_queue_get_max_sectors(struct request_queue *q, | ||
| 828 | unsigned int cmd_flags) | ||
| 829 | { | ||
| 830 | if (unlikely(cmd_flags & REQ_DISCARD)) | ||
| 831 | return q->limits.max_discard_sectors; | ||
| 832 | |||
| 833 | if (unlikely(cmd_flags & REQ_WRITE_SAME)) | ||
| 834 | return q->limits.max_write_same_sectors; | ||
| 835 | |||
| 836 | return q->limits.max_sectors; | ||
| 837 | } | ||
| 838 | |||
| 839 | static inline unsigned int blk_rq_get_max_sectors(struct request *rq) | ||
| 840 | { | ||
| 841 | struct request_queue *q = rq->q; | ||
| 842 | |||
| 843 | if (unlikely(rq->cmd_type == REQ_TYPE_BLOCK_PC)) | ||
| 844 | return q->limits.max_hw_sectors; | ||
| 845 | |||
| 846 | return blk_queue_get_max_sectors(q, rq->cmd_flags); | ||
| 847 | } | ||
| 848 | |||
| 805 | /* | 849 | /* |
| 806 | * Request issue related functions. | 850 | * Request issue related functions. |
| 807 | */ | 851 | */ |
| @@ -857,6 +901,8 @@ extern void blk_queue_max_segments(struct request_queue *, unsigned short); | |||
| 857 | extern void blk_queue_max_segment_size(struct request_queue *, unsigned int); | 901 | extern void blk_queue_max_segment_size(struct request_queue *, unsigned int); |
| 858 | extern void blk_queue_max_discard_sectors(struct request_queue *q, | 902 | extern void blk_queue_max_discard_sectors(struct request_queue *q, |
| 859 | unsigned int max_discard_sectors); | 903 | unsigned int max_discard_sectors); |
| 904 | extern void blk_queue_max_write_same_sectors(struct request_queue *q, | ||
| 905 | unsigned int max_write_same_sectors); | ||
| 860 | extern void blk_queue_logical_block_size(struct request_queue *, unsigned short); | 906 | extern void blk_queue_logical_block_size(struct request_queue *, unsigned short); |
| 861 | extern void blk_queue_physical_block_size(struct request_queue *, unsigned int); | 907 | extern void blk_queue_physical_block_size(struct request_queue *, unsigned int); |
| 862 | extern void blk_queue_alignment_offset(struct request_queue *q, | 908 | extern void blk_queue_alignment_offset(struct request_queue *q, |
| @@ -987,6 +1033,8 @@ static inline struct request *blk_map_queue_find_tag(struct blk_queue_tag *bqt, | |||
| 987 | extern int blkdev_issue_flush(struct block_device *, gfp_t, sector_t *); | 1033 | extern int blkdev_issue_flush(struct block_device *, gfp_t, sector_t *); |
| 988 | extern int blkdev_issue_discard(struct block_device *bdev, sector_t sector, | 1034 | extern int blkdev_issue_discard(struct block_device *bdev, sector_t sector, |
| 989 | sector_t nr_sects, gfp_t gfp_mask, unsigned long flags); | 1035 | sector_t nr_sects, gfp_t gfp_mask, unsigned long flags); |
| 1036 | extern int blkdev_issue_write_same(struct block_device *bdev, sector_t sector, | ||
| 1037 | sector_t nr_sects, gfp_t gfp_mask, struct page *page); | ||
| 990 | extern int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector, | 1038 | extern int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector, |
| 991 | sector_t nr_sects, gfp_t gfp_mask); | 1039 | sector_t nr_sects, gfp_t gfp_mask); |
| 992 | static inline int sb_issue_discard(struct super_block *sb, sector_t block, | 1040 | static inline int sb_issue_discard(struct super_block *sb, sector_t block, |
| @@ -1164,6 +1212,16 @@ static inline unsigned int bdev_discard_zeroes_data(struct block_device *bdev) | |||
| 1164 | return queue_discard_zeroes_data(bdev_get_queue(bdev)); | 1212 | return queue_discard_zeroes_data(bdev_get_queue(bdev)); |
| 1165 | } | 1213 | } |
| 1166 | 1214 | ||
| 1215 | static inline unsigned int bdev_write_same(struct block_device *bdev) | ||
| 1216 | { | ||
| 1217 | struct request_queue *q = bdev_get_queue(bdev); | ||
| 1218 | |||
| 1219 | if (q) | ||
| 1220 | return q->limits.max_write_same_sectors; | ||
| 1221 | |||
| 1222 | return 0; | ||
| 1223 | } | ||
| 1224 | |||
| 1167 | static inline int queue_dma_alignment(struct request_queue *q) | 1225 | static inline int queue_dma_alignment(struct request_queue *q) |
| 1168 | { | 1226 | { |
| 1169 | return q ? q->dma_alignment : 511; | 1227 | return q ? q->dma_alignment : 511; |
diff --git a/include/linux/fs.h b/include/linux/fs.h index c617ed024df8..39f3e12ca752 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -335,6 +335,7 @@ struct inodes_stat_t { | |||
| 335 | #define BLKDISCARDZEROES _IO(0x12,124) | 335 | #define BLKDISCARDZEROES _IO(0x12,124) |
| 336 | #define BLKSECDISCARD _IO(0x12,125) | 336 | #define BLKSECDISCARD _IO(0x12,125) |
| 337 | #define BLKROTATIONAL _IO(0x12,126) | 337 | #define BLKROTATIONAL _IO(0x12,126) |
| 338 | #define BLKZEROOUT _IO(0x12,127) | ||
| 338 | 339 | ||
| 339 | #define BMAP_IOCTL 1 /* obsolete - kept for compatibility */ | 340 | #define BMAP_IOCTL 1 /* obsolete - kept for compatibility */ |
| 340 | #define FIBMAP _IO(0x00,1) /* bmap access */ | 341 | #define FIBMAP _IO(0x00,1) /* bmap access */ |
| @@ -415,6 +416,7 @@ struct inodes_stat_t { | |||
| 415 | #include <linux/migrate_mode.h> | 416 | #include <linux/migrate_mode.h> |
| 416 | #include <linux/uidgid.h> | 417 | #include <linux/uidgid.h> |
| 417 | #include <linux/lockdep.h> | 418 | #include <linux/lockdep.h> |
| 419 | #include <linux/percpu-rwsem.h> | ||
| 418 | 420 | ||
| 419 | #include <asm/byteorder.h> | 421 | #include <asm/byteorder.h> |
| 420 | 422 | ||
| @@ -724,6 +726,8 @@ struct block_device { | |||
| 724 | int bd_fsfreeze_count; | 726 | int bd_fsfreeze_count; |
| 725 | /* Mutex for freeze */ | 727 | /* Mutex for freeze */ |
| 726 | struct mutex bd_fsfreeze_mutex; | 728 | struct mutex bd_fsfreeze_mutex; |
| 729 | /* A semaphore that prevents I/O while block size is being changed */ | ||
| 730 | struct percpu_rw_semaphore bd_block_size_semaphore; | ||
| 727 | }; | 731 | }; |
| 728 | 732 | ||
| 729 | /* | 733 | /* |
| @@ -2570,6 +2574,8 @@ extern int generic_segment_checks(const struct iovec *iov, | |||
| 2570 | unsigned long *nr_segs, size_t *count, int access_flags); | 2574 | unsigned long *nr_segs, size_t *count, int access_flags); |
| 2571 | 2575 | ||
| 2572 | /* fs/block_dev.c */ | 2576 | /* fs/block_dev.c */ |
| 2577 | extern ssize_t blkdev_aio_read(struct kiocb *iocb, const struct iovec *iov, | ||
| 2578 | unsigned long nr_segs, loff_t pos); | ||
| 2573 | extern ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov, | 2579 | extern ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov, |
| 2574 | unsigned long nr_segs, loff_t pos); | 2580 | unsigned long nr_segs, loff_t pos); |
| 2575 | extern int blkdev_fsync(struct file *filp, loff_t start, loff_t end, | 2581 | extern int blkdev_fsync(struct file *filp, loff_t start, loff_t end, |
diff --git a/include/linux/percpu-rwsem.h b/include/linux/percpu-rwsem.h new file mode 100644 index 000000000000..cf80f7e5277f --- /dev/null +++ b/include/linux/percpu-rwsem.h | |||
| @@ -0,0 +1,89 @@ | |||
| 1 | #ifndef _LINUX_PERCPU_RWSEM_H | ||
| 2 | #define _LINUX_PERCPU_RWSEM_H | ||
| 3 | |||
| 4 | #include <linux/mutex.h> | ||
| 5 | #include <linux/percpu.h> | ||
| 6 | #include <linux/rcupdate.h> | ||
| 7 | #include <linux/delay.h> | ||
| 8 | |||
| 9 | struct percpu_rw_semaphore { | ||
| 10 | unsigned __percpu *counters; | ||
| 11 | bool locked; | ||
| 12 | struct mutex mtx; | ||
| 13 | }; | ||
| 14 | |||
| 15 | static inline void percpu_down_read(struct percpu_rw_semaphore *p) | ||
| 16 | { | ||
| 17 | rcu_read_lock(); | ||
| 18 | if (unlikely(p->locked)) { | ||
| 19 | rcu_read_unlock(); | ||
| 20 | mutex_lock(&p->mtx); | ||
| 21 | this_cpu_inc(*p->counters); | ||
| 22 | mutex_unlock(&p->mtx); | ||
| 23 | return; | ||
| 24 | } | ||
| 25 | this_cpu_inc(*p->counters); | ||
| 26 | rcu_read_unlock(); | ||
| 27 | } | ||
| 28 | |||
| 29 | static inline void percpu_up_read(struct percpu_rw_semaphore *p) | ||
| 30 | { | ||
| 31 | /* | ||
| 32 | * On X86, write operation in this_cpu_dec serves as a memory unlock | ||
| 33 | * barrier (i.e. memory accesses may be moved before the write, but | ||
| 34 | * no memory accesses are moved past the write). | ||
| 35 | * On other architectures this may not be the case, so we need smp_mb() | ||
| 36 | * there. | ||
| 37 | */ | ||
| 38 | #if defined(CONFIG_X86) && (!defined(CONFIG_X86_PPRO_FENCE) && !defined(CONFIG_X86_OOSTORE)) | ||
| 39 | barrier(); | ||
| 40 | #else | ||
| 41 | smp_mb(); | ||
| 42 | #endif | ||
| 43 | this_cpu_dec(*p->counters); | ||
| 44 | } | ||
| 45 | |||
| 46 | static inline unsigned __percpu_count(unsigned __percpu *counters) | ||
| 47 | { | ||
| 48 | unsigned total = 0; | ||
| 49 | int cpu; | ||
| 50 | |||
| 51 | for_each_possible_cpu(cpu) | ||
| 52 | total += ACCESS_ONCE(*per_cpu_ptr(counters, cpu)); | ||
| 53 | |||
| 54 | return total; | ||
| 55 | } | ||
| 56 | |||
| 57 | static inline void percpu_down_write(struct percpu_rw_semaphore *p) | ||
| 58 | { | ||
| 59 | mutex_lock(&p->mtx); | ||
| 60 | p->locked = true; | ||
| 61 | synchronize_rcu(); | ||
| 62 | while (__percpu_count(p->counters)) | ||
| 63 | msleep(1); | ||
| 64 | smp_rmb(); /* paired with smp_mb() in percpu_sem_up_read() */ | ||
| 65 | } | ||
| 66 | |||
| 67 | static inline void percpu_up_write(struct percpu_rw_semaphore *p) | ||
| 68 | { | ||
| 69 | p->locked = false; | ||
| 70 | mutex_unlock(&p->mtx); | ||
| 71 | } | ||
| 72 | |||
| 73 | static inline int percpu_init_rwsem(struct percpu_rw_semaphore *p) | ||
| 74 | { | ||
| 75 | p->counters = alloc_percpu(unsigned); | ||
| 76 | if (unlikely(!p->counters)) | ||
| 77 | return -ENOMEM; | ||
| 78 | p->locked = false; | ||
| 79 | mutex_init(&p->mtx); | ||
| 80 | return 0; | ||
| 81 | } | ||
| 82 | |||
| 83 | static inline void percpu_free_rwsem(struct percpu_rw_semaphore *p) | ||
| 84 | { | ||
| 85 | free_percpu(p->counters); | ||
| 86 | p->counters = NULL; /* catch use after free bugs */ | ||
| 87 | } | ||
| 88 | |||
| 89 | #endif | ||
diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h index 7b600da9a635..4bd6c06eb28e 100644 --- a/include/linux/scatterlist.h +++ b/include/linux/scatterlist.h | |||
| @@ -201,6 +201,7 @@ static inline void *sg_virt(struct scatterlist *sg) | |||
| 201 | return page_address(sg_page(sg)) + sg->offset; | 201 | return page_address(sg_page(sg)) + sg->offset; |
| 202 | } | 202 | } |
| 203 | 203 | ||
| 204 | int sg_nents(struct scatterlist *sg); | ||
| 204 | struct scatterlist *sg_next(struct scatterlist *); | 205 | struct scatterlist *sg_next(struct scatterlist *); |
| 205 | struct scatterlist *sg_last(struct scatterlist *s, unsigned int); | 206 | struct scatterlist *sg_last(struct scatterlist *s, unsigned int); |
| 206 | void sg_init_table(struct scatterlist *, unsigned int); | 207 | void sg_init_table(struct scatterlist *, unsigned int); |
