diff options
| -rw-r--r-- | fs/cifs/cifsglob.h | 3 | ||||
| -rw-r--r-- | fs/cifs/cifsproto.h | 3 | ||||
| -rw-r--r-- | fs/cifs/cifssmb.c | 7 | ||||
| -rw-r--r-- | fs/cifs/file.c | 31 | ||||
| -rw-r--r-- | fs/cifs/smb2pdu.c | 5 | ||||
| -rw-r--r-- | fs/cifs/smb2proto.h | 3 |
6 files changed, 33 insertions, 19 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index d6a031ed391b..86dc28c7aa5c 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
| @@ -323,7 +323,8 @@ struct smb_version_operations { | |||
| 323 | /* async read from the server */ | 323 | /* async read from the server */ |
| 324 | int (*async_readv)(struct cifs_readdata *); | 324 | int (*async_readv)(struct cifs_readdata *); |
| 325 | /* async write to the server */ | 325 | /* async write to the server */ |
| 326 | int (*async_writev)(struct cifs_writedata *); | 326 | int (*async_writev)(struct cifs_writedata *, |
| 327 | void (*release)(struct kref *)); | ||
| 327 | /* sync read from the server */ | 328 | /* sync read from the server */ |
| 328 | int (*sync_read)(const unsigned int, struct cifsFileInfo *, | 329 | int (*sync_read)(const unsigned int, struct cifsFileInfo *, |
| 329 | struct cifs_io_parms *, unsigned int *, char **, | 330 | struct cifs_io_parms *, unsigned int *, char **, |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 79e6e9a93a8c..d00e09dfc452 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
| @@ -488,7 +488,8 @@ void cifs_readdata_release(struct kref *refcount); | |||
| 488 | int cifs_async_readv(struct cifs_readdata *rdata); | 488 | int cifs_async_readv(struct cifs_readdata *rdata); |
| 489 | int cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid); | 489 | int cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid); |
| 490 | 490 | ||
| 491 | int cifs_async_writev(struct cifs_writedata *wdata); | 491 | int cifs_async_writev(struct cifs_writedata *wdata, |
| 492 | void (*release)(struct kref *kref)); | ||
| 492 | void cifs_writev_complete(struct work_struct *work); | 493 | void cifs_writev_complete(struct work_struct *work); |
| 493 | struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages, | 494 | struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages, |
| 494 | work_func_t complete); | 495 | work_func_t complete); |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 0cd742ccb019..f3264bd7a83d 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
| @@ -1910,7 +1910,7 @@ cifs_writev_requeue(struct cifs_writedata *wdata) | |||
| 1910 | 1910 | ||
| 1911 | do { | 1911 | do { |
| 1912 | server = tlink_tcon(wdata->cfile->tlink)->ses->server; | 1912 | server = tlink_tcon(wdata->cfile->tlink)->ses->server; |
| 1913 | rc = server->ops->async_writev(wdata); | 1913 | rc = server->ops->async_writev(wdata, cifs_writedata_release); |
| 1914 | } while (rc == -EAGAIN); | 1914 | } while (rc == -EAGAIN); |
| 1915 | 1915 | ||
| 1916 | for (i = 0; i < wdata->nr_pages; i++) { | 1916 | for (i = 0; i < wdata->nr_pages; i++) { |
| @@ -2025,7 +2025,8 @@ cifs_writev_callback(struct mid_q_entry *mid) | |||
| 2025 | 2025 | ||
| 2026 | /* cifs_async_writev - send an async write, and set up mid to handle result */ | 2026 | /* cifs_async_writev - send an async write, and set up mid to handle result */ |
| 2027 | int | 2027 | int |
| 2028 | cifs_async_writev(struct cifs_writedata *wdata) | 2028 | cifs_async_writev(struct cifs_writedata *wdata, |
| 2029 | void (*release)(struct kref *kref)) | ||
| 2029 | { | 2030 | { |
| 2030 | int rc = -EACCES; | 2031 | int rc = -EACCES; |
| 2031 | WRITE_REQ *smb = NULL; | 2032 | WRITE_REQ *smb = NULL; |
| @@ -2099,7 +2100,7 @@ cifs_async_writev(struct cifs_writedata *wdata) | |||
| 2099 | if (rc == 0) | 2100 | if (rc == 0) |
| 2100 | cifs_stats_inc(&tcon->stats.cifs_stats.num_writes); | 2101 | cifs_stats_inc(&tcon->stats.cifs_stats.num_writes); |
| 2101 | else | 2102 | else |
| 2102 | kref_put(&wdata->refcount, cifs_writedata_release); | 2103 | kref_put(&wdata->refcount, release); |
| 2103 | 2104 | ||
| 2104 | async_writev_out: | 2105 | async_writev_out: |
| 2105 | cifs_small_buf_release(smb); | 2106 | cifs_small_buf_release(smb); |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 853d6d1cc822..a301edbdad4a 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
| @@ -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 | ||
| 2333 | static void | 2334 | static void |
| 2334 | cifs_uncached_writev_complete(struct work_struct *work) | 2335 | cifs_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 | |||
| 2346 | static void | ||
| 2347 | cifs_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; |
| @@ -2454,7 +2462,8 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, | |||
| 2454 | wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE); | 2462 | wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE); |
| 2455 | rc = cifs_uncached_retry_writev(wdata); | 2463 | rc = cifs_uncached_retry_writev(wdata); |
| 2456 | if (rc) { | 2464 | if (rc) { |
| 2457 | kref_put(&wdata->refcount, cifs_writedata_release); | 2465 | kref_put(&wdata->refcount, |
| 2466 | cifs_uncached_writedata_release); | ||
| 2458 | break; | 2467 | break; |
| 2459 | } | 2468 | } |
| 2460 | 2469 | ||
| @@ -2496,7 +2505,7 @@ restart_loop: | |||
| 2496 | } | 2505 | } |
| 2497 | } | 2506 | } |
| 2498 | list_del_init(&wdata->list); | 2507 | list_del_init(&wdata->list); |
| 2499 | kref_put(&wdata->refcount, cifs_writedata_release); | 2508 | kref_put(&wdata->refcount, cifs_uncached_writedata_release); |
| 2500 | } | 2509 | } |
| 2501 | 2510 | ||
| 2502 | if (total_written > 0) | 2511 | if (total_written > 0) |
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 2013234b73ad..a3f7a9c3cc69 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c | |||
| @@ -1890,7 +1890,8 @@ smb2_writev_callback(struct mid_q_entry *mid) | |||
| 1890 | 1890 | ||
| 1891 | /* smb2_async_writev - send an async write, and set up mid to handle result */ | 1891 | /* smb2_async_writev - send an async write, and set up mid to handle result */ |
| 1892 | int | 1892 | int |
| 1893 | smb2_async_writev(struct cifs_writedata *wdata) | 1893 | smb2_async_writev(struct cifs_writedata *wdata, |
| 1894 | void (*release)(struct kref *kref)) | ||
| 1894 | { | 1895 | { |
| 1895 | int rc = -EACCES; | 1896 | int rc = -EACCES; |
| 1896 | struct smb2_write_req *req = NULL; | 1897 | struct smb2_write_req *req = NULL; |
| @@ -1938,7 +1939,7 @@ smb2_async_writev(struct cifs_writedata *wdata) | |||
| 1938 | smb2_writev_callback, wdata, 0); | 1939 | smb2_writev_callback, wdata, 0); |
| 1939 | 1940 | ||
| 1940 | if (rc) { | 1941 | if (rc) { |
| 1941 | kref_put(&wdata->refcount, cifs_writedata_release); | 1942 | kref_put(&wdata->refcount, release); |
| 1942 | cifs_stats_fail_inc(tcon, SMB2_WRITE_HE); | 1943 | cifs_stats_fail_inc(tcon, SMB2_WRITE_HE); |
| 1943 | } | 1944 | } |
| 1944 | 1945 | ||
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index 93adc64666f3..0ce48db20a65 100644 --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h | |||
| @@ -123,7 +123,8 @@ extern int SMB2_get_srv_num(const unsigned int xid, struct cifs_tcon *tcon, | |||
| 123 | extern int smb2_async_readv(struct cifs_readdata *rdata); | 123 | extern int smb2_async_readv(struct cifs_readdata *rdata); |
| 124 | extern int SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms, | 124 | extern int SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms, |
| 125 | unsigned int *nbytes, char **buf, int *buf_type); | 125 | unsigned int *nbytes, char **buf, int *buf_type); |
| 126 | extern int smb2_async_writev(struct cifs_writedata *wdata); | 126 | extern int smb2_async_writev(struct cifs_writedata *wdata, |
| 127 | void (*release)(struct kref *kref)); | ||
| 127 | extern int SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms, | 128 | extern int SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms, |
| 128 | unsigned int *nbytes, struct kvec *iov, int n_vec); | 129 | unsigned int *nbytes, struct kvec *iov, int n_vec); |
| 129 | extern int SMB2_echo(struct TCP_Server_Info *server); | 130 | extern int SMB2_echo(struct TCP_Server_Info *server); |
