aboutsummaryrefslogtreecommitdiffstats
path: root/fs/logfs
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2010-04-04 22:37:28 -0400
committerTejun Heo <tj@kernel.org>2010-04-04 22:37:28 -0400
commit336f5899d287f06d8329e208fc14ce50f7ec9698 (patch)
tree9b762d450d5eb248a6ff8317badb7e223d93ed58 /fs/logfs
parenta4ab2773205e8b94c18625455f85e3b6bb9d7ad6 (diff)
parentdb217dece3003df0841bacf9556b5c06aa097dae (diff)
Merge branch 'master' into export-slabh
Diffstat (limited to 'fs/logfs')
-rw-r--r--fs/logfs/dev_bdev.c9
-rw-r--r--fs/logfs/dir.c4
-rw-r--r--fs/logfs/journal.c7
-rw-r--r--fs/logfs/logfs.h1
-rw-r--r--fs/logfs/readwrite.c13
-rw-r--r--fs/logfs/segment.c54
-rw-r--r--fs/logfs/super.c15
7 files changed, 67 insertions, 36 deletions
diff --git a/fs/logfs/dev_bdev.c b/fs/logfs/dev_bdev.c
index 18e8c144c7f1..243c00071f76 100644
--- a/fs/logfs/dev_bdev.c
+++ b/fs/logfs/dev_bdev.c
@@ -81,6 +81,7 @@ static void writeseg_end_io(struct bio *bio, int err)
81 prefetchw(&bvec->bv_page->flags); 81 prefetchw(&bvec->bv_page->flags);
82 82
83 end_page_writeback(page); 83 end_page_writeback(page);
84 page_cache_release(page);
84 } while (bvec >= bio->bi_io_vec); 85 } while (bvec >= bio->bi_io_vec);
85 bio_put(bio); 86 bio_put(bio);
86 if (atomic_dec_and_test(&super->s_pending_writes)) 87 if (atomic_dec_and_test(&super->s_pending_writes))
@@ -98,8 +99,10 @@ static int __bdev_writeseg(struct super_block *sb, u64 ofs, pgoff_t index,
98 unsigned int max_pages = queue_max_hw_sectors(q) >> (PAGE_SHIFT - 9); 99 unsigned int max_pages = queue_max_hw_sectors(q) >> (PAGE_SHIFT - 9);
99 int i; 100 int i;
100 101
102 if (max_pages > BIO_MAX_PAGES)
103 max_pages = BIO_MAX_PAGES;
101 bio = bio_alloc(GFP_NOFS, max_pages); 104 bio = bio_alloc(GFP_NOFS, max_pages);
102 BUG_ON(!bio); /* FIXME: handle this */ 105 BUG_ON(!bio);
103 106
104 for (i = 0; i < nr_pages; i++) { 107 for (i = 0; i < nr_pages; i++) {
105 if (i >= max_pages) { 108 if (i >= max_pages) {
@@ -192,8 +195,10 @@ static int do_erase(struct super_block *sb, u64 ofs, pgoff_t index,
192 unsigned int max_pages = queue_max_hw_sectors(q) >> (PAGE_SHIFT - 9); 195 unsigned int max_pages = queue_max_hw_sectors(q) >> (PAGE_SHIFT - 9);
193 int i; 196 int i;
194 197
198 if (max_pages > BIO_MAX_PAGES)
199 max_pages = BIO_MAX_PAGES;
195 bio = bio_alloc(GFP_NOFS, max_pages); 200 bio = bio_alloc(GFP_NOFS, max_pages);
196 BUG_ON(!bio); /* FIXME: handle this */ 201 BUG_ON(!bio);
197 202
198 for (i = 0; i < nr_pages; i++) { 203 for (i = 0; i < nr_pages; i++) {
199 if (i >= max_pages) { 204 if (i >= max_pages) {
diff --git a/fs/logfs/dir.c b/fs/logfs/dir.c
index e1cb99566100..2396a85c0f55 100644
--- a/fs/logfs/dir.c
+++ b/fs/logfs/dir.c
@@ -303,12 +303,12 @@ static int __logfs_readdir(struct file *file, void *buf, filldir_t filldir)
303 (filler_t *)logfs_readpage, NULL); 303 (filler_t *)logfs_readpage, NULL);
304 if (IS_ERR(page)) 304 if (IS_ERR(page))
305 return PTR_ERR(page); 305 return PTR_ERR(page);
306 dd = kmap_atomic(page, KM_USER0); 306 dd = kmap(page);
307 BUG_ON(dd->namelen == 0); 307 BUG_ON(dd->namelen == 0);
308 308
309 full = filldir(buf, (char *)dd->name, be16_to_cpu(dd->namelen), 309 full = filldir(buf, (char *)dd->name, be16_to_cpu(dd->namelen),
310 pos, be64_to_cpu(dd->ino), dd->type); 310 pos, be64_to_cpu(dd->ino), dd->type);
311 kunmap_atomic(dd, KM_USER0); 311 kunmap(page);
312 page_cache_release(page); 312 page_cache_release(page);
313 if (full) 313 if (full)
314 break; 314 break;
diff --git a/fs/logfs/journal.c b/fs/logfs/journal.c
index f186043e862a..33bd260b8309 100644
--- a/fs/logfs/journal.c
+++ b/fs/logfs/journal.c
@@ -801,6 +801,7 @@ void do_logfs_journal_wl_pass(struct super_block *sb)
801{ 801{
802 struct logfs_super *super = logfs_super(sb); 802 struct logfs_super *super = logfs_super(sb);
803 struct logfs_area *area = super->s_journal_area; 803 struct logfs_area *area = super->s_journal_area;
804 struct btree_head32 *head = &super->s_reserved_segments;
804 u32 segno, ec; 805 u32 segno, ec;
805 int i, err; 806 int i, err;
806 807
@@ -808,6 +809,7 @@ void do_logfs_journal_wl_pass(struct super_block *sb)
808 /* Drop old segments */ 809 /* Drop old segments */
809 journal_for_each(i) 810 journal_for_each(i)
810 if (super->s_journal_seg[i]) { 811 if (super->s_journal_seg[i]) {
812 btree_remove32(head, super->s_journal_seg[i]);
811 logfs_set_segment_unreserved(sb, 813 logfs_set_segment_unreserved(sb,
812 super->s_journal_seg[i], 814 super->s_journal_seg[i],
813 super->s_journal_ec[i]); 815 super->s_journal_ec[i]);
@@ -820,8 +822,13 @@ void do_logfs_journal_wl_pass(struct super_block *sb)
820 super->s_journal_seg[i] = segno; 822 super->s_journal_seg[i] = segno;
821 super->s_journal_ec[i] = ec; 823 super->s_journal_ec[i] = ec;
822 logfs_set_segment_reserved(sb, segno); 824 logfs_set_segment_reserved(sb, segno);
825 err = btree_insert32(head, segno, (void *)1, GFP_KERNEL);
826 BUG_ON(err); /* mempool should prevent this */
827 err = logfs_erase_segment(sb, segno, 1);
828 BUG_ON(err); /* FIXME: remount-ro would be nicer */
823 } 829 }
824 /* Manually move journal_area */ 830 /* Manually move journal_area */
831 freeseg(sb, area->a_segno);
825 area->a_segno = super->s_journal_seg[0]; 832 area->a_segno = super->s_journal_seg[0];
826 area->a_is_open = 0; 833 area->a_is_open = 0;
827 area->a_used_bytes = 0; 834 area->a_used_bytes = 0;
diff --git a/fs/logfs/logfs.h b/fs/logfs/logfs.h
index 129779431373..b84b0eec6024 100644
--- a/fs/logfs/logfs.h
+++ b/fs/logfs/logfs.h
@@ -587,6 +587,7 @@ void move_page_to_btree(struct page *page);
587int logfs_init_mapping(struct super_block *sb); 587int logfs_init_mapping(struct super_block *sb);
588void logfs_sync_area(struct logfs_area *area); 588void logfs_sync_area(struct logfs_area *area);
589void logfs_sync_segments(struct super_block *sb); 589void logfs_sync_segments(struct super_block *sb);
590void freeseg(struct super_block *sb, u32 segno);
590 591
591/* area handling */ 592/* area handling */
592int logfs_init_areas(struct super_block *sb); 593int logfs_init_areas(struct super_block *sb);
diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c
index d5919af2c7a7..bff40253dfb2 100644
--- a/fs/logfs/readwrite.c
+++ b/fs/logfs/readwrite.c
@@ -1595,7 +1595,6 @@ int logfs_delete(struct inode *inode, pgoff_t index,
1595 return ret; 1595 return ret;
1596} 1596}
1597 1597
1598/* Rewrite cannot mark the inode dirty but has to write it immediatly. */
1599int logfs_rewrite_block(struct inode *inode, u64 bix, u64 ofs, 1598int logfs_rewrite_block(struct inode *inode, u64 bix, u64 ofs,
1600 gc_level_t gc_level, long flags) 1599 gc_level_t gc_level, long flags)
1601{ 1600{
@@ -1612,6 +1611,18 @@ int logfs_rewrite_block(struct inode *inode, u64 bix, u64 ofs,
1612 if (level != 0) 1611 if (level != 0)
1613 alloc_indirect_block(inode, page, 0); 1612 alloc_indirect_block(inode, page, 0);
1614 err = logfs_write_buf(inode, page, flags); 1613 err = logfs_write_buf(inode, page, flags);
1614 if (!err && shrink_level(gc_level) == 0) {
1615 /* Rewrite cannot mark the inode dirty but has to
1616 * write it immediatly.
1617 * Q: Can't we just create an alias for the inode
1618 * instead? And if not, why not?
1619 */
1620 if (inode->i_ino == LOGFS_INO_MASTER)
1621 logfs_write_anchor(inode->i_sb);
1622 else {
1623 err = __logfs_write_inode(inode, flags);
1624 }
1625 }
1615 } 1626 }
1616 logfs_put_write_page(page); 1627 logfs_put_write_page(page);
1617 return err; 1628 return err;
diff --git a/fs/logfs/segment.c b/fs/logfs/segment.c
index 614d7a6fda2d..801a3a141625 100644
--- a/fs/logfs/segment.c
+++ b/fs/logfs/segment.c
@@ -94,50 +94,58 @@ void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len,
94 } while (len); 94 } while (len);
95} 95}
96 96
97/* 97static void pad_partial_page(struct logfs_area *area)
98 * bdev_writeseg will write full pages. Memset the tail to prevent data leaks.
99 */
100static void pad_wbuf(struct logfs_area *area, int final)
101{ 98{
102 struct super_block *sb = area->a_sb; 99 struct super_block *sb = area->a_sb;
103 struct logfs_super *super = logfs_super(sb);
104 struct page *page; 100 struct page *page;
105 u64 ofs = dev_ofs(sb, area->a_segno, area->a_used_bytes); 101 u64 ofs = dev_ofs(sb, area->a_segno, area->a_used_bytes);
106 pgoff_t index = ofs >> PAGE_SHIFT; 102 pgoff_t index = ofs >> PAGE_SHIFT;
107 long offset = ofs & (PAGE_SIZE-1); 103 long offset = ofs & (PAGE_SIZE-1);
108 u32 len = PAGE_SIZE - offset; 104 u32 len = PAGE_SIZE - offset;
109 105
110 if (len == PAGE_SIZE) { 106 if (len % PAGE_SIZE) {
111 /* The math in this function can surely use some love */ 107 page = get_mapping_page(sb, index, 0);
112 len = 0;
113 }
114 if (len) {
115 BUG_ON(area->a_used_bytes >= super->s_segsize);
116
117 page = get_mapping_page(area->a_sb, index, 0);
118 BUG_ON(!page); /* FIXME: reserve a pool */ 108 BUG_ON(!page); /* FIXME: reserve a pool */
119 memset(page_address(page) + offset, 0xff, len); 109 memset(page_address(page) + offset, 0xff, len);
120 SetPagePrivate(page); 110 SetPagePrivate(page);
121 page_cache_release(page); 111 page_cache_release(page);
122 } 112 }
113}
123 114
124 if (!final) 115static void pad_full_pages(struct logfs_area *area)
125 return; 116{
117 struct super_block *sb = area->a_sb;
118 struct logfs_super *super = logfs_super(sb);
119 u64 ofs = dev_ofs(sb, area->a_segno, area->a_used_bytes);
120 u32 len = super->s_segsize - area->a_used_bytes;
121 pgoff_t index = PAGE_CACHE_ALIGN(ofs) >> PAGE_CACHE_SHIFT;
122 pgoff_t no_indizes = len >> PAGE_CACHE_SHIFT;
123 struct page *page;
126 124
127 area->a_used_bytes += len; 125 while (no_indizes) {
128 for ( ; area->a_used_bytes < super->s_segsize; 126 page = get_mapping_page(sb, index, 0);
129 area->a_used_bytes += PAGE_SIZE) {
130 /* Memset another page */
131 index++;
132 page = get_mapping_page(area->a_sb, index, 0);
133 BUG_ON(!page); /* FIXME: reserve a pool */ 127 BUG_ON(!page); /* FIXME: reserve a pool */
134 memset(page_address(page), 0xff, PAGE_SIZE); 128 SetPageUptodate(page);
129 memset(page_address(page), 0xff, PAGE_CACHE_SIZE);
135 SetPagePrivate(page); 130 SetPagePrivate(page);
136 page_cache_release(page); 131 page_cache_release(page);
132 index++;
133 no_indizes--;
137 } 134 }
138} 135}
139 136
140/* 137/*
138 * bdev_writeseg will write full pages. Memset the tail to prevent data leaks.
139 * Also make sure we allocate (and memset) all pages for final writeout.
140 */
141static void pad_wbuf(struct logfs_area *area, int final)
142{
143 pad_partial_page(area);
144 if (final)
145 pad_full_pages(area);
146}
147
148/*
141 * We have to be careful with the alias tree. Since lookup is done by bix, 149 * We have to be careful with the alias tree. Since lookup is done by bix,
142 * it needs to be normalized, so 14, 15, 16, etc. all match when dealing with 150 * it needs to be normalized, so 14, 15, 16, etc. all match when dealing with
143 * indirect blocks. So always use it through accessor functions. 151 * indirect blocks. So always use it through accessor functions.
@@ -684,7 +692,7 @@ int logfs_segment_delete(struct inode *inode, struct logfs_shadow *shadow)
684 return 0; 692 return 0;
685} 693}
686 694
687static void freeseg(struct super_block *sb, u32 segno) 695void freeseg(struct super_block *sb, u32 segno)
688{ 696{
689 struct logfs_super *super = logfs_super(sb); 697 struct logfs_super *super = logfs_super(sb);
690 struct address_space *mapping = super->s_mapping_inode->i_mapping; 698 struct address_space *mapping = super->s_mapping_inode->i_mapping;
diff --git a/fs/logfs/super.c b/fs/logfs/super.c
index 46990eafe052..b60bfac3263c 100644
--- a/fs/logfs/super.c
+++ b/fs/logfs/super.c
@@ -278,7 +278,7 @@ static int logfs_recover_sb(struct super_block *sb)
278 } 278 }
279 if (valid0 && valid1 && ds_cmp(ds0, ds1)) { 279 if (valid0 && valid1 && ds_cmp(ds0, ds1)) {
280 printk(KERN_INFO"Superblocks don't match - fixing.\n"); 280 printk(KERN_INFO"Superblocks don't match - fixing.\n");
281 return write_one_sb(sb, super->s_devops->find_last_sb); 281 return logfs_write_sb(sb);
282 } 282 }
283 /* If neither is valid now, something's wrong. Didn't we properly 283 /* If neither is valid now, something's wrong. Didn't we properly
284 * check them before?!? */ 284 * check them before?!? */
@@ -290,6 +290,10 @@ static int logfs_make_writeable(struct super_block *sb)
290{ 290{
291 int err; 291 int err;
292 292
293 err = logfs_open_segfile(sb);
294 if (err)
295 return err;
296
293 /* Repair any broken superblock copies */ 297 /* Repair any broken superblock copies */
294 err = logfs_recover_sb(sb); 298 err = logfs_recover_sb(sb);
295 if (err) 299 if (err)
@@ -300,10 +304,6 @@ static int logfs_make_writeable(struct super_block *sb)
300 if (err) 304 if (err)
301 return err; 305 return err;
302 306
303 err = logfs_open_segfile(sb);
304 if (err)
305 return err;
306
307 /* Do one GC pass before any data gets dirtied */ 307 /* Do one GC pass before any data gets dirtied */
308 logfs_gc_pass(sb); 308 logfs_gc_pass(sb);
309 309
@@ -329,7 +329,7 @@ static int logfs_get_sb_final(struct super_block *sb, struct vfsmount *mnt)
329 329
330 sb->s_root = d_alloc_root(rootdir); 330 sb->s_root = d_alloc_root(rootdir);
331 if (!sb->s_root) 331 if (!sb->s_root)
332 goto fail; 332 goto fail2;
333 333
334 super->s_erase_page = alloc_pages(GFP_KERNEL, 0); 334 super->s_erase_page = alloc_pages(GFP_KERNEL, 0);
335 if (!super->s_erase_page) 335 if (!super->s_erase_page)
@@ -573,8 +573,7 @@ int logfs_get_sb_device(struct file_system_type *type, int flags,
573 return 0; 573 return 0;
574 574
575err1: 575err1:
576 up_write(&sb->s_umount); 576 deactivate_locked_super(sb);
577 deactivate_super(sb);
578 return err; 577 return err;
579err0: 578err0:
580 kfree(super); 579 kfree(super);