24 Apr, 2007

1 commit

  • NR_FILE_PAGES must be accounted for depending on the zone that the page
    belongs to. If we replace the page in the radix tree then we may have to
    shift the count to another zone.

    Suggested-by: Ethan Solomita
    Eventually-typed-in-by: Christoph Lameter
    Cc: Martin Bligh
    Cc:
    Signed-off-by: Christoph Lameter
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Christoph Lameter
     

05 Mar, 2007

1 commit

  • Currently we do not check for vma flags if sys_move_pages is called to move
    individual pages. If sys_migrate_pages is called to move pages then we
    check for vm_flags that indicate a non migratable vma but that still
    includes VM_LOCKED and we can migrate mlocked pages.

    Extract the vma_migratable check from mm/mempolicy.c, fix it and put it
    into migrate.h so that is can be used from both locations.

    Problem was spotted by Lee Schermerhorn

    Signed-off-by: Christoph Lameter
    Signed-off-by: Lee Schermerhorn
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Christoph Lameter
     

08 Dec, 2006

1 commit

  • Make radix tree lookups safe to be performed without locks. Readers are
    protected against nodes being deleted by using RCU based freeing. Readers
    are protected against new node insertion by using memory barriers to ensure
    the node itself will be properly written before it is visible in the radix
    tree.

    Each radix tree node keeps a record of their height (above leaf nodes).
    This height does not change after insertion -- when the radix tree is
    extended, higher nodes are only inserted in the top. So a lookup can take
    the pointer to what is *now* the root node, and traverse down it even if
    the tree is concurrently extended and this node becomes a subtree of a new
    root.

    "Direct" pointers (tree height of 0, where root->rnode points directly to
    the data item) are handled by using the low bit of the pointer to signal
    whether rnode is a direct pointer or a pointer to a radix tree node.

    When a reader wants to traverse the next branch, they will take a copy of
    the pointer. This pointer will be either NULL (and the branch is empty) or
    non-NULL (and will point to a valid node).

    [akpm@osdl.org: cleanups]
    [Lee.Schermerhorn@hp.com: bugfixes, comments, simplifications]
    [clameter@sgi.com: build fix]
    Signed-off-by: Nick Piggin
    Cc: "Paul E. McKenney"
    Signed-off-by: Lee Schermerhorn
    Cc: Christoph Lameter
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Nick Piggin
     

04 Nov, 2006

1 commit

  • sys_move_pages() uses vmalloc() to allocate an array of structures that is
    fills with information passed from user mode and then passes to
    do_stat_pages() (in the case the node list is NULL). do_stat_pages()
    depends on a marker in the node field of the structure to decide how large
    the array is and this marker is correctly inserted into the last element of
    the array. However, vmalloc() doesn't zero the memory it allocates and if
    the user passes NULL for the node list, then the node fields are not filled
    in (except for the end marker). If the memory the vmalloc() returned
    happend to have a word with the marker value in it in just the right place,
    do_pages_stat will fail to fill the status field of part of the array and
    we will return (random) kernel data to user mode.

    Signed-off-by: Stephen Rothwell
    Cc: Christoph Lameter
    Cc:
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Stephen Rothwell
     

01 Oct, 2006

