diff options
author | Dan Williams <dan.j.williams@intel.com> | 2016-03-18 14:27:36 -0400 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2016-04-22 15:26:23 -0400 |
commit | 9d90725ddca347450c4ab177ad680ed76063afd4 (patch) | |
tree | 6658dda356e6868ab912534a6135397c3d4dedc0 | |
parent | 8378af17a4021f01b3bed20c1bd19c3921c1f5ac (diff) |
libnvdimm, blk: move i/o infrastructure to nd_namespace_blk
Consolidate the information for issuing i/o to a blk-namespace, and
eliminate some pointer chasing.
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
-rw-r--r-- | drivers/nvdimm/blk.c | 137 | ||||
-rw-r--r-- | include/linux/nd.h | 2 |
2 files changed, 71 insertions, 68 deletions
diff --git a/drivers/nvdimm/blk.c b/drivers/nvdimm/blk.c index 26d039879ba2..4c14ecdc792b 100644 --- a/drivers/nvdimm/blk.c +++ b/drivers/nvdimm/blk.c | |||
@@ -21,17 +21,19 @@ | |||
21 | #include <linux/sizes.h> | 21 | #include <linux/sizes.h> |
22 | #include "nd.h" | 22 | #include "nd.h" |
23 | 23 | ||
24 | struct nd_blk_device { | 24 | static u32 nsblk_meta_size(struct nd_namespace_blk *nsblk) |
25 | struct nd_namespace_blk *nsblk; | 25 | { |
26 | struct nd_blk_region *ndbr; | 26 | return nsblk->lbasize - ((nsblk->lbasize >= 4096) ? 4096 : 512); |
27 | size_t disk_size; | 27 | } |
28 | u32 sector_size; | ||
29 | u32 internal_lbasize; | ||
30 | }; | ||
31 | 28 | ||
32 | static u32 nd_blk_meta_size(struct nd_blk_device *blk_dev) | 29 | static u32 nsblk_internal_lbasize(struct nd_namespace_blk *nsblk) |
33 | { | 30 | { |
34 | return blk_dev->nsblk->lbasize - blk_dev->sector_size; | 31 | return roundup(nsblk->lbasize, INT_LBASIZE_ALIGNMENT); |
32 | } | ||
33 | |||
34 | static u32 nsblk_sector_size(struct nd_namespace_blk *nsblk) | ||
35 | { | ||
36 | return nsblk->lbasize - nsblk_meta_size(nsblk); | ||
35 | } | 37 | } |
36 | 38 | ||
37 | static resource_size_t to_dev_offset(struct nd_namespace_blk *nsblk, | 39 | static resource_size_t to_dev_offset(struct nd_namespace_blk *nsblk, |
@@ -55,20 +57,29 @@ static resource_size_t to_dev_offset(struct nd_namespace_blk *nsblk, | |||
55 | return SIZE_MAX; | 57 | return SIZE_MAX; |
56 | } | 58 | } |
57 | 59 | ||
60 | static struct nd_blk_region *to_ndbr(struct nd_namespace_blk *nsblk) | ||
61 | { | ||
62 | struct nd_region *nd_region; | ||
63 | struct device *parent; | ||
64 | |||
65 | parent = nsblk->common.dev.parent; | ||
66 | nd_region = container_of(parent, struct nd_region, dev); | ||
67 | return container_of(nd_region, struct nd_blk_region, nd_region); | ||
68 | } | ||
69 | |||
58 | #ifdef CONFIG_BLK_DEV_INTEGRITY | 70 | #ifdef CONFIG_BLK_DEV_INTEGRITY |
59 | static int nd_blk_rw_integrity(struct nd_blk_device *blk_dev, | 71 | static int nd_blk_rw_integrity(struct nd_namespace_blk *nsblk, |
60 | struct bio_integrity_payload *bip, u64 lba, | 72 | struct bio_integrity_payload *bip, u64 lba, int rw) |
61 | int rw) | ||
62 | { | 73 | { |
63 | unsigned int len = nd_blk_meta_size(blk_dev); | 74 | struct nd_blk_region *ndbr = to_ndbr(nsblk); |
75 | unsigned int len = nsblk_meta_size(nsblk); | ||
64 | resource_size_t dev_offset, ns_offset; | 76 | resource_size_t dev_offset, ns_offset; |
65 | struct nd_namespace_blk *nsblk; | 77 | u32 internal_lbasize, sector_size; |
66 | struct nd_blk_region *ndbr; | ||
67 | int err = 0; | 78 | int err = 0; |
68 | 79 | ||
69 | nsblk = blk_dev->nsblk; | 80 | internal_lbasize = nsblk_internal_lbasize(nsblk); |
70 | ndbr = blk_dev->ndbr; | 81 | sector_size = nsblk_sector_size(nsblk); |
71 | ns_offset = lba * blk_dev->internal_lbasize + blk_dev->sector_size; | 82 | ns_offset = lba * internal_lbasize + sector_size; |
72 | dev_offset = to_dev_offset(nsblk, ns_offset, len); | 83 | dev_offset = to_dev_offset(nsblk, ns_offset, len); |
73 | if (dev_offset == SIZE_MAX) | 84 | if (dev_offset == SIZE_MAX) |
74 | return -EIO; | 85 | return -EIO; |
@@ -102,25 +113,26 @@ static int nd_blk_rw_integrity(struct nd_blk_device *blk_dev, | |||
102 | } | 113 | } |
103 | 114 | ||
104 | #else /* CONFIG_BLK_DEV_INTEGRITY */ | 115 | #else /* CONFIG_BLK_DEV_INTEGRITY */ |
105 | static int nd_blk_rw_integrity(struct nd_blk_device *blk_dev, | 116 | static int nd_blk_rw_integrity(struct nd_namespace_blk *nsblk, |
106 | struct bio_integrity_payload *bip, u64 lba, | 117 | struct bio_integrity_payload *bip, u64 lba, int rw) |
107 | int rw) | ||
108 | { | 118 | { |
109 | return 0; | 119 | return 0; |
110 | } | 120 | } |
111 | #endif | 121 | #endif |
112 | 122 | ||
113 | static int nd_blk_do_bvec(struct nd_blk_device *blk_dev, | 123 | static int nsblk_do_bvec(struct nd_namespace_blk *nsblk, |
114 | struct bio_integrity_payload *bip, struct page *page, | 124 | struct bio_integrity_payload *bip, struct page *page, |
115 | unsigned int len, unsigned int off, int rw, | 125 | unsigned int len, unsigned int off, int rw, sector_t sector) |
116 | sector_t sector) | ||
117 | { | 126 | { |
118 | struct nd_blk_region *ndbr = blk_dev->ndbr; | 127 | struct nd_blk_region *ndbr = to_ndbr(nsblk); |
119 | resource_size_t dev_offset, ns_offset; | 128 | resource_size_t dev_offset, ns_offset; |
129 | u32 internal_lbasize, sector_size; | ||
120 | int err = 0; | 130 | int err = 0; |
121 | void *iobuf; | 131 | void *iobuf; |
122 | u64 lba; | 132 | u64 lba; |
123 | 133 | ||
134 | internal_lbasize = nsblk_internal_lbasize(nsblk); | ||
135 | sector_size = nsblk_sector_size(nsblk); | ||
124 | while (len) { | 136 | while (len) { |
125 | unsigned int cur_len; | 137 | unsigned int cur_len; |
126 | 138 | ||
@@ -130,11 +142,11 @@ static int nd_blk_do_bvec(struct nd_blk_device *blk_dev, | |||
130 | * Block Window setup/move steps. the do_io routine is capable | 142 | * Block Window setup/move steps. the do_io routine is capable |
131 | * of handling len <= PAGE_SIZE. | 143 | * of handling len <= PAGE_SIZE. |
132 | */ | 144 | */ |
133 | cur_len = bip ? min(len, blk_dev->sector_size) : len; | 145 | cur_len = bip ? min(len, sector_size) : len; |
134 | 146 | ||
135 | lba = div_u64(sector << SECTOR_SHIFT, blk_dev->sector_size); | 147 | lba = div_u64(sector << SECTOR_SHIFT, sector_size); |
136 | ns_offset = lba * blk_dev->internal_lbasize; | 148 | ns_offset = lba * internal_lbasize; |
137 | dev_offset = to_dev_offset(blk_dev->nsblk, ns_offset, cur_len); | 149 | dev_offset = to_dev_offset(nsblk, ns_offset, cur_len); |
138 | if (dev_offset == SIZE_MAX) | 150 | if (dev_offset == SIZE_MAX) |
139 | return -EIO; | 151 | return -EIO; |
140 | 152 | ||
@@ -145,13 +157,13 @@ static int nd_blk_do_bvec(struct nd_blk_device *blk_dev, | |||
145 | return err; | 157 | return err; |
146 | 158 | ||
147 | if (bip) { | 159 | if (bip) { |
148 | err = nd_blk_rw_integrity(blk_dev, bip, lba, rw); | 160 | err = nd_blk_rw_integrity(nsblk, bip, lba, rw); |
149 | if (err) | 161 | if (err) |
150 | return err; | 162 | return err; |
151 | } | 163 | } |
152 | len -= cur_len; | 164 | len -= cur_len; |
153 | off += cur_len; | 165 | off += cur_len; |
154 | sector += blk_dev->sector_size >> SECTOR_SHIFT; | 166 | sector += sector_size >> SECTOR_SHIFT; |
155 | } | 167 | } |
156 | 168 | ||
157 | return err; | 169 | return err; |
@@ -160,7 +172,7 @@ static int nd_blk_do_bvec(struct nd_blk_device *blk_dev, | |||
160 | static blk_qc_t nd_blk_make_request(struct request_queue *q, struct bio *bio) | 172 | static blk_qc_t nd_blk_make_request(struct request_queue *q, struct bio *bio) |
161 | { | 173 | { |
162 | struct bio_integrity_payload *bip; | 174 | struct bio_integrity_payload *bip; |
163 | struct nd_blk_device *blk_dev; | 175 | struct nd_namespace_blk *nsblk; |
164 | struct bvec_iter iter; | 176 | struct bvec_iter iter; |
165 | unsigned long start; | 177 | unsigned long start; |
166 | struct bio_vec bvec; | 178 | struct bio_vec bvec; |
@@ -179,17 +191,17 @@ static blk_qc_t nd_blk_make_request(struct request_queue *q, struct bio *bio) | |||
179 | } | 191 | } |
180 | 192 | ||
181 | bip = bio_integrity(bio); | 193 | bip = bio_integrity(bio); |
182 | blk_dev = q->queuedata; | 194 | nsblk = q->queuedata; |
183 | rw = bio_data_dir(bio); | 195 | rw = bio_data_dir(bio); |
184 | do_acct = nd_iostat_start(bio, &start); | 196 | do_acct = nd_iostat_start(bio, &start); |
185 | bio_for_each_segment(bvec, bio, iter) { | 197 | bio_for_each_segment(bvec, bio, iter) { |
186 | unsigned int len = bvec.bv_len; | 198 | unsigned int len = bvec.bv_len; |
187 | 199 | ||
188 | BUG_ON(len > PAGE_SIZE); | 200 | BUG_ON(len > PAGE_SIZE); |
189 | err = nd_blk_do_bvec(blk_dev, bip, bvec.bv_page, len, | 201 | err = nsblk_do_bvec(nsblk, bip, bvec.bv_page, len, |
190 | bvec.bv_offset, rw, iter.bi_sector); | 202 | bvec.bv_offset, rw, iter.bi_sector); |
191 | if (err) { | 203 | if (err) { |
192 | dev_dbg(&blk_dev->nsblk->common.dev, | 204 | dev_dbg(&nsblk->common.dev, |
193 | "io error in %s sector %lld, len %d,\n", | 205 | "io error in %s sector %lld, len %d,\n", |
194 | (rw == READ) ? "READ" : "WRITE", | 206 | (rw == READ) ? "READ" : "WRITE", |
195 | (unsigned long long) iter.bi_sector, len); | 207 | (unsigned long long) iter.bi_sector, len); |
@@ -205,17 +217,16 @@ static blk_qc_t nd_blk_make_request(struct request_queue *q, struct bio *bio) | |||
205 | return BLK_QC_T_NONE; | 217 | return BLK_QC_T_NONE; |
206 | } | 218 | } |
207 | 219 | ||
208 | static int nd_blk_rw_bytes(struct nd_namespace_common *ndns, | 220 | static int nsblk_rw_bytes(struct nd_namespace_common *ndns, |
209 | resource_size_t offset, void *iobuf, size_t n, int rw) | 221 | resource_size_t offset, void *iobuf, size_t n, int rw) |
210 | { | 222 | { |
211 | struct nd_blk_device *blk_dev = dev_get_drvdata(ndns->claim); | 223 | struct nd_namespace_blk *nsblk = to_nd_namespace_blk(&ndns->dev); |
212 | struct nd_namespace_blk *nsblk = blk_dev->nsblk; | 224 | struct nd_blk_region *ndbr = to_ndbr(nsblk); |
213 | struct nd_blk_region *ndbr = blk_dev->ndbr; | ||
214 | resource_size_t dev_offset; | 225 | resource_size_t dev_offset; |
215 | 226 | ||
216 | dev_offset = to_dev_offset(nsblk, offset, n); | 227 | dev_offset = to_dev_offset(nsblk, offset, n); |
217 | 228 | ||
218 | if (unlikely(offset + n > blk_dev->disk_size)) { | 229 | if (unlikely(offset + n > nsblk->size)) { |
219 | dev_WARN_ONCE(&ndns->dev, 1, "request out of range\n"); | 230 | dev_WARN_ONCE(&ndns->dev, 1, "request out of range\n"); |
220 | return -EFAULT; | 231 | return -EFAULT; |
221 | } | 232 | } |
@@ -242,16 +253,16 @@ static void nd_blk_release_disk(void *disk) | |||
242 | put_disk(disk); | 253 | put_disk(disk); |
243 | } | 254 | } |
244 | 255 | ||
245 | static int nd_blk_attach_disk(struct device *dev, | 256 | static int nsblk_attach_disk(struct nd_namespace_blk *nsblk) |
246 | struct nd_namespace_common *ndns, struct nd_blk_device *blk_dev) | ||
247 | { | 257 | { |
258 | struct device *dev = &nsblk->common.dev; | ||
248 | resource_size_t available_disk_size; | 259 | resource_size_t available_disk_size; |
249 | struct request_queue *q; | 260 | struct request_queue *q; |
250 | struct gendisk *disk; | 261 | struct gendisk *disk; |
251 | u64 internal_nlba; | 262 | u64 internal_nlba; |
252 | 263 | ||
253 | internal_nlba = div_u64(blk_dev->disk_size, blk_dev->internal_lbasize); | 264 | internal_nlba = div_u64(nsblk->size, nsblk_internal_lbasize(nsblk)); |
254 | available_disk_size = internal_nlba * blk_dev->sector_size; | 265 | available_disk_size = internal_nlba * nsblk_sector_size(nsblk); |
255 | 266 | ||
256 | q = blk_alloc_queue(GFP_KERNEL); | 267 | q = blk_alloc_queue(GFP_KERNEL); |
257 | if (!q) | 268 | if (!q) |
@@ -264,9 +275,9 @@ static int nd_blk_attach_disk(struct device *dev, | |||
264 | blk_queue_make_request(q, nd_blk_make_request); | 275 | blk_queue_make_request(q, nd_blk_make_request); |
265 | blk_queue_max_hw_sectors(q, UINT_MAX); | 276 | blk_queue_max_hw_sectors(q, UINT_MAX); |
266 | blk_queue_bounce_limit(q, BLK_BOUNCE_ANY); | 277 | blk_queue_bounce_limit(q, BLK_BOUNCE_ANY); |
267 | blk_queue_logical_block_size(q, blk_dev->sector_size); | 278 | blk_queue_logical_block_size(q, nsblk_sector_size(nsblk)); |
268 | queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q); | 279 | queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q); |
269 | q->queuedata = blk_dev; | 280 | q->queuedata = nsblk; |
270 | 281 | ||
271 | disk = alloc_disk(0); | 282 | disk = alloc_disk(0); |
272 | if (!disk) | 283 | if (!disk) |
@@ -276,17 +287,17 @@ static int nd_blk_attach_disk(struct device *dev, | |||
276 | return -ENOMEM; | 287 | return -ENOMEM; |
277 | } | 288 | } |
278 | 289 | ||
279 | disk->driverfs_dev = &ndns->dev; | 290 | disk->driverfs_dev = dev; |
280 | disk->first_minor = 0; | 291 | disk->first_minor = 0; |
281 | disk->fops = &nd_blk_fops; | 292 | disk->fops = &nd_blk_fops; |
282 | disk->queue = q; | 293 | disk->queue = q; |
283 | disk->flags = GENHD_FL_EXT_DEVT; | 294 | disk->flags = GENHD_FL_EXT_DEVT; |
284 | nvdimm_namespace_disk_name(ndns, disk->disk_name); | 295 | nvdimm_namespace_disk_name(&nsblk->common, disk->disk_name); |
285 | set_capacity(disk, 0); | 296 | set_capacity(disk, 0); |
286 | add_disk(disk); | 297 | add_disk(disk); |
287 | 298 | ||
288 | if (nd_blk_meta_size(blk_dev)) { | 299 | if (nsblk_meta_size(nsblk)) { |
289 | int rc = nd_integrity_init(disk, nd_blk_meta_size(blk_dev)); | 300 | int rc = nd_integrity_init(disk, nsblk_meta_size(nsblk)); |
290 | 301 | ||
291 | if (rc) | 302 | if (rc) |
292 | return rc; | 303 | return rc; |
@@ -301,33 +312,23 @@ static int nd_blk_probe(struct device *dev) | |||
301 | { | 312 | { |
302 | struct nd_namespace_common *ndns; | 313 | struct nd_namespace_common *ndns; |
303 | struct nd_namespace_blk *nsblk; | 314 | struct nd_namespace_blk *nsblk; |
304 | struct nd_blk_device *blk_dev; | ||
305 | 315 | ||
306 | ndns = nvdimm_namespace_common_probe(dev); | 316 | ndns = nvdimm_namespace_common_probe(dev); |
307 | if (IS_ERR(ndns)) | 317 | if (IS_ERR(ndns)) |
308 | return PTR_ERR(ndns); | 318 | return PTR_ERR(ndns); |
309 | 319 | ||
310 | blk_dev = devm_kzalloc(dev, sizeof(*blk_dev), GFP_KERNEL); | ||
311 | if (!blk_dev) | ||
312 | return -ENOMEM; | ||
313 | |||
314 | nsblk = to_nd_namespace_blk(&ndns->dev); | 320 | nsblk = to_nd_namespace_blk(&ndns->dev); |
315 | blk_dev->disk_size = nvdimm_namespace_capacity(ndns); | 321 | nsblk->size = nvdimm_namespace_capacity(ndns); |
316 | blk_dev->ndbr = to_nd_blk_region(dev->parent); | 322 | dev_set_drvdata(dev, nsblk); |
317 | blk_dev->nsblk = to_nd_namespace_blk(&ndns->dev); | 323 | |
318 | blk_dev->internal_lbasize = roundup(nsblk->lbasize, | 324 | ndns->rw_bytes = nsblk_rw_bytes; |
319 | INT_LBASIZE_ALIGNMENT); | ||
320 | blk_dev->sector_size = ((nsblk->lbasize >= 4096) ? 4096 : 512); | ||
321 | dev_set_drvdata(dev, blk_dev); | ||
322 | |||
323 | ndns->rw_bytes = nd_blk_rw_bytes; | ||
324 | if (is_nd_btt(dev)) | 325 | if (is_nd_btt(dev)) |
325 | return nvdimm_namespace_attach_btt(ndns); | 326 | return nvdimm_namespace_attach_btt(ndns); |
326 | else if (nd_btt_probe(dev, ndns, blk_dev) == 0) { | 327 | else if (nd_btt_probe(dev, ndns, nsblk) == 0) { |
327 | /* we'll come back as btt-blk */ | 328 | /* we'll come back as btt-blk */ |
328 | return -ENXIO; | 329 | return -ENXIO; |
329 | } else | 330 | } else |
330 | return nd_blk_attach_disk(dev, ndns, blk_dev); | 331 | return nsblk_attach_disk(nsblk); |
331 | } | 332 | } |
332 | 333 | ||
333 | static int nd_blk_remove(struct device *dev) | 334 | static int nd_blk_remove(struct device *dev) |
diff --git a/include/linux/nd.h b/include/linux/nd.h index 5489ab756d1a..5ea4aec7fd63 100644 --- a/include/linux/nd.h +++ b/include/linux/nd.h | |||
@@ -82,6 +82,7 @@ struct nd_namespace_pmem { | |||
82 | * @uuid: namespace name supplied in the dimm label | 82 | * @uuid: namespace name supplied in the dimm label |
83 | * @id: ida allocated id | 83 | * @id: ida allocated id |
84 | * @lbasize: blk namespaces have a native sector size when btt not present | 84 | * @lbasize: blk namespaces have a native sector size when btt not present |
85 | * @size: sum of all the resource ranges allocated to this namespace | ||
85 | * @num_resources: number of dpa extents to claim | 86 | * @num_resources: number of dpa extents to claim |
86 | * @res: discontiguous dpa extents for given dimm | 87 | * @res: discontiguous dpa extents for given dimm |
87 | */ | 88 | */ |
@@ -91,6 +92,7 @@ struct nd_namespace_blk { | |||
91 | u8 *uuid; | 92 | u8 *uuid; |
92 | int id; | 93 | int id; |
93 | unsigned long lbasize; | 94 | unsigned long lbasize; |
95 | resource_size_t size; | ||
94 | int num_resources; | 96 | int num_resources; |
95 | struct resource **res; | 97 | struct resource **res; |
96 | }; | 98 | }; |