|
@@ -1670,8 +1670,8 @@ cifs_write(struct cifsFileInfo *open_file, __u32 pid, const char *write_data,
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- len = min((size_t)cifs_sb->wsize,
|
|
|
- write_size - total_written);
|
|
|
+ len = min(server->ops->wp_retry_size(dentry->d_inode),
|
|
|
+ (unsigned int)write_size - total_written);
|
|
|
/* iov[0] is reserved for smb header */
|
|
|
iov[1].iov_base = (char *)write_data + total_written;
|
|
|
iov[1].iov_len = len;
|
|
@@ -2031,6 +2031,7 @@ static int cifs_writepages(struct address_space *mapping,
|
|
|
struct writeback_control *wbc)
|
|
|
{
|
|
|
struct cifs_sb_info *cifs_sb = CIFS_SB(mapping->host->i_sb);
|
|
|
+ struct TCP_Server_Info *server;
|
|
|
bool done = false, scanned = false, range_whole = false;
|
|
|
pgoff_t end, index;
|
|
|
struct cifs_writedata *wdata;
|
|
@@ -2053,23 +2054,30 @@ static int cifs_writepages(struct address_space *mapping,
|
|
|
range_whole = true;
|
|
|
scanned = true;
|
|
|
}
|
|
|
+ server = cifs_sb_master_tcon(cifs_sb)->ses->server;
|
|
|
retry:
|
|
|
while (!done && index <= end) {
|
|
|
- unsigned int i, nr_pages, found_pages;
|
|
|
+ unsigned int i, nr_pages, found_pages, wsize, credits;
|
|
|
pgoff_t next = 0, tofind, saved_index = index;
|
|
|
|
|
|
- tofind = min((cifs_sb->wsize / PAGE_CACHE_SIZE) - 1,
|
|
|
- end - index) + 1;
|
|
|
+ rc = server->ops->wait_mtu_credits(server, cifs_sb->wsize,
|
|
|
+ &wsize, &credits);
|
|
|
+ if (rc)
|
|
|
+ break;
|
|
|
+
|
|
|
+ tofind = min((wsize / PAGE_CACHE_SIZE) - 1, end - index) + 1;
|
|
|
|
|
|
wdata = wdata_alloc_and_fillpages(tofind, mapping, end, &index,
|
|
|
&found_pages);
|
|
|
if (!wdata) {
|
|
|
rc = -ENOMEM;
|
|
|
+ add_credits_and_wake_if(server, credits, 0);
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
if (found_pages == 0) {
|
|
|
kref_put(&wdata->refcount, cifs_writedata_release);
|
|
|
+ add_credits_and_wake_if(server, credits, 0);
|
|
|
break;
|
|
|
}
|
|
|
|
|
@@ -2079,13 +2087,17 @@ retry:
|
|
|
/* nothing to write? */
|
|
|
if (nr_pages == 0) {
|
|
|
kref_put(&wdata->refcount, cifs_writedata_release);
|
|
|
+ add_credits_and_wake_if(server, credits, 0);
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
+ wdata->credits = credits;
|
|
|
+
|
|
|
rc = wdata_send_pages(wdata, nr_pages, mapping, wbc);
|
|
|
|
|
|
/* send failure -- clean up the mess */
|
|
|
if (rc != 0) {
|
|
|
+ add_credits_and_wake_if(server, wdata->credits, 0);
|
|
|
for (i = 0; i < nr_pages; ++i) {
|
|
|
if (rc == -EAGAIN)
|
|
|
redirty_page_for_writepage(wbc,
|
|
@@ -2466,17 +2478,26 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
|
|
|
memcpy(&saved_from, from, sizeof(struct iov_iter));
|
|
|
|
|
|
do {
|
|
|
- nr_pages = get_numpages(cifs_sb->wsize, len, &cur_len);
|
|
|
+ unsigned int wsize, credits;
|
|
|
+
|
|
|
+ rc = server->ops->wait_mtu_credits(server, cifs_sb->wsize,
|
|
|
+ &wsize, &credits);
|
|
|
+ if (rc)
|
|
|
+ break;
|
|
|
+
|
|
|
+ nr_pages = get_numpages(wsize, len, &cur_len);
|
|
|
wdata = cifs_writedata_alloc(nr_pages,
|
|
|
cifs_uncached_writev_complete);
|
|
|
if (!wdata) {
|
|
|
rc = -ENOMEM;
|
|
|
+ add_credits_and_wake_if(server, credits, 0);
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
rc = cifs_write_allocate_pages(wdata->pages, nr_pages);
|
|
|
if (rc) {
|
|
|
kfree(wdata);
|
|
|
+ add_credits_and_wake_if(server, credits, 0);
|
|
|
break;
|
|
|
}
|
|
|
|
|
@@ -2486,6 +2507,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
|
|
|
for (i = 0; i < nr_pages; i++)
|
|
|
put_page(wdata->pages[i]);
|
|
|
kfree(wdata);
|
|
|
+ add_credits_and_wake_if(server, credits, 0);
|
|
|
break;
|
|
|
}
|
|
|
|
|
@@ -2504,12 +2526,14 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
|
|
|
wdata->bytes = cur_len;
|
|
|
wdata->pagesz = PAGE_SIZE;
|
|
|
wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE);
|
|
|
+ wdata->credits = credits;
|
|
|
|
|
|
if (!wdata->cfile->invalidHandle ||
|
|
|
!cifs_reopen_file(wdata->cfile, false))
|
|
|
rc = server->ops->async_writev(wdata,
|
|
|
cifs_uncached_writedata_release);
|
|
|
if (rc) {
|
|
|
+ add_credits_and_wake_if(server, wdata->credits, 0);
|
|
|
kref_put(&wdata->refcount,
|
|
|
cifs_uncached_writedata_release);
|
|
|
if (rc == -EAGAIN) {
|