aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/logfs/dev_bdev.c88
-rw-r--r--fs/logfs/dev_mtd.c3
-rw-r--r--fs/logfs/journal.c2
-rw-r--r--fs/logfs/logfs.h6
-rw-r--r--fs/logfs/segment.c6
-rw-r--r--fs/logfs/super.c12
6 files changed, 97 insertions, 20 deletions
diff --git a/fs/logfs/dev_bdev.c b/fs/logfs/dev_bdev.c
index 58a057b6e1af..9718c22f186d 100644
--- a/fs/logfs/dev_bdev.c
+++ b/fs/logfs/dev_bdev.c
@@ -167,27 +167,91 @@ static void bdev_writeseg(struct super_block *sb, u64 ofs, size_t len)
167 generic_unplug_device(bdev_get_queue(logfs_super(sb)->s_bdev)); 167 generic_unplug_device(bdev_get_queue(logfs_super(sb)->s_bdev));
168} 168}
169 169
170static int bdev_erase(struct super_block *sb, loff_t to, size_t len) 170
171static void erase_end_io(struct bio *bio, int err)
172{
173 const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
174 struct super_block *sb = bio->bi_private;
175 struct logfs_super *super = logfs_super(sb);
176
177 BUG_ON(!uptodate); /* FIXME: Retry io or write elsewhere */
178 BUG_ON(err);
179 BUG_ON(bio->bi_vcnt == 0);
180 bio_put(bio);
181 if (atomic_dec_and_test(&super->s_pending_writes))
182 wake_up(&wq);
183}
184
185static int do_erase(struct super_block *sb, u64 ofs, pgoff_t index,
186 size_t nr_pages)
187{
188 struct logfs_super *super = logfs_super(sb);
189 struct bio *bio;
190 struct request_queue *q = bdev_get_queue(sb->s_bdev);
191 unsigned int max_pages = queue_max_hw_sectors(q) >> (PAGE_SHIFT - 9);
192 int i;
193
194 bio = bio_alloc(GFP_NOFS, max_pages);
195 BUG_ON(!bio); /* FIXME: handle this */
196
197 for (i = 0; i < nr_pages; i++) {
198 if (i >= max_pages) {
199 /* Block layer cannot split bios :( */
200 bio->bi_vcnt = i;
201 bio->bi_idx = 0;
202 bio->bi_size = i * PAGE_SIZE;
203 bio->bi_bdev = super->s_bdev;
204 bio->bi_sector = ofs >> 9;
205 bio->bi_private = sb;
206 bio->bi_end_io = erase_end_io;
207 atomic_inc(&super->s_pending_writes);
208 submit_bio(WRITE, bio);
209
210 ofs += i * PAGE_SIZE;
211 index += i;
212 nr_pages -= i;
213 i = 0;
214
215 bio = bio_alloc(GFP_NOFS, max_pages);
216 BUG_ON(!bio);
217 }
218 bio->bi_io_vec[i].bv_page = super->s_erase_page;
219 bio->bi_io_vec[i].bv_len = PAGE_SIZE;
220 bio->bi_io_vec[i].bv_offset = 0;
221 }
222 bio->bi_vcnt = nr_pages;
223 bio->bi_idx = 0;
224 bio->bi_size = nr_pages * PAGE_SIZE;
225 bio->bi_bdev = super->s_bdev;
226 bio->bi_sector = ofs >> 9;
227 bio->bi_private = sb;
228 bio->bi_end_io = erase_end_io;
229 atomic_inc(&super->s_pending_writes);
230 submit_bio(WRITE, bio);
231 return 0;
232}
233
234static int bdev_erase(struct super_block *sb, loff_t to, size_t len,
235 int ensure_write)
171{ 236{
172 struct logfs_super *super = logfs_super(sb); 237 struct logfs_super *super = logfs_super(sb);
173 struct address_space *mapping = super->s_mapping_inode->i_mapping;
174 struct page *page;
175 pgoff_t index = to >> PAGE_SHIFT;
176 int i, nr_pages = len >> PAGE_SHIFT;
177 238
178 BUG_ON(to & (PAGE_SIZE - 1)); 239 BUG_ON(to & (PAGE_SIZE - 1));
179 BUG_ON(len & (PAGE_SIZE - 1)); 240 BUG_ON(len & (PAGE_SIZE - 1));
180 241
181 if (logfs_super(sb)->s_flags & LOGFS_SB_FLAG_RO) 242 if (super->s_flags & LOGFS_SB_FLAG_RO)
182 return -EROFS; 243 return -EROFS;
183 244
184 for (i = 0; i < nr_pages; i++) { 245 if (ensure_write) {
185 page = find_get_page(mapping, index + i); 246 /*
186 if (page) { 247 * Object store doesn't care whether erases happen or not.
187 memset(page_address(page), 0xFF, PAGE_SIZE); 248 * But for the journal they are required. Otherwise a scan
188 page_cache_release(page); 249 * can find an old commit entry and assume it is the current
189 } 250 * one, travelling back in time.
251 */
252 do_erase(sb, to, to >> PAGE_SHIFT, len >> PAGE_SHIFT);
190 } 253 }
254
191 return 0; 255 return 0;
192} 256}
193 257
diff --git a/fs/logfs/dev_mtd.c b/fs/logfs/dev_mtd.c
index 68e99d046c23..cafb6ef2e05b 100644
--- a/fs/logfs/dev_mtd.c
+++ b/fs/logfs/dev_mtd.c
@@ -83,7 +83,8 @@ static int mtd_erase_mapping(struct super_block *sb, loff_t ofs, size_t len)
83 return 0; 83 return 0;
84} 84}
85 85
86static int mtd_erase(struct super_block *sb, loff_t ofs, size_t len) 86static int mtd_erase(struct super_block *sb, loff_t ofs, size_t len,
87 int ensure_write)
87{ 88{
88 struct mtd_info *mtd = logfs_super(sb)->s_mtd; 89 struct mtd_info *mtd = logfs_super(sb)->s_mtd;
89 struct erase_info ei; 90 struct erase_info ei;
diff --git a/fs/logfs/journal.c b/fs/logfs/journal.c
index 2f2e8e4fd02d..c0e7d63221d4 100644
--- a/fs/logfs/journal.c
+++ b/fs/logfs/journal.c
@@ -392,7 +392,7 @@ static int journal_erase_segment(struct logfs_area *area)
392 u64 ofs; 392 u64 ofs;
393 int err; 393 int err;
394 394
395 err = logfs_erase_segment(sb, area->a_segno); 395 err = logfs_erase_segment(sb, area->a_segno, 1);
396 if (err) 396 if (err)
397 return err; 397 return err;
398 398
diff --git a/fs/logfs/logfs.h b/fs/logfs/logfs.h
index e3082abe9e3b..72592114a28f 100644
--- a/fs/logfs/logfs.h
+++ b/fs/logfs/logfs.h
@@ -151,7 +151,8 @@ struct logfs_device_ops {
151 int (*write_sb)(struct super_block *sb, struct page *page); 151 int (*write_sb)(struct super_block *sb, struct page *page);
152 int (*readpage)(void *_sb, struct page *page); 152 int (*readpage)(void *_sb, struct page *page);
153 void (*writeseg)(struct super_block *sb, u64 ofs, size_t len); 153 void (*writeseg)(struct super_block *sb, u64 ofs, size_t len);
154 int (*erase)(struct super_block *sb, loff_t ofs, size_t len); 154 int (*erase)(struct super_block *sb, loff_t ofs, size_t len,
155 int ensure_write);
155 void (*sync)(struct super_block *sb); 156 void (*sync)(struct super_block *sb);
156 void (*put_device)(struct super_block *sb); 157 void (*put_device)(struct super_block *sb);
157}; 158};
@@ -327,6 +328,7 @@ struct logfs_super {
327 u64 s_feature_compat; 328 u64 s_feature_compat;
328 u64 s_feature_flags; 329 u64 s_feature_flags;
329 u64 s_sb_ofs[2]; 330 u64 s_sb_ofs[2];
331 struct page *s_erase_page; /* for dev_bdev.c */
330 /* alias.c fields */ 332 /* alias.c fields */
331 struct btree_head32 s_segment_alias; /* remapped segments */ 333 struct btree_head32 s_segment_alias; /* remapped segments */
332 int s_no_object_aliases; 334 int s_no_object_aliases;
@@ -572,7 +574,7 @@ int get_page_reserve(struct inode *inode, struct page *page);
572extern struct logfs_block_ops indirect_block_ops; 574extern struct logfs_block_ops indirect_block_ops;
573 575
574/* segment.c */ 576/* segment.c */
575int logfs_erase_segment(struct super_block *sb, u32 ofs); 577int logfs_erase_segment(struct super_block *sb, u32 ofs, int ensure_erase);
576int wbuf_read(struct super_block *sb, u64 ofs, size_t len, void *buf); 578int wbuf_read(struct super_block *sb, u64 ofs, size_t len, void *buf);
577int logfs_segment_read(struct inode *inode, struct page *page, u64 ofs, u64 bix, 579int logfs_segment_read(struct inode *inode, struct page *page, u64 ofs, u64 bix,
578 level_t level); 580 level_t level);
diff --git a/fs/logfs/segment.c b/fs/logfs/segment.c
index 5f58b74516ca..664cd0dd3576 100644
--- a/fs/logfs/segment.c
+++ b/fs/logfs/segment.c
@@ -25,14 +25,14 @@ static int logfs_mark_segment_bad(struct super_block *sb, u32 segno)
25 return 0; 25 return 0;
26} 26}
27 27
28int logfs_erase_segment(struct super_block *sb, u32 segno) 28int logfs_erase_segment(struct super_block *sb, u32 segno, int ensure_erase)
29{ 29{
30 struct logfs_super *super = logfs_super(sb); 30 struct logfs_super *super = logfs_super(sb);
31 31
32 super->s_gec++; 32 super->s_gec++;
33 33
34 return super->s_devops->erase(sb, (u64)segno << super->s_segshift, 34 return super->s_devops->erase(sb, (u64)segno << super->s_segshift,
35 super->s_segsize); 35 super->s_segsize, ensure_erase);
36} 36}
37 37
38static s64 logfs_get_free_bytes(struct logfs_area *area, size_t bytes) 38static s64 logfs_get_free_bytes(struct logfs_area *area, size_t bytes)
@@ -798,7 +798,7 @@ static int ostore_erase_segment(struct logfs_area *area)
798 u64 ofs; 798 u64 ofs;
799 int err; 799 int err;
800 800
801 err = logfs_erase_segment(sb, area->a_segno); 801 err = logfs_erase_segment(sb, area->a_segno, 0);
802 if (err) 802 if (err)
803 return err; 803 return err;
804 804
diff --git a/fs/logfs/super.c b/fs/logfs/super.c
index d128a2c1c8d1..94d80f7ee7c2 100644
--- a/fs/logfs/super.c
+++ b/fs/logfs/super.c
@@ -317,6 +317,7 @@ static int logfs_make_writeable(struct super_block *sb)
317 317
318static int logfs_get_sb_final(struct super_block *sb, struct vfsmount *mnt) 318static int logfs_get_sb_final(struct super_block *sb, struct vfsmount *mnt)
319{ 319{
320 struct logfs_super *super = logfs_super(sb);
320 struct inode *rootdir; 321 struct inode *rootdir;
321 int err; 322 int err;
322 323
@@ -329,15 +330,22 @@ static int logfs_get_sb_final(struct super_block *sb, struct vfsmount *mnt)
329 if (!sb->s_root) 330 if (!sb->s_root)
330 goto fail; 331 goto fail;
331 332
333 super->s_erase_page = alloc_pages(GFP_KERNEL, 0);
334 if (!super->s_erase_page)
335 goto fail2;
336 memset(page_address(super->s_erase_page), 0xFF, PAGE_SIZE);
337
332 /* FIXME: check for read-only mounts */ 338 /* FIXME: check for read-only mounts */
333 err = logfs_make_writeable(sb); 339 err = logfs_make_writeable(sb);
334 if (err) 340 if (err)
335 goto fail2; 341 goto fail3;
336 342
337 log_super("LogFS: Finished mounting\n"); 343 log_super("LogFS: Finished mounting\n");
338 simple_set_mnt(mnt, sb); 344 simple_set_mnt(mnt, sb);
339 return 0; 345 return 0;
340 346
347fail3:
348 __free_page(super->s_erase_page);
341fail2: 349fail2:
342 iput(rootdir); 350 iput(rootdir);
343fail: 351fail:
@@ -498,6 +506,8 @@ static void logfs_kill_sb(struct super_block *sb)
498 logfs_cleanup_journal(sb); 506 logfs_cleanup_journal(sb);
499 logfs_cleanup_areas(sb); 507 logfs_cleanup_areas(sb);
500 logfs_cleanup_rw(sb); 508 logfs_cleanup_rw(sb);
509 if (super->s_erase_page)
510 __free_page(super->s_erase_page);
501 super->s_devops->put_device(sb); 511 super->s_devops->put_device(sb);
502 mempool_destroy(super->s_btree_pool); 512 mempool_destroy(super->s_btree_pool);
503 mempool_destroy(super->s_alias_pool); 513 mempool_destroy(super->s_alias_pool);