diff options
author | Christoph Hellwig <hch@lst.de> | 2014-09-10 20:37:24 -0400 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2014-09-12 13:33:49 -0400 |
commit | 9cc475411779d635619c2d414da0769e3cbf796b (patch) | |
tree | 794f67ee82aa15c021ddcc29e05043791d47afcd | |
parent | 34dc93c2fc04da0d01acf8a1660b4ab276208af7 (diff) |
pnfs/blocklayout: move extent processing to blocklayout.c
This isn't device(id) related, so move it into the main file. Simple move
for now, the next commit will clean it up a bit.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
-rw-r--r-- | fs/nfs/blocklayout/blocklayout.c | 186 | ||||
-rw-r--r-- | fs/nfs/blocklayout/blocklayout.h | 2 | ||||
-rw-r--r-- | fs/nfs/blocklayout/blocklayoutdev.c | 186 |
3 files changed, 186 insertions, 188 deletions
diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c index cf10a6e291e4..61a858cd54fe 100644 --- a/fs/nfs/blocklayout/blocklayout.c +++ b/fs/nfs/blocklayout/blocklayout.c | |||
@@ -446,6 +446,192 @@ static void bl_free_lseg(struct pnfs_layout_segment *lseg) | |||
446 | kfree(lseg); | 446 | kfree(lseg); |
447 | } | 447 | } |
448 | 448 | ||
449 | /* Tracks info needed to ensure extents in layout obey constraints of spec */ | ||
450 | struct layout_verification { | ||
451 | u32 mode; /* R or RW */ | ||
452 | u64 start; /* Expected start of next non-COW extent */ | ||
453 | u64 inval; /* Start of INVAL coverage */ | ||
454 | u64 cowread; /* End of COW read coverage */ | ||
455 | }; | ||
456 | |||
457 | /* Verify the extent meets the layout requirements of the pnfs-block draft, | ||
458 | * section 2.3.1. | ||
459 | */ | ||
460 | static int verify_extent(struct pnfs_block_extent *be, | ||
461 | struct layout_verification *lv) | ||
462 | { | ||
463 | if (lv->mode == IOMODE_READ) { | ||
464 | if (be->be_state == PNFS_BLOCK_READWRITE_DATA || | ||
465 | be->be_state == PNFS_BLOCK_INVALID_DATA) | ||
466 | return -EIO; | ||
467 | if (be->be_f_offset != lv->start) | ||
468 | return -EIO; | ||
469 | lv->start += be->be_length; | ||
470 | return 0; | ||
471 | } | ||
472 | /* lv->mode == IOMODE_RW */ | ||
473 | if (be->be_state == PNFS_BLOCK_READWRITE_DATA) { | ||
474 | if (be->be_f_offset != lv->start) | ||
475 | return -EIO; | ||
476 | if (lv->cowread > lv->start) | ||
477 | return -EIO; | ||
478 | lv->start += be->be_length; | ||
479 | lv->inval = lv->start; | ||
480 | return 0; | ||
481 | } else if (be->be_state == PNFS_BLOCK_INVALID_DATA) { | ||
482 | if (be->be_f_offset != lv->start) | ||
483 | return -EIO; | ||
484 | lv->start += be->be_length; | ||
485 | return 0; | ||
486 | } else if (be->be_state == PNFS_BLOCK_READ_DATA) { | ||
487 | if (be->be_f_offset > lv->start) | ||
488 | return -EIO; | ||
489 | if (be->be_f_offset < lv->inval) | ||
490 | return -EIO; | ||
491 | if (be->be_f_offset < lv->cowread) | ||
492 | return -EIO; | ||
493 | /* It looks like you might want to min this with lv->start, | ||
494 | * but you really don't. | ||
495 | */ | ||
496 | lv->inval = lv->inval + be->be_length; | ||
497 | lv->cowread = be->be_f_offset + be->be_length; | ||
498 | return 0; | ||
499 | } else | ||
500 | return -EIO; | ||
501 | } | ||
502 | |||
503 | static int decode_sector_number(__be32 **rp, sector_t *sp) | ||
504 | { | ||
505 | uint64_t s; | ||
506 | |||
507 | *rp = xdr_decode_hyper(*rp, &s); | ||
508 | if (s & 0x1ff) { | ||
509 | printk(KERN_WARNING "NFS: %s: sector not aligned\n", __func__); | ||
510 | return -1; | ||
511 | } | ||
512 | *sp = s >> SECTOR_SHIFT; | ||
513 | return 0; | ||
514 | } | ||
515 | |||
516 | /* XDR decode pnfs_block_layout4 structure */ | ||
517 | static int | ||
518 | nfs4_blk_process_layoutget(struct pnfs_layout_hdr *lo, | ||
519 | struct nfs4_layoutget_res *lgr, gfp_t gfp_flags) | ||
520 | { | ||
521 | struct pnfs_block_layout *bl = BLK_LO2EXT(lo); | ||
522 | int i, status = -EIO; | ||
523 | uint32_t count; | ||
524 | struct pnfs_block_extent *be = NULL, *save; | ||
525 | struct xdr_stream stream; | ||
526 | struct xdr_buf buf; | ||
527 | struct page *scratch; | ||
528 | __be32 *p; | ||
529 | struct layout_verification lv = { | ||
530 | .mode = lgr->range.iomode, | ||
531 | .start = lgr->range.offset >> SECTOR_SHIFT, | ||
532 | .inval = lgr->range.offset >> SECTOR_SHIFT, | ||
533 | .cowread = lgr->range.offset >> SECTOR_SHIFT, | ||
534 | }; | ||
535 | LIST_HEAD(extents); | ||
536 | |||
537 | dprintk("---> %s\n", __func__); | ||
538 | |||
539 | scratch = alloc_page(gfp_flags); | ||
540 | if (!scratch) | ||
541 | return -ENOMEM; | ||
542 | |||
543 | xdr_init_decode_pages(&stream, &buf, lgr->layoutp->pages, lgr->layoutp->len); | ||
544 | xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE); | ||
545 | |||
546 | p = xdr_inline_decode(&stream, 4); | ||
547 | if (unlikely(!p)) | ||
548 | goto out_err; | ||
549 | |||
550 | count = be32_to_cpup(p++); | ||
551 | |||
552 | dprintk("%s enter, number of extents %i\n", __func__, count); | ||
553 | p = xdr_inline_decode(&stream, (28 + NFS4_DEVICEID4_SIZE) * count); | ||
554 | if (unlikely(!p)) | ||
555 | goto out_err; | ||
556 | |||
557 | /* Decode individual extents, putting them in temporary | ||
558 | * staging area until whole layout is decoded to make error | ||
559 | * recovery easier. | ||
560 | */ | ||
561 | for (i = 0; i < count; i++) { | ||
562 | struct nfs4_deviceid id; | ||
563 | |||
564 | be = kzalloc(sizeof(struct pnfs_block_extent), GFP_NOFS); | ||
565 | if (!be) { | ||
566 | status = -ENOMEM; | ||
567 | goto out_err; | ||
568 | } | ||
569 | memcpy(&id, p, NFS4_DEVICEID4_SIZE); | ||
570 | p += XDR_QUADLEN(NFS4_DEVICEID4_SIZE); | ||
571 | |||
572 | be->be_device = | ||
573 | nfs4_find_get_deviceid(NFS_SERVER(lo->plh_inode), &id, | ||
574 | lo->plh_lc_cred, gfp_flags); | ||
575 | if (!be->be_device) | ||
576 | goto out_err; | ||
577 | |||
578 | /* The next three values are read in as bytes, | ||
579 | * but stored as 512-byte sector lengths | ||
580 | */ | ||
581 | if (decode_sector_number(&p, &be->be_f_offset) < 0) | ||
582 | goto out_err; | ||
583 | if (decode_sector_number(&p, &be->be_length) < 0) | ||
584 | goto out_err; | ||
585 | if (decode_sector_number(&p, &be->be_v_offset) < 0) | ||
586 | goto out_err; | ||
587 | be->be_state = be32_to_cpup(p++); | ||
588 | if (verify_extent(be, &lv)) { | ||
589 | dprintk("%s verify failed\n", __func__); | ||
590 | goto out_err; | ||
591 | } | ||
592 | list_add_tail(&be->be_list, &extents); | ||
593 | } | ||
594 | if (lgr->range.offset + lgr->range.length != | ||
595 | lv.start << SECTOR_SHIFT) { | ||
596 | dprintk("%s Final length mismatch\n", __func__); | ||
597 | be = NULL; | ||
598 | goto out_err; | ||
599 | } | ||
600 | if (lv.start < lv.cowread) { | ||
601 | dprintk("%s Final uncovered COW extent\n", __func__); | ||
602 | be = NULL; | ||
603 | goto out_err; | ||
604 | } | ||
605 | /* Extents decoded properly, now try to merge them in to | ||
606 | * existing layout extents. | ||
607 | */ | ||
608 | list_for_each_entry_safe(be, save, &extents, be_list) { | ||
609 | list_del(&be->be_list); | ||
610 | |||
611 | status = ext_tree_insert(bl, be); | ||
612 | if (status) | ||
613 | goto out_free_list; | ||
614 | } | ||
615 | status = 0; | ||
616 | out: | ||
617 | __free_page(scratch); | ||
618 | dprintk("%s returns %i\n", __func__, status); | ||
619 | return status; | ||
620 | |||
621 | out_err: | ||
622 | nfs4_put_deviceid_node(be->be_device); | ||
623 | kfree(be); | ||
624 | out_free_list: | ||
625 | while (!list_empty(&extents)) { | ||
626 | be = list_first_entry(&extents, struct pnfs_block_extent, | ||
627 | be_list); | ||
628 | list_del(&be->be_list); | ||
629 | nfs4_put_deviceid_node(be->be_device); | ||
630 | kfree(be); | ||
631 | } | ||
632 | goto out; | ||
633 | } | ||
634 | |||
449 | /* We pretty much ignore lseg, and store all data layout wide, so we | 635 | /* We pretty much ignore lseg, and store all data layout wide, so we |
450 | * can correctly merge. | 636 | * can correctly merge. |
451 | */ | 637 | */ |
diff --git a/fs/nfs/blocklayout/blocklayout.h b/fs/nfs/blocklayout/blocklayout.h index 9757f3eabdd2..00c11eb9d765 100644 --- a/fs/nfs/blocklayout/blocklayout.h +++ b/fs/nfs/blocklayout/blocklayout.h | |||
@@ -113,8 +113,6 @@ struct bl_msg_hdr { | |||
113 | /* blocklayoutdev.c */ | 113 | /* blocklayoutdev.c */ |
114 | ssize_t bl_pipe_downcall(struct file *, const char __user *, size_t); | 114 | ssize_t bl_pipe_downcall(struct file *, const char __user *, size_t); |
115 | void bl_pipe_destroy_msg(struct rpc_pipe_msg *); | 115 | void bl_pipe_destroy_msg(struct rpc_pipe_msg *); |
116 | int nfs4_blk_process_layoutget(struct pnfs_layout_hdr *lo, | ||
117 | struct nfs4_layoutget_res *lgr, gfp_t gfp_flags); | ||
118 | 116 | ||
119 | struct nfs4_deviceid_node *bl_alloc_deviceid_node(struct nfs_server *server, | 117 | struct nfs4_deviceid_node *bl_alloc_deviceid_node(struct nfs_server *server, |
120 | struct pnfs_device *pdev, gfp_t gfp_mask); | 118 | struct pnfs_device *pdev, gfp_t gfp_mask); |
diff --git a/fs/nfs/blocklayout/blocklayoutdev.c b/fs/nfs/blocklayout/blocklayoutdev.c index d6527d20c508..2b54e2940288 100644 --- a/fs/nfs/blocklayout/blocklayoutdev.c +++ b/fs/nfs/blocklayout/blocklayoutdev.c | |||
@@ -40,19 +40,6 @@ | |||
40 | 40 | ||
41 | #define NFSDBG_FACILITY NFSDBG_PNFS_LD | 41 | #define NFSDBG_FACILITY NFSDBG_PNFS_LD |
42 | 42 | ||
43 | static int decode_sector_number(__be32 **rp, sector_t *sp) | ||
44 | { | ||
45 | uint64_t s; | ||
46 | |||
47 | *rp = xdr_decode_hyper(*rp, &s); | ||
48 | if (s & 0x1ff) { | ||
49 | printk(KERN_WARNING "NFS: %s: sector not aligned\n", __func__); | ||
50 | return -1; | ||
51 | } | ||
52 | *sp = s >> SECTOR_SHIFT; | ||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | ssize_t bl_pipe_downcall(struct file *filp, const char __user *src, | 43 | ssize_t bl_pipe_downcall(struct file *filp, const char __user *src, |
57 | size_t mlen) | 44 | size_t mlen) |
58 | { | 45 | { |
@@ -183,176 +170,3 @@ bl_free_deviceid_node(struct nfs4_deviceid_node *d) | |||
183 | 170 | ||
184 | kfree(dev); | 171 | kfree(dev); |
185 | } | 172 | } |
186 | |||
187 | /* Tracks info needed to ensure extents in layout obey constraints of spec */ | ||
188 | struct layout_verification { | ||
189 | u32 mode; /* R or RW */ | ||
190 | u64 start; /* Expected start of next non-COW extent */ | ||
191 | u64 inval; /* Start of INVAL coverage */ | ||
192 | u64 cowread; /* End of COW read coverage */ | ||
193 | }; | ||
194 | |||
195 | /* Verify the extent meets the layout requirements of the pnfs-block draft, | ||
196 | * section 2.3.1. | ||
197 | */ | ||
198 | static int verify_extent(struct pnfs_block_extent *be, | ||
199 | struct layout_verification *lv) | ||
200 | { | ||
201 | if (lv->mode == IOMODE_READ) { | ||
202 | if (be->be_state == PNFS_BLOCK_READWRITE_DATA || | ||
203 | be->be_state == PNFS_BLOCK_INVALID_DATA) | ||
204 | return -EIO; | ||
205 | if (be->be_f_offset != lv->start) | ||
206 | return -EIO; | ||
207 | lv->start += be->be_length; | ||
208 | return 0; | ||
209 | } | ||
210 | /* lv->mode == IOMODE_RW */ | ||
211 | if (be->be_state == PNFS_BLOCK_READWRITE_DATA) { | ||
212 | if (be->be_f_offset != lv->start) | ||
213 | return -EIO; | ||
214 | if (lv->cowread > lv->start) | ||
215 | return -EIO; | ||
216 | lv->start += be->be_length; | ||
217 | lv->inval = lv->start; | ||
218 | return 0; | ||
219 | } else if (be->be_state == PNFS_BLOCK_INVALID_DATA) { | ||
220 | if (be->be_f_offset != lv->start) | ||
221 | return -EIO; | ||
222 | lv->start += be->be_length; | ||
223 | return 0; | ||
224 | } else if (be->be_state == PNFS_BLOCK_READ_DATA) { | ||
225 | if (be->be_f_offset > lv->start) | ||
226 | return -EIO; | ||
227 | if (be->be_f_offset < lv->inval) | ||
228 | return -EIO; | ||
229 | if (be->be_f_offset < lv->cowread) | ||
230 | return -EIO; | ||
231 | /* It looks like you might want to min this with lv->start, | ||
232 | * but you really don't. | ||
233 | */ | ||
234 | lv->inval = lv->inval + be->be_length; | ||
235 | lv->cowread = be->be_f_offset + be->be_length; | ||
236 | return 0; | ||
237 | } else | ||
238 | return -EIO; | ||
239 | } | ||
240 | |||
241 | /* XDR decode pnfs_block_layout4 structure */ | ||
242 | int | ||
243 | nfs4_blk_process_layoutget(struct pnfs_layout_hdr *lo, | ||
244 | struct nfs4_layoutget_res *lgr, gfp_t gfp_flags) | ||
245 | { | ||
246 | struct pnfs_block_layout *bl = BLK_LO2EXT(lo); | ||
247 | int i, status = -EIO; | ||
248 | uint32_t count; | ||
249 | struct pnfs_block_extent *be = NULL, *save; | ||
250 | struct xdr_stream stream; | ||
251 | struct xdr_buf buf; | ||
252 | struct page *scratch; | ||
253 | __be32 *p; | ||
254 | struct layout_verification lv = { | ||
255 | .mode = lgr->range.iomode, | ||
256 | .start = lgr->range.offset >> SECTOR_SHIFT, | ||
257 | .inval = lgr->range.offset >> SECTOR_SHIFT, | ||
258 | .cowread = lgr->range.offset >> SECTOR_SHIFT, | ||
259 | }; | ||
260 | LIST_HEAD(extents); | ||
261 | |||
262 | dprintk("---> %s\n", __func__); | ||
263 | |||
264 | scratch = alloc_page(gfp_flags); | ||
265 | if (!scratch) | ||
266 | return -ENOMEM; | ||
267 | |||
268 | xdr_init_decode_pages(&stream, &buf, lgr->layoutp->pages, lgr->layoutp->len); | ||
269 | xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE); | ||
270 | |||
271 | p = xdr_inline_decode(&stream, 4); | ||
272 | if (unlikely(!p)) | ||
273 | goto out_err; | ||
274 | |||
275 | count = be32_to_cpup(p++); | ||
276 | |||
277 | dprintk("%s enter, number of extents %i\n", __func__, count); | ||
278 | p = xdr_inline_decode(&stream, (28 + NFS4_DEVICEID4_SIZE) * count); | ||
279 | if (unlikely(!p)) | ||
280 | goto out_err; | ||
281 | |||
282 | /* Decode individual extents, putting them in temporary | ||
283 | * staging area until whole layout is decoded to make error | ||
284 | * recovery easier. | ||
285 | */ | ||
286 | for (i = 0; i < count; i++) { | ||
287 | struct nfs4_deviceid id; | ||
288 | |||
289 | be = kzalloc(sizeof(struct pnfs_block_extent), GFP_NOFS); | ||
290 | if (!be) { | ||
291 | status = -ENOMEM; | ||
292 | goto out_err; | ||
293 | } | ||
294 | memcpy(&id, p, NFS4_DEVICEID4_SIZE); | ||
295 | p += XDR_QUADLEN(NFS4_DEVICEID4_SIZE); | ||
296 | |||
297 | be->be_device = | ||
298 | nfs4_find_get_deviceid(NFS_SERVER(lo->plh_inode), &id, | ||
299 | lo->plh_lc_cred, gfp_flags); | ||
300 | if (!be->be_device) | ||
301 | goto out_err; | ||
302 | |||
303 | /* The next three values are read in as bytes, | ||
304 | * but stored as 512-byte sector lengths | ||
305 | */ | ||
306 | if (decode_sector_number(&p, &be->be_f_offset) < 0) | ||
307 | goto out_err; | ||
308 | if (decode_sector_number(&p, &be->be_length) < 0) | ||
309 | goto out_err; | ||
310 | if (decode_sector_number(&p, &be->be_v_offset) < 0) | ||
311 | goto out_err; | ||
312 | be->be_state = be32_to_cpup(p++); | ||
313 | if (verify_extent(be, &lv)) { | ||
314 | dprintk("%s verify failed\n", __func__); | ||
315 | goto out_err; | ||
316 | } | ||
317 | list_add_tail(&be->be_list, &extents); | ||
318 | } | ||
319 | if (lgr->range.offset + lgr->range.length != | ||
320 | lv.start << SECTOR_SHIFT) { | ||
321 | dprintk("%s Final length mismatch\n", __func__); | ||
322 | be = NULL; | ||
323 | goto out_err; | ||
324 | } | ||
325 | if (lv.start < lv.cowread) { | ||
326 | dprintk("%s Final uncovered COW extent\n", __func__); | ||
327 | be = NULL; | ||
328 | goto out_err; | ||
329 | } | ||
330 | /* Extents decoded properly, now try to merge them in to | ||
331 | * existing layout extents. | ||
332 | */ | ||
333 | list_for_each_entry_safe(be, save, &extents, be_list) { | ||
334 | list_del(&be->be_list); | ||
335 | |||
336 | status = ext_tree_insert(bl, be); | ||
337 | if (status) | ||
338 | goto out_free_list; | ||
339 | } | ||
340 | status = 0; | ||
341 | out: | ||
342 | __free_page(scratch); | ||
343 | dprintk("%s returns %i\n", __func__, status); | ||
344 | return status; | ||
345 | |||
346 | out_err: | ||
347 | nfs4_put_deviceid_node(be->be_device); | ||
348 | kfree(be); | ||
349 | out_free_list: | ||
350 | while (!list_empty(&extents)) { | ||
351 | be = list_first_entry(&extents, struct pnfs_block_extent, | ||
352 | be_list); | ||
353 | list_del(&be->be_list); | ||
354 | nfs4_put_deviceid_node(be->be_device); | ||
355 | kfree(be); | ||
356 | } | ||
357 | goto out; | ||
358 | } | ||