aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2016-03-18 14:27:36 -0400
committerDan Williams <dan.j.williams@intel.com>2016-04-22 15:26:23 -0400
commit9d90725ddca347450c4ab177ad680ed76063afd4 (patch)
tree6658dda356e6868ab912534a6135397c3d4dedc0
parent8378af17a4021f01b3bed20c1bd19c3921c1f5ac (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.c137
-rw-r--r--include/linux/nd.h2
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
24struct nd_blk_device { 24static 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
32static u32 nd_blk_meta_size(struct nd_blk_device *blk_dev) 29static 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
34static u32 nsblk_sector_size(struct nd_namespace_blk *nsblk)
35{
36 return nsblk->lbasize - nsblk_meta_size(nsblk);
35} 37}
36 38
37static resource_size_t to_dev_offset(struct nd_namespace_blk *nsblk, 39static 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
60static 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
59static int nd_blk_rw_integrity(struct nd_blk_device *blk_dev, 71static 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 */
105static int nd_blk_rw_integrity(struct nd_blk_device *blk_dev, 116static 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
113static int nd_blk_do_bvec(struct nd_blk_device *blk_dev, 123static 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,
160static blk_qc_t nd_blk_make_request(struct request_queue *q, struct bio *bio) 172static 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
208static int nd_blk_rw_bytes(struct nd_namespace_common *ndns, 220static 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
245static int nd_blk_attach_disk(struct device *dev, 256static 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
333static int nd_blk_remove(struct device *dev) 334static 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};