aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r--fs/cifs/file.c74
1 files changed, 57 insertions, 17 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 853d6d1cc822..53c15074bb36 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -244,7 +244,7 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
244 xid); 244 xid);
245 else 245 else
246 rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb, 246 rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb,
247 xid, &fid->netfid); 247 xid, fid);
248 248
249out: 249out:
250 kfree(buf); 250 kfree(buf);
@@ -2043,7 +2043,8 @@ retry:
2043 } 2043 }
2044 wdata->pid = wdata->cfile->pid; 2044 wdata->pid = wdata->cfile->pid;
2045 server = tlink_tcon(wdata->cfile->tlink)->ses->server; 2045 server = tlink_tcon(wdata->cfile->tlink)->ses->server;
2046 rc = server->ops->async_writev(wdata); 2046 rc = server->ops->async_writev(wdata,
2047 cifs_writedata_release);
2047 } while (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN); 2048 } while (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN);
2048 2049
2049 for (i = 0; i < nr_pages; ++i) 2050 for (i = 0; i < nr_pages; ++i)
@@ -2331,9 +2332,20 @@ size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len)
2331} 2332}
2332 2333
2333static void 2334static void
2334cifs_uncached_writev_complete(struct work_struct *work) 2335cifs_uncached_writedata_release(struct kref *refcount)
2335{ 2336{
2336 int i; 2337 int i;
2338 struct cifs_writedata *wdata = container_of(refcount,
2339 struct cifs_writedata, refcount);
2340
2341 for (i = 0; i < wdata->nr_pages; i++)
2342 put_page(wdata->pages[i]);
2343 cifs_writedata_release(refcount);
2344}
2345
2346static void
2347cifs_uncached_writev_complete(struct work_struct *work)
2348{
2337 struct cifs_writedata *wdata = container_of(work, 2349 struct cifs_writedata *wdata = container_of(work,
2338 struct cifs_writedata, work); 2350 struct cifs_writedata, work);
2339 struct inode *inode = wdata->cfile->dentry->d_inode; 2351 struct inode *inode = wdata->cfile->dentry->d_inode;
@@ -2347,12 +2359,7 @@ cifs_uncached_writev_complete(struct work_struct *work)
2347 2359
2348 complete(&wdata->done); 2360 complete(&wdata->done);
2349 2361
2350 if (wdata->result != -EAGAIN) { 2362 kref_put(&wdata->refcount, cifs_uncached_writedata_release);
2351 for (i = 0; i < wdata->nr_pages; i++)
2352 put_page(wdata->pages[i]);
2353 }
2354
2355 kref_put(&wdata->refcount, cifs_writedata_release);
2356} 2363}
2357 2364
2358/* attempt to send write to server, retry on any -EAGAIN errors */ 2365/* attempt to send write to server, retry on any -EAGAIN errors */
@@ -2370,7 +2377,8 @@ cifs_uncached_retry_writev(struct cifs_writedata *wdata)
2370 if (rc != 0) 2377 if (rc != 0)
2371 continue; 2378 continue;
2372 } 2379 }
2373 rc = server->ops->async_writev(wdata); 2380 rc = server->ops->async_writev(wdata,
2381 cifs_uncached_writedata_release);
2374 } while (rc == -EAGAIN); 2382 } while (rc == -EAGAIN);
2375 2383
2376 return rc; 2384 return rc;
@@ -2381,7 +2389,7 @@ cifs_iovec_write(struct file *file, const struct iovec *iov,
2381 unsigned long nr_segs, loff_t *poffset) 2389 unsigned long nr_segs, loff_t *poffset)
2382{ 2390{
2383 unsigned long nr_pages, i; 2391 unsigned long nr_pages, i;
2384 size_t copied, len, cur_len; 2392 size_t bytes, copied, len, cur_len;
2385 ssize_t total_written = 0; 2393 ssize_t total_written = 0;
2386 loff_t offset; 2394 loff_t offset;
2387 struct iov_iter it; 2395 struct iov_iter it;
@@ -2436,14 +2444,45 @@ cifs_iovec_write(struct file *file, const struct iovec *iov,
2436 2444
2437 save_len = cur_len; 2445 save_len = cur_len;
2438 for (i = 0; i < nr_pages; i++) { 2446 for (i = 0; i < nr_pages; i++) {
2439 copied = min_t(const size_t, cur_len, PAGE_SIZE); 2447 bytes = min_t(const size_t, cur_len, PAGE_SIZE);
2440 copied = iov_iter_copy_from_user(wdata->pages[i], &it, 2448 copied = iov_iter_copy_from_user(wdata->pages[i], &it,
2441 0, copied); 2449 0, bytes);
2442 cur_len -= copied; 2450 cur_len -= copied;
2443 iov_iter_advance(&it, copied); 2451 iov_iter_advance(&it, copied);
2452 /*
2453 * If we didn't copy as much as we expected, then that
2454 * may mean we trod into an unmapped area. Stop copying
2455 * at that point. On the next pass through the big
2456 * loop, we'll likely end up getting a zero-length
2457 * write and bailing out of it.
2458 */
2459 if (copied < bytes)
2460 break;
2444 } 2461 }
2445 cur_len = save_len - cur_len; 2462 cur_len = save_len - cur_len;
2446 2463
2464 /*
2465 * If we have no data to send, then that probably means that
2466 * the copy above failed altogether. That's most likely because
2467 * the address in the iovec was bogus. Set the rc to -EFAULT,
2468 * free anything we allocated and bail out.
2469 */
2470 if (!cur_len) {
2471 for (i = 0; i < nr_pages; i++)
2472 put_page(wdata->pages[i]);
2473 kfree(wdata);
2474 rc = -EFAULT;
2475 break;
2476 }
2477
2478 /*
2479 * i + 1 now represents the number of pages we actually used in
2480 * the copy phase above. Bring nr_pages down to that, and free
2481 * any pages that we didn't use.
2482 */
2483 for ( ; nr_pages > i + 1; nr_pages--)
2484 put_page(wdata->pages[nr_pages - 1]);
2485
2447 wdata->sync_mode = WB_SYNC_ALL; 2486 wdata->sync_mode = WB_SYNC_ALL;
2448 wdata->nr_pages = nr_pages; 2487 wdata->nr_pages = nr_pages;
2449 wdata->offset = (__u64)offset; 2488 wdata->offset = (__u64)offset;
@@ -2454,7 +2493,8 @@ cifs_iovec_write(struct file *file, const struct iovec *iov,
2454 wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE); 2493 wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE);
2455 rc = cifs_uncached_retry_writev(wdata); 2494 rc = cifs_uncached_retry_writev(wdata);
2456 if (rc) { 2495 if (rc) {
2457 kref_put(&wdata->refcount, cifs_writedata_release); 2496 kref_put(&wdata->refcount,
2497 cifs_uncached_writedata_release);
2458 break; 2498 break;
2459 } 2499 }
2460 2500
@@ -2496,7 +2536,7 @@ restart_loop:
2496 } 2536 }
2497 } 2537 }
2498 list_del_init(&wdata->list); 2538 list_del_init(&wdata->list);
2499 kref_put(&wdata->refcount, cifs_writedata_release); 2539 kref_put(&wdata->refcount, cifs_uncached_writedata_release);
2500 } 2540 }
2501 2541
2502 if (total_written > 0) 2542 if (total_written > 0)
@@ -2559,8 +2599,8 @@ cifs_writev(struct kiocb *iocb, const struct iovec *iov,
2559 if (rc > 0) { 2599 if (rc > 0) {
2560 ssize_t err; 2600 ssize_t err;
2561 2601
2562 err = generic_write_sync(file, pos, rc); 2602 err = generic_write_sync(file, iocb->ki_pos - rc, rc);
2563 if (err < 0 && rc > 0) 2603 if (err < 0)
2564 rc = err; 2604 rc = err;
2565 } 2605 }
2566 2606