Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 189251
b: refs/heads/master
c: 246750f
h: refs/heads/master
i:
  189249: cf01c02
  189247: 7cc78d4
v: v3
  • Loading branch information
Linus Torvalds committed Mar 30, 2010
1 parent e8acdac commit 27ce565
Show file tree
Hide file tree
Showing 14 changed files with 112 additions and 50 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 570b8fb505896e007fd3bb07573ba6640e51851d
refs/heads/master: 246750ffa1b26335df4e485b4e4d28d83756ac43
4 changes: 3 additions & 1 deletion trunk/arch/x86/kernel/head32.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <linux/init.h>
#include <linux/start_kernel.h>
#include <linux/mm.h>

#include <asm/setup.h>
#include <asm/sections.h>
Expand Down Expand Up @@ -44,9 +45,10 @@ void __init i386_start_kernel(void)
#ifdef CONFIG_BLK_DEV_INITRD
/* Reserve INITRD */
if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) {
/* Assume only end is not page aligned */
u64 ramdisk_image = boot_params.hdr.ramdisk_image;
u64 ramdisk_size = boot_params.hdr.ramdisk_size;
u64 ramdisk_end = ramdisk_image + ramdisk_size;
u64 ramdisk_end = PAGE_ALIGN(ramdisk_image + ramdisk_size);
reserve_early(ramdisk_image, ramdisk_end, "RAMDISK");
}
#endif
Expand Down
3 changes: 2 additions & 1 deletion trunk/arch/x86/kernel/head64.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,10 @@ void __init x86_64_start_reservations(char *real_mode_data)
#ifdef CONFIG_BLK_DEV_INITRD
/* Reserve INITRD */
if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) {
/* Assume only end is not page aligned */
unsigned long ramdisk_image = boot_params.hdr.ramdisk_image;
unsigned long ramdisk_size = boot_params.hdr.ramdisk_size;
unsigned long ramdisk_end = ramdisk_image + ramdisk_size;
unsigned long ramdisk_end = PAGE_ALIGN(ramdisk_image + ramdisk_size);
reserve_early(ramdisk_image, ramdisk_end, "RAMDISK");
}
#endif
Expand Down
10 changes: 6 additions & 4 deletions trunk/arch/x86/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -314,16 +314,17 @@ static void __init reserve_brk(void)
#define MAX_MAP_CHUNK (NR_FIX_BTMAPS << PAGE_SHIFT)
static void __init relocate_initrd(void)
{

/* Assume only end is not page aligned */
u64 ramdisk_image = boot_params.hdr.ramdisk_image;
u64 ramdisk_size = boot_params.hdr.ramdisk_size;
u64 area_size = PAGE_ALIGN(ramdisk_size);
u64 end_of_lowmem = max_low_pfn_mapped << PAGE_SHIFT;
u64 ramdisk_here;
unsigned long slop, clen, mapaddr;
char *p, *q;

/* We need to move the initrd down into lowmem */
ramdisk_here = find_e820_area(0, end_of_lowmem, ramdisk_size,
ramdisk_here = find_e820_area(0, end_of_lowmem, area_size,
PAGE_SIZE);

if (ramdisk_here == -1ULL)
Expand All @@ -332,7 +333,7 @@ static void __init relocate_initrd(void)

/* Note: this includes all the lowmem currently occupied by
the initrd, we rely on that fact to keep the data intact. */
reserve_early(ramdisk_here, ramdisk_here + ramdisk_size,
reserve_early(ramdisk_here, ramdisk_here + area_size,
"NEW RAMDISK");
initrd_start = ramdisk_here + PAGE_OFFSET;
initrd_end = initrd_start + ramdisk_size;
Expand Down Expand Up @@ -376,9 +377,10 @@ static void __init relocate_initrd(void)

static void __init reserve_initrd(void)
{
/* Assume only end is not page aligned */
u64 ramdisk_image = boot_params.hdr.ramdisk_image;
u64 ramdisk_size = boot_params.hdr.ramdisk_size;
u64 ramdisk_end = ramdisk_image + ramdisk_size;
u64 ramdisk_end = PAGE_ALIGN(ramdisk_image + ramdisk_size);
u64 end_of_lowmem = max_low_pfn_mapped << PAGE_SHIFT;

if (!boot_params.hdr.type_of_loader ||
Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/x86/kernel/vmlinux.lds.S
Original file line number Diff line number Diff line change
Expand Up @@ -291,8 +291,8 @@ SECTIONS
.smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) {
__smp_locks = .;
*(.smp_locks)
__smp_locks_end = .;
. = ALIGN(PAGE_SIZE);
__smp_locks_end = .;
}

#ifdef CONFIG_X86_64
Expand Down
32 changes: 26 additions & 6 deletions trunk/arch/x86/mm/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -331,19 +331,31 @@ int devmem_is_allowed(unsigned long pagenr)

void free_init_pages(char *what, unsigned long begin, unsigned long end)
{
unsigned long addr = begin;
unsigned long addr;
unsigned long begin_aligned, end_aligned;

if (addr >= end)
/* Make sure boundaries are page aligned */
begin_aligned = PAGE_ALIGN(begin);
end_aligned = end & PAGE_MASK;

if (WARN_ON(begin_aligned != begin || end_aligned != end)) {
begin = begin_aligned;
end = end_aligned;
}

if (begin >= end)
return;

addr = begin;

/*
* If debugging page accesses then do not free this memory but
* mark them not present - any buggy init-section access will
* create a kernel page fault:
*/
#ifdef CONFIG_DEBUG_PAGEALLOC
printk(KERN_INFO "debug: unmapping init memory %08lx..%08lx\n",
begin, PAGE_ALIGN(end));
begin, end);
set_memory_np(begin, (end - begin) >> PAGE_SHIFT);
#else
/*
Expand All @@ -358,8 +370,7 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end)
for (; addr < end; addr += PAGE_SIZE) {
ClearPageReserved(virt_to_page(addr));
init_page_count(virt_to_page(addr));
memset((void *)(addr & ~(PAGE_SIZE-1)),
POISON_FREE_INITMEM, PAGE_SIZE);
memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE);
free_page(addr);
totalram_pages++;
}
Expand All @@ -376,6 +387,15 @@ void free_initmem(void)
#ifdef CONFIG_BLK_DEV_INITRD
void free_initrd_mem(unsigned long start, unsigned long end)
{
free_init_pages("initrd memory", start, end);
/*
* end could be not aligned, and We can not align that,
* decompresser could be confused by aligned initrd_end
* We already reserve the end partial page before in
* - i386_start_kernel()
* - x86_64_start_kernel()
* - relocate_initrd()
* So here We can do PAGE_ALIGN() safely to get partial page to be freed
*/
free_init_pages("initrd memory", start, PAGE_ALIGN(end));
}
#endif
9 changes: 7 additions & 2 deletions trunk/fs/logfs/dev_bdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,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))
Expand All @@ -97,8 +98,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) {
Expand Down Expand Up @@ -191,8 +194,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) {
Expand Down
4 changes: 2 additions & 2 deletions trunk/fs/logfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
7 changes: 7 additions & 0 deletions trunk/fs/logfs/journal.c
Original file line number Diff line number Diff line change
Expand Up @@ -800,13 +800,15 @@ 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;

log_journal("Journal requires wear-leveling.\n");
/* 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]);
Expand All @@ -819,8 +821,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;
Expand Down
1 change: 1 addition & 0 deletions trunk/fs/logfs/logfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
13 changes: 12 additions & 1 deletion trunk/fs/logfs/readwrite.c
Original file line number Diff line number Diff line change
Expand Up @@ -1594,7 +1594,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)
{
Expand All @@ -1611,6 +1610,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;
Expand Down
54 changes: 31 additions & 23 deletions trunk/fs/logfs/segment.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,49 +93,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
Expand Down Expand Up @@ -683,7 +691,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;
Expand Down
15 changes: 7 additions & 8 deletions trunk/fs/logfs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,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?!? */
Expand All @@ -289,6 +289,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)
Expand All @@ -299,10 +303,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);

Expand All @@ -328,7 +328,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)
Expand Down Expand Up @@ -572,8 +572,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);
Expand Down
Loading

0 comments on commit 27ce565

Please sign in to comment.