diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2015-04-01 20:17:51 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2015-04-11 22:28:25 -0400 |
commit | 070b3656cf228eaaef7b28b59264c5c7cdbdd0fb (patch) | |
tree | 76040fdba3e0703df0be897aba7310332454d60e | |
parent | 4f3b35c157e43107cc7e1f1aa06694e8b22e10bb (diff) |
9p: switch p9_client_write() to passing it struct iov_iter *
... and make it loop until it's done
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/9p/vfs_file.c | 24 | ||||
-rw-r--r-- | fs/9p/xattr.c | 32 | ||||
-rw-r--r-- | include/net/9p/client.h | 5 | ||||
-rw-r--r-- | net/9p/client.c | 98 |
4 files changed, 62 insertions, 97 deletions
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index b40133796b87..75a2bb01420d 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/utsname.h> | 36 | #include <linux/utsname.h> |
37 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
38 | #include <linux/idr.h> | 38 | #include <linux/idr.h> |
39 | #include <linux/uio.h> | ||
39 | #include <net/9p/9p.h> | 40 | #include <net/9p/9p.h> |
40 | #include <net/9p/client.h> | 41 | #include <net/9p/client.h> |
41 | 42 | ||
@@ -457,24 +458,20 @@ v9fs_file_write_internal(struct inode *inode, struct p9_fid *fid, | |||
457 | const char __user *data, size_t count, | 458 | const char __user *data, size_t count, |
458 | loff_t *offset, int invalidate) | 459 | loff_t *offset, int invalidate) |
459 | { | 460 | { |
460 | int n; | ||
461 | loff_t i_size; | ||
462 | size_t total = 0; | ||
463 | loff_t origin = *offset; | 461 | loff_t origin = *offset; |
464 | unsigned long pg_start, pg_end; | 462 | struct iovec iov = {.iov_base = (void __user *)data, .iov_len = count}; |
463 | struct iov_iter from; | ||
464 | int total, err = 0; | ||
465 | 465 | ||
466 | p9_debug(P9_DEBUG_VFS, "data %p count %d offset %x\n", | 466 | p9_debug(P9_DEBUG_VFS, "data %p count %d offset %x\n", |
467 | data, (int)count, (int)*offset); | 467 | data, (int)count, (int)*offset); |
468 | 468 | ||
469 | do { | 469 | iov_iter_init(&from, WRITE, &iov, 1, count); |
470 | n = p9_client_write(fid, NULL, data+total, origin+total, count); | ||
471 | if (n <= 0) | ||
472 | break; | ||
473 | count -= n; | ||
474 | total += n; | ||
475 | } while (count > 0); | ||
476 | 470 | ||
471 | total = p9_client_write(fid, origin, &from, &err); | ||
477 | if (invalidate && (total > 0)) { | 472 | if (invalidate && (total > 0)) { |
473 | loff_t i_size; | ||
474 | unsigned long pg_start, pg_end; | ||
478 | pg_start = origin >> PAGE_CACHE_SHIFT; | 475 | pg_start = origin >> PAGE_CACHE_SHIFT; |
479 | pg_end = (origin + total - 1) >> PAGE_CACHE_SHIFT; | 476 | pg_end = (origin + total - 1) >> PAGE_CACHE_SHIFT; |
480 | if (inode->i_mapping && inode->i_mapping->nrpages) | 477 | if (inode->i_mapping && inode->i_mapping->nrpages) |
@@ -487,10 +484,7 @@ v9fs_file_write_internal(struct inode *inode, struct p9_fid *fid, | |||
487 | i_size_write(inode, *offset); | 484 | i_size_write(inode, *offset); |
488 | } | 485 | } |
489 | } | 486 | } |
490 | if (n < 0) | 487 | return total ? total : err; |
491 | return n; | ||
492 | |||
493 | return total; | ||
494 | } | 488 | } |
495 | 489 | ||
496 | /** | 490 | /** |
diff --git a/fs/9p/xattr.c b/fs/9p/xattr.c index f95e01e058e4..d4cab07f668d 100644 --- a/fs/9p/xattr.c +++ b/fs/9p/xattr.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/fs.h> | 16 | #include <linux/fs.h> |
17 | #include <linux/sched.h> | 17 | #include <linux/sched.h> |
18 | #include <linux/uio.h> | ||
18 | #include <net/9p/9p.h> | 19 | #include <net/9p/9p.h> |
19 | #include <net/9p/client.h> | 20 | #include <net/9p/client.h> |
20 | 21 | ||
@@ -120,8 +121,11 @@ int v9fs_xattr_set(struct dentry *dentry, const char *name, | |||
120 | int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name, | 121 | int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name, |
121 | const void *value, size_t value_len, int flags) | 122 | const void *value, size_t value_len, int flags) |
122 | { | 123 | { |
123 | u64 offset = 0; | 124 | struct kvec kvec = {.iov_base = (void *)value, .iov_len = value_len}; |
124 | int retval, msize, write_count; | 125 | struct iov_iter from; |
126 | int retval; | ||
127 | |||
128 | iov_iter_kvec(&from, WRITE | ITER_KVEC, &kvec, 1, value_len); | ||
125 | 129 | ||
126 | p9_debug(P9_DEBUG_VFS, "name = %s value_len = %zu flags = %d\n", | 130 | p9_debug(P9_DEBUG_VFS, "name = %s value_len = %zu flags = %d\n", |
127 | name, value_len, flags); | 131 | name, value_len, flags); |
@@ -135,29 +139,11 @@ int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name, | |||
135 | * On success fid points to xattr | 139 | * On success fid points to xattr |
136 | */ | 140 | */ |
137 | retval = p9_client_xattrcreate(fid, name, value_len, flags); | 141 | retval = p9_client_xattrcreate(fid, name, value_len, flags); |
138 | if (retval < 0) { | 142 | if (retval < 0) |
139 | p9_debug(P9_DEBUG_VFS, "p9_client_xattrcreate failed %d\n", | 143 | p9_debug(P9_DEBUG_VFS, "p9_client_xattrcreate failed %d\n", |
140 | retval); | 144 | retval); |
141 | goto err; | 145 | else |
142 | } | 146 | p9_client_write(fid, 0, &from, &retval); |
143 | msize = fid->clnt->msize; | ||
144 | while (value_len) { | ||
145 | if (value_len > (msize - P9_IOHDRSZ)) | ||
146 | write_count = msize - P9_IOHDRSZ; | ||
147 | else | ||
148 | write_count = value_len; | ||
149 | write_count = p9_client_write(fid, ((char *)value)+offset, | ||
150 | NULL, offset, write_count); | ||
151 | if (write_count < 0) { | ||
152 | /* error in xattr write */ | ||
153 | retval = write_count; | ||
154 | goto err; | ||
155 | } | ||
156 | offset += write_count; | ||
157 | value_len -= write_count; | ||
158 | } | ||
159 | retval = 0; | ||
160 | err: | ||
161 | p9_client_clunk(fid); | 147 | p9_client_clunk(fid); |
162 | return retval; | 148 | return retval; |
163 | } | 149 | } |
diff --git a/include/net/9p/client.h b/include/net/9p/client.h index 6fab66c5c5af..63ae7653389d 100644 --- a/include/net/9p/client.h +++ b/include/net/9p/client.h | |||
@@ -211,6 +211,8 @@ struct p9_dirent { | |||
211 | char d_name[256]; | 211 | char d_name[256]; |
212 | }; | 212 | }; |
213 | 213 | ||
214 | struct iov_iter; | ||
215 | |||
214 | int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb); | 216 | int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb); |
215 | int p9_client_rename(struct p9_fid *fid, struct p9_fid *newdirfid, | 217 | int p9_client_rename(struct p9_fid *fid, struct p9_fid *newdirfid, |
216 | const char *name); | 218 | const char *name); |
@@ -238,8 +240,7 @@ int p9_client_remove(struct p9_fid *fid); | |||
238 | int p9_client_unlinkat(struct p9_fid *dfid, const char *name, int flags); | 240 | int p9_client_unlinkat(struct p9_fid *dfid, const char *name, int flags); |
239 | int p9_client_read(struct p9_fid *fid, char *data, char __user *udata, | 241 | int p9_client_read(struct p9_fid *fid, char *data, char __user *udata, |
240 | u64 offset, u32 count); | 242 | u64 offset, u32 count); |
241 | int p9_client_write(struct p9_fid *fid, char *data, const char __user *udata, | 243 | int p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err); |
242 | u64 offset, u32 count); | ||
243 | int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset); | 244 | int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset); |
244 | int p9dirent_read(struct p9_client *clnt, char *buf, int len, | 245 | int p9dirent_read(struct p9_client *clnt, char *buf, int len, |
245 | struct p9_dirent *dirent); | 246 | struct p9_dirent *dirent); |
diff --git a/net/9p/client.c b/net/9p/client.c index 9ef5d85f082f..aa38cfeb8615 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
@@ -1611,69 +1611,53 @@ error: | |||
1611 | EXPORT_SYMBOL(p9_client_read); | 1611 | EXPORT_SYMBOL(p9_client_read); |
1612 | 1612 | ||
1613 | int | 1613 | int |
1614 | p9_client_write(struct p9_fid *fid, char *data, const char __user *udata, | 1614 | p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err) |
1615 | u64 offset, u32 count) | ||
1616 | { | 1615 | { |
1617 | int err, rsize; | 1616 | struct p9_client *clnt = fid->clnt; |
1618 | struct p9_client *clnt; | ||
1619 | struct p9_req_t *req; | 1617 | struct p9_req_t *req; |
1620 | struct iov_iter from; | 1618 | int total = 0; |
1621 | union { | 1619 | |
1622 | struct kvec kv; | 1620 | p9_debug(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %zd\n", |
1623 | struct iovec iov; | 1621 | fid->fid, (unsigned long long) offset, |
1624 | } v; | 1622 | iov_iter_count(from)); |
1625 | 1623 | ||
1626 | if (data) { | 1624 | while (iov_iter_count(from)) { |
1627 | v.kv.iov_base = data; | 1625 | int count = iov_iter_count(from); |
1628 | v.kv.iov_len = count; | 1626 | int rsize = fid->iounit; |
1629 | iov_iter_kvec(&from, ITER_KVEC | WRITE, &v.kv, 1, count); | 1627 | if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) |
1630 | } else { | 1628 | rsize = clnt->msize - P9_IOHDRSZ; |
1631 | v.iov.iov_base = udata; | 1629 | |
1632 | v.iov.iov_len = count; | 1630 | if (count < rsize) |
1633 | iov_iter_init(&from, WRITE, &v.iov, 1, count); | 1631 | rsize = count; |
1634 | } | 1632 | |
1635 | 1633 | /* Don't bother zerocopy for small IO (< 1024) */ | |
1636 | p9_debug(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %d\n", | 1634 | if (clnt->trans_mod->zc_request && rsize > 1024) { |
1637 | fid->fid, (unsigned long long) offset, count); | 1635 | req = p9_client_zc_rpc(clnt, P9_TWRITE, NULL, from, 0, |
1638 | err = 0; | 1636 | rsize, P9_ZC_HDR_SZ, "dqd", |
1639 | clnt = fid->clnt; | 1637 | fid->fid, offset, rsize); |
1640 | 1638 | } else { | |
1641 | rsize = fid->iounit; | 1639 | req = p9_client_rpc(clnt, P9_TWRITE, "dqV", fid->fid, |
1642 | if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) | 1640 | offset, rsize, from); |
1643 | rsize = clnt->msize - P9_IOHDRSZ; | 1641 | } |
1642 | if (IS_ERR(req)) { | ||
1643 | *err = PTR_ERR(req); | ||
1644 | break; | ||
1645 | } | ||
1644 | 1646 | ||
1645 | if (count < rsize) | 1647 | *err = p9pdu_readf(req->rc, clnt->proto_version, "d", &count); |
1646 | rsize = count; | 1648 | if (*err) { |
1649 | trace_9p_protocol_dump(clnt, req->rc); | ||
1650 | p9_free_req(clnt, req); | ||
1651 | } | ||
1647 | 1652 | ||
1648 | /* Don't bother zerocopy for small IO (< 1024) */ | 1653 | p9_debug(P9_DEBUG_9P, "<<< RWRITE count %d\n", count); |
1649 | if (clnt->trans_mod->zc_request && rsize > 1024) { | ||
1650 | req = p9_client_zc_rpc(clnt, P9_TWRITE, NULL, &from, 0, rsize, | ||
1651 | P9_ZC_HDR_SZ, "dqd", | ||
1652 | fid->fid, offset, rsize); | ||
1653 | } else { | ||
1654 | req = p9_client_rpc(clnt, P9_TWRITE, "dqV", fid->fid, | ||
1655 | offset, rsize, &from); | ||
1656 | } | ||
1657 | if (IS_ERR(req)) { | ||
1658 | err = PTR_ERR(req); | ||
1659 | goto error; | ||
1660 | } | ||
1661 | 1654 | ||
1662 | err = p9pdu_readf(req->rc, clnt->proto_version, "d", &count); | 1655 | p9_free_req(clnt, req); |
1663 | if (err) { | 1656 | iov_iter_advance(from, count); |
1664 | trace_9p_protocol_dump(clnt, req->rc); | 1657 | total += count; |
1665 | goto free_and_error; | 1658 | offset += count; |
1666 | } | 1659 | } |
1667 | 1660 | return total; | |
1668 | p9_debug(P9_DEBUG_9P, "<<< RWRITE count %d\n", count); | ||
1669 | |||
1670 | p9_free_req(clnt, req); | ||
1671 | return count; | ||
1672 | |||
1673 | free_and_error: | ||
1674 | p9_free_req(clnt, req); | ||
1675 | error: | ||
1676 | return err; | ||
1677 | } | 1661 | } |
1678 | EXPORT_SYMBOL(p9_client_write); | 1662 | EXPORT_SYMBOL(p9_client_write); |
1679 | 1663 | ||