aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/file.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-02-10 10:33:50 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2014-02-10 10:33:50 -0800
commitcbf2822a7d44352c5c4c15baf0da3a3dc8495e90 (patch)
tree3d45cb221c14bd021287cb6507187f5c27556640 /fs/cifs/file.c
parentLinux 3.14-rc2 (diff)
parent[CIFS] clean up page array when uncached write send fails (diff)
downloadlinux-dev-cbf2822a7d44352c5c4c15baf0da3a3dc8495e90.tar.xz
linux-dev-cbf2822a7d44352c5c4c15baf0da3a3dc8495e90.zip
Merge branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6
Pull CIFS fixes from Steve French: "Small fix from Jeff for writepages leak, and some fixes for ACLs and xattrs when SMB2 enabled. Am expecting another fix from Jeff and at least one more fix (for mounting SMB2 with cifsacl) in the next week" * 'for-next' of git://git.samba.org/sfrench/cifs-2.6: [CIFS] clean up page array when uncached write send fails cifs: use a flexarray in cifs_writedata retrieving CIFS ACLs when mounted with SMB2 fails dropping session Add protocol specific operation for CIFS xattrs
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r--fs/cifs/file.c31
1 files changed, 20 insertions, 11 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index a7eda8ebfacc..755584684f6c 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -2043,7 +2043,8 @@ retry:
}
wdata->pid = wdata->cfile->pid;
server = tlink_tcon(wdata->cfile->tlink)->ses->server;
- rc = server->ops->async_writev(wdata);
+ rc = server->ops->async_writev(wdata,
+ cifs_writedata_release);
} while (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN);
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)
}
static void
-cifs_uncached_writev_complete(struct work_struct *work)
+cifs_uncached_writedata_release(struct kref *refcount)
{
int i;
+ struct cifs_writedata *wdata = container_of(refcount,
+ struct cifs_writedata, refcount);
+
+ for (i = 0; i < wdata->nr_pages; i++)
+ put_page(wdata->pages[i]);
+ cifs_writedata_release(refcount);
+}
+
+static void
+cifs_uncached_writev_complete(struct work_struct *work)
+{
struct cifs_writedata *wdata = container_of(work,
struct cifs_writedata, work);
struct inode *inode = wdata->cfile->dentry->d_inode;
@@ -2347,12 +2359,7 @@ cifs_uncached_writev_complete(struct work_struct *work)
complete(&wdata->done);
- if (wdata->result != -EAGAIN) {
- for (i = 0; i < wdata->nr_pages; i++)
- put_page(wdata->pages[i]);
- }
-
- kref_put(&wdata->refcount, cifs_writedata_release);
+ kref_put(&wdata->refcount, cifs_uncached_writedata_release);
}
/* attempt to send write to server, retry on any -EAGAIN errors */
@@ -2370,7 +2377,8 @@ cifs_uncached_retry_writev(struct cifs_writedata *wdata)
if (rc != 0)
continue;
}
- rc = server->ops->async_writev(wdata);
+ rc = server->ops->async_writev(wdata,
+ cifs_uncached_writedata_release);
} while (rc == -EAGAIN);
return rc;
@@ -2454,7 +2462,8 @@ cifs_iovec_write(struct file *file, const struct iovec *iov,
wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE);
rc = cifs_uncached_retry_writev(wdata);
if (rc) {
- kref_put(&wdata->refcount, cifs_writedata_release);
+ kref_put(&wdata->refcount,
+ cifs_uncached_writedata_release);
break;
}
@@ -2496,7 +2505,7 @@ restart_loop:
}
}
list_del_init(&wdata->list);
- kref_put(&wdata->refcount, cifs_writedata_release);
+ kref_put(&wdata->refcount, cifs_uncached_writedata_release);
}
if (total_written > 0)