2 commits

  • Make it possible to disable the block layer. Not all embedded devices require
    it, some can make do with just JFFS2, NFS, ramfs, etc - none of which require
    the block layer to be present.

    This patch does the following:

    (*) Introduces CONFIG_BLOCK to disable the block layer, buffering and blockdev
    support.

    (*) Adds dependencies on CONFIG_BLOCK to any configuration item that controls
    an item that uses the block layer. This includes:

    (*) Block I/O tracing.

    (*) Disk partition code.

    (*) All filesystems that are block based, eg: Ext3, ReiserFS, ISOFS.

    (*) The SCSI layer. As far as I can tell, even SCSI chardevs use the
    block layer to do scheduling. Some drivers that use SCSI facilities -
    such as USB storage - end up disabled indirectly from this.

    (*) Various block-based device drivers, such as IDE and the old CDROM
    drivers.

    (*) MTD blockdev handling and FTL.

    (*) JFFS - which uses set_bdev_super(), something it could avoid doing by
    taking a leaf out of JFFS2's book.

    (*) Makes most of the contents of linux/blkdev.h, linux/buffer_head.h and
    linux/elevator.h contingent on CONFIG_BLOCK being set. sector_div() is,
    however, still used in places, and so is still available.

    (*) Also made contingent are the contents of linux/mpage.h, linux/genhd.h and
    parts of linux/fs.h.

    (*) Makes a number of files in fs/ contingent on CONFIG_BLOCK.

    (*) Makes mm/bounce.c (bounce buffering) contingent on CONFIG_BLOCK.

    (*) set_page_dirty() doesn't call __set_page_dirty_buffers() if CONFIG_BLOCK
    is not enabled.

    (*) fs/no-block.c is created to hold out-of-line stubs and things that are
    required when CONFIG_BLOCK is not set:

    (*) Default blockdev file operations (to give error ENODEV on opening).

    (*) Makes some /proc changes:

    (*) /proc/devices does not list any blockdevs.

    (*) /proc/diskstats and /proc/partitions are contingent on CONFIG_BLOCK.

    (*) Makes some compat ioctl handling contingent on CONFIG_BLOCK.

    (*) If CONFIG_BLOCK is not defined, makes sys_quotactl() return -ENODEV if
    given command other than Q_SYNC or if a special device is specified.

    (*) In init/do_mounts.c, no reference is made to the blockdev routines if
    CONFIG_BLOCK is not defined. This does not prohibit NFS roots or JFFS2.

    (*) The bdflush, ioprio_set and ioprio_get syscalls can now be absent (return
    error ENOSYS by way of cond_syscall if so).

    (*) The seclvl_bd_claim() and seclvl_bd_release() security calls do nothing if
    CONFIG_BLOCK is not set, since they can't then happen.

    Signed-Off-By: David Howells
    Signed-off-by: Jens Axboe

    David Howells
     
  • Stop fallback_migrate_page() from using page_has_buffers() since that might not
    be available. Use PagePrivate() instead since that's more general.

    Signed-Off-By: David Howells
    Signed-off-by: Jens Axboe

    David Howells
     

26 Sep, 2006

2 commits


26 Jun, 2006

2 commits

  • Hugh clarified the role of VM_LOCKED. So we can now implement page
    migration for mlocked pages.

    Allow the migration of mlocked pages. This means that try_to_unmap must
    unmap mlocked pages in the migration case.

    Signed-off-by: Christoph Lameter
    Acked-by: Hugh Dickins
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Christoph Lameter
     
  • Hooks for calling vma specific migration functions

    With this patch a vma may define a vma->vm_ops->migrate function. That
    function may perform page migration on its own (some vmas may not contain page
    structs and therefore cannot be handled by regular page migration. Pages in a
    vma may require special preparatory treatment before migration is possible
    etc) . Only mmap_sem is held when the migration function is called. The
    migrate() function gets passed two sets of nodemasks describing the source and
    the target of the migration. The flags parameter either contains

    MPOL_MF_MOVE which means that only pages used exclusively by
    the specified mm should be moved

    or

    MPOL_MF_MOVE_ALL which means that pages shared with other processes
    should also be moved.

    The migration function returns 0 on success or an error condition. An error
    condition will prevent regular page migration from occurring.

    On its own this patch cannot be included since there are no users for this
    functionality. But it seems that the uncached allocator will need this
    functionality at some point.

    Signed-off-by: Christoph Lameter
    Cc: Hugh Dickins
    Cc: Andi Kleen
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Christoph Lameter
     

23 Jun, 2006

