CIFS: Fix error paths in writeback code
This patch aims to address writeback code problems related to error paths. In particular it respects EINTR and related error codes and stores and returns the first error occurred during writeback. Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com> Acked-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:

committed by
Steve French

parent
ee258d7915
commit
9a66396f18
@@ -733,7 +733,8 @@ reopen_success:
|
||||
|
||||
if (can_flush) {
|
||||
rc = filemap_write_and_wait(inode->i_mapping);
|
||||
mapping_set_error(inode->i_mapping, rc);
|
||||
if (!is_interrupt_error(rc))
|
||||
mapping_set_error(inode->i_mapping, rc);
|
||||
|
||||
if (tcon->unix_ext)
|
||||
rc = cifs_get_inode_info_unix(&inode, full_path,
|
||||
@@ -2118,6 +2119,7 @@ static int cifs_writepages(struct address_space *mapping,
|
||||
pgoff_t end, index;
|
||||
struct cifs_writedata *wdata;
|
||||
int rc = 0;
|
||||
int saved_rc = 0;
|
||||
unsigned int xid;
|
||||
|
||||
/*
|
||||
@@ -2146,8 +2148,10 @@ retry:
|
||||
|
||||
rc = server->ops->wait_mtu_credits(server, cifs_sb->wsize,
|
||||
&wsize, &credits);
|
||||
if (rc)
|
||||
if (rc != 0) {
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
|
||||
tofind = min((wsize / PAGE_SIZE) - 1, end - index) + 1;
|
||||
|
||||
@@ -2155,6 +2159,7 @@ retry:
|
||||
&found_pages);
|
||||
if (!wdata) {
|
||||
rc = -ENOMEM;
|
||||
done = true;
|
||||
add_credits_and_wake_if(server, credits, 0);
|
||||
break;
|
||||
}
|
||||
@@ -2183,7 +2188,7 @@ retry:
|
||||
if (rc != 0) {
|
||||
add_credits_and_wake_if(server, wdata->credits, 0);
|
||||
for (i = 0; i < nr_pages; ++i) {
|
||||
if (rc == -EAGAIN)
|
||||
if (is_retryable_error(rc))
|
||||
redirty_page_for_writepage(wbc,
|
||||
wdata->pages[i]);
|
||||
else
|
||||
@@ -2191,7 +2196,7 @@ retry:
|
||||
end_page_writeback(wdata->pages[i]);
|
||||
put_page(wdata->pages[i]);
|
||||
}
|
||||
if (rc != -EAGAIN)
|
||||
if (!is_retryable_error(rc))
|
||||
mapping_set_error(mapping, rc);
|
||||
}
|
||||
kref_put(&wdata->refcount, cifs_writedata_release);
|
||||
@@ -2201,6 +2206,15 @@ retry:
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Return immediately if we received a signal during writing */
|
||||
if (is_interrupt_error(rc)) {
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (rc != 0 && saved_rc == 0)
|
||||
saved_rc = rc;
|
||||
|
||||
wbc->nr_to_write -= nr_pages;
|
||||
if (wbc->nr_to_write <= 0)
|
||||
done = true;
|
||||
@@ -2218,6 +2232,9 @@ retry:
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if (saved_rc != 0)
|
||||
rc = saved_rc;
|
||||
|
||||
if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
|
||||
mapping->writeback_index = index;
|
||||
|
||||
@@ -2250,8 +2267,8 @@ cifs_writepage_locked(struct page *page, struct writeback_control *wbc)
|
||||
set_page_writeback(page);
|
||||
retry_write:
|
||||
rc = cifs_partialpagewrite(page, 0, PAGE_SIZE);
|
||||
if (rc == -EAGAIN) {
|
||||
if (wbc->sync_mode == WB_SYNC_ALL)
|
||||
if (is_retryable_error(rc)) {
|
||||
if (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN)
|
||||
goto retry_write;
|
||||
redirty_page_for_writepage(wbc, page);
|
||||
} else if (rc != 0) {
|
||||
|
Reference in New Issue
Block a user