diff options
author | Steve French <smfrench@gmail.com> | 2014-02-07 20:45:12 -0600 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2014-02-07 20:47:00 -0600 |
commit | 4a5c80d7b5615be8098f9d5da97d166afc318abc (patch) | |
tree | ff3e40a816442722056805cc0cc1844051a30988 /fs/cifs/cifssmb.c | |
parent | 26c8f0d601f5d4c0d9f4bc8c5151539aae5dc26a (diff) | |
download | lwn-4a5c80d7b5615be8098f9d5da97d166afc318abc.tar.gz lwn-4a5c80d7b5615be8098f9d5da97d166afc318abc.zip |
[CIFS] clean up page array when uncached write send fails
In the event that a send fails in an uncached write, or we end up
needing to reissue it (-EAGAIN case), we'll kfree the wdata but
the pages currently leak.
Fix this by adding a new kref release routine for uncached writedata
that releases the pages, and have the uncached codepaths use that.
[original patch by Jeff modified to fix minor formatting problems]
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Reviewed-by: Pavel Shilovsky <piastry@etersoft.ru>
Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r-- | fs/cifs/cifssmb.c | 7 |
1 files changed, 4 insertions, 3 deletions
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) do { server = tlink_tcon(wdata->cfile->tlink)->ses->server; - rc = server->ops->async_writev(wdata); + rc = server->ops->async_writev(wdata, cifs_writedata_release); } while (rc == -EAGAIN); for (i = 0; i < wdata->nr_pages; i++) { @@ -2025,7 +2025,8 @@ cifs_writev_callback(struct mid_q_entry *mid) /* cifs_async_writev - send an async write, and set up mid to handle result */ int -cifs_async_writev(struct cifs_writedata *wdata) +cifs_async_writev(struct cifs_writedata *wdata, + void (*release)(struct kref *kref)) { int rc = -EACCES; WRITE_REQ *smb = NULL; @@ -2099,7 +2100,7 @@ cifs_async_writev(struct cifs_writedata *wdata) if (rc == 0) cifs_stats_inc(&tcon->stats.cifs_stats.num_writes); else - kref_put(&wdata->refcount, cifs_writedata_release); + kref_put(&wdata->refcount, release); async_writev_out: cifs_small_buf_release(smb); |