aboutsummaryrefslogtreecommitdiffstats
path: root/fs/logfs/segment.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/logfs/segment.c')
-rw-r--r--fs/logfs/segment.c70
1 files changed, 38 insertions, 32 deletions
diff --git a/fs/logfs/segment.c b/fs/logfs/segment.c
index 1a14f9910d55..a9657afb70ad 100644
--- a/fs/logfs/segment.c
+++ b/fs/logfs/segment.c
@@ -10,6 +10,7 @@
10 * three kinds of objects: inodes, dentries and blocks, both data and indirect. 10 * three kinds of objects: inodes, dentries and blocks, both data and indirect.
11 */ 11 */
12#include "logfs.h" 12#include "logfs.h"
13#include <linux/slab.h>
13 14
14static int logfs_mark_segment_bad(struct super_block *sb, u32 segno) 15static int logfs_mark_segment_bad(struct super_block *sb, u32 segno)
15{ 16{
@@ -66,7 +67,7 @@ static struct page *get_mapping_page(struct super_block *sb, pgoff_t index,
66 return page; 67 return page;
67} 68}
68 69
69void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len, 70int __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len,
70 int use_filler) 71 int use_filler)
71{ 72{
72 pgoff_t index = ofs >> PAGE_SHIFT; 73 pgoff_t index = ofs >> PAGE_SHIFT;
@@ -80,8 +81,10 @@ void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len,
80 copylen = min((ulong)len, PAGE_SIZE - offset); 81 copylen = min((ulong)len, PAGE_SIZE - offset);
81 82
82 page = get_mapping_page(area->a_sb, index, use_filler); 83 page = get_mapping_page(area->a_sb, index, use_filler);
83 SetPageUptodate(page); 84 if (IS_ERR(page))
85 return PTR_ERR(page);
84 BUG_ON(!page); /* FIXME: reserve a pool */ 86 BUG_ON(!page); /* FIXME: reserve a pool */
87 SetPageUptodate(page);
85 memcpy(page_address(page) + offset, buf, copylen); 88 memcpy(page_address(page) + offset, buf, copylen);
86 SetPagePrivate(page); 89 SetPagePrivate(page);
87 page_cache_release(page); 90 page_cache_release(page);
@@ -91,52 +94,61 @@ void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len,
91 offset = 0; 94 offset = 0;
92 index++; 95 index++;
93 } while (len); 96 } while (len);
97 return 0;
94} 98}
95 99
96/* 100static void pad_partial_page(struct logfs_area *area)
97 * bdev_writeseg will write full pages. Memset the tail to prevent data leaks.
98 */
99static void pad_wbuf(struct logfs_area *area, int final)
100{ 101{
101 struct super_block *sb = area->a_sb; 102 struct super_block *sb = area->a_sb;
102 struct logfs_super *super = logfs_super(sb);
103 struct page *page; 103 struct page *page;
104 u64 ofs = dev_ofs(sb, area->a_segno, area->a_used_bytes); 104 u64 ofs = dev_ofs(sb, area->a_segno, area->a_used_bytes);
105 pgoff_t index = ofs >> PAGE_SHIFT; 105 pgoff_t index = ofs >> PAGE_SHIFT;
106 long offset = ofs & (PAGE_SIZE-1); 106 long offset = ofs & (PAGE_SIZE-1);
107 u32 len = PAGE_SIZE - offset; 107 u32 len = PAGE_SIZE - offset;
108 108
109 if (len == PAGE_SIZE) { 109 if (len % PAGE_SIZE) {
110 /* The math in this function can surely use some love */ 110 page = get_mapping_page(sb, index, 0);
111 len = 0;
112 }
113 if (len) {
114 BUG_ON(area->a_used_bytes >= super->s_segsize);
115
116 page = get_mapping_page(area->a_sb, index, 0);
117 BUG_ON(!page); /* FIXME: reserve a pool */ 111 BUG_ON(!page); /* FIXME: reserve a pool */
118 memset(page_address(page) + offset, 0xff, len); 112 memset(page_address(page) + offset, 0xff, len);
119 SetPagePrivate(page); 113 SetPagePrivate(page);
120 page_cache_release(page); 114 page_cache_release(page);
121 } 115 }
116}
122 117
123 if (!final) 118static void pad_full_pages(struct logfs_area *area)
124 return; 119{
120 struct super_block *sb = area->a_sb;
121 struct logfs_super *super = logfs_super(sb);
122 u64 ofs = dev_ofs(sb, area->a_segno, area->a_used_bytes);
123 u32 len = super->s_segsize - area->a_used_bytes;
124 pgoff_t index = PAGE_CACHE_ALIGN(ofs) >> PAGE_CACHE_SHIFT;
125 pgoff_t no_indizes = len >> PAGE_CACHE_SHIFT;
126 struct page *page;
125 127
126 area->a_used_bytes += len; 128 while (no_indizes) {
127 for ( ; area->a_used_bytes < super->s_segsize; 129 page = get_mapping_page(sb, index, 0);
128 area->a_used_bytes += PAGE_SIZE) {
129 /* Memset another page */
130 index++;
131 page = get_mapping_page(area->a_sb, index, 0);
132 BUG_ON(!page); /* FIXME: reserve a pool */ 130 BUG_ON(!page); /* FIXME: reserve a pool */
133 memset(page_address(page), 0xff, PAGE_SIZE); 131 SetPageUptodate(page);
132 memset(page_address(page), 0xff, PAGE_CACHE_SIZE);
134 SetPagePrivate(page); 133 SetPagePrivate(page);
135 page_cache_release(page); 134 page_cache_release(page);
135 index++;
136 no_indizes--;
136 } 137 }
137} 138}
138 139
139/* 140/*
141 * bdev_writeseg will write full pages. Memset the tail to prevent data leaks.
142 * Also make sure we allocate (and memset) all pages for final writeout.
143 */
144static void pad_wbuf(struct logfs_area *area, int final)
145{
146 pad_partial_page(area);
147 if (final)
148 pad_full_pages(area);
149}
150
151/*
140 * We have to be careful with the alias tree. Since lookup is done by bix, 152 * We have to be careful with the alias tree. Since lookup is done by bix,
141 * it needs to be normalized, so 14, 15, 16, etc. all match when dealing with 153 * it needs to be normalized, so 14, 15, 16, etc. all match when dealing with
142 * indirect blocks. So always use it through accessor functions. 154 * indirect blocks. So always use it through accessor functions.
@@ -174,14 +186,8 @@ static int btree_write_alias(struct super_block *sb, struct logfs_block *block,
174 return 0; 186 return 0;
175} 187}
176 188
177static gc_level_t btree_block_level(struct logfs_block *block)
178{
179 return expand_level(block->ino, block->level);
180}
181
182static struct logfs_block_ops btree_block_ops = { 189static struct logfs_block_ops btree_block_ops = {
183 .write_block = btree_write_block, 190 .write_block = btree_write_block,
184 .block_level = btree_block_level,
185 .free_block = __free_block, 191 .free_block = __free_block,
186 .write_alias = btree_write_alias, 192 .write_alias = btree_write_alias,
187}; 193};
@@ -683,7 +689,7 @@ int logfs_segment_delete(struct inode *inode, struct logfs_shadow *shadow)
683 return 0; 689 return 0;
684} 690}
685 691
686static void freeseg(struct super_block *sb, u32 segno) 692void freeseg(struct super_block *sb, u32 segno)
687{ 693{
688 struct logfs_super *super = logfs_super(sb); 694 struct logfs_super *super = logfs_super(sb);
689 struct address_space *mapping = super->s_mapping_inode->i_mapping; 695 struct address_space *mapping = super->s_mapping_inode->i_mapping;
@@ -910,7 +916,7 @@ err:
910 for (i--; i >= 0; i--) 916 for (i--; i >= 0; i--)
911 free_area(super->s_area[i]); 917 free_area(super->s_area[i]);
912 free_area(super->s_journal_area); 918 free_area(super->s_journal_area);
913 mempool_destroy(super->s_alias_pool); 919 logfs_mempool_destroy(super->s_alias_pool);
914 return -ENOMEM; 920 return -ENOMEM;
915} 921}
916 922