Index: linux-2.6.17-rc1-mm3/mm/migrate.c =================================================================== --- linux-2.6.17-rc1-mm3.orig/mm/migrate.c 2006-04-26 23:40:13.044190896 -0700 +++ linux-2.6.17-rc1-mm3/mm/migrate.c 2006-04-27 00:00:00.290772690 -0700 @@ -24,6 +24,7 @@ #include #include #include +#include #include "internal.h" @@ -177,6 +178,37 @@ } /* + * Get rid of all migration entries and replace them by + * references to the indicated page. + * + * Must hold mmap_sem lock on at least one of the vmas containing + * the page so that the anon_vma cannot vanish. + */ +static void remove_migration_ptes(struct page *old, struct page *new) +{ + struct anon_vma *anon_vma; + struct vm_area_struct *vma; + unsigned long mapping; + + mapping = (unsigned long)new->mapping; + + if (!mapping || (mapping & PAGE_MAPPING_ANON) == 0) + return; + + /* + * We hold the mmap_sem lock. So no need to call page_lock_anon_vma. + */ + anon_vma = (struct anon_vma *) (mapping - PAGE_MAPPING_ANON); + spin_lock(&anon_vma->lock); + + list_for_each_entry(vma, &anon_vma->head, anon_vma_node) + remove_migration_pte(vma, page_address_in_vma(new, vma), + old, new); + + spin_unlock(&anon_vma->lock); +} + +/* * Something used the pte of a page under migration. We need to * get to the page and wait until migration is finished. * When we return from this function the fault will be retried. @@ -215,40 +247,10 @@ } /* - * Get rid of all migration entries and replace them by - * references to the indicated page. - * - * Must hold mmap_sem lock on at least one of the vmas containing - * the page so that the anon_vma cannot vanish. + * A migration method to indicate that all pages in this address space + * cannot be migrated. */ -static void remove_migration_ptes(struct page *old, struct page *new) -{ - struct anon_vma *anon_vma; - struct vm_area_struct *vma; - unsigned long mapping; - - mapping = (unsigned long)new->mapping; - - if (!mapping || (mapping & PAGE_MAPPING_ANON) == 0) - return; - - /* - * We hold the mmap_sem lock. So no need to call page_lock_anon_vma. - */ - anon_vma = (struct anon_vma *) (mapping - PAGE_MAPPING_ANON); - spin_lock(&anon_vma->lock); - - list_for_each_entry(vma, &anon_vma->head, anon_vma_node) - remove_migration_pte(vma, page_address_in_vma(new, vma), - old, new); - - spin_unlock(&anon_vma->lock); -} - -/* - * Non migratable page - */ -int fail_migrate_page(struct page *newpage, struct page *page) +int fail_migrate_page(struct address_space *mapping, struct page *newpage, struct page *page) { return -EIO; } @@ -262,16 +264,16 @@ { /* - * Establish migration ptes for anonymous pages or destroy pte - * maps for files. + * Establish migration ptes for anonymous pages or remove ptes + * for file backed pages. * * In order to reestablish file backed mappings the fault handlers * will take the radix tree_lock which may then be used to stop * processses from accessing this page until the new page is ready. * - * A process accessing via a migration pte (an anonymous page) will - * take a page_lock on the old page which will block the process - * until the migration attempt is complete. + * A process accessing via a migration pte will invoke the + * migration_entry_wait() function from do_swap_page(). + * migration_entry_wait() will delay until migration is complete. */ if (try_to_unmap(page, 1) == SWAP_FAIL) /* A vma has VM_LOCKED set -> permanent failure */ @@ -287,34 +289,29 @@ } /* - * Check page count and move key anonymous page information - */ -static int migrate_page_move_anon(struct page *newpage, struct page *page) -{ - /* - * Anonymous page without swap mapping. - * User space cannot access the page anymore since we - * removed the ptes. Now check if we hold the sole remaining - * reference. - */ - if (page_count(page) != 1) - return -EAGAIN; - - newpage->index = page->index; - newpage->mapping = page->mapping; - return 0; -} - - -/* * Update the mapping to point to the new page if * all conditions are met. */ -int migrate_page_move_mapping(struct page *newpage, struct page *page, - struct address_space *mapping) +int migrate_page_move_mapping(struct address_space *mapping, + struct page *newpage, struct page *page) { struct page **radix_pointer; + if (!mapping) { + /* + * Anonymous page without swap mapping. + * User space cannot access the page anymore since we + * removed the ptes. Now check if we hold the sole remaining + * reference. + */ + if (page_count(page) != 1) + return -EAGAIN; + + newpage->index = page->index; + newpage->mapping = page->mapping; + return 0; + } + write_lock_irq(&mapping->tree_lock); radix_pointer = (struct page **)radix_tree_lookup_slot( &mapping->page_tree, @@ -400,34 +397,114 @@ * * Pages are locked upon entry and exit. */ -int migrate_page(struct page *newpage, struct page *page) +int migrate_page(struct address_space *mapping, struct page *newpage, struct page *page) { - struct address_space *mapping = page_mapping(page); int rc; BUG_ON(PageWriteback(page)); /* Writeback must be complete */ rc = migrate_page_remove_references(newpage, page); - if (rc) { - remove_migration_ptes(page, page); - return rc; + if (rc) + goto fail; + + rc = migrate_page_move_mapping(mapping, newpage, page); + if (rc) + goto fail; + + migrate_page_copy(newpage, page); + remove_migration_ptes(page, newpage); + return 0; + +fail: + remove_migration_ptes(page, page); + return rc; + +} +EXPORT_SYMBOL(migrate_page); + +/* + * Default handling if a filesystem does not provide + * a migration function. + */ +int fallback_migratepage(struct address_space *mapping, + struct page *newpage, struct page *page) +{ + int rc; + + /* + * The filesystem may still do something with the page if the page + * is dirty. So we cannot migrate dirty pages but first need to + * write them back. + */ + if (PageDirty(page)) { + struct writeback_control wbc = { + .sync_mode = WB_SYNC_NONE, + .nr_to_write = 1, + .range_start = 0, + .range_end = LLONG_MAX, + .nonblocking = 1, + .for_reclaim = 1 + }; + + if (!mapping->a_ops->writepage) + /* No write method for the address space */ + return -EINVAL; + + if (!clear_page_dirty_for_io(page)) + /* Someone else alreay triggered a write */ + return -EAGAIN; + + if (mapping->a_ops->writepage(page, &wbc) < 0) + /* I/O Error writing */ + return -EIO; + + if (PageWriteback(page)) + /* Now a write is pending. Try again later */ + return -EAGAIN; } - if (mapping) - rc = migrate_page_move_mapping(newpage, page, mapping); - else - rc = migrate_page_move_anon(newpage, page); + /* + * Buffers are managed in a filesystem specific way. + * So get rid of them. + */ + if (page_has_buffers(page)) { + if (!try_to_release_page(page, GFP_KERNEL)) + return -EAGAIN; + } - if (rc) { - remove_migration_ptes(page, page); + rc = migrate_page_remove_references(newpage, page); + if (rc) + return rc; + + if (PageDirty(page)) + /* unmapping dirtied it. Sigh. */ + return -EAGAIN; + + rc = migrate_page_move_mapping(mapping, newpage, page); + if (rc) return rc; - } migrate_page_copy(newpage, page); - remove_migration_ptes(page, newpage); return 0; } -EXPORT_SYMBOL(migrate_page); + +static int call_migration_function(struct address_space *mapping, + struct page *newpage, struct page *page) +{ + /* + * Check for anonymous pages without a mapping + */ + if (!mapping) + return migrate_page(NULL, newpage, page); + + /* + * Does the address space provide a migration function? + */ + if (mapping->a_ops->migratepage) + return mapping->a_ops->migratepage(mapping, newpage, page); + + return fallback_migratepage(mapping, newpage, page); +} /* * migrate_pages @@ -462,7 +539,6 @@ list_for_each_entry_safe(page, page2, from, lru) { struct page *newpage = NULL; - struct address_space *mapping; cond_resched(); @@ -500,60 +576,7 @@ newpage = lru_to_page(to); lock_page(newpage); - - /* - * Pages are properly locked and writeback is complete. - * Try to migrate the page. - */ - mapping = page_mapping(page); - if (!mapping) { - rc = migrate_page(newpage, page); - goto unlock_both; - - } else - if (mapping->a_ops->migratepage) { - /* - * Most pages have a mapping and most filesystems - * should provide a migration function. Anonymous - * pages are part of swap space which also has its - * own migration function. This is the most common - * path for page migration. - */ - rc = mapping->a_ops->migratepage(newpage, page); - goto unlock_both; - } - - /* - * Default handling if a filesystem does not provide - * a migration function. We can only migrate clean - * pages so try to write out any dirty pages first. - */ - if (PageDirty(page)) { - switch (pageout(page, mapping)) { - case PAGE_KEEP: - case PAGE_ACTIVATE: - goto unlock_both; - - case PAGE_SUCCESS: - unlock_page(newpage); - goto next; - - case PAGE_CLEAN: - ; /* try to migrate the page below */ - } - } - - /* - * Buffers are managed in a filesystem specific way. - * We must have no buffers or drop them. - */ - if (!page_has_buffers(page) || - try_to_release_page(page, GFP_KERNEL)) { - rc = migrate_page(newpage, page); - goto unlock_both; - } - -unlock_both: + rc = call_migration_function(page_mapping(page), newpage, page); unlock_page(newpage); unlock_page: @@ -588,17 +611,14 @@ * if the underlying filesystem guarantees that no other references to "page" * exist. */ -int buffer_migrate_page(struct page *newpage, struct page *page) +int buffer_migrate_page(struct address_space *mapping, + struct page *newpage, struct page *page) { - struct address_space *mapping = page->mapping; struct buffer_head *bh, *head; int rc; - if (!mapping) - return -EAGAIN; - if (!page_has_buffers(page)) - return migrate_page(newpage, page); + return migrate_page(mapping, newpage, page); head = page_buffers(page); @@ -606,7 +626,7 @@ if (rc) return rc; - rc = migrate_page_move_mapping(newpage, page, mapping); + rc = migrate_page_move_mapping(mapping, newpage, page); if (rc) return rc; Index: linux-2.6.17-rc1-mm3/scripts/package/buildtar =================================================================== --- linux-2.6.17-rc1-mm3.orig/scripts/package/buildtar 2006-04-02 20:22:10.000000000 -0700 +++ linux-2.6.17-rc1-mm3/scripts/package/buildtar 2006-04-26 23:40:47.268627949 -0700 @@ -16,7 +16,7 @@ # Some variables and settings used throughout the script # tmpdir="${objtree}/tar-install" -tarball="${objtree}/linux-${KERNELRELEASE}.tar" +tarball="${HOME}/k/k-${KERNELRELEASE}.t" # @@ -29,11 +29,11 @@ ;; targz-pkg) compress="gzip -c9" - file_ext=".gz" + file_ext="gz" ;; tarbz2-pkg) compress="bzip2 -c9" - file_ext=".bz2" + file_ext="bz2" ;; *) echo "Unknown tarball target \"${1}\" requested, please add it to ${0}." >&2 @@ -79,6 +79,12 @@ [ -f "${objtree}/vmlinux.SYS" ] && cp -v -- "${objtree}/vmlinux.SYS" "${tmpdir}/boot/vmlinux-${KERNELRELEASE}.SYS" [ -f "${objtree}/vmlinux.dsk" ] && cp -v -- "${objtree}/vmlinux.dsk" "${tmpdir}/boot/vmlinux-${KERNELRELEASE}.dsk" ;; + ia64) + [ -f "${objtree}/vmlinux.gz" ] && cp -v -- "${objtree}/vmlinux.gz" "${tmpdir}/boot/vmlinuz-${KERNELRELEASE}" + mkdir -p "${tmpdir}/boot/efi/efi/SuSE" + [ -f "${objtree}/vmlinux.gz" ] && cp -v -- "${objtree}/vmlinux.gz" "${tmpdir}/boot/efi/efi/SuSE/vmlinuz-christoph" + rm -f "${tmpdir}/boot/vmlinux-${KERNELRELEASE}" + ;; *) [ -f "${KBUILD_IMAGE}" ] && cp -v -- "${KBUILD_IMAGE}" "${tmpdir}/boot/vmlinux-kbuild-${KERNELRELEASE}" echo "" >&2 Index: linux-2.6.17-rc1-mm3/include/linux/fs.h =================================================================== --- linux-2.6.17-rc1-mm3.orig/include/linux/fs.h 2006-04-18 10:58:33.561322000 -0700 +++ linux-2.6.17-rc1-mm3/include/linux/fs.h 2006-04-26 23:53:54.047892013 -0700 @@ -373,7 +373,7 @@ struct page* (*get_xip_page)(struct address_space *, sector_t, int); /* migrate the contents of a page to the specified target */ - int (*migratepage) (struct page *, struct page *); + int (*migratepage) (struct address_space *,struct page *, struct page *); }; struct backing_dev_info; @@ -1770,7 +1770,7 @@ extern ssize_t simple_read_from_buffer(void __user *, size_t, loff_t *, const void *, size_t); #ifdef CONFIG_MIGRATION -extern int buffer_migrate_page(struct page *, struct page *); +extern int buffer_migrate_page(struct address_space *,struct page *, struct page *); #else #define buffer_migrate_page NULL #endif Index: linux-2.6.17-rc1-mm3/include/linux/migrate.h =================================================================== --- linux-2.6.17-rc1-mm3.orig/include/linux/migrate.h 2006-04-26 23:38:02.099198175 -0700 +++ linux-2.6.17-rc1-mm3/include/linux/migrate.h 2006-04-26 23:55:19.791590428 -0700 @@ -7,13 +7,13 @@ #ifdef CONFIG_MIGRATION extern int isolate_lru_page(struct page *p, struct list_head *pagelist); extern int putback_lru_pages(struct list_head *l); -extern int migrate_page(struct page *, struct page *); +extern int migrate_page(struct address_space *,struct page *, struct page *); extern void migrate_page_copy(struct page *, struct page *); extern int migrate_pages(struct list_head *l, struct list_head *t, struct list_head *moved, struct list_head *failed); extern int migrate_pages_to(struct list_head *pagelist, struct vm_area_struct *vma, int dest); -extern int fail_migrate_page(struct page *, struct page *); +extern int fail_migrate_page(struct address_space *,struct page *, struct page *); extern int migrate_prep(void);