diff options
Diffstat (limited to 'fs/logfs/segment.c')
-rw-r--r-- | fs/logfs/segment.c | 51 |
1 files changed, 39 insertions, 12 deletions
diff --git a/fs/logfs/segment.c b/fs/logfs/segment.c index 9d5187353255..ab798ed1cc88 100644 --- a/fs/logfs/segment.c +++ b/fs/logfs/segment.c | |||
@@ -86,7 +86,11 @@ int __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len, | |||
86 | BUG_ON(!page); /* FIXME: reserve a pool */ | 86 | BUG_ON(!page); /* FIXME: reserve a pool */ |
87 | SetPageUptodate(page); | 87 | SetPageUptodate(page); |
88 | memcpy(page_address(page) + offset, buf, copylen); | 88 | memcpy(page_address(page) + offset, buf, copylen); |
89 | SetPagePrivate(page); | 89 | |
90 | if (!PagePrivate(page)) { | ||
91 | SetPagePrivate(page); | ||
92 | page_cache_get(page); | ||
93 | } | ||
90 | page_cache_release(page); | 94 | page_cache_release(page); |
91 | 95 | ||
92 | buf += copylen; | 96 | buf += copylen; |
@@ -110,7 +114,10 @@ static void pad_partial_page(struct logfs_area *area) | |||
110 | page = get_mapping_page(sb, index, 0); | 114 | page = get_mapping_page(sb, index, 0); |
111 | BUG_ON(!page); /* FIXME: reserve a pool */ | 115 | BUG_ON(!page); /* FIXME: reserve a pool */ |
112 | memset(page_address(page) + offset, 0xff, len); | 116 | memset(page_address(page) + offset, 0xff, len); |
113 | SetPagePrivate(page); | 117 | if (!PagePrivate(page)) { |
118 | SetPagePrivate(page); | ||
119 | page_cache_get(page); | ||
120 | } | ||
114 | page_cache_release(page); | 121 | page_cache_release(page); |
115 | } | 122 | } |
116 | } | 123 | } |
@@ -130,7 +137,10 @@ static void pad_full_pages(struct logfs_area *area) | |||
130 | BUG_ON(!page); /* FIXME: reserve a pool */ | 137 | BUG_ON(!page); /* FIXME: reserve a pool */ |
131 | SetPageUptodate(page); | 138 | SetPageUptodate(page); |
132 | memset(page_address(page), 0xff, PAGE_CACHE_SIZE); | 139 | memset(page_address(page), 0xff, PAGE_CACHE_SIZE); |
133 | SetPagePrivate(page); | 140 | if (!PagePrivate(page)) { |
141 | SetPagePrivate(page); | ||
142 | page_cache_get(page); | ||
143 | } | ||
134 | page_cache_release(page); | 144 | page_cache_release(page); |
135 | index++; | 145 | index++; |
136 | no_indizes--; | 146 | no_indizes--; |
@@ -485,8 +495,12 @@ static void move_btree_to_page(struct inode *inode, struct page *page, | |||
485 | mempool_free(item, super->s_alias_pool); | 495 | mempool_free(item, super->s_alias_pool); |
486 | } | 496 | } |
487 | block->page = page; | 497 | block->page = page; |
488 | SetPagePrivate(page); | 498 | |
489 | page->private = (unsigned long)block; | 499 | if (!PagePrivate(page)) { |
500 | SetPagePrivate(page); | ||
501 | page_cache_get(page); | ||
502 | set_page_private(page, (unsigned long) block); | ||
503 | } | ||
490 | block->ops = &indirect_block_ops; | 504 | block->ops = &indirect_block_ops; |
491 | initialize_block_counters(page, block, data, 0); | 505 | initialize_block_counters(page, block, data, 0); |
492 | } | 506 | } |
@@ -536,8 +550,12 @@ void move_page_to_btree(struct page *page) | |||
536 | list_add(&item->list, &block->item_list); | 550 | list_add(&item->list, &block->item_list); |
537 | } | 551 | } |
538 | block->page = NULL; | 552 | block->page = NULL; |
539 | ClearPagePrivate(page); | 553 | |
540 | page->private = 0; | 554 | if (PagePrivate(page)) { |
555 | ClearPagePrivate(page); | ||
556 | page_cache_release(page); | ||
557 | set_page_private(page, 0); | ||
558 | } | ||
541 | block->ops = &btree_block_ops; | 559 | block->ops = &btree_block_ops; |
542 | err = alias_tree_insert(block->sb, block->ino, block->bix, block->level, | 560 | err = alias_tree_insert(block->sb, block->ino, block->bix, block->level, |
543 | block); | 561 | block); |
@@ -702,7 +720,10 @@ void freeseg(struct super_block *sb, u32 segno) | |||
702 | page = find_get_page(mapping, ofs >> PAGE_SHIFT); | 720 | page = find_get_page(mapping, ofs >> PAGE_SHIFT); |
703 | if (!page) | 721 | if (!page) |
704 | continue; | 722 | continue; |
705 | ClearPagePrivate(page); | 723 | if (PagePrivate(page)) { |
724 | ClearPagePrivate(page); | ||
725 | page_cache_release(page); | ||
726 | } | ||
706 | page_cache_release(page); | 727 | page_cache_release(page); |
707 | } | 728 | } |
708 | } | 729 | } |
@@ -841,6 +862,16 @@ static void free_area(struct logfs_area *area) | |||
841 | kfree(area); | 862 | kfree(area); |
842 | } | 863 | } |
843 | 864 | ||
865 | void free_areas(struct super_block *sb) | ||
866 | { | ||
867 | struct logfs_super *super = logfs_super(sb); | ||
868 | int i; | ||
869 | |||
870 | for_each_area(i) | ||
871 | free_area(super->s_area[i]); | ||
872 | free_area(super->s_journal_area); | ||
873 | } | ||
874 | |||
844 | static struct logfs_area *alloc_area(struct super_block *sb) | 875 | static struct logfs_area *alloc_area(struct super_block *sb) |
845 | { | 876 | { |
846 | struct logfs_area *area; | 877 | struct logfs_area *area; |
@@ -923,10 +954,6 @@ err: | |||
923 | void logfs_cleanup_areas(struct super_block *sb) | 954 | void logfs_cleanup_areas(struct super_block *sb) |
924 | { | 955 | { |
925 | struct logfs_super *super = logfs_super(sb); | 956 | struct logfs_super *super = logfs_super(sb); |
926 | int i; | ||
927 | 957 | ||
928 | btree_grim_visitor128(&super->s_object_alias_tree, 0, kill_alias); | 958 | btree_grim_visitor128(&super->s_object_alias_tree, 0, kill_alias); |
929 | for_each_area(i) | ||
930 | free_area(super->s_area[i]); | ||
931 | free_area(super->s_journal_area); | ||
932 | } | 959 | } |