16 commits

  • This patch inserts security_task_movememory hook calls into memory management
    code to enable security modules to mediate this operation between tasks.

    Since the last posting, the hook has been renamed following feedback from
    Christoph Lameter.

    Signed-off-by: David Quigley
    Acked-by: Stephen Smalley
    Signed-off-by: James Morris
    Cc: Andi Kleen
    Acked-by: Christoph Lameter
    Acked-by: Chris Wright
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    David Quigley
     
  • move_pages() is used to move individual pages of a process. The function can
    be used to determine the location of pages and to move them onto the desired
    node. move_pages() returns status information for each page.

    long move_pages(pid, number_of_pages_to_move,
    addresses_of_pages[],
    nodes[] or NULL,
    status[],
    flags);

    The addresses of pages is an array of void * pointing to the
    pages to be moved.

    The nodes array contains the node numbers that the pages should be moved
    to. If a NULL is passed instead of an array then no pages are moved but
    the status array is updated. The status request may be used to determine
    the page state before issuing another move_pages() to move pages.

    The status array will contain the state of all individual page migration
    attempts when the function terminates. The status array is only valid if
    move_pages() completed successfullly.

    Possible page states in status[]:

    0..MAX_NUMNODES The page is now on the indicated node.

    -ENOENT Page is not present

    -EACCES Page is mapped by multiple processes and can only
    be moved if MPOL_MF_MOVE_ALL is specified.

    -EPERM The page has been mlocked by a process/driver and
    cannot be moved.

    -EBUSY Page is busy and cannot be moved. Try again later.

    -EFAULT Invalid address (no VMA or zero page).

    -ENOMEM Unable to allocate memory on target node.

    -EIO Unable to write back page. The page must be written
    back in order to move it since the page is dirty and the
    filesystem does not provide a migration function that
    would allow the moving of dirty pages.

    -EINVAL A dirty page cannot be moved. The filesystem does not provide
    a migration function and has no ability to write back pages.

    The flags parameter indicates what types of pages to move:

    MPOL_MF_MOVE Move pages that are only mapped by the process.

    MPOL_MF_MOVE_ALL Also move pages that are mapped by multiple processes.
    Requires sufficient capabilities.

    Possible return codes from move_pages()

    -ENOENT No pages found that would require moving. All pages
    are either already on the target node, not present, had an
    invalid address or could not be moved because they were
    mapped by multiple processes.

    -EINVAL Flags other than MPOL_MF_MOVE(_ALL) specified or an attempt
    to migrate pages in a kernel thread.

    -EPERM MPOL_MF_MOVE_ALL specified without sufficient priviledges.
    or an attempt to move a process belonging to another user.

    -EACCES One of the target nodes is not allowed by the current cpuset.

    -ENODEV One of the target nodes is not online.

    -ESRCH Process does not exist.

    -E2BIG Too many pages to move.

    -ENOMEM Not enough memory to allocate control array.

    -EFAULT Parameters could not be accessed.

    A test program for move_pages() may be found with the patches
    on ftp.kernel.org:/pub/linux/kernel/people/christoph/pmig/patches-2.6.17-rc4-mm3

    From: Christoph Lameter

    Detailed results for sys_move_pages()

    Pass a pointer to an integer to get_new_page() that may be used to
    indicate where the completion status of a migration operation should be
    placed. This allows sys_move_pags() to report back exactly what happened to
    each page.

    Wish there would be a better way to do this. Looks a bit hacky.

    Signed-off-by: Christoph Lameter
    Cc: Hugh Dickins
    Cc: Jes Sorensen
    Cc: KAMEZAWA Hiroyuki
    Cc: Lee Schermerhorn
    Cc: Andi Kleen
    Cc: Michael Kerrisk
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Christoph Lameter
     
  • Instead of passing a list of new pages, pass a function to allocate a new
    page. This allows the correct placement of MPOL_INTERLEAVE pages during page
    migration. It also further simplifies the callers of migrate pages.
    migrate_pages() becomes similar to migrate_pages_to() so drop
    migrate_pages_to(). The batching of new page allocations becomes unnecessary.

    Signed-off-by: Christoph Lameter
    Cc: Hugh Dickins
    Cc: Jes Sorensen
    Cc: KAMEZAWA Hiroyuki
    Cc: Lee Schermerhorn
    Cc: Andi Kleen
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Christoph Lameter
     
  • Do not leave pages on the lists passed to migrate_pages(). Seems that we will
    not need any postprocessing of pages. This will simplify the handling of
    pages by the callers of migrate_pages().

    Signed-off-by: Christoph Lameter
    Cc: Hugh Dickins
    Cc: Jes Sorensen
    Cc: KAMEZAWA Hiroyuki
    Cc: Lee Schermerhorn
    Cc: Andi Kleen
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Christoph Lameter
     
  • Currently migrate_pages() is mess with lots of goto. Extract two functions
    from migrate_pages() and get rid of the gotos.

    Plus we can just unconditionally set the locked bit on the new page since we
    are the only one holding a reference. Locking is to stop others from
    accessing the page once we establish references to the new page.

    Remove the list_del from move_to_lru in order to have finer control over list
    processing.

    [akpm@osdl.org: add debug check]
    Signed-off-by: Christoph Lameter
    Cc: Hugh Dickins
    Cc: Jes Sorensen
    Cc: KAMEZAWA Hiroyuki
    Cc: Lee Schermerhorn
    Cc: Andi Kleen
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Christoph Lameter
     
  • This implements the use of migration entries to preserve ptes of file backed
    pages during migration. Processes can therefore be migrated back and forth
    without loosing their connection to pagecache pages.

    Note that we implement the migration entries only for linear mappings.
    Nonlinear mappings still require the unmapping of the ptes for migration.

    And another writepage() ugliness shows up. writepage() can drop the page
    lock. Therefore we have to remove migration ptes before calling writepages()
    in order to avoid having migration entries point to unlocked pages.

    Signed-off-by: Christoph Lameter
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Christoph Lameter
     
  • If we install a migration entry then the rss not really decreases since the
    page is just moved somewhere else. We can save ourselves the work of
    decrementing and later incrementing which will just eventually cause cacheline
    bouncing.

    Signed-off-by: Christoph Lameter
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Christoph Lameter
     
  • Use the migration entries for page migration

    This modifies the migration code to use the new migration entries. It now
    becomes possible to migrate anonymous pages without having to add a swap
    entry.

    We add a couple of new functions to replace migration entries with the proper
    ptes.

    We cannot take the tree_lock for migrating anonymous pages anymore. However,
    we know that we hold the only remaining reference to the page when the page
    count reaches 1.

    Signed-off-by: Christoph Lameter
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Christoph Lameter
     
  • Rip the page migration logic out.

    Remove all code that has to do with swapping during page migration.

    This also guts the ability to migrate pages to swap. No one used that so lets
    let it go for good.

    Page migration should be a bit broken after this patch.

    Signed-off-by: Christoph Lameter
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Christoph Lameter
     
  • Implement read/write migration ptes

    We take the upper two swapfiles for the two types of migration ptes and define
    a series of macros in swapops.h.

    The VM is modified to handle the migration entries. migration entries can
    only be encountered when the page they are pointing to is locked. This limits
    the number of places one has to fix. We also check in copy_pte_range and in
    mprotect_pte_range() for migration ptes.

    We check for migration ptes in do_swap_cache and call a function that will
    then wait on the page lock. This allows us to effectively stop all accesses
    to apge.

    Migration entries are created by try_to_unmap if called for migration and
    removed by local functions in migrate.c

    From: Hugh Dickins

    Several times while testing swapless page migration (I've no NUMA, just
    hacking it up to migrate recklessly while running load), I've hit the
    BUG_ON(!PageLocked(p)) in migration_entry_to_page.

    This comes from an orphaned migration entry, unrelated to the current
    correctly locked migration, but hit by remove_anon_migration_ptes as it
    checks an address in each vma of the anon_vma list.

    Such an orphan may be left behind if an earlier migration raced with fork:
    copy_one_pte can duplicate a migration entry from parent to child, after
    remove_anon_migration_ptes has checked the child vma, but before it has
    removed it from the parent vma. (If the process were later to fault on this
    orphaned entry, it would hit the same BUG from migration_entry_wait.)

    This could be fixed by locking anon_vma in copy_one_pte, but we'd rather
    not. There's no such problem with file pages, because vma_prio_tree_add
    adds child vma after parent vma, and the page table locking at each end is
    enough to serialize. Follow that example with anon_vma: add new vmas to the
    tail instead of the head.

    (There's no corresponding problem when inserting migration entries,
    because a missed pte will leave the page count and mapcount high, which is
    allowed for. And there's no corresponding problem when migrating via swap,
    because a leftover swap entry will be correctly faulted. But the swapless
    method has no refcounting of its entries.)

    From: Ingo Molnar

    pte_unmap_unlock() takes the pte pointer as an argument.

    From: Hugh Dickins

    Several times while testing swapless page migration, gcc has tried to exec
    a pointer instead of a string: smells like COW mappings are not being
    properly write-protected on fork.

    The protection in copy_one_pte looks very convincing, until at last you
    realize that the second arg to make_migration_entry is a boolean "write",
    and SWP_MIGRATION_READ is 30.

    Anyway, it's better done like in change_pte_range, using
    is_write_migration_entry and make_migration_entry_read.

    From: Hugh Dickins

    Remove unnecessary obfuscation from sys_swapon's range check on swap type,
    which blew up causing memory corruption once swapless migration made
    MAX_SWAPFILES no longer 2 ^ MAX_SWAPFILES_SHIFT.

    Signed-off-by: Hugh Dickins
    Acked-by: Martin Schwidefsky
    Signed-off-by: Hugh Dickins
    Signed-off-by: Christoph Lameter
    Signed-off-by: Ingo Molnar
    From: Hugh Dickins
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Christoph Lameter
     
  • Move the fallback code into a new fallback function and make the function
    behave like any other migration function. This requires retaking the lock if
    pageout() drops it.

    Signed-off-by: Christoph Lameter
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Christoph Lameter
     
  • Change handling of address spaces.

    Pass a pointer to the address space in which the page is migrated to all
    migration function. This avoids repeatedly having to retrieve the address
    space pointer from the page and checking it for validity. The old page
    mapping will change once migration has gone to a certain step, so it is less
    confusing to have the pointer always available.

    Move the setting of the mapping and index for the new page into
    migrate_pages().

    Signed-off-by: Christoph Lameter
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Christoph Lameter
     
  • Extract try_to_unmap and rename remove_references -> move_mapping

    try_to_unmap() may significantly change the page state by for example setting
    the dirty bit. It is therefore best to unmap in migrate_pages() before
    calling any migration functions.

    migrate_page_remove_references() will then only move the new page in place of
    the old page in the mapping. Rename the function to
    migrate_page_move_mapping().

    This allows us to get rid of the special unmapping for the fallback path.

    Signed-off-by: Christoph Lameter
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Christoph Lameter
     
  • Drop nr_refs parameter from migrate_page_remove_references()

    The nr_refs parameter is not really useful since the number of remaining
    references is always

    1 for anonymous pages without a mapping
    2 for pages with a mapping
    3 for pages with a mapping and PagePrivate set.

    Remove the early check for the number of references since we are checking
    page_mapcount() earlier. Ultimately only the refcount matters after the
    tree_lock has been obtained.

    Signed-off-by: Christoph Lameter
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Christoph Lameter
     
  • Remove the export for migrate_page_remove_references() and migrate_page_copy()
    that are unlikely to be used directly by filesystems implementing migration.
    The export was useful when buffer_migrate_page() lived in fs/buffer.c but it
    has now been moved to migrate.c in the migration reorg.

    Signed-off-by: Christoph Lameter
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Christoph Lameter
     
  • Reorder functions in migrate.c. Group all migration functions for struct
    address_space_operations together.

    Signed-off-by: Christoph Lameter
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Christoph Lameter
     

