To prepare for multithreading the work to preserve a shmem file, divide the work into subranges of the total index range of the file. The chunk size is a rather arbitrary 256k indices. Signed-off-by: Anthony Yznaga <anthony.yznaga@xxxxxxxxxx> --- mm/shmem_pkram.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 57 insertions(+), 7 deletions(-) diff --git a/mm/shmem_pkram.c b/mm/shmem_pkram.c index 8682b0c002c0..e52722b3a709 100644 --- a/mm/shmem_pkram.c +++ b/mm/shmem_pkram.c @@ -74,16 +74,14 @@ static int save_page(struct page *page, struct pkram_access *pa) return err; } -static int save_file_content(struct pkram_stream *ps, struct address_space *mapping) +static int save_file_content_range(struct pkram_access *pa, + struct address_space *mapping, + unsigned long start, unsigned long end) { - PKRAM_ACCESS(pa, ps, pages); struct pagevec pvec; - unsigned long start, end; int err = 0; int i; - start = 0; - end = DIV_ROUND_UP(i_size_read(mapping->host), PAGE_SIZE); pagevec_init(&pvec); for ( ; ; ) { pvec.nr = find_get_pages_range(mapping, &start, end, @@ -95,7 +93,7 @@ static int save_file_content(struct pkram_stream *ps, struct address_space *mapp lock_page(page); BUG_ON(page->mapping != mapping); - err = save_page(page, &pa); + err = save_page(page, pa); if (PageCompound(page)) { start = page->index + compound_nr(page); i += compound_nr(page); @@ -113,10 +111,62 @@ static int save_file_content(struct pkram_stream *ps, struct address_space *mapp cond_resched(); } - pkram_finish_access(&pa, err == 0); return err; } +struct shmem_pkram_arg { + struct pkram_stream *ps; + struct address_space *mapping; + struct mm_struct *mm; + atomic64_t next; +}; + +unsigned long shmem_pkram_max_index_range = 512 * 512; + +static int get_save_range(unsigned long max, atomic64_t *next, unsigned long *start, unsigned long *end) +{ + unsigned long index; + + index = atomic64_fetch_add(shmem_pkram_max_index_range, next); + if (index >= max) + return -ENODATA; + + *start = index; + *end = index + shmem_pkram_max_index_range - 1; + + return 0; +} + +static int do_save_file_content(struct pkram_stream *ps, + struct address_space *mapping, + atomic64_t *next) +{ + PKRAM_ACCESS(pa, ps, pages); + unsigned long start, end, max; + int ret; + + max = DIV_ROUND_UP(i_size_read(mapping->host), PAGE_SIZE); + + do { + ret = get_save_range(max, next, &start, &end); + if (!ret) + ret = save_file_content_range(&pa, mapping, start, end); + } while (!ret); + + if (ret == -ENODATA) + ret = 0; + + pkram_finish_access(&pa, ret == 0); + return ret; +} + +static int save_file_content(struct pkram_stream *ps, struct address_space *mapping) +{ + struct shmem_pkram_arg arg = { ps, mapping, NULL, ATOMIC64_INIT(0) }; + + return do_save_file_content(arg.ps, arg.mapping, &arg.next); +} + static int save_file(struct dentry *dentry, struct pkram_stream *ps) { PKRAM_ACCESS(pa_bytes, ps, bytes); -- 1.8.3.1