aboutsummaryrefslogtreecommitdiffstats
path: root/fs/logfs
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2010-04-26 03:08:27 -0400
committerPaul Mundt <lethal@linux-sh.org>2010-04-26 03:08:27 -0400
commite19553427c2e8fdb04fdd98e407164bb59a840ba (patch)
tree5332234b2dad07c03c27e4608afb16f297f41e61 /fs/logfs
parent35f6cd4a06432034665a1499ca4b022437423aac (diff)
parent83515bc7df812555e20cda48614674e2f346f9f5 (diff)
Merge branch 'sh/stable-updates'
Conflicts: arch/sh/kernel/dwarf.c drivers/dma/shdma.c Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'fs/logfs')
-rw-r--r--fs/logfs/dev_bdev.c1
-rw-r--r--fs/logfs/dir.c2
-rw-r--r--fs/logfs/gc.c9
-rw-r--r--fs/logfs/inode.c1
-rw-r--r--fs/logfs/journal.c30
-rw-r--r--fs/logfs/logfs.h15
-rw-r--r--fs/logfs/readwrite.c76
-rw-r--r--fs/logfs/segment.c9
-rw-r--r--fs/logfs/super.c12
9 files changed, 99 insertions, 56 deletions
diff --git a/fs/logfs/dev_bdev.c b/fs/logfs/dev_bdev.c
index a5d0c56d3ebc..243c00071f76 100644
--- a/fs/logfs/dev_bdev.c
+++ b/fs/logfs/dev_bdev.c
@@ -9,6 +9,7 @@
9#include <linux/bio.h> 9#include <linux/bio.h>
10#include <linux/blkdev.h> 10#include <linux/blkdev.h>
11#include <linux/buffer_head.h> 11#include <linux/buffer_head.h>
12#include <linux/gfp.h>
12 13
13#define PAGE_OFS(ofs) ((ofs) & (PAGE_SIZE-1)) 14#define PAGE_OFS(ofs) ((ofs) & (PAGE_SIZE-1))
14 15
diff --git a/fs/logfs/dir.c b/fs/logfs/dir.c
index c76b4b5c7ff6..2396a85c0f55 100644
--- a/fs/logfs/dir.c
+++ b/fs/logfs/dir.c
@@ -6,7 +6,7 @@
6 * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org> 6 * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org>
7 */ 7 */
8#include "logfs.h" 8#include "logfs.h"
9 9#include <linux/slab.h>
10 10
11/* 11/*
12 * Atomic dir operations 12 * Atomic dir operations
diff --git a/fs/logfs/gc.c b/fs/logfs/gc.c
index 92949f95a901..76c242fbe1b0 100644
--- a/fs/logfs/gc.c
+++ b/fs/logfs/gc.c
@@ -7,6 +7,7 @@
7 */ 7 */
8#include "logfs.h" 8#include "logfs.h"
9#include <linux/sched.h> 9#include <linux/sched.h>
10#include <linux/slab.h>
10 11
11/* 12/*
12 * Wear leveling needs to kick in when the difference between low erase 13 * Wear leveling needs to kick in when the difference between low erase
@@ -458,6 +459,14 @@ static void __logfs_gc_pass(struct super_block *sb, int target)
458 struct logfs_block *block; 459 struct logfs_block *block;
459 int round, progress, last_progress = 0; 460 int round, progress, last_progress = 0;
460 461
462 /*
463 * Doing too many changes to the segfile at once would result
464 * in a large number of aliases. Write the journal before
465 * things get out of hand.
466 */
467 if (super->s_shadow_tree.no_shadowed_segments >= MAX_OBJ_ALIASES)
468 logfs_write_anchor(sb);
469
461 if (no_free_segments(sb) >= target && 470 if (no_free_segments(sb) >= target &&
462 super->s_no_object_aliases < MAX_OBJ_ALIASES) 471 super->s_no_object_aliases < MAX_OBJ_ALIASES)
463 return; 472 return;
diff --git a/fs/logfs/inode.c b/fs/logfs/inode.c
index 33ec1aeaeec4..14ed27274da2 100644
--- a/fs/logfs/inode.c
+++ b/fs/logfs/inode.c
@@ -6,6 +6,7 @@
6 * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org> 6 * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org>
7 */ 7 */
8#include "logfs.h" 8#include "logfs.h"
9#include <linux/slab.h>
9#include <linux/writeback.h> 10#include <linux/writeback.h>
10#include <linux/backing-dev.h> 11#include <linux/backing-dev.h>
11 12
diff --git a/fs/logfs/journal.c b/fs/logfs/journal.c
index d57c7b07b60b..fb0a613f885b 100644
--- a/fs/logfs/journal.c
+++ b/fs/logfs/journal.c
@@ -6,6 +6,7 @@
6 * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org> 6 * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org>
7 */ 7 */
8#include "logfs.h" 8#include "logfs.h"
9#include <linux/slab.h>
9 10
10static void logfs_calc_free(struct super_block *sb) 11static void logfs_calc_free(struct super_block *sb)
11{ 12{
@@ -388,7 +389,10 @@ static void journal_get_erase_count(struct logfs_area *area)
388static int journal_erase_segment(struct logfs_area *area) 389static int journal_erase_segment(struct logfs_area *area)
389{ 390{
390 struct super_block *sb = area->a_sb; 391 struct super_block *sb = area->a_sb;
391 struct logfs_segment_header sh; 392 union {
393 struct logfs_segment_header sh;
394 unsigned char c[ALIGN(sizeof(struct logfs_segment_header), 16)];
395 } u;
392 u64 ofs; 396 u64 ofs;
393 int err; 397 int err;
394 398
@@ -396,20 +400,21 @@ static int journal_erase_segment(struct logfs_area *area)
396 if (err) 400 if (err)
397 return err; 401 return err;
398 402
399 sh.pad = 0; 403 memset(&u, 0, sizeof(u));
400 sh.type = SEG_JOURNAL; 404 u.sh.pad = 0;
401 sh.level = 0; 405 u.sh.type = SEG_JOURNAL;
402 sh.segno = cpu_to_be32(area->a_segno); 406 u.sh.level = 0;
403 sh.ec = cpu_to_be32(area->a_erase_count); 407 u.sh.segno = cpu_to_be32(area->a_segno);
404 sh.gec = cpu_to_be64(logfs_super(sb)->s_gec); 408 u.sh.ec = cpu_to_be32(area->a_erase_count);
405 sh.crc = logfs_crc32(&sh, sizeof(sh), 4); 409 u.sh.gec = cpu_to_be64(logfs_super(sb)->s_gec);
410 u.sh.crc = logfs_crc32(&u.sh, sizeof(u.sh), 4);
406 411
407 /* This causes a bug in segment.c. Not yet. */ 412 /* This causes a bug in segment.c. Not yet. */
408 //logfs_set_segment_erased(sb, area->a_segno, area->a_erase_count, 0); 413 //logfs_set_segment_erased(sb, area->a_segno, area->a_erase_count, 0);
409 414
410 ofs = dev_ofs(sb, area->a_segno, 0); 415 ofs = dev_ofs(sb, area->a_segno, 0);
411 area->a_used_bytes = ALIGN(sizeof(sh), 16); 416 area->a_used_bytes = sizeof(u);
412 logfs_buf_write(area, ofs, &sh, sizeof(sh)); 417 logfs_buf_write(area, ofs, &u, sizeof(u));
413 return 0; 418 return 0;
414} 419}
415 420
@@ -493,6 +498,8 @@ static void account_shadows(struct super_block *sb)
493 498
494 btree_grim_visitor64(&tree->new, (unsigned long)sb, account_shadow); 499 btree_grim_visitor64(&tree->new, (unsigned long)sb, account_shadow);
495 btree_grim_visitor64(&tree->old, (unsigned long)sb, account_shadow); 500 btree_grim_visitor64(&tree->old, (unsigned long)sb, account_shadow);
501 btree_grim_visitor32(&tree->segment_map, 0, NULL);
502 tree->no_shadowed_segments = 0;
496 503
497 if (li->li_block) { 504 if (li->li_block) {
498 /* 505 /*
@@ -606,9 +613,9 @@ static size_t __logfs_write_je(struct super_block *sb, void *buf, u16 type,
606 if (len == 0) 613 if (len == 0)
607 return logfs_write_header(super, header, 0, type); 614 return logfs_write_header(super, header, 0, type);
608 615
616 BUG_ON(len > sb->s_blocksize);
609 compr_len = logfs_compress(buf, data, len, sb->s_blocksize); 617 compr_len = logfs_compress(buf, data, len, sb->s_blocksize);
610 if (compr_len < 0 || type == JE_ANCHOR) { 618 if (compr_len < 0 || type == JE_ANCHOR) {
611 BUG_ON(len > sb->s_blocksize);
612 memcpy(data, buf, len); 619 memcpy(data, buf, len);
613 compr_len = len; 620 compr_len = len;
614 compr = COMPR_NONE; 621 compr = COMPR_NONE;
@@ -660,6 +667,7 @@ static int logfs_write_je_buf(struct super_block *sb, void *buf, u16 type,
660 if (ofs < 0) 667 if (ofs < 0)
661 return ofs; 668 return ofs;
662 logfs_buf_write(area, ofs, super->s_compressed_je, len); 669 logfs_buf_write(area, ofs, super->s_compressed_je, len);
670 BUG_ON(super->s_no_je >= MAX_JOURNAL_ENTRIES);
663 super->s_je_array[super->s_no_je++] = cpu_to_be64(ofs); 671 super->s_je_array[super->s_no_je++] = cpu_to_be64(ofs);
664 return 0; 672 return 0;
665} 673}
diff --git a/fs/logfs/logfs.h b/fs/logfs/logfs.h
index b84b0eec6024..0a3df1a0c936 100644
--- a/fs/logfs/logfs.h
+++ b/fs/logfs/logfs.h
@@ -257,10 +257,14 @@ struct logfs_shadow {
257 * struct shadow_tree 257 * struct shadow_tree
258 * @new: shadows where old_ofs==0, indexed by new_ofs 258 * @new: shadows where old_ofs==0, indexed by new_ofs
259 * @old: shadows where old_ofs!=0, indexed by old_ofs 259 * @old: shadows where old_ofs!=0, indexed by old_ofs
260 * @segment_map: bitfield of segments containing shadows
261 * @no_shadowed_segment: number of segments containing shadows
260 */ 262 */
261struct shadow_tree { 263struct shadow_tree {
262 struct btree_head64 new; 264 struct btree_head64 new;
263 struct btree_head64 old; 265 struct btree_head64 old;
266 struct btree_head32 segment_map;
267 int no_shadowed_segments;
264}; 268};
265 269
266struct object_alias_item { 270struct object_alias_item {
@@ -305,13 +309,14 @@ typedef int write_alias_t(struct super_block *sb, u64 ino, u64 bix,
305 level_t level, int child_no, __be64 val); 309 level_t level, int child_no, __be64 val);
306struct logfs_block_ops { 310struct logfs_block_ops {
307 void (*write_block)(struct logfs_block *block); 311 void (*write_block)(struct logfs_block *block);
308 gc_level_t (*block_level)(struct logfs_block *block);
309 void (*free_block)(struct super_block *sb, struct logfs_block*block); 312 void (*free_block)(struct super_block *sb, struct logfs_block*block);
310 int (*write_alias)(struct super_block *sb, 313 int (*write_alias)(struct super_block *sb,
311 struct logfs_block *block, 314 struct logfs_block *block,
312 write_alias_t *write_one_alias); 315 write_alias_t *write_one_alias);
313}; 316};
314 317
318#define MAX_JOURNAL_ENTRIES 256
319
315struct logfs_super { 320struct logfs_super {
316 struct mtd_info *s_mtd; /* underlying device */ 321 struct mtd_info *s_mtd; /* underlying device */
317 struct block_device *s_bdev; /* underlying device */ 322 struct block_device *s_bdev; /* underlying device */
@@ -378,7 +383,7 @@ struct logfs_super {
378 u32 s_journal_ec[LOGFS_JOURNAL_SEGS]; /* journal erasecounts */ 383 u32 s_journal_ec[LOGFS_JOURNAL_SEGS]; /* journal erasecounts */
379 u64 s_last_version; 384 u64 s_last_version;
380 struct logfs_area *s_journal_area; /* open journal segment */ 385 struct logfs_area *s_journal_area; /* open journal segment */
381 __be64 s_je_array[64]; 386 __be64 s_je_array[MAX_JOURNAL_ENTRIES];
382 int s_no_je; 387 int s_no_je;
383 388
384 int s_sum_index; /* for the 12 summaries */ 389 int s_sum_index; /* for the 12 summaries */
@@ -722,4 +727,10 @@ static inline struct logfs_area *get_area(struct super_block *sb,
722 return logfs_super(sb)->s_area[(__force u8)gc_level]; 727 return logfs_super(sb)->s_area[(__force u8)gc_level];
723} 728}
724 729
730static inline void logfs_mempool_destroy(mempool_t *pool)
731{
732 if (pool)
733 mempool_destroy(pool);
734}
735
725#endif 736#endif
diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c
index c3a3a6814b84..3159db6958e5 100644
--- a/fs/logfs/readwrite.c
+++ b/fs/logfs/readwrite.c
@@ -18,6 +18,7 @@
18 */ 18 */
19#include "logfs.h" 19#include "logfs.h"
20#include <linux/sched.h> 20#include <linux/sched.h>
21#include <linux/slab.h>
21 22
22static u64 adjust_bix(u64 bix, level_t level) 23static u64 adjust_bix(u64 bix, level_t level)
23{ 24{
@@ -429,25 +430,6 @@ static void inode_write_block(struct logfs_block *block)
429 } 430 }
430} 431}
431 432
432static gc_level_t inode_block_level(struct logfs_block *block)
433{
434 BUG_ON(block->inode->i_ino == LOGFS_INO_MASTER);
435 return GC_LEVEL(LOGFS_MAX_LEVELS);
436}
437
438static gc_level_t indirect_block_level(struct logfs_block *block)
439{
440 struct page *page;
441 struct inode *inode;
442 u64 bix;
443 level_t level;
444
445 page = block->page;
446 inode = page->mapping->host;
447 logfs_unpack_index(page->index, &bix, &level);
448 return expand_level(inode->i_ino, level);
449}
450
451/* 433/*
452 * This silences a false, yet annoying gcc warning. I hate it when my editor 434 * This silences a false, yet annoying gcc warning. I hate it when my editor
453 * jumps into bitops.h each time I recompile this file. 435 * jumps into bitops.h each time I recompile this file.
@@ -586,14 +568,12 @@ static void indirect_free_block(struct super_block *sb,
586 568
587static struct logfs_block_ops inode_block_ops = { 569static struct logfs_block_ops inode_block_ops = {
588 .write_block = inode_write_block, 570 .write_block = inode_write_block,
589 .block_level = inode_block_level,
590 .free_block = inode_free_block, 571 .free_block = inode_free_block,
591 .write_alias = inode_write_alias, 572 .write_alias = inode_write_alias,
592}; 573};
593 574
594struct logfs_block_ops indirect_block_ops = { 575struct logfs_block_ops indirect_block_ops = {
595 .write_block = indirect_write_block, 576 .write_block = indirect_write_block,
596 .block_level = indirect_block_level,
597 .free_block = indirect_free_block, 577 .free_block = indirect_free_block,
598 .write_alias = indirect_write_alias, 578 .write_alias = indirect_write_alias,
599}; 579};
@@ -1240,6 +1220,18 @@ static void free_shadow(struct inode *inode, struct logfs_shadow *shadow)
1240 mempool_free(shadow, super->s_shadow_pool); 1220 mempool_free(shadow, super->s_shadow_pool);
1241} 1221}
1242 1222
1223static void mark_segment(struct shadow_tree *tree, u32 segno)
1224{
1225 int err;
1226
1227 if (!btree_lookup32(&tree->segment_map, segno)) {
1228 err = btree_insert32(&tree->segment_map, segno, (void *)1,
1229 GFP_NOFS);
1230 BUG_ON(err);
1231 tree->no_shadowed_segments++;
1232 }
1233}
1234
1243/** 1235/**
1244 * fill_shadow_tree - Propagate shadow tree changes due to a write 1236 * fill_shadow_tree - Propagate shadow tree changes due to a write
1245 * @inode: Inode owning the page 1237 * @inode: Inode owning the page
@@ -1287,6 +1279,8 @@ static void fill_shadow_tree(struct inode *inode, struct page *page,
1287 1279
1288 super->s_dirty_used_bytes += shadow->new_len; 1280 super->s_dirty_used_bytes += shadow->new_len;
1289 super->s_dirty_free_bytes += shadow->old_len; 1281 super->s_dirty_free_bytes += shadow->old_len;
1282 mark_segment(tree, shadow->old_ofs >> super->s_segshift);
1283 mark_segment(tree, shadow->new_ofs >> super->s_segshift);
1290 } 1284 }
1291} 1285}
1292 1286
@@ -1844,19 +1838,37 @@ static int __logfs_truncate(struct inode *inode, u64 size)
1844 return logfs_truncate_direct(inode, size); 1838 return logfs_truncate_direct(inode, size);
1845} 1839}
1846 1840
1847int logfs_truncate(struct inode *inode, u64 size) 1841/*
1842 * Truncate, by changing the segment file, can consume a fair amount
1843 * of resources. So back off from time to time and do some GC.
1844 * 8 or 2048 blocks should be well within safety limits even if
1845 * every single block resided in a different segment.
1846 */
1847#define TRUNCATE_STEP (8 * 1024 * 1024)
1848int logfs_truncate(struct inode *inode, u64 target)
1848{ 1849{
1849 struct super_block *sb = inode->i_sb; 1850 struct super_block *sb = inode->i_sb;
1850 int err; 1851 u64 size = i_size_read(inode);
1852 int err = 0;
1851 1853
1852 logfs_get_wblocks(sb, NULL, 1); 1854 size = ALIGN(size, TRUNCATE_STEP);
1853 err = __logfs_truncate(inode, size); 1855 while (size > target) {
1854 if (!err) 1856 if (size > TRUNCATE_STEP)
1855 err = __logfs_write_inode(inode, 0); 1857 size -= TRUNCATE_STEP;
1856 logfs_put_wblocks(sb, NULL, 1); 1858 else
1859 size = 0;
1860 if (size < target)
1861 size = target;
1862
1863 logfs_get_wblocks(sb, NULL, 1);
1864 err = __logfs_truncate(inode, target);
1865 if (!err)
1866 err = __logfs_write_inode(inode, 0);
1867 logfs_put_wblocks(sb, NULL, 1);
1868 }
1857 1869
1858 if (!err) 1870 if (!err)
1859 err = vmtruncate(inode, size); 1871 err = vmtruncate(inode, target);
1860 1872
1861 /* I don't trust error recovery yet. */ 1873 /* I don't trust error recovery yet. */
1862 WARN_ON(err); 1874 WARN_ON(err);
@@ -2250,8 +2262,6 @@ void logfs_cleanup_rw(struct super_block *sb)
2250 struct logfs_super *super = logfs_super(sb); 2262 struct logfs_super *super = logfs_super(sb);
2251 2263
2252 destroy_meta_inode(super->s_segfile_inode); 2264 destroy_meta_inode(super->s_segfile_inode);
2253 if (super->s_block_pool) 2265 logfs_mempool_destroy(super->s_block_pool);
2254 mempool_destroy(super->s_block_pool); 2266 logfs_mempool_destroy(super->s_shadow_pool);
2255 if (super->s_shadow_pool)
2256 mempool_destroy(super->s_shadow_pool);
2257} 2267}
diff --git a/fs/logfs/segment.c b/fs/logfs/segment.c
index 0ecd8f07c11e..f77ce2b470ba 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{
@@ -182,14 +183,8 @@ static int btree_write_alias(struct super_block *sb, struct logfs_block *block,
182 return 0; 183 return 0;
183} 184}
184 185
185static gc_level_t btree_block_level(struct logfs_block *block)
186{
187 return expand_level(block->ino, block->level);
188}
189
190static struct logfs_block_ops btree_block_ops = { 186static struct logfs_block_ops btree_block_ops = {
191 .write_block = btree_write_block, 187 .write_block = btree_write_block,
192 .block_level = btree_block_level,
193 .free_block = __free_block, 188 .free_block = __free_block,
194 .write_alias = btree_write_alias, 189 .write_alias = btree_write_alias,
195}; 190};
@@ -918,7 +913,7 @@ err:
918 for (i--; i >= 0; i--) 913 for (i--; i >= 0; i--)
919 free_area(super->s_area[i]); 914 free_area(super->s_area[i]);
920 free_area(super->s_journal_area); 915 free_area(super->s_journal_area);
921 mempool_destroy(super->s_alias_pool); 916 logfs_mempool_destroy(super->s_alias_pool);
922 return -ENOMEM; 917 return -ENOMEM;
923} 918}
924 919
diff --git a/fs/logfs/super.c b/fs/logfs/super.c
index 9d856c49afc5..5866ee6e1327 100644
--- a/fs/logfs/super.c
+++ b/fs/logfs/super.c
@@ -11,6 +11,8 @@
11 */ 11 */
12#include "logfs.h" 12#include "logfs.h"
13#include <linux/bio.h> 13#include <linux/bio.h>
14#include <linux/slab.h>
15#include <linux/blkdev.h>
14#include <linux/mtd/mtd.h> 16#include <linux/mtd/mtd.h>
15#include <linux/statfs.h> 17#include <linux/statfs.h>
16#include <linux/buffer_head.h> 18#include <linux/buffer_head.h>
@@ -136,6 +138,10 @@ static int logfs_sb_set(struct super_block *sb, void *_super)
136 sb->s_fs_info = super; 138 sb->s_fs_info = super;
137 sb->s_mtd = super->s_mtd; 139 sb->s_mtd = super->s_mtd;
138 sb->s_bdev = super->s_bdev; 140 sb->s_bdev = super->s_bdev;
141 if (sb->s_bdev)
142 sb->s_bdi = &bdev_get_queue(sb->s_bdev)->backing_dev_info;
143 if (sb->s_mtd)
144 sb->s_bdi = sb->s_mtd->backing_dev_info;
139 return 0; 145 return 0;
140} 146}
141 147
@@ -451,6 +457,8 @@ static int logfs_read_sb(struct super_block *sb, int read_only)
451 457
452 btree_init_mempool64(&super->s_shadow_tree.new, super->s_btree_pool); 458 btree_init_mempool64(&super->s_shadow_tree.new, super->s_btree_pool);
453 btree_init_mempool64(&super->s_shadow_tree.old, super->s_btree_pool); 459 btree_init_mempool64(&super->s_shadow_tree.old, super->s_btree_pool);
460 btree_init_mempool32(&super->s_shadow_tree.segment_map,
461 super->s_btree_pool);
454 462
455 ret = logfs_init_mapping(sb); 463 ret = logfs_init_mapping(sb);
456 if (ret) 464 if (ret)
@@ -515,8 +523,8 @@ static void logfs_kill_sb(struct super_block *sb)
515 if (super->s_erase_page) 523 if (super->s_erase_page)
516 __free_page(super->s_erase_page); 524 __free_page(super->s_erase_page);
517 super->s_devops->put_device(sb); 525 super->s_devops->put_device(sb);
518 mempool_destroy(super->s_btree_pool); 526 logfs_mempool_destroy(super->s_btree_pool);
519 mempool_destroy(super->s_alias_pool); 527 logfs_mempool_destroy(super->s_alias_pool);
520 kfree(super); 528 kfree(super);
521 log_super("LogFS: Finished unmounting\n"); 529 log_super("LogFS: Finished unmounting\n");
522} 530}