From e8acdac6f817e619bbe91f5acadb01501964272e Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Tue, 30 Mar 2010 00:04:00 +0100 Subject: [PATCH] --- yaml --- r: 189250 b: refs/heads/master c: 570b8fb505896e007fd3bb07573ba6640e51851d h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/arch/x86/kernel/head32.c | 4 +-- trunk/arch/x86/kernel/head64.c | 3 +- trunk/arch/x86/kernel/setup.c | 10 +++--- trunk/arch/x86/kernel/vmlinux.lds.S | 2 +- trunk/arch/x86/mm/init.c | 32 ++++------------- trunk/fs/logfs/dev_bdev.c | 9 ++--- trunk/fs/logfs/dir.c | 4 +-- trunk/fs/logfs/journal.c | 7 ---- trunk/fs/logfs/logfs.h | 1 - trunk/fs/logfs/readwrite.c | 13 +------ trunk/fs/logfs/segment.c | 54 ++++++++++++----------------- trunk/fs/logfs/super.c | 15 ++++---- trunk/kernel/cred.c | 6 +++- trunk/kernel/early_res.c | 6 ---- 15 files changed, 55 insertions(+), 113 deletions(-) diff --git a/[refs] b/[refs] index fdfe3e118daa..400fa9e0219d 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 4660d3d240ac6c92cd3ad33657ca302026bdc24b +refs/heads/master: 570b8fb505896e007fd3bb07573ba6640e51851d diff --git a/trunk/arch/x86/kernel/head32.c b/trunk/arch/x86/kernel/head32.c index b2e246037392..adedeef1dedc 100644 --- a/trunk/arch/x86/kernel/head32.c +++ b/trunk/arch/x86/kernel/head32.c @@ -7,7 +7,6 @@ #include #include -#include #include #include @@ -45,10 +44,9 @@ 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 = PAGE_ALIGN(ramdisk_image + ramdisk_size); + u64 ramdisk_end = ramdisk_image + ramdisk_size; reserve_early(ramdisk_image, ramdisk_end, "RAMDISK"); } #endif diff --git a/trunk/arch/x86/kernel/head64.c b/trunk/arch/x86/kernel/head64.c index 7147143fd614..b5a9896ca1e7 100644 --- a/trunk/arch/x86/kernel/head64.c +++ b/trunk/arch/x86/kernel/head64.c @@ -103,10 +103,9 @@ 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 = PAGE_ALIGN(ramdisk_image + ramdisk_size); + unsigned long ramdisk_end = ramdisk_image + ramdisk_size; reserve_early(ramdisk_image, ramdisk_end, "RAMDISK"); } #endif diff --git a/trunk/arch/x86/kernel/setup.c b/trunk/arch/x86/kernel/setup.c index d76e18570c60..5d7ba1a449bd 100644 --- a/trunk/arch/x86/kernel/setup.c +++ b/trunk/arch/x86/kernel/setup.c @@ -314,17 +314,16 @@ 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, area_size, + ramdisk_here = find_e820_area(0, end_of_lowmem, ramdisk_size, PAGE_SIZE); if (ramdisk_here == -1ULL) @@ -333,7 +332,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 + area_size, + reserve_early(ramdisk_here, ramdisk_here + ramdisk_size, "NEW RAMDISK"); initrd_start = ramdisk_here + PAGE_OFFSET; initrd_end = initrd_start + ramdisk_size; @@ -377,10 +376,9 @@ 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 = PAGE_ALIGN(ramdisk_image + ramdisk_size); + u64 ramdisk_end = ramdisk_image + ramdisk_size; u64 end_of_lowmem = max_low_pfn_mapped << PAGE_SHIFT; if (!boot_params.hdr.type_of_loader || diff --git a/trunk/arch/x86/kernel/vmlinux.lds.S b/trunk/arch/x86/kernel/vmlinux.lds.S index 2cc249718c46..44879df55696 100644 --- a/trunk/arch/x86/kernel/vmlinux.lds.S +++ b/trunk/arch/x86/kernel/vmlinux.lds.S @@ -291,8 +291,8 @@ SECTIONS .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) { __smp_locks = .; *(.smp_locks) - . = ALIGN(PAGE_SIZE); __smp_locks_end = .; + . = ALIGN(PAGE_SIZE); } #ifdef CONFIG_X86_64 diff --git a/trunk/arch/x86/mm/init.c b/trunk/arch/x86/mm/init.c index 452ee5b8f309..e71c5cbc8f35 100644 --- a/trunk/arch/x86/mm/init.c +++ b/trunk/arch/x86/mm/init.c @@ -331,23 +331,11 @@ int devmem_is_allowed(unsigned long pagenr) void free_init_pages(char *what, unsigned long begin, unsigned long end) { - unsigned long addr; - unsigned long begin_aligned, end_aligned; + unsigned long addr = begin; - /* 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) + if (addr >= 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 @@ -355,7 +343,7 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end) */ #ifdef CONFIG_DEBUG_PAGEALLOC printk(KERN_INFO "debug: unmapping init memory %08lx..%08lx\n", - begin, end); + begin, PAGE_ALIGN(end)); set_memory_np(begin, (end - begin) >> PAGE_SHIFT); #else /* @@ -370,7 +358,8 @@ 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, POISON_FREE_INITMEM, PAGE_SIZE); + memset((void *)(addr & ~(PAGE_SIZE-1)), + POISON_FREE_INITMEM, PAGE_SIZE); free_page(addr); totalram_pages++; } @@ -387,15 +376,6 @@ void free_initmem(void) #ifdef CONFIG_BLK_DEV_INITRD void free_initrd_mem(unsigned long start, unsigned long 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)); + free_init_pages("initrd memory", start, end); } #endif diff --git a/trunk/fs/logfs/dev_bdev.c b/trunk/fs/logfs/dev_bdev.c index a5d0c56d3ebc..9718c22f186d 100644 --- a/trunk/fs/logfs/dev_bdev.c +++ b/trunk/fs/logfs/dev_bdev.c @@ -80,7 +80,6 @@ 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,10 +97,8 @@ 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); + BUG_ON(!bio); /* FIXME: handle this */ for (i = 0; i < nr_pages; i++) { if (i >= max_pages) { @@ -194,10 +191,8 @@ 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); + BUG_ON(!bio); /* FIXME: handle this */ for (i = 0; i < nr_pages; i++) { if (i >= max_pages) { diff --git a/trunk/fs/logfs/dir.c b/trunk/fs/logfs/dir.c index c76b4b5c7ff6..56a8bfbb0120 100644 --- a/trunk/fs/logfs/dir.c +++ b/trunk/fs/logfs/dir.c @@ -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(page); + dd = kmap_atomic(page, KM_USER0); 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(page); + kunmap_atomic(dd, KM_USER0); page_cache_release(page); if (full) break; diff --git a/trunk/fs/logfs/journal.c b/trunk/fs/logfs/journal.c index d57c7b07b60b..6ad30a4c9052 100644 --- a/trunk/fs/logfs/journal.c +++ b/trunk/fs/logfs/journal.c @@ -800,7 +800,6 @@ 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,7 +807,6 @@ 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]); @@ -821,13 +819,8 @@ 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; diff --git a/trunk/fs/logfs/logfs.h b/trunk/fs/logfs/logfs.h index b84b0eec6024..129779431373 100644 --- a/trunk/fs/logfs/logfs.h +++ b/trunk/fs/logfs/logfs.h @@ -587,7 +587,6 @@ 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); diff --git a/trunk/fs/logfs/readwrite.c b/trunk/fs/logfs/readwrite.c index c3a3a6814b84..7a23b3e7c0a7 100644 --- a/trunk/fs/logfs/readwrite.c +++ b/trunk/fs/logfs/readwrite.c @@ -1594,6 +1594,7 @@ 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) { @@ -1610,18 +1611,6 @@ 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; diff --git a/trunk/fs/logfs/segment.c b/trunk/fs/logfs/segment.c index 0ecd8f07c11e..1a14f9910d55 100644 --- a/trunk/fs/logfs/segment.c +++ b/trunk/fs/logfs/segment.c @@ -93,57 +93,49 @@ void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len, } while (len); } -static void pad_partial_page(struct logfs_area *area) +/* + * bdev_writeseg will write full pages. Memset the tail to prevent data leaks. + */ +static void pad_wbuf(struct logfs_area *area, int final) { 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) { - page = get_mapping_page(sb, index, 0); + 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); BUG_ON(!page); /* FIXME: reserve a pool */ memset(page_address(page) + offset, 0xff, len); SetPagePrivate(page); page_cache_release(page); } -} -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; + if (!final) + return; - while (no_indizes) { - page = get_mapping_page(sb, index, 0); + 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); BUG_ON(!page); /* FIXME: reserve a pool */ - SetPageUptodate(page); - memset(page_address(page), 0xff, PAGE_CACHE_SIZE); + memset(page_address(page), 0xff, PAGE_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 @@ -691,7 +683,7 @@ int logfs_segment_delete(struct inode *inode, struct logfs_shadow *shadow) return 0; } -void freeseg(struct super_block *sb, u32 segno) +static 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; diff --git a/trunk/fs/logfs/super.c b/trunk/fs/logfs/super.c index 9d856c49afc5..c66beab78dee 100644 --- a/trunk/fs/logfs/super.c +++ b/trunk/fs/logfs/super.c @@ -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 logfs_write_sb(sb); + return write_one_sb(sb, super->s_devops->find_last_sb); } /* If neither is valid now, something's wrong. Didn't we properly * check them before?!? */ @@ -289,10 +289,6 @@ 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) @@ -303,6 +299,10 @@ 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); @@ -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 fail2; + goto fail; super->s_erase_page = alloc_pages(GFP_KERNEL, 0); if (!super->s_erase_page) @@ -572,7 +572,8 @@ int logfs_get_sb_device(struct file_system_type *type, int flags, return 0; err1: - deactivate_locked_super(sb); + up_write(&sb->s_umount); + deactivate_super(sb); return err; err0: kfree(super); diff --git a/trunk/kernel/cred.c b/trunk/kernel/cred.c index 1ed8ca18790c..1b1129d0cce8 100644 --- a/trunk/kernel/cred.c +++ b/trunk/kernel/cred.c @@ -364,7 +364,7 @@ struct cred *prepare_usermodehelper_creds(void) new = kmem_cache_alloc(cred_jar, GFP_ATOMIC); if (!new) - return NULL; + goto free_tgcred; kdebug("prepare_usermodehelper_creds() alloc %p", new); @@ -397,6 +397,10 @@ struct cred *prepare_usermodehelper_creds(void) error: put_cred(new); +free_tgcred: +#ifdef CONFIG_KEYS + kfree(tgcred); +#endif return NULL; } diff --git a/trunk/kernel/early_res.c b/trunk/kernel/early_res.c index 31aa9332ef3f..3cb2c661bb78 100644 --- a/trunk/kernel/early_res.c +++ b/trunk/kernel/early_res.c @@ -333,12 +333,6 @@ void __init free_early_partial(u64 start, u64 end) struct early_res *r; int i; - if (start == end) - return; - - if (WARN_ONCE(start > end, " wrong range [%#llx, %#llx]\n", start, end)) - return; - try_next: i = find_overlapped_early(start, end); if (i >= max_early_res)