mm: Refactor find_get_pages() & friends
Subsystems (3)
PATCH 1/1 mm: Refactor find_get_pages() & friends
Collapse redundant implementations of various gang pagecache lookup - this is also prep work for pagecache iterator work
--- include/linux/pagemap.h | 142 +++++++++++++++++-- include/linux/radix-tree.h | 49 ++----- mm/filemap.c | 331 +++++---------------------------------------- 3 files changed, 174 insertions(+), 348 deletions(-)
include/linux/pagemap.h +130 -12
@@ -352,18 +352,136 @@ static inline struct page *grab_cache_page_nowait(struct address_space *mapping,struct page *find_get_entry (struct address_space *mapping,pgoff_t offset);struct page *find_lock_entry (struct address_space *mapping,pgoff_t offset); -unsigned find_get_entries (struct address_space *mapping,pgoff_t start, -unsigned int nr_entries,struct page **entries, -pgoff_t *indices); -unsigned find_get_pages (struct address_space *mapping,pgoff_t start, -unsigned int nr_pages,struct page **pages); -unsigned find_get_pages_contig (struct address_space *mapping,pgoff_t start, -unsigned int nr_pages,struct page **pages); -unsigned find_get_pages_tag (struct address_space *mapping,pgoff_t *index, -int tag,unsigned int nr_pages,struct page **pages); -unsigned find_get_entries_tag (struct address_space *mapping,pgoff_t start, -int tag,unsigned int nr_entries, -struct page **entries,pgoff_t *indices); + +unsigned __find_get_pages (struct address_space *mapping, +pgoff_t start,pgoff_t end, +unsigned nr_entries,struct page **entries, +pgoff_t *indices,unsigned flags); + +/** +* find_get_entries - gang pagecache lookup +* @mapping: The address_space to search +* @start: The starting page cache index +* @nr_entries: The maximum number of entries +* @entries: Where the resulting entries are placed +* @indices: The cache indices corresponding to the entries in @entries +* +* find_get_entries() will search for and return a group of up to +* @nr_entries entries in the mapping. The entries are placed at +* @entries. find_get_entries() takes a reference against any actual +* pages it returns. +* +* The search returns a group of mapping-contiguous page cache entries +* with ascending indexes. There may be holes in the indices due to +* not-present pages. +* +* Any shadow entries of evicted pages, or swap entries from +* shmem/tmpfs, are included in the returned array. +* +* find_get_entries() returns the number of pages and shadow entries +* which were found. +*/ +static inline unsigned find_get_entries (struct address_space *mapping, +pgoff_t start,unsigned nr_entries, +struct page **entries,pgoff_t *indices) +{ +return __find_get_pages (mapping, start,ULONG_MAX , + nr_entries, entries, indices, +RADIX_TREE_ITER_EXCEPTIONAL ); +} + +/** +* find_get_pages - gang pagecache lookup +* @mapping: The address_space to search +* @start: The starting page index +* @nr_pages: The maximum number of pages +* @pages: Where the resulting pages are placed +* +* find_get_pages() will search for and return a group of up to +* @nr_pages pages in the mapping. The pages are placed at @pages. +* find_get_pages() takes a reference against the returned pages. +* +* The search returns a group of mapping-contiguous pages with ascending +* indexes. There may be holes in the indices due to not-present pages. +* +* find_get_pages() returns the number of pages which were found. +*/ +static inline unsigned find_get_pages (struct address_space *mapping, +pgoff_t start,unsigned nr_pages, +struct page **pages) +{ +return __find_get_pages (mapping, start,ULONG_MAX , + nr_pages, pages,NULL ,0 ); +} + +/** +* find_get_pages_contig - gang contiguous pagecache lookup +* @mapping: The address_space to search +* @start: The starting page index +* @nr_pages: The maximum number of pages +* @pages: Where the resulting pages are placed +* +* find_get_pages_contig() works exactly like find_get_pages(), except +* that the returned number of pages are guaranteed to be contiguous. +* +* find_get_pages_contig() returns the number of pages which were found. +*/ +static inline unsigned find_get_pages_contig (struct address_space *mapping, +pgoff_t start,unsigned nr_pages, +struct page **pages) +{ +return __find_get_pages (mapping, start,ULONG_MAX , + nr_pages, pages,NULL , +RADIX_TREE_ITER_CONTIG ); +} + +/** +* find_get_pages_tag - find and return pages that match @tag +* @mapping: the address_space to search +* @index: the starting page index +* @tag: the tag index +* @nr_pages: the maximum number of pages +* @pages: where the resulting pages are placed +* +* Like find_get_pages, except we only return pages which are tagged with +* @tag. We update @index to index the next page for the traversal. +*/ +static inline unsigned find_get_pages_tag (struct address_space *mapping, +pgoff_t *index,int tag, +unsigned nr_pages,struct page **pages) +{ +unsigned ret; + + ret =__find_get_pages (mapping, *index,ULONG_MAX , + nr_pages, pages,NULL , +RADIX_TREE_ITER_TAGGED |tag); +if (ret) + *index = pages[ret -1 ]->index +1 ; + +return ret; +} + +/** +* find_get_entries_tag - find and return entries that match @tag +* @mapping: the address_space to search +* @start: the starting page cache index +* @tag: the tag index +* @nr_entries: the maximum number of entries +* @entries: where the resulting entries are placed +* @indices: the cache indices corresponding to the entries in @entries +* +* Like find_get_entries, except we only return entries which are tagged with +* @tag. +*/ +static inline unsigned find_get_entries_tag (struct address_space *mapping, +pgoff_t start,int tag,unsigned nr_entries, +struct page **entries,pgoff_t *indices) +{ +return __find_get_pages (mapping, start,ULONG_MAX , + nr_entries, entries, indices, +RADIX_TREE_ITER_EXCEPTIONAL | +RADIX_TREE_ITER_TAGGED |tag); +}struct page *grab_cache_page_write_begin (struct address_space *mapping,pgoff_t index,unsigned flags);
include/linux/radix-tree.h +10 -39
79 lines not on this page · raw message
mm/filemap.c +34 -297
389 lines not on this page · raw message
Signature · 7 lines
2.7.0 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Andrew Morton
maintainerQuoted 2 lines · On Tue, 8 Mar 2016 16:16:43 -0900 Kent Overstreet <[email protected]>…
Collapse redundant implementations of various gang pagecache lookup - this is also prep work for pagecache iterator work
Patch looks nice. Unfortunately filemap.c has changed rather a lot since 4.5. Can you please redo the patch some time?
And a more informative changelog would be appropriate, although it's all pretty obvious. I don't know what "pagecache iterator work" is and I doubt if many other readers do either, so some illumination there wouldn't hurt.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 5 lines · Andrew Morton
Quoted 2 lines · On Tue, 8 Mar 2016 16:16:43 -0900 Kent Overstreet <[email protected]>…
Collapse redundant implementations of various gang pagecache lookup - this is also prep work for pagecache iterator work
Quoted 7 lines
Patch looks nice. Unfortunately
filemap.chas changed rather a lot since 4.5. Can you please redo the patch some time?And a more informative changelog would be appropriate, although it's all pretty obvious. I don't know what "pagecache iterator work" is and I doubt if many other readers do either, so some illumination there wouldn't hurt.
Can do - sending you the pagecache iterator patch too:
Kent Overstreet (2):
mm: Refactor find_get_pages() & friends
mm: Real pagecache iterators
fs/ext4/inode.c | 261 +++++++++++++------------------ include/linux/pagemap.h | 142 +++++++++++++++-- include/linux/pagevec.h | 67 +++++++- include/linux/radix-tree.h | 49 ++---- mm/filemap.c | 376 ++++++++++----------------------------------- mm/page-writeback.c | 148 ++++++++---------- mm/swap.c | 33 +--- mm/truncate.c | 259 ++++++++++++------------------- 8 files changed, 546 insertions(+), 789 deletions(-)
Signature · 7 lines
2.8.0.rc3 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 1/2 mm: Refactor find_get_pages() & friends
Collapse redundant implementations of various gang pagecache lookup - this is also prep work for pagecache iterators, in the next patch. This gives us a single common interface (__find_get_pages()) that the pagecache iterator will make use of.
--- include/linux/pagemap.h | 142 ++++++++++++++++++-- include/linux/radix-tree.h | 49 ++----- mm/filemap.c | 316 +++++---------------------------------------- 3 files changed, 174 insertions(+), 333 deletions(-)
include/linux/pagemap.h +130 -12
@@ -339,18 +339,136 @@ static inline struct page *grab_cache_page_nowait(struct address_space *mapping,struct page *find_get_entry (struct address_space *mapping,pgoff_t offset);struct page *find_lock_entry (struct address_space *mapping,pgoff_t offset); -unsigned find_get_entries (struct address_space *mapping,pgoff_t start, -unsigned int nr_entries,struct page **entries, -pgoff_t *indices); -unsigned find_get_pages (struct address_space *mapping,pgoff_t start, -unsigned int nr_pages,struct page **pages); -unsigned find_get_pages_contig (struct address_space *mapping,pgoff_t start, -unsigned int nr_pages,struct page **pages); -unsigned find_get_pages_tag (struct address_space *mapping,pgoff_t *index, -int tag,unsigned int nr_pages,struct page **pages); -unsigned find_get_entries_tag (struct address_space *mapping,pgoff_t start, -int tag,unsigned int nr_entries, -struct page **entries,pgoff_t *indices); + +unsigned __find_get_pages (struct address_space *mapping, +pgoff_t start,pgoff_t end, +unsigned nr_entries,struct page **entries, +pgoff_t *indices,unsigned flags); + +/** +* find_get_entries - gang pagecache lookup +* @mapping: The address_space to search +* @start: The starting page cache index +* @nr_entries: The maximum number of entries +* @entries: Where the resulting entries are placed +* @indices: The cache indices corresponding to the entries in @entries +* +* find_get_entries() will search for and return a group of up to +* @nr_entries entries in the mapping. The entries are placed at +* @entries. find_get_entries() takes a reference against any actual +* pages it returns. +* +* The search returns a group of mapping-contiguous page cache entries +* with ascending indexes. There may be holes in the indices due to +* not-present pages. +* +* Any shadow entries of evicted pages, or swap entries from +* shmem/tmpfs, are included in the returned array. +* +* find_get_entries() returns the number of pages and shadow entries +* which were found. +*/ +static inline unsigned find_get_entries (struct address_space *mapping, +pgoff_t start,unsigned nr_entries, +struct page **entries,pgoff_t *indices) +{ +return __find_get_pages (mapping, start,ULONG_MAX , + nr_entries, entries, indices, +RADIX_TREE_ITER_EXCEPTIONAL ); +} + +/** +* find_get_pages - gang pagecache lookup +* @mapping: The address_space to search +* @start: The starting page index +* @nr_pages: The maximum number of pages +* @pages: Where the resulting pages are placed +* +* find_get_pages() will search for and return a group of up to +* @nr_pages pages in the mapping. The pages are placed at @pages. +* find_get_pages() takes a reference against the returned pages. +* +* The search returns a group of mapping-contiguous pages with ascending +* indexes. There may be holes in the indices due to not-present pages. +* +* find_get_pages() returns the number of pages which were found. +*/ +static inline unsigned find_get_pages (struct address_space *mapping, +pgoff_t start,unsigned nr_pages, +struct page **pages) +{ +return __find_get_pages (mapping, start,ULONG_MAX , + nr_pages, pages,NULL ,0 ); +} + +/** +* find_get_pages_contig - gang contiguous pagecache lookup +* @mapping: The address_space to search +* @start: The starting page index +* @nr_pages: The maximum number of pages +* @pages: Where the resulting pages are placed +* +* find_get_pages_contig() works exactly like find_get_pages(), except +* that the returned number of pages are guaranteed to be contiguous. +* +* find_get_pages_contig() returns the number of pages which were found. +*/ +static inline unsigned find_get_pages_contig (struct address_space *mapping, +pgoff_t start,unsigned nr_pages, +struct page **pages) +{ +return __find_get_pages (mapping, start,ULONG_MAX , + nr_pages, pages,NULL , +RADIX_TREE_ITER_CONTIG ); +} + +/** +* find_get_pages_tag - find and return pages that match @tag +* @mapping: the address_space to search +* @index: the starting page index +* @tag: the tag index +* @nr_pages: the maximum number of pages +* @pages: where the resulting pages are placed +* +* Like find_get_pages, except we only return pages which are tagged with +* @tag. We update @index to index the next page for the traversal. +*/ +static inline unsigned find_get_pages_tag (struct address_space *mapping, +pgoff_t *index,int tag, +unsigned nr_pages,struct page **pages) +{ +unsigned ret; + + ret =__find_get_pages (mapping, *index,ULONG_MAX , + nr_pages, pages,NULL , +RADIX_TREE_ITER_TAGGED |tag); +if (ret) + *index = pages[ret -1 ]->index +1 ; + +return ret; +} + +/** +* find_get_entries_tag - find and return entries that match @tag +* @mapping: the address_space to search +* @start: the starting page cache index +* @tag: the tag index +* @nr_entries: the maximum number of entries +* @entries: where the resulting entries are placed +* @indices: the cache indices corresponding to the entries in @entries +* +* Like find_get_entries, except we only return entries which are tagged with +* @tag. +*/ +static inline unsigned find_get_entries_tag (struct address_space *mapping, +pgoff_t start,int tag,unsigned nr_entries, +struct page **entries,pgoff_t *indices) +{ +return __find_get_pages (mapping, start,ULONG_MAX , + nr_entries, entries, indices, +RADIX_TREE_ITER_EXCEPTIONAL | +RADIX_TREE_ITER_TAGGED |tag); +}struct page *grab_cache_page_write_begin (struct address_space *mapping,pgoff_t index,unsigned flags);
include/linux/radix-tree.h +10 -39
79 lines not on this page · raw message
mm/filemap.c +34 -282
371 lines not on this page · raw message
Signature · 7 lines
2.8.0.rc3 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 2/2 mm: Real pagecache iterators
Introduce for_each_pagecache_page() and related macros, with the goal of replacing most/all uses of pagevec_lookup().
For the most part this shouldn't be a functional change. The one functional difference with the new macros is that they now take an @end parameter, so we're able to avoid grabbing pages in __find_get_pages() that we'll never use.
This patch only does some of the conversions, the ones I was able to easily test myself - the conversions are mechanical but tricky enough they generally warrent testing.
--- fs/ext4/inode.c | 261 ++++++++++++++++++++---------------------------- include/linux/pagevec.h | 67 ++++++++++++- mm/filemap.c | 76 +++++++++----- mm/page-writeback.c | 148 +++++++++++---------------- mm/swap.c | 33 +----- mm/truncate.c | 259 +++++++++++++++++------------------------------ 6 files changed, 380 insertions(+), 464 deletions(-)
fs/ext4/inode.c +106 -155
@@ -1605,11 +1605,10 @@ struct mpage_da_data {static void mpage_release_unused_pages (struct mpage_da_data *mpd,bool invalidate) { -int nr_pages, i;pgoff_t index, end; -struct pagevec pvec; +struct pagecache_iter iter; +struct page *page;struct inode *inode = mpd->inode; -struct address_space *mapping = inode->i_mapping;/* This is necessary when next_page == 0. */ if (mpd->first_page >= mpd->next_page)
@@ -1624,25 +1623,14 @@ static void mpage_release_unused_pages(struct mpage_da_data *mpd,ext4_es_remove_extent (inode, start, last - start +1 ); } -pagevec_init (&pvec,0 ); -while (index <= end) { - nr_pages =pagevec_lookup (&pvec, mapping, index,PAGEVEC_SIZE ); -if (nr_pages ==0 ) -break ; -for (i =0 ; i < nr_pages; i++) { -struct page *page = pvec.pages[i]; -if (page->index > end) -break ; -BUG_ON (!PageLocked (page)); -BUG_ON (PageWriteback (page)); -if (invalidate) { -block_invalidatepage (page,0 ,PAGE_CACHE_SIZE ); -ClearPageUptodate (page); - } -unlock_page (page); +for_each_pagecache_page (&iter, inode->i_mapping, index, end, page) { +BUG_ON (!PageLocked (page)); +BUG_ON (PageWriteback (page)); +if (invalidate) { +block_invalidatepage (page,0 ,PAGE_CACHE_SIZE ); +ClearPageUptodate (page); } - index = pvec.pages[nr_pages -1 ]->index +1 ; -pagevec_release (&pvec); +unlock_page (page); } }
@@ -2209,8 +2197,8 @@ static int mpage_process_page_bufs(struct mpage_da_data *mpd,*/ static int mpage_map_and_submit_buffers (struct mpage_da_data *mpd) { -struct pagevec pvec; -int nr_pages, i; +struct pagecache_iter iter; +struct page *page;struct inode *inode = mpd->inode;struct buffer_head *head, *bh;int bpp_bits =PAGE_CACHE_SHIFT - inode->i_blkbits;
@@ -2224,67 +2212,55 @@ static int mpage_map_and_submit_buffers(struct mpage_da_data *mpd) lblk = start << bpp_bits; pblock = mpd->map.m_pblk; -pagevec_init (&pvec,0 ); -while (start <= end) { - nr_pages =pagevec_lookup (&pvec, inode->i_mapping, start, -PAGEVEC_SIZE ); -if (nr_pages ==0 ) -break ; -for (i =0 ; i < nr_pages; i++) { -struct page *page = pvec.pages[i]; - -if (page->index > end) -break ; -/* Up to 'end' pages must be contiguous */ -BUG_ON (page->index != start); - bh = head =page_buffers (page); -do { -if (lblk < mpd->map.m_lblk) -continue ; -if (lblk >= mpd->map.m_lblk + mpd->map.m_len) { -/* -* Buffer after end of mapped extent. -* Find next buffer in the page to map. -*/ - mpd->map.m_len =0 ; - mpd->map.m_flags =0 ; -/* -* FIXME: If dioread_nolock supports -* blocksize < pagesize, we need to make -* sure we add size mapped so far to -* io_end->size as the following call -* can submit the page for IO. -*/ - err =mpage_process_page_bufs (mpd, head, - bh, lblk); -pagevec_release (&pvec); -if (err >0 ) - err =0 ; -return err; - } -if (buffer_delay (bh)) { -clear_buffer_delay (bh); - bh->b_blocknr = pblock++; - } -clear_buffer_unwritten (bh); - }while (lblk++, (bh = bh->b_this_page) != head); - -/* -* FIXME: This is going to break if dioread_nolock -* supports blocksize < pagesize as we will try to -* convert potentially unmapped parts of inode. -*/ - mpd->io_submit.io_end->size +=PAGE_CACHE_SIZE ; -/* Page fully mapped - let IO run! */ - err =mpage_submit_page (mpd, page); -if (err <0 ) { -pagevec_release (&pvec); +for_each_pagecache_page (&iter, inode->i_mapping, start, end, page) { +/* Up to 'end' pages must be contiguous */ +BUG_ON (page->index != start); + bh = head =page_buffers (page); +do { +if (lblk < mpd->map.m_lblk) +continue ; +if (lblk >= mpd->map.m_lblk + mpd->map.m_len) { +/* +* Buffer after end of mapped extent. Find next +* buffer in the page to map. +*/ + mpd->map.m_len =0 ; + mpd->map.m_flags =0 ; +/* +* FIXME: If dioread_nolock supports blocksize < +* pagesize, we need to make sure we add size +* mapped so far to io_end->size as the +* following call can submit the page for IO. +*/ + err =mpage_process_page_bufs (mpd, head, + bh, lblk); +pagecache_iter_release (&iter); +if (err >0 ) + err =0 ;return err; } - start++; +if (buffer_delay (bh)) { +clear_buffer_delay (bh); + bh->b_blocknr = pblock++; + } +clear_buffer_unwritten (bh); + }while (lblk++, (bh = bh->b_this_page) != head); + +/* +* FIXME: This is going to break if dioread_nolock supports +* blocksize < pagesize as we will try to convert potentially +* unmapped parts of inode. +*/ + mpd->io_submit.io_end->size +=PAGE_CACHE_SIZE ; +/* Page fully mapped - let IO run! */ + err =mpage_submit_page (mpd, page); +if (err <0 ) { +pagecache_iter_release (&iter); +return err; } -pagevec_release (&pvec); + start++; } +/* Extent fully mapped and matches with page boundary. We are done. */ mpd->map.m_len =0 ; mpd->map.m_flags =0 ;
@@ -2485,13 +2461,10 @@ static int ext4_da_writepages_trans_blocks(struct inode *inode)static int mpage_prepare_extent_to_map (struct mpage_da_data *mpd) {struct address_space *mapping = mpd->inode->i_mapping; -struct pagevec pvec; -unsigned int nr_pages; +struct pagecache_iter iter; +struct page *page;long left = mpd->wbc->nr_to_write; -pgoff_t index = mpd->first_page; -pgoff_t end = mpd->last_page; -int tag; -int i, err =0 ; +int tag, err =0 ;int blkbits = mpd->inode->i_blkbits;ext4_lblk_t lblk;struct buffer_head *head;
@@ -2501,81 +2474,59 @@ static int mpage_prepare_extent_to_map(struct mpage_da_data *mpd)else tag =PAGECACHE_TAG_DIRTY ; -pagevec_init (&pvec,0 ); mpd->map.m_len =0 ; - mpd->next_page = index; -while (index <= end) { - nr_pages =pagevec_lookup_tag (&pvec, mapping, &index, tag, -min (end - index, (pgoff_t )PAGEVEC_SIZE -1 ) +1 ); -if (nr_pages ==0 ) - goto out; - -for (i =0 ; i < nr_pages; i++) { -struct page *page = pvec.pages[i]; + mpd->next_page = mpd->first_page; -/* -* At this point, the page may be truncated or -* invalidated (changing page->mapping to NULL), or -* even swizzled back from swapper_space to tmpfs file -* mapping. However, page->index will not change -* because we have a reference on the page. -*/ -if (page->index > end) - goto out; - -/* -* Accumulated enough dirty pages? This doesn't apply -* to WB_SYNC_ALL mode. For integrity sync we have to -* keep going because someone may be concurrently -* dirtying pages, and we might have synced a lot of -* newly appeared dirty pages, but have not synced all -* of the old dirty pages. -*/ -if (mpd->wbc->sync_mode ==WB_SYNC_NONE && left <=0 ) - goto out; - -/* If we can't merge this page, we are done. */ -if (mpd->map.m_len >0 && mpd->next_page != page->index) - goto out; +for_each_pagecache_tag (&iter, mapping, tag, mpd->first_page, + mpd->last_page, page) { +/* +* Accumulated enough dirty pages? This doesn't apply to +* WB_SYNC_ALL mode. For integrity sync we have to keep going +* because someone may be concurrently dirtying pages, and we +* might have synced a lot of newly appeared dirty pages, but +* have not synced all of the old dirty pages. +*/ +if (mpd->wbc->sync_mode ==WB_SYNC_NONE && left <=0 ) +break ; -lock_page (page); -/* -* If the page is no longer dirty, or its mapping no -* longer corresponds to inode we are writing (which -* means it has been truncated or invalidated), or the -* page is already under writeback and we are not doing -* a data integrity writeback, skip the page -*/ -if (!PageDirty (page) || - (PageWriteback (page) && - (mpd->wbc->sync_mode ==WB_SYNC_NONE )) || -unlikely (page->mapping != mapping)) { -unlock_page (page); -continue ; - } +/* If we can't merge this page, we are done. */ +if (mpd->map.m_len >0 && mpd->next_page != page->index) +break ; -wait_on_page_writeback (page); -BUG_ON (PageWriteback (page)); - -if (mpd->map.m_len ==0 ) - mpd->first_page = page->index; - mpd->next_page = page->index +1 ; -/* Add all dirty buffers to mpd */ - lblk = ((ext4_lblk_t )page->index) << - (PAGE_CACHE_SHIFT - blkbits); - head =page_buffers (page); - err =mpage_process_page_bufs (mpd, head, head, lblk); -if (err <=0 ) - goto out; - err =0 ; - left--; +lock_page (page); +/* +* If the page is no longer dirty, or its mapping no longer +* corresponds to inode we are writing (which means it has been +* truncated or invalidated), or the page is already under +* writeback and we are not doing a data integrity writeback, +* skip the page +*/ +if (!PageDirty (page) || + (PageWriteback (page) && + (mpd->wbc->sync_mode ==WB_SYNC_NONE )) || +unlikely (page->mapping != mapping)) { +unlock_page (page); +continue ; } -pagevec_release (&pvec); -cond_resched (); + +wait_on_page_writeback (page); +BUG_ON (PageWriteback (page)); + +if (mpd->map.m_len ==0 ) + mpd->first_page = page->index; + mpd->next_page = page->index +1 ; +/* Add all dirty buffers to mpd */ + lblk = ((ext4_lblk_t )page->index) << + (PAGE_CACHE_SHIFT - blkbits); + head =page_buffers (page); + err =mpage_process_page_bufs (mpd, head, head, lblk); +if (err <=0 ) +break ; + err =0 ; + left--; } -return 0 ; -out: -pagevec_release (&pvec); +pagecache_iter_release (&iter); +return err; }
include/linux/pagevec.h +63 -4
77 lines not on this page · raw message
mm/filemap.c +53 -23
94 lines not on this page · raw message
mm/page-writeback.c +61 -87
183 lines not on this page · raw message
mm/swap.c +3 -30
@@ -718,6 +718,9 @@ void release_pages(struct page **pages, int nr, bool cold)for (i =0 ; i < nr; i++) {struct page *page = pages[i]; +if (radix_tree_exceptional_entry (page)) +continue ; +/* * Make sure the IRQ-safe lock-holding time does not get * excessive with a continuous string of pages from the
@@ -857,36 +860,6 @@ void __pagevec_lru_add(struct pagevec *pvec)EXPORT_SYMBOL (__pagevec_lru_add);/** -* pagevec_lookup_entries - gang pagecache lookup -* @pvec: Where the resulting entries are placed -* @mapping: The address_space to search -* @start: The starting entry index -* @nr_entries: The maximum number of entries -* @indices: The cache indices corresponding to the entries in @pvec -* -* pagevec_lookup_entries() will search for and return a group of up -* to @nr_entries pages and shadow entries in the mapping. All -* entries are placed in @pvec. pagevec_lookup_entries() takes a -* reference against actual pages in @pvec. -* -* The search returns a group of mapping-contiguous entries with -* ascending indexes. There may be holes in the indices due to -* not-present entries. -* -* pagevec_lookup_entries() returns the number of entries which were -* found. -*/ -unsigned pagevec_lookup_entries (struct pagevec *pvec, -struct address_space *mapping, -pgoff_t start,unsigned nr_pages, -pgoff_t *indices) -{ - pvec->nr =find_get_entries (mapping, start, nr_pages, - pvec->pages, indices); -return pagevec_count (pvec); -} - -/** * pagevec_remove_exceptionals - pagevec exceptionals pruning * @pvec: The pagevec to prune *
mm/truncate.c +94 -165
322 lines not on this page · raw message
Signature · 7 lines
2.8.0.rc3 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Andrew Morton
maintainerRe: [PATCH 2/2] mm: Real pagecache iterators
Quoted 10 lines · On Thu, 31 Mar 2016 18:38:11 -0800 Kent Overstreet <[email protected]>…
Introduce
for_each_pagecache_page()and related macros, with the goal of replacing most/all uses ofpagevec_lookup().For the most part this shouldn't be a functional change. The one functional difference with the new macros is that they now take an @end parameter, so we're able to avoid grabbing pages in
__find_get_pages()that we'll never use.This patch only does some of the conversions, the ones I was able to easily test myself - the conversions are mechanical but tricky enough they generally warrent testing.
What is the reason for this change?
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH 2/2] mm: Real pagecache iterators
Quoted 9 lines · Andrew Morton
Quoted 7 lines · On Thu, 31 Mar 2016 18:38:11 -0800 Kent Overstreet <[email protected]>…
Introduce
for_each_pagecache_page()and related macros, with the goal of replacing most/all uses ofpagevec_lookup().For the most part this shouldn't be a functional change. The one functional difference with the new macros is that they now take an @end parameter, so we're able to avoid grabbing pages in
__find_get_pages()that we'll never use.
Quoted 5 lines
Quoted 3 lines
This patch only does some of the conversions, the ones I was able to easily test myself - the conversions are mechanical but tricky enough they generally warrent testing.
What is the reason for this change?
I just got tired of code being hard to follow when I was trying to work on some pagecache invalidation stuff.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Andrew Morton
maintainerRe: [PATCH 2/2] mm: Real pagecache iterators
In reply to Kent OverstreetQuoted 14 lines · On Thu, 31 Mar 2016 18:38:11 -0800 Kent Overstreet <[email protected]>…
Introduce
for_each_pagecache_page()and related macros, with the goal of replacing most/all uses ofpagevec_lookup().For the most part this shouldn't be a functional change. The one functional difference with the new macros is that they now take an @end parameter, so we're able to avoid grabbing pages in
__find_get_pages()that we'll never use.This patch only does some of the conversions, the ones I was able to easily test myself - the conversions are mechanical but tricky enough they generally warrent testing.
Signed-off-by Kent Overstreet <[email protected]>Cc Andrew Morton <[email protected]>Cc Al Viro <[email protected]>
Quoted 8 lines
--- fs/ext4/inode.c | 261 ++++++++++++++++++++---------------------------- include/linux/pagevec.h | 67 ++++++++++++- mm/filemap.c | 76 +++++++++----- mm/page-writeback.c | 148 +++++++++++---------------- mm/swap.c | 33 +----- mm/truncate.c | 259 +++++++++++++++++------------------------------ 6 files changed, 380 insertions(+), 464 deletions(-)
hm, it's a lot of churn in sensitive areas for an 80 line saving. What do others think?
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>