diff for duplicates of <20100713102058.2835.10655.sendpatchset@danny.redhat> diff --git a/a/1.txt b/N1/1.txt index 27ed5ed..9819356 100644 --- a/a/1.txt +++ b/N1/1.txt @@ -372,9 +372,3 @@ index 03aa2d5..a7baef1 100644 * reference on the swaphandle, it doesn't matter if it becomes unused. -- 1.7.1.1 - --- -To unsubscribe, send a message with 'unsubscribe linux-mm' in -the body to majordomo@kvack.org. For more info on Linux MM, -see: http://www.linux-mm.org/ . -Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a> diff --git a/a/content_digest b/N1/content_digest index 1ff026f..6bd16c7 100644 --- a/a/content_digest +++ b/N1/content_digest @@ -389,12 +389,6 @@ " * swap_lock prevents swap_map being freed. Don't grab an extra\n" " * reference on the swaphandle, it doesn't matter if it becomes unused.\n" "-- \n" - "1.7.1.1\n" - "\n" - "--\n" - "To unsubscribe, send a message with 'unsubscribe linux-mm' in\n" - "the body to majordomo@kvack.org. For more info on Linux MM,\n" - "see: http://www.linux-mm.org/ .\n" - "Don't email: <a href=mailto:\"dont@kvack.org\"> email@kvack.org </a>" + 1.7.1.1 -b5df0efdce83ae2928e5fcff3156274a98e01d3adc6668cd9eae85d903fcd4f8 +50c051ac878fa2024ba69ee7fd078038754ffd8389e12b4afa2100b6d56fff63
diff --git a/a/1.txt b/N2/1.txt index 27ed5ed..8b13789 100644 --- a/a/1.txt +++ b/N2/1.txt @@ -1,380 +1 @@ ->From 0c3f6a5db5c61a222135286e8a6ada7411b3ac3b Mon Sep 17 00:00:00 2001 -From: Xiaotian Feng <dfeng@redhat.com> -Date: Tue, 13 Jul 2010 13:08:45 +0800 -Subject: [PATCH 22/30] mm: add support for non block device backed swap files -New addres_space_operations methods are added: - int swapon(struct file *); - int swapoff(struct file *); - int swap_out(struct file *, struct page *, struct writeback_control *); - int swap_in(struct file *, struct page *); - -When during sys_swapon() the ->swapon() method is found and returns no error -the swapper_space.a_ops will proxy to sis->swap_file->f_mapping->a_ops, and -make use of ->swap_{out,in}() to write/read swapcache pages. - -The ->swapon() method will be used to communicate to the file that the VM -relies on it, and the address_space should take adequate measures (like -reserving memory for mempools or the like). The ->swapoff() method will be -called on sys_swapoff() when ->swapon() was found and returned no error. - -This new interface can be used to obviate the need for ->bmap in the swapfile -code. A filesystem would need to load (and maybe even allocate) the full block -map for a file into memory and pin it there on ->swapon() so that -->swap_{out,in}() have instant access to it. It can be released on ->swapoff(). - -The reason to provide ->swap_{out,in}() over using {write,read}page() is to - 1) make a distinction between swapcache and pagecache pages, and - 2) to provide a struct file * for credential context (normally not needed - in the context of writepage, as the page content is normally dirtied - using either of the following interfaces: - write_{begin,end}() - {prepare,commit}_write() - page_mkwrite() - which do have the file context. - -[miklos@szeredi.hu: cleanups] -[dfeng@redhat.com: fix get_swap_info return value] -[dfeng@redhat.com: fix wrong SWP_FILE enum] -Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> -Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de> -Signed-off-by: Xiaotian Feng <dfeng@redhat.com> ---- - Documentation/filesystems/Locking | 22 +++++++++++++++ - Documentation/filesystems/vfs.txt | 18 ++++++++++++ - include/linux/buffer_head.h | 1 + - include/linux/fs.h | 9 ++++++ - include/linux/swap.h | 5 +++- - mm/page_io.c | 54 +++++++++++++++++++++++++++++++++++++ - mm/swap_state.c | 4 +- - mm/swapfile.c | 36 +++++++++++++++++++++++- - 8 files changed, 144 insertions(+), 5 deletions(-) - -diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking -index 96d4293..9e221ad 100644 ---- a/Documentation/filesystems/Locking -+++ b/Documentation/filesystems/Locking -@@ -174,6 +174,10 @@ prototypes: - int (*direct_IO)(int, struct kiocb *, const struct iovec *iov, - loff_t offset, unsigned long nr_segs); - int (*launder_page) (struct page *); -+ int (*swapon) (struct file *); -+ int (*swapoff) (struct file *); -+ int (*swap_out) (struct file *, struct page *, struct writeback_control *); -+ int (*swap_in) (struct file *, struct page *); - - locking rules: - All except set_page_dirty may block -@@ -193,6 +197,10 @@ invalidatepage: no yes - releasepage: no yes - direct_IO: no - launder_page: no yes -+swapon no -+swapoff no -+swap_out no yes, unlocks -+swap_in no yes, unlocks - - ->write_begin(), ->write_end(), ->sync_page() and ->readpage() - may be called from the request handler (/dev/loop). -@@ -292,6 +300,20 @@ cleaned, or an error value if not. Note that in order to prevent the page - getting mapped back in and redirtied, it needs to be kept locked - across the entire operation. - -+ ->swapon() will be called with a non-zero argument on files backing -+(non block device backed) swapfiles. A return value of zero indicates success, -+in which case this file can be used for backing swapspace. The swapspace -+operations will be proxied to the address space operations. -+ -+ ->swapoff() will be called in the sys_swapoff() path when ->swapon() -+returned success. -+ -+ ->swap_out() when swapon() returned success, this method is used to -+write the swap page. -+ -+ ->swap_in() when swapon() returned success, this method is used to -+read the swap page. -+ - Note: currently almost all instances of address_space methods are - using BKL for internal serialization and that's one of the worst sources - of contention. Normally they are calling library functions (in fs/buffer.c) -diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt -index 94677e7..209ae81 100644 ---- a/Documentation/filesystems/vfs.txt -+++ b/Documentation/filesystems/vfs.txt -@@ -542,6 +542,11 @@ struct address_space_operations { - int (*migratepage) (struct page *, struct page *); - int (*launder_page) (struct page *); - int (*error_remove_page) (struct mapping *mapping, struct page *page); -+ int (*swapon)(struct file *); -+ int (*swapoff)(struct file *); -+ int (*swap_out)(struct file *file, struct page *page, -+ struct writeback_control *wbc); -+ int (*swap_in)(struct file *file, struct page *page); - }; - - writepage: called by the VM to write a dirty page to backing store. -@@ -706,6 +711,19 @@ struct address_space_operations { - unless you have them locked or reference counts increased. - - -+ swapon: Called when swapon is used on a file. A -+ return value of zero indicates success, in which case this -+ file can be used to back swapspace. The swapspace operations -+ will be proxied to this address space's ->swap_{out,in} methods. -+ -+ swapoff: Called during swapoff on files where swapon was successfull. -+ -+ swap_out: Called to write a swapcache page to a backing store, similar to -+ writepage. -+ -+ swap_in: Called to read a swapcache page from a backing store, similar to -+ readpage. -+ - The File Object - =============== - -diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h -index 5aa3850..7ec96e7 100644 ---- a/include/linux/buffer_head.h -+++ b/include/linux/buffer_head.h -@@ -329,6 +329,7 @@ static inline int inode_has_buffers(struct inode *inode) { return 0; } - static inline void invalidate_inode_buffers(struct inode *inode) {} - static inline int remove_inode_buffers(struct inode *inode) { return 1; } - static inline int sync_mapping_buffers(struct address_space *mapping) { return 0; } -+static inline void block_sync_page(struct page *) { } - - #endif /* CONFIG_BLOCK */ - #endif /* _LINUX_BUFFER_HEAD_H */ -diff --git a/include/linux/fs.h b/include/linux/fs.h -index dc9d185..ef11408 100644 ---- a/include/linux/fs.h -+++ b/include/linux/fs.h -@@ -612,6 +612,15 @@ struct address_space_operations { - int (*is_partially_uptodate) (struct page *, read_descriptor_t *, - unsigned long); - int (*error_remove_page)(struct address_space *, struct page *); -+ -+ /* -+ * swapfile support -+ */ -+ int (*swapon)(struct file *file); -+ int (*swapoff)(struct file *file); -+ int (*swap_out)(struct file *file, struct page *page, -+ struct writeback_control *wbc); -+ int (*swap_in)(struct file *file, struct page *page); - }; - - /* -diff --git a/include/linux/swap.h b/include/linux/swap.h -index ff4acea..dafea65 100644 ---- a/include/linux/swap.h -+++ b/include/linux/swap.h -@@ -147,7 +147,7 @@ enum { - SWP_SOLIDSTATE = (1 << 4), /* blkdev seeks are cheap */ - SWP_CONTINUED = (1 << 5), /* swap_map has count continuation */ - SWP_BLKDEV = (1 << 6), /* its a block device */ -- /* add others here before... */ -+ SWP_FILE = (1 << 7), /* file swap area */ - SWP_SCANNING = (1 << 8), /* refcount in scan_swap_map */ - }; - -@@ -293,6 +293,8 @@ extern void swap_unplug_io_fn(struct backing_dev_info *, struct page *); - /* linux/mm/page_io.c */ - extern int swap_readpage(struct page *); - extern int swap_writepage(struct page *page, struct writeback_control *wbc); -+extern void swap_sync_page(struct page *page); -+extern int swap_set_page_dirty(struct page *page); - extern void end_swap_bio_read(struct bio *bio, int err); - - /* linux/mm/swap_state.c */ -@@ -329,6 +331,7 @@ extern int swap_type_of(dev_t, sector_t, struct block_device **); - extern unsigned int count_swap_pages(int, int); - extern sector_t map_swap_page(struct page *, struct block_device **); - extern sector_t swapdev_block(int, pgoff_t); -+extern struct swap_info_struct *page_swap_info(struct page *); - extern int reuse_swap_page(struct page *); - extern int try_to_free_swap(struct page *); - struct backing_dev_info; -diff --git a/mm/page_io.c b/mm/page_io.c -index 2dee975..012b9ef 100644 ---- a/mm/page_io.c -+++ b/mm/page_io.c -@@ -18,6 +18,7 @@ - #include <linux/bio.h> - #include <linux/swapops.h> - #include <linux/writeback.h> -+#include <linux/buffer_head.h> - #include <asm/pgtable.h> - - static struct bio *get_swap_bio(gfp_t gfp_flags, -@@ -98,6 +99,17 @@ int swap_writepage(struct page *page, struct writeback_control *wbc) - unlock_page(page); - goto out; - } -+ -+ if (sis->flags & SWP_FILE) { -+ struct file *swap_file = sis->swap_file; -+ struct address_space *mapping = swap_file->f_mapping; -+ -+ ret = mapping->a_ops->swap_out(swap_file, page, wbc); -+ if (!ret) -+ count_vm_event(PSWPOUT); -+ return ret; -+ } -+ - bio = get_swap_bio(GFP_NOIO, page, end_swap_bio_write); - if (bio == NULL) { - set_page_dirty(page); -@@ -115,13 +127,55 @@ out: - return ret; - } - -+void swap_sync_page(struct page *page) -+{ -+ struct swap_info_struct *sis = page_swap_info(page); -+ -+ if (!sis) -+ return; -+ -+ if (sis->flags & SWP_FILE) { -+ struct address_space *mapping = sis->swap_file->f_mapping; -+ -+ if (mapping->a_ops->sync_page) -+ mapping->a_ops->sync_page(page); -+ } else { -+ block_sync_page(page); -+ } -+} -+ -+int swap_set_page_dirty(struct page *page) -+{ -+ struct swap_info_struct *sis = page_swap_info(page); -+ -+ if (sis->flags & SWP_FILE) { -+ struct address_space *mapping = sis->swap_file->f_mapping; -+ -+ return mapping->a_ops->set_page_dirty(page); -+ } else { -+ return __set_page_dirty_nobuffers(page); -+ } -+} -+ - int swap_readpage(struct page *page) - { - struct bio *bio; - int ret = 0; -+ struct swap_info_struct *sis = page_swap_info(page); - - VM_BUG_ON(!PageLocked(page)); - VM_BUG_ON(PageUptodate(page)); -+ -+ if (sis->flags & SWP_FILE) { -+ struct file *swap_file = sis->swap_file; -+ struct address_space *mapping = swap_file->f_mapping; -+ -+ ret = mapping->a_ops->swap_in(swap_file, page); -+ if (!ret) -+ count_vm_event(PSWPIN); -+ return ret; -+ } -+ - bio = get_swap_bio(GFP_KERNEL, page, end_swap_bio_read); - if (bio == NULL) { - unlock_page(page); -diff --git a/mm/swap_state.c b/mm/swap_state.c -index 8d5399f..041428b 100644 ---- a/mm/swap_state.c -+++ b/mm/swap_state.c -@@ -28,8 +28,8 @@ - */ - static const struct address_space_operations swap_aops = { - .writepage = swap_writepage, -- .sync_page = block_sync_page, -- .set_page_dirty = __set_page_dirty_nobuffers, -+ .sync_page = swap_sync_page, -+ .set_page_dirty = swap_set_page_dirty, - .migratepage = migrate_page, - }; - -diff --git a/mm/swapfile.c b/mm/swapfile.c -index 03aa2d5..a7baef1 100644 ---- a/mm/swapfile.c -+++ b/mm/swapfile.c -@@ -1353,6 +1353,14 @@ static void destroy_swap_extents(struct swap_info_struct *sis) - list_del(&se->list); - kfree(se); - } -+ -+ if (sis->flags & SWP_FILE) { -+ struct file *swap_file = sis->swap_file; -+ struct address_space *mapping = swap_file->f_mapping; -+ -+ sis->flags &= ~SWP_FILE; -+ mapping->a_ops->swapoff(swap_file); -+ } - } - - /* -@@ -1434,7 +1442,9 @@ add_swap_extent(struct swap_info_struct *sis, unsigned long start_page, - */ - static int setup_swap_extents(struct swap_info_struct *sis, sector_t *span) - { -- struct inode *inode; -+ struct file *swap_file = sis->swap_file; -+ struct address_space *mapping = swap_file->f_mapping; -+ struct inode *inode = mapping->host; - unsigned blocks_per_page; - unsigned long page_no; - unsigned blkbits; -@@ -1445,13 +1455,22 @@ static int setup_swap_extents(struct swap_info_struct *sis, sector_t *span) - int nr_extents = 0; - int ret; - -- inode = sis->swap_file->f_mapping->host; - if (S_ISBLK(inode->i_mode)) { - ret = add_swap_extent(sis, 0, sis->max, 0); - *span = sis->pages; - goto out; - } - -+ if (mapping->a_ops->swapon) { -+ ret = mapping->a_ops->swapon(swap_file); -+ if (!ret) { -+ sis->flags |= SWP_FILE; -+ ret = add_swap_extent(sis, 0, sis->max, 0); -+ *span = sis->pages; -+ } -+ goto out; -+ } -+ - blkbits = inode->i_blkbits; - blocks_per_page = PAGE_SIZE >> blkbits; - -@@ -2228,6 +2247,19 @@ int swapcache_prepare(swp_entry_t entry) - return __swap_duplicate(entry, SWAP_HAS_CACHE); - } - -+struct swap_info_struct *page_swap_info(struct page *page) -+{ -+ swp_entry_t swap = { .val = page_private(page) }; -+ if (!PageSwapCache(page) || !swap.val) { -+ /* This should only happen from sync_page. -+ * In other cases the page should be locked and -+ * should be in a SwapCache -+ */ -+ return NULL; -+ } -+ return swap_info[swp_type(swap)]; -+} -+ - /* - * swap_lock prevents swap_map being freed. Don't grab an extra - * reference on the swaphandle, it doesn't matter if it becomes unused. --- -1.7.1.1 - --- -To unsubscribe, send a message with 'unsubscribe linux-mm' in -the body to majordomo@kvack.org. For more info on Linux MM, -see: http://www.linux-mm.org/ . -Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a> diff --git a/a/content_digest b/N2/content_digest index 1ff026f..28fe411 100644 --- a/a/content_digest +++ b/N2/content_digest @@ -16,385 +16,5 @@ " davem@davemloft.net\0" "\00:1\0" "b\0" - ">From 0c3f6a5db5c61a222135286e8a6ada7411b3ac3b Mon Sep 17 00:00:00 2001\n" - "From: Xiaotian Feng <dfeng@redhat.com>\n" - "Date: Tue, 13 Jul 2010 13:08:45 +0800\n" - "Subject: [PATCH 22/30] mm: add support for non block device backed swap files\n" - "\n" - "New addres_space_operations methods are added:\n" - " int swapon(struct file *);\n" - " int swapoff(struct file *);\n" - " int swap_out(struct file *, struct page *, struct writeback_control *);\n" - " int swap_in(struct file *, struct page *);\n" - "\n" - "When during sys_swapon() the ->swapon() method is found and returns no error\n" - "the swapper_space.a_ops will proxy to sis->swap_file->f_mapping->a_ops, and\n" - "make use of ->swap_{out,in}() to write/read swapcache pages.\n" - "\n" - "The ->swapon() method will be used to communicate to the file that the VM\n" - "relies on it, and the address_space should take adequate measures (like\n" - "reserving memory for mempools or the like). The ->swapoff() method will be\n" - "called on sys_swapoff() when ->swapon() was found and returned no error.\n" - "\n" - "This new interface can be used to obviate the need for ->bmap in the swapfile\n" - "code. A filesystem would need to load (and maybe even allocate) the full block\n" - "map for a file into memory and pin it there on ->swapon() so that\n" - "->swap_{out,in}() have instant access to it. It can be released on ->swapoff().\n" - "\n" - "The reason to provide ->swap_{out,in}() over using {write,read}page() is to\n" - " 1) make a distinction between swapcache and pagecache pages, and\n" - " 2) to provide a struct file * for credential context (normally not needed\n" - " in the context of writepage, as the page content is normally dirtied\n" - " using either of the following interfaces:\n" - " write_{begin,end}()\n" - " {prepare,commit}_write()\n" - " page_mkwrite()\n" - " which do have the file context.\n" - "\n" - "[miklos@szeredi.hu: cleanups]\n" - "[dfeng@redhat.com: fix get_swap_info return value]\n" - "[dfeng@redhat.com: fix wrong SWP_FILE enum]\n" - "Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>\n" - "Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>\n" - "Signed-off-by: Xiaotian Feng <dfeng@redhat.com>\n" - "---\n" - " Documentation/filesystems/Locking | 22 +++++++++++++++\n" - " Documentation/filesystems/vfs.txt | 18 ++++++++++++\n" - " include/linux/buffer_head.h | 1 +\n" - " include/linux/fs.h | 9 ++++++\n" - " include/linux/swap.h | 5 +++-\n" - " mm/page_io.c | 54 +++++++++++++++++++++++++++++++++++++\n" - " mm/swap_state.c | 4 +-\n" - " mm/swapfile.c | 36 +++++++++++++++++++++++-\n" - " 8 files changed, 144 insertions(+), 5 deletions(-)\n" - "\n" - "diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking\n" - "index 96d4293..9e221ad 100644\n" - "--- a/Documentation/filesystems/Locking\n" - "+++ b/Documentation/filesystems/Locking\n" - "@@ -174,6 +174,10 @@ prototypes:\n" - " \tint (*direct_IO)(int, struct kiocb *, const struct iovec *iov,\n" - " \t\t\tloff_t offset, unsigned long nr_segs);\n" - " \tint (*launder_page) (struct page *);\n" - "+\tint (*swapon) (struct file *);\n" - "+\tint (*swapoff) (struct file *);\n" - "+\tint (*swap_out) (struct file *, struct page *, struct writeback_control *);\n" - "+\tint (*swap_in) (struct file *, struct page *);\n" - " \n" - " locking rules:\n" - " \tAll except set_page_dirty may block\n" - "@@ -193,6 +197,10 @@ invalidatepage:\t\tno\tyes\n" - " releasepage:\t\tno\tyes\n" - " direct_IO:\t\tno\n" - " launder_page:\t\tno\tyes\n" - "+swapon\t\t\tno\n" - "+swapoff\t\t\tno\n" - "+swap_out\t\tno\tyes, unlocks\n" - "+swap_in\t\t\tno\tyes, unlocks\n" - " \n" - " \t->write_begin(), ->write_end(), ->sync_page() and ->readpage()\n" - " may be called from the request handler (/dev/loop).\n" - "@@ -292,6 +300,20 @@ cleaned, or an error value if not. Note that in order to prevent the page\n" - " getting mapped back in and redirtied, it needs to be kept locked\n" - " across the entire operation.\n" - " \n" - "+\t->swapon() will be called with a non-zero argument on files backing\n" - "+(non block device backed) swapfiles. A return value of zero indicates success,\n" - "+in which case this file can be used for backing swapspace. The swapspace\n" - "+operations will be proxied to the address space operations.\n" - "+\n" - "+\t->swapoff() will be called in the sys_swapoff() path when ->swapon()\n" - "+returned success.\n" - "+\n" - "+\t->swap_out() when swapon() returned success, this method is used to\n" - "+write the swap page.\n" - "+\n" - "+\t->swap_in() when swapon() returned success, this method is used to\n" - "+read the swap page.\n" - "+\n" - " \tNote: currently almost all instances of address_space methods are\n" - " using BKL for internal serialization and that's one of the worst sources\n" - " of contention. Normally they are calling library functions (in fs/buffer.c)\n" - "diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt\n" - "index 94677e7..209ae81 100644\n" - "--- a/Documentation/filesystems/vfs.txt\n" - "+++ b/Documentation/filesystems/vfs.txt\n" - "@@ -542,6 +542,11 @@ struct address_space_operations {\n" - " \tint (*migratepage) (struct page *, struct page *);\n" - " \tint (*launder_page) (struct page *);\n" - " \tint (*error_remove_page) (struct mapping *mapping, struct page *page);\n" - "+\tint (*swapon)(struct file *);\n" - "+\tint (*swapoff)(struct file *);\n" - "+\tint (*swap_out)(struct file *file, struct page *page,\n" - "+\t\t\tstruct writeback_control *wbc);\n" - "+\tint (*swap_in)(struct file *file, struct page *page);\n" - " };\n" - " \n" - " writepage: called by the VM to write a dirty page to backing store.\n" - "@@ -706,6 +711,19 @@ struct address_space_operations {\n" - " \tunless you have them locked or reference counts increased.\n" - " \n" - " \n" - "+ swapon: Called when swapon is used on a file. A\n" - "+\treturn value of zero indicates success, in which case this\n" - "+\tfile can be used to back swapspace. The swapspace operations\n" - "+\twill be proxied to this address space's ->swap_{out,in} methods.\n" - "+\n" - "+ swapoff: Called during swapoff on files where swapon was successfull.\n" - "+\n" - "+ swap_out: Called to write a swapcache page to a backing store, similar to\n" - "+\twritepage.\n" - "+\n" - "+ swap_in: Called to read a swapcache page from a backing store, similar to\n" - "+\treadpage.\n" - "+\n" - " The File Object\n" - " ===============\n" - " \n" - "diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h\n" - "index 5aa3850..7ec96e7 100644\n" - "--- a/include/linux/buffer_head.h\n" - "+++ b/include/linux/buffer_head.h\n" - "@@ -329,6 +329,7 @@ static inline int inode_has_buffers(struct inode *inode) { return 0; }\n" - " static inline void invalidate_inode_buffers(struct inode *inode) {}\n" - " static inline int remove_inode_buffers(struct inode *inode) { return 1; }\n" - " static inline int sync_mapping_buffers(struct address_space *mapping) { return 0; }\n" - "+static inline void block_sync_page(struct page *) { }\n" - " \n" - " #endif /* CONFIG_BLOCK */\n" - " #endif /* _LINUX_BUFFER_HEAD_H */\n" - "diff --git a/include/linux/fs.h b/include/linux/fs.h\n" - "index dc9d185..ef11408 100644\n" - "--- a/include/linux/fs.h\n" - "+++ b/include/linux/fs.h\n" - "@@ -612,6 +612,15 @@ struct address_space_operations {\n" - " \tint (*is_partially_uptodate) (struct page *, read_descriptor_t *,\n" - " \t\t\t\t\tunsigned long);\n" - " \tint (*error_remove_page)(struct address_space *, struct page *);\n" - "+\n" - "+\t/*\n" - "+\t * swapfile support\n" - "+\t */\n" - "+\tint (*swapon)(struct file *file);\n" - "+\tint (*swapoff)(struct file *file);\n" - "+\tint (*swap_out)(struct file *file, struct page *page,\n" - "+\t\t\tstruct writeback_control *wbc);\n" - "+\tint (*swap_in)(struct file *file, struct page *page);\n" - " };\n" - " \n" - " /*\n" - "diff --git a/include/linux/swap.h b/include/linux/swap.h\n" - "index ff4acea..dafea65 100644\n" - "--- a/include/linux/swap.h\n" - "+++ b/include/linux/swap.h\n" - "@@ -147,7 +147,7 @@ enum {\n" - " \tSWP_SOLIDSTATE\t= (1 << 4),\t/* blkdev seeks are cheap */\n" - " \tSWP_CONTINUED\t= (1 << 5),\t/* swap_map has count continuation */\n" - " \tSWP_BLKDEV\t= (1 << 6),\t/* its a block device */\n" - "-\t\t\t\t\t/* add others here before... */\n" - "+\tSWP_FILE\t= (1 << 7),\t/* file swap area */\n" - " \tSWP_SCANNING\t= (1 << 8),\t/* refcount in scan_swap_map */\n" - " };\n" - " \n" - "@@ -293,6 +293,8 @@ extern void swap_unplug_io_fn(struct backing_dev_info *, struct page *);\n" - " /* linux/mm/page_io.c */\n" - " extern int swap_readpage(struct page *);\n" - " extern int swap_writepage(struct page *page, struct writeback_control *wbc);\n" - "+extern void swap_sync_page(struct page *page);\n" - "+extern int swap_set_page_dirty(struct page *page);\n" - " extern void end_swap_bio_read(struct bio *bio, int err);\n" - " \n" - " /* linux/mm/swap_state.c */\n" - "@@ -329,6 +331,7 @@ extern int swap_type_of(dev_t, sector_t, struct block_device **);\n" - " extern unsigned int count_swap_pages(int, int);\n" - " extern sector_t map_swap_page(struct page *, struct block_device **);\n" - " extern sector_t swapdev_block(int, pgoff_t);\n" - "+extern struct swap_info_struct *page_swap_info(struct page *);\n" - " extern int reuse_swap_page(struct page *);\n" - " extern int try_to_free_swap(struct page *);\n" - " struct backing_dev_info;\n" - "diff --git a/mm/page_io.c b/mm/page_io.c\n" - "index 2dee975..012b9ef 100644\n" - "--- a/mm/page_io.c\n" - "+++ b/mm/page_io.c\n" - "@@ -18,6 +18,7 @@\n" - " #include <linux/bio.h>\n" - " #include <linux/swapops.h>\n" - " #include <linux/writeback.h>\n" - "+#include <linux/buffer_head.h>\n" - " #include <asm/pgtable.h>\n" - " \n" - " static struct bio *get_swap_bio(gfp_t gfp_flags,\n" - "@@ -98,6 +99,17 @@ int swap_writepage(struct page *page, struct writeback_control *wbc)\n" - " \t\tunlock_page(page);\n" - " \t\tgoto out;\n" - " \t}\n" - "+\n" - "+\tif (sis->flags & SWP_FILE) {\n" - "+\t\tstruct file *swap_file = sis->swap_file;\n" - "+\t\tstruct address_space *mapping = swap_file->f_mapping;\n" - "+\n" - "+\t\tret = mapping->a_ops->swap_out(swap_file, page, wbc);\n" - "+\t\tif (!ret)\n" - "+\t\t\tcount_vm_event(PSWPOUT);\n" - "+\t\treturn ret;\n" - "+\t}\n" - "+\n" - " \tbio = get_swap_bio(GFP_NOIO, page, end_swap_bio_write);\n" - " \tif (bio == NULL) {\n" - " \t\tset_page_dirty(page);\n" - "@@ -115,13 +127,55 @@ out:\n" - " \treturn ret;\n" - " }\n" - " \n" - "+void swap_sync_page(struct page *page)\n" - "+{\n" - "+\tstruct swap_info_struct *sis = page_swap_info(page);\n" - "+\n" - "+\tif (!sis)\n" - "+\t\treturn;\n" - "+\n" - "+\tif (sis->flags & SWP_FILE) {\n" - "+\t\tstruct address_space *mapping = sis->swap_file->f_mapping;\n" - "+\n" - "+\tif (mapping->a_ops->sync_page)\n" - "+\t\tmapping->a_ops->sync_page(page);\n" - "+\t} else {\n" - "+\t\tblock_sync_page(page);\n" - "+\t}\n" - "+}\n" - "+\n" - "+int swap_set_page_dirty(struct page *page)\n" - "+{\n" - "+\tstruct swap_info_struct *sis = page_swap_info(page);\n" - "+\n" - "+\tif (sis->flags & SWP_FILE) {\n" - "+\t\tstruct address_space *mapping = sis->swap_file->f_mapping;\n" - "+\n" - "+\t\treturn mapping->a_ops->set_page_dirty(page);\n" - "+\t} else {\n" - "+\t\treturn __set_page_dirty_nobuffers(page);\n" - "+\t}\n" - "+}\n" - "+\n" - " int swap_readpage(struct page *page)\n" - " {\n" - " \tstruct bio *bio;\n" - " \tint ret = 0;\n" - "+\tstruct swap_info_struct *sis = page_swap_info(page);\n" - " \n" - " \tVM_BUG_ON(!PageLocked(page));\n" - " \tVM_BUG_ON(PageUptodate(page));\n" - "+\n" - "+\tif (sis->flags & SWP_FILE) {\n" - "+\t\tstruct file *swap_file = sis->swap_file;\n" - "+\t\tstruct address_space *mapping = swap_file->f_mapping;\n" - "+\n" - "+\t\tret = mapping->a_ops->swap_in(swap_file, page);\n" - "+\t\tif (!ret)\n" - "+\t\t\tcount_vm_event(PSWPIN);\n" - "+\t\treturn ret;\n" - "+\t}\n" - "+\n" - " \tbio = get_swap_bio(GFP_KERNEL, page, end_swap_bio_read);\n" - " \tif (bio == NULL) {\n" - " \t\tunlock_page(page);\n" - "diff --git a/mm/swap_state.c b/mm/swap_state.c\n" - "index 8d5399f..041428b 100644\n" - "--- a/mm/swap_state.c\n" - "+++ b/mm/swap_state.c\n" - "@@ -28,8 +28,8 @@\n" - " */\n" - " static const struct address_space_operations swap_aops = {\n" - " \t.writepage\t= swap_writepage,\n" - "-\t.sync_page\t= block_sync_page,\n" - "-\t.set_page_dirty\t= __set_page_dirty_nobuffers,\n" - "+\t.sync_page\t= swap_sync_page,\n" - "+\t.set_page_dirty\t= swap_set_page_dirty,\n" - " \t.migratepage\t= migrate_page,\n" - " };\n" - " \n" - "diff --git a/mm/swapfile.c b/mm/swapfile.c\n" - "index 03aa2d5..a7baef1 100644\n" - "--- a/mm/swapfile.c\n" - "+++ b/mm/swapfile.c\n" - "@@ -1353,6 +1353,14 @@ static void destroy_swap_extents(struct swap_info_struct *sis)\n" - " \t\tlist_del(&se->list);\n" - " \t\tkfree(se);\n" - " \t}\n" - "+\n" - "+\tif (sis->flags & SWP_FILE) {\n" - "+\t\tstruct file *swap_file = sis->swap_file;\n" - "+\t\tstruct address_space *mapping = swap_file->f_mapping;\n" - "+\n" - "+\t\tsis->flags &= ~SWP_FILE;\n" - "+\t\tmapping->a_ops->swapoff(swap_file);\n" - "+\t}\n" - " }\n" - " \n" - " /*\n" - "@@ -1434,7 +1442,9 @@ add_swap_extent(struct swap_info_struct *sis, unsigned long start_page,\n" - " */\n" - " static int setup_swap_extents(struct swap_info_struct *sis, sector_t *span)\n" - " {\n" - "-\tstruct inode *inode;\n" - "+\tstruct file *swap_file = sis->swap_file;\n" - "+\tstruct address_space *mapping = swap_file->f_mapping;\n" - "+\tstruct inode *inode = mapping->host;\n" - " \tunsigned blocks_per_page;\n" - " \tunsigned long page_no;\n" - " \tunsigned blkbits;\n" - "@@ -1445,13 +1455,22 @@ static int setup_swap_extents(struct swap_info_struct *sis, sector_t *span)\n" - " \tint nr_extents = 0;\n" - " \tint ret;\n" - " \n" - "-\tinode = sis->swap_file->f_mapping->host;\n" - " \tif (S_ISBLK(inode->i_mode)) {\n" - " \t\tret = add_swap_extent(sis, 0, sis->max, 0);\n" - " \t\t*span = sis->pages;\n" - " \t\tgoto out;\n" - " \t}\n" - " \n" - "+\tif (mapping->a_ops->swapon) {\n" - "+\t\tret = mapping->a_ops->swapon(swap_file);\n" - "+\t\tif (!ret) {\n" - "+\t\t\tsis->flags |= SWP_FILE;\n" - "+\t\t\tret = add_swap_extent(sis, 0, sis->max, 0);\n" - "+\t\t\t*span = sis->pages;\n" - "+\t\t}\n" - "+\t\tgoto out;\n" - "+\t}\n" - "+\n" - " \tblkbits = inode->i_blkbits;\n" - " \tblocks_per_page = PAGE_SIZE >> blkbits;\n" - " \n" - "@@ -2228,6 +2247,19 @@ int swapcache_prepare(swp_entry_t entry)\n" - " \treturn __swap_duplicate(entry, SWAP_HAS_CACHE);\n" - " }\n" - " \n" - "+struct swap_info_struct *page_swap_info(struct page *page)\n" - "+{\n" - "+\tswp_entry_t swap = { .val = page_private(page) };\n" - "+\tif (!PageSwapCache(page) || !swap.val) {\n" - "+\t\t/* This should only happen from sync_page.\n" - "+\t\t * In other cases the page should be locked and\n" - "+\t\t * should be in a SwapCache\n" - "+\t\t */\n" - "+\t\treturn NULL;\n" - "+\t}\n" - "+\treturn swap_info[swp_type(swap)];\n" - "+}\n" - "+\n" - " /*\n" - " * swap_lock prevents swap_map being freed. Don't grab an extra\n" - " * reference on the swaphandle, it doesn't matter if it becomes unused.\n" - "-- \n" - "1.7.1.1\n" - "\n" - "--\n" - "To unsubscribe, send a message with 'unsubscribe linux-mm' in\n" - "the body to majordomo@kvack.org. For more info on Linux MM,\n" - "see: http://www.linux-mm.org/ .\n" - "Don't email: <a href=mailto:\"dont@kvack.org\"> email@kvack.org </a>" -b5df0efdce83ae2928e5fcff3156274a98e01d3adc6668cd9eae85d903fcd4f8 +8739668466f6a2d5335d76da776c1a4f8ec5742290e9c2b4aa7aa12a6aa44ea3
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.