Commit 7e48ff82 authored by Pavel Shilovsky's avatar Pavel Shilovsky Committed by Steve French

CIFS: Separate page processing from writepages

Signed-off-by: default avatarPavel Shilovsky <pshilovsky@samba.org>
Reviewed-by: default avatarJeff Layton <jlayton@samba.org>
Signed-off-by: default avatarSteve French <smfrench@gmail.com>
parent 038bc961
......@@ -1878,73 +1878,15 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
return rc;
}
static int cifs_writepages(struct address_space *mapping,
struct writeback_control *wbc)
static unsigned int
wdata_prepare_pages(struct cifs_writedata *wdata, unsigned int found_pages,
struct address_space *mapping,
struct writeback_control *wbc,
pgoff_t end, pgoff_t *index, pgoff_t *next, bool *done)
{
struct cifs_sb_info *cifs_sb = CIFS_SB(mapping->host->i_sb);
bool done = false, scanned = false, range_whole = false;
pgoff_t end, index;
struct cifs_writedata *wdata;
struct TCP_Server_Info *server;
unsigned int nr_pages = 0, i;
struct page *page;
int rc = 0;
/*
* If wsize is smaller than the page cache size, default to writing
* one page at a time via cifs_writepage
*/
if (cifs_sb->wsize < PAGE_CACHE_SIZE)
return generic_writepages(mapping, wbc);
if (wbc->range_cyclic) {
index = mapping->writeback_index; /* Start from prev offset */
end = -1;
} else {
index = wbc->range_start >> PAGE_CACHE_SHIFT;
end = wbc->range_end >> PAGE_CACHE_SHIFT;
if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
range_whole = true;
scanned = true;
}
retry:
while (!done && index <= end) {
unsigned int i, nr_pages, found_pages;
pgoff_t next = 0, tofind;
struct page **pages;
tofind = min((cifs_sb->wsize / PAGE_CACHE_SIZE) - 1,
end - index) + 1;
wdata = cifs_writedata_alloc((unsigned int)tofind,
cifs_writev_complete);
if (!wdata) {
rc = -ENOMEM;
break;
}
/*
* find_get_pages_tag seems to return a max of 256 on each
* iteration, so we must call it several times in order to
* fill the array or the wsize is effectively limited to
* 256 * PAGE_CACHE_SIZE.
*/
found_pages = 0;
pages = wdata->pages;
do {
nr_pages = find_get_pages_tag(mapping, &index,
PAGECACHE_TAG_DIRTY,
tofind, pages);
found_pages += nr_pages;
tofind -= nr_pages;
pages += nr_pages;
} while (nr_pages && tofind && index <= end);
if (found_pages == 0) {
kref_put(&wdata->refcount, cifs_writedata_release);
break;
}
nr_pages = 0;
for (i = 0; i < found_pages; i++) {
page = wdata->pages[i];
/*
......@@ -1966,12 +1908,12 @@ static int cifs_writepages(struct address_space *mapping,
}
if (!wbc->range_cyclic && page->index > end) {
done = true;
*done = true;
unlock_page(page);
break;
}
if (next && (page->index != next)) {
if (*next && (page->index != *next)) {
/* Not next consecutive page */
unlock_page(page);
break;
......@@ -1991,22 +1933,21 @@ static int cifs_writepages(struct address_space *mapping,
* See cifs_writepage() for more commentary.
*/
set_page_writeback(page);
if (page_offset(page) >= i_size_read(mapping->host)) {
done = true;
*done = true;
unlock_page(page);
end_page_writeback(page);
break;
}
wdata->pages[i] = page;
next = page->index + 1;
*next = page->index + 1;
++nr_pages;
}
/* reset index to refind any pages skipped */
if (nr_pages == 0)
index = wdata->pages[0]->index + 1;
*index = wdata->pages[0]->index + 1;
/* put any pages we aren't going to use */
for (i = nr_pages; i < found_pages; i++) {
......@@ -2014,6 +1955,77 @@ static int cifs_writepages(struct address_space *mapping,
wdata->pages[i] = NULL;
}
return nr_pages;
}
static int cifs_writepages(struct address_space *mapping,
struct writeback_control *wbc)
{
struct cifs_sb_info *cifs_sb = CIFS_SB(mapping->host->i_sb);
bool done = false, scanned = false, range_whole = false;
pgoff_t end, index;
struct cifs_writedata *wdata;
struct TCP_Server_Info *server;
int rc = 0;
/*
* If wsize is smaller than the page cache size, default to writing
* one page at a time via cifs_writepage
*/
if (cifs_sb->wsize < PAGE_CACHE_SIZE)
return generic_writepages(mapping, wbc);
if (wbc->range_cyclic) {
index = mapping->writeback_index; /* Start from prev offset */
end = -1;
} else {
index = wbc->range_start >> PAGE_CACHE_SHIFT;
end = wbc->range_end >> PAGE_CACHE_SHIFT;
if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
range_whole = true;
scanned = true;
}
retry:
while (!done && index <= end) {
unsigned int i, nr_pages, found_pages;
pgoff_t next = 0, tofind;
struct page **pages;
tofind = min((cifs_sb->wsize / PAGE_CACHE_SIZE) - 1,
end - index) + 1;
wdata = cifs_writedata_alloc((unsigned int)tofind,
cifs_writev_complete);
if (!wdata) {
rc = -ENOMEM;
break;
}
/*
* find_get_pages_tag seems to return a max of 256 on each
* iteration, so we must call it several times in order to
* fill the array or the wsize is effectively limited to
* 256 * PAGE_CACHE_SIZE.
*/
found_pages = 0;
pages = wdata->pages;
do {
nr_pages = find_get_pages_tag(mapping, &index,
PAGECACHE_TAG_DIRTY,
tofind, pages);
found_pages += nr_pages;
tofind -= nr_pages;
pages += nr_pages;
} while (nr_pages && tofind && index <= end);
if (found_pages == 0) {
kref_put(&wdata->refcount, cifs_writedata_release);
break;
}
nr_pages = wdata_prepare_pages(wdata, found_pages, mapping, wbc,
end, &index, &next, &done);
/* nothing to write? */
if (nr_pages == 0) {
kref_put(&wdata->refcount, cifs_writedata_release);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment