diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-09-14 01:16:11 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-09-14 01:16:11 -0400 |
commit | 4d8d9f540b780f7a3688a72275aecd8fd99c99e5 (patch) | |
tree | c35899a9b3d93b1db289c7769d75264d66842894 | |
parent | a0efc03b7925c4b606b1c49feb394859754e1cc8 (diff) | |
parent | b228ba1cb95afbaeeb86cf06cd9fd6f6369c3b14 (diff) |
Merge tag 'for-linus-20180913' of git://git.kernel.dk/linux-block
Pull block fixes from Jens Axboe:
"Three fixes that should go into this series. This contains:
- Increase number of policies supported by blk-cgroup.
With blk-iolatency, we now have four in kernel, but we had a hard
limit of three...
- Fix regression in null_blk, where the zoned supported broke
queue_mode=0 (bio based).
- NVMe pull request, with a single fix for an issue in the rdma code"
* tag 'for-linus-20180913' of git://git.kernel.dk/linux-block:
null_blk: fix zoned support for non-rq based operation
blk-cgroup: increase number of supported policies
nvmet-rdma: fix possible bogus dereference under heavy load
-rw-r--r-- | block/blk-cgroup.c | 4 | ||||
-rw-r--r-- | drivers/block/null_blk.h | 17 | ||||
-rw-r--r-- | drivers/block/null_blk_main.c | 45 | ||||
-rw-r--r-- | drivers/block/null_blk_zoned.c | 34 | ||||
-rw-r--r-- | drivers/nvme/target/rdma.c | 27 | ||||
-rw-r--r-- | include/linux/blkdev.h | 2 |
6 files changed, 91 insertions, 38 deletions
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index c19f9078da1e..c630e02836a8 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c | |||
@@ -1510,8 +1510,10 @@ int blkcg_policy_register(struct blkcg_policy *pol) | |||
1510 | for (i = 0; i < BLKCG_MAX_POLS; i++) | 1510 | for (i = 0; i < BLKCG_MAX_POLS; i++) |
1511 | if (!blkcg_policy[i]) | 1511 | if (!blkcg_policy[i]) |
1512 | break; | 1512 | break; |
1513 | if (i >= BLKCG_MAX_POLS) | 1513 | if (i >= BLKCG_MAX_POLS) { |
1514 | pr_warn("blkcg_policy_register: BLKCG_MAX_POLS too small\n"); | ||
1514 | goto err_unlock; | 1515 | goto err_unlock; |
1516 | } | ||
1515 | 1517 | ||
1516 | /* Make sure cpd/pd_alloc_fn and cpd/pd_free_fn in pairs */ | 1518 | /* Make sure cpd/pd_alloc_fn and cpd/pd_free_fn in pairs */ |
1517 | if ((!pol->cpd_alloc_fn ^ !pol->cpd_free_fn) || | 1519 | if ((!pol->cpd_alloc_fn ^ !pol->cpd_free_fn) || |
diff --git a/drivers/block/null_blk.h b/drivers/block/null_blk.h index d81781f22dba..34e0030f0592 100644 --- a/drivers/block/null_blk.h +++ b/drivers/block/null_blk.h | |||
@@ -87,10 +87,10 @@ struct nullb { | |||
87 | #ifdef CONFIG_BLK_DEV_ZONED | 87 | #ifdef CONFIG_BLK_DEV_ZONED |
88 | int null_zone_init(struct nullb_device *dev); | 88 | int null_zone_init(struct nullb_device *dev); |
89 | void null_zone_exit(struct nullb_device *dev); | 89 | void null_zone_exit(struct nullb_device *dev); |
90 | blk_status_t null_zone_report(struct nullb *nullb, | 90 | blk_status_t null_zone_report(struct nullb *nullb, struct bio *bio); |
91 | struct nullb_cmd *cmd); | 91 | void null_zone_write(struct nullb_cmd *cmd, sector_t sector, |
92 | void null_zone_write(struct nullb_cmd *cmd); | 92 | unsigned int nr_sectors); |
93 | void null_zone_reset(struct nullb_cmd *cmd); | 93 | void null_zone_reset(struct nullb_cmd *cmd, sector_t sector); |
94 | #else | 94 | #else |
95 | static inline int null_zone_init(struct nullb_device *dev) | 95 | static inline int null_zone_init(struct nullb_device *dev) |
96 | { | 96 | { |
@@ -98,11 +98,14 @@ static inline int null_zone_init(struct nullb_device *dev) | |||
98 | } | 98 | } |
99 | static inline void null_zone_exit(struct nullb_device *dev) {} | 99 | static inline void null_zone_exit(struct nullb_device *dev) {} |
100 | static inline blk_status_t null_zone_report(struct nullb *nullb, | 100 | static inline blk_status_t null_zone_report(struct nullb *nullb, |
101 | struct nullb_cmd *cmd) | 101 | struct bio *bio) |
102 | { | 102 | { |
103 | return BLK_STS_NOTSUPP; | 103 | return BLK_STS_NOTSUPP; |
104 | } | 104 | } |
105 | static inline void null_zone_write(struct nullb_cmd *cmd) {} | 105 | static inline void null_zone_write(struct nullb_cmd *cmd, sector_t sector, |
106 | static inline void null_zone_reset(struct nullb_cmd *cmd) {} | 106 | unsigned int nr_sectors) |
107 | { | ||
108 | } | ||
109 | static inline void null_zone_reset(struct nullb_cmd *cmd, sector_t sector) {} | ||
107 | #endif /* CONFIG_BLK_DEV_ZONED */ | 110 | #endif /* CONFIG_BLK_DEV_ZONED */ |
108 | #endif /* __NULL_BLK_H */ | 111 | #endif /* __NULL_BLK_H */ |
diff --git a/drivers/block/null_blk_main.c b/drivers/block/null_blk_main.c index 6127e3ff7b4b..093b614d6524 100644 --- a/drivers/block/null_blk_main.c +++ b/drivers/block/null_blk_main.c | |||
@@ -1157,16 +1157,33 @@ static void null_restart_queue_async(struct nullb *nullb) | |||
1157 | } | 1157 | } |
1158 | } | 1158 | } |
1159 | 1159 | ||
1160 | static bool cmd_report_zone(struct nullb *nullb, struct nullb_cmd *cmd) | ||
1161 | { | ||
1162 | struct nullb_device *dev = cmd->nq->dev; | ||
1163 | |||
1164 | if (dev->queue_mode == NULL_Q_BIO) { | ||
1165 | if (bio_op(cmd->bio) == REQ_OP_ZONE_REPORT) { | ||
1166 | cmd->error = null_zone_report(nullb, cmd->bio); | ||
1167 | return true; | ||
1168 | } | ||
1169 | } else { | ||
1170 | if (req_op(cmd->rq) == REQ_OP_ZONE_REPORT) { | ||
1171 | cmd->error = null_zone_report(nullb, cmd->rq->bio); | ||
1172 | return true; | ||
1173 | } | ||
1174 | } | ||
1175 | |||
1176 | return false; | ||
1177 | } | ||
1178 | |||
1160 | static blk_status_t null_handle_cmd(struct nullb_cmd *cmd) | 1179 | static blk_status_t null_handle_cmd(struct nullb_cmd *cmd) |
1161 | { | 1180 | { |
1162 | struct nullb_device *dev = cmd->nq->dev; | 1181 | struct nullb_device *dev = cmd->nq->dev; |
1163 | struct nullb *nullb = dev->nullb; | 1182 | struct nullb *nullb = dev->nullb; |
1164 | int err = 0; | 1183 | int err = 0; |
1165 | 1184 | ||
1166 | if (req_op(cmd->rq) == REQ_OP_ZONE_REPORT) { | 1185 | if (cmd_report_zone(nullb, cmd)) |
1167 | cmd->error = null_zone_report(nullb, cmd); | ||
1168 | goto out; | 1186 | goto out; |
1169 | } | ||
1170 | 1187 | ||
1171 | if (test_bit(NULLB_DEV_FL_THROTTLED, &dev->flags)) { | 1188 | if (test_bit(NULLB_DEV_FL_THROTTLED, &dev->flags)) { |
1172 | struct request *rq = cmd->rq; | 1189 | struct request *rq = cmd->rq; |
@@ -1234,10 +1251,24 @@ static blk_status_t null_handle_cmd(struct nullb_cmd *cmd) | |||
1234 | cmd->error = errno_to_blk_status(err); | 1251 | cmd->error = errno_to_blk_status(err); |
1235 | 1252 | ||
1236 | if (!cmd->error && dev->zoned) { | 1253 | if (!cmd->error && dev->zoned) { |
1237 | if (req_op(cmd->rq) == REQ_OP_WRITE) | 1254 | sector_t sector; |
1238 | null_zone_write(cmd); | 1255 | unsigned int nr_sectors; |
1239 | else if (req_op(cmd->rq) == REQ_OP_ZONE_RESET) | 1256 | int op; |
1240 | null_zone_reset(cmd); | 1257 | |
1258 | if (dev->queue_mode == NULL_Q_BIO) { | ||
1259 | op = bio_op(cmd->bio); | ||
1260 | sector = cmd->bio->bi_iter.bi_sector; | ||
1261 | nr_sectors = cmd->bio->bi_iter.bi_size >> 9; | ||
1262 | } else { | ||
1263 | op = req_op(cmd->rq); | ||
1264 | sector = blk_rq_pos(cmd->rq); | ||
1265 | nr_sectors = blk_rq_sectors(cmd->rq); | ||
1266 | } | ||
1267 | |||
1268 | if (op == REQ_OP_WRITE) | ||
1269 | null_zone_write(cmd, sector, nr_sectors); | ||
1270 | else if (op == REQ_OP_ZONE_RESET) | ||
1271 | null_zone_reset(cmd, sector); | ||
1241 | } | 1272 | } |
1242 | out: | 1273 | out: |
1243 | /* Complete IO by inline, softirq or timer */ | 1274 | /* Complete IO by inline, softirq or timer */ |
diff --git a/drivers/block/null_blk_zoned.c b/drivers/block/null_blk_zoned.c index a979ca00d7be..7c6b86d98700 100644 --- a/drivers/block/null_blk_zoned.c +++ b/drivers/block/null_blk_zoned.c | |||
@@ -48,8 +48,8 @@ void null_zone_exit(struct nullb_device *dev) | |||
48 | kvfree(dev->zones); | 48 | kvfree(dev->zones); |
49 | } | 49 | } |
50 | 50 | ||
51 | static void null_zone_fill_rq(struct nullb_device *dev, struct request *rq, | 51 | static void null_zone_fill_bio(struct nullb_device *dev, struct bio *bio, |
52 | unsigned int zno, unsigned int nr_zones) | 52 | unsigned int zno, unsigned int nr_zones) |
53 | { | 53 | { |
54 | struct blk_zone_report_hdr *hdr = NULL; | 54 | struct blk_zone_report_hdr *hdr = NULL; |
55 | struct bio_vec bvec; | 55 | struct bio_vec bvec; |
@@ -57,7 +57,7 @@ static void null_zone_fill_rq(struct nullb_device *dev, struct request *rq, | |||
57 | void *addr; | 57 | void *addr; |
58 | unsigned int zones_to_cpy; | 58 | unsigned int zones_to_cpy; |
59 | 59 | ||
60 | bio_for_each_segment(bvec, rq->bio, iter) { | 60 | bio_for_each_segment(bvec, bio, iter) { |
61 | addr = kmap_atomic(bvec.bv_page); | 61 | addr = kmap_atomic(bvec.bv_page); |
62 | 62 | ||
63 | zones_to_cpy = bvec.bv_len / sizeof(struct blk_zone); | 63 | zones_to_cpy = bvec.bv_len / sizeof(struct blk_zone); |
@@ -84,29 +84,24 @@ static void null_zone_fill_rq(struct nullb_device *dev, struct request *rq, | |||
84 | } | 84 | } |
85 | } | 85 | } |
86 | 86 | ||
87 | blk_status_t null_zone_report(struct nullb *nullb, | 87 | blk_status_t null_zone_report(struct nullb *nullb, struct bio *bio) |
88 | struct nullb_cmd *cmd) | ||
89 | { | 88 | { |
90 | struct nullb_device *dev = nullb->dev; | 89 | struct nullb_device *dev = nullb->dev; |
91 | struct request *rq = cmd->rq; | 90 | unsigned int zno = null_zone_no(dev, bio->bi_iter.bi_sector); |
92 | unsigned int zno = null_zone_no(dev, blk_rq_pos(rq)); | ||
93 | unsigned int nr_zones = dev->nr_zones - zno; | 91 | unsigned int nr_zones = dev->nr_zones - zno; |
94 | unsigned int max_zones = (blk_rq_bytes(rq) / | 92 | unsigned int max_zones; |
95 | sizeof(struct blk_zone)) - 1; | ||
96 | 93 | ||
94 | max_zones = (bio->bi_iter.bi_size / sizeof(struct blk_zone)) - 1; | ||
97 | nr_zones = min_t(unsigned int, nr_zones, max_zones); | 95 | nr_zones = min_t(unsigned int, nr_zones, max_zones); |
98 | 96 | null_zone_fill_bio(nullb->dev, bio, zno, nr_zones); | |
99 | null_zone_fill_rq(nullb->dev, rq, zno, nr_zones); | ||
100 | 97 | ||
101 | return BLK_STS_OK; | 98 | return BLK_STS_OK; |
102 | } | 99 | } |
103 | 100 | ||
104 | void null_zone_write(struct nullb_cmd *cmd) | 101 | void null_zone_write(struct nullb_cmd *cmd, sector_t sector, |
102 | unsigned int nr_sectors) | ||
105 | { | 103 | { |
106 | struct nullb_device *dev = cmd->nq->dev; | 104 | struct nullb_device *dev = cmd->nq->dev; |
107 | struct request *rq = cmd->rq; | ||
108 | sector_t sector = blk_rq_pos(rq); | ||
109 | unsigned int rq_sectors = blk_rq_sectors(rq); | ||
110 | unsigned int zno = null_zone_no(dev, sector); | 105 | unsigned int zno = null_zone_no(dev, sector); |
111 | struct blk_zone *zone = &dev->zones[zno]; | 106 | struct blk_zone *zone = &dev->zones[zno]; |
112 | 107 | ||
@@ -118,7 +113,7 @@ void null_zone_write(struct nullb_cmd *cmd) | |||
118 | case BLK_ZONE_COND_EMPTY: | 113 | case BLK_ZONE_COND_EMPTY: |
119 | case BLK_ZONE_COND_IMP_OPEN: | 114 | case BLK_ZONE_COND_IMP_OPEN: |
120 | /* Writes must be at the write pointer position */ | 115 | /* Writes must be at the write pointer position */ |
121 | if (blk_rq_pos(rq) != zone->wp) { | 116 | if (sector != zone->wp) { |
122 | cmd->error = BLK_STS_IOERR; | 117 | cmd->error = BLK_STS_IOERR; |
123 | break; | 118 | break; |
124 | } | 119 | } |
@@ -126,7 +121,7 @@ void null_zone_write(struct nullb_cmd *cmd) | |||
126 | if (zone->cond == BLK_ZONE_COND_EMPTY) | 121 | if (zone->cond == BLK_ZONE_COND_EMPTY) |
127 | zone->cond = BLK_ZONE_COND_IMP_OPEN; | 122 | zone->cond = BLK_ZONE_COND_IMP_OPEN; |
128 | 123 | ||
129 | zone->wp += rq_sectors; | 124 | zone->wp += nr_sectors; |
130 | if (zone->wp == zone->start + zone->len) | 125 | if (zone->wp == zone->start + zone->len) |
131 | zone->cond = BLK_ZONE_COND_FULL; | 126 | zone->cond = BLK_ZONE_COND_FULL; |
132 | break; | 127 | break; |
@@ -137,11 +132,10 @@ void null_zone_write(struct nullb_cmd *cmd) | |||
137 | } | 132 | } |
138 | } | 133 | } |
139 | 134 | ||
140 | void null_zone_reset(struct nullb_cmd *cmd) | 135 | void null_zone_reset(struct nullb_cmd *cmd, sector_t sector) |
141 | { | 136 | { |
142 | struct nullb_device *dev = cmd->nq->dev; | 137 | struct nullb_device *dev = cmd->nq->dev; |
143 | struct request *rq = cmd->rq; | 138 | unsigned int zno = null_zone_no(dev, sector); |
144 | unsigned int zno = null_zone_no(dev, blk_rq_pos(rq)); | ||
145 | struct blk_zone *zone = &dev->zones[zno]; | 139 | struct blk_zone *zone = &dev->zones[zno]; |
146 | 140 | ||
147 | zone->cond = BLK_ZONE_COND_EMPTY; | 141 | zone->cond = BLK_ZONE_COND_EMPTY; |
diff --git a/drivers/nvme/target/rdma.c b/drivers/nvme/target/rdma.c index 3533e918ea37..bfc4da660bb4 100644 --- a/drivers/nvme/target/rdma.c +++ b/drivers/nvme/target/rdma.c | |||
@@ -66,6 +66,7 @@ struct nvmet_rdma_rsp { | |||
66 | 66 | ||
67 | struct nvmet_req req; | 67 | struct nvmet_req req; |
68 | 68 | ||
69 | bool allocated; | ||
69 | u8 n_rdma; | 70 | u8 n_rdma; |
70 | u32 flags; | 71 | u32 flags; |
71 | u32 invalidate_rkey; | 72 | u32 invalidate_rkey; |
@@ -174,11 +175,19 @@ nvmet_rdma_get_rsp(struct nvmet_rdma_queue *queue) | |||
174 | unsigned long flags; | 175 | unsigned long flags; |
175 | 176 | ||
176 | spin_lock_irqsave(&queue->rsps_lock, flags); | 177 | spin_lock_irqsave(&queue->rsps_lock, flags); |
177 | rsp = list_first_entry(&queue->free_rsps, | 178 | rsp = list_first_entry_or_null(&queue->free_rsps, |
178 | struct nvmet_rdma_rsp, free_list); | 179 | struct nvmet_rdma_rsp, free_list); |
179 | list_del(&rsp->free_list); | 180 | if (likely(rsp)) |
181 | list_del(&rsp->free_list); | ||
180 | spin_unlock_irqrestore(&queue->rsps_lock, flags); | 182 | spin_unlock_irqrestore(&queue->rsps_lock, flags); |
181 | 183 | ||
184 | if (unlikely(!rsp)) { | ||
185 | rsp = kmalloc(sizeof(*rsp), GFP_KERNEL); | ||
186 | if (unlikely(!rsp)) | ||
187 | return NULL; | ||
188 | rsp->allocated = true; | ||
189 | } | ||
190 | |||
182 | return rsp; | 191 | return rsp; |
183 | } | 192 | } |
184 | 193 | ||
@@ -187,6 +196,11 @@ nvmet_rdma_put_rsp(struct nvmet_rdma_rsp *rsp) | |||
187 | { | 196 | { |
188 | unsigned long flags; | 197 | unsigned long flags; |
189 | 198 | ||
199 | if (rsp->allocated) { | ||
200 | kfree(rsp); | ||
201 | return; | ||
202 | } | ||
203 | |||
190 | spin_lock_irqsave(&rsp->queue->rsps_lock, flags); | 204 | spin_lock_irqsave(&rsp->queue->rsps_lock, flags); |
191 | list_add_tail(&rsp->free_list, &rsp->queue->free_rsps); | 205 | list_add_tail(&rsp->free_list, &rsp->queue->free_rsps); |
192 | spin_unlock_irqrestore(&rsp->queue->rsps_lock, flags); | 206 | spin_unlock_irqrestore(&rsp->queue->rsps_lock, flags); |
@@ -776,6 +790,15 @@ static void nvmet_rdma_recv_done(struct ib_cq *cq, struct ib_wc *wc) | |||
776 | 790 | ||
777 | cmd->queue = queue; | 791 | cmd->queue = queue; |
778 | rsp = nvmet_rdma_get_rsp(queue); | 792 | rsp = nvmet_rdma_get_rsp(queue); |
793 | if (unlikely(!rsp)) { | ||
794 | /* | ||
795 | * we get here only under memory pressure, | ||
796 | * silently drop and have the host retry | ||
797 | * as we can't even fail it. | ||
798 | */ | ||
799 | nvmet_rdma_post_recv(queue->dev, cmd); | ||
800 | return; | ||
801 | } | ||
779 | rsp->queue = queue; | 802 | rsp->queue = queue; |
780 | rsp->cmd = cmd; | 803 | rsp->cmd = cmd; |
781 | rsp->flags = 0; | 804 | rsp->flags = 0; |
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index d6869e0e2b64..6980014357d4 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h | |||
@@ -54,7 +54,7 @@ struct blk_stat_callback; | |||
54 | * Maximum number of blkcg policies allowed to be registered concurrently. | 54 | * Maximum number of blkcg policies allowed to be registered concurrently. |
55 | * Defined here to simplify include dependency. | 55 | * Defined here to simplify include dependency. |
56 | */ | 56 | */ |
57 | #define BLKCG_MAX_POLS 3 | 57 | #define BLKCG_MAX_POLS 5 |
58 | 58 | ||
59 | typedef void (rq_end_io_fn)(struct request *, blk_status_t); | 59 | typedef void (rq_end_io_fn)(struct request *, blk_status_t); |
60 | 60 | ||