diff options
author | Fred Isaman <iisaman@citi.umich.edu> | 2011-07-30 20:52:50 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-07-31 12:18:17 -0400 |
commit | 9f3770422c771da32c1d14e650c695eec27dbd1d (patch) | |
tree | 5c0ce4d8af872198c21c0fe3fd21fc8bf06a2d4b | |
parent | c1c2a4cd352269f1fb585b4a5c63abe24dd946c6 (diff) |
pnfsblock: merge rw extents
Signed-off-by: Fred Isaman <iisaman@citi.umich.edu>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
Signed-off-by: Benny Halevy <bhalevy@tonian.com>
Signed-off-by: Jim Rees <rees@umich.edu>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r-- | fs/nfs/blocklayout/extents.c | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/fs/nfs/blocklayout/extents.c b/fs/nfs/blocklayout/extents.c index 473faee9cdef..292aadfd4d46 100644 --- a/fs/nfs/blocklayout/extents.c +++ b/fs/nfs/blocklayout/extents.c | |||
@@ -493,3 +493,50 @@ bl_find_get_extent(struct pnfs_block_layout *bl, sector_t isect, | |||
493 | print_bl_extent(ret); | 493 | print_bl_extent(ret); |
494 | return ret; | 494 | return ret; |
495 | } | 495 | } |
496 | |||
497 | /* Helper function to set_to_rw that initialize a new extent */ | ||
498 | static void | ||
499 | _prep_new_extent(struct pnfs_block_extent *new, | ||
500 | struct pnfs_block_extent *orig, | ||
501 | sector_t offset, sector_t length, int state) | ||
502 | { | ||
503 | kref_init(&new->be_refcnt); | ||
504 | /* don't need to INIT_LIST_HEAD(&new->be_node) */ | ||
505 | memcpy(&new->be_devid, &orig->be_devid, sizeof(struct nfs4_deviceid)); | ||
506 | new->be_mdev = orig->be_mdev; | ||
507 | new->be_f_offset = offset; | ||
508 | new->be_length = length; | ||
509 | new->be_v_offset = orig->be_v_offset - orig->be_f_offset + offset; | ||
510 | new->be_state = state; | ||
511 | new->be_inval = orig->be_inval; | ||
512 | } | ||
513 | |||
514 | /* Tries to merge be with extent in front of it in list. | ||
515 | * Frees storage if not used. | ||
516 | */ | ||
517 | static struct pnfs_block_extent * | ||
518 | _front_merge(struct pnfs_block_extent *be, struct list_head *head, | ||
519 | struct pnfs_block_extent *storage) | ||
520 | { | ||
521 | struct pnfs_block_extent *prev; | ||
522 | |||
523 | if (!storage) | ||
524 | goto no_merge; | ||
525 | if (&be->be_node == head || be->be_node.prev == head) | ||
526 | goto no_merge; | ||
527 | prev = list_entry(be->be_node.prev, struct pnfs_block_extent, be_node); | ||
528 | if ((prev->be_f_offset + prev->be_length != be->be_f_offset) || | ||
529 | !extents_consistent(prev, be)) | ||
530 | goto no_merge; | ||
531 | _prep_new_extent(storage, prev, prev->be_f_offset, | ||
532 | prev->be_length + be->be_length, prev->be_state); | ||
533 | list_replace(&prev->be_node, &storage->be_node); | ||
534 | bl_put_extent(prev); | ||
535 | list_del(&be->be_node); | ||
536 | bl_put_extent(be); | ||
537 | return storage; | ||
538 | |||
539 | no_merge: | ||
540 | kfree(storage); | ||
541 | return be; | ||
542 | } | ||