mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
CIFS: Separate page processing from writepages
Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org> Reviewed-by: Jeff Layton <jlayton@samba.org> Signed-off-by: Steve French <smfrench@gmail.com>
This commit is contained in:
parent
038bc961c3
commit
7e48ff8202
152
fs/cifs/file.c
152
fs/cifs/file.c
@ -1878,6 +1878,86 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
|
||||
return rc;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
unsigned int nr_pages = 0, i;
|
||||
struct page *page;
|
||||
|
||||
for (i = 0; i < found_pages; i++) {
|
||||
page = wdata->pages[i];
|
||||
/*
|
||||
* At this point we hold neither mapping->tree_lock nor
|
||||
* lock on the page itself: the page may be truncated or
|
||||
* invalidated (changing page->mapping to NULL), or even
|
||||
* swizzled back from swapper_space to tmpfs file
|
||||
* mapping
|
||||
*/
|
||||
|
||||
if (nr_pages == 0)
|
||||
lock_page(page);
|
||||
else if (!trylock_page(page))
|
||||
break;
|
||||
|
||||
if (unlikely(page->mapping != mapping)) {
|
||||
unlock_page(page);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!wbc->range_cyclic && page->index > end) {
|
||||
*done = true;
|
||||
unlock_page(page);
|
||||
break;
|
||||
}
|
||||
|
||||
if (*next && (page->index != *next)) {
|
||||
/* Not next consecutive page */
|
||||
unlock_page(page);
|
||||
break;
|
||||
}
|
||||
|
||||
if (wbc->sync_mode != WB_SYNC_NONE)
|
||||
wait_on_page_writeback(page);
|
||||
|
||||
if (PageWriteback(page) ||
|
||||
!clear_page_dirty_for_io(page)) {
|
||||
unlock_page(page);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* This actually clears the dirty bit in the radix tree.
|
||||
* See cifs_writepage() for more commentary.
|
||||
*/
|
||||
set_page_writeback(page);
|
||||
if (page_offset(page) >= i_size_read(mapping->host)) {
|
||||
*done = true;
|
||||
unlock_page(page);
|
||||
end_page_writeback(page);
|
||||
break;
|
||||
}
|
||||
|
||||
wdata->pages[i] = page;
|
||||
*next = page->index + 1;
|
||||
++nr_pages;
|
||||
}
|
||||
|
||||
/* reset index to refind any pages skipped */
|
||||
if (nr_pages == 0)
|
||||
*index = wdata->pages[0]->index + 1;
|
||||
|
||||
/* put any pages we aren't going to use */
|
||||
for (i = nr_pages; i < found_pages; i++) {
|
||||
page_cache_release(wdata->pages[i]);
|
||||
wdata->pages[i] = NULL;
|
||||
}
|
||||
|
||||
return nr_pages;
|
||||
}
|
||||
|
||||
static int cifs_writepages(struct address_space *mapping,
|
||||
struct writeback_control *wbc)
|
||||
{
|
||||
@ -1886,7 +1966,6 @@ static int cifs_writepages(struct address_space *mapping,
|
||||
pgoff_t end, index;
|
||||
struct cifs_writedata *wdata;
|
||||
struct TCP_Server_Info *server;
|
||||
struct page *page;
|
||||
int rc = 0;
|
||||
|
||||
/*
|
||||
@ -1944,75 +2023,8 @@ retry:
|
||||
break;
|
||||
}
|
||||
|
||||
nr_pages = 0;
|
||||
for (i = 0; i < found_pages; i++) {
|
||||
page = wdata->pages[i];
|
||||
/*
|
||||
* At this point we hold neither mapping->tree_lock nor
|
||||
* lock on the page itself: the page may be truncated or
|
||||
* invalidated (changing page->mapping to NULL), or even
|
||||
* swizzled back from swapper_space to tmpfs file
|
||||
* mapping
|
||||
*/
|
||||
|
||||
if (nr_pages == 0)
|
||||
lock_page(page);
|
||||
else if (!trylock_page(page))
|
||||
break;
|
||||
|
||||
if (unlikely(page->mapping != mapping)) {
|
||||
unlock_page(page);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!wbc->range_cyclic && page->index > end) {
|
||||
done = true;
|
||||
unlock_page(page);
|
||||
break;
|
||||
}
|
||||
|
||||
if (next && (page->index != next)) {
|
||||
/* Not next consecutive page */
|
||||
unlock_page(page);
|
||||
break;
|
||||
}
|
||||
|
||||
if (wbc->sync_mode != WB_SYNC_NONE)
|
||||
wait_on_page_writeback(page);
|
||||
|
||||
if (PageWriteback(page) ||
|
||||
!clear_page_dirty_for_io(page)) {
|
||||
unlock_page(page);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* This actually clears the dirty bit in the radix tree.
|
||||
* See cifs_writepage() for more commentary.
|
||||
*/
|
||||
set_page_writeback(page);
|
||||
|
||||
if (page_offset(page) >= i_size_read(mapping->host)) {
|
||||
done = true;
|
||||
unlock_page(page);
|
||||
end_page_writeback(page);
|
||||
break;
|
||||
}
|
||||
|
||||
wdata->pages[i] = page;
|
||||
next = page->index + 1;
|
||||
++nr_pages;
|
||||
}
|
||||
|
||||
/* reset index to refind any pages skipped */
|
||||
if (nr_pages == 0)
|
||||
index = wdata->pages[0]->index + 1;
|
||||
|
||||
/* put any pages we aren't going to use */
|
||||
for (i = nr_pages; i < found_pages; i++) {
|
||||
page_cache_release(wdata->pages[i]);
|
||||
wdata->pages[i] = NULL;
|
||||
}
|
||||
nr_pages = wdata_prepare_pages(wdata, found_pages, mapping, wbc,
|
||||
end, &index, &next, &done);
|
||||
|
||||
/* nothing to write? */
|
||||
if (nr_pages == 0) {
|
||||
|
Loading…
Reference in New Issue
Block a user