aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS1
-rw-r--r--fs/logfs/dir.c2
-rw-r--r--fs/logfs/file.c2
-rw-r--r--fs/logfs/gc.c2
-rw-r--r--fs/logfs/inode.c4
-rw-r--r--fs/logfs/journal.c1
-rw-r--r--fs/logfs/logfs.h5
-rw-r--r--fs/logfs/readwrite.c51
-rw-r--r--fs/logfs/segment.c51
-rw-r--r--fs/logfs/super.c3
-rw-r--r--include/linux/mtd/mtd.h4
11 files changed, 89 insertions, 37 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 6803338dc885..a1fce9a3ab20 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4140,6 +4140,7 @@ F: fs/partitions/ldm.*
4140 4140
4141LogFS 4141LogFS
4142M: Joern Engel <joern@logfs.org> 4142M: Joern Engel <joern@logfs.org>
4143M: Prasad Joshi <prasadjoshi.linux@gmail.com>
4143L: logfs@logfs.org 4144L: logfs@logfs.org
4144W: logfs.org 4145W: logfs.org
4145S: Maintained 4146S: Maintained
diff --git a/fs/logfs/dir.c b/fs/logfs/dir.c
index 501043e8966c..3de7a32cadbe 100644
--- a/fs/logfs/dir.c
+++ b/fs/logfs/dir.c
@@ -71,7 +71,7 @@ static int write_dir(struct inode *dir, struct logfs_disk_dentry *dd,
71 71
72static int write_inode(struct inode *inode) 72static int write_inode(struct inode *inode)
73{ 73{
74 return __logfs_write_inode(inode, WF_LOCK); 74 return __logfs_write_inode(inode, NULL, WF_LOCK);
75} 75}
76 76
77static s64 dir_seek_data(struct inode *inode, s64 pos) 77static s64 dir_seek_data(struct inode *inode, s64 pos)
diff --git a/fs/logfs/file.c b/fs/logfs/file.c
index b548c87a86f1..3886cded283c 100644
--- a/fs/logfs/file.c
+++ b/fs/logfs/file.c
@@ -230,7 +230,9 @@ int logfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
230 return ret; 230 return ret;
231 231
232 mutex_lock(&inode->i_mutex); 232 mutex_lock(&inode->i_mutex);
233 logfs_get_wblocks(sb, NULL, WF_LOCK);
233 logfs_write_anchor(sb); 234 logfs_write_anchor(sb);
235 logfs_put_wblocks(sb, NULL, WF_LOCK);
234 mutex_unlock(&inode->i_mutex); 236 mutex_unlock(&inode->i_mutex);
235 237
236 return 0; 238 return 0;
diff --git a/fs/logfs/gc.c b/fs/logfs/gc.c
index caa4419285dc..d4efb061bdc5 100644
--- a/fs/logfs/gc.c
+++ b/fs/logfs/gc.c
@@ -367,7 +367,7 @@ static struct gc_candidate *get_candidate(struct super_block *sb)
367 int i, max_dist; 367 int i, max_dist;
368 struct gc_candidate *cand = NULL, *this; 368 struct gc_candidate *cand = NULL, *this;
369 369
370 max_dist = min(no_free_segments(sb), LOGFS_NO_AREAS); 370 max_dist = min(no_free_segments(sb), LOGFS_NO_AREAS - 1);
371 371
372 for (i = max_dist; i >= 0; i--) { 372 for (i = max_dist; i >= 0; i--) {
373 this = first_in_list(&super->s_low_list[i]); 373 this = first_in_list(&super->s_low_list[i]);
diff --git a/fs/logfs/inode.c b/fs/logfs/inode.c
index 388df1aa35e5..a422f42238b2 100644
--- a/fs/logfs/inode.c
+++ b/fs/logfs/inode.c
@@ -286,7 +286,7 @@ static int logfs_write_inode(struct inode *inode, struct writeback_control *wbc)
286 if (logfs_inode(inode)->li_flags & LOGFS_IF_STILLBORN) 286 if (logfs_inode(inode)->li_flags & LOGFS_IF_STILLBORN)
287 return 0; 287 return 0;
288 288
289 ret = __logfs_write_inode(inode, flags); 289 ret = __logfs_write_inode(inode, NULL, flags);
290 LOGFS_BUG_ON(ret, inode->i_sb); 290 LOGFS_BUG_ON(ret, inode->i_sb);
291 return ret; 291 return ret;
292} 292}
@@ -363,7 +363,9 @@ static void logfs_init_once(void *_li)
363 363
364static int logfs_sync_fs(struct super_block *sb, int wait) 364static int logfs_sync_fs(struct super_block *sb, int wait)
365{ 365{
366 logfs_get_wblocks(sb, NULL, WF_LOCK);
366 logfs_write_anchor(sb); 367 logfs_write_anchor(sb);
368 logfs_put_wblocks(sb, NULL, WF_LOCK);
367 return 0; 369 return 0;
368} 370}
369 371
diff --git a/fs/logfs/journal.c b/fs/logfs/journal.c
index 9da29706f91c..1e1c369df22b 100644
--- a/fs/logfs/journal.c
+++ b/fs/logfs/journal.c
@@ -612,7 +612,6 @@ static size_t __logfs_write_je(struct super_block *sb, void *buf, u16 type,
612 if (len == 0) 612 if (len == 0)
613 return logfs_write_header(super, header, 0, type); 613 return logfs_write_header(super, header, 0, type);
614 614
615 BUG_ON(len > sb->s_blocksize);
616 compr_len = logfs_compress(buf, data, len, sb->s_blocksize); 615 compr_len = logfs_compress(buf, data, len, sb->s_blocksize);
617 if (compr_len < 0 || type == JE_ANCHOR) { 616 if (compr_len < 0 || type == JE_ANCHOR) {
618 memcpy(data, buf, len); 617 memcpy(data, buf, len);
diff --git a/fs/logfs/logfs.h b/fs/logfs/logfs.h
index 926373866a55..5f0937609465 100644
--- a/fs/logfs/logfs.h
+++ b/fs/logfs/logfs.h
@@ -528,7 +528,7 @@ void logfs_destroy_inode_cache(void);
528void logfs_set_blocks(struct inode *inode, u64 no); 528void logfs_set_blocks(struct inode *inode, u64 no);
529/* these logically belong into inode.c but actually reside in readwrite.c */ 529/* these logically belong into inode.c but actually reside in readwrite.c */
530int logfs_read_inode(struct inode *inode); 530int logfs_read_inode(struct inode *inode);
531int __logfs_write_inode(struct inode *inode, long flags); 531int __logfs_write_inode(struct inode *inode, struct page *, long flags);
532void logfs_evict_inode(struct inode *inode); 532void logfs_evict_inode(struct inode *inode);
533 533
534/* journal.c */ 534/* journal.c */
@@ -577,6 +577,8 @@ void initialize_block_counters(struct page *page, struct logfs_block *block,
577 __be64 *array, int page_is_empty); 577 __be64 *array, int page_is_empty);
578int logfs_exist_block(struct inode *inode, u64 bix); 578int logfs_exist_block(struct inode *inode, u64 bix);
579int get_page_reserve(struct inode *inode, struct page *page); 579int get_page_reserve(struct inode *inode, struct page *page);
580void logfs_get_wblocks(struct super_block *sb, struct page *page, int lock);
581void logfs_put_wblocks(struct super_block *sb, struct page *page, int lock);
580extern struct logfs_block_ops indirect_block_ops; 582extern struct logfs_block_ops indirect_block_ops;
581 583
582/* segment.c */ 584/* segment.c */
@@ -594,6 +596,7 @@ int logfs_init_mapping(struct super_block *sb);
594void logfs_sync_area(struct logfs_area *area); 596void logfs_sync_area(struct logfs_area *area);
595void logfs_sync_segments(struct super_block *sb); 597void logfs_sync_segments(struct super_block *sb);
596void freeseg(struct super_block *sb, u32 segno); 598void freeseg(struct super_block *sb, u32 segno);
599void free_areas(struct super_block *sb);
597 600
598/* area handling */ 601/* area handling */
599int logfs_init_areas(struct super_block *sb); 602int logfs_init_areas(struct super_block *sb);
diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c
index 2ac4217b7901..4153e65b0148 100644
--- a/fs/logfs/readwrite.c
+++ b/fs/logfs/readwrite.c
@@ -244,8 +244,7 @@ static void preunlock_page(struct super_block *sb, struct page *page, int lock)
244 * is waiting for s_write_mutex. We annotate this fact by setting PG_pre_locked 244 * is waiting for s_write_mutex. We annotate this fact by setting PG_pre_locked
245 * in addition to PG_locked. 245 * in addition to PG_locked.
246 */ 246 */
247static void logfs_get_wblocks(struct super_block *sb, struct page *page, 247void logfs_get_wblocks(struct super_block *sb, struct page *page, int lock)
248 int lock)
249{ 248{
250 struct logfs_super *super = logfs_super(sb); 249 struct logfs_super *super = logfs_super(sb);
251 250
@@ -260,8 +259,7 @@ static void logfs_get_wblocks(struct super_block *sb, struct page *page,
260 } 259 }
261} 260}
262 261
263static void logfs_put_wblocks(struct super_block *sb, struct page *page, 262void logfs_put_wblocks(struct super_block *sb, struct page *page, int lock)
264 int lock)
265{ 263{
266 struct logfs_super *super = logfs_super(sb); 264 struct logfs_super *super = logfs_super(sb);
267 265
@@ -424,7 +422,7 @@ static void inode_write_block(struct logfs_block *block)
424 if (inode->i_ino == LOGFS_INO_MASTER) 422 if (inode->i_ino == LOGFS_INO_MASTER)
425 logfs_write_anchor(inode->i_sb); 423 logfs_write_anchor(inode->i_sb);
426 else { 424 else {
427 ret = __logfs_write_inode(inode, 0); 425 ret = __logfs_write_inode(inode, NULL, 0);
428 /* see indirect_write_block comment */ 426 /* see indirect_write_block comment */
429 BUG_ON(ret); 427 BUG_ON(ret);
430 } 428 }
@@ -560,8 +558,13 @@ static void inode_free_block(struct super_block *sb, struct logfs_block *block)
560static void indirect_free_block(struct super_block *sb, 558static void indirect_free_block(struct super_block *sb,
561 struct logfs_block *block) 559 struct logfs_block *block)
562{ 560{
563 ClearPagePrivate(block->page); 561 struct page *page = block->page;
564 block->page->private = 0; 562
563 if (PagePrivate(page)) {
564 ClearPagePrivate(page);
565 page_cache_release(page);
566 set_page_private(page, 0);
567 }
565 __free_block(sb, block); 568 __free_block(sb, block);
566} 569}
567 570
@@ -650,8 +653,11 @@ static void alloc_data_block(struct inode *inode, struct page *page)
650 logfs_unpack_index(page->index, &bix, &level); 653 logfs_unpack_index(page->index, &bix, &level);
651 block = __alloc_block(inode->i_sb, inode->i_ino, bix, level); 654 block = __alloc_block(inode->i_sb, inode->i_ino, bix, level);
652 block->page = page; 655 block->page = page;
656
653 SetPagePrivate(page); 657 SetPagePrivate(page);
654 page->private = (unsigned long)block; 658 page_cache_get(page);
659 set_page_private(page, (unsigned long) block);
660
655 block->ops = &indirect_block_ops; 661 block->ops = &indirect_block_ops;
656} 662}
657 663
@@ -1570,11 +1576,15 @@ int logfs_write_buf(struct inode *inode, struct page *page, long flags)
1570static int __logfs_delete(struct inode *inode, struct page *page) 1576static int __logfs_delete(struct inode *inode, struct page *page)
1571{ 1577{
1572 long flags = WF_DELETE; 1578 long flags = WF_DELETE;
1579 int err;
1573 1580
1574 inode->i_ctime = inode->i_mtime = CURRENT_TIME; 1581 inode->i_ctime = inode->i_mtime = CURRENT_TIME;
1575 1582
1576 if (page->index < I0_BLOCKS) 1583 if (page->index < I0_BLOCKS)
1577 return logfs_write_direct(inode, page, flags); 1584 return logfs_write_direct(inode, page, flags);
1585 err = grow_inode(inode, page->index, 0);
1586 if (err)
1587 return err;
1578 return logfs_write_rec(inode, page, page->index, 0, flags); 1588 return logfs_write_rec(inode, page, page->index, 0, flags);
1579} 1589}
1580 1590
@@ -1623,7 +1633,7 @@ int logfs_rewrite_block(struct inode *inode, u64 bix, u64 ofs,
1623 if (inode->i_ino == LOGFS_INO_MASTER) 1633 if (inode->i_ino == LOGFS_INO_MASTER)
1624 logfs_write_anchor(inode->i_sb); 1634 logfs_write_anchor(inode->i_sb);
1625 else { 1635 else {
1626 err = __logfs_write_inode(inode, flags); 1636 err = __logfs_write_inode(inode, page, flags);
1627 } 1637 }
1628 } 1638 }
1629 } 1639 }
@@ -1873,7 +1883,7 @@ int logfs_truncate(struct inode *inode, u64 target)
1873 logfs_get_wblocks(sb, NULL, 1); 1883 logfs_get_wblocks(sb, NULL, 1);
1874 err = __logfs_truncate(inode, size); 1884 err = __logfs_truncate(inode, size);
1875 if (!err) 1885 if (!err)
1876 err = __logfs_write_inode(inode, 0); 1886 err = __logfs_write_inode(inode, NULL, 0);
1877 logfs_put_wblocks(sb, NULL, 1); 1887 logfs_put_wblocks(sb, NULL, 1);
1878 } 1888 }
1879 1889
@@ -1901,8 +1911,11 @@ static void move_page_to_inode(struct inode *inode, struct page *page)
1901 li->li_block = block; 1911 li->li_block = block;
1902 1912
1903 block->page = NULL; 1913 block->page = NULL;
1904 page->private = 0; 1914 if (PagePrivate(page)) {
1905 ClearPagePrivate(page); 1915 ClearPagePrivate(page);
1916 page_cache_release(page);
1917 set_page_private(page, 0);
1918 }
1906} 1919}
1907 1920
1908static void move_inode_to_page(struct page *page, struct inode *inode) 1921static void move_inode_to_page(struct page *page, struct inode *inode)
@@ -1918,8 +1931,12 @@ static void move_inode_to_page(struct page *page, struct inode *inode)
1918 BUG_ON(PagePrivate(page)); 1931 BUG_ON(PagePrivate(page));
1919 block->ops = &indirect_block_ops; 1932 block->ops = &indirect_block_ops;
1920 block->page = page; 1933 block->page = page;
1921 page->private = (unsigned long)block; 1934
1922 SetPagePrivate(page); 1935 if (!PagePrivate(page)) {
1936 SetPagePrivate(page);
1937 page_cache_get(page);
1938 set_page_private(page, (unsigned long) block);
1939 }
1923 1940
1924 block->inode = NULL; 1941 block->inode = NULL;
1925 li->li_block = NULL; 1942 li->li_block = NULL;
@@ -2106,14 +2123,14 @@ void logfs_set_segment_unreserved(struct super_block *sb, u32 segno, u32 ec)
2106 ec_level); 2123 ec_level);
2107} 2124}
2108 2125
2109int __logfs_write_inode(struct inode *inode, long flags) 2126int __logfs_write_inode(struct inode *inode, struct page *page, long flags)
2110{ 2127{
2111 struct super_block *sb = inode->i_sb; 2128 struct super_block *sb = inode->i_sb;
2112 int ret; 2129 int ret;
2113 2130
2114 logfs_get_wblocks(sb, NULL, flags & WF_LOCK); 2131 logfs_get_wblocks(sb, page, flags & WF_LOCK);
2115 ret = do_write_inode(inode); 2132 ret = do_write_inode(inode);
2116 logfs_put_wblocks(sb, NULL, flags & WF_LOCK); 2133 logfs_put_wblocks(sb, page, flags & WF_LOCK);
2117 return ret; 2134 return ret;
2118} 2135}
2119 2136
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
865void 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
844static struct logfs_area *alloc_area(struct super_block *sb) 875static 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:
923void logfs_cleanup_areas(struct super_block *sb) 954void 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}
diff --git a/fs/logfs/super.c b/fs/logfs/super.c
index e795c234ea33..c9ee7f5d1caf 100644
--- a/fs/logfs/super.c
+++ b/fs/logfs/super.c
@@ -486,14 +486,15 @@ static void logfs_kill_sb(struct super_block *sb)
486 /* Alias entries slow down mount, so evict as many as possible */ 486 /* Alias entries slow down mount, so evict as many as possible */
487 sync_filesystem(sb); 487 sync_filesystem(sb);
488 logfs_write_anchor(sb); 488 logfs_write_anchor(sb);
489 free_areas(sb);
489 490
490 /* 491 /*
491 * From this point on alias entries are simply dropped - and any 492 * From this point on alias entries are simply dropped - and any
492 * writes to the object store are considered bugs. 493 * writes to the object store are considered bugs.
493 */ 494 */
494 super->s_flags |= LOGFS_SB_FLAG_SHUTDOWN;
495 log_super("LogFS: Now in shutdown\n"); 495 log_super("LogFS: Now in shutdown\n");
496 generic_shutdown_super(sb); 496 generic_shutdown_super(sb);
497 super->s_flags |= LOGFS_SB_FLAG_SHUTDOWN;
497 498
498 BUG_ON(super->s_dirty_used_bytes || super->s_dirty_free_bytes); 499 BUG_ON(super->s_dirty_used_bytes || super->s_dirty_free_bytes);
499 500
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 1a81fde8f333..221295208fd0 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -441,7 +441,7 @@ static inline void mtd_resume(struct mtd_info *mtd)
441static inline int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs) 441static inline int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs)
442{ 442{
443 if (!mtd->block_isbad) 443 if (!mtd->block_isbad)
444 return -EOPNOTSUPP; 444 return 0;
445 return mtd->block_isbad(mtd, ofs); 445 return mtd->block_isbad(mtd, ofs);
446} 446}
447 447
@@ -489,7 +489,7 @@ static inline int mtd_has_oob(const struct mtd_info *mtd)
489 489
490static inline int mtd_can_have_bb(const struct mtd_info *mtd) 490static inline int mtd_can_have_bb(const struct mtd_info *mtd)
491{ 491{
492 return !!mtd->block_isbad; 492 return 0;
493} 493}
494 494
495 /* Kernel-side ioctl definitions */ 495 /* Kernel-side ioctl definitions */