diff options
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r-- | fs/cifs/file.c | 78 |
1 files changed, 66 insertions, 12 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 7f5f6176c6f1..21d404535739 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -777,6 +777,11 @@ cifs_reopen_persistent_handles(struct cifs_tcon *tcon) struct list_head *tmp1; struct list_head tmp_list; + if (!tcon->use_persistent || !tcon->need_reopen_files) + return; + + tcon->need_reopen_files = false; + cifs_dbg(FYI, "Reopen persistent handles"); INIT_LIST_HEAD(&tmp_list); @@ -793,7 +798,8 @@ cifs_reopen_persistent_handles(struct cifs_tcon *tcon) list_for_each_safe(tmp, tmp1, &tmp_list) { open_file = list_entry(tmp, struct cifsFileInfo, rlist); - cifs_reopen_file(open_file, false /* do not flush */); + if (cifs_reopen_file(open_file, false /* do not flush */)) + tcon->need_reopen_files = true; list_del_init(&open_file->rlist); cifsFileInfo_put(open_file); } @@ -2591,7 +2597,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, wdata->credits = credits; if (!wdata->cfile->invalidHandle || - !cifs_reopen_file(wdata->cfile, false)) + !(rc = cifs_reopen_file(wdata->cfile, false))) rc = server->ops->async_writev(wdata, cifs_uncached_writedata_release); if (rc) { @@ -2878,7 +2884,15 @@ cifs_readdata_to_iov(struct cifs_readdata *rdata, struct iov_iter *iter) for (i = 0; i < rdata->nr_pages; i++) { struct page *page = rdata->pages[i]; size_t copy = min_t(size_t, remaining, PAGE_SIZE); - size_t written = copy_page_to_iter(page, 0, copy, iter); + size_t written; + + if (unlikely(iter->type & ITER_PIPE)) { + void *addr = kmap_atomic(page); + + written = copy_to_iter(addr, copy, iter); + kunmap_atomic(addr); + } else + written = copy_page_to_iter(page, 0, copy, iter); remaining -= written; if (written < copy && iov_iter_count(iter) > 0) break; @@ -2897,8 +2911,9 @@ cifs_uncached_readv_complete(struct work_struct *work) } static int -cifs_uncached_read_into_pages(struct TCP_Server_Info *server, - struct cifs_readdata *rdata, unsigned int len) +uncached_fill_pages(struct TCP_Server_Info *server, + struct cifs_readdata *rdata, struct iov_iter *iter, + unsigned int len) { int result = 0; unsigned int i; @@ -2927,7 +2942,10 @@ cifs_uncached_read_into_pages(struct TCP_Server_Info *server, rdata->tailsz = len; len = 0; } - result = cifs_read_page_from_socket(server, page, n); + if (iter) + result = copy_page_from_iter(page, 0, n, iter); + else + result = cifs_read_page_from_socket(server, page, n); if (result < 0) break; @@ -2939,6 +2957,21 @@ cifs_uncached_read_into_pages(struct TCP_Server_Info *server, } static int +cifs_uncached_read_into_pages(struct TCP_Server_Info *server, + struct cifs_readdata *rdata, unsigned int len) +{ + return uncached_fill_pages(server, rdata, NULL, len); +} + +static int +cifs_uncached_copy_into_pages(struct TCP_Server_Info *server, + struct cifs_readdata *rdata, + struct iov_iter *iter) +{ + return uncached_fill_pages(server, rdata, iter, iter->count); +} + +static int cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, struct cifs_sb_info *cifs_sb, struct list_head *rdata_list) { @@ -2985,10 +3018,11 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, rdata->pid = pid; rdata->pagesz = PAGE_SIZE; rdata->read_into_pages = cifs_uncached_read_into_pages; + rdata->copy_into_pages = cifs_uncached_copy_into_pages; rdata->credits = credits; if (!rdata->cfile->invalidHandle || - !cifs_reopen_file(rdata->cfile, true)) + !(rc = cifs_reopen_file(rdata->cfile, true))) rc = server->ops->async_readv(rdata); error: if (rc) { @@ -3248,7 +3282,7 @@ cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset) * sure that it doesn't change while being written back. */ static int -cifs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) +cifs_page_mkwrite(struct vm_fault *vmf) { struct page *page = vmf->page; @@ -3335,8 +3369,9 @@ cifs_readv_complete(struct work_struct *work) } static int -cifs_readpages_read_into_pages(struct TCP_Server_Info *server, - struct cifs_readdata *rdata, unsigned int len) +readpages_fill_pages(struct TCP_Server_Info *server, + struct cifs_readdata *rdata, struct iov_iter *iter, + unsigned int len) { int result = 0; unsigned int i; @@ -3390,7 +3425,10 @@ cifs_readpages_read_into_pages(struct TCP_Server_Info *server, continue; } - result = cifs_read_page_from_socket(server, page, n); + if (iter) + result = copy_page_from_iter(page, 0, n, iter); + else + result = cifs_read_page_from_socket(server, page, n); if (result < 0) break; @@ -3402,6 +3440,21 @@ cifs_readpages_read_into_pages(struct TCP_Server_Info *server, } static int +cifs_readpages_read_into_pages(struct TCP_Server_Info *server, + struct cifs_readdata *rdata, unsigned int len) +{ + return readpages_fill_pages(server, rdata, NULL, len); +} + +static int +cifs_readpages_copy_into_pages(struct TCP_Server_Info *server, + struct cifs_readdata *rdata, + struct iov_iter *iter) +{ + return readpages_fill_pages(server, rdata, iter, iter->count); +} + +static int readpages_get_pages(struct address_space *mapping, struct list_head *page_list, unsigned int rsize, struct list_head *tmplist, unsigned int *nr_pages, loff_t *offset, unsigned int *bytes) @@ -3555,6 +3608,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, rdata->pid = pid; rdata->pagesz = PAGE_SIZE; rdata->read_into_pages = cifs_readpages_read_into_pages; + rdata->copy_into_pages = cifs_readpages_copy_into_pages; rdata->credits = credits; list_for_each_entry_safe(page, tpage, &tmplist, lru) { @@ -3563,7 +3617,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, } if (!rdata->cfile->invalidHandle || - !cifs_reopen_file(rdata->cfile, true)) + !(rc = cifs_reopen_file(rdata->cfile, true))) rc = server->ops->async_readv(rdata); if (rc) { add_credits_and_wake_if(server, rdata->credits, 0); |