Merge branch 'master' into export-slabh

This commit is contained in:
Tejun Heo 2010-04-05 11:37:28 +09:00
commit 336f5899d2
183 changed files with 4561 additions and 2618 deletions

View file

@ -81,6 +81,7 @@ static void writeseg_end_io(struct bio *bio, int err)
prefetchw(&bvec->bv_page->flags);
end_page_writeback(page);
page_cache_release(page);
} while (bvec >= bio->bi_io_vec);
bio_put(bio);
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,
unsigned int max_pages = queue_max_hw_sectors(q) >> (PAGE_SHIFT - 9);
int i;
if (max_pages > BIO_MAX_PAGES)
max_pages = BIO_MAX_PAGES;
bio = bio_alloc(GFP_NOFS, max_pages);
BUG_ON(!bio); /* FIXME: handle this */
BUG_ON(!bio);
for (i = 0; i < nr_pages; i++) {
if (i >= max_pages) {
@ -192,8 +195,10 @@ static int do_erase(struct super_block *sb, u64 ofs, pgoff_t index,
unsigned int max_pages = queue_max_hw_sectors(q) >> (PAGE_SHIFT - 9);
int i;
if (max_pages > BIO_MAX_PAGES)
max_pages = BIO_MAX_PAGES;
bio = bio_alloc(GFP_NOFS, max_pages);
BUG_ON(!bio); /* FIXME: handle this */
BUG_ON(!bio);
for (i = 0; i < nr_pages; i++) {
if (i >= max_pages) {

View file

@ -303,12 +303,12 @@ static int __logfs_readdir(struct file *file, void *buf, filldir_t filldir)
(filler_t *)logfs_readpage, NULL);
if (IS_ERR(page))
return PTR_ERR(page);
dd = kmap_atomic(page, KM_USER0);
dd = kmap(page);
BUG_ON(dd->namelen == 0);
full = filldir(buf, (char *)dd->name, be16_to_cpu(dd->namelen),
pos, be64_to_cpu(dd->ino), dd->type);
kunmap_atomic(dd, KM_USER0);
kunmap(page);
page_cache_release(page);
if (full)
break;

View file

@ -801,6 +801,7 @@ void do_logfs_journal_wl_pass(struct super_block *sb)
{
struct logfs_super *super = logfs_super(sb);
struct logfs_area *area = super->s_journal_area;
struct btree_head32 *head = &super->s_reserved_segments;
u32 segno, ec;
int i, err;
@ -808,6 +809,7 @@ void do_logfs_journal_wl_pass(struct super_block *sb)
/* Drop old segments */
journal_for_each(i)
if (super->s_journal_seg[i]) {
btree_remove32(head, super->s_journal_seg[i]);
logfs_set_segment_unreserved(sb,
super->s_journal_seg[i],
super->s_journal_ec[i]);
@ -820,8 +822,13 @@ void do_logfs_journal_wl_pass(struct super_block *sb)
super->s_journal_seg[i] = segno;
super->s_journal_ec[i] = ec;
logfs_set_segment_reserved(sb, segno);
err = btree_insert32(head, segno, (void *)1, GFP_KERNEL);
BUG_ON(err); /* mempool should prevent this */
err = logfs_erase_segment(sb, segno, 1);
BUG_ON(err); /* FIXME: remount-ro would be nicer */
}
/* Manually move journal_area */
freeseg(sb, area->a_segno);
area->a_segno = super->s_journal_seg[0];
area->a_is_open = 0;
area->a_used_bytes = 0;

View file

@ -587,6 +587,7 @@ void move_page_to_btree(struct page *page);
int logfs_init_mapping(struct super_block *sb);
void logfs_sync_area(struct logfs_area *area);
void logfs_sync_segments(struct super_block *sb);
void freeseg(struct super_block *sb, u32 segno);
/* area handling */
int logfs_init_areas(struct super_block *sb);

View file

@ -1595,7 +1595,6 @@ int logfs_delete(struct inode *inode, pgoff_t index,
return ret;
}
/* Rewrite cannot mark the inode dirty but has to write it immediatly. */
int logfs_rewrite_block(struct inode *inode, u64 bix, u64 ofs,
gc_level_t gc_level, long flags)
{
@ -1612,6 +1611,18 @@ int logfs_rewrite_block(struct inode *inode, u64 bix, u64 ofs,
if (level != 0)
alloc_indirect_block(inode, page, 0);
err = logfs_write_buf(inode, page, flags);
if (!err && shrink_level(gc_level) == 0) {
/* Rewrite cannot mark the inode dirty but has to
* write it immediatly.
* Q: Can't we just create an alias for the inode
* instead? And if not, why not?
*/
if (inode->i_ino == LOGFS_INO_MASTER)
logfs_write_anchor(inode->i_sb);
else {
err = __logfs_write_inode(inode, flags);
}
}
}
logfs_put_write_page(page);
return err;

View file

@ -94,49 +94,57 @@ void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len,
} while (len);
}
/*
* bdev_writeseg will write full pages. Memset the tail to prevent data leaks.
*/
static void pad_wbuf(struct logfs_area *area, int final)
static void pad_partial_page(struct logfs_area *area)
{
struct super_block *sb = area->a_sb;
struct logfs_super *super = logfs_super(sb);
struct page *page;
u64 ofs = dev_ofs(sb, area->a_segno, area->a_used_bytes);
pgoff_t index = ofs >> PAGE_SHIFT;
long offset = ofs & (PAGE_SIZE-1);
u32 len = PAGE_SIZE - offset;
if (len == PAGE_SIZE) {
/* The math in this function can surely use some love */
len = 0;
}
if (len) {
BUG_ON(area->a_used_bytes >= super->s_segsize);
page = get_mapping_page(area->a_sb, index, 0);
if (len % PAGE_SIZE) {
page = get_mapping_page(sb, index, 0);
BUG_ON(!page); /* FIXME: reserve a pool */
memset(page_address(page) + offset, 0xff, len);
SetPagePrivate(page);
page_cache_release(page);
}
}
if (!final)
return;
static void pad_full_pages(struct logfs_area *area)
{
struct super_block *sb = area->a_sb;
struct logfs_super *super = logfs_super(sb);
u64 ofs = dev_ofs(sb, area->a_segno, area->a_used_bytes);
u32 len = super->s_segsize - area->a_used_bytes;
pgoff_t index = PAGE_CACHE_ALIGN(ofs) >> PAGE_CACHE_SHIFT;
pgoff_t no_indizes = len >> PAGE_CACHE_SHIFT;
struct page *page;
area->a_used_bytes += len;
for ( ; area->a_used_bytes < super->s_segsize;
area->a_used_bytes += PAGE_SIZE) {
/* Memset another page */
index++;
page = get_mapping_page(area->a_sb, index, 0);
while (no_indizes) {
page = get_mapping_page(sb, index, 0);
BUG_ON(!page); /* FIXME: reserve a pool */
memset(page_address(page), 0xff, PAGE_SIZE);
SetPageUptodate(page);
memset(page_address(page), 0xff, PAGE_CACHE_SIZE);
SetPagePrivate(page);
page_cache_release(page);
index++;
no_indizes--;
}
}
/*
* bdev_writeseg will write full pages. Memset the tail to prevent data leaks.
* Also make sure we allocate (and memset) all pages for final writeout.
*/
static void pad_wbuf(struct logfs_area *area, int final)
{
pad_partial_page(area);
if (final)
pad_full_pages(area);
}
/*
* We have to be careful with the alias tree. Since lookup is done by bix,
* it needs to be normalized, so 14, 15, 16, etc. all match when dealing with
@ -684,7 +692,7 @@ int logfs_segment_delete(struct inode *inode, struct logfs_shadow *shadow)
return 0;
}
static void freeseg(struct super_block *sb, u32 segno)
void freeseg(struct super_block *sb, u32 segno)
{
struct logfs_super *super = logfs_super(sb);
struct address_space *mapping = super->s_mapping_inode->i_mapping;

View file

@ -278,7 +278,7 @@ static int logfs_recover_sb(struct super_block *sb)
}
if (valid0 && valid1 && ds_cmp(ds0, ds1)) {
printk(KERN_INFO"Superblocks don't match - fixing.\n");
return write_one_sb(sb, super->s_devops->find_last_sb);
return logfs_write_sb(sb);
}
/* If neither is valid now, something's wrong. Didn't we properly
* check them before?!? */
@ -290,6 +290,10 @@ static int logfs_make_writeable(struct super_block *sb)
{
int err;
err = logfs_open_segfile(sb);
if (err)
return err;
/* Repair any broken superblock copies */
err = logfs_recover_sb(sb);
if (err)
@ -300,10 +304,6 @@ static int logfs_make_writeable(struct super_block *sb)
if (err)
return err;
err = logfs_open_segfile(sb);
if (err)
return err;
/* Do one GC pass before any data gets dirtied */
logfs_gc_pass(sb);
@ -329,7 +329,7 @@ static int logfs_get_sb_final(struct super_block *sb, struct vfsmount *mnt)
sb->s_root = d_alloc_root(rootdir);
if (!sb->s_root)
goto fail;
goto fail2;
super->s_erase_page = alloc_pages(GFP_KERNEL, 0);
if (!super->s_erase_page)
@ -573,8 +573,7 @@ int logfs_get_sb_device(struct file_system_type *type, int flags,
return 0;
err1:
up_write(&sb->s_umount);
deactivate_super(sb);
deactivate_locked_super(sb);
return err;
err0:
kfree(super);