02 May, 2006

1 commit

  • Currently we check PageDirty() in order to make the decision to swap out
    the page. However, the dirty information may be only be contained in the
    ptes pointing to the page. We need to first unmap the ptes before checking
    for PageDirty(). If unmap is successful then the page count of the page
    will also be decreased so that pageout() works properly.

    This is a fix necessary for 2.6.17. Without this fix we may migrate dirty
    pages for filesystems without migration functions. Filesystems may keep
    pointers to dirty pages. Migration of dirty pages can result in the
    filesystem keeping pointers to freed pages.

    Unmapping is currently not be separated out from removing all the
    references to a page and moving the mapping. Therefore try_to_unmap will
    be called again in migrate_page() if the writeout is successful. However,
    it wont do anything since the ptes are already removed.

    The coming updates to the page migration code will restructure the code
    so that this is no longer necessary.

    Signed-off-by: Christoph Lameter
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Christoph Lameter
     

11 Apr, 2006

2 commits


22 Mar, 2006

1 commit

  • Centralize the page migration functions in anticipation of additional
    tinkering. Creates a new file mm/migrate.c

    1. Extract buffer_migrate_page() from fs/buffer.c

    2. Extract central migration code from vmscan.c

    3. Extract some components from mempolicy.c

    4. Export pageout() and remove_from_swap() from vmscan.c

    5. Make it possible to configure NUMA systems without page migration
    and non-NUMA systems with page migration.

    I had to so some #ifdeffing in mempolicy.c that may need a cleanup.

    Signed-off-by: Christoph Lameter
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Christoph Lameter